diff options
-rw-r--r-- | ChangeLog | 29 | ||||
-rw-r--r-- | pango/pangocairo-atsuifont.c | 20 | ||||
-rw-r--r-- | pango/pangocairo-fcfont.c | 15 | ||||
-rw-r--r-- | pango/pangocairo-font.c | 153 | ||||
-rw-r--r-- | pango/pangocairo-private.h | 25 | ||||
-rw-r--r-- | pango/pangocairo-render.c | 109 | ||||
-rw-r--r-- | pango/pangocairo-win32font.c | 2 |
7 files changed, 309 insertions, 44 deletions
@@ -1,5 +1,34 @@ 2006-01-14 Behdad Esfahbod <behdad@gnome.org> + Draw hexbox for cairo backend. Bug #313551. Based on patch by + LingNing Zhang. + + * pango/pangocairo-private.h (_PangoCairoFontIface): Add new methods: + get_font_face and get_scaled_font, and getters: + _pango_cairo_font_get_font_face, _pango_cairo_font_get_scaled_font. + + * pango/pangocairo-private.h: Add _PangoCairoHexBoxInfo, and getter + _pango_cairo_get_hex_box_info, and + _pango_cairo_get_glyph_extents_missing. + + * pango/pangocairo-fcfont.c, pango/pangocairo-atsuifont.c, + * pango/pangocairo-win32font.c: Export get_font_face and + get_scaled_font methods. + + * pango/pangocairo-fcfont.c: Use _pango_cairo_get_glyph_extents_missing + on missing glyphs. + + * pango/pangocairo-font.c: Implement _pango_cairo_font_get_font_face, + _pango_cairo_font_get_scaled_font, _pango_cairo_get_hex_box_info, and + _pango_cairo_get_glyph_extents_missing. + + * pango/pangocairo-render.c (_pango_cairo_renderer_draw_unknown_glyph): + Added. + * pango/pangocairo-render.c (pango_cairo_renderer_draw_glyphs): + Cleaned up to use the added function above. + +2006-01-14 Behdad Esfahbod <behdad@gnome.org> + * */*.c, */*/*.c: Make sure #include <config.h> is the first include in the file. (bug #158870, based on patch by Luis Menina) diff --git a/pango/pangocairo-atsuifont.c b/pango/pangocairo-atsuifont.c index 016e68bb..81a9bac5 100644 --- a/pango/pangocairo-atsuifont.c +++ b/pango/pangocairo-atsuifont.c @@ -70,15 +70,6 @@ pango_cairo_atsui_font_install (PangoCairoFont *font, cairo_set_font_options (cr, cwfont->options); } -static void -cairo_font_iface_init (PangoCairoFontIface *iface) -{ - iface->install = pango_cairo_atsui_font_install; -} - -G_DEFINE_TYPE_WITH_CODE (PangoCairoATSUIFont, pango_cairo_atsui_font, PANGO_TYPE_ATSUI_FONT, - { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) }); - static cairo_font_face_t * pango_cairo_atsui_font_get_font_face (PangoCairoFont *font) { @@ -118,6 +109,17 @@ pango_cairo_atsui_font_get_scaled_font (PangoCairoFont *font) } static void +cairo_font_iface_init (PangoCairoFontIface *iface) +{ + iface->install = pango_cairo_atsui_font_install; + iface->get_font_face = pango_cairo_atsui_font_get_font_face; + iface->get_scaled_font = pango_cairo_atsui_font_get_scaled_font; +} + +G_DEFINE_TYPE_WITH_CODE (PangoCairoATSUIFont, pango_cairo_atsui_font, PANGO_TYPE_ATSUI_FONT, + { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) }); + +static void pango_cairo_atsui_font_get_glyph_extents (PangoFont *font, PangoGlyph glyph, PangoRectangle *ink_rect, diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c index 5913ca91..e5a8b194 100644 --- a/pango/pangocairo-fcfont.c +++ b/pango/pangocairo-fcfont.c @@ -189,6 +189,8 @@ static void cairo_font_iface_init (PangoCairoFontIface *iface) { iface->install = pango_cairo_fc_font_install; + iface->get_font_face = pango_cairo_fc_font_get_font_face; + iface->get_scaled_font = pango_cairo_fc_font_get_scaled_font; } G_DEFINE_TYPE_WITH_CODE (PangoCairoFcFont, pango_cairo_fc_font, PANGO_TYPE_FC_FONT, @@ -363,8 +365,7 @@ pango_cairo_fc_font_glyph_extents_cache_init (PangoCairoFcFont *cffont) cffont->font_extents.x = 0; cffont->font_extents.y = - font_extents.ascent * PANGO_SCALE; cffont->font_extents.height = (font_extents.ascent + font_extents.descent) * PANGO_SCALE; - /* The width is only used for the width of box drawn for glyph-not-found */ - cffont->font_extents.width = (font_extents.ascent - font_extents.descent) * PANGO_SCALE; + cffont->font_extents.width = 0; cffont->glyph_extents_cache = g_new0 (GlyphExtentsCacheEntry, GLYPH_CACHE_NUM_ENTRIES); /* Make sure all cache entries are invalid initially */ @@ -445,8 +446,12 @@ pango_cairo_fc_font_get_glyph_extents (PangoFont *font, if (cffont->glyph_extents_cache == NULL) pango_cairo_fc_font_glyph_extents_cache_init (cffont); - - if (!glyph || glyph & PANGO_CAIRO_UNKNOWN_FLAG) + if (glyph & PANGO_CAIRO_UNKNOWN_FLAG) + { + _pango_cairo_get_glyph_extents_missing((PangoCairoFont *)font, glyph, ink_rect, logical_rect); + return; + } + else if (!glyph) { if (ink_rect) *ink_rect = cffont->font_extents; @@ -537,7 +542,7 @@ get_font_size (PangoCairoFcFontMap *cffontmap, PangoContext *context, const PangoFontDescription *desc, FcPattern *pattern, - PangoMatrix *matrix) + const PangoMatrix *matrix) { double size; diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c index 259b45d9..37c7834f 100644 --- a/pango/pangocairo-font.c +++ b/pango/pangocairo-font.c @@ -72,3 +72,156 @@ _pango_cairo_font_install (PangoCairoFont *font, (* PANGO_CAIRO_FONT_GET_IFACE (font)->install) (font, cr); } + +cairo_font_face_t * +_pango_cairo_font_get_font_face (PangoCairoFont *font) +{ + g_return_val_if_fail (PANGO_IS_CAIRO_FONT (font), NULL); + + return (* PANGO_CAIRO_FONT_GET_IFACE (font)->get_font_face) (font); +} + +cairo_scaled_font_t * +_pango_cairo_font_get_scaled_font (PangoCairoFont *font) +{ + g_return_val_if_fail (PANGO_IS_CAIRO_FONT (font), NULL); + + return (* PANGO_CAIRO_FONT_GET_IFACE (font)->get_scaled_font) (font); +} + +static void +_pango_cairo_hex_box_info_destroy (PangoCairoHexBoxInfo *hbi) +{ + if (hbi) + { + g_object_unref (hbi->font); + g_slice_free (PangoCairoHexBoxInfo, hbi); + } +} + +PangoCairoHexBoxInfo * +_pango_cairo_get_hex_box_info (PangoCairoFont *cfont) +{ + static const char hexdigits[] = "0123456789ABCDEF"; + char c[2] = {0, 0}; + PangoFont *mini_font; + PangoCairoFont *mini_cfont; + PangoCairoHexBoxInfo *hbi; + int i; + double width = 0; + double height = 0; + cairo_font_extents_t font_extents; + PangoFontDescription *mini_desc, *desc; + cairo_scaled_font_t *scaled_font, *scaled_mini_font; + cairo_surface_t *surface; + cairo_t *cr; + + hbi = (PangoCairoHexBoxInfo *) g_object_get_data (G_OBJECT (cfont), "hex_box_info"); + if (hbi) + return hbi; + + + mini_desc = pango_font_description_new (); + desc = pango_font_describe ((PangoFont *)cfont); + + pango_font_description_set_family_static (mini_desc, "mono-space"); + + /* set size on mini_desc */ + { + int new_size; + new_size = pango_font_description_get_size (desc) / 2.4 + .9; + + if (pango_font_description_get_size_is_absolute (desc)) + pango_font_description_set_absolute_size (mini_desc, new_size); + else + pango_font_description_set_size (mini_desc, new_size); + } + + pango_font_description_free (desc); + + /* load mini_font */ + { + PangoContext *context; + PangoFontMap *fontmap; + + fontmap = pango_font_get_font_map ((PangoFont *)cfont); + g_assert (fontmap); + context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap)); + + pango_context_set_language (context, pango_language_from_string ("en")); + mini_font = pango_font_map_load_font (fontmap, context, mini_desc); + + g_object_unref (context); + g_object_unref (fontmap); + } + + pango_font_description_free (mini_desc); + + mini_cfont = (PangoCairoFont *) mini_font; + scaled_font = _pango_cairo_font_get_scaled_font (cfont); + scaled_mini_font = _pango_cairo_font_get_scaled_font (mini_cfont); + + surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 0, 0); + cr = cairo_create (surface); + _pango_cairo_font_install (mini_cfont, cr); + cairo_surface_destroy (surface); + + for (i = 0 ; i < 16 ; i++) + { + cairo_text_extents_t extents; + + c[0] = hexdigits[i]; + cairo_text_extents (cr, c, &extents); + width = MAX (width, extents.width); + height = MAX (height, extents.height); + } + + cairo_destroy (cr); + cairo_scaled_font_extents (scaled_font, &font_extents); + + hbi = g_slice_new (PangoCairoHexBoxInfo); + hbi->font = mini_font; + + hbi->digit_width = width; + hbi->digit_height = height; + + hbi->pad = hbi->digit_height / 8; + + hbi->box_height = 5 * hbi->pad + 2 * hbi->digit_height; + hbi->box_descent = font_extents.descent - + (font_extents.ascent + font_extents.descent - hbi->box_height) / 2; + + g_object_set_data_full (G_OBJECT (cfont), "hex_box_info", hbi, (GDestroyNotify)_pango_cairo_hex_box_info_destroy); + + return hbi; +} + +void +_pango_cairo_get_glyph_extents_missing (PangoCairoFont *cfont, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + PangoCairoHexBoxInfo *hbi; + gint cols; + + cols = (glyph & ~PANGO_CAIRO_UNKNOWN_FLAG) > 0xffff ? 3 : 2; + hbi = _pango_cairo_get_hex_box_info (cfont); + + if (ink_rect) + { + ink_rect->x = PANGO_SCALE * hbi->pad; + ink_rect->y = PANGO_SCALE * (hbi->box_descent - hbi->box_height); + ink_rect->width = PANGO_SCALE * (3 * hbi->pad + cols * (hbi->digit_width + hbi->pad)); + ink_rect->height = PANGO_SCALE * hbi->box_height; + } + + if (logical_rect) + { + logical_rect->x = 0; + logical_rect->y = PANGO_SCALE * (hbi->box_descent - (hbi->box_height + hbi->pad)); + logical_rect->width = PANGO_SCALE * (5 * hbi->pad + cols * (hbi->digit_width + hbi->pad)); + logical_rect->height = PANGO_SCALE * (hbi->box_height + 2 * hbi->pad); + } +} + diff --git a/pango/pangocairo-private.h b/pango/pangocairo-private.h index 75be37ec..290c761c 100644 --- a/pango/pangocairo-private.h +++ b/pango/pangocairo-private.h @@ -60,12 +60,18 @@ struct _PangoCairoFontIface void (*install) (PangoCairoFont *font, cairo_t *cr); + + cairo_font_face_t *(*get_font_face) (PangoCairoFont *font); + + cairo_scaled_font_t *(*get_scaled_font) (PangoCairoFont *font); }; GType pango_cairo_font_get_type (void); void _pango_cairo_font_install (PangoCairoFont *font, cairo_t *cr); +cairo_font_face_t *_pango_cairo_font_get_font_face (PangoCairoFont *font); +cairo_scaled_font_t *_pango_cairo_font_get_scaled_font (PangoCairoFont *font); #define PANGO_TYPE_CAIRO_RENDERER (pango_cairo_renderer_get_type()) #define PANGO_CAIRO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRenderer)) @@ -78,6 +84,25 @@ GType pango_cairo_renderer_get_type (void); const cairo_font_options_t *_pango_cairo_context_get_merged_font_options (PangoContext *context); +typedef struct _PangoCairoHexBoxInfo PangoCairoHexBoxInfo; + +struct _PangoCairoHexBoxInfo +{ + PangoFont *font; + double digit_width; + double digit_height; + double pad; + double box_descent; + double box_height; +}; + +PangoCairoHexBoxInfo *_pango_cairo_get_hex_box_info (PangoCairoFont *font); + +void _pango_cairo_get_glyph_extents_missing (PangoCairoFont *cfont, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + G_END_DECLS #endif /* __PANGOCAIRO_PRIVATE_H__ */ diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c index 48b7ab78..4abed6f8 100644 --- a/pango/pangocairo-render.c +++ b/pango/pangocairo-render.c @@ -57,6 +57,71 @@ set_color (PangoCairoRenderer *crenderer, color->green / 65535., color->blue / 65535.); } + +static void +_pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer, + PangoFont *font, + PangoGlyphInfo *gi, + double cx, + double cy) +{ + char buf[7]; + double ys[2]; + double xs[3]; + int row, col; + int cols; + char hexbox_string[2] = {0, 0}; + double temp_x, temp_y; + PangoCairoHexBoxInfo *hbi; + gunichar ch; + + hbi = _pango_cairo_get_hex_box_info ((PangoCairoFont *)font); + + ch = gi->glyph & ~PANGO_CAIRO_UNKNOWN_FLAG; + + cols = ch > 0xffff ? 3 : 2; + g_snprintf (buf, sizeof(buf), cols == 2 ? "%04X" : "%06X", ch); + + ys[1] = cy + hbi->box_descent - hbi->pad * 2; + ys[0] = ys[1] - hbi->digit_height - hbi->pad; + + xs[0] = cx + hbi->pad * 3.0; + xs[1] = xs[0] + hbi->digit_width + hbi->pad; + xs[2] = xs[1] + hbi->digit_width + hbi->pad; + + cairo_save (crenderer->cr); + cairo_get_current_point (crenderer->cr, &temp_x, &temp_y); + + cairo_rectangle (crenderer->cr, + cx + hbi->pad * 1.5, + cy + hbi->box_descent - hbi->pad * 0.5, + (double)gi->geometry.width / PANGO_SCALE - 3 * hbi->pad, + -(hbi->box_height - hbi->pad)); + + if (!crenderer->do_path) + { + cairo_save (crenderer->cr); + cairo_set_line_width (crenderer->cr, hbi->pad); + cairo_stroke (crenderer->cr); + cairo_restore (crenderer->cr); + } + + _pango_cairo_font_install (PANGO_CAIRO_FONT (hbi->font), crenderer->cr); + for (row = 0; row < 2; row++) + for (col = 0; col < cols; col++) + { + hexbox_string[0] = buf[row * cols + col]; + cairo_move_to (crenderer->cr, xs[col], ys[row]); + + if (crenderer->do_path) + cairo_text_path (crenderer->cr, hexbox_string); + else + cairo_show_text (crenderer->cr, hexbox_string); + } + + cairo_move_to (crenderer->cr, temp_x, temp_y); + cairo_restore (crenderer->cr); +} static void pango_cairo_renderer_draw_glyphs (PangoRenderer *renderer, @@ -93,36 +158,20 @@ pango_cairo_renderer_draw_glyphs (PangoRenderer *renderer, PangoGlyphInfo *gi = &glyphs->glyphs[i]; if (gi->glyph) - { - if (gi->glyph & PANGO_CAIRO_UNKNOWN_FLAG) - { - int mini_pad = gi->geometry.width / 10; - /* draw an empty dashed box, no hexbox for now */ - cairo_rectangle (crenderer->cr, - crenderer->x_offset + (double)(x + x_position + mini_pad) / PANGO_SCALE, - crenderer->y_offset + (double)(y - mini_pad) / PANGO_SCALE, - (double)(gi->geometry.width - 2 * mini_pad) / PANGO_SCALE, - -(double)(gi->geometry.width - 2 * mini_pad) / PANGO_SCALE); - if (!crenderer->do_path) - { - double dash = (double)mini_pad * 2 / PANGO_SCALE; - cairo_save (crenderer->cr); - cairo_set_line_width (crenderer->cr, (double)mini_pad / PANGO_SCALE); - cairo_set_dash (crenderer->cr, &dash, 1, 0); - cairo_stroke (crenderer->cr); - cairo_restore (crenderer->cr); - } - } - else - { - cairo_glyphs[count].index = gi->glyph; - cairo_glyphs[count].x = crenderer->x_offset + (double)(x + x_position + gi->geometry.x_offset) / PANGO_SCALE; - cairo_glyphs[count].y = crenderer->y_offset + (double)(y + gi->geometry.y_offset) / PANGO_SCALE; - - count++; - } - } - + { + double cx = crenderer->x_offset + (double)(x + x_position + gi->geometry.x_offset) / PANGO_SCALE; + double cy = crenderer->y_offset + (double)(y + gi->geometry.y_offset) / PANGO_SCALE; + + if (gi->glyph & PANGO_CAIRO_UNKNOWN_FLAG) + _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; } diff --git a/pango/pangocairo-win32font.c b/pango/pangocairo-win32font.c index 57bb16e3..1a48ee9b 100644 --- a/pango/pangocairo-win32font.c +++ b/pango/pangocairo-win32font.c @@ -154,6 +154,8 @@ static void cairo_font_iface_init (PangoCairoFontIface *iface) { iface->install = pango_cairo_win32_font_install; + iface->get_font_face = pango_cairo_win32_font_get_font_face; + iface->get_scaled_font = pango_cairo_win32_font_get_scaled_font; } G_DEFINE_TYPE_WITH_CODE (PangoCairoWin32Font, pango_cairo_win32_font, PANGO_TYPE_WIN32_FONT, |