/* Font backend for the Microsoft W32 Uniscribe API.
- Copyright (C) 2008-2011 Free Software Foundation, Inc.
+ Copyright (C) 2008-2012 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#define _WIN32_WINNT 0x500
#include <windows.h>
#include <usp10.h>
-#include <setjmp.h>
#include "lisp.h"
#include "w32term.h"
/* 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)
}
if (SUCCEEDED (result))
{
- int j, nclusters, from, to;
+ int j, from, to, adj_offset = 0;
from = 0;
to = from;
}
}
}
+
+ /* 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
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
{
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];
+ }
}
}
}
/* 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);
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];
}
&& 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]
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.
struct frame * f;
HDC context;
HFONT check_font, old_font;
- DWORD table;
int i, retval = 0;
struct gcpro gcpro1;
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,
register_font_driver (&uniscribe_font_driver, NULL);
}
-