static void draw_text (RsvgDrawingCtx * ctx, cairo_t *cr, double *x, double *y, const char *text) { PangoContext *context; PangoLayout *layout; RsvgState *state; PangoLayoutLine *line; int w, h; state = rsvg_current_state (ctx); if (state->font_size.length == 0) return; context = ctx->render->create_pango_context (ctx); layout = rsvg_text_create_layout (ctx, state, text, context); pango_layout_get_size(layout, &w, &h); // From pango example // http://git.gnome.org/browse/pango/tree/examples/cairotwisted.c line = pango_layout_get_line_readonly (layout, 0); cairo_move_to (cr, *x, *y); pango_cairo_layout_line_path (cr, line); // Update x, y based on dimensions of text drawn if (PANGO_GRAVITY_IS_VERTICAL (state->text_gravity)) *y += w / (double)PANGO_SCALE; else *x += w / (double)PANGO_SCALE; g_object_unref (layout); g_object_unref (context); }
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { #if defined(USE_FREETYPE) if (!primaryFont()->platformData().m_pattern) { drawSimpleText(context, run, point, from, to); return; } #endif cairo_t* cr = context->platformContext(); PangoLayout* layout = pango_cairo_create_layout(cr); setPangoAttributes(this, run, layout); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); // Our layouts are single line PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0); // Get the region where this text will be laid out. We will use it to clip // the Cairo context, for when we are only painting part of the text run and // to calculate the size of the shadow buffer. PangoRegionType partialRegion = 0; char* start = g_utf8_offset_to_pointer(utf8, from); char* end = g_utf8_offset_to_pointer(start, to - from); int ranges[] = {start - utf8, end - utf8}; partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1); drawGlyphsShadow(context, cr, point, layoutLine, partialRegion); cairo_save(cr); cairo_translate(cr, point.x(), point.y()); float red, green, blue, alpha; context->fillColor().getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); gdk_cairo_region(cr, partialRegion); cairo_clip(cr); pango_cairo_show_layout_line(cr, layoutLine); if (context->textDrawingMode() & TextModeStroke) { Color strokeColor = context->strokeColor(); strokeColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); pango_cairo_layout_line_path(cr, layoutLine); cairo_set_line_width(cr, context->strokeThickness()); cairo_stroke(cr); } // Pango sometimes leaves behind paths we don't want cairo_new_path(cr); destroyPangoRegion(partialRegion); g_free(utf8); g_object_unref(layout); cairo_restore(cr); }
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { cairo_t* cr = context->platformContext(); cairo_save(cr); cairo_translate(cr, point.x(), point.y()); PangoLayout* layout = pango_cairo_create_layout(cr); setPangoAttributes(this, run, layout); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); // Our layouts are single line PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0); GdkRegion* partialRegion = NULL; if (to - from != run.length()) { // Clip the region of the run to be rendered char* start = g_utf8_offset_to_pointer(utf8, from); char* end = g_utf8_offset_to_pointer(start, to - from); int ranges[] = {start - utf8, end - utf8}; partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1); gdk_region_shrink(partialRegion, 0, -pixelSize()); } Color fillColor = context->fillColor(); float red, green, blue, alpha; // Text shadow, inspired by FontMac IntSize shadowSize; int shadowBlur = 0; Color shadowColor; bool hasShadow = context->textDrawingMode() == cTextFill && context->getShadow(shadowSize, shadowBlur, shadowColor); // TODO: Blur support if (hasShadow) { // Disable graphics context shadows (not yet implemented) and paint them manually context->clearShadow(); Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); cairo_save(cr); shadowFillColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); cairo_translate(cr, shadowSize.width(), shadowSize.height()); if (partialRegion) { gdk_cairo_region(cr, partialRegion); cairo_clip(cr); } pango_cairo_show_layout_line(cr, layoutLine); cairo_restore(cr); } fillColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); if (partialRegion) { gdk_cairo_region(cr, partialRegion); cairo_clip(cr); } pango_cairo_show_layout_line(cr, layoutLine); if (context->textDrawingMode() & cTextStroke) { Color strokeColor = context->strokeColor(); strokeColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); pango_cairo_layout_line_path(cr, layoutLine); cairo_set_line_width(cr, context->strokeThickness()); cairo_stroke(cr); } // Re-enable the platform shadow we disabled earlier if (hasShadow) context->setShadow(shadowSize, shadowBlur, shadowColor); // Pango sometimes leaves behind paths we don't want cairo_new_path(cr); if (partialRegion) gdk_region_destroy(partialRegion); g_free(utf8); g_object_unref(layout); cairo_restore(cr); }
static VALUE rg_pango_layout_line_path(VALUE self, VALUE line) { pango_cairo_layout_line_path(RVAL2CRCONTEXT(self), RVAL2PANGOLAYOUTLINE(line)); return self; }