bool gfxScriptItemizer::Next(PRUint32& aRunStart, PRUint32& aRunLimit, PRInt32& aRunScript) { /* if we've fallen off the end of the text, we're done */ if (scriptLimit >= textLength) { return PR_FALSE; } SYNC_FIXUP(); scriptCode = HB_SCRIPT_COMMON; for (scriptStart = scriptLimit; scriptLimit < textLength; scriptLimit += 1) { PRUint32 ch; PRInt32 sc; PRInt32 pairIndex; PRUint32 startOfChar = scriptLimit; ch = textPtr[scriptLimit]; /* * MODIFICATION for Gecko - clear the paired-character stack * when we see a space character, because we cannot trust * context outside the current "word" when doing textrun * construction */ if (ch == 0x20) { while (STACK_IS_NOT_EMPTY()) { pop(); } sc = HB_SCRIPT_COMMON; pairIndex = -1; } else { /* decode UTF-16 (may be surrogate pair) */ if (NS_IS_HIGH_SURROGATE(ch) && scriptLimit < textLength - 1) { PRUint32 low = textPtr[scriptLimit + 1]; if (NS_IS_LOW_SURROGATE(low)) { ch = SURROGATE_TO_UCS4(ch, low); scriptLimit += 1; } } sc = gfxUnicodeProperties::GetScriptCode(ch); pairIndex = getPairIndex(ch); /* * Paired character handling: * * if it's an open character, push it onto the stack. * if it's a close character, find the matching open on the * stack, and use that script code. Any non-matching open * characters above it on the stack will be poped. */ if (pairIndex >= 0) { if ((pairIndex & 1) == 0) { push(pairIndex, scriptCode); } else { PRInt32 pi = pairIndex & ~1; while (STACK_IS_NOT_EMPTY() && TOP().pairIndex != pi) { pop(); } if (STACK_IS_NOT_EMPTY()) { sc = TOP().scriptCode; } } } } if (sameScript(scriptCode, sc)) { if (scriptCode <= HB_SCRIPT_INHERITED && sc > HB_SCRIPT_INHERITED) { scriptCode = sc; fixup(scriptCode); } /* * if this character is a close paired character, * pop the matching open character from the stack */ if (pairIndex >= 0 && (pairIndex & 1) != 0) { pop(); } } else { /* * reset scriptLimit in case it was advanced during reading a * multiple-code-unit character */ scriptLimit = startOfChar; break; } } aRunStart = scriptStart; aRunLimit = scriptLimit; aRunScript = scriptCode; return PR_TRUE; }
bool gfxScriptItemizer::Next(uint32_t& aRunStart, uint32_t& aRunLimit, int32_t& aRunScript) { /* if we've fallen off the end of the text, we're done */ if (scriptLimit >= textLength) { return false; } SYNC_FIXUP(); scriptCode = MOZ_SCRIPT_COMMON; for (scriptStart = scriptLimit; scriptLimit < textLength; scriptLimit += 1) { uint32_t ch; int32_t sc; uint32_t startOfChar = scriptLimit; ch = textPtr[scriptLimit]; /* decode UTF-16 (may be surrogate pair) */ if (NS_IS_HIGH_SURROGATE(ch) && scriptLimit < textLength - 1) { uint32_t low = textPtr[scriptLimit + 1]; if (NS_IS_LOW_SURROGATE(low)) { ch = SURROGATE_TO_UCS4(ch, low); scriptLimit += 1; } } // Get the nsCharProps2 record for the current character, // so we can read the script and (if needed) the gen category // without needing to do two multi-level lookups. // NOTE that this means we're relying on an implementation detail // of the nsUnicodeProperties tables, and might have to revise this // if the nsCharProps records used there are modified in future. const nsCharProps2& charProps = GetCharProps2(ch); // Initialize gc to UNASSIGNED; we'll only set it to the true GC // if the character has script=COMMON, otherwise we don't care. uint8_t gc = HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED; sc = charProps.mScriptCode; if (sc == MOZ_SCRIPT_COMMON) { /* * Paired character handling: * * if it's an open character, push it onto the stack. * if it's a close character, find the matching open on the * stack, and use that script code. Any non-matching open * characters above it on the stack will be popped. * * We only do this if the script is COMMON; for chars with * specific script assignments, we just use them as-is. */ gc = charProps.mCategory; if (gc == HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION) { uint32_t endPairChar = mozilla::unicode::GetMirroredChar(ch); if (endPairChar != ch) { push(endPairChar, scriptCode); } } else if (gc == HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION && HasMirroredChar(ch)) { while (STACK_IS_NOT_EMPTY() && TOP().endPairChar != ch) { pop(); } if (STACK_IS_NOT_EMPTY()) { sc = TOP().scriptCode; } } } if (SameScript(scriptCode, sc)) { if (scriptCode <= MOZ_SCRIPT_INHERITED && sc > MOZ_SCRIPT_INHERITED) { scriptCode = sc; fixup(scriptCode); } /* * if this character is a close paired character, * pop the matching open character from the stack */ if (gc == HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION && HasMirroredChar(ch)) { pop(); } } else { /* * reset scriptLimit in case it was advanced during reading a * multiple-code-unit character */ scriptLimit = startOfChar; break; } } aRunStart = scriptStart; aRunLimit = scriptLimit; aRunScript = scriptCode; return true; }