X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/220d91b834f7f7252b9953460422151b86b3520c..cf5fc6dbeac10220394ab201ba3f4402e1e91faf:/src/w32uniscribe.c diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index 6c29e6ee2d..5d160b9d42 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -1,5 +1,5 @@ /* Font backend for the Microsoft W32 Uniscribe API. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -27,7 +27,6 @@ along with GNU Emacs. If not, see . */ #define _WIN32_WINNT 0x500 #include #include -#include #include "lisp.h" #include "w32term.h" @@ -52,10 +51,6 @@ int uniscribe_available = 0; extern Lisp_Object Quniscribe; extern Lisp_Object Qopentype; -extern int initialized; - -extern struct font_driver uniscribe_font_driver; - /* EnumFontFamiliesEx callback. */ static int CALLBACK add_opentype_font_name_to_list (ENUMLOGFONTEX *, NEWTEXTMETRICEX *, @@ -235,7 +230,7 @@ uniscribe_shape (Lisp_Object lgstring) /* First we need to break up the glyph string into runs of glyphs that can be treated together. First try a single run. */ max_items = 2; - items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1); + items = xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1); while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL, items, &nitems)) == E_OUTOFMEMORY) @@ -324,7 +319,7 @@ uniscribe_shape (Lisp_Object lgstring) } if (SUCCEEDED (result)) { - int j, nclusters, from, to; + int j, from, to, adj_offset = 0; from = 0; to = from; @@ -368,6 +363,32 @@ uniscribe_shape (Lisp_Object lgstring) } } } + + /* For RTL text, the Uniscribe shaper prepares + the values in ADVANCES array for layout in + reverse order, whereby "advance width" is + applied to move the pen in reverse direction + and _before_ drawing the glyph. Since we + draw glyphs in their normal left-to-right + order, we need to adjust the coordinates of + each non-base glyph in a grapheme cluster via + X-OFF component of the gstring's ADJUSTMENT + sub-vector. This loop computes, for each + grapheme cluster, the initial value of the + adjustment for the base character, which is + then updated for each successive glyph in the + grapheme cluster. */ + if (items[i].a.fRTL) + { + int j1 = j; + + adj_offset = 0; + while (j1 < nglyphs && !attributes[j1].fClusterStart) + { + adj_offset += advances[j1]; + j1++; + } + } } LGLYPH_SET_CHAR (lglyph, chars[items[i].iCharPos @@ -396,9 +417,11 @@ uniscribe_shape (Lisp_Object lgstring) if (SUCCEEDED (result)) { - LGLYPH_SET_LBEARING (lglyph, char_metric.abcA); - LGLYPH_SET_RBEARING (lglyph, (char_metric.abcA - + char_metric.abcB)); + int lbearing = char_metric.abcA; + int rbearing = char_metric.abcA + char_metric.abcB; + + LGLYPH_SET_LBEARING (lglyph, lbearing); + LGLYPH_SET_RBEARING (lglyph, rbearing); } else { @@ -406,18 +429,47 @@ uniscribe_shape (Lisp_Object lgstring) LGLYPH_SET_RBEARING (lglyph, advances[j]); } - if (offsets[j].du || offsets[j].dv) + if (offsets[j].du || offsets[j].dv + /* For non-base glyphs of RTL grapheme clusters, + adjust the X offset even if both DU and DV + are zero. */ + || (!attributes[j].fClusterStart && items[i].a.fRTL)) { Lisp_Object vec; vec = Fmake_vector (make_number (3), Qnil); - ASET (vec, 0, make_number (offsets[j].du)); - ASET (vec, 1, make_number (offsets[j].dv)); + if (items[i].a.fRTL) + { + /* Empirically, it looks like Uniscribe + interprets DU in reverse direction for + RTL clusters. E.g., if we don't reverse + the direction, the Hebrew point HOLAM is + drawn above the right edge of the base + consonant, instead of above the left edge. */ + ASET (vec, 0, make_number (-offsets[j].du + + adj_offset)); + /* Update the adjustment value for the width + advance of the glyph we just emitted. */ + adj_offset -= 2 * advances[j]; + } + else + ASET (vec, 0, make_number (offsets[j].du + adj_offset)); + /* In the font definition coordinate system, the + Y coordinate points up, while in our screen + coordinates Y grows downwards. So we need to + reverse the sign of Y-OFFSET here. */ + ASET (vec, 1, make_number (-offsets[j].dv)); /* Based on what ftfont.c does... */ ASET (vec, 2, make_number (advances[j])); LGLYPH_SET_ADJUSTMENT (lglyph, vec); } else - LGLYPH_SET_ADJUSTMENT (lglyph, Qnil); + { + LGLYPH_SET_ADJUSTMENT (lglyph, Qnil); + /* Update the adjustment value to compensate for + the width of the base character. */ + if (items[i].a.fRTL) + adj_offset -= advances[j]; + } } } } @@ -473,7 +525,7 @@ uniscribe_encode_char (struct font *font, int c) /* Non BMP characters must be handled by the uniscribe shaping engine as GDI functions (except blindly displaying lines of - unicode text) and the promising looking ScriptGetCMap do not + Unicode text) and the promising looking ScriptGetCMap do not convert surrogate pairs to glyph indexes correctly. */ { items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1); @@ -511,7 +563,7 @@ uniscribe_encode_char (struct font *font, int c) if (SUCCEEDED (result) && nglyphs == 1) { /* Some fonts return .notdef glyphs instead of failing. - (Truetype spec reserves glyph code 0 for .notdef) */ + (TrueType spec reserves glyph code 0 for .notdef) */ if (glyphs[0]) code = glyphs[0]; } @@ -585,7 +637,7 @@ add_opentype_font_name_to_list (ENUMLOGFONTEX *logical_font, && font_type != TRUETYPE_FONTTYPE) return 1; - /* Skip fonts that have no unicode coverage. */ + /* Skip fonts that have no Unicode coverage. */ if (!physical_font->ntmFontSig.fsUsb[3] && !physical_font->ntmFontSig.fsUsb[2] && !physical_font->ntmFontSig.fsUsb[1] @@ -633,8 +685,6 @@ add_opentype_font_name_to_list (ENUMLOGFONTEX *logical_font, STR[4] = '\0'; \ } while (0) -static char* NOTHING = " "; - #define SNAME(VAL) SDATA (SYMBOL_NAME (VAL)) /* Check if font supports the otf script/language/features specified. @@ -650,7 +700,6 @@ uniscribe_check_otf (LOGFONT *font, Lisp_Object otf_spec) struct frame * f; HDC context; HFONT check_font, old_font; - DWORD table; int i, retval = 0; struct gcpro gcpro1; @@ -940,7 +989,11 @@ struct font_driver uniscribe_font_driver = NULL, /* otf_drive - use shape instead. */ NULL, /* start_for_frame */ NULL, /* end_for_frame */ - uniscribe_shape + uniscribe_shape, + NULL, /* check */ + NULL, /* get_variation_glyphs */ + NULL, /* filter_properties */ + NULL, /* cached_font_ok */ }; /* Note that this should be called at every startup, not just when dumping, @@ -964,6 +1017,3 @@ syms_of_w32uniscribe (void) register_font_driver (&uniscribe_font_driver, NULL); } - -/* arch-tag: 9530f0e1-7471-47dd-a780-94330af87ea0 - (do not change this comment) */