具有选择背景颜色的 GTK+3 渲染矩形
GTK+3 render rectangle with selection background color
如何在 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;
}
使用 gtk_render_frame()
and gtk_render_background()
,并设置您从 GtkWidget
实例获得的 GtkStyleContext
具有您要复制的 CSS 状态。
要紧扣主题,就不能画自己; CSS 没有 "colors":每个 CSS 状态可以有多个图层,包括图像、渐变和复杂的混合模式。
好吧,这是我的技巧:
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};
}
看来我没能说服人们,为什么你需要环境色,所以这里有两个用例:
确定我们是否使用 dark/light 主题。对于某些应用程序,这就足够了。仅当主题支持 dark/light 模式时查询状态才有效。这证明了实际结果。
用作模拟全局照明的输入颜色。小部件的阴影应该受环境影响,因此得名。另一个好名字是 get_average_background
。 Themers:请不要使用高对比度的渐变。
案例 1:情节
现在你说光标和函数图的颜色应该是主题化的。这根本不可能:此绘图小部件的用户可以根据需要添加任意数量的曲线和光标,区分它们的最简单方法是使用不同的颜色。
曲线和光标亮度如何?如果背景很暗,那么曲线应该很亮,反之亦然。应该选择什么背景?理想情况下,一些东西可以关闭父小部件的背景,但如果主题是常规的,则白色代表浅色,黑色代表深色。你注意到第二张图中的曲线更暗了吗?
案例 2:看起来像金属拨动开关按钮的复选框
使用以下技术,我创建了一个开关,看起来就像是通过 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);
想法
第一个示例归结为 light/dark 当前缺少的查询。也许不需要查询颜色就可以工作,但是在渲染背景时必须有一个 API 来控制形状和混合模式。例如,为了渲染环境反射,我使用 multiply 而不是 over。此外,gtk_render_background
似乎是空操作,因为 GtkDrawingArea
的不透明度为零(这就是我需要循环的原因)。要发挥作用,它必须使用屏幕上显示的背景,而不是当前小部件的背景。
如何在 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;
}
使用 gtk_render_frame()
and gtk_render_background()
,并设置您从 GtkWidget
实例获得的 GtkStyleContext
具有您要复制的 CSS 状态。
要紧扣主题,就不能画自己; CSS 没有 "colors":每个 CSS 状态可以有多个图层,包括图像、渐变和复杂的混合模式。
好吧,这是我的技巧:
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};
}
看来我没能说服人们,为什么你需要环境色,所以这里有两个用例:
确定我们是否使用 dark/light 主题。对于某些应用程序,这就足够了。仅当主题支持 dark/light 模式时查询状态才有效。这证明了实际结果。
用作模拟全局照明的输入颜色。小部件的阴影应该受环境影响,因此得名。另一个好名字是
get_average_background
。 Themers:请不要使用高对比度的渐变。
案例 1:情节
现在你说光标和函数图的颜色应该是主题化的。这根本不可能:此绘图小部件的用户可以根据需要添加任意数量的曲线和光标,区分它们的最简单方法是使用不同的颜色。
曲线和光标亮度如何?如果背景很暗,那么曲线应该很亮,反之亦然。应该选择什么背景?理想情况下,一些东西可以关闭父小部件的背景,但如果主题是常规的,则白色代表浅色,黑色代表深色。你注意到第二张图中的曲线更暗了吗?
案例 2:看起来像金属拨动开关按钮的复选框
使用以下技术,我创建了一个开关,看起来就像是通过 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);
想法
第一个示例归结为 light/dark 当前缺少的查询。也许不需要查询颜色就可以工作,但是在渲染背景时必须有一个 API 来控制形状和混合模式。例如,为了渲染环境反射,我使用 multiply 而不是 over。此外,gtk_render_background
似乎是空操作,因为 GtkDrawingArea
的不透明度为零(这就是我需要循环的原因)。要发挥作用,它必须使用屏幕上显示的背景,而不是当前小部件的背景。