From f28b1c823db2ad56fed356ef864a7508d23048b8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 30 Jul 2014 02:15:44 -0400 Subject: [PATCH 1/7] [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. --- src/Makefile.am | 1 + src/check-includes.sh | 2 +- src/hb-ot-shape-complex-arabic-fallback.hh | 125 +++++++- src/hb-ot-shape-complex-arabic-win1256.hh | 328 +++++++++++++++++++++ 4 files changed, 442 insertions(+), 14 deletions(-) create mode 100644 src/hb-ot-shape-complex-arabic-win1256.hh diff --git a/src/Makefile.am b/src/Makefile.am index acedaa0b6..ba07ac5d6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,6 +91,7 @@ HBSOURCES += \ hb-ot-shape-complex-arabic.cc \ hb-ot-shape-complex-arabic-fallback.hh \ hb-ot-shape-complex-arabic-table.hh \ + hb-ot-shape-complex-arabic-win1256.hh \ hb-ot-shape-complex-default.cc \ hb-ot-shape-complex-hangul.cc \ hb-ot-shape-complex-hebrew.cc \ diff --git a/src/check-includes.sh b/src/check-includes.sh index 5643c6973..902f2357e 100755 --- a/src/check-includes.sh +++ b/src/check-includes.sh @@ -27,7 +27,7 @@ echo 'Checking that source files #include "hb-*private.hh" first (or none)' for x in $HBSOURCES; do test -f "$srcdir/$x" && x="$srcdir/$x" - grep '#.*\' "$x" /dev/null | head -n 1 + grep '#.*\' "$x" /dev/null | grep -v 'include _' | head -n 1 done | grep -v '"hb-.*private[.]hh"' | grep -v 'hb-private[.]hh:' | diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh index d488885dc..ae55b8720 100644 --- a/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/src/hb-ot-shape-complex-arabic-fallback.hh @@ -81,6 +81,9 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS num_glyphs++; } + if (!num_glyphs) + return NULL; + /* Bubble-sort! * May not be good-enough for presidential candidate interviews, but good-enough for us... */ 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 } } + if (!num_ligatures) + return NULL; + OT::Supplier first_glyphs_supplier (first_glyphs, num_first_glyphs); OT::Supplier ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs); OT::Supplier ligatures_supplier (ligature_list, num_ligatures); @@ -198,6 +204,9 @@ struct arabic_fallback_plan_t { ASSERT_POD (); + unsigned int num_lookups; + bool free_lookups; + hb_mask_t mask_array[ARABIC_NUM_FALLBACK_FEATURES]; OT::SubstLookup *lookup_array[ARABIC_NUM_FALLBACK_FEATURES]; hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_NUM_FALLBACK_FEATURES]; @@ -205,6 +214,91 @@ struct arabic_fallback_plan_t static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_WITH_WIN1256) +#define HB_WITH_WIN1256 +#endif + +#ifdef HB_WITH_WIN1256 +#include "hb-ot-shape-complex-arabic-win1256.hh" +#endif + +struct ManifestLookup { + OT::USHORT fallbackType; + OT::OffsetTo lookupOffset; +}; +typedef OT::ArrayOf Manifest; + +static bool +arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan, + const hb_ot_shape_plan_t *plan, + hb_font_t *font) +{ +#ifdef HB_WITH_WIN1256 + /* Does this font look like it's Windows-1256-encoded? */ + hb_codepoint_t g; + if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ && + hb_font_get_glyph (font, 0x0644u, 0, &g) && g == 225 /* LAM */ && + hb_font_get_glyph (font, 0x0649u, 0, &g) && g == 236 /* ALEF MAKSURA */ && + hb_font_get_glyph (font, 0x064Au, 0, &g) && g == 237 /* YEH */ && + hb_font_get_glyph (font, 0x0652u, 0, &g) && g == 250 /* SUKUN */)) + return false; + + const Manifest &manifest = reinterpret_cast (arabic_win1256_gsub_lookups.manifest); + ASSERT_STATIC (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup) + <= ARABIC_NUM_FALLBACK_FEATURES); + /* TODO sanitize the table? */ + + unsigned j = 0; + unsigned int count = manifest.len; + for (unsigned int i = 0; i < count; i++) + { + fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].fallbackType); + if (fallback_plan->mask_array[j]) + { + fallback_plan->lookup_array[j] = const_cast (&(&manifest+manifest[i].lookupOffset)); + if (fallback_plan->lookup_array[j]) + { + fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]); + j++; + } + } + } + + fallback_plan->num_lookups = j; + fallback_plan->free_lookups = false; + + return j > 0; +#else + return false; +#endif +} + +static bool +arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan, + const hb_ot_shape_plan_t *plan, + hb_font_t *font) +{ + unsigned int j = 0; + for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) + { + fallback_plan->mask_array[j] = plan->map.get_1_mask (arabic_fallback_features[i]); + if (fallback_plan->mask_array[j]) + { + fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i); + if (fallback_plan->lookup_array[j]) + { + fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]); + j++; + } + } + } + + fallback_plan->num_lookups = j; + fallback_plan->free_lookups = true; + + return j > 0; +} + static arabic_fallback_plan_t * arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan, hb_font_t *font) @@ -213,17 +307,21 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan, if (unlikely (!fallback_plan)) return const_cast (&arabic_fallback_plan_nil); - for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) - { - fallback_plan->mask_array[i] = plan->map.get_1_mask (arabic_fallback_features[i]); - if (fallback_plan->mask_array[i]) { - fallback_plan->lookup_array[i] = arabic_fallback_synthesize_lookup (plan, font, i); - if (fallback_plan->lookup_array[i]) - fallback_plan->accel_array[i].init (*fallback_plan->lookup_array[i]); - } - } + fallback_plan->num_lookups = 0; + fallback_plan->free_lookups = false; - return fallback_plan; + /* Try synthesizing GSUB table using Unicode Arabic Presentation Forms, + * in case the font has cmap entries for the presentation-forms characters. */ + if (arabic_fallback_plan_init_unicode (fallback_plan, plan, font)) + return fallback_plan; + + /* See if this looks like a Windows-1256-encoded font. If it does, use a + * hand-coded GSUB table. */ + if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font)) + return fallback_plan; + + free (fallback_plan); + return const_cast (&arabic_fallback_plan_nil); } static void @@ -232,11 +330,12 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan) if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil) return; - for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) + for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) if (fallback_plan->lookup_array[i]) { fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]); - free (fallback_plan->lookup_array[i]); + if (fallback_plan->free_lookups) + free (fallback_plan->lookup_array[i]); } free (fallback_plan); @@ -248,7 +347,7 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan, hb_buffer_t *buffer) { OT::hb_apply_context_t c (0, font, buffer); - for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) + for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) if (fallback_plan->lookup_array[i]) { c.set_lookup_mask (fallback_plan->mask_array[i]); hb_ot_layout_substitute_lookup (&c, diff --git a/src/hb-ot-shape-complex-arabic-win1256.hh b/src/hb-ot-shape-complex-arabic-win1256.hh new file mode 100644 index 000000000..160540f8d --- /dev/null +++ b/src/hb-ot-shape-complex-arabic-win1256.hh @@ -0,0 +1,328 @@ +/* + * Copyright © 2014 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH + + +/* + * The macros in the first part of this file are generic macros that can + * be used to define the bytes for OpenType table data in code in a + * readable manner. We can move the macros to reside with their respective + * struct types, but since we only use these to define one data table, the + * Windows-1256 Arabic shaping table in this file, we keep them here. + */ + + +/* First we measure, then we cut. */ +#ifndef OT_MEASURE +#define OT_MEASURE +#define OT_TABLE_START static const struct TABLE_NAME { char start[0 +#define OT_TABLE_END ]; } +#define OT_LABEL(Name) ]; char Name[0 +#define OT_USHORT(u16) +2/*bytes*/ +#define OT_DISTANCE(From,To,ItemSize) 0/*don't care */ +#else +#undef OT_MEASURE +#define OT_TABLE_START TABLE_NAME = { { +#define OT_TABLE_END } }; +#define OT_LABEL(Name) }, { +#define OT_USHORT(u16) ((u16)>>8), ((u16)&0xFF), +#define OT_DISTANCE(From,To,ItemSize) ((offsetof (struct TABLE_NAME, To) - \ + offsetof (struct TABLE_NAME, From)) / (ItemSize) \ + /* ASSERT_STATIC_EXPR it's divisible. */) +#endif + + +/* Whenever we receive an argument that is a list, it will expand to + * contain commas. That cannot be passed to another macro because the + * commas will throw off the preprocessor. The solution is to wrap + * the passed-in argument in OT_LIST() before passing to the next macro. + * Unfortunately this trick requires vararg macros. */ +#define OT_LIST(Args...) Args + + +/* + * Basic Types + */ + +#define OT_OFFSET(From, To) \ + OT_USHORT(OT_DISTANCE(From, To, 1)) // Offset from From to To in bytes + +#define OT_COUNT(Start, End, ItemSize) \ + OT_USHORT(OT_DISTANCE(Start, End, ItemSize)) +#define OT_UCOUNT(Start,End) \ + OT_COUNT(Start, End, 2) // USHORT count + +#define OT_GLYPHID OT_USHORT // GlyphID + +#define OT_UARRAY(Name, Items) \ + OT_LABEL(Name) \ + OT_UCOUNT(Name##Data, Name##DataEnd) \ + OT_LABEL(Name##Data) \ + Items \ + OT_LABEL(Name##DataEnd) + +#define OT_UHEADLESSARRAY(Name, Items) \ + OT_LABEL(Name) \ + OT_USHORT(OT_DISTANCE(Name##Data, Name##DataEnd, 2) + 1) \ + OT_LABEL(Name##Data) \ + Items \ + OT_LABEL(Name##DataEnd) + + +/* + * Common Types + */ + +#define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \ + OT_LABEL(Name) \ + OT_USHORT(LookupType) \ + OT_USHORT(LookupFlag) \ + OT_UARRAY(Name##SubLookupOffsetsArray, OT_LIST(SubLookupOffsets)) + +#define OT_SUBLOOKUP(Name, SubFormat, Items) \ + OT_LABEL(Name) \ + OT_USHORT(SubFormat) \ + Items + +#define OT_COVERAGE1(Name, Items) \ + OT_LABEL(Name) \ + OT_USHORT(1) \ + OT_UARRAY(Name##Glyphs, OT_LIST(Items)) + + +/* + * GSUB + */ + +#define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \ + OT_SUBLOOKUP(Name, 2, \ + OT_OFFSET(Name, Name##Coverage) \ + OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \ + ) \ + OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \ + /* ASSERT_STATIC_EXPR len(FromGlyphs) == len(ToGlyphs) */ + +#define OT_SUBLOOKUP_MULTIPLE_SUBST_FORMAT1(Name, FromGlyphs, SequenceOffsets) \ + OT_SUBLOOKUP(Name, 1, \ + OT_OFFSET(Name, Name##Coverage) \ + OT_UARRAY(Name##SequenceOffsetsArray, OT_LIST(SequenceOffsets)) \ + ) \ + OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \ + /* ASSERT_STATIC_EXPR len(FromGlyphs) == len(SequenceOffsets) */ + +#define OT_SEQUENCE(Name, SubstituteGlyphs) \ + OT_LABEL(Name) \ + OT_UARRAY(Name##SubstituteGlyphsArray, OT_LIST(SubstituteGlyphs)) + +#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \ + OT_SUBLOOKUP(Name, 1, \ + OT_OFFSET(Name, Name##Coverage) \ + OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \ + ) \ + OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \ + /* ASSERT_STATIC_EXPR len(FirstGlyphs) == len(LigatureSetOffsets) */ + +#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \ + OT_LABEL(Name) \ + OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) + +#define OT_LIGATURE(Name, Components, LigGlyph) \ + OT_LABEL(Name) \ + LigGlyph \ + OT_UHEADLESSARRAY(Name##ComponentsArray, OT_LIST(Components)) + + +/* + * + * Start of Windows-1256 shaping table. + * + */ + +/* Table name. */ +#define TABLE_NAME arabic_win1256_gsub_lookups + +/* Table manifest. */ +#define MANIFEST(Items) \ + OT_LABEL(manifest) \ + OT_COUNT(manifestData, manifestDataEnd, 4) \ + OT_LABEL(manifestData) \ + Items \ + OT_LABEL(manifestDataEnd) + +#define MANIFEST_LOOKUP(FallbackType, Name) \ + OT_USHORT(FallbackType) \ + OT_OFFSET(manifest, Name) + +/* Shorthand. */ +#define G OT_GLYPHID + +/* We use this to differentiate a medial-Lam from an initial-Lam. + * In this two-shape encoding, those two have the same glyph. But + * for Lam-Alef ligature formations we need to differentiate. As + * such, we add a MultipleSubst to the end of 'medi' feature to + * insert an extra glyph there, and we use that to replace the + * proper ligature later. As long as this is the code for an + * isolated form, it will work fine, as an isolated form cannot + * happen between a Lam-Alef sequence of the shapes that form a + * ligature. */ +#define LAM_MEDI_MARKER 225 + + +/* + * Table Start + */ +OT_TABLE_START + + +/* + * Manifest + */ +MANIFEST( + MANIFEST_LOOKUP(FALLBACK_INIT, initLookup) + MANIFEST_LOOKUP(FALLBACK_MEDI, mediLookup) + MANIFEST_LOOKUP(FALLBACK_FINA, finaLookup) + MANIFEST_LOOKUP(FALLBACK_RLIG, rligLookup) + MANIFEST_LOOKUP(FALLBACK_RLIG, rligMarksLookup) +) + +/* + * Lookups + */ +OT_LOOKUP(initLookup, OT::SubstLookupSubTable::Single, OT::LookupFlag::IgnoreMarks, + OT_OFFSET(initLookup, initmediSubLookup) + OT_OFFSET(initLookup, initSubLookup) +) +OT_LOOKUP(mediLookup, OT::SubstLookupSubTable::Single, OT::LookupFlag::IgnoreMarks, + OT_OFFSET(mediLookup, initmediSubLookup) + OT_OFFSET(mediLookup, mediSubLookup) +) +OT_LOOKUP(finaLookup, OT::SubstLookupSubTable::Single, OT::LookupFlag::IgnoreMarks, + OT_OFFSET(finaLookup, finaSubLookup) +) +OT_LOOKUP(mediLamLookup, OT::SubstLookupSubTable::Multiple, OT::LookupFlag::IgnoreMarks, + OT_OFFSET(mediLamLookup, mediLamSubLookup) +) +OT_LOOKUP(rligLookup, OT::SubstLookupSubTable::Ligature, OT::LookupFlag::IgnoreMarks, + OT_OFFSET(rligLookup, lamAlefLigaturesSubLookup) +) +OT_LOOKUP(rligMarksLookup, OT::SubstLookupSubTable::Ligature, 0, + OT_OFFSET(rligMarksLookup, shaddaLigaturesSubLookup) +) + +/* + * init/medi/fina forms + */ +OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initmediSubLookup, + G(198) G(200) G(201) G(202) G(203) G(211) G(212) G(213) + G(214) G(223) G(225) G(227) G(228) G(236) G(237), + G(162) G(4) G(5) G(5) G(6) G(13) G(14) G(15) + G(26) G(140) G(141) G(142) G(143) G(154) G(154) +) +OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initSubLookup, + G(204) G(205) G(206) G(218) G(219) G(221) G(222) G(229), + G(7) G(9) G(11) G(27) G(30) G(128) G(131) G(144) +) +OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(mediSubLookup, + G(204) G(205) G(206) G(218) G(219) G(221) G(222) G(229), + G(8) G(10) G(12) G(28) G(31) G(129) G(138) G(149) +) +OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(finaSubLookup, + G(194) G(195) G(197) G(198) G(199) G(218) G(219) G(229) G(236) G(237), + G(2) G(1) G(3) G(181) G(0) G(29) G(127) G(152) G(160) G(156) +) +OT_SUBLOOKUP_MULTIPLE_SUBST_FORMAT1(mediLamSubLookup, + G(141), + OT_OFFSET(mediLamSubLookup, mediLamSequence) +) +OT_SEQUENCE(mediLamSequence, G(141) G(LAM_MEDI_MARKER)) + +/* + * Lam+Alef ligatures + */ +OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(lamAlefLigaturesSubLookup, + G(141), + OT_OFFSET(lamAlefLigaturesSubLookup, lamLigatureSet) +) +OT_LIGATURE_SET(lamLigatureSet, + OT_OFFSET(lamLigatureSet, lamInitLigature1) + OT_OFFSET(lamLigatureSet, lamInitLigature2) + OT_OFFSET(lamLigatureSet, lamInitLigature3) + OT_OFFSET(lamLigatureSet, lamInitLigature4) + OT_OFFSET(lamLigatureSet, lamMediLigature1) + OT_OFFSET(lamLigatureSet, lamMediLigature2) + OT_OFFSET(lamLigatureSet, lamMediLigature3) + OT_OFFSET(lamLigatureSet, lamMediLigature4) +) +OT_LIGATURE(lamInitLigature1, G(0), G(165)) +OT_LIGATURE(lamInitLigature2, G(1), G(178)) +OT_LIGATURE(lamInitLigature3, G(2), G(180)) +OT_LIGATURE(lamInitLigature4, G(3), G(252)) +OT_LIGATURE(lamMediLigature1, G(LAM_MEDI_MARKER) G(0), G(170)) +OT_LIGATURE(lamMediLigature2, G(LAM_MEDI_MARKER) G(1), G(179)) +OT_LIGATURE(lamMediLigature3, G(LAM_MEDI_MARKER) G(2), G(185)) +OT_LIGATURE(lamMediLigature4, G(LAM_MEDI_MARKER) G(3), G(255)) + +/* + * Shadda ligatures + */ +OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(shaddaLigaturesSubLookup, + G(248), + OT_OFFSET(shaddaLigaturesSubLookup, shaddaLigatureSet) +) +OT_LIGATURE_SET(shaddaLigatureSet, + OT_OFFSET(shaddaLigatureSet, shaddaLigature1) + OT_OFFSET(shaddaLigatureSet, shaddaLigature2) + OT_OFFSET(shaddaLigatureSet, shaddaLigature3) +) +OT_LIGATURE(shaddaLigature1, G(243), G(172)) +OT_LIGATURE(shaddaLigature2, G(245), G(173)) +OT_LIGATURE(shaddaLigature3, G(246), G(175)) + +/* + * Table end + */ +OT_TABLE_END + + +/* + * Clean up + */ +#undef OT_TABLE_START +#undef OT_TABLE_END +#undef OT_LABEL +#undef OT_USHORT +#undef OT_DISTANCE + +/* + * Include a second time to get the table data... + */ +#ifdef OT_MEASURE +#include __FILE__ +#endif + +#define HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH +#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH */ From 1789ccb1dd56af6117eac00e633eff94860ba252 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 31 Jul 2014 11:04:00 -0400 Subject: [PATCH 2/7] [arabic/win1256] Remove GCC'ism The table can now compile independently too. If we cannot make it work on MSVC, we can always generate the data and distribute it. The code now compiles cleanly with: gcc -c -xc -std=c99 -Werror -pedantic hb-ot-shape-complex-arabic-win1256.hh g++ -c -xc -std=c++1x -Werror -pedantic hb-ot-shape-complex-arabic-win1256.hh See: https://github.com/behdad/harfbuzz/commit/a97f537cec209649302899975d76ca2b2661da7a#commitcomment-7218736 --- src/hb-ot-shape-complex-arabic-fallback.hh | 4 +- src/hb-ot-shape-complex-arabic-win1256.hh | 123 ++++++++++++--------- 2 files changed, 75 insertions(+), 52 deletions(-) diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh index ae55b8720..00d75ac1f 100644 --- a/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/src/hb-ot-shape-complex-arabic-fallback.hh @@ -223,7 +223,7 @@ static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; #endif struct ManifestLookup { - OT::USHORT fallbackType; + OT::Tag tag; OT::OffsetTo lookupOffset; }; typedef OT::ArrayOf Manifest; @@ -252,7 +252,7 @@ arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan, unsigned int count = manifest.len; for (unsigned int i = 0; i < count; i++) { - fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].fallbackType); + fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].tag); if (fallback_plan->mask_array[j]) { fallback_plan->lookup_array[j] = const_cast (&(&manifest+manifest[i].lookupOffset)); diff --git a/src/hb-ot-shape-complex-arabic-win1256.hh b/src/hb-ot-shape-complex-arabic-win1256.hh index 160540f8d..cceac42d0 100644 --- a/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/src/hb-ot-shape-complex-arabic-win1256.hh @@ -39,78 +39,92 @@ /* First we measure, then we cut. */ #ifndef OT_MEASURE #define OT_MEASURE -#define OT_TABLE_START static const struct TABLE_NAME { char start[0 -#define OT_TABLE_END ]; } -#define OT_LABEL(Name) ]; char Name[0 +#define OT_TABLE_START static const struct TABLE_NAME { +#define OT_TABLE_END } +#define OT_LABEL_START(Name) unsigned char Name[ +#define OT_LABEL_END ]; +#define OT_BYTE(u8) +1/*byte*/ #define OT_USHORT(u16) +2/*bytes*/ -#define OT_DISTANCE(From,To,ItemSize) 0/*don't care */ #else #undef OT_MEASURE -#define OT_TABLE_START TABLE_NAME = { { -#define OT_TABLE_END } }; -#define OT_LABEL(Name) }, { -#define OT_USHORT(u16) ((u16)>>8), ((u16)&0xFF), -#define OT_DISTANCE(From,To,ItemSize) ((offsetof (struct TABLE_NAME, To) - \ - offsetof (struct TABLE_NAME, From)) / (ItemSize) \ - /* ASSERT_STATIC_EXPR it's divisible. */) +#define OT_TABLE_START TABLE_NAME = { +#define OT_TABLE_END }; +#define OT_LABEL_START(Name) { +#define OT_LABEL_END }, +#define OT_BYTE(u8) (u8), +#define OT_USHORT(u16) (unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu), +#define OT_COUNT(Name, ItemSize) ((unsigned int) sizeof(((struct TABLE_NAME*)0)->Name) \ + / (unsigned int)(ItemSize) \ + /* OT_ASSERT it's divisible (and positive). */) +#define OT_DISTANCE(From,To) ((unsigned int) \ + ((char*)(&((struct TABLE_NAME*)0)->To) - \ + (char*)(&((struct TABLE_NAME*)0)->From)) \ + /* OT_ASSERT it's positive. */) #endif +#define OT_LABEL(Name) \ + OT_LABEL_END \ + OT_LABEL_START(Name) + /* Whenever we receive an argument that is a list, it will expand to * contain commas. That cannot be passed to another macro because the * commas will throw off the preprocessor. The solution is to wrap * the passed-in argument in OT_LIST() before passing to the next macro. * Unfortunately this trick requires vararg macros. */ -#define OT_LIST(Args...) Args +#define OT_LIST(...) __VA_ARGS__ /* * Basic Types */ -#define OT_OFFSET(From, To) \ - OT_USHORT(OT_DISTANCE(From, To, 1)) // Offset from From to To in bytes +#define OT_TAG(a,b,c,d) \ + OT_BYTE(a) OT_BYTE(b) OT_BYTE(c) OT_BYTE(d) -#define OT_COUNT(Start, End, ItemSize) \ - OT_USHORT(OT_DISTANCE(Start, End, ItemSize)) -#define OT_UCOUNT(Start,End) \ - OT_COUNT(Start, End, 2) // USHORT count +#define OT_OFFSET(From, To) /* Offset from From to To in bytes */ \ + OT_USHORT(OT_DISTANCE(From, To)) -#define OT_GLYPHID OT_USHORT // GlyphID +#define OT_GLYPHID /* GlyphID */ \ + OT_USHORT #define OT_UARRAY(Name, Items) \ - OT_LABEL(Name) \ - OT_UCOUNT(Name##Data, Name##DataEnd) \ + OT_LABEL_START(Name) \ + OT_USHORT(OT_COUNT(Name##Data, 2)) \ OT_LABEL(Name##Data) \ Items \ - OT_LABEL(Name##DataEnd) + OT_LABEL_END #define OT_UHEADLESSARRAY(Name, Items) \ - OT_LABEL(Name) \ - OT_USHORT(OT_DISTANCE(Name##Data, Name##DataEnd, 2) + 1) \ + OT_LABEL_START(Name) \ + OT_USHORT(OT_COUNT(Name##Data, 2) + 1) \ OT_LABEL(Name##Data) \ Items \ - OT_LABEL(Name##DataEnd) + OT_LABEL_END /* * Common Types */ +#define OT_LOOKUP_FLAG_IGNORE_MARKS 0x08u + #define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \ - OT_LABEL(Name) \ + OT_LABEL_START(Name) \ OT_USHORT(LookupType) \ OT_USHORT(LookupFlag) \ + OT_LABEL_END \ OT_UARRAY(Name##SubLookupOffsetsArray, OT_LIST(SubLookupOffsets)) #define OT_SUBLOOKUP(Name, SubFormat, Items) \ - OT_LABEL(Name) \ + OT_LABEL_START(Name) \ OT_USHORT(SubFormat) \ Items #define OT_COVERAGE1(Name, Items) \ - OT_LABEL(Name) \ + OT_LABEL_START(Name) \ OT_USHORT(1) \ + OT_LABEL_END \ OT_UARRAY(Name##Glyphs, OT_LIST(Items)) @@ -118,9 +132,14 @@ * GSUB */ +#define OT_LOOKUP_TYPE_SUBST_SINGLE 1u +#define OT_LOOKUP_TYPE_SUBST_MULTIPLE 2u +#define OT_LOOKUP_TYPE_SUBST_LIGATURE 4u + #define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \ OT_SUBLOOKUP(Name, 2, \ OT_OFFSET(Name, Name##Coverage) \ + OT_LABEL_END \ OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \ ) \ OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \ @@ -129,30 +148,31 @@ #define OT_SUBLOOKUP_MULTIPLE_SUBST_FORMAT1(Name, FromGlyphs, SequenceOffsets) \ OT_SUBLOOKUP(Name, 1, \ OT_OFFSET(Name, Name##Coverage) \ + OT_LABEL_END \ OT_UARRAY(Name##SequenceOffsetsArray, OT_LIST(SequenceOffsets)) \ ) \ OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \ /* ASSERT_STATIC_EXPR len(FromGlyphs) == len(SequenceOffsets) */ #define OT_SEQUENCE(Name, SubstituteGlyphs) \ - OT_LABEL(Name) \ - OT_UARRAY(Name##SubstituteGlyphsArray, OT_LIST(SubstituteGlyphs)) + OT_UARRAY(Name, OT_LIST(SubstituteGlyphs)) #define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \ OT_SUBLOOKUP(Name, 1, \ OT_OFFSET(Name, Name##Coverage) \ + OT_LABEL_END \ OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \ ) \ OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \ /* ASSERT_STATIC_EXPR len(FirstGlyphs) == len(LigatureSetOffsets) */ #define OT_LIGATURE_SET(Name, LigatureSetOffsets) \ - OT_LABEL(Name) \ - OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) + OT_UARRAY(Name, OT_LIST(LigatureSetOffsets)) #define OT_LIGATURE(Name, Components, LigGlyph) \ - OT_LABEL(Name) \ + OT_LABEL_START(Name) \ LigGlyph \ + OT_LABEL_END \ OT_UHEADLESSARRAY(Name##ComponentsArray, OT_LIST(Components)) @@ -167,14 +187,14 @@ /* Table manifest. */ #define MANIFEST(Items) \ - OT_LABEL(manifest) \ - OT_COUNT(manifestData, manifestDataEnd, 4) \ + OT_LABEL_START(manifest) \ + OT_USHORT(OT_COUNT(manifestData, 6)) \ OT_LABEL(manifestData) \ Items \ - OT_LABEL(manifestDataEnd) + OT_LABEL_END -#define MANIFEST_LOOKUP(FallbackType, Name) \ - OT_USHORT(FallbackType) \ +#define MANIFEST_LOOKUP(Tag, Name) \ + Tag \ OT_OFFSET(manifest, Name) /* Shorthand. */ @@ -202,34 +222,34 @@ OT_TABLE_START * Manifest */ MANIFEST( - MANIFEST_LOOKUP(FALLBACK_INIT, initLookup) - MANIFEST_LOOKUP(FALLBACK_MEDI, mediLookup) - MANIFEST_LOOKUP(FALLBACK_FINA, finaLookup) - MANIFEST_LOOKUP(FALLBACK_RLIG, rligLookup) - MANIFEST_LOOKUP(FALLBACK_RLIG, rligMarksLookup) + MANIFEST_LOOKUP(OT_TAG('i','n','i','t'), initLookup) + MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLookup) + MANIFEST_LOOKUP(OT_TAG('f','i','n','a'), finaLookup) + MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligLookup) + MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligMarksLookup) ) /* * Lookups */ -OT_LOOKUP(initLookup, OT::SubstLookupSubTable::Single, OT::LookupFlag::IgnoreMarks, +OT_LOOKUP(initLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS, OT_OFFSET(initLookup, initmediSubLookup) OT_OFFSET(initLookup, initSubLookup) ) -OT_LOOKUP(mediLookup, OT::SubstLookupSubTable::Single, OT::LookupFlag::IgnoreMarks, +OT_LOOKUP(mediLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS, OT_OFFSET(mediLookup, initmediSubLookup) OT_OFFSET(mediLookup, mediSubLookup) ) -OT_LOOKUP(finaLookup, OT::SubstLookupSubTable::Single, OT::LookupFlag::IgnoreMarks, +OT_LOOKUP(finaLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS, OT_OFFSET(finaLookup, finaSubLookup) ) -OT_LOOKUP(mediLamLookup, OT::SubstLookupSubTable::Multiple, OT::LookupFlag::IgnoreMarks, +OT_LOOKUP(mediLamLookup, OT_LOOKUP_TYPE_SUBST_MULTIPLE, OT_LOOKUP_FLAG_IGNORE_MARKS, OT_OFFSET(mediLamLookup, mediLamSubLookup) ) -OT_LOOKUP(rligLookup, OT::SubstLookupSubTable::Ligature, OT::LookupFlag::IgnoreMarks, +OT_LOOKUP(rligLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, OT_LOOKUP_FLAG_IGNORE_MARKS, OT_OFFSET(rligLookup, lamAlefLigaturesSubLookup) ) -OT_LOOKUP(rligMarksLookup, OT::SubstLookupSubTable::Ligature, 0, +OT_LOOKUP(rligMarksLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, 0, OT_OFFSET(rligMarksLookup, shaddaLigaturesSubLookup) ) @@ -313,9 +333,12 @@ OT_TABLE_END */ #undef OT_TABLE_START #undef OT_TABLE_END -#undef OT_LABEL +#undef OT_LABEL_START +#undef OT_LABEL_END +#undef OT_BYTE #undef OT_USHORT #undef OT_DISTANCE +#undef OT_COUNT /* * Include a second time to get the table data... From a2de193220ee2839125594bd1a60b5b66ab4598e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 31 Jul 2014 18:21:05 -0400 Subject: [PATCH 3/7] [arabic/win1256] Fix shaping of JEEM, HAH, and KHAH https://bugzilla.mozilla.org/show_bug.cgi?id=1045139#c16 --- src/hb-ot-shape-complex-arabic-win1256.hh | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/hb-ot-shape-complex-arabic-win1256.hh b/src/hb-ot-shape-complex-arabic-win1256.hh index cceac42d0..3b1e8c6e7 100644 --- a/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/src/hb-ot-shape-complex-arabic-win1256.hh @@ -257,22 +257,24 @@ OT_LOOKUP(rligMarksLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, 0, * init/medi/fina forms */ OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initmediSubLookup, - G(198) G(200) G(201) G(202) G(203) G(211) G(212) G(213) - G(214) G(223) G(225) G(227) G(228) G(236) G(237), - G(162) G(4) G(5) G(5) G(6) G(13) G(14) G(15) - G(26) G(140) G(141) G(142) G(143) G(154) G(154) + G(198) G(200) G(201) G(202) G(203) G(204) G(205) G(206) G(211) + G(212) G(213) G(214) G(223) G(225) G(227) G(228) G(236) G(237), + G(162) G(4) G(5) G(5) G(6) G(7) G(9) G(11) G(13) + G(14) G(15) G(26) G(140) G(141) G(142) G(143) G(154) G(154) ) OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initSubLookup, - G(204) G(205) G(206) G(218) G(219) G(221) G(222) G(229), - G(7) G(9) G(11) G(27) G(30) G(128) G(131) G(144) + G(218) G(219) G(221) G(222) G(229), + G(27) G(30) G(128) G(131) G(144) ) OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(mediSubLookup, - G(204) G(205) G(206) G(218) G(219) G(221) G(222) G(229), - G(8) G(10) G(12) G(28) G(31) G(129) G(138) G(149) + G(218) G(219) G(221) G(222) G(229), + G(28) G(31) G(129) G(138) G(149) ) OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(finaSubLookup, - G(194) G(195) G(197) G(198) G(199) G(218) G(219) G(229) G(236) G(237), - G(2) G(1) G(3) G(181) G(0) G(29) G(127) G(152) G(160) G(156) + G(194) G(195) G(197) G(198) G(199) G(204) G(205) G(206) G(218) + G(219) G(229) G(236) G(237), + G(2) G(1) G(3) G(181) G(0) G(8) G(10) G(12) G(29) + G(127) G(152) G(160) G(156) ) OT_SUBLOOKUP_MULTIPLE_SUBST_FORMAT1(mediLamSubLookup, G(141), From e839e2523e64fd0cf21929f6a45e2facd59c7917 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 1 Aug 2014 16:09:31 -0400 Subject: [PATCH 4/7] [arabic/win1256] Fix TEH MARBUTA final form https://bugzilla.mozilla.org/show_bug.cgi?id=1045139#c18 --- src/hb-ot-shape-complex-arabic-win1256.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hb-ot-shape-complex-arabic-win1256.hh b/src/hb-ot-shape-complex-arabic-win1256.hh index 3b1e8c6e7..e4cb626e1 100644 --- a/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/src/hb-ot-shape-complex-arabic-win1256.hh @@ -271,10 +271,10 @@ OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(mediSubLookup, G(28) G(31) G(129) G(138) G(149) ) OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(finaSubLookup, - G(194) G(195) G(197) G(198) G(199) G(204) G(205) G(206) G(218) - G(219) G(229) G(236) G(237), - G(2) G(1) G(3) G(181) G(0) G(8) G(10) G(12) G(29) - G(127) G(152) G(160) G(156) + G(194) G(195) G(197) G(198) G(199) G(201) G(204) G(205) G(206) + G(218) G(219) G(229) G(236) G(237), + G(2) G(1) G(3) G(181) G(0) G(159) G(8) G(10) G(12) + G(29) G(127) G(152) G(160) G(156) ) OT_SUBLOOKUP_MULTIPLE_SUBST_FORMAT1(mediLamSubLookup, G(141), From 55977f2a462b7fa1248eab3787053dc82320d3e5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 1 Aug 2014 16:14:33 -0400 Subject: [PATCH 5/7] [arabic/win1256] Hook up lamMedi lookup Restructure lookup array to accommodate. https://bugzilla.mozilla.org/show_bug.cgi?id=1045139#c18 --- src/hb-ot-shape-complex-arabic-fallback.hh | 26 +++++++++------------- src/hb-ot-shape-complex-arabic-win1256.hh | 1 + 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh index 00d75ac1f..a991af926 100644 --- a/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/src/hb-ot-shape-complex-arabic-fallback.hh @@ -33,7 +33,8 @@ #include "hb-ot-layout-gsub-table.hh" -/* Features ordered the same as the entries in shaping_table rows. */ +/* Features ordered the same as the entries in shaping_table rows, + * followed by rlig. Don't change. */ static const hb_tag_t arabic_fallback_features[] = { HB_TAG('i','n','i','t'), @@ -43,16 +44,6 @@ static const hb_tag_t arabic_fallback_features[] = HB_TAG('r','l','i','g'), }; -/* Same order as the fallback feature array */ -enum { - FALLBACK_INIT, - FALLBACK_MEDI, - FALLBACK_FINA, - FALLBACK_ISOL, - FALLBACK_RLIG, - ARABIC_NUM_FALLBACK_FEATURES -}; - static OT::SubstLookup * arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font, @@ -200,6 +191,8 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan, return arabic_fallback_synthesize_lookup_ligature (plan, font); } +#define ARABIC_FALLBACK_MAX_LOOKUPS 6 + struct arabic_fallback_plan_t { ASSERT_POD (); @@ -207,9 +200,9 @@ struct arabic_fallback_plan_t unsigned int num_lookups; bool free_lookups; - hb_mask_t mask_array[ARABIC_NUM_FALLBACK_FEATURES]; - OT::SubstLookup *lookup_array[ARABIC_NUM_FALLBACK_FEATURES]; - hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_NUM_FALLBACK_FEATURES]; + hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS]; + OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS]; + hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS]; }; static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; @@ -245,7 +238,7 @@ arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan, const Manifest &manifest = reinterpret_cast (arabic_win1256_gsub_lookups.manifest); ASSERT_STATIC (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup) - <= ARABIC_NUM_FALLBACK_FEATURES); + <= ARABIC_FALLBACK_MAX_LOOKUPS); /* TODO sanitize the table? */ unsigned j = 0; @@ -278,8 +271,9 @@ arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan, const hb_ot_shape_plan_t *plan, hb_font_t *font) { + ASSERT_STATIC (ARRAY_LENGTH(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS); unsigned int j = 0; - for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) + for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++) { fallback_plan->mask_array[j] = plan->map.get_1_mask (arabic_fallback_features[i]); if (fallback_plan->mask_array[j]) diff --git a/src/hb-ot-shape-complex-arabic-win1256.hh b/src/hb-ot-shape-complex-arabic-win1256.hh index e4cb626e1..a19ce6ce8 100644 --- a/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/src/hb-ot-shape-complex-arabic-win1256.hh @@ -224,6 +224,7 @@ OT_TABLE_START MANIFEST( MANIFEST_LOOKUP(OT_TAG('i','n','i','t'), initLookup) MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLookup) + MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLamLookup) MANIFEST_LOOKUP(OT_TAG('f','i','n','a'), finaLookup) MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligLookup) MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligMarksLookup) From abfa4252cce1c56c472693dcd8400cd97ededd2f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 1 Aug 2014 19:05:33 -0400 Subject: [PATCH 6/7] [arabic/win1256] Really fix lam-alef this time https://bugzilla.mozilla.org/show_bug.cgi?id=1045139#c26 https://github.com/behdad/harfbuzz/commit/b276e897d17519a2c28f79d024904ac2bdd86bcf#commitcomment-7243499 --- src/hb-ot-shape-complex-arabic-fallback.hh | 2 +- src/hb-ot-shape-complex-arabic-win1256.hh | 49 +++++++--------------- 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh index a991af926..e62cea479 100644 --- a/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/src/hb-ot-shape-complex-arabic-fallback.hh @@ -191,7 +191,7 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan, return arabic_fallback_synthesize_lookup_ligature (plan, font); } -#define ARABIC_FALLBACK_MAX_LOOKUPS 6 +#define ARABIC_FALLBACK_MAX_LOOKUPS 5 struct arabic_fallback_plan_t { diff --git a/src/hb-ot-shape-complex-arabic-win1256.hh b/src/hb-ot-shape-complex-arabic-win1256.hh index a19ce6ce8..006cab86e 100644 --- a/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/src/hb-ot-shape-complex-arabic-win1256.hh @@ -175,7 +175,6 @@ OT_LABEL_END \ OT_UHEADLESSARRAY(Name##ComponentsArray, OT_LIST(Components)) - /* * * Start of Windows-1256 shaping table. @@ -200,18 +199,6 @@ /* Shorthand. */ #define G OT_GLYPHID -/* We use this to differentiate a medial-Lam from an initial-Lam. - * In this two-shape encoding, those two have the same glyph. But - * for Lam-Alef ligature formations we need to differentiate. As - * such, we add a MultipleSubst to the end of 'medi' feature to - * insert an extra glyph there, and we use that to replace the - * proper ligature later. As long as this is the code for an - * isolated form, it will work fine, as an isolated form cannot - * happen between a Lam-Alef sequence of the shapes that form a - * ligature. */ -#define LAM_MEDI_MARKER 225 - - /* * Table Start */ @@ -222,11 +209,10 @@ OT_TABLE_START * Manifest */ MANIFEST( + MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligLookup) MANIFEST_LOOKUP(OT_TAG('i','n','i','t'), initLookup) MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLookup) - MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLamLookup) MANIFEST_LOOKUP(OT_TAG('f','i','n','a'), finaLookup) - MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligLookup) MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligMarksLookup) ) @@ -240,12 +226,14 @@ OT_LOOKUP(initLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS, OT_LOOKUP(mediLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS, OT_OFFSET(mediLookup, initmediSubLookup) OT_OFFSET(mediLookup, mediSubLookup) + OT_OFFSET(mediLookup, medifinaLamAlefSubLookup) ) OT_LOOKUP(finaLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS, OT_OFFSET(finaLookup, finaSubLookup) -) -OT_LOOKUP(mediLamLookup, OT_LOOKUP_TYPE_SUBST_MULTIPLE, OT_LOOKUP_FLAG_IGNORE_MARKS, - OT_OFFSET(mediLamLookup, mediLamSubLookup) + /* We don't need this one currently as the sequence inherits masks + * from the first item. Just in case we change that in the future + * to be smart about Arabic masks when ligating... */ + OT_OFFSET(finaLookup, medifinaLamAlefSubLookup) ) OT_LOOKUP(rligLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, OT_LOOKUP_FLAG_IGNORE_MARKS, OT_OFFSET(rligLookup, lamAlefLigaturesSubLookup) @@ -277,17 +265,16 @@ OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(finaSubLookup, G(2) G(1) G(3) G(181) G(0) G(159) G(8) G(10) G(12) G(29) G(127) G(152) G(160) G(156) ) -OT_SUBLOOKUP_MULTIPLE_SUBST_FORMAT1(mediLamSubLookup, - G(141), - OT_OFFSET(mediLamSubLookup, mediLamSequence) +OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(medifinaLamAlefSubLookup, + G(165) G(178) G(180) G(252), + G(170) G(179) G(185) G(255) ) -OT_SEQUENCE(mediLamSequence, G(141) G(LAM_MEDI_MARKER)) /* * Lam+Alef ligatures */ OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(lamAlefLigaturesSubLookup, - G(141), + G(225), OT_OFFSET(lamAlefLigaturesSubLookup, lamLigatureSet) ) OT_LIGATURE_SET(lamLigatureSet, @@ -295,19 +282,11 @@ OT_LIGATURE_SET(lamLigatureSet, OT_OFFSET(lamLigatureSet, lamInitLigature2) OT_OFFSET(lamLigatureSet, lamInitLigature3) OT_OFFSET(lamLigatureSet, lamInitLigature4) - OT_OFFSET(lamLigatureSet, lamMediLigature1) - OT_OFFSET(lamLigatureSet, lamMediLigature2) - OT_OFFSET(lamLigatureSet, lamMediLigature3) - OT_OFFSET(lamLigatureSet, lamMediLigature4) ) -OT_LIGATURE(lamInitLigature1, G(0), G(165)) -OT_LIGATURE(lamInitLigature2, G(1), G(178)) -OT_LIGATURE(lamInitLigature3, G(2), G(180)) -OT_LIGATURE(lamInitLigature4, G(3), G(252)) -OT_LIGATURE(lamMediLigature1, G(LAM_MEDI_MARKER) G(0), G(170)) -OT_LIGATURE(lamMediLigature2, G(LAM_MEDI_MARKER) G(1), G(179)) -OT_LIGATURE(lamMediLigature3, G(LAM_MEDI_MARKER) G(2), G(185)) -OT_LIGATURE(lamMediLigature4, G(LAM_MEDI_MARKER) G(3), G(255)) +OT_LIGATURE(lamInitLigature1, G(199), G(165)) +OT_LIGATURE(lamInitLigature2, G(195), G(178)) +OT_LIGATURE(lamInitLigature3, G(194), G(180)) +OT_LIGATURE(lamInitLigature4, G(197), G(252)) /* * Shadda ligatures From 6ab6be32c5857ce3344021ad2996e80b2a8c8f99 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 2 Aug 2014 14:58:38 -0400 Subject: [PATCH 7/7] [arabic/win1256] Remove unused MultipleSubst macros --- src/hb-ot-shape-complex-arabic-win1256.hh | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/hb-ot-shape-complex-arabic-win1256.hh b/src/hb-ot-shape-complex-arabic-win1256.hh index 006cab86e..63ed3f8e0 100644 --- a/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/src/hb-ot-shape-complex-arabic-win1256.hh @@ -145,18 +145,6 @@ OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \ /* ASSERT_STATIC_EXPR len(FromGlyphs) == len(ToGlyphs) */ -#define OT_SUBLOOKUP_MULTIPLE_SUBST_FORMAT1(Name, FromGlyphs, SequenceOffsets) \ - OT_SUBLOOKUP(Name, 1, \ - OT_OFFSET(Name, Name##Coverage) \ - OT_LABEL_END \ - OT_UARRAY(Name##SequenceOffsetsArray, OT_LIST(SequenceOffsets)) \ - ) \ - OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \ - /* ASSERT_STATIC_EXPR len(FromGlyphs) == len(SequenceOffsets) */ - -#define OT_SEQUENCE(Name, SubstituteGlyphs) \ - OT_UARRAY(Name, OT_LIST(SubstituteGlyphs)) - #define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \ OT_SUBLOOKUP(Name, 1, \ OT_OFFSET(Name, Name##Coverage) \