X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/b6bd159922608fa474026837771d63bf7eadcf97..6c6f1994bf684f510d600bd18023fa01b4b06500:/src/w32uniscribe.c diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index f6347bb88f..c153c8f356 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -1,5 +1,5 @@ /* Font backend for the Microsoft W32 Uniscribe API. - Copyright (C) 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2008-2013 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" @@ -231,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) @@ -320,7 +319,7 @@ uniscribe_shape (Lisp_Object lgstring) } if (SUCCEEDED (result)) { - int j, from, to; + int j, from, to, adj_offset = 0; from = 0; to = from; @@ -334,7 +333,7 @@ uniscribe_shape (Lisp_Object lgstring) if (NILP (lglyph)) { - lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil); + lglyph = LGLYPH_NEW (); LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph); } /* Copy to a 32-bit data type to shut up the @@ -364,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 @@ -392,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 { @@ -402,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)); + Lisp_Object vec = make_uninit_vector (3); + + 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]; + } } } } @@ -469,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); @@ -507,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]; } @@ -581,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] @@ -961,4 +1017,3 @@ syms_of_w32uniscribe (void) register_font_driver (&uniscribe_font_driver, NULL); } -