GTK + 3渲染矩形,选择背景颜色

时间:2017-04-12 17:37:15

标签: background selection gtk3

如何在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;
    }

2 个答案:

答案 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};
    }

它接缝我无法说服人们,为什么你需要环境色,所以这里有两个用例:

  1. 确定我们是否使用深色/浅色主题。对于某些应用,这就足够了。仅当主题支持暗/亮模式时,查询状态才有效。这证明了实际结果。

  2. 用作模拟全局照明的输入颜色。窗口小部件的阴影应该受环境影响,因此名称。另一个好名字是get_average_background。 Themers:请不要使用高对比度的渐变色。

  3. 案例1:情节

    Dark plot

    Light plot

    现在你说游标和功能图的颜色应该是可以的。这根本不可能:这个绘图小部件的用户可以根据需要添加尽可能多的曲线和光标,区分它们的最简单方法是使用不同的颜色。

    曲线和光标亮度怎么样?如果背景很暗,则曲线应该很亮,反之亦然。应该选择什么背景?理想情况下,某些东西会关闭父窗口小部件的背景,但是如果主题是常规的,那么白色代表光线,黑色代表黑暗可以使用。您是否注意到第二个图中曲线较暗?

    案例2:一个看起来像金属切换开关按钮的复选框

    Switch

    通过以下技术,我创建了一个开关,看起来就像通过Cycles路径跟踪器渲染一样。 这是在Gtk + 2中实现的,但算法是相同的。

    两个输入图像

    Light Background

    代码

    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状态可以有多个图层,渐变和复杂混合模式的图层。