bug 449292 - part 5 - break text into script runs before font-matching and shaping. r=jdaggett sr=roc

This commit is contained in:
Jonathan Kew 2010-06-11 20:14:38 +01:00
Родитель 5754ac6b39
Коммит 37f3b9fe59
12 изменённых файлов: 66 добавлений и 37 удалений

Просмотреть файл

@ -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<gfxFontEntry> 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.
*

Просмотреть файл

@ -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

Просмотреть файл

@ -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();

Просмотреть файл

@ -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

Просмотреть файл

@ -61,7 +61,8 @@ public:
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength);
PRUint32 aRunLength,
PRInt32 aRunScript);
};
#endif /* GFX_DWRITESHAPER_H */

Просмотреть файл

@ -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<gfxTextRange,3> fontRanges;
ComputeRanges(fontRanges, aString, 0, aLength);
ComputeRanges(fontRanges, aString, aScriptRunStart, aScriptRunEnd);
PRUint32 numRanges = fontRanges.Length();
nsAutoTArray<PRPackedBool,SMALL_GLYPH_RUN> 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;

Просмотреть файл

@ -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<GDIFontEntry*>(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");

Просмотреть файл

@ -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

Просмотреть файл

@ -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<gfxGDIFont*>(mFont);
DCFromContext dc(aContext);

Просмотреть файл

@ -58,7 +58,8 @@ public:
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength);
PRUint32 aRunLength,
PRInt32 aRunScript);
};
#endif /* GFX_GDISHAPER_H */

Просмотреть файл

@ -551,7 +551,8 @@ gfxUniscribeShaper::InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength)
PRUint32 aRunLength,
PRInt32 aRunScript)
{
DCFromContext aDC(aContext);

Просмотреть файл

@ -68,7 +68,8 @@ public:
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength);
PRUint32 aRunLength,
PRInt32 aRunScript);
SCRIPT_CACHE *ScriptCache() { return &mScriptCache; }