void pango_render_text_shadow(cairo_t *context, PangoLayout *layout) { cairo_push_group(context); cairo_new_path(context); cairo_move_to(context, 15.0+8.0, 10.0+8.0); pango_cairo_layout_path(context, layout); cairo_set_line_width(context, 6.0); cairo_set_miter_limit(context, 2.0); cairo_set_source_rgb(context, 0.0, 0.0, 0.0); cairo_stroke_preserve(context); cairo_fill(context); cairo_pop_group_to_source(context); cairo_paint_with_alpha(context, 0.6); cairo_new_path(context); cairo_move_to(context, 15.0, 10.0); pango_cairo_layout_path(context, layout); cairo_set_line_width(context, 6.0); cairo_set_miter_limit(context, 2.0); cairo_set_source_rgb(context, 0.0, 0.3, 0.9); cairo_stroke_preserve(context); cairo_set_source_rgb(context, 0.9, 0.1, 0.8); cairo_fill(context); }
void ZDrawSongInfo(IDirectFB *dfb, IDirectFBSurface *dfbsurface, const gchar *title, const gchar *artist, gint w, gint h, DFBColor *color, DFBColor *strokeColor, double strokeWidth, const PangoFontDescription *desc) { cairo_t *cr = NULL; cairo_surface_t *surface = NULL; cairo_surface_t *cairosurface = NULL; PangoLayout *layout = NULL; if(!dfb || !dfbsurface) return; /* prepare layout */ layout = pango_layout_new(gdk_pango_context_get()); pango_layout_set_single_paragraph_mode (layout, TRUE); pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); pango_layout_set_width(layout, w* PANGO_SCALE); pango_layout_set_font_description(layout, desc); surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); cr = cairo_create(surface); /* Draw title */ if(title) { pango_layout_set_text(layout, title, -1); cairo_move_to(cr, 0, 0); pango_cairo_layout_path(cr, layout); ZCairoSetDFBColor(cr, strokeColor); cairo_set_line_width(cr, strokeWidth); cairo_stroke_preserve(cr); ZCairoSetDFBColor(cr, color); cairo_fill(cr); } /* Draw artist */ if(artist) { pango_layout_set_text(layout, artist, -1); cairo_move_to(cr, 0, h/2); pango_cairo_layout_path(cr, layout); ZCairoSetDFBColor(cr, strokeColor); cairo_set_line_width(cr, strokeWidth); cairo_stroke_preserve(cr); ZCairoSetDFBColor(cr, color); cairo_fill(cr); } g_object_unref(layout); cairo_destroy(cr); /* Draw cairo_surface to dfbsurface */ /* create surface */ cairosurface = cairo_directfb_surface_create(dfb, dfbsurface); cr = cairo_create(cairosurface); cairo_set_source_surface(cr, surface, 0, 0); cairo_paint(cr); cairo_destroy(cr); cairo_surface_destroy(surface); cairo_surface_destroy(cairosurface); }
void ZCairoDrawLyric(cairo_t *cr, gboolean isUpLine, gint space, gint w, gint h, DFBColor *bgColor, const gchar *text, gint fullWidth, DFBColor *color1, DFBColor *strokeColor1, double strokeWidth1, DFBColor *color2, DFBColor *strokeColor2, double strokeWidth2, const PangoFontDescription *desc) { PangoLayout *layout = NULL; gint x, y; /* Prepare layout */ layout = pango_layout_new(gdk_pango_context_get()); pango_layout_set_single_paragraph_mode (layout, TRUE); pango_layout_set_alignment(layout, isUpLine ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, text, -1); /* Clear background */ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); /* Draw background */ if(bgColor) { ZCairoSetDFBColor(cr, bgColor); cairo_paint(cr); } /* Draw original text */ x = isUpLine ? space : w - fullWidth - space; y = 0; cairo_move_to(cr, x, y); pango_cairo_layout_path(cr, layout); ZCairoSetDFBColor(cr, strokeColor1); cairo_set_line_width(cr, strokeWidth1); cairo_stroke_preserve(cr); ZCairoSetDFBColor(cr, color1); cairo_fill(cr); /* Draw effect text */ y = h/2; cairo_move_to(cr, x, y); pango_cairo_layout_path(cr, layout); ZCairoSetDFBColor(cr, strokeColor2); cairo_set_line_width(cr, strokeWidth2); cairo_stroke_preserve(cr); ZCairoSetDFBColor(cr, color2); cairo_fill(cr); g_object_unref(layout); }
/* Draws a rounded rectangle with text inside. */ static gboolean numbers_draw_cb (GtkWidget *widget, cairo_t *ctx, gpointer data) { double x, y, w, h; PangoLayout * layout; gint font_size = gtk_widget_get_font_size (widget); #if (INDICATOR_MESSAGES_HAS_LOZENGE == 1) gboolean is_lozenge = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "is-lozenge")); /* let the label handle the drawing if it's not a lozenge */ if (!is_lozenge) return FALSE; #endif if (!GTK_IS_WIDGET (widget)) return FALSE; /* get style + arrow position / dimensions */ double red, green, blue; GtkStyleContext *style = gtk_widget_get_style_context (widget); GdkRGBA color; gtk_style_context_get_color (style, gtk_widget_get_state(widget), &color); red = color.red; green = color.green; blue = color.blue; GtkAllocation allocation; gtk_widget_get_allocation (widget, &allocation); w = allocation.width; h = allocation.height; x = y = 0; layout = gtk_label_get_layout (GTK_LABEL(widget)); PangoRectangle layout_extents; pango_layout_get_extents (layout, NULL, &layout_extents); pango_extents_to_pixels (&layout_extents, NULL); if (layout_extents.width == 0) return TRUE; cairo_set_line_width (ctx, 1.0); cairo_set_fill_rule (ctx, CAIRO_FILL_RULE_EVEN_ODD); /* cairo drawing code */ custom_cairo_rounded_rectangle (ctx, x - font_size/2.0, y, w + font_size, h); cairo_set_source_rgba (ctx, red, green, blue, 0.5); x += (allocation.width - layout_extents.width) / 2.0; y += (allocation.height - layout_extents.height) / 2.0; cairo_move_to (ctx, floor (x), floor (y)); pango_cairo_layout_path (ctx, layout); cairo_fill (ctx); return TRUE; }
void ol_osd_render_paint_text (OlOsdRenderContext *context, cairo_t *cr, const char *text, double xpos, double ypos) { ol_assert (context != NULL); ol_assert (cr != NULL); ol_assert (text != NULL); ol_osd_render_set_text (context, text); int width, height; xpos += context->outline_width / 2.0 + context->blur_radius; ypos += context->outline_width / 2.0 + context->blur_radius; pango_layout_get_pixel_size (context->pango_layout, &width, &height); /* draws the outline of the text */ cairo_move_to (cr, xpos, ypos); cairo_save (cr); pango_cairo_layout_path(cr, context->pango_layout); cairo_set_source_rgb (cr, ol_color_black.r, ol_color_black.g, ol_color_black.b); if (context->outline_width > 0) { cairo_set_line_width (cr, context->outline_width); if (context->blur_radius > 1e-4) { cairo_stroke_preserve (cr); cairo_fill (cr); ol_gussian_blur (cairo_get_target (cr), context->blur_radius); } else { cairo_stroke (cr); } } cairo_restore (cr); cairo_save (cr); cairo_new_path (cr); /* creates the linear pattern */ cairo_pattern_t *pattern = cairo_pattern_create_linear (xpos, ypos, xpos, ypos + height); int i; for (i = 0; i < OL_LINEAR_COLOR_COUNT; i++) { cairo_pattern_add_color_stop_rgb(pattern, context->linear_pos[i], context->linear_colors[i].r, context->linear_colors[i].g, context->linear_colors[i].b); } cairo_set_source (cr, pattern); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); /* draws the text */ cairo_move_to (cr, xpos, ypos); pango_cairo_show_layout (cr, context->pango_layout); cairo_pattern_destroy (pattern); cairo_restore (cr); }
void pango_render_text_simple(cairo_t *context, PangoLayout *layout) { cairo_new_path(context); cairo_move_to(context, 15.0, 10.0); pango_cairo_layout_path(context, layout); cairo_set_source_rgb(context, 0.9, 0.1, 0.8); cairo_fill(context); }
PP_Bool ppb_browser_font_trusted_draw_text_at(PP_Resource font, PP_Resource image_data, const struct PP_BrowserFont_Trusted_TextRun *text, const struct PP_Point *position, uint32_t color, const struct PP_Rect *clip, PP_Bool image_data_is_opaque) { (void)image_data_is_opaque; // TODO: is it worth implementing? struct pp_browser_font_s *bf = pp_resource_acquire(font, PP_RESOURCE_BROWSER_FONT); if (!bf) return PP_FALSE; struct pp_image_data_s *id = pp_resource_acquire(image_data, PP_RESOURCE_IMAGE_DATA); if (!id) { pp_resource_release(font); return PP_FALSE; } cairo_t *cr = cairo_create(id->cairo_surf); if (clip) { cairo_rectangle(cr, clip->point.x, clip->point.y, clip->size.width, clip->size.height); cairo_clip(cr); } PangoFontMetrics *m = pango_font_get_metrics(bf->font, NULL); int32_t ascent = pango_font_metrics_get_ascent(m) / PANGO_SCALE; cairo_surface_mark_dirty(id->cairo_surf); if (position) cairo_move_to(cr, position->x, position->y - ascent); else cairo_move_to(cr, 0, 0); pango_font_metrics_unref(m); cairo_set_source_rgba(cr, ((color >> 16) & 0xffu) / 255.0, ((color >> 8) & 0xffu) / 255.0, ((color >> 0) & 0xffu) / 255.0, ((color >> 24) & 0xffu) / 255.0); PangoLayout *layout = pango_cairo_create_layout(cr); uint32_t len = 0; const char *s = ""; if (text->text.type == PP_VARTYPE_STRING) s = ppb_var_var_to_utf8(text->text, &len); // TODO: factor into rtl direction pango_layout_set_font_description(layout, bf->font_desc); pango_layout_set_text(layout, s, len); pango_cairo_layout_path(cr, layout); cairo_fill(cr); g_object_unref(layout); cairo_surface_flush(id->cairo_surf); cairo_destroy(cr); pp_resource_release(font); pp_resource_release(image_data); return PP_FALSE; }
void GuiSolidLabelElementRenderer::Render(Rect bounds) { if(cairoContext) { cairo_save(cairoContext); Color color = element->GetColor(); FontProperties font = element->GetFont(); cairo_set_source_rgba(cairoContext, 1.0 * color.r / 255, 1.0 * color.g / 255, 1.0 * color.b / 255, 1.0 * color.a / 255 ); if(element->GetWrapLine()) pango_layout_set_width(layout, bounds.Width() * PANGO_SCALE); pango_cairo_update_layout(cairoContext, layout); int layoutWidth, layoutHeight; int plotX1, plotY1; pango_layout_get_pixel_size( layout, &layoutWidth, &layoutHeight); switch(element->GetHorizontalAlignment()) { case Alignment::Left: plotX1 = bounds.x1; break; case Alignment::Center: plotX1 = bounds.x1 + (bounds.Width() - layoutWidth) / 2; break; case Alignment::Right: plotX1 = bounds.x1 + (bounds.Width() - layoutWidth); break; } switch(element->GetVerticalAlignment()) { case Alignment::Top: plotY1 = bounds.y1; break; case Alignment::Center: plotY1 = bounds.y1 + (bounds.Height() - layoutHeight) / 2; break; case Alignment::Bottom: plotY1 = bounds.y1 + (bounds.Height() - layoutHeight); break; } cairo_move_to(cairoContext, plotX1, plotY1); pango_cairo_layout_path(cairoContext, layout); cairo_fill(cairoContext); cairo_restore(cairoContext); } }
static void draw_page (GtkPrintOperation *operation, GtkPrintContext *context, int page_nr) { cairo_t *cr; PangoLayout *layout; PangoFontDescription *desc; cr = gtk_print_context_get_cairo_context (context); /* Draw a red rectangle, as wide as the paper (inside the margins) */ cairo_set_source_rgb (cr, 1.0, 0, 0); cairo_rectangle (cr, 0, 0, gtk_print_context_get_width (context), 50); cairo_fill (cr); /* Draw some lines */ cairo_move_to (cr, 20, 10); cairo_line_to (cr, 40, 20); cairo_arc (cr, 60, 60, 20, 0, G_PI); cairo_line_to (cr, 80, 20); cairo_set_source_rgb (cr, 0, 0, 0); cairo_set_line_width (cr, 5); cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); cairo_stroke (cr); /* Draw some text */ layout = gtk_print_context_create_pango_layout (context); pango_layout_set_text (layout, "Hello World! Printing is easy", -1); desc = pango_font_description_from_string ("sans 28"); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); cairo_move_to (cr, 30, 20); pango_cairo_layout_path (cr, layout); /* Font Outline */ cairo_set_source_rgb (cr, 0.93, 1.0, 0.47); cairo_set_line_width (cr, 0.5); cairo_stroke_preserve (cr); /* Font Fill */ cairo_set_source_rgb (cr, 0, 0.0, 1.0); cairo_fill (cr); g_object_unref (layout); }
void TextAsset::drawText(cairo_t* cairoContext, const std::string& textString, const Rect& rect, PangoFontDescription* inFontDescription, bool outlineEnabled) { cairo_move_to(cairoContext, rect.x, rect.y); PangoLayout* layout = pango_cairo_create_layout(cairoContext); // Kerning PangoAttrList* attr_list = pango_attr_list_new(); PangoAttribute* spacing_attr = pango_attr_letter_spacing_new(pango_units_from_double(_kern)); pango_attr_list_insert(attr_list, spacing_attr); pango_layout_set_attributes(layout, attr_list); pango_cairo_context_set_resolution(pango_layout_get_context(layout), DISPLAY_RESOLUTION); pango_layout_set_text(layout, textString.c_str(), textString.length()); pango_layout_set_font_description(layout, inFontDescription); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_width(layout, pango_units_from_double(rect.size.width + WIDTH_PADDING)); pango_layout_set_height(layout, pango_units_from_double(rect.size.height + HEIGHT_PADDING)); pango_layout_set_alignment(layout, _alignment); applyLeading(cairoContext, layout, inFontDescription); pango_cairo_show_layout(cairoContext, layout); // Core Text defines positive outline width values as stroke only if (_outlineThickness <= 0.0f) { cairo_fill_preserve(cairoContext); } // Outline if (outlineEnabled && _outlineThickness != 0.0f) { const float outlineThickness = (fabsf(_outlineThickness) / 100.0f) * _fontSize * CLIENT_TO_SERVER_SCALE; cairo_set_source_rgba(cairoContext, _outlineColor.red, _outlineColor.green, _outlineColor.blue, _outlineColor.alpha); pango_cairo_layout_path(cairoContext, layout); cairo_set_line_width(cairoContext, outlineThickness); cairo_stroke(cairoContext); } else { cairo_new_path(cairoContext); } g_object_unref(layout); }
static void br_cairo_draw_tooltip(duc_graph *g, double x, double y, char *text) { struct cairo_backend_data *bd = g->backend_data; cairo_t *cr = bd->cr; char font[32]; snprintf(font, sizeof font, "Arial, Sans, %d", FONT_SIZE_TOOLTIP); PangoLayout *layout = pango_cairo_create_layout(cr); PangoFontDescription *desc = pango_font_description_from_string(font); pango_layout_set_text(layout, text, -1); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); pango_cairo_update_layout(cr, layout); int w,h; pango_layout_get_size(layout, &w, &h); w /= PANGO_SCALE; h /= PANGO_SCALE; /* shadow box */ int i; for(i=1; i<3; i++) { cairo_rectangle(cr, x - w - 10 + i, y - h - 10 + i, w + 10 + i, h + 10 + i); cairo_set_source_rgba(cr, 0, 0, 0, 0.25); cairo_fill(cr); } /* tooltip box */ cairo_rectangle(cr, x - w - 10 + 0.5, y - h - 10 + 0.5, w + 10, h + 10); cairo_set_source_rgba(cr, 1, 1, 1, 1); cairo_fill_preserve(cr); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_stroke(cr); /* black text */ cairo_move_to(cr, x - w - 5, y - h - 5); pango_cairo_layout_path(cr, layout); g_object_unref(layout); cairo_set_source_rgb(cr, 0, 0, 0); cairo_set_line_width(cr, 1); cairo_fill(cr); }
void pango_render_text_border(cairo_t *context, PangoLayout *layout) { cairo_new_path(context); cairo_move_to(context, 15.0, 10.0); pango_cairo_layout_path(context, layout); cairo_set_line_width(context, 6.0); cairo_set_miter_limit(context, 2.0); cairo_set_source_rgb(context, 0.0, 0.3, 0.9); cairo_stroke_preserve(context); cairo_set_source_rgb(context, 0.9, 0.1, 0.8); cairo_fill(context); }
void rendertext(cairo_t *cr) { PangoLayout *layout; layout = pango_cairo_create_layout(cr); pangotext(layout); cairo_new_path(cr); cairo_move_to(cr,0,0); cairo_set_line_width(cr,0.5); cairo_set_source_rgb(cr,0.0,0.0,1.0); pango_cairo_layout_path(cr,layout); cairo_stroke_preserve(cr); g_object_unref(layout); }
static void annotation_txt(MF2UI *ui, RobTkDial * d, cairo_t *cr, const char *txt) { int tw, th; cairo_save(cr); PangoLayout * pl = pango_cairo_create_layout(cr); pango_layout_set_font_description(pl, ui->font[1]); pango_layout_set_text(pl, txt, -1); pango_layout_get_pixel_size(pl, &tw, &th); cairo_translate (cr, d->w_cx, d->w_height); cairo_translate (cr, -tw/2.0 - 0.5, -th); cairo_set_source_rgba (cr, .0, .0, .0, .7); rounded_rectangle(cr, -1, -1, tw+3, th+1, 3); cairo_fill(cr); CairoSetSouerceRGBA(c_wht); pango_cairo_layout_path(cr, pl); cairo_fill(cr); g_object_unref(pl); cairo_restore(cr); cairo_new_path(cr); }
// Apply the labels to the map. void simplet_lithograph_apply(simplet_lithograph_t *litho, simplet_list_t *styles){ simplet_listiter_t *iter = simplet_get_list_iter(litho->placements); placement_t *placement; cairo_save(litho->ctx); while((placement = (placement_t *) simplet_list_next(iter))){ if(placement->placed == TRUE) continue; cairo_move_to(litho->ctx, placement->bounds->nw.x, placement->bounds->se.y); // Draw the placement pango_cairo_layout_path(litho->ctx, placement->layout); placement->placed = TRUE; } simplet_apply_styles(litho->ctx, styles, "text-stroke-weight", "text-stroke-color", "color", NULL); // Apply and draw various outline options. cairo_restore(litho->ctx); }
static PyObject * pango_LayoutPath(PyObject *self, PyObject *args) { PycairoContext *context; cairo_t *ctx; void *LayoutObj; PangoLayout *layout; if (!PyArg_ParseTuple(args, "OO", &context, &LayoutObj)) { return NULL; } ctx = context->ctx; layout = PyCObject_AsVoidPtr(LayoutObj); pango_cairo_layout_path(ctx, layout); Py_INCREF(Py_None); return Py_None; }
static void img_write_text(cairo_t* cr, const char *txt, const char *font, float x, float y, float ang) { int tw, th; cairo_save(cr); PangoLayout * pl = pango_cairo_create_layout(cr); PangoFontDescription *desc = pango_font_description_from_string(font); pango_layout_set_font_description(pl, desc); pango_font_description_free(desc); pango_layout_set_text(pl, txt, -1); pango_layout_get_pixel_size(pl, &tw, &th); cairo_translate (cr, x, y); cairo_rotate (cr, ang); cairo_translate (cr, -tw/2.0, -th/2.0); pango_cairo_layout_path(cr, pl); cairo_fill(cr); g_object_unref(pl); cairo_restore(cr); cairo_new_path (cr); }
static void br_cairo_draw_text(duc_graph *g, double x, double y, double size, char *text) { struct cairo_backend_data *bd = g->backend_data; cairo_t *cr = bd->cr; char font[32]; snprintf(font, sizeof font, "Arial, Sans, %.0f", size); PangoLayout *layout = pango_cairo_create_layout(cr); PangoFontDescription *desc = pango_font_description_from_string(font); pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); pango_layout_set_text(layout, text, -1); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); pango_cairo_update_layout(cr, layout); int w,h; pango_layout_get_size(layout, &w, &h); x -= ((double)w / PANGO_SCALE / 2); y -= ((double)h / PANGO_SCALE / 2); cairo_move_to(cr, x, y); pango_cairo_layout_path(cr, layout); g_object_unref(layout); /* light grey background */ cairo_set_line_join (cr, CAIRO_LINE_JOIN_BEVEL); cairo_set_source_rgba(cr, 1, 1, 1, 0.6); cairo_set_line_width(cr, 3); cairo_stroke_preserve(cr); /* black text */ cairo_set_source_rgb(cr, 0, 0, 0); cairo_set_line_width(cr, 1); cairo_fill(cr); }
void draw_password_mask(void) { cairo_t *cr = cairo_create(lualock.pw_surface); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); draw_password_field(cr); PangoLayout *layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, lualock.style.font_desc); cairo_set_source_rgba(cr, lualock.style.r, lualock.style.g, lualock.style.b, lualock.style.a); cairo_move_to(cr, lualock.style.off_x, lualock.style.off_y); gchar *password_mask = get_password_mask(); pango_layout_set_text(layout, password_mask, -1); free(password_mask); pango_cairo_update_layout(cr, layout); pango_cairo_layout_path(cr, layout); cairo_fill(cr); g_object_unref(layout); cairo_destroy(cr); }
static void rsvg_cairo_clip_render_pango_layout (RsvgDrawingCtx * ctx, PangoLayout * layout, double x, double y) { RsvgCairoClipRender *render = RSVG_CAIRO_CLIP_RENDER (ctx->render); RsvgCairoRender *cairo_render = &render->super; cairo_matrix_t affine; PangoGravity gravity = pango_context_get_gravity (pango_layout_get_context (layout)); double rotation; affine = ctx->state->affine; rsvg_cairo_clip_apply_affine (render, &affine); rotation = pango_gravity_to_rotation (gravity); cairo_save (cairo_render->cr); cairo_move_to (cairo_render->cr, x, y); if (rotation != 0.) cairo_rotate (cairo_render->cr, -rotation); pango_cairo_update_layout (cairo_render->cr, layout); pango_cairo_layout_path (cairo_render->cr, layout); cairo_restore (cairo_render->cr); }
void *dt_control_expose(void *voidptr) { int width, height, pointerx, pointery; if(!darktable.gui->surface) return NULL; width = dt_cairo_image_surface_get_width(darktable.gui->surface); height = dt_cairo_image_surface_get_height(darktable.gui->surface); GtkWidget *widget = dt_ui_center(darktable.gui->ui); GdkDevice *device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(widget))); gdk_window_get_device_position(gtk_widget_get_window(widget), device, &pointerx, &pointery, NULL); // create a gtk-independent surface to draw on cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); // TODO: control_expose: only redraw the part not overlapped by temporary control panel show! // float tb = 8; // fmaxf(10, width/100.0); darktable.control->tabborder = tb; darktable.control->width = width; darktable.control->height = height; GdkRGBA color; GtkStyleContext *context = gtk_widget_get_style_context(widget); gboolean color_found = gtk_style_context_lookup_color (context, "bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_set_line_width(cr, tb); cairo_rectangle(cr, tb / 2., tb / 2., width - tb, height - tb); cairo_stroke(cr); cairo_set_line_width(cr, 1.5); color_found = gtk_style_context_lookup_color (context, "really_dark_bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_rectangle(cr, tb, tb, width - 2 * tb, height - 2 * tb); cairo_stroke(cr); cairo_save(cr); cairo_translate(cr, tb, tb); cairo_rectangle(cr, 0, 0, width - 2 * tb, height - 2 * tb); cairo_clip(cr); cairo_new_path(cr); // draw view dt_view_manager_expose(darktable.view_manager, cr, width - 2 * tb, height - 2 * tb, pointerx - tb, pointery - tb); cairo_restore(cr); // draw log message, if any dt_pthread_mutex_lock(&darktable.control->log_mutex); if(darktable.control->log_ack != darktable.control->log_pos) { PangoRectangle ink; PangoLayout *layout; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); const float fontsize = DT_PIXEL_APPLY_DPI(14); pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, darktable.control->log_message[darktable.control->log_ack], -1); pango_layout_get_pixel_extents(layout, &ink, NULL); const float pad = DT_PIXEL_APPLY_DPI(20.0f), xc = width / 2.0; const float yc = height * 0.85 + DT_PIXEL_APPLY_DPI(10), wd = pad + ink.width * .5f; float rad = DT_PIXEL_APPLY_DPI(14); cairo_set_line_width(cr, 1.); cairo_move_to(cr, xc - wd, yc + rad); for(int k = 0; k < 5; k++) { cairo_arc(cr, xc - wd, yc, rad, M_PI / 2.0, 3.0 / 2.0 * M_PI); cairo_line_to(cr, xc + wd, yc - rad); cairo_arc(cr, xc + wd, yc, rad, 3.0 * M_PI / 2.0, M_PI / 2.0); cairo_line_to(cr, xc - wd, yc + rad); if(k == 0) { color_found = gtk_style_context_lookup_color (context, "selected_bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_fill_preserve(cr); } cairo_set_source_rgba(cr, 0., 0., 0., 1.0 / (1 + k)); cairo_stroke(cr); rad += .5f; } color_found = gtk_style_context_lookup_color (context, "fg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_move_to(cr, xc - wd + .5f * pad, (yc + 1. / 3. * fontsize) - fontsize); pango_cairo_show_layout(cr, layout); pango_font_description_free(desc); g_object_unref(layout); } // draw busy indicator if(darktable.control->log_busy > 0) { PangoRectangle ink; PangoLayout *layout; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); const float fontsize = DT_PIXEL_APPLY_DPI(14); pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, _("working.."), -1); pango_layout_get_pixel_extents(layout, &ink, NULL); const float xc = width / 2.0, yc = height * 0.85 - DT_PIXEL_APPLY_DPI(30), wd = ink.width * .5f; cairo_move_to(cr, xc - wd, yc + 1. / 3. * fontsize - fontsize); pango_cairo_layout_path(cr, layout); cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); cairo_fill_preserve(cr); cairo_set_line_width(cr, 0.7); cairo_set_source_rgb(cr, 0.3, 0.3, 0.3); cairo_stroke(cr); pango_font_description_free(desc); g_object_unref(layout); } dt_pthread_mutex_unlock(&darktable.control->log_mutex); cairo_destroy(cr); cairo_t *cr_pixmap = cairo_create(darktable.gui->surface); cairo_set_source_surface(cr_pixmap, cst, 0, 0); cairo_paint(cr_pixmap); cairo_destroy(cr_pixmap); cairo_surface_destroy(cst); return NULL; }
static gboolean _lib_histogram_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_histogram_t *d = (dt_lib_histogram_t *)self->data; dt_develop_t *dev = darktable.develop; uint32_t *hist = dev->histogram; float hist_max = dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR ? dev->histogram_max : logf(1.0 + dev->histogram_max); const int inset = DT_HIST_INSET; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); gtk_render_background(gtk_widget_get_style_context(widget), cr, 0, 0, allocation.width, allocation.height); cairo_translate(cr, 4 * inset, inset); width -= 2 * 4 * inset; height -= 2 * inset; if(d->mode_x == 0) { d->color_w = 0.06 * width; d->button_spacing = 0.01 * width; d->button_h = 0.06 * width; d->button_y = d->button_spacing; d->mode_w = d->color_w; d->mode_x = width - 3 * (d->color_w + d->button_spacing) - (d->mode_w + d->button_spacing); d->red_x = width - 3 * (d->color_w + d->button_spacing); d->green_x = width - 2 * (d->color_w + d->button_spacing); d->blue_x = width - (d->color_w + d->button_spacing); } // TODO: probably this should move to the configure-event callback! That would be future proof if we ever // (again) allow to resize the side panels. const gint stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); // this code assumes that the first expose comes before the first (preview) pipe is processed and that the // size of the widget doesn't change! if(dev->histogram_waveform_width == 0) { dev->histogram_waveform = (uint32_t *)calloc(height * stride / 4, sizeof(uint32_t)); dev->histogram_waveform_stride = stride; dev->histogram_waveform_height = height; dev->histogram_waveform_width = width; // return TRUE; // there are enough expose events following ... } #if 1 // draw shadow around float alpha = 1.0f; cairo_set_line_width(cr, 0.2); for(int k = 0; k < inset; k++) { cairo_rectangle(cr, -k, -k, width + 2 * k, height + 2 * k); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.5f; cairo_fill(cr); } cairo_set_line_width(cr, 1.0); #else cairo_set_line_width(cr, 1.0); cairo_set_source_rgb(cr, .1, .1, .1); cairo_rectangle(cr, 0, 0, width, height); cairo_stroke(cr); #endif cairo_rectangle(cr, 0, 0, width, height); cairo_clip(cr); cairo_set_source_rgb(cr, .3, .3, .3); cairo_rectangle(cr, 0, 0, width, height); cairo_fill(cr); if(d->highlight == 1) { cairo_set_source_rgb(cr, .5, .5, .5); cairo_rectangle(cr, 0, 0, .2 * width, height); cairo_fill(cr); } else if(d->highlight == 2) { cairo_set_source_rgb(cr, .5, .5, .5); cairo_rectangle(cr, 0.2 * width, 0, width, height); cairo_fill(cr); } // draw grid cairo_set_line_width(cr, .4); cairo_set_source_rgb(cr, .1, .1, .1); if(dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM) dt_draw_waveform_lines(cr, 0, 0, width, height); else dt_draw_grid(cr, 4, 0, 0, width, height); if(hist_max > 0.0f) { cairo_save(cr); if(dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM) { // make the color channel selector work: uint8_t *buf = (uint8_t *)malloc(sizeof(uint8_t) * height * stride); uint8_t mask[3] = { d->blue, d->green, d->red }; memcpy(buf, dev->histogram_waveform, sizeof(uint8_t) * height * stride); for(int y = 0; y < height; y++) for(int x = 0; x < width; x++) for(int k = 0; k < 3; k++) { buf[y * stride + x * 4 + k] *= mask[k]; } cairo_surface_t *source = cairo_image_surface_create_for_data(buf, CAIRO_FORMAT_ARGB32, width, height, stride); cairo_set_source_surface(cr, source, 0.0, 0.0); cairo_set_operator(cr, CAIRO_OPERATOR_ADD); cairo_paint(cr); cairo_surface_destroy(source); free(buf); } else { // cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); cairo_translate(cr, 0, height); cairo_scale(cr, width / 63.0, -(height - 10) / hist_max); cairo_set_operator(cr, CAIRO_OPERATOR_ADD); // cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_line_width(cr, 1.); if(d->red) { cairo_set_source_rgba(cr, 1., 0., 0., 0.2); dt_draw_histogram_8(cr, hist, 0, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR); } if(d->green) { cairo_set_source_rgba(cr, 0., 1., 0., 0.2); dt_draw_histogram_8(cr, hist, 1, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR); } if(d->blue) { cairo_set_source_rgba(cr, 0., 0., 1., 0.2); dt_draw_histogram_8(cr, hist, 2, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR); } cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); // cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); } cairo_restore(cr); } cairo_set_source_rgb(cr, .25, .25, .25); cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); PangoLayout *layout; PangoRectangle ink; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_font_description_set_absolute_size(desc, .1 * height * PANGO_SCALE); pango_layout_set_font_description(layout, desc); char exifline[50]; dt_image_print_exif(&dev->image_storage, exifline, 50); pango_layout_set_text(layout, exifline, -1); pango_layout_get_pixel_extents(layout, &ink, NULL); cairo_move_to(cr, .02 * width, .98 * height - ink.height - ink.y); cairo_save(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0)); cairo_set_source_rgba(cr, 1, 1, 1, 0.3); pango_cairo_layout_path(cr, layout); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, .25, .25, .25); cairo_fill(cr); cairo_restore(cr); // buttons to control the display of the histogram: linear/log, r, g, b if(d->highlight != 0) { _draw_mode_toggle(cr, d->mode_x, d->button_y, d->mode_w, d->button_h, dev->histogram_type); cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.4); _draw_color_toggle(cr, d->red_x, d->button_y, d->color_w, d->button_h, d->red); cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 0.4); _draw_color_toggle(cr, d->green_x, d->button_y, d->color_w, d->button_h, d->green); cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 0.4); _draw_color_toggle(cr, d->blue_x, d->button_y, d->color_w, d->button_h, d->blue); } cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); pango_font_description_free(desc); g_object_unref(layout); return TRUE; }
void render_glyph( cairo_t* cr, PangoFontDescription* font_desc, PangoFont* font, const guint code_point, const size_t cell_x, const size_t cell_y, const size_t cell_size, const double tex_size, const int ascent, const int descent, std::ostream& bgm_out ) { PangoLayout *layout = pango_cairo_create_layout(cr); char str[6] = {'\0'}; size_t len = 0; oglplus::aux::ConvertCodePointToUTF8(code_point, str, len); pango_layout_set_font_description(layout, font_desc); pango_layout_set_text(layout, str, len); const int baseline = pango_layout_get_baseline(layout); const double inv_ps = 1.0 / double(PANGO_SCALE); const double font_size = ascent+descent; PangoRectangle ink_rect, log_rect; pango_layout_get_extents( layout, &ink_rect, &log_rect ); // code point number bgm_out << code_point << std::endl; // hex representation of the number bgm_out << std::hex << "0x" << code_point << std::dec << std::endl; // the utf-8 sequence bgm_out << "'" << str << "'" << std::endl; // // vertex[0] logical rectangle metrics // // Left bearing (x) bgm_out << PANGO_LBEARING(log_rect)/font_size << std::endl; // Right bearing (x+width) bgm_out << PANGO_RBEARING(log_rect)/font_size << std::endl; // Ascent bgm_out << (baseline-log_rect.y)/font_size << std::endl; // Descent bgm_out << (log_rect.height+log_rect.y-baseline)/font_size << std::endl; // // vertex[1] ink rectangle metrics // // Left bearing (x) bgm_out << PANGO_LBEARING(ink_rect)/font_size << std::endl; // Right bearing (x+width) bgm_out << PANGO_RBEARING(ink_rect)/font_size << std::endl; // Ascent bgm_out << (baseline-ink_rect.y)/font_size << std::endl; // Descent bgm_out << (ink_rect.y+ink_rect.height-baseline)/font_size << std::endl; // // vertex[2] texture coordinates // // Origin X bgm_out << (cell_x*cell_size+ink_rect.x*inv_ps)/tex_size << std::endl; // Origin Y bgm_out << 1.0-(cell_y*cell_size+baseline*inv_ps)/tex_size << std::endl; // Width bgm_out << ((ink_rect.width)*inv_ps)/tex_size << std::endl; // Height bgm_out << ((ink_rect.height)*inv_ps)/tex_size << std::endl; // separating newline bgm_out << std::endl; cairo_new_path(cr); cairo_move_to(cr, cell_x*cell_size, cell_y*cell_size); cairo_set_line_width(cr, 0.5); pango_cairo_update_layout(cr, layout); pango_cairo_layout_path(cr, layout); cairo_fill(cr); g_object_unref(layout); }
static gboolean video_area_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer user_data) { GthMediaViewerPage *self = user_data; GtkAllocation allocation; GtkStyleContext *style_context; if (self->priv->xwin_assigned && self->priv->has_video) return FALSE; gtk_widget_get_allocation (widget, &allocation); style_context = gtk_widget_get_style_context (widget); if (self->priv->icon == NULL) { char *type; GIcon *icon; int size; type = NULL; if (self->priv->file_data != NULL) type = g_content_type_from_mime_type (gth_file_data_get_mime_type (self->priv->file_data)); if (type == NULL) type = g_content_type_from_mime_type ("text/plain"); icon = g_content_type_get_icon (type); size = allocation.width; if (size > allocation.height) size = allocation.height; size = size / 3; self->priv->icon = _g_icon_get_pixbuf (icon, size, _gtk_widget_get_icon_theme (widget)); g_object_unref (icon); g_free (type); } cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); cairo_rectangle (cr, 0, 0, allocation.width, allocation.height); cairo_fill (cr); if (self->priv->icon != NULL) { int icon_w, icon_h; int text_w; int icon_x, icon_y; PangoRectangle logical_rect; int x, y; PangoFontDescription *font; icon_w = gdk_pixbuf_get_width (self->priv->icon); icon_h = gdk_pixbuf_get_height (self->priv->icon); text_w = (icon_w * 3 / 2); pango_layout_set_width (self->priv->caption_layout, PANGO_SCALE * text_w); pango_layout_get_extents (self->priv->caption_layout, NULL, &logical_rect); icon_x = (allocation.width - icon_w) / 2; x = (allocation.width - text_w) / 2; icon_y = (allocation.height - (icon_h + PANGO_PIXELS (logical_rect.height))) / 2; y = icon_y + icon_h; gdk_cairo_set_source_pixbuf (cr, self->priv->icon, icon_x, icon_y); cairo_rectangle (cr, icon_x, icon_y, icon_w, icon_h); cairo_fill (cr); cairo_move_to (cr, x, y); gtk_style_context_get (style_context, gtk_widget_get_state_flags (widget), "font", &font, NULL); pango_layout_set_font_description (self->priv->caption_layout, font); pango_cairo_layout_path (cr, self->priv->caption_layout); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_fill (cr); } return TRUE; }
static void write_text_full ( cairo_t* cr, const char *txt, PangoFontDescription *font, const float x, const float y, const float ang, const int align, const float * const col) { int tw, th; cairo_save(cr); PangoLayout * pl = pango_cairo_create_layout(cr); pango_layout_set_font_description(pl, font); if (strncmp(txt, "<markup>", 8)) { pango_layout_set_text(pl, txt, -1); } else { pango_layout_set_markup(pl, txt, -1); } pango_layout_get_pixel_size(pl, &tw, &th); cairo_translate (cr, rintf(x), rintf(y)); if (ang != 0) { cairo_rotate (cr, ang); } switch(abs(align)) { case 1: cairo_translate (cr, -tw, ceil(th/-2.0)); pango_layout_set_alignment (pl, PANGO_ALIGN_RIGHT); break; case 2: cairo_translate (cr, ceil(tw/-2.0), ceil(th/-2.0)); pango_layout_set_alignment (pl, PANGO_ALIGN_CENTER); break; case 3: cairo_translate (cr, 0, ceil(th/-2.0)); pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT); break; case 4: cairo_translate (cr, -tw, -th); pango_layout_set_alignment (pl, PANGO_ALIGN_RIGHT); break; case 5: cairo_translate (cr, ceil(tw/-2.0), -th); pango_layout_set_alignment (pl, PANGO_ALIGN_CENTER); break; case 6: cairo_translate (cr, 0, -th); pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT); break; case 7: cairo_translate (cr, -tw, 0); pango_layout_set_alignment (pl, PANGO_ALIGN_RIGHT); break; case 8: cairo_translate (cr, ceil(tw/-2.0), 0); pango_layout_set_alignment (pl, PANGO_ALIGN_CENTER); break; case 9: cairo_translate (cr, 0, 0); pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT); break; default: break; } if (align < 0) { cairo_set_source_rgba (cr, .0, .0, .0, .5); cairo_rectangle (cr, 0, 0, tw, th); cairo_fill (cr); } #if 1 cairo_set_source_rgba (cr, col[0], col[1], col[2], col[3]); pango_cairo_show_layout(cr, pl); #else cairo_set_source_rgba (cr, col[0], col[1], col[2], col[3]); pango_cairo_layout_path(cr, pl); cairo_fill(cr); #endif g_object_unref(pl); cairo_restore(cr); cairo_new_path (cr); }
gboolean ly_3lrc_desktop_on_expose_cb (GtkWidget * widget, cairo_t *cr, gpointer data) { gchar desktop_font[1024]="Sans Regular 25"; ly_reg_get("3lrc_desktop_font", "%1024[^\n]", desktop_font); gchar path[1024]; g_snprintf(path,sizeof(path),"%sicon/null.png",LY_GLB_PROG_UIXDIR); if(!desktop_bg) desktop_bg=cairo_image_surface_create_from_png(path); cairo_set_source_surface(cr, desktop_bg, 0, 0); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); int width; int height; width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); int x=0; int y=height; //鼠标进入 if(flag_notify) { //填充圆角矩形拖动区域 cairo_set_source_rgba(cr,0,0,0,0.3); cairo_move_to (cr, 0 + 5, 0); cairo_line_to (cr, 0 + width - 5, 0); cairo_move_to (cr, 0 + width, 0 + 5); cairo_line_to (cr, 0 + width, 0 + height - 5); cairo_move_to (cr, 0 + width - 5, 0 + height); cairo_line_to (cr, 0 + 5, 0 + height); cairo_move_to (cr, 0, 0 + height - 5); cairo_line_to (cr, 0, 0 + 5); cairo_arc (cr, 0 + 5, 0 + 5, 5, M_PI, 3 * M_PI / 2.0); cairo_arc (cr, 0 + width - 5, 0 + 5, 5, 3 * M_PI / 2, 2 * M_PI); cairo_arc (cr, 0 + width - 5, 0 + height - 5, 5, 0, M_PI / 2); cairo_arc (cr, 0 + 5, 0 + height - 5, 5, M_PI / 2, M_PI); cairo_fill(cr); } if(ly_lrc_get_length()>0) { //计算占空比 gint64 t1=0; gint64 t2=0; LyMdhMetadata *md=NULL; md=ly_pqm_get_current_md(); if(!md) return FALSE; if(ly_lrc_get_index()+1<ly_lrc_get_length()) t1=(ly_lrc_get_array()[ly_lrc_get_index()+1])->time-(ly_lrc_get_array()[ly_lrc_get_index()])->time; else t1=ly_mdh_time_str2int(md->duration)-ly_mdh_time_str2int(md->start)-(ly_lrc_get_array()[ly_lrc_get_index()])->time; t2=ly_aud_get_position_abs()-ly_mdh_time_str2int(md->start)-(ly_lrc_get_array()[ly_lrc_get_index()])->time; if(t1!=0) { x=(int)((t2/(gdouble)t1)*pos_layout[X]); } //画歌词 cairo_set_source_rgb(cr,0,0,0); //确定起始点 if((x>=width/2)&&(pos_layout[X]>width)&&(width<(pos_layout[X]-x)*2)) { cairo_move_to(cr, 0-(x-width/2), 5); x=width/2; } else if((x>=width/2)&&(pos_layout[X]>width)&&(width>=(pos_layout[X]-x)*2)) cairo_move_to(cr, 0-(pos_layout[X]-width), 5); else cairo_move_to(cr, 0, 5); PangoLayout *layout; PangoFontDescription *desc; layout = pango_cairo_create_layout (cr); pango_layout_set_text(layout, ly_lrc_get_array()[ly_lrc_get_index()]->text, -1); desc = pango_font_description_from_string (desktop_font); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); pango_layout_get_size(layout,&pos_layout[X],&pos_layout[Y]); pos_layout[X]=pos_layout[X]/1000; pango_cairo_update_layout (cr, layout); pango_cairo_layout_path (cr, layout); cairo_clip(cr); g_object_unref (layout); //画背景条 cairo_pattern_t *pat; pat = cairo_pattern_create_linear (0, 0,10.0, 150); cairo_pattern_add_color_stop_rgb (pat, 0.1, 65535/65535.0, 10449/65535.0, 0/65535.0); cairo_pattern_add_color_stop_rgb (pat, 0.5, 65535/65535.0, 61062/65535.0, 0/65535.0); cairo_pattern_add_color_stop_rgb (pat, 0.9, 65535/65535.0, 10449/65535.0, 0/65535.0); //画矩形 if((x>=width/2)&&(pos_layout[X]>width)&&(width<(pos_layout[X]-x)*2)) cairo_rectangle (cr, 0, 0, width/2, y); else if((x>=width/2)&&(pos_layout[X]>width)&&(width>=(pos_layout[X]-x)*2)) cairo_rectangle (cr, 0, 0, width-(pos_layout[X]-x), y); else cairo_rectangle (cr, 0, 0, x, y); cairo_set_source (cr, pat); cairo_fill(cr); cairo_pattern_destroy (pat); pat = cairo_pattern_create_linear (0, 0,10.0, 150); cairo_pattern_add_color_stop_rgb (pat, 0.1, 19532/65535.0, 65535/65535.0, 65535/65535.0); cairo_pattern_add_color_stop_rgb (pat, 0.5, 5539/65535.0, 0/65535.0, 65535/65535.0); cairo_pattern_add_color_stop_rgb (pat, 0.9, 19532/65535.0, 65535/65535.0, 65535/65535.0); //画矩形 if((x>=width/2)&&(pos_layout[X]>width)&&(width<(pos_layout[X]-x)*2)) cairo_rectangle (cr, width/2, 0, width-(width/2), y); else if((x>=width/2)&&(pos_layout[X]>width)&&(width>=(pos_layout[X]-x)*2)) cairo_rectangle (cr, width-(pos_layout[X]-x), 0, pos_layout[X]-x, y); else cairo_rectangle (cr, x, 0, width-x, y); cairo_set_source (cr, pat); cairo_fill(cr); cairo_pattern_destroy (pat); } int lrc_desktop=1; int lrc_desktop_fix=0; if(!ly_reg_get("3lrc_desktop_state", "%d:%d", &lrc_desktop, &lrc_desktop_fix)) { ly_reg_set("3lrc_desktop_state", "%d:%d", lrc_desktop, lrc_desktop_fix); } if(lrc_desktop_fix>0) gtk_widget_set_sensitive(widget,FALSE); else gtk_widget_set_sensitive(widget,TRUE); cairo_region_t *region; if(!(lrc_desktop_fix)) { cairo_rectangle_int_t rect; rect.x=rect.y=0; rect.width=width; rect.height=height; region=cairo_region_create_rectangle(&rect); } else { region=cairo_region_create(); } gdk_window_input_shape_combine_region (gtk_widget_get_window(widget), region, 0, 0); cairo_region_destroy (region); return FALSE; }
gboolean text_to_path (const Text *text, GArray *points) { cairo_t *cr; cairo_surface_t *surface; PangoLayout *layout; PangoRectangle ink_rect; char *str; gboolean ret = FALSE; if (!PANGO_IS_CAIRO_FONT_MAP (pango_context_get_font_map (dia_font_get_context()))) return FALSE; layout = pango_layout_new(dia_font_get_context()); pango_layout_set_font_description (layout, dia_font_get_description (text->font)); pango_layout_set_indent (layout, 0); pango_layout_set_justify (layout, FALSE); pango_layout_set_alignment (layout, text->alignment == ALIGN_LEFT ? PANGO_ALIGN_LEFT : text->alignment == ALIGN_RIGHT ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_CENTER); str = text_get_string_copy (text); pango_layout_set_text (layout, str, -1); g_free (str); pango_layout_get_extents (layout, &ink_rect, NULL); /* any surface should do - this one is always available */ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ink_rect.width / PANGO_SCALE, ink_rect.height / PANGO_SCALE); cr = cairo_create (surface); cairo_surface_destroy (surface); pango_cairo_layout_path (cr, layout); /* convert the path */ if (cairo_status (cr) == CAIRO_STATUS_SUCCESS) { cairo_path_t *path; int i; path = cairo_copy_path (cr); for (i=0; i < path->num_data; i += path->data[i].header.length) { cairo_path_data_t *data = &path->data[i]; BezPoint bp; switch (data->header.type) { case CAIRO_PATH_MOVE_TO : bp.type = BEZ_MOVE_TO; bp.p1.x = data[1].point.x; bp.p1.y = data[1].point.y; break; case CAIRO_PATH_LINE_TO : bp.type = BEZ_LINE_TO; bp.p1.x = data[1].point.x; bp.p1.y = data[1].point.y; break; case CAIRO_PATH_CURVE_TO : bp.type = BEZ_CURVE_TO; bp.p1.x = data[1].point.x; bp.p1.y = data[1].point.y; bp.p2.x = data[2].point.x; bp.p2.y = data[2].point.y; bp.p3.x = data[3].point.x; bp.p3.y = data[3].point.y; break; case CAIRO_PATH_CLOSE_PATH : /* can't do anything */ default : continue; } g_array_append_val (points, bp); } ret = (path->status == CAIRO_STATUS_SUCCESS); cairo_path_destroy (path); } /* finally scale it ? */ /* clean up */ g_object_unref (layout); cairo_destroy (cr); return ret; }
static GdkPixbuf * create_gallery (ThumbApp *app) { GdkPixbuf *screenshot, *pixbuf = NULL; cairo_t *cr; cairo_surface_t *surface; PangoLayout *layout; PangoFontDescription *font_desc; gint64 stream_length, screenshot_interval, pos; guint columns = 3, rows, current_column, current_row, x, y; gint screenshot_width = 0, screenshot_height = 0, x_padding = 0, y_padding = 0; gfloat scale = 1.0; gchar *header_text, *duration_text, *filename; /* Calculate how many screenshots we're going to take */ stream_length = app->duration; /* As a default, we have one screenshot per minute of stream, * but adjusted so we don't have any gaps in the resulting gallery. */ if (gallery == 0) { gallery = stream_length / 60000; while (gallery % 3 != 0 && gallery % 4 != 0 && gallery % 5 != 0) { gallery++; } } if (gallery < GALLERY_MIN) gallery = GALLERY_MIN; if (gallery > GALLERY_MAX) gallery = GALLERY_MAX; screenshot_interval = stream_length / gallery; /* Put a lower bound on the screenshot interval so we can't enter an infinite loop below */ if (screenshot_interval == 0) screenshot_interval = 1; PROGRESS_DEBUG ("Producing gallery of %u screenshots, taken at %" G_GINT64_FORMAT " millisecond intervals throughout a %" G_GINT64_FORMAT " millisecond-long stream.", gallery, screenshot_interval, stream_length); /* Calculate how to arrange the screenshots so we don't get ones orphaned on the last row. * At this point, only deal with arrangements of 3, 4 or 5 columns. */ y = G_MAXUINT; for (x = 3; x <= 5; x++) { if (gallery % x == 0 || x - gallery % x < y) { y = x - gallery % x; columns = x; /* Have we found an optimal solution already? */ if (y == x) break; } } rows = ceil ((gfloat) gallery / (gfloat) columns); PROGRESS_DEBUG ("Outputting as %u rows and %u columns.", rows, columns); /* Take the screenshots and composite them into a pixbuf */ current_column = current_row = x = y = 0; for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) { if (pos == stream_length) screenshot = capture_frame_at_time (app, pos - 1); else screenshot = capture_frame_at_time (app, pos); if (pixbuf == NULL) { screenshot_width = gdk_pixbuf_get_width (screenshot); screenshot_height = gdk_pixbuf_get_height (screenshot); /* Calculate a scaling factor so that screenshot_width -> output_size */ scale = (float) output_size / (float) screenshot_width; x_padding = x = MAX (output_size * 0.05, 1); y_padding = y = MAX (scale * screenshot_height * 0.05, 1); PROGRESS_DEBUG ("Scaling each screenshot by %f.", scale); /* Create our massive pixbuf */ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, columns * output_size + (columns + 1) * x_padding, (guint) (rows * scale * screenshot_height + (rows + 1) * y_padding)); gdk_pixbuf_fill (pixbuf, 0x000000ff); PROGRESS_DEBUG ("Created output pixbuf (%ux%u).", gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf)); } /* Composite the screenshot into our gallery */ gdk_pixbuf_composite (screenshot, pixbuf, x, y, output_size, scale * screenshot_height, (gdouble) x, (gdouble) y, scale, scale, GDK_INTERP_BILINEAR, 255); g_object_unref (screenshot); PROGRESS_DEBUG ("Composited screenshot from %" G_GINT64_FORMAT " milliseconds (address %u) at (%u,%u).", pos, GPOINTER_TO_UINT (screenshot), x, y); /* We print progress in the range 10% (MIN_PROGRESS) to 50% (MAX_PROGRESS - MIN_PROGRESS) / 2.0 */ PRINT_PROGRESS (MIN_PROGRESS + (current_row * columns + current_column) * (((MAX_PROGRESS - MIN_PROGRESS) / gallery) / 2.0)); current_column = (current_column + 1) % columns; x += output_size + x_padding; if (current_column == 0) { x = x_padding; y += scale * screenshot_height + y_padding; current_row++; } } PROGRESS_DEBUG ("Converting pixbuf to a Cairo surface."); /* Load the pixbuf into a Cairo surface and overlay the text. The height is the height of * the gallery plus the necessary height for 3 lines of header (at ~18px each), plus some * extra padding. */ surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf) + GALLERY_HEADER_HEIGHT + y_padding); cr = cairo_create (surface); cairo_surface_destroy (surface); /* First, copy across the gallery pixbuf */ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0.0, GALLERY_HEADER_HEIGHT + y_padding); cairo_rectangle (cr, 0.0, GALLERY_HEADER_HEIGHT + y_padding, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf)); cairo_fill (cr); g_object_unref (pixbuf); /* Build the header information */ duration_text = xplayer_time_to_string (stream_length); filename = NULL; if (strstr (app->input, "://")) { char *local; local = g_filename_from_uri (app->input, NULL, NULL); filename = g_path_get_basename (local); g_free (local); } if (filename == NULL) filename = g_path_get_basename (app->input); /* Translators: The first string is "Filename" (as translated); the second is an actual filename. The third string is "Resolution" (as translated); the fourth and fifth are screenshot height and width, respectively. The sixth string is "Duration" (as translated); the seventh is the movie duration in words. */ header_text = g_markup_printf_escaped (_("<b>%s</b>: %s\n<b>%s</b>: %d\303\227%d\n<b>%s</b>: %s"), _("Filename"), filename, _("Resolution"), screenshot_width, screenshot_height, _("Duration"), duration_text); g_free (duration_text); g_free (filename); PROGRESS_DEBUG ("Writing header text with Pango."); /* Write out some header information */ layout = pango_cairo_create_layout (cr); font_desc = pango_font_description_from_string ("Sans 18px"); pango_layout_set_font_description (layout, font_desc); pango_font_description_free (font_desc); pango_layout_set_markup (layout, header_text, -1); g_free (header_text); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */ cairo_move_to (cr, (gdouble) x_padding, (gdouble) y_padding); pango_cairo_show_layout (cr, layout); /* Go through each screenshot and write its timestamp */ current_column = current_row = 0; x = x_padding + output_size; y = y_padding * 2 + GALLERY_HEADER_HEIGHT + scale * screenshot_height; font_desc = pango_font_description_from_string ("Sans 10px"); pango_layout_set_font_description (layout, font_desc); pango_font_description_free (font_desc); PROGRESS_DEBUG ("Writing screenshot timestamps with Pango."); for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) { gchar *timestamp_text; gint layout_width, layout_height; timestamp_text = xplayer_time_to_string (pos); pango_layout_set_text (layout, timestamp_text, -1); pango_layout_get_pixel_size (layout, &layout_width, &layout_height); /* Display the timestamp in the bottom-right corner of the current screenshot */ cairo_move_to (cr, x - layout_width - 0.02 * output_size, y - layout_height - 0.02 * scale * screenshot_height); /* We have to stroke the text so it's visible against screenshots of the same * foreground color. */ pango_cairo_layout_path (cr, layout); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */ cairo_stroke_preserve (cr); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */ cairo_fill (cr); PROGRESS_DEBUG ("Writing timestamp \"%s\" at (%f,%f).", timestamp_text, x - layout_width - 0.02 * output_size, y - layout_height - 0.02 * scale * screenshot_height); /* We print progress in the range 50% (MAX_PROGRESS - MIN_PROGRESS) / 2.0) to 90% (MAX_PROGRESS) */ PRINT_PROGRESS (MIN_PROGRESS + (MAX_PROGRESS - MIN_PROGRESS) / 2.0 + (current_row * columns + current_column) * (((MAX_PROGRESS - MIN_PROGRESS) / gallery) / 2.0)); g_free (timestamp_text); current_column = (current_column + 1) % columns; x += output_size + x_padding; if (current_column == 0) { x = x_padding + output_size; y += scale * screenshot_height + y_padding; current_row++; } } g_object_unref (layout); PROGRESS_DEBUG ("Converting Cairo surface back to pixbuf."); /* Create a new pixbuf from the Cairo context */ pixbuf = cairo_surface_to_pixbuf (cairo_get_target (cr)); cairo_destroy (cr); return pixbuf; }
static void draw_str(struct gra2cairo_local *local, int draw, char *str, struct fontmap *font, int size, int space, int *fw, int *ah, int *dh) { PangoAttribute *attr; PangoAttrList *alist; PangoLayoutIter *piter; int w, h, baseline; if (size == 0 || str == NULL) { if (fw) *fw = 0; if (ah) *ah = 0; if (dh) *dh = 0; return; } if (local->layout == NULL) { local->layout = pango_cairo_create_layout(local->cairo); } alist = pango_attr_list_new(); attr = pango_attr_size_new_absolute(mxd2ph(local, size) * PANGO_SCALE); pango_attr_list_insert(alist, attr); attr = pango_attr_letter_spacing_new(mxd2ph(local, space) * PANGO_SCALE); pango_attr_list_insert(alist, attr); pango_layout_set_font_description(local->layout, font->font); pango_layout_set_attributes(local->layout, alist); pango_attr_list_unref(alist); pango_layout_set_text(local->layout, str, -1); pango_layout_get_pixel_size(local->layout, &w, &h); piter = pango_layout_get_iter(local->layout); baseline = pango_layout_iter_get_baseline(piter) / PANGO_SCALE; if (fw) *fw = w; if (ah) *ah = baseline; if (dh) *dh = h - baseline; if (draw && str) { double x, y; double cx, cy; x = - local->fontsin * baseline; y = - local->fontcos * baseline; cairo_get_current_point(local->cairo, &cx, &cy); relative_move(local->cairo, x, y); cairo_save(local->cairo); cairo_rotate(local->cairo, -local->fontdir * G_PI / 180.); pango_cairo_update_layout(local->cairo, local->layout); if (local->text2path) { pango_cairo_layout_path(local->cairo, local->layout); cairo_fill(local->cairo); cairo_restore(local->cairo); cairo_move_to(local->cairo, cx + w * local->fontcos, cy - w * local->fontsin); } else { pango_cairo_show_layout(local->cairo, local->layout); cairo_restore(local->cairo); relative_move(local->cairo, w * local->fontcos - x, - w * local->fontsin - y); } } pango_layout_iter_free(piter); }
static gboolean _lib_navigation_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_navigation_t *d = (dt_lib_navigation_t *)self->data; const int inset = DT_NAVIGATION_INSET; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; dt_develop_t *dev = darktable.develop; /* double buffering of image data: only take new data if valid */ if(dev->preview_pipe->backbuf && dev->preview_status == DT_DEV_PIXELPIPE_VALID) { /* re-allocate in case of changed image dimensions */ if(d->buffer == NULL || dev->preview_pipe->backbuf_width != d->wd || dev->preview_pipe->backbuf_height != d->ht) { g_free(d->buffer); d->wd = dev->preview_pipe->backbuf_width; d->ht = dev->preview_pipe->backbuf_height; d->buffer = g_malloc0((size_t)d->wd * d->ht * 4 * sizeof(unsigned char)); } /* update buffer if new data is available */ if(d->buffer && dev->preview_pipe->input_timestamp > d->timestamp) { dt_pthread_mutex_t *mutex = &dev->preview_pipe->backbuf_mutex; dt_pthread_mutex_lock(mutex); memcpy(d->buffer, dev->preview_pipe->backbuf, (size_t)d->wd * d->ht * 4 * sizeof(unsigned char)); d->timestamp = dev->preview_pipe->input_timestamp; dt_pthread_mutex_unlock(mutex); } } /* get the current style */ cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); GtkStyleContext *context = gtk_widget_get_style_context(widget); gtk_render_background(context, cr, 0, 0, allocation.width, allocation.height); width -= 2 * inset; height -= 2 * inset; cairo_translate(cr, inset, inset); /* draw navigation image if available */ if(d->buffer) { cairo_save(cr); const int wd = d->wd; const int ht = d->ht; const float scale = fminf(width / (float)wd, height / (float)ht); const int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wd); cairo_surface_t *surface = cairo_image_surface_create_for_data(d->buffer, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_translate(cr, width / 2.0, height / 2.0f); cairo_scale(cr, scale, scale); cairo_translate(cr, -.5f * wd, -.5f * ht); // draw shadow around float alpha = 1.0f; for(int k = 0; k < 4; k++) { cairo_rectangle(cr, -k / scale, -k / scale, wd + 2 * k / scale, ht + 2 * k / scale); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } cairo_rectangle(cr, 0, 0, wd - 2, ht - 1); cairo_set_source_surface(cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST); cairo_fill(cr); cairo_surface_destroy(surface); // draw box where we are dt_dev_zoom_t zoom = dt_control_get_dev_zoom(); int closeup = dt_control_get_dev_closeup(); float zoom_x = dt_control_get_dev_zoom_x(); float zoom_y = dt_control_get_dev_zoom_y(); const float min_scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, closeup ? 2.0 : 1.0, 0); const float cur_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0); // avoid numerical instability for small resolutions: double h, w; if(cur_scale > min_scale) { float boxw = 1, boxh = 1; dt_dev_check_zoom_bounds(darktable.develop, &zoom_x, &zoom_y, zoom, closeup, &boxw, &boxh); cairo_translate(cr, wd * (.5f + zoom_x), ht * (.5f + zoom_y)); cairo_set_source_rgb(cr, 0., 0., 0.); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.f / scale)); boxw *= wd; boxh *= ht; cairo_rectangle(cr, -boxw / 2 - 1, -boxh / 2 - 1, boxw + 2, boxh + 2); cairo_stroke(cr); cairo_set_source_rgb(cr, 1., 1., 1.); cairo_rectangle(cr, -boxw / 2, -boxh / 2, boxw, boxh); cairo_stroke(cr); } cairo_restore(cr); if(fabsf(cur_scale - min_scale) > 0.001f) { /* Zoom % */ PangoLayout *layout; PangoRectangle ink; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); const float fontsize = DT_PIXEL_APPLY_DPI(11); pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE); pango_layout_set_font_description(layout, desc); cairo_translate(cr, 0, height); cairo_set_source_rgba(cr, 1., 1., 1., 0.5); cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); char zoomline[5]; snprintf(zoomline, sizeof(zoomline), "%.0f%%", cur_scale * 100); pango_layout_set_text(layout, zoomline, -1); pango_layout_get_pixel_extents(layout, &ink, NULL); h = d->zoom_h = ink.height; w = d->zoom_w = ink.width; cairo_move_to(cr, width - w - h * 1.1 - ink.x, - fontsize); cairo_save(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0)); GdkRGBA *color; gtk_style_context_get(context, gtk_widget_get_state_flags(widget), "background-color", &color, NULL); gdk_cairo_set_source_rgba(cr, color); pango_cairo_layout_path(cr, layout); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_fill(cr); cairo_restore(cr); gdk_rgba_free(color); pango_font_description_free(desc); g_object_unref(layout); } else { // draw the zoom-to-fit icon cairo_translate(cr, 0, height); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); static int height = -1; if(height == -1) { PangoLayout *layout; PangoRectangle ink; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_font_description_set_absolute_size(desc, DT_PIXEL_APPLY_DPI(11) * PANGO_SCALE); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, "100%", -1); // dummy text, just to get the height pango_layout_get_pixel_extents(layout, &ink, NULL); height = ink.height; pango_font_description_free(desc); g_object_unref(layout); } h = d->zoom_h = height; w = h * 1.5; float sp = h * 0.6; d->zoom_w = w + sp; cairo_move_to(cr, width - w - h - sp, -1.0 * h); cairo_rectangle(cr, width - w - h - sp, -1.0 * h, w, h); cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); cairo_fill(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0)); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_move_to(cr, width - w * 0.8 - h - sp, -1.0 * h); cairo_line_to(cr, width - w - h - sp, -1.0 * h); cairo_line_to(cr, width - w - h - sp, -0.7 * h); cairo_stroke(cr); cairo_move_to(cr, width - w - h - sp, -0.3 * h); cairo_line_to(cr, width - w - h - sp, 0); cairo_line_to(cr, width - w * 0.8 - h - sp, 0); cairo_stroke(cr); cairo_move_to(cr, width - w * 0.2 - h - sp, 0); cairo_line_to(cr, width - h - sp, 0); cairo_line_to(cr, width - h - sp, -0.3 * h); cairo_stroke(cr); cairo_move_to(cr, width - h - sp, -0.7 * h); cairo_line_to(cr, width - h - sp, -1.0 * h); cairo_line_to(cr, width - w * 0.2 - h - sp, -1.0 * h); cairo_stroke(cr); } cairo_move_to(cr, width - 0.95 * h, -0.9 * h); cairo_line_to(cr, width - 0.05 * h, -0.9 * h); cairo_line_to(cr, width - 0.5 * h, -0.1 * h); cairo_fill(cr); } /* blit memsurface into widget */ cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); return TRUE; }