如何在GTK + 3中渲染具有选择背景颜色的矩形。我找不到任何API来执行此操作:
static gboolean draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data)
{
auto state=reinterpret_cast<State*>(data);
auto width = gtk_widget_get_allocated_width (widget);
auto height = gtk_widget_get_allocated_height (widget);
auto context = gtk_widget_get_style_context (widget);
gtk_render_background(context,cr,0,0,width,height);
cairo_rectangle(cr,0,height*(1.0 - state->max),width,height*(state->max - state->min));
cairo_set_source_rgb(cr, 0.05,0.6,0.15); //What color should be used here?
cairo_fill (cr);
cairo_set_source_rgb(cr,0.01,0.3,0.07); //And here
auto mid=height*(1.0 - 0.5*(state->min + state->max));
cairo_move_to(cr,0, mid);
cairo_line_to(cr,width,mid);
cairo_stroke(cr);
return FALSE;
}
答案 0 :(得分:0)
嗯,这是我的黑客:
ColorRGBA get_ambient_color(GtkWidget* widget)
{
auto surface=cairo_image_surface_create(CAIRO_FORMAT_ARGB32,4,4);
auto cr=cairo_create(surface);
while(widge!=NULL)
{
auto context=gtk_widget_get_style_context(widget));
gtk_render_background(context,cr,0,0,1,1);
cairo_surface_flush(surface);
auto content=cairo_image_surface_get_data(surface);
if(content[3]==255)
{
auto ret=ColorRGBA{content[2]/255.0f,content[1]/255.0f,content[0]/255.0f,content[3]/255.0f};
cairo_destroy(cr);
cairo_surface_destroy(surface);
return ret;
}
// Surface is not opaque yet. Continue to parent container.
widget_handle=gtk_widget_get_parent(GTK_WIDGET(widget_handle));
}
cairo_destroy(cr);
cairo_surface_destroy(surface);
return ColorRGBA{1.0f,1.0f,1.0f,1.0f};
}
它接缝我无法说服人们,为什么你需要环境色,所以这里有两个用例:
确定我们是否使用深色/浅色主题。对于某些应用,这就足够了。仅当主题支持暗/亮模式时,查询状态才有效。这证明了实际结果。
用作模拟全局照明的输入颜色。窗口小部件的阴影应该受环境影响,因此名称。另一个好名字是get_average_background
。 Themers:请不要使用高对比度的渐变色。
现在你说游标和功能图的颜色应该是可以的。这根本不可能:这个绘图小部件的用户可以根据需要添加尽可能多的曲线和光标,区分它们的最简单方法是使用不同的颜色。
曲线和光标亮度怎么样?如果背景很暗,则曲线应该很亮,反之亦然。应该选择什么背景?理想情况下,某些东西会关闭父窗口小部件的背景,但是如果主题是常规的,那么白色代表光线,黑色代表黑暗可以使用。您是否注意到第二个图中曲线较暗?
通过以下技术,我创建了一个开关,看起来就像通过Cycles路径跟踪器渲染一样。 这是在Gtk + 2中实现的,但算法是相同的。
GtkAllocation alloc;
gtk_widget_get_allocation(widget,&alloc);
auto width=alloc.width;
auto context=CairoContext( gdk_cairo_create(gtk_widget_get_window(widget)) );
auto w_in=cairo_image_surface_get_width(light);
auto h_in=cairo_image_surface_get_height(light);
// Render direct lighting
auto surf_temp=CairoSurface( cairo_image_surface_create(CAIRO_FORMAT_ARGB32,w_in,h_in) );
auto context_temp=CairoContext( cairo_create(surf_temp) );
cairo_set_source_surface(context_temp,light,0,0);
cairo_set_operator(context_temp,CAIRO_OPERATOR_OVER);
cairo_paint(context_temp);
//Render ambient reflections
auto surf_temp_2=CairoSurface( cairo_image_surface_create(CAIRO_FORMAT_ARGB32,w_in,h_in) );
auto context_temp_2=CairoContext( cairo_create(surf_temp_2) );
cairo_set_source_surface(context_temp_2,background,0,0);
cairo_set_operator(context_temp_2,CAIRO_OPERATOR_OVER);
cairo_paint(context_temp_2);
cairo_set_operator(context_temp_2,CAIRO_OPERATOR_MULTIPLY);
//Multiply reflections with the background color
cairo_set_source_rgb(context_temp_2, color_bg.r, color_bg.g, color_bg.b);
cairo_rectangle(context_temp_2, 0, 0, w_in, h_in);
cairo_mask_surface(context_temp_2,surf_temp,0,0);
//Add the results
cairo_set_source_surface(context_temp,surf_temp_2,0,0);
cairo_set_operator(context_temp,CAIRO_OPERATOR_ADD);
cairo_mask_surface(context_temp,surf_temp,0,0);
//Scale and move things into place
auto s=static_cast<double>(width)/static_cast<double>(w_in);
cairo_translate(context,alloc.x,alloc.y);
cairo_scale(context,s,s);
cairo_set_source_surface(context,surf_temp,0,0);
cairo_set_operator(context,CAIRO_OPERATOR_OVER);
cairo_paint(context);
第一个例子归结为目前缺少的明/暗查询。也许查询颜色不是必需的,但是在渲染背景时必须有一个控制形状和混合模式的API。例如,为了渲染环境反射,我使用乘法而不是结束。此外,gtk_render_background
似乎是无操作,因为GtkDrawingArea
的不透明度为零(这就是我需要循环的原因)。为了有用,它必须使用屏幕上显示的背景,而不是当前小部件的背景。
答案 1 :(得分:-1)
使用gtk_render_frame()
和gtk_render_background()
,并设置从GtkStyleContext
实例获取的GtkWidget
,其中包含您要复制的CSS状态。
如果你想坚持主题,那你就无法画出自己;并且CSS没有&#34;颜色&#34;:每个CSS状态可以有多个图层,渐变和复杂混合模式的图层。