/* State 0: prev was U, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,6}, },
/* State 1: prev was R or ISOL/ALAPH, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN2,5}, {NONE,ISOL,6}, },
/* State 2: prev was D/L in ISOL form, willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {INIT,FINA,1}, {INIT,FINA,3}, {INIT,FINA,4}, {INIT,FINA,6}, },
/* State 3: prev was D in FINA form, willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {MEDI,FINA,1}, {MEDI,FINA,3}, {MEDI,FINA,4}, {MEDI,FINA,6}, },
/* State 4: prev was FINA ALAPH, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {MED2,ISOL,1}, {MED2,ISOL,2}, {MED2,FIN2,5}, {MED2,ISOL,6}, },
/* State 5: prev was FIN2/FIN3 ALAPH, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {ISOL,ISOL,1}, {ISOL,ISOL,2}, {ISOL,FIN2,5}, {ISOL,ISOL,6}, },
/* State 6: prev was DALATH/RISH, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN3,5}, {NONE,ISOL,6}, }
};
/* We apply features according to the Arabic spec, with pauses * in between most. * * The pause between init/medi/... and rlig is required. See eg: * https://bugzilla.mozilla.org/show_bug.cgi?id=644184 * * The pauses between init/medi/... themselves are not necessarily * needed as only one of those features is applied to any character. * The only difference it makes is when fonts have contextual * substitutions. We now follow the order of the spec, which makes * for better experience if that's what Uniscribe is doing. * * At least for Arabic, looks like Uniscribe has a pause between * rlig and calt. Otherwise the IranNastaliq's ALLAH ligature won't * work. However, testing shows that rlig and calt are applied * together for Mongolian in Uniscribe. As such, we only add a * pause for Arabic, not other scripts.
*/
/* Normally, Unicode says a ZWNJ means "don't ligate". In Arabic script * however, it says a ZWJ should also mean "don't ligate". So we run
* the main ligating features as MANUAL_ZWJ. */
/* The spec includes 'cswh'. Earlier versions of Windows * used to enable this by default, but testing suggests * that Windows 8 and later do not enable it by default, * and spec now says 'Off by default'. * We disabled this in ae23c24c32. * Note that IranNastaliq uses this feature extensively * to fixup broken glyph sequences. Oh well...
* Test case: U+0643,U+0640,U+0631. */ //map->enable_feature (HB_TAG('c','s','w','h'), F_MANUAL_ZWJ);
map->enable_feature (HB_TAG('m','s','e','t'), F_MANUAL_ZWJ);
}
#include"hb-ot-shaper-arabic-fallback.hh"
struct arabic_shape_plan_t
{ /* The "+ 1" in the next array is to accommodate for the "NONE" command, * which is not an OpenType feature, but this simplifies the code by not * having to do a "if (... < NONE) ..." and just rely on the fact that
* mask_array[NONE] == 0. */
hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
if (entry->prev_action != NONE && prev != UINT_MAX)
{
info[prev].arabic_shaping_action() = entry->prev_action;
buffer->safe_to_insert_tatweel (prev, i + 1);
} else
{ if (prev == UINT_MAX)
{ if (this_type >= JOINING_TYPE_R)
buffer->unsafe_to_concat_from_outbuffer (0, i + 1);
} else
{ if (this_type >= JOINING_TYPE_R ||
(2 <= state && state <= 5) /* States that have a possible prev_action. */)
buffer->unsafe_to_concat (prev, i + 1);
}
}
retry:
arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan; if (unlikely (!fallback_plan))
{ /* This sucks. We need a font to build the fallback plan... */
fallback_plan = arabic_fallback_plan_create (plan, font); if (unlikely (!arabic_plan->fallback_plan.cmpexch (nullptr, fallback_plan)))
{
arabic_fallback_plan_destroy (fallback_plan); goto retry;
}
}
/* 'stch' feature was just applied. Look for anything that multiplied, * and record it for stch treatment later. Note that rtlm, frac, etc * are applied before stch, but we assume that they didn't result in
* anything multiplying into 5 pieces, so it's safe-ish... */
/* We do a two pass implementation: * First pass calculates the exact number of extra glyphs we need, * We then enlarge buffer to have that much room, * Second pass applies the stretch, copying things to the end of buffer.
*/
int sign = font->x_scale < 0 ? -1 : +1; unsignedint extra_glyphs_needed = 0; // Set during MEASURE, used during CUT enum { MEASURE, CUT } /* step_t */;
hb_position_t w_total = 0; // Total to be filled
hb_position_t w_fixed = 0; // Sum of fixed tiles
hb_position_t w_repeating = 0; // Sum of repeating tiles int n_fixed = 0; int n_repeating = 0;
static hb_codepoint_t
modifier_combining_marks[] =
{
0x0654u, /* ARABIC HAMZA ABOVE */
0x0655u, /* ARABIC HAMZA BELOW */
0x0658u, /* ARABIC MARK NOON GHUNNA */
0x06DCu, /* ARABIC SMALL HIGH SEEN */
0x06E3u, /* ARABIC SMALL LOW SEEN */
0x06E7u, /* ARABIC SMALL HIGH YEH */
0x06E8u, /* ARABIC SMALL HIGH NOON */
0x08CAu, /* ARABIC SMALL HIGH FARSI YEH */
0x08CBu, /* ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW */
0x08CDu, /* ARABIC SMALL HIGH ZAH */
0x08CEu, /* ARABIC LARGE ROUND DOT ABOVE */
0x08CFu, /* ARABIC LARGE ROUND DOT BELOW */
0x08D3u, /* ARABIC SMALL LOW WAW */
0x08F3u, /* ARABIC SMALL HIGH WAW */
};
staticinlinebool
info_is_mcm (const hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint; for (unsignedint i = 0; i < ARRAY_LENGTH (modifier_combining_marks); i++) if (u == modifier_combining_marks[i]) returntrue; returnfalse;
}
DEBUG_MSG (ARABIC, buffer, "Reordering marks from %u to %u", start, end);
unsignedint i = start; for (unsignedint cc = 220; cc <= 230; cc += 10)
{
DEBUG_MSG (ARABIC, buffer, "Looking for %u's starting at %u", cc, i); while (i < end && info_cc(info[i]) < cc)
i++;
DEBUG_MSG (ARABIC, buffer, "Looking for %u's stopped at %u", cc, i);
if (i == end) break;
if (info_cc(info[i]) > cc) continue;
unsignedint j = i; while (j < end && info_cc(info[j]) == cc && info_is_mcm (info[j]))
j++;
if (i == j) continue;
DEBUG_MSG (ARABIC, buffer, "Found %u's from %u to %u", cc, i, j);
/* Renumber CC such that the reordered sequence is still sorted. * 22 and 26 are chosen because they are smaller than all Arabic categories, * and are folded back to 220/230 respectively during fallback mark positioning. * * We do this because the CGJ-handling logic in the normalizer relies on * mark sequences having an increasing order even after this reordering. * https://github.com/harfbuzz/harfbuzz/issues/554 * This, however, does break some obscure sequences, where the normalizer * might compose a sequence that it should not. For example, in the seequence * ALEF, HAMZAH, MADDAH, we should NOT try to compose ALEF+MADDAH, but with this * renumbering, we will.
*/ unsignedint new_start = start + j - i; unsignedint new_cc = cc == 220 ? HB_MODIFIED_COMBINING_CLASS_CCC22 : HB_MODIFIED_COMBINING_CLASS_CCC26; while (start < new_start)
{
_hb_glyph_info_set_modified_combining_class (&info[start], new_cc);
start++;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.