Skip to content

Commit a97f537

Browse files
committed
[arabic] Implement Windows-1256 private shaping
Bug 1045139 - The Arabic text with "MS Sans Serif" font is rendered bad https://bugzilla.mozilla.org/show_bug.cgi?id=1045139 This is only enabled on Windows platforms, and requires support from Uniscribe to work. But for clients that do hook up to Uniscribe, this fixes shaping of Windows-1256-encoded bitmap fonts like "MS Sans Serif". The code and table together have just less than a 1kb footprint when enabled. UNTESTED. I might even have broken regular Arabic fallback shaping.
1 parent bf96b1b commit a97f537

File tree

4 files changed

+442
-14
lines changed

4 files changed

+442
-14
lines changed

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ HBSOURCES += \
9191
hb-ot-shape-complex-arabic.cc \
9292
hb-ot-shape-complex-arabic-fallback.hh \
9393
hb-ot-shape-complex-arabic-table.hh \
94+
hb-ot-shape-complex-arabic-win1256.hh \
9495
hb-ot-shape-complex-default.cc \
9596
hb-ot-shape-complex-hangul.cc \
9697
hb-ot-shape-complex-hebrew.cc \

src/check-includes.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ echo 'Checking that source files #include "hb-*private.hh" first (or none)'
2727

2828
for x in $HBSOURCES; do
2929
test -f "$srcdir/$x" && x="$srcdir/$x"
30-
grep '#.*\<include\>' "$x" /dev/null | head -n 1
30+
grep '#.*\<include\>' "$x" /dev/null | grep -v 'include _' | head -n 1
3131
done |
3232
grep -v '"hb-.*private[.]hh"' |
3333
grep -v 'hb-private[.]hh:' |

src/hb-ot-shape-complex-arabic-fallback.hh

Lines changed: 112 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
8181
num_glyphs++;
8282
}
8383

84+
if (!num_glyphs)
85+
return NULL;
86+
8487
/* Bubble-sort!
8588
* May not be good-enough for presidential candidate interviews, but good-enough for us... */
8689
hb_bubble_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]);
@@ -158,6 +161,9 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
158161
}
159162
}
160163

164+
if (!num_ligatures)
165+
return NULL;
166+
161167
OT::Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs);
162168
OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs);
163169
OT::Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures);
@@ -198,13 +204,101 @@ struct arabic_fallback_plan_t
198204
{
199205
ASSERT_POD ();
200206

207+
unsigned int num_lookups;
208+
bool free_lookups;
209+
201210
hb_mask_t mask_array[ARABIC_NUM_FALLBACK_FEATURES];
202211
OT::SubstLookup *lookup_array[ARABIC_NUM_FALLBACK_FEATURES];
203212
hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_NUM_FALLBACK_FEATURES];
204213
};
205214

206215
static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
207216

