Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/pango/ChangeLog,v
retrieving revision 1.1283
diff -u -p -r1.1283 ChangeLog
--- ChangeLog	14 Jan 2006 07:00:04 -0000	1.1283
+++ ChangeLog	14 Jan 2006 13:19:42 -0000
@@ -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)
 
Index: pango/pangocairo-atsuifont.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangocairo-atsuifont.c,v
retrieving revision 1.2
diff -u -p -r1.2 pangocairo-atsuifont.c
--- pango/pangocairo-atsuifont.c	14 Jan 2006 07:00:11 -0000	1.2
+++ pango/pangocairo-atsuifont.c	14 Jan 2006 13:19:43 -0000
@@ -70,15 +70,6 @@ pango_cairo_atsui_font_install (PangoCai
   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)
 {
@@ -116,6 +107,17 @@ pango_cairo_atsui_font_get_scaled_font (
   
   return cafont->scaled_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,
Index: pango/pangocairo-fcfont.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangocairo-fcfont.c,v
retrieving revision 1.23
diff -u -p -r1.23 pangocairo-fcfont.c
--- pango/pangocairo-fcfont.c	14 Jan 2006 07:00:11 -0000	1.23
+++ pango/pangocairo-fcfont.c	14 Jan 2006 13:19:43 -0000
@@ -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_
   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 (P
   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      
 	       PangoContext               *context,
 	       const PangoFontDescription *desc,
 	       FcPattern                  *pattern,
-	       PangoMatrix                *matrix)
+	       const PangoMatrix          *matrix)
 {
   double size;
 
Index: pango/pangocairo-font.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangocairo-font.c,v
retrieving revision 1.7
diff -u -p -r1.7 pangocairo-font.c
--- pango/pangocairo-font.c	14 Jan 2006 07:00:11 -0000	1.7
+++ pango/pangocairo-font.c	14 Jan 2006 13:19:43 -0000
@@ -72,3 +72,156 @@ _pango_cairo_font_install (PangoCairoFon
   
   (* 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);
+    }  
+}
+
Index: pango/pangocairo-private.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pangocairo-private.h,v
retrieving revision 1.6
diff -u -p -r1.6 pangocairo-private.h
--- pango/pangocairo-private.h	6 Dec 2005 01:20:46 -0000	1.6
+++ pango/pangocairo-private.h	14 Jan 2006 13:19:45 -0000
@@ -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))
@@ -77,6 +83,25 @@ GType pango_cairo_renderer_get_type    (
 
 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
 
Index: pango/pangocairo-render.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangocairo-render.c,v
retrieving revision 1.11
diff -u -p -r1.11 pangocairo-render.c
--- pango/pangocairo-render.c	14 Jan 2006 07:00:11 -0000	1.11
+++ pango/pangocairo-render.c	14 Jan 2006 13:19:45 -0000
@@ -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 (PangoR
       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;
     }
 
Index: pango/pangocairo-win32font.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangocairo-win32font.c,v
retrieving revision 1.16
diff -u -p -r1.16 pangocairo-win32font.c
--- pango/pangocairo-win32font.c	14 Jan 2006 07:00:11 -0000	1.16
+++ pango/pangocairo-win32font.c	14 Jan 2006 13:19:48 -0000
@@ -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,

