是否有一个API可以在GTK和OSX上执行每像素Alpha Blend?

问题描述:

我想在Linux(GTK)和OSX上绘制透明窗口(带有alpha通道)。有没有API来做到这一点?请注意,我不想设置全局透明度,应该为每个像素设置alpha级别。是否有一个API可以在GTK和OSX上执行每像素Alpha Blend?

我正在寻找与Windows上的UpdateLayeredWindow函数相同的API,如下例所示:Per Pixel Alpha Blend

对于Mac OS X,请参阅 RoundTransparentWindow示例代码。它通过使用自定义完全透明的窗口并在其中绘制图形来工作。虽然该示例仅使用具有硬边+整体alpha的形状,但可以使用任意alpha。

虽然该示例使用自定义窗口,但您可以使用相同的技术在正常窗口中打孔,方法是呼叫setOpaque:NO。 Hacky示例:

@implementation ClearView 

- (void)drawRect:(NSRect)rect 
{ 
    if (mask == nil) mask = [[NSImage imageNamed:@"mask"] retain]; 
    [self.window setOpaque:NO]; 
    [mask drawInRect:self.bounds 
      fromRect:(NSRect){{0, 0},mask.size} 
      operation:NSCompositeCopy 
      fraction:1.0]; 
} 

@end 

此技术的主要限制是标准阴影与alpha混合边缘不能很好地交互。

我在今年早些时候在我的实验文件夹中发现了这段代码。我不记得我写了多少内容,多少是基于互联网其他地方的例子。

这个例子将显示一个半透明的蓝色窗口,中间有一个完全不透明的GTK +按钮。例如,在窗口内的某处绘制一个alpha混合的PNG应该会导致它被正确合成。希望这会让你走上正轨。

与下列编译:

$ gcc `pkg-config --cflags --libs gtk+-2.0` -o per-pixel-opacity per-pixel-opacity.c 

现在的代码:

#include <gtk/gtk.h> 

static gboolean on_window_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) 
{ 
    cairo_t *cr; 
    cr = gdk_cairo_create(widget->window); // create cairo context 

    cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 0.2); 
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); // set drawing compositing operator 
                // SOURCE -> replace destination 
    cairo_paint(cr); // paint source 

    cairo_destroy(cr); 

    return FALSE; 
} 

gint main(gint argc, gchar **argv) 
{ 
    GtkWidget *window, *button, *vbox; 
    GdkScreen *screen; 
    GdkColormap *colormap; 

    gtk_init(&argc, &argv); 

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 

    g_signal_connect(G_OBJECT(window), "delete-event", gtk_main_quit, NULL); 
    g_signal_connect(G_OBJECT(window), "expose-event", G_CALLBACK(on_window_expose_event), NULL); 

    gtk_window_set_decorated(GTK_WINDOW(window), FALSE); 
    gtk_container_set_border_width(GTK_CONTAINER(window), 20); 

    gtk_widget_set_app_paintable(window, TRUE); 

    screen = gtk_widget_get_screen(window); 
    colormap = gdk_screen_get_rgba_colormap(screen); 
    gtk_widget_set_colormap(window, colormap); 

    button = gtk_button_new(); 
    gtk_button_set_label(GTK_BUTTON(button), "Don't Press!"); 

    gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(button)); 

    gtk_widget_show_all(window); 

    gtk_main(); 

    return 0; 
}