#define _WIN32_WINNT 0x500
#include <windows.h>
#include <usp10.h>
-#include <setjmp.h>
#include "lisp.h"
#include "w32term.h"
}
if (SUCCEEDED (result))
{
- int j, 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];
+ }
}
}
}