Bug 3927

Summary: Bogus metrics reported for glyph not available
Product: cairo Reporter: Hans Breuer <hans>
Component: win32 backendAssignee: Owen Taylor <otaylor>
Status: RESOLVED FIXED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: high CC: jwatt, tml
Version: 1.0.0   
Hardware: x86 (IA32)   
OS: Windows (All)   
Whiteboard:
i915 platform: i915 features:

Description Hans Breuer 2005-07-31 05:36:38 UTC
testgtk::labels and other pango layouts are broken due to this issue.
The patch below registers the failing of GetGlyphOutlineW() but does
not report the failing status back through the API. Instead it 
initializes the returned sizes to zero. 
This is consitent with other status handling in
_cairo_win32_scaled_font_glyph_extents() and fixes the issue for me.
But maybe the whole function should be changed to return back
failed status ...

diff --exclude-from=c:\util\tool\diff.ign -u --recursive
from-cvs/cairo/cairo/src/cairo-win32-font.c
my-gtk/cairo/cairo/src/cairo-win32-font.c
--- from-cvs/cairo/cairo/src/cairo-win32-font.c	Thu Jul 28 22:24:57 2005
+++ my-gtk/cairo/cairo/src/cairo-win32-font.c	Sat Jul 30 20:30:05 2005
@@ -722,8 +722,11 @@
 	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
 	if (status)
 	    return status;
