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) */