I wish to render text with transparent/translucent background (or no background) over other gtk widgets like GtkImage or GtkButton etc. Primary goal is to have text display
Here is an entire program that does this. Everything that you need to build and run it is at GitHub.
https://github.com/sweckhoff/GTK-Cairo-Sinusoids/blob/master/gtk_cairo_sinusoid_plot.c
#include <gtk/gtk.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
const gdouble pi = 3.14159265359;
#define ERASER_WIDTH 150
#define LABEL_STR_LEN 20
typedef struct {
gint width;
gint height;
gdouble rad_step;
gint scale_factor;
gint y_zero;
gint x_step;
gdouble rads;
gint last_x;
gint last_y;
gint current_x;
gint current_y;
gint current_eraser_x;
cairo_surface_t *plot_surface;
cairo_t *plot;
cairo_t *eraser;
GtkWidget *widget;
GtkWidget *label;
gdouble (*funct)(gdouble);
} graph_data_packet_t;
gboolean
do_graph (graph_data_packet_t *packet)
{
static gchar label_str[LABEL_STR_LEN];
if (packet->rads >= 2.0) {
packet->rads = 0.0;
}
gdouble pi_rads = pi * packet->rads;
snprintf(label_str, LABEL_STR_LEN, "%s%f%s", "Radians ", packet->rads, "pi");
gtk_label_set_text(GTK_LABEL(packet->label), label_str);
packet->rads += packet->rad_step;
if (packet->current_x > packet->width) {
packet->current_x = 0;
}
packet->last_x = packet->current_x;
packet->last_y = packet->current_y;
packet->current_x += packet->x_step;
packet->current_y = packet->y_zero - (packet->scale_factor * packet->funct (pi_rads));
packet->current_eraser_x += packet->x_step;
if (packet->current_eraser_x > packet->width) {
packet->current_eraser_x = 0;
}
gtk_widget_queue_draw(packet->widget);
return TRUE;
}
gboolean
draw_callback (GtkWidget *widget, cairo_t *drawing_area, graph_data_packet_t *packet)
{
// Erase Old
cairo_move_to (packet->eraser, packet->current_eraser_x, 0);
cairo_line_to (packet->eraser, packet->current_eraser_x, packet->height);
cairo_stroke(packet->eraser);
// Plot New
cairo_move_to (packet->plot, packet->last_x, packet->last_y);
cairo_line_to (packet->plot, packet->current_x, packet->current_y);
cairo_stroke (packet->plot);
// Apply source to drawing area
cairo_set_source_surface (drawing_area, packet->plot_surface, 0.0, 0.0);
cairo_paint(drawing_area);
return FALSE;
}
static void
destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit();
}
gboolean
delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}
int
main(int argc, char **argv)
{
GtkWidget *window = NULL;
GtkWidget *overlay = NULL;
GtkWidget *image_background = NULL;
GtkWidget *image = NULL;
GtkWidget *drawing_area = NULL;
GtkWidget *label = NULL;
graph_data_packet_t packet = {
.width = 400,
.height = 200,
.rad_step = 0.05,
.scale_factor = 75,
.y_zero = 100,
.x_step = 1,
.rads = 0.0,
.last_x = 0,
.last_y = 0,
.current_x = 0,
.current_y = 0,
.current_eraser_x = ERASER_WIDTH,
.plot_surface = NULL,
.plot = NULL,
.eraser = NULL,
.widget = NULL,
.label = NULL,
.funct = NULL
};
if (argc > 1) {
if (!strcmp("sine", argv[1])) {
packet.funct = sin;
} else if (!strcmp("cosine", argv[1])) {
packet.funct = cos;
} else {
packet.funct = sin;
}
} else {
packet.funct = sin;
}
gtk_init(&argc, &argv);
// Setup Cairo stuff
packet.plot_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 400, 200);
if (NULL == packet.plot_surface) {
return EXIT_FAILURE;
}
packet.plot = cairo_create (packet.plot_surface);
if (NULL == packet.plot) {
return EXIT_FAILURE;
}
cairo_set_source_rgb (packet.plot, 1.0, 0.0, 0.0);
packet.eraser = cairo_create (packet.plot_surface);
if (NULL == packet.eraser) {
return EXIT_FAILURE;
}
cairo_set_source_rgba (packet.eraser, 0.0, 0.0, 0.0, 0.0);
cairo_set_operator(packet.eraser, CAIRO_OPERATOR_CLEAR);
// Window
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
if(NULL == window) {
return EXIT_FAILURE;
}
packet.widget = window;
gtk_widget_set_size_request (window, 400, 200);
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), "delete_event",
G_CALLBACK (delete_event), NULL);
// Overlay
overlay = gtk_overlay_new ();
if (NULL == overlay) {
return EXIT_FAILURE;
}
// Background Image
image = gtk_image_new_from_file ("plot_background.png");
if (NULL == image) {
return EXIT_FAILURE;
}
image_background = gtk_image_new_from_file ("pi_background.png");
if (NULL == image_background) {
return EXIT_FAILURE;
}
// Plot
drawing_area = gtk_drawing_area_new ();
if (NULL == drawing_area) {
return EXIT_FAILURE;
}
gtk_widget_set_size_request (drawing_area, 400, 200);
g_signal_connect (G_OBJECT (drawing_area), "draw",
G_CALLBACK (draw_callback), &packet);
// Label
label = gtk_label_new ("Radians: 0.0 pi");
if (NULL == label) {
return EXIT_FAILURE;
}
packet.label = label;
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_END);
// Put it all together
gtk_container_add(GTK_CONTAINER(overlay), image_background);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), image);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), drawing_area);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), label);
gtk_container_add (GTK_CONTAINER (window), overlay);
gtk_widget_show_all (window);
g_timeout_add(100, (GSourceFunc) do_graph, &packet);
gtk_main();
return EXIT_SUCCESS;
}
You can do it with GtkOverlay widget (Gtk+ 3.2 at least)
GtkOverlay — A container which overlays widgets on top of each other
http://developer.gnome.org/gtk3/stable/GtkOverlay.html