diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h index 4c45984e1b4e..9d411df532f7 100644 --- a/gfx/thebes/public/gfxFont.h +++ b/gfx/thebes/public/gfxFont.h @@ -675,7 +675,8 @@ public: gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength) = 0; + PRUint32 aRunLength, + PRInt32 aRunScript) = 0; protected: // the font this shaper is working with @@ -949,7 +950,8 @@ public: gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength); + PRUint32 aRunLength, + PRInt32 aRunScript); protected: nsRefPtr mFontEntry; @@ -1946,11 +1948,22 @@ protected: // you should call this with the *first* bad font. void InitMetricsForBadFont(gfxFont* aBadFont); + // Set up the textrun glyphs, by finding script and font ranges + // and calling each font's InitTextRun() as appropriate void InitTextRun(gfxContext *aContext, gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aLength); + // InitTextRun helper to handle a single script run + void InitTextRun(gfxContext *aContext, + gfxTextRun *aTextRun, + const PRUnichar *aString, + PRUint32 aTotalLength, + PRUint32 aScriptRunStart, + PRUint32 aScriptRunEnd, + PRInt32 aRunScript); + /* If aResolveGeneric is true, then CSS/Gecko generic family names are * replaced with preferred fonts. * diff --git a/gfx/thebes/src/gfxCoreTextShaper.cpp b/gfx/thebes/src/gfxCoreTextShaper.cpp index a5c1ea854405..115308b181ac 100644 --- a/gfx/thebes/src/gfxCoreTextShaper.cpp +++ b/gfx/thebes/src/gfxCoreTextShaper.cpp @@ -107,7 +107,8 @@ gfxCoreTextShaper::InitTextRun(gfxContext *aContext, gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength) + PRUint32 aRunLength, + PRInt32 aRunScript) { // aRunStart and aRunLength define the section of the textRun and of aString // that is to be drawn with this particular font diff --git a/gfx/thebes/src/gfxCoreTextShaper.h b/gfx/thebes/src/gfxCoreTextShaper.h index c89d5c42def8..678507c252d5 100644 --- a/gfx/thebes/src/gfxCoreTextShaper.h +++ b/gfx/thebes/src/gfxCoreTextShaper.h @@ -61,7 +61,8 @@ public: gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength); + PRUint32 aRunLength, + PRInt32 aRunScript); // clean up static objects that may have been cached static void Shutdown(); diff --git a/gfx/thebes/src/gfxDWriteShaper.cpp b/gfx/thebes/src/gfxDWriteShaper.cpp index fa0a401fc23c..db273c76f58c 100644 --- a/gfx/thebes/src/gfxDWriteShaper.cpp +++ b/gfx/thebes/src/gfxDWriteShaper.cpp @@ -50,7 +50,8 @@ gfxDWriteShaper::InitTextRun(gfxContext *aContext, gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength) + PRUint32 aRunLength, + PRInt32 aRunScript) { HRESULT hr; // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES diff --git a/gfx/thebes/src/gfxDWriteShaper.h b/gfx/thebes/src/gfxDWriteShaper.h index 2d641d14bde9..bbc2a3ce5728 100644 --- a/gfx/thebes/src/gfxDWriteShaper.h +++ b/gfx/thebes/src/gfxDWriteShaper.h @@ -61,7 +61,8 @@ public: gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength); + PRUint32 aRunLength, + PRInt32 aRunScript); }; #endif /* GFX_DWRITESHAPER_H */ diff --git a/gfx/thebes/src/gfxFont.cpp b/gfx/thebes/src/gfxFont.cpp index d15fe1b5866b..7bec500ead7c 100644 --- a/gfx/thebes/src/gfxFont.cpp +++ b/gfx/thebes/src/gfxFont.cpp @@ -54,6 +54,7 @@ #include "gfxFontMissingGlyphs.h" #include "gfxUserFontSet.h" #include "gfxPlatformFontList.h" +#include "gfxScriptItemizer.h" #include "nsMathUtils.h" #include "nsBidiUtils.h" #include "nsUnicodeRange.h" @@ -1250,7 +1251,8 @@ gfxFont::InitTextRun(gfxContext *aContext, gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength) + PRUint32 aRunLength, + PRInt32 aRunScript) { NS_ASSERTION(mShaper != nsnull, "no shaper?!"); if (!mShaper) { @@ -1258,7 +1260,7 @@ gfxFont::InitTextRun(gfxContext *aContext, } PRBool ok = mShaper->InitTextRun(aContext, aTextRun, aString, - aRunStart, aRunLength); + aRunStart, aRunLength, aRunScript); NS_WARN_IF_FALSE(ok, "shaper failed, expect scrambled or missing text"); } @@ -1965,17 +1967,35 @@ gfxFontGroup::InitTextRun(gfxContext *aContext, gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aLength) +{ + // split into script runs so that script can potentially influence + // the font matching process below + gfxScriptItemizer scriptRuns(aString, aLength); + + PRUint32 runStart = 0, runLimit = aLength; + PRInt32 runScript = HB_SCRIPT_LATIN; + while (scriptRuns.Next(runStart, runLimit, runScript)) { + InitTextRun(aContext, aTextRun, aString, aLength, + runStart, runLimit, runScript); + } +} + +void +gfxFontGroup::InitTextRun(gfxContext *aContext, + gfxTextRun *aTextRun, + const PRUnichar *aString, + PRUint32 aTotalLength, + PRUint32 aScriptRunStart, + PRUint32 aScriptRunEnd, + PRInt32 aRunScript) { gfxFont *mainFont = mFonts[0].get(); - PRUint32 runStart = 0; + PRUint32 runStart = aScriptRunStart; nsAutoTArray fontRanges; - ComputeRanges(fontRanges, aString, 0, aLength); + ComputeRanges(fontRanges, aString, aScriptRunStart, aScriptRunEnd); PRUint32 numRanges = fontRanges.Length(); - nsAutoTArray unmatchedArray; - PRPackedBool *unmatched = NULL; - for (PRUint32 r = 0; r < numRanges; r++) { const gfxTextRange& range = fontRanges[r]; PRUint32 matchedLength = range.Length(); @@ -1987,23 +2007,15 @@ gfxFontGroup::InitTextRun(gfxContext *aContext, // do glyph layout and record the resulting positioned glyphs matchedFont->InitTextRun(aContext, aTextRun, aString, - runStart, matchedLength); + runStart, matchedLength, aRunScript); } else { - // no font available, so record missing glyph info instead - if (unmatched == NULL) { - if (unmatchedArray.SetLength(aLength)) { - unmatched = unmatchedArray.Elements(); - ::memset(unmatched, PR_FALSE, aLength*sizeof(PRPackedBool)); - } - } - // create the glyph run before calling SetMissing Glyph aTextRun->AddGlyphRun(mainFont, runStart, matchedLength); for (PRUint32 index = runStart; index < runStart + matchedLength; index++) { // Record the char code so we can draw a box with the Unicode value if (NS_IS_HIGH_SURROGATE(aString[index]) && - index + 1 < aLength && + index + 1 < aScriptRunEnd && NS_IS_LOW_SURROGATE(aString[index+1])) { aTextRun->SetMissingGlyph(index, SURROGATE_TO_UCS4(aString[index], @@ -2013,12 +2025,6 @@ gfxFontGroup::InitTextRun(gfxContext *aContext, aTextRun->SetMissingGlyph(index, aString[index]); } } - - // We have to remember the indices of unmatched chars to avoid overwriting - // their glyph (actually char code) data with the space glyph later, - // while we're retrieving actual glyph data from CoreText runs. - if (unmatched) - ::memset(unmatched + runStart, PR_TRUE, matchedLength); } runStart += matchedLength; diff --git a/gfx/thebes/src/gfxGDIFont.cpp b/gfx/thebes/src/gfxGDIFont.cpp index ab38f78113c5..b381cd9bd67e 100644 --- a/gfx/thebes/src/gfxGDIFont.cpp +++ b/gfx/thebes/src/gfxGDIFont.cpp @@ -111,7 +111,8 @@ gfxGDIFont::InitTextRun(gfxContext *aContext, gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength) + PRUint32 aRunLength, + PRInt32 aRunScript) { if (!mMetrics) { Initialize(); @@ -121,7 +122,7 @@ gfxGDIFont::InitTextRun(gfxContext *aContext, return; } PRBool ok = mShaper->InitTextRun(aContext, aTextRun, aString, - aRunStart, aRunLength); + aRunStart, aRunLength, aRunScript); if (!ok) { // shaping failed; if we were using uniscribe, fall back to GDI GDIFontEntry *fe = static_cast(GetFontEntry()); @@ -130,7 +131,7 @@ gfxGDIFont::InitTextRun(gfxContext *aContext, fe->mForceGDI = PR_TRUE; mShaper = new gfxGDIShaper(this); ok = mShaper->InitTextRun(aContext, aTextRun, aString, - aRunStart, aRunLength); + aRunStart, aRunLength, aRunScript); } } NS_WARN_IF_FALSE(ok, "shaper failed, expect broken or missing text"); diff --git a/gfx/thebes/src/gfxGDIFont.h b/gfx/thebes/src/gfxGDIFont.h index 68633c571e8b..ae50391d0e8e 100644 --- a/gfx/thebes/src/gfxGDIFont.h +++ b/gfx/thebes/src/gfxGDIFont.h @@ -78,7 +78,8 @@ public: gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength); + PRUint32 aRunLength, + PRInt32 aRunScript); protected: void Initialize(); // creates metrics and Cairo fonts diff --git a/gfx/thebes/src/gfxGDIShaper.cpp b/gfx/thebes/src/gfxGDIShaper.cpp index 58071870732b..bfa7cfefc0d1 100644 --- a/gfx/thebes/src/gfxGDIShaper.cpp +++ b/gfx/thebes/src/gfxGDIShaper.cpp @@ -54,7 +54,8 @@ gfxGDIShaper::InitTextRun(gfxContext *aContext, gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength) + PRUint32 aRunLength, + PRInt32 aRunScript) { gfxGDIFont *f = static_cast(mFont); DCFromContext dc(aContext); diff --git a/gfx/thebes/src/gfxGDIShaper.h b/gfx/thebes/src/gfxGDIShaper.h index 9faac8446046..bee182493cfb 100644 --- a/gfx/thebes/src/gfxGDIShaper.h +++ b/gfx/thebes/src/gfxGDIShaper.h @@ -58,7 +58,8 @@ public: gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength); + PRUint32 aRunLength, + PRInt32 aRunScript); }; #endif /* GFX_GDISHAPER_H */ diff --git a/gfx/thebes/src/gfxUniscribeShaper.cpp b/gfx/thebes/src/gfxUniscribeShaper.cpp index 04b3269f96f5..63dda2c7d6d2 100644 --- a/gfx/thebes/src/gfxUniscribeShaper.cpp +++ b/gfx/thebes/src/gfxUniscribeShaper.cpp @@ -551,7 +551,8 @@ gfxUniscribeShaper::InitTextRun(gfxContext *aContext, gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength) + PRUint32 aRunLength, + PRInt32 aRunScript) { DCFromContext aDC(aContext); diff --git a/gfx/thebes/src/gfxUniscribeShaper.h b/gfx/thebes/src/gfxUniscribeShaper.h index d810846ca4c6..5ac839a3e319 100644 --- a/gfx/thebes/src/gfxUniscribeShaper.h +++ b/gfx/thebes/src/gfxUniscribeShaper.h @@ -68,7 +68,8 @@ public: gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aRunStart, - PRUint32 aRunLength); + PRUint32 aRunLength, + PRInt32 aRunScript); SCRIPT_CACHE *ScriptCache() { return &mScriptCache; }