зеркало из https://github.com/mozilla/pjs.git
Bug 380484. Work around ATSUI's 32k pixel limitation; when creating textruns, split the textrun up into smaller pieces if necessary before we pass it to ATSUI. r=vlad
This commit is contained in:
Родитель
1229e4399d
Коммит
45323b4ff4
|
@ -128,8 +128,11 @@ protected:
|
|||
const nsACString& aGenericName,
|
||||
void *closure);
|
||||
|
||||
void InitTextRun(gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength,
|
||||
PRBool aWrapped);
|
||||
PRUint32 GuessMaximumStringLength();
|
||||
|
||||
/** Returns true for success */
|
||||
PRBool InitTextRun(gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength,
|
||||
PRBool aWrapped, PRUint32 aSegmentStart, PRUint32 aSegmentLength);
|
||||
|
||||
ATSUFontFallbacks mFallbacks;
|
||||
};
|
||||
|
|
|
@ -422,21 +422,6 @@ SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString)
|
|||
UCDisposeTextBreakLocator(&locator);
|
||||
}
|
||||
|
||||
void
|
||||
gfxAtsuiFontGroup::MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLength,
|
||||
PRBool aWrapped, gfxTextRun *aTextRun)
|
||||
{
|
||||
// NS_ASSERTION(!(aParams->mFlags & TEXT_NEED_BOUNDING_BOX),
|
||||
// "Glyph extents not yet supported");
|
||||
const PRUnichar *realString = aString + (aWrapped ? 1 : 0);
|
||||
aTextRun->RecordSurrogates(realString);
|
||||
if (!(aTextRun->GetFlags() & TEXT_IS_8BIT)) {
|
||||
SetupClusterBoundaries(aTextRun, realString);
|
||||
}
|
||||
|
||||
InitTextRun(aTextRun, aString, aLength, aWrapped);
|
||||
}
|
||||
|
||||
#define UNICODE_LRO 0x202d
|
||||
#define UNICODE_RLO 0x202e
|
||||
#define UNICODE_PDF 0x202c
|
||||
|
@ -448,6 +433,70 @@ AppendDirectionalIndicator(PRUint32 aFlags, nsAString& aString)
|
|||
aString.Append(overrides[(aFlags & gfxTextRunFactory::TEXT_IS_RTL) != 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a textrun and an offset into that textrun, we need to choose a length
|
||||
* for the substring of the textrun that we should analyze next. The length
|
||||
* should be <= aMaxLength if possible. It must always end at a cluster
|
||||
* boundary and it should end at the end of the textrun or at the
|
||||
* boundary of a space if possible.
|
||||
*/
|
||||
static PRUint32
|
||||
FindTextRunSegmentLength(gfxTextRun *aTextRun, PRUint32 aOffset, PRUint32 aMaxLength)
|
||||
{
|
||||
if (aOffset + aMaxLength >= aTextRun->GetLength()) {
|
||||
// The remaining part of the textrun fits within the max length,
|
||||
// so just use it.
|
||||
return aTextRun->GetLength() - aOffset;
|
||||
}
|
||||
|
||||
// Try to end the segment before or after a space, since spaces don't kern
|
||||
// or ligate.
|
||||
PRUint32 end;
|
||||
for (end = aOffset + aMaxLength; end > aOffset; --end) {
|
||||
if (aTextRun->IsClusterStart(end) &&
|
||||
(aTextRun->GetChar(end) == ' ' || aTextRun->GetChar(end - 1) == ' '))
|
||||
return end - aOffset;
|
||||
}
|
||||
|
||||
// Try to end the segment at the last cluster boundary.
|
||||
for (end = aOffset + aMaxLength; end > aOffset; --end) {
|
||||
if (aTextRun->IsClusterStart(end))
|
||||
return end - aOffset;
|
||||
}
|
||||
|
||||
// I guess we just have to return a segment that's the entire cluster
|
||||
// starting at aOffset.
|
||||
for (end = aOffset + 1; end < aTextRun->GetLength(); ++end) {
|
||||
if (aTextRun->IsClusterStart(end))
|
||||
return end - aOffset;
|
||||
}
|
||||
return aTextRun->GetLength() - aOffset;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
gfxAtsuiFontGroup::GuessMaximumStringLength()
|
||||
{
|
||||
gfxFloat maxAdvance = GetFontAt(0)->GetMetrics().maxAdvance;
|
||||
// ATSUI can't handle offsets of more than 32K pixels
|
||||
PRUint32 chars = 0x7FFF/PRUint32(maxAdvance);
|
||||
return PR_MAX(1, chars);
|
||||
}
|
||||
|
||||
/*
|
||||
* ATSUI can't handle more than 32K pixels of text. We can easily have
|
||||
* textruns longer than that. Our strategy here is to divide the textrun up
|
||||
* into pieces each of which is less than 32K pixels wide. We pick a number
|
||||
* of characters 'maxLen' such that the first font's max-advance times that
|
||||
* number of characters is less than 32K pixels; then we try glyph conversion
|
||||
* of the string broken up into chunks each with no more than 'maxLen'
|
||||
* characters. That could fail (e.g. if fallback fonts are used); if it does,
|
||||
* we retry with a smaller maxLen. When breaking up the string into chunks
|
||||
* we prefer to break at space boundaries because spaces don't kern or ligate
|
||||
* with other characters, usually. We insist on breaking at cluster boundaries.
|
||||
* If the font size is incredibly huge and/or clusters are very large, this
|
||||
* could mean that we actually put more than 'maxLen' characters in a chunk.
|
||||
*/
|
||||
|
||||
gfxTextRun *
|
||||
gfxAtsuiFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
const Parameters *aParams, PRUint32 aFlags)
|
||||
|
@ -456,14 +505,33 @@ gfxAtsuiFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
|||
if (!textRun)
|
||||
return nsnull;
|
||||
|
||||
textRun->RecordSurrogates(aString);
|
||||
SetupClusterBoundaries(textRun, aString);
|
||||
|
||||
PRUint32 maxLen;
|
||||
nsAutoString utf16;
|
||||
AppendDirectionalIndicator(aFlags, utf16);
|
||||
utf16.Append(aString, aLength);
|
||||
// Ensure that none of the whitespace in the run is considered "trailing"
|
||||
// by ATSUI's bidi algorithm
|
||||
utf16.Append('.');
|
||||
utf16.Append(UNICODE_PDF);
|
||||
MakeTextRunInternal(utf16.get(), utf16.Length(), PR_TRUE, textRun);
|
||||
for (maxLen = GuessMaximumStringLength(); maxLen > 0; maxLen /= 2) {
|
||||
PRUint32 start = 0;
|
||||
while (start < aLength) {
|
||||
PRUint32 len = FindTextRunSegmentLength(textRun, start, maxLen);
|
||||
|
||||
utf16.Truncate();
|
||||
AppendDirectionalIndicator(aFlags, utf16);
|
||||
utf16.Append(aString + start, len);
|
||||
// Ensure that none of the whitespace in the run is considered "trailing"
|
||||
// by ATSUI's bidi algorithm
|
||||
utf16.Append('.');
|
||||
utf16.Append(UNICODE_PDF);
|
||||
if (!InitTextRun(textRun, utf16.get(), utf16.Length(), PR_TRUE,
|
||||
start, len) && maxLen > 1)
|
||||
break;
|
||||
start += len;
|
||||
}
|
||||
if (start == aLength)
|
||||
break;
|
||||
textRun->ResetGlyphRuns();
|
||||
}
|
||||
|
||||
return textRun;
|
||||
}
|
||||
|
||||
|
@ -476,19 +544,35 @@ gfxAtsuiFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
|||
if (!textRun)
|
||||
return nsnull;
|
||||
|
||||
nsDependentCSubstring cString(reinterpret_cast<const char*>(aString),
|
||||
reinterpret_cast<const char*>(aString + aLength));
|
||||
PRUint32 maxLen;
|
||||
nsAutoString utf16;
|
||||
PRBool wrapBidi = (aFlags & TEXT_IS_RTL) != 0;
|
||||
if (wrapBidi) {
|
||||
AppendDirectionalIndicator(aFlags, utf16);
|
||||
for (maxLen = GuessMaximumStringLength(); maxLen > 0; maxLen /= 2) {
|
||||
PRUint32 start = 0;
|
||||
while (start < aLength) {
|
||||
PRUint32 len = FindTextRunSegmentLength(textRun, start, maxLen);
|
||||
|
||||
nsDependentCSubstring cString(reinterpret_cast<const char*>(aString + start),
|
||||
reinterpret_cast<const char*>(aString + start + len));
|
||||
utf16.Truncate();
|
||||
PRBool wrapBidi = (aFlags & TEXT_IS_RTL) != 0;
|
||||
if (wrapBidi) {
|
||||
AppendDirectionalIndicator(aFlags, utf16);
|
||||
}
|
||||
AppendASCIItoUTF16(cString, utf16);
|
||||
if (wrapBidi) {
|
||||
utf16.Append('.');
|
||||
utf16.Append(UNICODE_PDF);
|
||||
}
|
||||
if (!InitTextRun(textRun, utf16.get(), utf16.Length(), wrapBidi,
|
||||
start, len) && maxLen > 1)
|
||||
break;
|
||||
start += len;
|
||||
}
|
||||
if (start == aLength)
|
||||
break;
|
||||
textRun->ResetGlyphRuns();
|
||||
}
|
||||
AppendASCIItoUTF16(cString, utf16);
|
||||
if (wrapBidi) {
|
||||
utf16.Append('.');
|
||||
utf16.Append(UNICODE_PDF);
|
||||
}
|
||||
MakeTextRunInternal(utf16.get(), utf16.Length(), wrapBidi, textRun);
|
||||
|
||||
return textRun;
|
||||
}
|
||||
|
||||
|
@ -540,7 +624,12 @@ private:
|
|||
ATSUDirectDataSelector mSelector;
|
||||
};
|
||||
|
||||
#define ATSUI_SPECIAL_GLYPH_ID 0xFFFF
|
||||
#define ATSUI_SPECIAL_GLYPH_ID 0xFFFF
|
||||
/**
|
||||
* This flag seems to be set on glyphs that have overrun the 32K pixel
|
||||
* limit in ATSUI.
|
||||
*/
|
||||
#define ATSUI_OVERRUNNING_GLYPH_FLAG 0x100000
|
||||
|
||||
/**
|
||||
* Calculate the advance in appunits of a run of ATSUI glyphs
|
||||
|
@ -561,7 +650,8 @@ GetAdvanceAppUnits(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
|
|||
static void
|
||||
SetGlyphsForCharacterGroup(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
|
||||
Fixed *aBaselineDeltas, PRUint32 aAppUnitsPerDevUnit,
|
||||
gfxTextRun *aRun, const PRPackedBool *aUnmatched,
|
||||
gfxTextRun *aRun, PRUint32 aSegmentStart,
|
||||
const PRPackedBool *aUnmatched,
|
||||
const PRUnichar *aString)
|
||||
{
|
||||
NS_ASSERTION(aGlyphCount > 0, "Must set at least one glyph");
|
||||
|
@ -593,7 +683,7 @@ SetGlyphsForCharacterGroup(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
|
|||
if (!allMatched) {
|
||||
for (i = firstOffset; i <= lastOffset; ++i) {
|
||||
PRUint32 index = i/2;
|
||||
aRun->SetMissingGlyph(index, aString[index]);
|
||||
aRun->SetMissingGlyph(aSegmentStart + index, aString[index]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -605,9 +695,9 @@ SetGlyphsForCharacterGroup(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
|
|||
if (!inOrder) {
|
||||
// Because the characters in this group were not in the textrun's
|
||||
// required order, we must make the entire group an indivisible cluster
|
||||
aRun->SetCharacterGlyph(index, g.SetClusterContinuation());
|
||||
aRun->SetCharacterGlyph(aSegmentStart + index, g.SetClusterContinuation());
|
||||
} else if (!aRun->GetCharacterGlyphs()[index].IsClusterContinuation()) {
|
||||
aRun->SetCharacterGlyph(index, g.SetLigatureContinuation());
|
||||
aRun->SetCharacterGlyph(aSegmentStart + index, g.SetLigatureContinuation());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -619,7 +709,7 @@ SetGlyphsForCharacterGroup(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
|
|||
(!aBaselineDeltas || aBaselineDeltas[displayGlyph - aGlyphs] == 0) &&
|
||||
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
|
||||
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(displayGlyph->glyphID)) {
|
||||
aRun->SetCharacterGlyph(index, g.SetSimpleGlyph(advance, displayGlyph->glyphID));
|
||||
aRun->SetCharacterGlyph(aSegmentStart + index, g.SetSimpleGlyph(advance, displayGlyph->glyphID));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -647,20 +737,24 @@ SetGlyphsForCharacterGroup(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
|
|||
}
|
||||
if (detailedGlyphs.Length() == 0) {
|
||||
NS_WARNING("No glyphs visible at all!");
|
||||
aRun->SetCharacterGlyph(index, g.SetMissing());
|
||||
aRun->SetCharacterGlyph(aSegmentStart + index, g.SetMissing());
|
||||
return;
|
||||
}
|
||||
|
||||
detailedGlyphs[detailedGlyphs.Length() - 1].mIsLastGlyph = PR_TRUE;
|
||||
detailedGlyphs[detailedGlyphs.Length() - 1].mAdvance =
|
||||
GetAdvanceAppUnits(advanceStart, aGlyphs + aGlyphCount - advanceStart, aAppUnitsPerDevUnit);
|
||||
aRun->SetDetailedGlyphs(index, detailedGlyphs.Elements(), detailedGlyphs.Length());
|
||||
aRun->SetDetailedGlyphs(aSegmentStart + index, detailedGlyphs.Elements(), detailedGlyphs.Length());
|
||||
}
|
||||
|
||||
static void
|
||||
/**
|
||||
* Returns true if there are overrunning glyphs
|
||||
*/
|
||||
static PRBool
|
||||
PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
|
||||
const PRUnichar *aString, PRBool aWrapped,
|
||||
const PRPackedBool *aUnmatched)
|
||||
const PRPackedBool *aUnmatched,
|
||||
PRUint32 aSegmentStart, PRUint32 aSegmentLength)
|
||||
{
|
||||
// AutoLayoutDataArrayPtr advanceDeltasArray(aLine, kATSUDirectDataAdvanceDeltaFixedArray);
|
||||
// Fixed *advanceDeltas = NS_STATIC_CAST(Fixed *, advanceDeltasArray.mArray);
|
||||
|
@ -672,7 +766,7 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
|
|||
PRUint32 numGlyphs = glyphRecordsArray.mItemCount;
|
||||
if (numGlyphs == 0 || !glyphRecordsArray.mArray) {
|
||||
NS_WARNING("Failed to retrieve key glyph data");
|
||||
return;
|
||||
return PR_FALSE;
|
||||
}
|
||||
ATSLayoutRecord *glyphRecords = NS_STATIC_CAST(ATSLayoutRecord *, glyphRecordsArray.mArray);
|
||||
NS_ASSERTION(!baselineDeltas || baselineDeltasArray.mItemCount == numGlyphs,
|
||||
|
@ -681,7 +775,7 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
|
|||
"Last glyph should be a terminator glyph");
|
||||
--numGlyphs;
|
||||
if (numGlyphs == 0)
|
||||
return;
|
||||
return PR_FALSE;
|
||||
|
||||
PRUint32 appUnitsPerDevUnit = aRun->GetAppUnitsPerDevUnit();
|
||||
PRBool isRTL = aRun->IsRightToLeft();
|
||||
|
@ -690,18 +784,19 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
|
|||
// The glyph array includes a glyph for the artificial trailing
|
||||
// non-whitespace character. Strip that glyph from the array now.
|
||||
if (isRTL) {
|
||||
NS_ASSERTION(glyphRecords[0].originalOffset == aRun->GetLength()*2,
|
||||
NS_ASSERTION(glyphRecords[0].originalOffset == aSegmentLength*2,
|
||||
"Couldn't find glyph for trailing marker");
|
||||
glyphRecords++;
|
||||
} else {
|
||||
NS_ASSERTION(glyphRecords[numGlyphs - 1].originalOffset == aRun->GetLength()*2,
|
||||
NS_ASSERTION(glyphRecords[numGlyphs - 1].originalOffset == aSegmentLength*2,
|
||||
"Couldn't find glyph for trailing marker");
|
||||
}
|
||||
--numGlyphs;
|
||||
if (numGlyphs == 0)
|
||||
return;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRUint32 allFlags = 0;
|
||||
// Now process the glyphs, which should basically be in
|
||||
// the textrun's desired order, so process them in textrun order
|
||||
PRInt32 direction = PRInt32(aRun->GetDirection());
|
||||
|
@ -713,6 +808,7 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
|
|||
while (glyphCount < numGlyphs) {
|
||||
ATSLayoutRecord *glyph = &glyphRecords[glyphIndex + direction*glyphCount];
|
||||
PRUint32 glyphOffset = glyph->originalOffset;
|
||||
allFlags |= glyph->flags;
|
||||
// Always add the current glyph to the group if it's for the same
|
||||
// character as a character whose glyph is already in the group,
|
||||
// or an earlier character. The latter can happen because ATSUI
|
||||
|
@ -722,7 +818,7 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
|
|||
// In this case we need to make sure the glyph for the consonant
|
||||
// is added to the group containing the vowel.
|
||||
if (lastOffset < glyphOffset) {
|
||||
if (!aRun->IsClusterStart(glyphOffset/2)) {
|
||||
if (!aRun->IsClusterStart(aSegmentStart + glyphOffset/2)) {
|
||||
// next character is a cluster continuation,
|
||||
// add it to the current group
|
||||
lastOffset = glyphOffset;
|
||||
|
@ -747,13 +843,13 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
|
|||
SetGlyphsForCharacterGroup(glyphRecords + numGlyphs - glyphCount,
|
||||
glyphCount,
|
||||
baselineDeltas ? baselineDeltas + numGlyphs - glyphCount : nsnull,
|
||||
appUnitsPerDevUnit, aRun, aUnmatched,
|
||||
aString);
|
||||
appUnitsPerDevUnit, aRun, aSegmentStart,
|
||||
aUnmatched, aString);
|
||||
} else {
|
||||
SetGlyphsForCharacterGroup(glyphRecords,
|
||||
glyphCount, baselineDeltas,
|
||||
appUnitsPerDevUnit, aRun, aUnmatched,
|
||||
aString);
|
||||
appUnitsPerDevUnit, aRun, aSegmentStart,
|
||||
aUnmatched, aString);
|
||||
glyphRecords += glyphCount;
|
||||
if (baselineDeltas) {
|
||||
baselineDeltas += glyphCount;
|
||||
|
@ -761,17 +857,23 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
|
|||
}
|
||||
numGlyphs -= glyphCount;
|
||||
}
|
||||
|
||||
return (allFlags & ATSUI_OVERRUNNING_GLYPH_FLAG) != 0;
|
||||
}
|
||||
|
||||
struct PostLayoutCallbackClosure {
|
||||
gfxTextRun *mTextRun;
|
||||
const PRUnichar *mString;
|
||||
// This is true when we inserted an artifical trailing character at the
|
||||
// end of the string when computing the ATSUI layout.
|
||||
PRPackedBool mWrapped;
|
||||
// Either null or an array of stringlength booleans set to true for
|
||||
// each character that did not match any fonts
|
||||
nsAutoArrayPtr<PRPackedBool> mUnmatchedChars;
|
||||
PRUint32 mSegmentStart;
|
||||
PRUint32 mSegmentLength;
|
||||
// This is true when we inserted an artifical trailing character at the
|
||||
// end of the string when computing the ATSUI layout.
|
||||
PRPackedBool mWrapped;
|
||||
// The callback *sets* this to indicate whether there were overrunning glyphs
|
||||
PRPackedBool mOverrunningGlyphs;
|
||||
};
|
||||
|
||||
// This is really disgusting, but the ATSUI refCon thing is also disgusting
|
||||
|
@ -784,17 +886,21 @@ PostLayoutOperationCallback(ATSULayoutOperationSelector iCurrentOperation,
|
|||
void *iOperationCallbackParameterPtr,
|
||||
ATSULayoutOperationCallbackStatus *oCallbackStatus)
|
||||
{
|
||||
PostLayoutCallback(iLineRef, gCallbackClosure->mTextRun,
|
||||
gCallbackClosure->mString, gCallbackClosure->mWrapped,
|
||||
gCallbackClosure->mUnmatchedChars);
|
||||
gCallbackClosure->mOverrunningGlyphs =
|
||||
PostLayoutCallback(iLineRef, gCallbackClosure->mTextRun,
|
||||
gCallbackClosure->mString, gCallbackClosure->mWrapped,
|
||||
gCallbackClosure->mUnmatchedChars,
|
||||
gCallbackClosure->mSegmentStart,
|
||||
gCallbackClosure->mSegmentLength);
|
||||
*oCallbackStatus = kATSULayoutOperationCallbackStatusContinue;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
void
|
||||
PRBool
|
||||
gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
||||
const PRUnichar *aString, PRUint32 aLength,
|
||||
PRBool aWrapped)
|
||||
PRBool aWrapped, PRUint32 aSegmentStart,
|
||||
PRUint32 aSegmentLength)
|
||||
{
|
||||
OSStatus status;
|
||||
gfxAtsuiFont *atsuiFont = GetFontAt(0);
|
||||
|
@ -802,17 +908,16 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
|||
nsTArray<ATSUStyle> stylesToDispose;
|
||||
PRUint32 headerChars = aWrapped ? 1 : 0;
|
||||
const PRUnichar *realString = aString + headerChars;
|
||||
PRUint32 realLength = aRun->GetLength();
|
||||
NS_ASSERTION(realLength == aLength - (aWrapped ? 3 : 0),
|
||||
NS_ASSERTION(aSegmentLength == aLength - (aWrapped ? 3 : 0),
|
||||
"Length mismatch");
|
||||
|
||||
#ifdef DUMP_TEXT_RUNS
|
||||
NS_ConvertUTF16toUTF8 str(realString, realLength);
|
||||
NS_ConvertUTF16toUTF8 str(realString, aSegmentLength);
|
||||
NS_ConvertUTF16toUTF8 families(mFamilies);
|
||||
printf("%p(%s) TEXTRUN \"%s\" ENDTEXTRUN\n", this, families.get(), str.get());
|
||||
#endif
|
||||
|
||||
UniCharCount runLengths = realLength;
|
||||
UniCharCount runLengths = aSegmentLength;
|
||||
ATSUTextLayout layout;
|
||||
// Create the text layout for the whole string, but only produce glyphs
|
||||
// for the text inside LRO/RLO - PDF, if present. For wrapped strings
|
||||
|
@ -821,7 +926,7 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
|||
status = ATSUCreateTextLayoutWithTextPtr
|
||||
(aString,
|
||||
headerChars,
|
||||
realLength + (aWrapped ? 1 : 0),
|
||||
aSegmentLength + (aWrapped ? 1 : 0),
|
||||
aLength,
|
||||
1,
|
||||
&runLengths,
|
||||
|
@ -833,6 +938,8 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
|||
closure.mTextRun = aRun;
|
||||
closure.mString = realString;
|
||||
closure.mWrapped = aWrapped;
|
||||
closure.mSegmentStart = aSegmentStart;
|
||||
closure.mSegmentLength = aSegmentLength;
|
||||
NS_ASSERTION(!gCallbackClosure, "Reentering InitTextRun? Expect disaster!");
|
||||
gCallbackClosure = &closure;
|
||||
|
||||
|
@ -868,8 +975,8 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
|||
/* Now go through and update the styles for the text, based on font matching. */
|
||||
|
||||
UniCharArrayOffset runStart = headerChars;
|
||||
UniCharCount totalLength = runStart + realLength;
|
||||
UniCharCount runLength = realLength;
|
||||
UniCharCount totalLength = runStart + aSegmentLength;
|
||||
UniCharCount runLength = aSegmentLength;
|
||||
|
||||
//fprintf (stderr, "==== Starting font maching [string length: %d]\n", totalLength);
|
||||
while (runStart < totalLength) {
|
||||
|
@ -882,7 +989,7 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
|||
if (status == noErr) {
|
||||
//fprintf (stderr, "ATSUMatchFontsToText returned noErr\n");
|
||||
// everything's good, finish up
|
||||
aRun->AddGlyphRun(atsuiFont, runStart - headerChars);
|
||||
aRun->AddGlyphRun(atsuiFont, aSegmentStart + runStart - headerChars);
|
||||
break;
|
||||
} else if (status == kATSUFontsMatched) {
|
||||
//fprintf (stderr, "ATSUMatchFontsToText returned kATSUFontsMatched: FID %d\n", substituteFontID);
|
||||
|
@ -898,14 +1005,14 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
|||
ATSUSetAttributes (subStyle, 1, fontTags, fontArgSizes, fontArgs);
|
||||
|
||||
if (changedOffset > runStart) {
|
||||
aRun->AddGlyphRun(atsuiFont, runStart - headerChars);
|
||||
aRun->AddGlyphRun(atsuiFont, aSegmentStart + runStart - headerChars);
|
||||
}
|
||||
|
||||
ATSUSetRunStyle (layout, subStyle, changedOffset, changedLength);
|
||||
|
||||
gfxAtsuiFont *font = FindFontFor(substituteFontID);
|
||||
if (font) {
|
||||
aRun->AddGlyphRun(font, changedOffset - headerChars);
|
||||
aRun->AddGlyphRun(font, aSegmentStart + changedOffset - headerChars);
|
||||
}
|
||||
|
||||
stylesToDispose.AppendElement(subStyle);
|
||||
|
@ -913,7 +1020,7 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
|||
//fprintf (stderr, "ATSUMatchFontsToText returned kATSUFontsNotMatched\n");
|
||||
/* I need to select the last resort font; how the heck do I do that? */
|
||||
// Record which font is associated with these glyphs, anyway
|
||||
aRun->AddGlyphRun(atsuiFont, runStart - headerChars);
|
||||
aRun->AddGlyphRun(atsuiFont, aSegmentStart + runStart - headerChars);
|
||||
|
||||
if (!closure.mUnmatchedChars) {
|
||||
closure.mUnmatchedChars = new PRPackedBool[aLength];
|
||||
|
@ -937,7 +1044,7 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
|||
// the result of this call.
|
||||
ATSTrapezoid trap;
|
||||
ItemCount trapCount;
|
||||
ATSUGetGlyphBounds(layout, 0, 0, headerChars, realLength,
|
||||
ATSUGetGlyphBounds(layout, 0, 0, headerChars, aSegmentLength,
|
||||
kATSUseFractionalOrigins, 1, &trap, &trapCount);
|
||||
|
||||
ATSUDisposeTextLayout(layout);
|
||||
|
@ -948,4 +1055,5 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
|||
ATSUDisposeStyle(stylesToDispose[i]);
|
||||
}
|
||||
gCallbackClosure = nsnull;
|
||||
return !closure.mOverrunningGlyphs;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче