summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog29
-rw-r--r--pango/pangocairo-atsuifont.c20
-rw-r--r--pango/pangocairo-fcfont.c15
-rw-r--r--pango/pangocairo-font.c153
-rw-r--r--pango/pangocairo-private.h25
-rw-r--r--pango/pangocairo-render.c109
-rw-r--r--pango/pangocairo-win32font.c2
7 files changed, 309 insertions, 44 deletions
diff --git a/ChangeLog b/ChangeLog
index 1abbca8a..15d1fd24 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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,