217+
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_WITH_WIN1256)
218+
#define HB_WITH_WIN1256
219+
#endif
220+
221+
#ifdef HB_WITH_WIN1256
222+
#include "hb-ot-shape-complex-arabic-win1256.hh"
223+
#endif
224+
225+
struct ManifestLookup {
226+
OT::USHORT fallbackType;
227+
OT::OffsetTo<OT::SubstLookup> lookupOffset;
228+
};
229+
typedef OT::ArrayOf<ManifestLookup> Manifest;
230+
231+
static bool
232+
arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan,
233+
const hb_ot_shape_plan_t *plan,
234+
hb_font_t *font)
235+
{
236+
#ifdef HB_WITH_WIN1256
237+
/* Does this font look like it's Windows-1256-encoded? */
238+
hb_codepoint_t g;
239+
if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ &&
240+
hb_font_get_glyph (font, 0x0644u, 0, &g) && g == 225 /* LAM */ &&
241+
hb_font_get_glyph (font, 0x0649u, 0, &g) && g == 236 /* ALEF MAKSURA */ &&
242+
hb_font_get_glyph (font, 0x064Au, 0, &g) && g == 237 /* YEH */ &&
243+
hb_font_get_glyph (font, 0x0652u, 0, &g) && g == 250 /* SUKUN */))
244+
return false;
245+
246+
const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest);
247+
ASSERT_STATIC (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup)
248+
<= ARABIC_NUM_FALLBACK_FEATURES);
249+
/* TODO sanitize the table? */
250+
251+
unsigned j = 0;
252+
unsigned int count = manifest.len;
253+
for (unsigned int i = 0; i < count; i++)
254+
{
255+
fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].fallbackType);
256+
if (fallback_plan->mask_array[j])
257+
{
258+
fallback_plan->lookup_array[j] = const_cast<OT::SubstLookup*> (&(&manifest+manifest[i].lookupOffset));
259+
if (fallback_plan->lookup_array[j])
260+
{
261+
fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
262+
j++;
263+
}
264+
}
265+
}
266+
267+
fallback_plan->num_lookups = j;
268+
fallback_plan->free_lookups = false;
269+
270+
return j > 0;
271+
#else
272+
return false;
273+
#endif
274+
}
275+
276+
static bool
277+
arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
278+
const hb_ot_shape_plan_t *plan,
279+
hb_font_t *font)
280+
{
281+
unsigned int j = 0;
282+
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
283+
{
284+
fallback_plan->mask_array[j] = plan->map.get_1_mask (arabic_fallback_features[i]);
285+
if (fallback_plan->mask_array[j])
286+
{
287+
fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i);
288+
if (fallback_plan->lookup_array[j])
289+
{
290+
fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
291+
j++;
292+
}
293+
}
294+
}
295+
296+
fallback_plan->num_lookups = j;
297+
fallback_plan->free_lookups = true;
298+
299+
return j > 0;
300+
}
301+
208302
static arabic_fallback_plan_t *
209303
arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
210304
hb_font_t *font)
@@ -213,17 +307,21 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
213307
if (unlikely (!fallback_plan))
214308
return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
215309

216-
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
217-
{
218-
fallback_plan->mask_array[i] = plan->map.get_1_mask (arabic_fallback_features[i]);
219-
if (fallback_plan->mask_array[i]) {
220-
fallback_plan->lookup_array[i] = arabic_fallback_synthesize_lookup (plan, font, i);
221-
if (fallback_plan->lookup_array[i])
222-
fallback_plan->accel_array[i].init (*fallback_plan->lookup_array[i]);
223-
}
224-
}
310+
fallback_plan->num_lookups = 0;
311+
fallback_plan->free_lookups = false;
312+
313+
/* Try synthesizing GSUB table using Unicode Arabic Presentation Forms,
314+
* in case the font has cmap entries for the presentation-forms characters. */
315+
if (arabic_fallback_plan_init_unicode (fallback_plan, plan, font))
316+
return fallback_plan;
225317

226-
return fallback_plan;
318+
/* See if this looks like a Windows-1256-encoded font. If it does, use a
319+
* hand-coded GSUB table. */
320+
if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
321+
return fallback_plan;
322+
323+
free (fallback_plan);
324+
return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
227325
}
228326

229327
static void
@@ -232,11 +330,12 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
232330
if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
233331
return;
234332

235-
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
333+
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
236334
if (fallback_plan->lookup_array[i])
237335
{
238336
fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]);
239-
free (fallback_plan->lookup_array[i]);
337+
if (fallback_plan->free_lookups)
338+
free (fallback_plan->lookup_array[i]);
240339
}
241340

242341
free (fallback_plan);
@@ -248,7 +347,7 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
248347
hb_buffer_t *buffer)
249348
{
250349
OT::hb_apply_context_t c (0, font, buffer);
251-
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
350+
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
252351
if (fallback_plan->lookup_array[i]) {
253352
c.set_lookup_mask (fallback_plan->mask_array[i]);
254353
hb_ot_layout_substitute_lookup (&c,

0 commit comments

Comments
 (0)