-	GetGlyphOutlineW (hdc, glyphs[0].index, GGO_METRICS | GGO_GLYPH_INDEX,
-			  &metrics, 0, NULL, &matrix);
+	if (GetGlyphOutlineW (hdc, glyphs[0].index, GGO_METRICS | GGO_GLYPH_INDEX,
+			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {
+	    status = _cairo_win32_print_gdi_error ("GetGlyphOutlineW");
+	    memset (&metrics, 0, sizeof(GLYPHMETRICS));
+	}
 	cairo_win32_scaled_font_done_font (&scaled_font->base);
 
 	if (scaled_font->swap_axes) {
@@ -757,8 +760,11 @@
 	 * of the font.
 	 */
 	status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
-	GetGlyphOutlineW (hdc, glyphs[0].index, GGO_METRICS | GGO_GLYPH_INDEX,
-			  &metrics, 0, NULL, &matrix);
+	if (GetGlyphOutlineW (hdc, glyphs[0].index, GGO_METRICS | GGO_GLYPH_INDEX,
+			  &metrics, 0, NULL, &matrix) == GDI_ERROR) {
+	    status = _cairo_win32_print_gdi_error ("GetGlyphOutlineW");
+	    memset (&metrics, 0, sizeof(GLYPHMETRICS));
+	}
 	_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
 
 	extents->x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square;
Comment 1 Owen Taylor 2005-07-31 05:42:20 UTC
Leaving aside the fix (which is likely right), why are not-available glyphs
being passed to this function? Does that need debugging?
Comment 2 Hans Breuer 2005-07-31 05:54:27 UTC
There may be a bug in Pango causing this, but I'm definitely not the expert.
But I think is quite usual for Pango to ask for not existing glyphs - and
finally render them as boxes. 
Comment 3 Owen Taylor 2005-07-31 06:14:30 UTC
No, that should never happen. Pango always is using glyph IDs that
it got from Uniscribe or by querying the Win32 API.
Comment 4 Hans Breuer 2005-07-31 06:40:08 UTC
So there is a bug in basic_engine_shape ?
The GDI_ERROR seems to be triggered by measuring the extents
for pango_win32_get_unknown_glyph ().


_cairo_win32_scaled_font_glyph_extents(void * 0x00d61a20, cairo_glyph_t *
0x0012c490, int 1, cairo_text_extents_t * 0x0012c460) line 727
_cairo_scaled_font_glyph_extents(_cairo_scaled_font * 0x00d61a20, cairo_glyph_t
* 0x0012c490, int 1, cairo_text_extents_t * 0x0012c460) line 900 + 25 bytes
cairo_scaled_font_glyph_extents(_cairo_scaled_font * 0x00d61a20, cairo_glyph_t *
0x0012c51c, int 1, cairo_text_extents_t * 0x0012c4e8) line 1188
pango_cairo_win32_font_get_glyph_extents(_PangoFont * 0x00d60170, unsigned int
268490076, _PangoRectangle * 0x00000000, _PangoRectangle * 0x0012c564) line 187
+ 19 bytes
pango_font_get_glyph_extents(_PangoFont * 0x00d60170, unsigned int 268490076,
_PangoRectangle * 0x00000000, _PangoRectangle * 0x0012c564) line 1190 + 24 bytes
set_glyph(_PangoFont * 0x00d60170, _PangoGlyphString * 0x00d5faf0, int 0, int 0,
unsigned int 268490076) line 205 + 31 bytes
basic_engine_shape(_PangoEngineShape * 0x00d0bfe0, _PangoFont * 0x00d60170,
const char * 0x00d5e4ea, int 6, _PangoAnalysis * 0x00d6148c, _PangoGlyphString *
0x00d5faf0) line 1039 + 41 bytes
_pango_engine_shape_shape(_PangoEngineShape * 0x00d0bfe0, _PangoFont *
0x00d60170, const char * 0x00d5e4ea, int 6, _PangoAnalysis * 0x00d6148c,
_PangoGlyphString * 0x00d5faf0) line 77 + 32 bytes
pango_shape(const char * 0x00d5e4ea, int 6, _PangoAnalysis * 0x00d6148c,
_PangoGlyphString * 0x00d5faf0) line 48 + 34 bytes
shape_run(_PangoLayoutLine * 0x00d60010, _ParaBreakState * 0x0012c704,
_PangoItem * 0x00d61480) line 2689 + 35 bytes
process_item(_PangoLayout * 0x00d5e460, _PangoLayoutLine * 0x00d60010,
_ParaBreakState * 0x0012c704, int 0, int 0) line 2780 + 17 bytes
process_line(_PangoLayout * 0x00d5e460, _ParaBreakState * 0x0012c704) line 2988
+ 29 bytes
pango_layout_check_lines(_PangoLayout * 0x00d5e460) line 3285 + 13 bytes
pango_layout_get_extents_internal(_PangoLayout * 0x00d5e460, _PangoRectangle *
0x00000000, _PangoRectangle * 0x0012c878, _GSList * * 0x00000000) line 2013 + 9
bytes
pango_layout_get_extents(_PangoLayout * 0x00d5e460, _PangoRectangle *
0x00000000, _PangoRectangle * 0x0012c878) line 2178 + 19 bytes
gtk_label_size_request(_GtkWidget * 0x00cef628, _GtkRequisition * 0x00cef644)
line 2017 + 18 bytes
Comment 5 Carl Worth 2005-08-22 17:14:46 UTC
Move bugs against "cvs" version to "0.9.3" so we can remove the "cvs" version.
Comment 6 Tor Lillqvist 2005-09-26 02:55:33 UTC
pango_win32_get_unknown_glyph() returns the passed-in Unicode character ORed
with PANGO_WIN32_UNKNOWN_FLAG. In 2.6 days, the glyph indexes eventually were
passed to pango_win32_render() which notices this flag and replaces it with
glyph index 0 (which apparently in all TrueType fonts is the invalid glyph?).
cairo does not know about this PANGO_WIN32_UNKNOWN_FLAG so it thinks the glyph
index is a valid one.

As to why invalid glyphs are tried to be rendered in the first place, I don't
know. I could reproduce this problem only after editing the "sans" line in
pango.aliases, setting it to just "sans = arial", so that some of the non-ASCII
labels in testgtk::labels aren't covered. But why isn't it noticed earlier that
the "sans" font doesn't cover the attempted characters, I don't know.
Comment 7 Owen Taylor 2005-09-26 05:06:47 UTC
0 is present in all TrueType fonts - it is typically a box, though in some
cases it can also be blank.

I think the right thing to do is:

 Create a PANGO_UNKNOWN_FLAG in some private header and use it consistently
 across all backends (we have a bunch of UNKNOWN flags now, all with the
 same value)

 Make pangocairo-render.c draw a box itself for anything marked with this
 flag rather than passing it to cairo. (Doing hex boxes in pangocairo-render.c
 is an open work item, but empty boxes are a simple first step.)
 (http://bugzilla.gnome.org/show_bug.cgi?id=313551)

The patch in this bug should be applied, of course.
Comment 8 Tor Lillqvist 2005-09-26 07:51:19 UTC
Patch committed to HEAD. (Does cairo use any separate stable branch?) Should
this bug be kept open until Pango is fixed not to call cairo for undefined glyphs?
Comment 9 Carl Worth 2005-09-26 08:57:52 UTC
(In reply to comment #8)
> Patch committed to HEAD. (Does cairo use any separate stable branch?)

Yes. Things that are strictly bug-fixes, (as this appears to be), should be
committed to the current maintenance branch. The tag you want now is:

   -r BRANCH_1_0

Please commit this fix on that branch as well. Thanks!



Comment 10 Tor Lillqvist 2005-09-26 09:14:18 UTC
Committed to BRANCH_1_0, too. (Without the error message, though, as cairo 1.0.2
presumably will still be most often used with a Pango that causes invalid glyph
indixes to be passed to this function.)
Comment 11 Carl Worth 2005-09-26 10:00:59 UTC
Sounds perfect. Thanks so much!

-Carl
Comment 12 Behdad Esfahbod 2006-06-13 15:06:25 UTC
Pango draws cute hexboxes for all cairo backends now.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.