From fb5d6ad85ca10e67db70575b0604894fa8c484f5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 6 Aug 2008 08:38:47 +0000 Subject: [PATCH] New public API: 2008-07-30 Behdad Esfahbod * docs/pango-sections.txt: * docs/tmpl/pango-renderer.sgml: * pango/pango-renderer.c: * pango/pango-renderer.h: New public API: PangoRenderer::draw_glyph_item() pango_renderer_draw_glyph_item() Make layout and layout-line default renderers go through draw_glyph_item(), which then by default falls back to draw_glyphs(). The advantage in draw_glyph_item() is that it has access to the text and cluster information. * pango/pangocairo.h: * pango/pangocairo-render.c: New public API: pango_cairo_show_glyph_item() svn path=/trunk/; revision=2674 --- ChangeLog | 16 ++++ docs/pango-sections.txt | 2 + docs/tmpl/pango-renderer.sgml | 13 +++ docs/tmpl/pangocairo.sgml | 10 +++ pango/pango-renderer.c | 67 +++++++++++++++- pango/pango-renderer.h | 16 +++- pango/pango.def | 1 + pango/pangocairo-render.c | 178 +++++++++++++++++++++++++++++++++++++++++- pango/pangocairo.def | 1 + pango/pangocairo.h | 3 + 10 files changed, 299 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index c151f02..5fd8deb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 2008-07-30 Behdad Esfahbod + * docs/pango-sections.txt: + * docs/tmpl/pango-renderer.sgml: + * pango/pango-renderer.c: + * pango/pango-renderer.h: + New public API: + + PangoRenderer::draw_glyph_item() + pango_renderer_draw_glyph_item() + + Make layout and layout-line default renderers go through + draw_glyph_item(), which then by default falls back to + draw_glyphs(). The advantage in draw_glyph_item() is that it + has access to the text and cluster information. + +2008-07-30 Behdad Esfahbod + * docs/tmpl/text-attributes.sgml: Fix doc build warning. 2008-07-19 Behdad Esfahbod diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt index 458917d..1232b4e 100644 --- a/docs/pango-sections.txt +++ b/docs/pango-sections.txt @@ -647,6 +647,7 @@ PangoRendererClass pango_renderer_draw_layout pango_renderer_draw_layout_line pango_renderer_draw_glyphs +pango_renderer_draw_glyph_item pango_renderer_draw_rectangle pango_renderer_draw_error_underline pango_renderer_draw_trapezoid @@ -851,6 +852,7 @@ pango_cairo_update_context pango_cairo_create_layout pango_cairo_update_layout pango_cairo_show_glyph_string +pango_cairo_show_glyph_item pango_cairo_show_layout_line pango_cairo_show_layout pango_cairo_show_error_underline diff --git a/docs/tmpl/pango-renderer.sgml b/docs/tmpl/pango-renderer.sgml index c265271..6f2e838 100644 --- a/docs/tmpl/pango-renderer.sgml +++ b/docs/tmpl/pango-renderer.sgml @@ -60,6 +60,7 @@ The #GObject type for #PangoRenderPart. @begin: @end: @prepare_run: +@draw_glyph_item: @@ -95,6 +96,18 @@ The #GObject type for #PangoRenderPart. @y: + + + + + +@renderer: +@text: +@glyph_item: +@x: +@y: + + diff --git a/docs/tmpl/pangocairo.sgml b/docs/tmpl/pangocairo.sgml index edc8b52..24a2461 100644 --- a/docs/tmpl/pangocairo.sgml +++ b/docs/tmpl/pangocairo.sgml @@ -354,6 +354,16 @@ with Pango's Cairo renderer. @glyphs: + + + + + +@cr: +@text: +@glyph_item: + + diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c index a5f5368..9febedd 100644 --- a/pango/pango-renderer.c +++ b/pango/pango-renderer.c @@ -64,6 +64,11 @@ static void pango_renderer_default_draw_glyphs (PangoRenderer *rende PangoGlyphString *glyphs, int x, int y); +static void pango_renderer_default_draw_glyph_item (PangoRenderer *renderer, + const char *text, + PangoGlyphItem *glyph_item, + int x, + int y); static void pango_renderer_default_draw_rectangle (PangoRenderer *renderer, PangoRenderPart part, int x, @@ -107,6 +112,7 @@ pango_renderer_class_init (PangoRendererClass *klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); klass->draw_glyphs = pango_renderer_default_draw_glyphs; + klass->draw_glyph_item = pango_renderer_default_draw_glyph_item; klass->draw_rectangle = pango_renderer_default_draw_rectangle; klass->draw_error_underline = pango_renderer_default_draw_error_underline; klass->prepare_run = pango_renderer_default_prepare_run; @@ -455,6 +461,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer, GSList *l; gboolean got_overall = FALSE; PangoRectangle overall_rect; + const char *text; g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer)); @@ -476,6 +483,8 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer, state.underline = PANGO_UNDERLINE_NONE; state.strikethrough = FALSE; + text = pango_layout_get_text (line->layout); + for (l = line->runs; l; l = l->next) { PangoFontMetrics *metrics; @@ -556,9 +565,10 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer, } else { - pango_renderer_draw_glyphs (renderer, - run->item->analysis.font, run->glyphs, - x + x_off, y - rise); + pango_renderer_draw_glyph_item (renderer, + text, + run, + x + x_off, y - rise); } if (renderer->underline != PANGO_UNDERLINE_NONE || @@ -658,6 +668,57 @@ pango_renderer_default_draw_glyphs (PangoRenderer *renderer, } /** + * pango_renderer_draw_glyph_item: + * @renderer: a #PangoRenderer + * @text: the UTF-8 text that @glyph_item refers to + * @glyph_item: a #PangoGlyphItem + * @x: X position of left edge of baseline, in user space coordinates + * in Pango units. + * @y: Y position of left edge of baseline, in user space coordinates + * in Pango units. + * + * Draws the glyphs in @glyph_item with the specified #PangoRenderer, + * embedding the text associated with the glyphs in the output if the + * output format supports it (PDF for example). + * + * Note that @text is the start of the text for layout, which is then + * indexed by glyph_item->item->offset. + * + * The default implementation of this method simply falls back to + * pango_renderer_draw_glyphs(). + * + * Since: 1.22 + **/ +void +pango_renderer_draw_glyph_item (PangoRenderer *renderer, + const char *text, + PangoGlyphItem *glyph_item, + int x, + int y) +{ + g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer)); + + pango_renderer_activate (renderer); + + PANGO_RENDERER_GET_CLASS (renderer)->draw_glyph_item (renderer, text, glyph_item, x, y); + + pango_renderer_deactivate (renderer); +} + +static void +pango_renderer_default_draw_glyph_item (PangoRenderer *renderer, + const char *text, + PangoGlyphItem *glyph_item, + int x, + int y) +{ + pango_renderer_draw_glyphs (renderer, + glyph_item->item->analysis.font, + glyph_item->glyphs, + x, y); +} + +/** * pango_renderer_draw_rectangle: * @renderer: a #PangoRenderer * @part: type of object this rectangle is part of diff --git a/pango/pango-renderer.h b/pango/pango-renderer.h index 89c45fa..354127b 100644 --- a/pango/pango-renderer.h +++ b/pango/pango-renderer.h @@ -101,6 +101,7 @@ struct _PangoRenderer * @begin: Do renderer-specific initialization before drawing * @end: Do renderer-specific cleanup after drawing * @prepare_run: updates the renderer for a new run + * @draw_glyph_item: draws a #PangoGlyphItem * * Class structure for #PangoRenderer. * @@ -172,10 +173,18 @@ struct _PangoRendererClass void (*prepare_run) (PangoRenderer *renderer, PangoLayoutRun *run); + /* All of the following have default implementations + * and take as coordinates user coordinates in Pango units + */ + void (*draw_glyph_item) (PangoRenderer *renderer, + const char *text, + PangoGlyphItem *glyph_item, + int x, + int y); + /*< private >*/ /* Padding for future expansion */ - void (*_pango_reserved1) (void); void (*_pango_reserved2) (void); void (*_pango_reserved3) (void); void (*_pango_reserved4) (void); @@ -196,6 +205,11 @@ void pango_renderer_draw_glyphs (PangoRenderer *renderer, PangoGlyphString *glyphs, int x, int y); +void pango_renderer_draw_glyph_item (PangoRenderer *renderer, + const char *text, + PangoGlyphItem *glyph_item, + int x, + int y); void pango_renderer_draw_rectangle (PangoRenderer *renderer, PangoRenderPart part, int x, diff --git a/pango/pango.def b/pango/pango.def index 89fae6c..8823b2e 100644 --- a/pango/pango.def +++ b/pango/pango.def @@ -329,6 +329,7 @@ EXPORTS pango_renderer_deactivate pango_renderer_draw_error_underline pango_renderer_draw_glyph + pango_renderer_draw_glyph_item pango_renderer_draw_glyphs pango_renderer_draw_layout pango_renderer_draw_layout_line diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c index ea100b0..1fd7dbc 100644 --- a/pango/pangocairo-render.c +++ b/pango/pangocairo-render.c @@ -37,6 +37,7 @@ struct _PangoCairoRenderer cairo_t *cr; gboolean do_path; + gboolean has_show_text_glyphs; double x_offset, y_offset; /* house-keeping options */ @@ -270,6 +271,9 @@ done: cairo_restore (crenderer->cr); } +/* cairo_glyph_t is 24 bytes */ +#define MAX_STACK 40 + static void pango_cairo_renderer_draw_glyphs (PangoRenderer *renderer, PangoFont *font, @@ -279,9 +283,6 @@ pango_cairo_renderer_draw_glyphs (PangoRenderer *renderer, { PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer); - /* cairo_glyph_t is 24 bytes */ -#define MAX_STACK 40 - int i, count; int x_position = 0; cairo_glyph_t *cairo_glyphs; @@ -354,10 +355,103 @@ pango_cairo_renderer_draw_glyphs (PangoRenderer *renderer, done: cairo_restore (crenderer->cr); +} -#undef MAX_STACK +static void +pango_cairo_renderer_draw_glyph_item (PangoRenderer *renderer, + const char *text, + PangoGlyphItem *glyph_item, + int x, + int y) +{ + PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer); + PangoFont *font = glyph_item->item->analysis.font; + PangoGlyphString *glyphs = glyph_item->glyphs; + + int i, count; + int x_position = 0; + cairo_glyph_t *cairo_glyphs; + cairo_glyph_t stack_glyphs[MAX_STACK]; + double base_x = crenderer->x_offset + (double)x / PANGO_SCALE; + double base_y = crenderer->y_offset + (double)y / PANGO_SCALE; + + if (!crenderer->has_show_text_glyphs || crenderer->do_path) + { + pango_cairo_renderer_draw_glyphs (renderer, + glyph_item->item->analysis.font, + glyph_item->glyphs, + x, y); + return; + } + + cairo_save (crenderer->cr); + set_color (crenderer, PANGO_RENDER_PART_FOREGROUND); + + if (!_pango_cairo_font_install (font, crenderer->cr)) + { + for (i = 0; i < glyphs->num_glyphs; i++) + { + PangoGlyphInfo *gi = &glyphs->glyphs[i]; + + if (gi->glyph != PANGO_GLYPH_EMPTY) + { + double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; + double cy = gi->geometry.y_offset == 0 ? + base_y : + base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE; + + /* XXX */ + _pango_cairo_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy); + } + x_position += gi->geometry.width; + } + + goto done; + } + + if (glyphs->num_glyphs > MAX_STACK) + cairo_glyphs = g_new (cairo_glyph_t, glyphs->num_glyphs); + else + cairo_glyphs = stack_glyphs; + + count = 0; + for (i = 0; i < glyphs->num_glyphs; i++) + { + PangoGlyphInfo *gi = &glyphs->glyphs[i]; + + if (gi->glyph != PANGO_GLYPH_EMPTY) + { + double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; + double cy = gi->geometry.y_offset == 0 ? + base_y : + base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE; + + if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG) + /* XXX */ + _pango_cairo_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy); + else + { + cairo_glyphs[count].index = gi->glyph; + cairo_glyphs[count].x = cx; + cairo_glyphs[count].y = cy; + count++; + } + } + x_position += gi->geometry.width; + } + + /* XXX */ + cairo_show_glyphs (crenderer->cr, cairo_glyphs, count); + + if (glyphs->num_glyphs > MAX_STACK) + g_free (cairo_glyphs); + +done: + cairo_restore (crenderer->cr); } +#undef MAX_STACK + static void pango_cairo_renderer_draw_rectangle (PangoRenderer *renderer, PangoRenderPart part, @@ -544,6 +638,7 @@ pango_cairo_renderer_class_init (PangoCairoRendererClass *klass) PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); renderer_class->draw_glyphs = pango_cairo_renderer_draw_glyphs; + renderer_class->draw_glyph_item = pango_cairo_renderer_draw_glyph_item; renderer_class->draw_rectangle = pango_cairo_renderer_draw_rectangle; renderer_class->draw_error_underline = pango_cairo_renderer_draw_error_underline; renderer_class->draw_shape = pango_cairo_renderer_draw_shape; @@ -582,6 +677,7 @@ release_renderer (PangoCairoRenderer *renderer) { renderer->cr = NULL; renderer->do_path = FALSE; + renderer->has_show_text_glyphs = FALSE; renderer->x_offset = 0.; renderer->y_offset = 0.; @@ -596,6 +692,9 @@ save_current_point (PangoCairoRenderer *renderer) { renderer->cr_had_current_point = cairo_has_current_point (renderer->cr); cairo_get_current_point (renderer->cr, &renderer->x_offset, &renderer->y_offset); + + /* abuse save_current_point() to cache cairo_has_show_text_glyphs() result */ + renderer->has_show_text_glyphs = cairo_has_show_text_glyphs (renderer->cr); } static void @@ -652,6 +751,45 @@ _pango_cairo_do_glyph_string (cairo_t *cr, } static void +_pango_cairo_do_glyph_item (cairo_t *cr, + const char *text, + PangoGlyphItem *glyph_item, + gboolean do_path) +{ + PangoCairoRenderer *crenderer = acquire_renderer (); + PangoRenderer *renderer = (PangoRenderer *) crenderer; + + crenderer->cr = cr; + crenderer->do_path = do_path; + save_current_point (crenderer); + + if (!do_path) + { + /* unset all part colors, since when drawing just a glyph string, + * prepare_run() isn't called. + */ + + pango_renderer_activate (renderer); + + pango_renderer_set_color (renderer, PANGO_RENDER_PART_FOREGROUND, NULL); + pango_renderer_set_color (renderer, PANGO_RENDER_PART_BACKGROUND, NULL); + pango_renderer_set_color (renderer, PANGO_RENDER_PART_UNDERLINE, NULL); + pango_renderer_set_color (renderer, PANGO_RENDER_PART_STRIKETHROUGH, NULL); + } + + pango_renderer_draw_glyph_item (renderer, text, glyph_item, 0, 0); + + if (!do_path) + { + pango_renderer_deactivate (renderer); + } + + restore_current_point (crenderer); + + release_renderer (crenderer); +} + +static void _pango_cairo_do_layout_line (cairo_t *cr, PangoLayoutLine *line, gboolean do_path) @@ -739,6 +877,38 @@ pango_cairo_show_glyph_string (cairo_t *cr, _pango_cairo_do_glyph_string (cr, font, glyphs, FALSE); } + +/** + * pango_cairo_show_glyph_item: + * @cr: a Cairo context + * @text: the UTF-8 text that @glyph_item refers to + * @glyph_item: a #PangoGlyphItem + * + * Draws the glyphs in @glyph_item in the specified cairo context, + * embedding the text associated with the glyphs in the output if the + * output format supports it (PDF for example), otherwise it acts + * similar to pango_cairo_show_glyph_string(). + * + * The origin of the glyphs (the left edge of the baseline) will + * be drawn at the current point of the cairo context. + * + * Note that @text is the start of the text for layout, which is then + * indexed by glyph_item->item->offset. + * + * Since: 1.20 + **/ +void +pango_cairo_show_glyph_item (cairo_t *cr, + const char *text, + PangoGlyphItem *glyph_item) +{ + g_return_if_fail (cr != NULL); + g_return_if_fail (text != NULL); + g_return_if_fail (glyph_item != NULL); + + _pango_cairo_do_glyph_item (cr, text, glyph_item, FALSE); +} + /** * pango_cairo_show_layout_line: * @cr: a Cairo context diff --git a/pango/pangocairo.def b/pango/pangocairo.def index 3bceacd..f3052eb 100644 --- a/pango/pangocairo.def +++ b/pango/pangocairo.def @@ -26,6 +26,7 @@ EXPORTS pango_cairo_layout_path pango_cairo_renderer_get_type pango_cairo_show_error_underline + pango_cairo_show_glyph_item pango_cairo_show_glyph_string pango_cairo_show_layout pango_cairo_show_layout_line diff --git a/pango/pangocairo.h b/pango/pangocairo.h index b9191cd..f11bf65 100644 --- a/pango/pangocairo.h +++ b/pango/pangocairo.h @@ -116,6 +116,9 @@ void pango_cairo_update_layout (cairo_t *cr, void pango_cairo_show_glyph_string (cairo_t *cr, PangoFont *font, PangoGlyphString *glyphs); +void pango_cairo_show_glyph_item (cairo_t *cr, + const char *text, + PangoGlyphItem *glyph_item); void pango_cairo_show_layout_line (cairo_t *cr, PangoLayoutLine *line); void pango_cairo_show_layout (cairo_t *cr, -- 2.7.4