mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 606714 - shape long text runs in sections. r=jdaggett a=blocking2.0
This commit is contained in:
parent
1d73ebe076
commit
94c89c69d7
@ -1300,21 +1300,78 @@ 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)
|
||||
PRInt32 aRunScript,
|
||||
PRBool aPreferPlatformShaping)
|
||||
{
|
||||
PRBool ok = PR_FALSE;
|
||||
PRBool ok;
|
||||
|
||||
if (mHarfBuzzShaper) {
|
||||
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 && !aPreferPlatformShaping) {
|
||||
if (gfxPlatform::GetPlatform()->UseHarfBuzzLevel() >=
|
||||
gfxUnicodeProperties::ScriptShapingLevel(aRunScript)) {
|
||||
ok = mHarfBuzzShaper->InitTextRun(aContext, aTextRun, aString,
|
||||
aRunStart, aRunLength, aRunScript);
|
||||
aRunStart, thisRunLength,
|
||||
aRunScript);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1325,10 +1382,15 @@ gfxFont::InitTextRun(gfxContext *aContext,
|
||||
}
|
||||
if (mPlatformShaper) {
|
||||
ok = mPlatformShaper->InitTextRun(aContext, aTextRun, aString,
|
||||
aRunStart, aRunLength, aRunScript);
|
||||
aRunStart, thisRunLength,
|
||||
aRunScript);
|
||||
}
|
||||
}
|
||||
|
||||
aRunStart += thisRunLength;
|
||||
aRunLength -= thisRunLength;
|
||||
} while (ok && aRunLength > 0);
|
||||
|
||||
NS_WARN_IF_FALSE(ok, "shaper failed, expect scrambled or missing text");
|
||||
return ok;
|
||||
}
|
||||
|
@ -1136,7 +1136,8 @@ public:
|
||||
const PRUnichar *aString,
|
||||
PRUint32 aRunStart,
|
||||
PRUint32 aRunLength,
|
||||
PRInt32 aRunScript);
|
||||
PRInt32 aRunScript,
|
||||
PRBool aPreferPlatformShaping = PR_FALSE);
|
||||
|
||||
protected:
|
||||
nsRefPtr<gfxFontEntry> mFontEntry;
|
||||
|
@ -142,7 +142,8 @@ gfxGDIFont::InitTextRun(gfxContext *aContext,
|
||||
const PRUnichar *aString,
|
||||
PRUint32 aRunStart,
|
||||
PRUint32 aRunLength,
|
||||
PRInt32 aRunScript)
|
||||
PRInt32 aRunScript,
|
||||
PRBool aPreferPlatformShaping)
|
||||
{
|
||||
if (!mMetrics) {
|
||||
Initialize();
|
||||
|
@ -82,7 +82,8 @@ public:
|
||||
const PRUnichar *aString,
|
||||
PRUint32 aRunStart,
|
||||
PRUint32 aRunLength,
|
||||
PRInt32 aRunScript);
|
||||
PRInt32 aRunScript,
|
||||
PRBool aPreferPlatformShaping = PR_FALSE);
|
||||
|
||||
virtual PRBool ProvidesHintedWidths() const { return PR_TRUE; }
|
||||
|
||||
|
@ -159,54 +159,17 @@ gfxMacFont::InitTextRun(gfxContext *aContext,
|
||||
const PRUnichar *aString,
|
||||
PRUint32 aRunStart,
|
||||
PRUint32 aRunLength,
|
||||
PRInt32 aRunScript)
|
||||
PRInt32 aRunScript,
|
||||
PRBool aPreferPlatformShaping)
|
||||
{
|
||||
if (!mIsValid) {
|
||||
NS_WARNING("invalid font! expect incorrect text rendering");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool ok = PR_FALSE;
|
||||
|
||||
if (mHarfBuzzShaper &&
|
||||
!static_cast<MacOSFontEntry*>(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
|
||||
}
|
||||
PRBool ok = gfxFont::InitTextRun(aContext, aTextRun, aString,
|
||||
aRunStart, aRunLength, aRunScript,
|
||||
static_cast<MacOSFontEntry*>(GetFontEntry())->RequiresAATLayout());
|
||||
|
||||
aTextRun->AdjustAdvancesForSyntheticBold(aRunStart, aRunLength);
|
||||
|
||||
|
@ -62,7 +62,8 @@ public:
|
||||
const PRUnichar *aString,
|
||||
PRUint32 aRunStart,
|
||||
PRUint32 aRunLength,
|
||||
PRInt32 aRunScript);
|
||||
PRInt32 aRunScript,
|
||||
PRBool aPreferPlatformShaping = PR_FALSE);
|
||||
|
||||
/* overrides for the pure virtual methods in gfxFont */
|
||||
virtual const gfxFont::Metrics& GetMetrics() {
|
||||
|
@ -536,7 +536,8 @@ public:
|
||||
const PRUnichar *aString,
|
||||
PRUint32 aRunStart,
|
||||
PRUint32 aRunLength,
|
||||
PRInt32 aRunScript);
|
||||
PRInt32 aRunScript,
|
||||
PRBool aPreferPlatformShaping);
|
||||
|
||||
#if defined(ENABLE_FAST_PATH_8BIT)
|
||||
nsresult InitGlyphRunFast(gfxTextRun *aTextRun, const PRUnichar *aString,
|
||||
@ -1918,7 +1919,8 @@ gfxFcFont::InitTextRun(gfxContext *aContext,
|
||||
const PRUnichar *aString,
|
||||
PRUint32 aRunStart,
|
||||
PRUint32 aRunLength,
|
||||
PRInt32 aRunScript)
|
||||
PRInt32 aRunScript,
|
||||
PRBool aPreferPlatformShaping)
|
||||
{
|
||||
PRBool useFastPath = PR_FALSE;
|
||||
#if defined(ENABLE_FAST_PATH_8BIT)
|
||||
|
Loading…
Reference in New Issue
Block a user