diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index a11296d097a..23b98b9684d 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -1300,96 +1300,34 @@ gfxFont::Measure(gfxTextRun *aTextRun, return metrics; } -#define MAX_SHAPING_LENGTH 32760 // slightly less than 32K, trying to avoid - // over-stressing platform shapers - -#define BACKTRACK_LIMIT 1024 // If we can't find a space or a cluster start - // within 1K chars, just chop arbitrarily. - // Limiting backtrack here avoids pathological - // behavior on long runs with no whitespace. - PRBool gfxFont::InitTextRun(gfxContext *aContext, gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, PRUint32 aRunLength, - PRInt32 aRunScript, - PRBool aPreferPlatformShaping) + PRInt32 aRunScript) { - PRBool ok; + PRBool ok = PR_FALSE; - do { - // Because various shaping backends struggle with very long runs, - // we look for appropriate break locations (preferring whitespace), - // and shape sub-runs of no more than 32K characters at a time. - // See bug 606714 (CoreText), and similar Uniscribe issues. - // This loop always executes at least once, and "processes" up to - // MAX_RUN_LENGTH_FOR_SHAPING characters, updating aRunStart and - // aRunLength accordingly. It terminates when the entire run has - // been processed, or when shaping fails. - - PRUint32 thisRunLength; - ok = PR_FALSE; - - if (aRunLength <= MAX_SHAPING_LENGTH) { - thisRunLength = aRunLength; - } else { - // We're splitting this font run because it's very long - PRUint32 offset = aRunStart + MAX_SHAPING_LENGTH; - PRUint32 clusterStart = 0; - while (offset > aRunStart + MAX_SHAPING_LENGTH - BACKTRACK_LIMIT) { - if (aTextRun->IsClusterStart(offset)) { - if (!clusterStart) { - clusterStart = offset; - } - if (aString[offset] == ' ' || aString[offset - 1] == ' ') { - break; - } - } - --offset; - } - - if (offset > MAX_SHAPING_LENGTH - BACKTRACK_LIMIT) { - // we found a space, so break the run there - thisRunLength = offset - aRunStart; - } else if (clusterStart != 0) { - // didn't find a space, but we found a cluster start - thisRunLength = clusterStart - aRunStart; - } else { - // otherwise we'll simply break at MAX_SHAPING_LENGTH chars, - // which may interfere with shaping behavior (but in practice - // only pathological cases will lack ANY whitespace or cluster - // boundaries, so we don't really care; it won't affect any - // "real" text) - thisRunLength = MAX_SHAPING_LENGTH; - } + if (mHarfBuzzShaper) { + if (gfxPlatform::GetPlatform()->UseHarfBuzzLevel() >= + gfxUnicodeProperties::ScriptShapingLevel(aRunScript)) { + ok = mHarfBuzzShaper->InitTextRun(aContext, aTextRun, aString, + aRunStart, aRunLength, aRunScript); } + } - if (mHarfBuzzShaper && !aPreferPlatformShaping) { - if (gfxPlatform::GetPlatform()->UseHarfBuzzLevel() >= - gfxUnicodeProperties::ScriptShapingLevel(aRunScript)) { - ok = mHarfBuzzShaper->InitTextRun(aContext, aTextRun, aString, - aRunStart, thisRunLength, - aRunScript); - } + if (!ok) { + if (!mPlatformShaper) { + CreatePlatformShaper(); + NS_ASSERTION(mPlatformShaper, "no platform shaper available!"); } - - if (!ok) { - if (!mPlatformShaper) { - CreatePlatformShaper(); - NS_ASSERTION(mPlatformShaper, "no platform shaper available!"); - } - if (mPlatformShaper) { - ok = mPlatformShaper->InitTextRun(aContext, aTextRun, aString, - aRunStart, thisRunLength, - aRunScript); - } + if (mPlatformShaper) { + ok = mPlatformShaper->InitTextRun(aContext, aTextRun, aString, + aRunStart, aRunLength, aRunScript); } - - aRunStart += thisRunLength; - aRunLength -= thisRunLength; - } while (ok && aRunLength > 0); + } NS_WARN_IF_FALSE(ok, "shaper failed, expect scrambled or missing text"); return ok; diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 980dc39b8e4..3b9fd312169 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -1136,8 +1136,7 @@ public: const PRUnichar *aString, PRUint32 aRunStart, PRUint32 aRunLength, - PRInt32 aRunScript, - PRBool aPreferPlatformShaping = PR_FALSE); + PRInt32 aRunScript); protected: nsRefPtr mFontEntry; diff --git a/gfx/thebes/gfxGDIFont.cpp b/gfx/thebes/gfxGDIFont.cpp index ff7e84c4e7b..1181f9fcd97 100644 --- a/gfx/thebes/gfxGDIFont.cpp +++ b/gfx/thebes/gfxGDIFont.cpp @@ -142,8 +142,7 @@ gfxGDIFont::InitTextRun(gfxContext *aContext, const PRUnichar *aString, PRUint32 aRunStart, PRUint32 aRunLength, - PRInt32 aRunScript, - PRBool aPreferPlatformShaping) + PRInt32 aRunScript) { if (!mMetrics) { Initialize(); diff --git a/gfx/thebes/gfxGDIFont.h b/gfx/thebes/gfxGDIFont.h index b1366bc14a9..4c2cc5563ef 100644 --- a/gfx/thebes/gfxGDIFont.h +++ b/gfx/thebes/gfxGDIFont.h @@ -82,8 +82,7 @@ public: const PRUnichar *aString, PRUint32 aRunStart, PRUint32 aRunLength, - PRInt32 aRunScript, - PRBool aPreferPlatformShaping = PR_FALSE); + PRInt32 aRunScript); virtual PRBool ProvidesHintedWidths() const { return PR_TRUE; } diff --git a/gfx/thebes/gfxMacFont.cpp b/gfx/thebes/gfxMacFont.cpp index 1da12ab6175..57445baf223 100644 --- a/gfx/thebes/gfxMacFont.cpp +++ b/gfx/thebes/gfxMacFont.cpp @@ -159,17 +159,54 @@ gfxMacFont::InitTextRun(gfxContext *aContext, const PRUnichar *aString, PRUint32 aRunStart, PRUint32 aRunLength, - PRInt32 aRunScript, - PRBool aPreferPlatformShaping) + PRInt32 aRunScript) { if (!mIsValid) { NS_WARNING("invalid font! expect incorrect text rendering"); return PR_FALSE; } - PRBool ok = gfxFont::InitTextRun(aContext, aTextRun, aString, - aRunStart, aRunLength, aRunScript, - static_cast(GetFontEntry())->RequiresAATLayout()); + PRBool ok = PR_FALSE; + + if (mHarfBuzzShaper && + !static_cast(GetFontEntry())->RequiresAATLayout()) + { + if (gfxPlatform::GetPlatform()->UseHarfBuzzLevel() >= + gfxUnicodeProperties::ScriptShapingLevel(aRunScript)) { + ok = mHarfBuzzShaper->InitTextRun(aContext, aTextRun, aString, + aRunStart, aRunLength, + aRunScript); +#if DEBUG + if (!ok) { + NS_ConvertUTF16toUTF8 name(GetName()); + char msg[256]; + sprintf(msg, "HarfBuzz shaping failed for font: %s", + name.get()); + NS_WARNING(msg); + } +#endif + } + } + + if (!ok) { + // fallback to Core Text shaping + if (!mPlatformShaper) { + CreatePlatformShaper(); + } + + ok = mPlatformShaper->InitTextRun(aContext, aTextRun, aString, + aRunStart, aRunLength, + aRunScript); +#if DEBUG + if (!ok) { + NS_ConvertUTF16toUTF8 name(GetName()); + char msg[256]; + sprintf(msg, "Core Text shaping failed for font: %s", + name.get()); + NS_WARNING(msg); + } +#endif + } aTextRun->AdjustAdvancesForSyntheticBold(aRunStart, aRunLength); diff --git a/gfx/thebes/gfxMacFont.h b/gfx/thebes/gfxMacFont.h index 4d8a9957f81..b1320c980f1 100644 --- a/gfx/thebes/gfxMacFont.h +++ b/gfx/thebes/gfxMacFont.h @@ -62,8 +62,7 @@ public: const PRUnichar *aString, PRUint32 aRunStart, PRUint32 aRunLength, - PRInt32 aRunScript, - PRBool aPreferPlatformShaping = PR_FALSE); + PRInt32 aRunScript); /* overrides for the pure virtual methods in gfxFont */ virtual const gfxFont::Metrics& GetMetrics() {