Backout the last couple of gfx checkins because the bugs and patches were mixed up. I'll reland.

This commit is contained in:
roc+%cs.cmu.edu 2007-03-20 03:00:11 +00:00
Родитель 7e6c86eff8
Коммит 5d0896ff66
12 изменённых файлов: 341 добавлений и 555 удалений

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

@ -11,7 +11,7 @@ MODULE = thebes
DIRS = public src
ifdef ENABLE_TESTS
TOOL_DIRS += test
# TOOL_DIRS += test
endif
include $(topsrcdir)/config/rules.mk

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

@ -103,11 +103,11 @@ public:
Parameters* aParams);
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
Parameters* aParams);
// Here, aString is actually aLength + aHeaderChars*2 chars long; the first char
// may be a LRO or RLO bidi control character to force setting the direction
// for all characters, and if so the last character will be a PDF
// Here, aString is actually aLength + 1 chars long; the first char
// is an LRO or RLO bidi control character to force setting the direction
// for all characters
gfxTextRun *MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLength,
Parameters *aParams, PRUint32 aheaderChars);
Parameters *aParams);
ATSUFontFallbacks *GetATSUFontFallbacksPtr() { return &mFallbacks; }
@ -122,8 +122,7 @@ protected:
const nsACString& aGenericName,
void *closure);
void InitTextRun(gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength,
PRUint32 aHeaderChars);
void InitTextRun(gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength);
ATSUFontFallbacks mFallbacks;
};

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

@ -142,7 +142,7 @@ public:
const nsString& GetName() const { return mName; }
const gfxFontStyle *GetStyle() const { return mStyle; }
virtual nsString GetUniqueName() = 0;
virtual nsString GetUniqueName() { return GetName(); }
// Font metrics
struct Metrics {
@ -175,9 +175,6 @@ public:
* We let layout specify spacing on either side of any
* character. We need to specify both before and after
* spacing so that substring measurement can do the right things.
* These values are in appunits. They're always an integral number of
* appunits, but we specify them in floats in case very large spacing
* values are required.
*/
struct Spacing {
gfxFloat mBefore;
@ -232,8 +229,7 @@ public:
* @param aEnd draw characters up to here
* @param aBaselineOrigin the baseline origin; the left end of the baseline
* for LTR textruns, the right end of the baseline for RTL textruns. On return,
* this should be updated to the other end of the baseline. In application
* units, really!
* this should be updated to the other end of the baseline. In application units.
* @param aSpacing spacing to insert before and after characters (for RTL
* glyphs, before-spacing is inserted to the right of characters). There
* are aEnd - aStart elements in this array, unless it's null to indicate
@ -423,17 +419,7 @@ public:
* It is important that zero-length substrings are handled correctly. This will
* be on the test!
*
* gfxTextRun stores a list of zero or more glyphs for each character. For each
* glyph we store the glyph ID, the advance, and possibly an xoffset and yoffset.
* The idea is that a string is rendered by a loop that draws each glyph
* at its designated offset from the current point, then advances the current
* point by the glyph's advance in the direction of the textrun (LTR or RTL).
* Each glyph advance is always rounded to the nearest appunit; this ensures
* consistent results when dividing the text in a textrun into multiple text
* frames (frame boundaries are always aligned to appunits). We optimize
* for the case where a character has a single glyph and zero xoffset and yoffset,
* and the glyph ID and advance are in a reasonable range so we can pack all
* necessary data into 32 bits.
* This class should not be subclassed.
*/
class THEBES_API gfxTextRun {
public:
@ -693,7 +679,7 @@ public:
void *GetUserData() const { return mUserData; }
PRUint32 GetFlags() const { return mFlags; }
const gfxSkipChars& GetSkipChars() const { return mSkipChars; }
PRUint32 GetAppUnitsPerDevUnit() const { return mAppUnitsPerDevUnit; }
float GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit; }
// The caller is responsible for initializing our glyphs after construction.
// Initially all glyphs are such that GetCharacterGlyphs()[i].IsMissing() is true.
@ -719,7 +705,6 @@ public:
// Indicates that a linebreak is allowed before this character
FLAG_CAN_BREAK_BEFORE = 0x40000000U,
// The advance is stored in appunits
ADVANCE_MASK = 0x3FFF0000U,
ADVANCE_SHIFT = 16,
@ -765,7 +750,7 @@ public:
}
// Returns true if the advance aAdvance fits into the compressed representation.
// aAdvance is in pixels.
static PRBool IsSimpleAdvance(PRUint32 aAdvance) {
static PRBool IsSimpleAdvancePixels(PRUint32 aAdvance) {
return (aAdvance & (ADVANCE_MASK >> ADVANCE_SHIFT)) == aAdvance;
}
@ -793,7 +778,7 @@ public:
}
CompressedGlyph& SetSimpleGlyph(PRUint32 aAdvancePixels, PRUint32 aGlyph) {
NS_ASSERTION(IsSimpleAdvance(aAdvancePixels), "Advance overflow");
NS_ASSERTION(IsSimpleAdvancePixels(aAdvancePixels), "Advance overflow");
NS_ASSERTION(IsSimpleGlyphID(aGlyph), "Glyph overflow");
mValue = (mValue & FLAG_CAN_BREAK_BEFORE) | FLAG_IS_SIMPLE_GLYPH |
(aAdvancePixels << ADVANCE_SHIFT) | aGlyph;
@ -821,9 +806,8 @@ public:
* us track the length of the array. */
PRUint32 mIsLastGlyph:1;
PRUint32 mGlyphID:31;
// The advance, x-offset and y-offset of the glyph, in appunits
PRInt32 mAdvance;
float mXOffset, mYOffset;
// The advance, x-offset and y-offset of the glyph, in pixels
float mAdvance, mXOffset, mYOffset;
};
// The text is divided into GlyphRuns as necessary
@ -909,8 +893,8 @@ private:
// Returns mGlyphRuns.Length() when aOffset is mCharacterCount.
PRUint32 FindFirstGlyphRunContaining(PRUint32 aOffset);
// Computes the x-advance for a given cluster starting at aClusterOffset. Does
// not include any spacing. Result is in appunits.
PRInt32 ComputeClusterAdvance(PRUint32 aClusterOffset);
// not include any spacing. Result is in device pixels.
gfxFloat ComputeClusterAdvance(PRUint32 aClusterOffset);
// **** ligature helpers ****
// (Platforms do the actual ligaturization, but we need to do a bunch of stuff
@ -921,7 +905,7 @@ private:
PRUint32 mEndOffset;
PRUint32 mClusterCount;
PRUint32 mPartClusterIndex;
PRInt32 mLigatureWidth; // appunits
gfxFloat mLigatureWidth; // appunits
gfxFloat mBeforeSpacing; // appunits
gfxFloat mAfterSpacing; // appunits
};
@ -935,8 +919,8 @@ private:
void DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx, PRUint32 aOffset,
const gfxRect *aDirtyRect, gfxPoint *aPt,
PropertyProvider *aProvider);
void ShrinkToLigatureBoundaries(PRUint32 *aStart, PRUint32 *aEnd);
// result in appunits
void ShrinkToLigatureBoundaries(PRUint32 *aStart, PRUint32 *aEnd);
gfxFloat GetPartialLigatureWidth(PRUint32 aStart, PRUint32 aEnd, PropertyProvider *aProvider);
void AccumulatePartialLigatureMetrics(gfxFont *aFont,
PRUint32 aOffset, PRBool aTight,
@ -963,7 +947,9 @@ private:
void *mUserData;
gfxSkipChars mSkipChars;
PRUint32 mAppUnitsPerDevUnit;
// This is actually an integer, but we keep it in float form to reduce
// the conversions required
float mAppUnitsPerDevUnit;
PRUint32 mFlags;
PRUint32 mCharacterCount;
};

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

@ -82,8 +82,6 @@ public:
PRBool aTightBoundingBox,
Spacing *aSpacing);
virtual nsString GetUniqueName();
protected:
PangoFontDescription *mPangoFontDesc;
PangoContext *mPangoCtx;

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

@ -376,7 +376,7 @@ SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32
gfxTextRun *
gfxAtsuiFontGroup::MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLength,
Parameters *aParams, PRUint32 aHeaderChars)
Parameters *aParams)
{
// NS_ASSERTION(!(aParams->mFlags & TEXT_NEED_BOUNDING_BOX),
// "Glyph extents not yet supported");
@ -386,12 +386,12 @@ gfxAtsuiFontGroup::MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLengt
return nsnull;
// There's a one-char header in the string and a one-char trailer
textRun->RecordSurrogates(aString + aHeaderChars);
textRun->RecordSurrogates(aString + 1);
if (!(aParams->mFlags & TEXT_IS_8BIT)) {
SetupClusterBoundaries(textRun, aString + aHeaderChars, aLength);
SetupClusterBoundaries(textRun, aString + 1, aLength);
}
InitTextRun(textRun, aString, aLength, aHeaderChars);
InitTextRun(textRun, aString, aLength);
return textRun;
}
@ -414,7 +414,7 @@ gfxAtsuiFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
AppendDirectionalIndicator(aParams->mFlags, utf16);
utf16.Append(aString, aLength);
utf16.Append(UNICODE_PDF);
return MakeTextRunInternal(utf16.get(), aLength, aParams, 1);
return MakeTextRunInternal(utf16.get(), aLength, aParams);
}
gfxTextRun *
@ -425,16 +425,10 @@ gfxAtsuiFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
nsDependentCSubstring cString(reinterpret_cast<const char*>(aString),
reinterpret_cast<const char*>(aString + aLength));
nsAutoString utf16;
PRUint32 headerChars = 0;
if (aParams->mFlags & TEXT_IS_RTL) {
AppendDirectionalIndicator(aParams->mFlags, utf16);
headerChars = 1;
}
AppendDirectionalIndicator(aParams->mFlags, utf16);
AppendASCIItoUTF16(cString, utf16);
if (aParams->mFlags & TEXT_IS_RTL) {
utf16.Append(UNICODE_PDF);
}
return MakeTextRunInternal(utf16.get(), aLength, aParams, headerChars);
utf16.Append(UNICODE_PDF);
return MakeTextRunInternal(utf16.get(), aLength, aParams);
}
gfxAtsuiFont*
@ -488,121 +482,41 @@ private:
ATSUDirectDataSelector mSelector;
};
#define ATSUI_SPECIAL_GLYPH_ID 0xFFFF
/**
* Calculate the advance in appunits of a run of ATSUI glyphs
* Abstraction to iterate through an array in strange order. It just remaps
* array indices. Tragically we mainly need this because of ATSUI bugs.
* There are four cases we need to handle. Note that 0 <= i < L in all cases.
* 1) f(i) = i (LTR, no bug, most common)
* 2) f(i) = L - 1 - i (RTL, no bug, next most common)
* 3) f(i) = i < N ? N - 1 - i : i; (compensate for ATSUI bug in RTL mode)
* 4) f(i) = i < N ? i + L - N : L - 1 - i (compensate for ATSUI bug in LTR mode)
* We collapse 2) into 3) by setting N=L.
* We collapse 1) into 4) by setting N=L.
*/
static PRInt32
GetAdvanceAppUnits(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
PRUint32 aAppUnitsPerDevUnit)
{
Fixed fixedAdvance = aGlyphs[aGlyphCount].realPos - aGlyphs->realPos;
return PRInt32((PRInt64(fixedAdvance)*aAppUnitsPerDevUnit + (1 << 15)) >> 16);
}
/**
* Given a run of ATSUI glyphs that should be treated as a single cluster/ligature,
* store them in the textrun at the appropriate character and set the
* other characters involved to be ligature/cluster continuations as appropriate.
*/
static void
SetGlyphsForCharacterGroup(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
Fixed *aBaselineDeltas, PRUint32 aAppUnitsPerDevUnit,
gfxTextRun *aRun)
{
NS_ASSERTION(aGlyphCount > 0, "Must set at least one glyph");
PRUint32 firstOffset = aGlyphs[0].originalOffset;
PRUint32 lastOffset = firstOffset;
PRUint32 i;
PRUint32 regularGlyphCount = 0;
ATSLayoutRecord *displayGlyph = nsnull;
PRBool inOrder = PR_TRUE;
for (i = 0; i < aGlyphCount; ++i) {
ATSLayoutRecord *glyph = &aGlyphs[i];
PRUint32 offset = glyph->originalOffset;
firstOffset = PR_MIN(firstOffset, offset);
lastOffset = PR_MAX(lastOffset, offset);
if (glyph->glyphID != ATSUI_SPECIAL_GLYPH_ID) {
++regularGlyphCount;
displayGlyph = glyph;
}
if (i > 0 && aRun->IsRightToLeft() != (offset < aGlyphs[i - 1].originalOffset)) {
inOrder = PR_FALSE;
class GlyphMapper {
public:
GlyphMapper(PRBool aIsRTL, PRUint32 aL, PRUint32 aN)
: mL(aL), mN(aN), mRTL(aIsRTL) {}
PRUint32 MapIndex(PRUint32 aIndex)
{
if (mRTL) {
return aIndex < mN ? mN - 1 - aIndex : aIndex;
} else {
return aIndex < mN ? aIndex + mL - mN : mL - 1 - aIndex;
}
}
gfxTextRun::CompressedGlyph g;
PRUint32 offset;
for (offset = firstOffset + 2; offset <= lastOffset; offset += 2) {
PRUint32 index = offset/2;
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());
} else if (!aRun->GetCharacterGlyphs()[index].IsClusterContinuation()) {
aRun->SetCharacterGlyph(index, g.SetLigatureContinuation());
}
}
// Grab total advance for all glyphs
PRInt32 advance = GetAdvanceAppUnits(aGlyphs, aGlyphCount, aAppUnitsPerDevUnit);
PRUint32 index = firstOffset/2;
if (regularGlyphCount == 1) {
if (advance >= 0 &&
(!aBaselineDeltas || aBaselineDeltas[displayGlyph - aGlyphs] == 0) &&
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(displayGlyph->glyphID)) {
aRun->SetCharacterGlyph(index, g.SetSimpleGlyph(advance, displayGlyph->glyphID));
return;
}
}
nsAutoTArray<gfxTextRun::DetailedGlyph,10> detailedGlyphs;
ATSLayoutRecord *advanceStart = aGlyphs;
for (i = 0; i < aGlyphCount; ++i) {
ATSLayoutRecord *glyph = &aGlyphs[i];
if (glyph->glyphID != ATSUI_SPECIAL_GLYPH_ID || regularGlyphCount == 0) {
if (detailedGlyphs.Length() > 0) {
detailedGlyphs[detailedGlyphs.Length() - 1].mAdvance =
GetAdvanceAppUnits(advanceStart, glyph - advanceStart, aAppUnitsPerDevUnit);
advanceStart = glyph;
}
gfxTextRun::DetailedGlyph *details = detailedGlyphs.AppendElement();
if (!details)
return;
details->mIsLastGlyph = PR_FALSE;
details->mGlyphID = glyph->glyphID;
details->mXOffset = 0;
details->mYOffset = !aBaselineDeltas ? 0.0f
: FixedToFloat(aBaselineDeltas[i])*aAppUnitsPerDevUnit;
}
}
if (detailedGlyphs.Length() == 0) {
NS_WARNING("No glyphs visible at all!");
aRun->SetCharacterGlyph(index, g.SetMissing());
return;
}
detailedGlyphs[detailedGlyphs.Length() - 1].mIsLastGlyph = PR_TRUE;
detailedGlyphs[detailedGlyphs.Length() - 1].mAdvance =
GetAdvanceAppUnits(advanceStart, aGlyphs + aGlyphCount - advanceStart, aAppUnitsPerDevUnit);
// Should pass unmatchedness here but for now we'll just not tell the textrun
// whether these are "missing glyph" glyphs or not
aRun->SetDetailedGlyphs(index, detailedGlyphs.Elements(), detailedGlyphs.Length());
}
private:
PRUint32 mL, mN;
PRBool mRTL;
};
static void
PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
const PRUnichar *aString, const PRPackedBool *aUnmatched)
const PRUnichar *aString)
{
// AutoLayoutDataArrayPtr advanceDeltasArray(aLine, kATSUDirectDataAdvanceDeltaFixedArray);
// Fixed *advanceDeltas = NS_STATIC_CAST(Fixed *, advanceDeltasArray.mArray);
// AutoLayoutDataArrayPtr deviceDeltasArray(aLine, kATSUDirectDataDeviceDeltaSInt16Array);
AutoLayoutDataArrayPtr advanceDeltasArray(aLine, kATSUDirectDataAdvanceDeltaFixedArray);
AutoLayoutDataArrayPtr baselineDeltasArray(aLine, kATSUDirectDataBaselineDeltaFixedArray);
Fixed *baselineDeltas = NS_STATIC_CAST(Fixed *, baselineDeltasArray.mArray);
AutoLayoutDataArrayPtr deviceDeltasArray(aLine, kATSUDirectDataDeviceDeltaSInt16Array);
AutoLayoutDataArrayPtr glyphRecordsArray(aLine, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent);
PRUint32 numGlyphs = glyphRecordsArray.mItemCount;
@ -610,8 +524,11 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
NS_WARNING("Failed to retrieve key glyph data");
return;
}
Fixed *advanceDeltas = NS_STATIC_CAST(Fixed *, advanceDeltasArray.mArray);
Fixed *baselineDeltas = NS_STATIC_CAST(Fixed *, baselineDeltasArray.mArray);
ATSLayoutRecord *glyphRecords = NS_STATIC_CAST(ATSLayoutRecord *, glyphRecordsArray.mArray);
NS_ASSERTION(!baselineDeltas || baselineDeltasArray.mItemCount == numGlyphs,
NS_ASSERTION((!advanceDeltas || advanceDeltasArray.mItemCount == numGlyphs) &&
(!baselineDeltas || baselineDeltasArray.mItemCount == numGlyphs),
"Mismatched glyph counts");
NS_ASSERTION(glyphRecords[numGlyphs - 1].flags & kATSGlyphInfoTerminatorGlyph,
"Last glyph should be a terminator glyph");
@ -619,8 +536,9 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
if (numGlyphs == 0)
return;
const PRUint32 appUnitsPerDevUnit = aRun->GetAppUnitsPerDevUnit();
PRUint32 index = 0;
ItemCount k = 0;
PRUint32 length = aRun->GetLength();
// ATSUI seems to have a bug where trailing whitespace in a run,
// even after we've forced the direction with LRO/RLO/PDF, does not
// necessarily get the required direction.
@ -633,93 +551,141 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
// being rendered in LTR order at the end of the glyph array.
// In LTR situations, the bug manifests as the trailing whitespace characters
// being rendered in RTL order at the start of the glyph array.
// Compensate for this bug now by detecting those characters, setting up
// the glyphs for those characters, and then chopping those glyphs off
// the glyph array we need to look at.
PRUint32 stringTailOffset = aRun->GetLength() - 1;
PRBool isRTL = aRun->IsRightToLeft();
if (isRTL) {
while (numGlyphs > 0 &&
glyphRecords[numGlyphs - 1].originalOffset == stringTailOffset*2 &&
aString[stringTailOffset] == ' ') {
SetGlyphsForCharacterGroup(glyphRecords + numGlyphs - 1, 1,
baselineDeltas ? baselineDeltas + numGlyphs - 1 : nsnull,
appUnitsPerDevUnit, aRun);
--stringTailOffset;
--numGlyphs;
}
} else {
while (numGlyphs > 0 &&
glyphRecords[0].originalOffset == stringTailOffset*2 &&
aString[stringTailOffset] == ' ') {
SetGlyphsForCharacterGroup(glyphRecords, 1,
baselineDeltas,
appUnitsPerDevUnit, aRun);
--stringTailOffset;
--numGlyphs;
++glyphRecords;
}
PRUint32 incorrectDirectionGlyphCount = 0;
PRUint32 stringTailOffset = length - 1;
while (glyphRecords[aRun->IsRightToLeft() ? numGlyphs - 1 - incorrectDirectionGlyphCount
: incorrectDirectionGlyphCount].originalOffset == stringTailOffset*2 &&
aString[stringTailOffset] == ' ') {
++incorrectDirectionGlyphCount;
stringTailOffset--;
if (incorrectDirectionGlyphCount == numGlyphs)
break;
}
GlyphMapper mapper(aRun->IsRightToLeft(), numGlyphs,
numGlyphs - incorrectDirectionGlyphCount);
gfxTextRun::CompressedGlyph g;
nsAutoTArray<gfxTextRun::DetailedGlyph,1> detailedGlyphs;
PRBool gotRealCharacter = PR_FALSE;
while (index < length) {
ATSLayoutRecord *glyph = nsnull;
// ATSUI sometimes moves glyphs around in visual order to handle
// situations such as DEVANAGARI VOWEL I appearing before its base
// character (even though it follows the base character in the text).
// To handle this we make the reordered glyph(s) and the characters
// they're reordered around into a single cluster.
PRUint32 forceClusterGlyphs = 0;
PRUint32 nextIndex = index + 1;
if (k < numGlyphs) {
glyph = &glyphRecords[mapper.MapIndex(k)];
// originalOffset is in bytes, so we need to adjust index by 2 for comparisons
if (glyph->originalOffset > 2*index) {
// Detect the situation above. We assume that at most
// two glyphs have been moved from after a run of characters
// to visually before the run of characters, so the following glyph
// or the next glyph is a glyph for the current character.
// We can tweak this up if necessary...
const PRUint32 MAX_GLYPHS_REORDERED = 10;
PRUint32 reorderedGlyphs = 0;
PRUint32 i;
PRUint32 maxOffset = glyph->originalOffset;
for (i = 1; k + i < numGlyphs; ++i) {
ATSLayoutRecord *nextGlyph = &glyphRecords[mapper.MapIndex(k + i)];
if (i == MAX_GLYPHS_REORDERED || nextGlyph->originalOffset == 2*index) {
reorderedGlyphs = i;
break;
}
maxOffset = PR_MAX(maxOffset, nextGlyph->originalOffset);
}
if (reorderedGlyphs > 0) {
forceClusterGlyphs = reorderedGlyphs;
while (k + forceClusterGlyphs < numGlyphs) {
ATSLayoutRecord *nextGlyph = &glyphRecords[mapper.MapIndex(k + forceClusterGlyphs)];
if (nextGlyph->originalOffset > maxOffset)
break;
++forceClusterGlyphs;
}
nextIndex = maxOffset/2 + 1;
}
}
}
// Now process the rest of the glyphs, which should basically be in
// the textrun's desired order, so process them in textrun order
PRInt32 direction = PRInt32(aRun->GetDirection());
while (numGlyphs > 0) {
PRUint32 glyphIndex = isRTL ? numGlyphs - 1 : 0;
PRUint32 lastOffset = glyphRecords[glyphIndex].originalOffset;
PRUint32 glyphCount = 1;
// Determine the glyphs for this group
while (glyphCount < numGlyphs) {
ATSLayoutRecord *glyph = &glyphRecords[glyphIndex + direction*glyphCount];
PRUint32 glyphOffset = glyph->originalOffset;
// 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
// sometimes visually reorders glyphs; e.g. DEVANAGARI VOWEL I
// can have its glyph displayed before the glyph for the consonant that's
// it's logically after (even though this is all left-to-right text).
// In this case we need to make sure the glyph for the consonant
// is added to the group containing the vowel.
if (lastOffset < glyphOffset) {
// We could be at the end of a character group
if (glyph->glyphID != ATSUI_SPECIAL_GLYPH_ID) {
// Next character is a normal character, stop the group here
break;
if (k == numGlyphs ||
(glyph->originalOffset > 2*index && !forceClusterGlyphs)) {
NS_ASSERTION(index > 0, "Continuation at the start of a run??");
if (!aRun->GetCharacterGlyphs()[index].IsClusterContinuation()) {
if (gotRealCharacter) {
// No glyphs for character 'index', it must be a ligature continuation
aRun->SetCharacterGlyph(index, g.SetLigatureContinuation());
} else {
// Don't allow ligature continuations until we've actually
// got something for them to be a continuation of
aRun->SetCharacterGlyph(index, g.SetMissing());
}
if (aUnmatched && aUnmatched[glyphOffset/2]) {
// Next character is ummatched, so definitely stop the group here
break;
}
// Otherwise the next glyph is, we assume, a ligature continuation.
// Record that this character too is part of the group
lastOffset = glyphOffset;
}
++glyphCount;
}
if (isRTL) {
SetGlyphsForCharacterGroup(glyphRecords + numGlyphs - glyphCount,
glyphCount,
baselineDeltas ? baselineDeltas + numGlyphs - glyphCount : nsnull,
appUnitsPerDevUnit, aRun);
} else {
SetGlyphsForCharacterGroup(glyphRecords,
glyphCount, baselineDeltas,
appUnitsPerDevUnit, aRun);
glyphRecords += glyphCount;
if (baselineDeltas) {
baselineDeltas += glyphCount;
NS_ASSERTION(glyph->originalOffset >= 2*index, "Lost some glyphs");
PRUint32 glyphCount = 1;
if (forceClusterGlyphs) {
glyphCount = forceClusterGlyphs;
PRUint32 i;
// Mark all the characters that we forced to cluster, other
// than this leading character, as cluster continuations.
for (i = 0; i < forceClusterGlyphs; ++i) {
PRUint32 offset = glyphRecords[mapper.MapIndex(k + i)].originalOffset;
if (offset != 2*index) {
aRun->SetCharacterGlyph(offset/2, g.SetClusterContinuation());
}
}
} else {
// Find all the glyphs associated with this character
while (k + glyphCount < numGlyphs &&
glyphRecords[mapper.MapIndex(k + glyphCount)].originalOffset == 2*index) {
++glyphCount;
}
}
Fixed advance = glyph[1].realPos - glyph->realPos;
PRUint32 advancePixels = advance >> 16;
// "Fixed" values have their fraction in the low 16 bits
if (glyphCount == 1 && advance >= 0 && (advance & 0xFFFF) == 0 &&
(!baselineDeltas || baselineDeltas[mapper.MapIndex(k)] == 0) &&
gfxTextRun::CompressedGlyph::IsSimpleAdvancePixels(advancePixels) &&
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(glyph->glyphID)) {
aRun->SetCharacterGlyph(index, g.SetSimpleGlyph(advancePixels, glyph->glyphID));
} else {
if (detailedGlyphs.Length() < glyphCount) {
if (!detailedGlyphs.AppendElements(glyphCount - detailedGlyphs.Length()))
return;
}
PRUint32 i;
float appUnitsPerDevUnit = aRun->GetAppUnitsPerDevUnit();
for (i = 0; i < glyphCount; ++i) {
gfxTextRun::DetailedGlyph *details = &detailedGlyphs[i];
glyph = &glyphRecords[mapper.MapIndex(k + i)];
details->mIsLastGlyph = i == glyphCount - 1;
details->mGlyphID = glyph->glyphID;
float advanceAppUnits =
FixedToFloat(glyph[1].realPos - glyph->realPos)*appUnitsPerDevUnit;
details->mAdvance = ceilf(advanceAppUnits)/appUnitsPerDevUnit;
details->mXOffset = 0;
details->mYOffset = !baselineDeltas ? 0.0f
: FixedToFloat(baselineDeltas[mapper.MapIndex(k + i)]);
}
aRun->SetDetailedGlyphs(index, detailedGlyphs.Elements(), glyphCount);
}
gotRealCharacter = PR_TRUE;
k += glyphCount;
}
index = nextIndex;
if (index + 1 < length && NS_IS_HIGH_SURROGATE(aString[index])) {
++index;
}
numGlyphs -= glyphCount;
}
}
struct PostLayoutCallbackClosure {
gfxTextRun *mTextRun;
const PRUnichar *mString;
// Either null or an array of stringlength booleans set to true for
// each character that did not match any fonts
nsAutoArrayPtr<PRPackedBool> mUnmatchedChars;
gfxTextRun *mTextRun;
const PRUnichar *mString;
};
// This is really disgusting, but the ATSUI refCon thing is also disgusting
@ -733,15 +699,14 @@ PostLayoutOperationCallback(ATSULayoutOperationSelector iCurrentOperation,
ATSULayoutOperationCallbackStatus *oCallbackStatus)
{
PostLayoutCallback(iLineRef, gCallbackClosure->mTextRun,
gCallbackClosure->mString, gCallbackClosure->mUnmatchedChars);
gCallbackClosure->mString);
*oCallbackStatus = kATSULayoutOperationCallbackStatusContinue;
return noErr;
}
void
gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
const PRUnichar *aString, PRUint32 aLength,
PRUint32 aHeaderChars)
const PRUnichar *aString, PRUint32 aLength)
{
OSStatus status;
gfxAtsuiFont *atsuiFont = GetFontAt(0);
@ -750,15 +715,15 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
UniCharCount runLengths = aLength;
ATSUTextLayout layout;
// The string is actually aLength + 2*aHeaderChars chars, with optionally
// a header char to set the direction and a trailer char to pop it. So
// create the text layout giving the whole string as context, although we
// only want glyphs for the inner substring.
// The string is actually aLength + 2 chars, with a header char to set
// the direction and a trailer char to pop it. So create the text layout
// giving the whole string as context, although we only want glyphs for
// the inner substring.
status = ATSUCreateTextLayoutWithTextPtr
(aString,
aHeaderChars,
1,
aLength,
aLength + aHeaderChars*2,
aLength + 2,
1,
&runLengths,
&mainStyle,
@ -768,7 +733,7 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
PostLayoutCallbackClosure closure;
closure.mTextRun = aRun;
// Pass the real string to the closure, ignoring the header
closure.mString = aString + aHeaderChars;
closure.mString = aString + 1;
NS_ASSERTION(!gCallbackClosure, "Reentering InitTextRun? Expect disaster!");
gCallbackClosure = &closure;
@ -803,8 +768,8 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
/* Now go through and update the styles for the text, based on font matching. */
UniCharArrayOffset runStart = aHeaderChars;
UniCharCount totalLength = aLength + aHeaderChars;
UniCharArrayOffset runStart = 1;
UniCharCount totalLength = aLength + 1;
UniCharCount runLength = aLength;
//fprintf (stderr, "==== Starting font maching [string length: %d]\n", totalLength);
@ -818,7 +783,7 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
if (status == noErr) {
//fprintf (stderr, "ATSUMatchFontsToText returned noErr\n");
// everything's good, finish up
aRun->AddGlyphRun(atsuiFont, runStart - aHeaderChars);
aRun->AddGlyphRun(atsuiFont, runStart - 1);
break;
} else if (status == kATSUFontsMatched) {
//fprintf (stderr, "ATSUMatchFontsToText returned kATSUFontsMatched: FID %d\n", substituteFontID);
@ -834,14 +799,14 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
ATSUSetAttributes (subStyle, 1, fontTags, fontArgSizes, fontArgs);
if (changedOffset > runStart) {
aRun->AddGlyphRun(atsuiFont, runStart - aHeaderChars);
aRun->AddGlyphRun(atsuiFont, runStart - 1);
}
ATSUSetRunStyle (layout, subStyle, changedOffset, changedLength);
gfxAtsuiFont *font = FindFontFor(substituteFontID);
if (font) {
aRun->AddGlyphRun(font, changedOffset - aHeaderChars);
aRun->AddGlyphRun(font, changedOffset - 1);
}
stylesToDispose.AppendElement(subStyle);
@ -849,18 +814,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 - aHeaderChars);
if (!closure.mUnmatchedChars) {
closure.mUnmatchedChars = new PRPackedBool[aLength];
if (closure.mUnmatchedChars) {
memset(closure.mUnmatchedChars.get(), PR_FALSE, aLength);
}
}
if (closure.mUnmatchedChars) {
memset(closure.mUnmatchedChars.get() + changedOffset - aHeaderChars,
PR_TRUE, changedLength);
}
aRun->AddGlyphRun(atsuiFont, runStart - 1);
}
//fprintf (stderr, "total length: %d changedOffset: %d changedLength: %d\p=n", runLength, changedOffset, changedLength);
@ -873,8 +827,7 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
// the result of this call.
ATSTrapezoid trap;
ItemCount trapCount;
ATSUGetGlyphBounds(layout, 0, 0, aHeaderChars, aLength,
kATSUseFractionalOrigins, 1, &trap, &trapCount);
ATSUGetGlyphBounds(layout, 0, 0, 1, aLength, kATSUseDeviceOrigins, 1, &trap, &trapCount);
ATSUDisposeTextLayout(layout);

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

@ -57,16 +57,6 @@ gfxFont::gfxFont(const nsAString &aName, const gfxFontStyle *aFontStyle) :
{
}
/**
* A helper function in case we need to do any rounding or other
* processing here.
*/
static double
ToDeviceUnits(double aAppUnits, double aDevUnitsPerAppUnit)
{
return aAppUnits*aDevUnitsPerAppUnit;
}
void
gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
gfxContext *aContext, PRBool aDrawToPath, gfxPoint *aPt,
@ -75,19 +65,19 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
if (aStart >= aEnd)
return;
double appUnitsToPixels = 1.0/aTextRun->GetAppUnitsPerDevUnit();
const gfxTextRun::CompressedGlyph *charGlyphs = aTextRun->GetCharacterGlyphs();
const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit();
const double devUnitsPerAppUnit = 1/gfxFloat(appUnitsPerDevUnit);
PRBool isRTL = aTextRun->IsRightToLeft();
double direction = aTextRun->GetDirection();
nsAutoTArray<cairo_glyph_t,200> glyphBuffer;
PRUint32 i;
// Current position in appunits
double x = aPt->x;
double y = aPt->y;
PRBool isRTL = aTextRun->IsRightToLeft();
if (aSpacing) {
x += direction*aSpacing[0].mBefore;
x += direction*aSpacing[0].mBefore*appUnitsToPixels;
}
for (i = aStart; i < aEnd; ++i) {
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i];
@ -97,15 +87,10 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
return;
glyph->index = glyphData->GetSimpleGlyph();
double advance = glyphData->GetSimpleAdvance();
// Perhaps we should put a scale in the cairo context instead of
// doing this scaling here...
// Multiplying by the reciprocal may introduce tiny error here,
// but we assume cairo is going to round coordinates at some stage
// and this is faster
glyph->x = ToDeviceUnits(x, devUnitsPerAppUnit);
glyph->y = ToDeviceUnits(y, devUnitsPerAppUnit);
glyph->x = x;
glyph->y = y;
if (isRTL) {
glyph->x -= ToDeviceUnits(advance, devUnitsPerAppUnit);
glyph->x -= advance;
x -= advance;
} else {
x += advance;
@ -117,11 +102,11 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
if (!glyph)
return;
glyph->index = details->mGlyphID;
glyph->x = ToDeviceUnits(x + details->mXOffset, devUnitsPerAppUnit);
glyph->y = ToDeviceUnits(y + details->mYOffset, devUnitsPerAppUnit);
glyph->x = x + details->mXOffset;
glyph->y = y + details->mYOffset;
double advance = details->mAdvance;
if (isRTL) {
glyph->x -= ToDeviceUnits(advance, devUnitsPerAppUnit);
glyph->x -= advance;
}
x += direction*advance;
if (details->mIsLastGlyph)
@ -135,12 +120,16 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
if (i + 1 < aEnd) {
space += aSpacing[i + 1 - aStart].mBefore;
}
x += direction*space;
x += direction*space*appUnitsToPixels;
}
}
*aPt = gfxPoint(x, y);
// XXX is this needed? what does it do? Mac code was doing it.
// gfxFloat offsetX, offsetY;
// nsRefPtr<gfxASurface> surf = aContext->CurrentSurface (&offsetX, &offsetY);
cairo_t *cr = aContext->GetCairo();
SetupCairoFont(cr);
if (aDrawToPath) {
@ -164,7 +153,7 @@ gfxFont::Measure(gfxTextRun *aTextRun,
// XXX temporary code, does not handle glyphs outside the font-box
NS_ASSERTION(!(aTextRun->GetFlags() & gfxTextRunFactory::TEXT_NEED_BOUNDING_BOX),
"Glyph extents not yet supported");
PRInt32 advance = 0;
gfxFloat advancePixels = 0;
PRUint32 i;
const gfxTextRun::CompressedGlyph *charGlyphs = aTextRun->GetCharacterGlyphs();
PRUint32 clusterCount = 0;
@ -173,11 +162,11 @@ gfxFont::Measure(gfxTextRun *aTextRun,
if (g.IsClusterStart()) {
++clusterCount;
if (g.IsSimpleGlyph()) {
advance += charGlyphs[i].GetSimpleAdvance();
advancePixels += charGlyphs[i].GetSimpleAdvance();
} else if (g.IsComplexCluster()) {
const gfxTextRun::DetailedGlyph *details = aTextRun->GetDetailedGlyphs(i);
for (;;) {
advance += details->mAdvance;
advancePixels += details->mAdvance;
if (details->mIsLastGlyph)
break;
++details;
@ -185,21 +174,20 @@ gfxFont::Measure(gfxTextRun *aTextRun,
}
}
}
gfxFloat floatAdvance = advance;
gfxFloat dev2app = aTextRun->GetAppUnitsPerDevUnit();
gfxFloat advance = advancePixels*dev2app;
if (aSpacing) {
for (i = 0; i < aEnd - aStart; ++i) {
floatAdvance += aSpacing[i].mBefore + aSpacing[i].mAfter;
advance += aSpacing[i].mBefore + aSpacing[i].mAfter;
}
}
RunMetrics metrics;
const gfxFont::Metrics& fontMetrics = GetMetrics();
metrics.mAdvanceWidth = floatAdvance;
const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit();
metrics.mAscent = fontMetrics.maxAscent*appUnitsPerDevUnit;
metrics.mDescent = fontMetrics.maxDescent*appUnitsPerDevUnit;
metrics.mAdvanceWidth = advance;
metrics.mAscent = fontMetrics.maxAscent*dev2app;
metrics.mDescent = fontMetrics.maxDescent*dev2app;
metrics.mBoundingBox =
gfxRect(0, -metrics.mAscent, floatAdvance, metrics.mAscent + metrics.mDescent);
gfxRect(0, -metrics.mAscent, advance, metrics.mAscent + metrics.mDescent);
metrics.mClusterCount = clusterCount;
return metrics;
}
@ -426,7 +414,7 @@ gfxFontGroup::GetSpecialStringTextRun(SpecialString aString,
gfxTextRunFactory::Parameters params = {
nsnull, nsnull, nsnull, nsnull, nsnull, 0,
aTemplate->GetAppUnitsPerDevUnit(), TEXT_IS_PERSISTENT
PRUint32(aTemplate->GetAppUnitsPerDevUnit()), TEXT_IS_PERSISTENT
};
gfxTextRun* textRun;
@ -555,7 +543,7 @@ gfxTextRun::SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength,
return changed != 0;
}
PRInt32
gfxFloat
gfxTextRun::ComputeClusterAdvance(PRUint32 aClusterOffset)
{
CompressedGlyph *glyphData = &mCharacterGlyphs[aClusterOffset];
@ -563,7 +551,7 @@ gfxTextRun::ComputeClusterAdvance(PRUint32 aClusterOffset)
return glyphData->GetSimpleAdvance();
NS_ASSERTION(glyphData->IsComplexCluster(), "Unknown character type!");
NS_ASSERTION(mDetailedGlyphs, "Complex cluster but no details array!");
PRInt32 advance = 0;
gfxFloat advance = 0;
DetailedGlyph *details = mDetailedGlyphs[aClusterOffset];
NS_ASSERTION(details, "Complex cluster but no details!");
for (;;) {
@ -588,7 +576,7 @@ gfxTextRun::ComputeLigatureData(PRUint32 aPartOffset, PropertyProvider *aProvide
} while (!charGlyphs[ligStart].IsClusterStart());
}
result.mStartOffset = ligStart;
result.mLigatureWidth = ComputeClusterAdvance(ligStart);
result.mLigatureWidth = ComputeClusterAdvance(ligStart)*mAppUnitsPerDevUnit;
result.mPartClusterIndex = PR_UINT32_MAX;
PRUint32 charIndex = ligStart;
@ -633,9 +621,22 @@ gfxTextRun::GetAdjustedSpacing(PRUint32 aStart, PRUint32 aEnd,
aProvider->GetSpacing(aStart, aEnd - aStart, aSpacing);
// XXX the following loop could be avoided if we add some kind of
// TEXT_HAS_LIGATURES flag
CompressedGlyph *charGlyphs = mCharacterGlyphs;
PRUint32 i;
PRUint32 end = PR_MIN(aEnd, mCharacterCount - 1);
for (i = aStart; i <= end; ++i) {
if (charGlyphs[i].IsLigatureContinuation()) {
if (i < aEnd) {
aSpacing[i - aStart].mBefore = 0;
}
if (i > aStart) {
aSpacing[i - 1 - aStart].mAfter = 0;
}
}
}
if (mFlags & gfxTextRunFactory::TEXT_ABSOLUTE_SPACING) {
// Subtract character widths from mAfter at the end of clusters/ligatures to
// relativize spacing. This is a bit sad since we're going to add
@ -643,7 +644,7 @@ gfxTextRun::GetAdjustedSpacing(PRUint32 aStart, PRUint32 aEnd,
// produces simpler code and absolute spacing is rarely required.
// The width of the last nonligature cluster, in appunits
PRInt32 clusterWidth = 0;
gfxFloat clusterWidth = 0.0;
for (i = aStart; i < aEnd; ++i) {
CompressedGlyph *glyphData = &charGlyphs[i];
@ -651,46 +652,25 @@ gfxTextRun::GetAdjustedSpacing(PRUint32 aStart, PRUint32 aEnd,
if (i > aStart) {
aSpacing[i - 1 - aStart].mAfter -= clusterWidth;
}
clusterWidth = glyphData->GetSimpleAdvance();
clusterWidth = glyphData->GetSimpleAdvance()*mAppUnitsPerDevUnit;
} else if (glyphData->IsComplexCluster()) {
NS_ASSERTION(mDetailedGlyphs, "No details but we have a complex cluster...");
if (i > aStart) {
aSpacing[i - 1 - aStart].mAfter -= clusterWidth;
}
DetailedGlyph *details = mDetailedGlyphs[i];
clusterWidth = 0;
clusterWidth = 0.0;
for (;;) {
clusterWidth += details->mAdvance;
if (details->mIsLastGlyph)
break;
++details;
}
clusterWidth *= mAppUnitsPerDevUnit;
}
}
aSpacing[aEnd - 1 - aStart].mAfter -= clusterWidth;
}
// Move spacing inside a ligature to after the ligature.
// Do this after adjusting for ABSOLUTE_SPACING above.
// XXX we shouldn't really have to do this, textframe users should
// not put spacing inside ligatures.
// XXX the following loop could be avoided if we add some kind of
// TEXT_HAS_LIGATURES flag
gfxFloat accumulatedSpace = 0;
for (i = aStart; i <= aEnd; ++i) {
if (i < aEnd && charGlyphs[i].IsLigatureContinuation()) {
accumulatedSpace += aSpacing[i - aStart].mBefore;
aSpacing[i - aStart].mBefore = 0;
NS_ASSERTION(i > aStart, "Ligature continuation at start of spacing run?");
accumulatedSpace += aSpacing[i - 1 - aStart].mAfter;
aSpacing[i - 1 - aStart].mAfter = 0;
} else {
if (i > aStart) {
aSpacing[i - 1 - aStart].mAfter += accumulatedSpace;
accumulatedSpace = 0;
}
}
}
}
PRBool
@ -760,7 +740,7 @@ gfxTextRun::GetPartialLigatureWidth(PRUint32 aStart, PRUint32 aEnd,
}
}
gfxFloat result = gfxFloat(data.mLigatureWidth)*clusterCount/data.mClusterCount;
gfxFloat result = data.mLigatureWidth*clusterCount/data.mClusterCount;
if (aStart == data.mStartOffset) {
result += data.mBeforeSpacing;
}
@ -780,17 +760,19 @@ gfxTextRun::DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx, PRUint32 aOffs
if (!mCharacterGlyphs[aOffset].IsClusterStart() || !aDirtyRect)
return;
gfxFloat appUnitsToPixels = 1.0/mAppUnitsPerDevUnit;
// Draw partial ligature. We hack this by clipping the ligature.
LigatureData data = ComputeLigatureData(aOffset, aProvider);
// Width of a cluster in the ligature, in appunits
gfxFloat clusterWidth = data.mLigatureWidth/data.mClusterCount;
// Width of a cluster in the ligature, in device pixels
gfxFloat clusterWidth = data.mLigatureWidth*appUnitsToPixels/data.mClusterCount;
gfxFloat direction = GetDirection();
gfxFloat left = aDirtyRect->X();
gfxFloat right = aDirtyRect->XMost();
// The advance to the start of this cluster in the drawn ligature, in appunits
gfxFloat left = aDirtyRect->X()*appUnitsToPixels;
gfxFloat right = aDirtyRect->XMost()*appUnitsToPixels;
// The advance to the start of this cluster in the drawn ligature, in device pixels
gfxFloat widthBeforeCluster;
// Any spacing that should be included after the cluster, in appunits
// Any spacing that should be included after the cluster, in device pixels
gfxFloat afterSpace;
if (data.mStartOffset < aOffset) {
// Not the start of the ligature; need to clip the ligature before the current cluster
@ -800,7 +782,7 @@ gfxTextRun::DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx, PRUint32 aOffs
left = PR_MAX(left, aPt->x);
}
widthBeforeCluster = clusterWidth*data.mPartClusterIndex +
data.mBeforeSpacing;
data.mBeforeSpacing*appUnitsToPixels;
} else {
// We're drawing the start of the ligature, so our cluster includes any
// before-spacing.
@ -816,16 +798,12 @@ gfxTextRun::DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx, PRUint32 aOffs
}
afterSpace = 0;
} else {
afterSpace = data.mAfterSpacing;
afterSpace = data.mAfterSpacing*appUnitsToPixels;
}
aCtx->Save();
// use division here to ensure that when the rect is aligned on multiples
// of mAppUnitsPerDevUnit, we clip to true device unit boundaries
aCtx->Clip(gfxRect(left/mAppUnitsPerDevUnit,
aDirtyRect->Y()/mAppUnitsPerDevUnit,
(right - left)/mAppUnitsPerDevUnit,
aDirtyRect->Height()/mAppUnitsPerDevUnit));
aCtx->Clip(gfxRect(left, aDirtyRect->Y()*appUnitsToPixels, right - left,
aDirtyRect->Height()*appUnitsToPixels));
gfxPoint pt(aPt->x - direction*widthBeforeCluster, aPt->y);
DrawGlyphs(aFont, aCtx, PR_FALSE, &pt, data.mStartOffset,
data.mEndOffset, aProvider);
@ -841,9 +819,12 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt,
{
NS_ASSERTION(aStart + aLength <= mCharacterCount, "Substring out of range");
gfxFloat appUnitsToPixels = 1/mAppUnitsPerDevUnit;
CompressedGlyph *charGlyphs = mCharacterGlyphs;
gfxFloat direction = GetDirection();
gfxPoint pt = aPt;
gfxPoint pt(aPt.x*appUnitsToPixels, aPt.y*appUnitsToPixels);
gfxFloat startX = pt.x;
GlyphRunIterator iter(this, aStart, aLength);
while (iter.NextRun()) {
@ -873,7 +854,7 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt,
}
if (aAdvanceWidth) {
*aAdvanceWidth = (pt.x - aPt.x)*direction;
*aAdvanceWidth = (pt.x - startX)*direction*mAppUnitsPerDevUnit;
}
}
@ -884,9 +865,12 @@ gfxTextRun::DrawToPath(gfxContext *aContext, gfxPoint aPt,
{
NS_ASSERTION(aStart + aLength <= mCharacterCount, "Substring out of range");
gfxFloat appUnitsToPixels = 1/mAppUnitsPerDevUnit;
CompressedGlyph *charGlyphs = mCharacterGlyphs;
gfxFloat direction = GetDirection();
gfxPoint pt = aPt;
gfxPoint pt(aPt.x*appUnitsToPixels, aPt.y*appUnitsToPixels);
gfxFloat startX = pt.x;
GlyphRunIterator iter(this, aStart, aLength);
while (iter.NextRun()) {
@ -906,7 +890,7 @@ gfxTextRun::DrawToPath(gfxContext *aContext, gfxPoint aPt,
}
if (aAdvanceWidth) {
*aAdvanceWidth = (pt.x - aPt.x)*direction;
*aAdvanceWidth = (pt.x - startX)*direction*mAppUnitsPerDevUnit;
}
}
@ -1080,7 +1064,8 @@ gfxTextRun::BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
}
gfxFloat width = 0;
gfxFloat advance = 0;
PRUint32 pixelAdvance = 0;
gfxFloat floatAdvanceUnits = 0;
PRInt32 lastBreak = -1;
PRBool aborted = PR_FALSE;
PRUint32 end = aStart + aMaxLength;
@ -1109,11 +1094,14 @@ gfxTextRun::BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
PRBool lineBreakHere = mCharacterGlyphs[i].CanBreakBefore() &&
(!aSuppressInitialBreak || i > aStart);
if (lineBreakHere || (haveHyphenation && hyphenBuffer[i - bufferStart])) {
gfxFloat advance = gfxFloat(pixelAdvance)*mAppUnitsPerDevUnit + floatAdvanceUnits;
gfxFloat hyphenatedAdvance = advance;
PRBool hyphenation = !lineBreakHere;
if (hyphenation) {
hyphenatedAdvance += aProvider->GetHyphenWidth();
}
pixelAdvance = 0;
floatAdvanceUnits = 0;
if (lastBreak < 0 || width + hyphenatedAdvance <= aWidth) {
// We can break here.
@ -1122,7 +1110,6 @@ gfxTextRun::BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
}
width += advance;
advance = 0;
if (width > aWidth) {
// No more text fits. Abort
aborted = PR_TRUE;
@ -1133,12 +1120,12 @@ gfxTextRun::BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
if (i >= ligatureRunStart && i < ligatureRunEnd) {
CompressedGlyph *glyphData = &charGlyphs[i];
if (glyphData->IsSimpleGlyph()) {
advance += glyphData->GetSimpleAdvance();
pixelAdvance += glyphData->GetSimpleAdvance();
} else if (glyphData->IsComplexCluster()) {
NS_ASSERTION(mDetailedGlyphs, "No details but we have a complex cluster...");
DetailedGlyph *details = mDetailedGlyphs[i];
for (;;) {
advance += details->mAdvance;
floatAdvanceUnits += details->mAdvance*mAppUnitsPerDevUnit;
if (details->mIsLastGlyph)
break;
++details;
@ -1146,14 +1133,15 @@ gfxTextRun::BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
}
if (haveSpacing) {
PropertyProvider::Spacing *space = &spacingBuffer[i - bufferStart];
advance += space->mBefore + space->mAfter;
floatAdvanceUnits += space->mBefore + space->mAfter;
}
} else {
advance += GetPartialLigatureWidth(i, i + 1, aProvider);
floatAdvanceUnits += GetPartialLigatureWidth(i, i + 1, aProvider);
}
}
if (!aborted) {
gfxFloat advance = gfxFloat(pixelAdvance)*mAppUnitsPerDevUnit + floatAdvanceUnits;
width += advance;
}
@ -1217,6 +1205,7 @@ gfxTextRun::GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength,
}
}
PRUint32 pixelAdvance = 0;
PRUint32 ligatureRunStart = aStart;
PRUint32 ligatureRunEnd = aStart + aLength;
ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
@ -1228,12 +1217,12 @@ gfxTextRun::GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength,
for (i = ligatureRunStart; i < ligatureRunEnd; ++i) {
CompressedGlyph *glyphData = &charGlyphs[i];
if (glyphData->IsSimpleGlyph()) {
result += glyphData->GetSimpleAdvance();
pixelAdvance += glyphData->GetSimpleAdvance();
} else if (glyphData->IsComplexCluster()) {
NS_ASSERTION(mDetailedGlyphs, "No details but we have a complex cluster...");
DetailedGlyph *details = mDetailedGlyphs[i];
for (;;) {
result += details->mAdvance;
result += details->mAdvance*mAppUnitsPerDevUnit;
if (details->mIsLastGlyph)
break;
++details;
@ -1241,7 +1230,7 @@ gfxTextRun::GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength,
}
}
return result;
return result + gfxFloat(pixelAdvance)*mAppUnitsPerDevUnit;
}
@ -1310,9 +1299,6 @@ void
gfxTextRun::SetDetailedGlyphs(PRUint32 aIndex, DetailedGlyph *aGlyphs,
PRUint32 aCount)
{
NS_ASSERTION(aCount > 0, "Can't set zero detailed glyphs");
NS_ASSERTION(aGlyphs[aCount - 1].mIsLastGlyph, "Failed to set last glyph flag");
if (!mCharacterGlyphs)
return;
@ -1349,4 +1335,4 @@ gfxTextRun::RecordSurrogates(const PRUnichar *aString)
SetCharacterGlyph(i, g.SetLowSurrogate());
}
}
}
}

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

@ -592,28 +592,6 @@ gfxPangoFont::GetPangoFont()
return pango_context_load_font(mPangoCtx, mPangoFontDesc);
}
nsString
gfxPangoFont::GetUniqueName()
{
PangoFont *font = GetPangoFont();
PangoFontDescription *desc = pango_font_describe(font);
char *str = pango_font_description_to_string(desc);
// chop off the trailing size, e.g. "Albany AMT 15.359375" -> "Albany AMT"
PRUint32 end = strlen(str);
while (end > 0) {
--end;
if (str[end] == ' ')
break;
}
str[end] = 0;
nsString result;
CopyUTF8toUTF16(str, result);
g_free(str);
return result;
}
static const char *sCJKLangGroup[] = {
"ja",
"ko",
@ -739,13 +717,13 @@ gfxPangoFontGroup::InitTextRun(gfxTextRun *aTextRun, const gchar *aUTF8Text,
static gfxTextRun::Metrics
GetPangoMetrics(PangoGlyphString *aGlyphs, PangoFont *aPangoFont,
PRUint32 aPixelsToUnits, PRUint32 aClusterCount)
gfxFloat aPixelsToUnits, PRUint32 aClusterCount)
{
PangoRectangle inkRect;
PangoRectangle logicalRect;
pango_glyph_string_extents(aGlyphs, aPangoFont, &inkRect, &logicalRect);
gfxFloat scale = aPixelsToUnits/gfxFloat(PANGO_SCALE);
gfxFloat scale = aPixelsToUnits/PANGO_SCALE;
gfxTextRun::Metrics metrics;
NS_ASSERTION(logicalRect.x == 0, "Weird logical rect...");
@ -771,7 +749,7 @@ gfxPangoFont::Measure(gfxTextRun *aTextRun,
const gfxTextRun::CompressedGlyph *charGlyphs = aTextRun->GetCharacterGlyphs();
nsAutoTArray<PangoGlyphInfo,200> glyphBuffer;
const gfxFloat appUnitsToPango = gfxFloat(PANGO_SCALE)/aTextRun->GetAppUnitsPerDevUnit();
gfxFloat appUnitsToPango = gfxFloat(PANGO_SCALE)/aTextRun->GetAppUnitsPerDevUnit();
// We start by assuming every character is a cluster and subtract off
// characters where that's not true
@ -844,8 +822,7 @@ gfxPangoFont::Measure(gfxTextRun *aTextRun,
glyphs.glyphs = glyphBuffer.Elements();
glyphs.log_clusters = nsnull;
glyphs.space = glyphBuffer.Length();
return GetPangoMetrics(&glyphs, GetPangoFont(),
aTextRun->GetAppUnitsPerDevUnit(), clusterCount);
return GetPangoMetrics(&glyphs, GetPangoFont(), aTextRun->GetAppUnitsPerDevUnit(), clusterCount);
}
#define IS_MISSING_GLYPH(g) (((g) & 0x10000000) || (g) == 0x0FFFFFFF)
@ -934,13 +911,6 @@ SetupClusterBoundaries(gfxTextRun* aTextRun, const gchar *aUTF8, PRUint32 aUTF8L
}
}
static PRInt32
ConvertPangoToAppUnits(PRInt32 aCoordinate, PRUint32 aAppUnitsPerDevUnit)
{
PRInt64 v = (PRInt64(aCoordinate)*aAppUnitsPerDevUnit + PANGO_SCALE/2)/PANGO_SCALE;
return PRInt32(v);
}
nsresult
gfxPangoFontGroup::SetGlyphs(gfxTextRun* aTextRun,
const gchar *aUTF8, PRUint32 aUTF8Length,
@ -960,7 +930,6 @@ gfxPangoFontGroup::SetGlyphs(gfxTextRun* aTextRun,
PRInt32 direction = aTextRun->IsRightToLeft() ? -1 : 1;
gfxTextRun::CompressedGlyph g;
nsAutoTArray<gfxTextRun::DetailedGlyph,1> detailedGlyphs;
const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit();
while (index < aUTF8Length) {
if (utf16Offset >= textRunLength) {
@ -1009,13 +978,13 @@ gfxPangoFontGroup::SetGlyphs(gfxTextRun* aTextRun,
width = aOverrideSpaceWidth;
}
PRInt32 advance = ConvertPangoToAppUnits(width, appUnitsPerDevUnit);
PRInt32 downscaledWidth = width/PANGO_SCALE;
if (glyphClusterCount == 1 &&
glyph->geometry.x_offset == 0 && glyph->geometry.y_offset == 0 &&
advance >= 0 &&
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
width >= 0 && downscaledWidth*PANGO_SCALE == width &&
gfxTextRun::CompressedGlyph::IsSimpleAdvancePixels(downscaledWidth) &&
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(glyph->glyph)) {
aTextRun->SetCharacterGlyph(utf16Offset, g.SetSimpleGlyph(advance, glyph->glyph));
aTextRun->SetCharacterGlyph(utf16Offset, g.SetSimpleGlyph(downscaledWidth, glyph->glyph));
} else if (haveMissingGlyph) {
// Note that missing-glyph IDs are not simple glyph IDs, so we'll
// always get here when a glyph is missing
@ -1032,13 +1001,9 @@ gfxPangoFontGroup::SetGlyphs(gfxTextRun* aTextRun,
details->mGlyphID = glyph->glyph;
NS_ASSERTION(details->mGlyphID == glyph->glyph,
"Seriously weird glyph ID detected!");
details->mAdvance =
ConvertPangoToAppUnits(glyph->geometry.width,
appUnitsPerDevUnit);
details->mXOffset =
float(glyph->geometry.x_offset)*appUnitsPerDevUnit/PANGO_SCALE;
details->mYOffset =
float(glyph->geometry.y_offset)*appUnitsPerDevUnit/PANGO_SCALE;
details->mAdvance = float(glyph->geometry.width)/PANGO_SCALE;
details->mXOffset = float(glyph->geometry.x_offset)/PANGO_SCALE;
details->mYOffset = float(glyph->geometry.y_offset)/PANGO_SCALE;
glyph += direction;
}
aTextRun->SetDetailedGlyphs(utf16Offset, detailedGlyphs.Elements(), glyphClusterCount);
@ -1070,7 +1035,6 @@ gfxPangoFontGroup::CreateGlyphRunsXft(gfxTextRun *aTextRun,
XftFont *xfont = font->GetXftFont();
PRUint32 utf16Offset = 0;
gfxTextRun::CompressedGlyph g;
const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit();
while (p < aUTF8 + aUTF8Length) {
gunichar ch = g_utf8_get_char(p);
@ -1086,13 +1050,12 @@ gfxPangoFontGroup::CreateGlyphRunsXft(gfxTextRun *aTextRun,
if (info.yOff > 0) {
NS_WARNING("vertical offsets not supported");
}
PRInt32 advance = info.xOff*appUnitsPerDevUnit;
if (advance >= 0 &&
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
if (info.xOff >= 0 &&
gfxTextRun::CompressedGlyph::IsSimpleAdvancePixels(info.xOff) &&
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(glyph)) {
aTextRun->SetCharacterGlyph(utf16Offset,
g.SetSimpleGlyph(advance, glyph));
g.SetSimpleGlyph(info.xOff, glyph));
} else if (IS_MISSING_GLYPH(glyph)) {
// Note that missing-glyph IDs are not simple glyph IDs, so we'll
// always get here when a glyph is missing
@ -1103,12 +1066,12 @@ gfxPangoFontGroup::CreateGlyphRunsXft(gfxTextRun *aTextRun,
details.mGlyphID = glyph;
NS_ASSERTION(details.mGlyphID == glyph,
"Seriously weird glyph ID detected!");
details.mAdvance = advance;
details.mAdvance = float(info.xOff);
details.mXOffset = 0;
details.mYOffset = 0;
aTextRun->SetDetailedGlyphs(utf16Offset, &details, 1);
}
NS_ASSERTION(!IS_SURROGATE(ch), "Surrogates shouldn't appear in UTF8");
if (ch >= 0x10000) {
// This character is a surrogate pair in UTF16

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

@ -612,25 +612,25 @@ SetupContextFont(gfxContext *aContext, gfxWindowsFont *aFont,
}
static void
SetupTextRunFromCharacterPlacement(gfxTextRun *aRun, double aCairoToAppUnits,
SetupTextRunFromCharacterPlacement(gfxTextRun *aRun, double aCairoToPixels,
int *aDXs, WCHAR *aGlyphs, gfxFont *aFont)
{
gfxTextRun::CompressedGlyph g;
PRUint32 i;
PRUint32 length = aRun->GetLength();
for (i = 0; i < length; ++i) {
double advance = aDXs[i]*aCairoToAppUnits;
PRInt32 advanceAppUnits = PRInt32(advance);
double advance = aDXs[i]*aCairoToPixels;
PRInt32 advancePixels = PRInt32(advance);
WCHAR glyph = aGlyphs[i];
if (advanceAppUnits >= 0 &&
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advanceAppUnits) &&
if (advance >= 0 && advance == advancePixels &&
gfxTextRun::CompressedGlyph::IsSimpleAdvancePixels(advancePixels) &&
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(glyph)) {
aRun->SetCharacterGlyph(i, g.SetSimpleGlyph(advanceAppUnits, glyph));
aRun->SetCharacterGlyph(i, g.SetSimpleGlyph(advancePixels, glyph));
} else {
gfxTextRun::DetailedGlyph details;
details.mIsLastGlyph = PR_TRUE;
details.mGlyphID = glyph;
details.mAdvance = advanceAppUnits;
details.mAdvance = float(advance);
details.mXOffset = 0;
details.mYOffset = 0;
aRun->SetDetailedGlyphs(i, &details, 1);
@ -708,8 +708,7 @@ gfxWindowsFontGroup::InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun,
results.lpGlyphs = glyphArray.Elements();
GetCharacterPlacementA(dc, aString, aLength, 0, &results, GCP_USEKERNING);
SetupTextRunFromCharacterPlacement(aRun, cairoToPixels*aRun->GetAppUnitsPerDevUnit(),
dxArray.Elements(),
SetupTextRunFromCharacterPlacement(aRun, cairoToPixels, dxArray.Elements(),
glyphArray.Elements(), font);
}
@ -742,8 +741,7 @@ gfxWindowsFontGroup::InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun,
results.lpGlyphs = glyphArray.Elements();
GetCharacterPlacementW(dc, aString, aLength, 0, &results, GCP_USEKERNING);
SetupTextRunFromCharacterPlacement(aRun, cairoToPixels*aRun->GetAppUnitsPerDevUnit(),
dxArray.Elements(),
SetupTextRunFromCharacterPlacement(aRun, cairoToPixels, dxArray.Elements(),
glyphArray.Elements(), font);
}
@ -1150,7 +1148,6 @@ public:
PRUint32 offset = 0;
nsAutoTArray<gfxTextRun::DetailedGlyph,1> detailedGlyphs;
gfxTextRun::CompressedGlyph g;
const PRUint32 appUnitsPerDevUnit = aRun->GetAppUnitsPerDevUnit();
while (offset < mLength) {
PRUint32 runOffset = offsetInRun + offset;
if (offset > 0 && mClusters[offset] == mClusters[offset - 1]) {
@ -1176,13 +1173,13 @@ public:
missing = PR_TRUE;
}
}
PRInt32 advance = mAdvances[k]*appUnitsPerDevUnit;
int advance = mAdvances[k];
WORD glyph = mGlyphs[k];
if (missing) {
aRun->SetCharacterGlyph(runOffset, g.SetMissing());
} else if (glyphCount == 1 && advance >= 0 &&
mOffsets[k].dv == 0 && mOffsets[k].du == 0 &&
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
gfxTextRun::CompressedGlyph::IsSimpleAdvancePixels(advance) &&
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(glyph)) {
aRun->SetCharacterGlyph(runOffset, g.SetSimpleGlyph(advance, glyph));
} else {
@ -1195,9 +1192,9 @@ public:
gfxTextRun::DetailedGlyph *details = &detailedGlyphs[i];
details->mIsLastGlyph = i == glyphCount - 1;
details->mGlyphID = mGlyphs[k + i];
details->mAdvance = mAdvances[k + i]*appUnitsPerDevUnit;
details->mXOffset = float(mOffsets[k + i].du)*appUnitsPerDevUnit;
details->mYOffset = float(mOffsets[k + i].dv)*appUnitsPerDevUnit;
details->mAdvance = float(mAdvances[k + i]);
details->mXOffset = float(mOffsets[k + i].du);
details->mYOffset = float(mOffsets[k + i].dv);
}
aRun->SetDetailedGlyphs(runOffset, detailedGlyphs.Elements(), glyphCount);
}

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

@ -54,11 +54,17 @@ REQUIRES = \
thebes \
$(NULL)
MAIN_CPPSRCS = $(NULL)
# All platforms
CPPSRCS = \
gfxSurfaceRefCountTest.cpp \
gfxFontSelectionTest.cpp \
$(NULL)
MAIN_CPPSRCS += gfxSurfaceRefCountTest.cpp
# mac and win32 for now
ifneq (,$(filter windows cocoa,$(MOZ_WIDGET_TOOLKIT)))
MAIN_CPPSRCS += gfxFontSelectionTest.cpp
endif
CPPSRCS = $(MAIN_CPPSRCS)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
CMMSRCS = gfxTestCocoaHelper.mm
@ -88,15 +94,4 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
OS_LIBS += -framework Cocoa
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
OS_LIBS += $(MOZ_PANGO_LIBS) $(MOZ_XFT_LIBS) $(XLIBS)
endif
include $(topsrcdir)/config/rules.mk
CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
CFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
ifdef MOZ_ENABLE_PANGO
CXXFLAGS += $(MOZ_PANGO_CFLAGS)
endif

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

@ -59,10 +59,6 @@
#include "gfxTestCocoaHelper.h"
#endif
#ifdef MOZ_WIDGET_GTK2
#include "gtk/gtk.h"
#endif
enum {
S_UTF8 = 0,
S_ASCII = 1
@ -111,8 +107,7 @@ struct TestEntry {
: utf8FamilyString(aUTF8FamilyString),
fontStyle(aFontStyle),
stringType(S_ASCII),
string(aString),
isRTL(PR_FALSE)
string(aString)
{
}
@ -123,8 +118,7 @@ struct TestEntry {
: utf8FamilyString(aUTF8FamilyString),
fontStyle(aFontStyle),
stringType(stringType),
string(aString),
isRTL(PR_FALSE)
string(aString)
{
}
@ -143,7 +137,7 @@ struct TestEntry {
if (/*!fontName.IsEmpty() &&*/ !fontName.Equals(aFontName))
return PR_FALSE;
if (num_glyphs != int(glyphs.data.Length()))
if (num_glyphs != glyphs.data.Length())
return PR_FALSE;
for (int j = 0; j < num_glyphs; j++) {
@ -157,11 +151,6 @@ struct TestEntry {
nsCString fontName;
LiteralArray glyphs;
};
void SetRTL()
{
isRTL = PR_TRUE;
}
// empty/NULL fontName means ignore font name
void Expect (const char *platform,
@ -184,9 +173,6 @@ struct TestEntry {
#elif defined(XP_MACOSX)
if (strcmp(platform, "macosx"))
return;
#elif defined(MOZ_ENABLE_PANGO)
if (strcmp(platform, "gtk2-pango"))
return;
#else
return;
#endif
@ -216,7 +202,6 @@ struct TestEntry {
int stringType;
char *string;
PRPackedBool isRTL;
nsTArray<ExpectItem> expectItems;
};
@ -230,7 +215,7 @@ MakeContext ()
nsRefPtr<gfxASurface> surface;
surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(size, size), gfxASurface::ImageFormatRGB24);
surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, size, gfxASurface::ImageFormatRGB24);
gfxContext *ctx = new gfxContext(surface);
NS_IF_ADDREF(ctx);
return ctx;
@ -267,7 +252,7 @@ DumpStore (gfxFontTestStore *store) {
printf ("Run[% 2d]: '%s' ", i, nsPromiseFlatCString(store->items[i].platformFont).get());
for (int j = 0; j < store->items[i].num_glyphs; j++)
printf ("%d ", int(store->items[i].glyphs[j].index));
printf ("%d ", store->items[i].glyphs[j].index);
printf ("\n");
}
@ -278,7 +263,7 @@ DumpTestExpect (TestEntry *test) {
for (PRUint32 i = 0; i < test->expectItems.Length(); i++) {
printf ("Run[% 2d]: '%s' ", i, nsPromiseFlatCString(test->expectItems[i].fontName).get());
for (PRUint32 j = 0; j < test->expectItems[i].glyphs.data.Length(); j++)
printf ("%d ", int(test->expectItems[i].glyphs.data[j]));
printf ("%d ", test->expectItems[i].glyphs.data[j]);
printf ("\n");
}
@ -299,28 +284,16 @@ RunTest (TestEntry *test, gfxContext *ctx) {
return PR_FALSE;
#endif
nsAutoPtr<gfxTextRun> textRun;
gfxTextRunFactory::Parameters params = {
ctx, nsnull, nsnull, nsnull, nsnull, 0, 60,
gfxTextRunFactory::TEXT_IS_ASCII
};
if (test->isRTL) {
params.mFlags |= gfxTextRunFactory::TEXT_IS_RTL;
}
PRUint32 length;
nsRefPtr<gfxTextRun> textRun;
if (test->stringType == S_ASCII) {
params.mFlags |= gfxTextRunFactory::TEXT_IS_ASCII;
length = strlen(test->string);
textRun = fontGroup->MakeTextRun(NS_REINTERPRET_CAST(PRUint8*, test->string), length, &params);
textRun = fontGroup->MakeTextRun(nsDependentCString(test->string));
} else {
params.mFlags |= gfxTextRunFactory::TEXT_HAS_SURROGATES; // just in case
NS_ConvertUTF8toUTF16 str(nsDependentCString(test->string));
length = str.Length();
textRun = fontGroup->MakeTextRun(str.get(), length, &params);
textRun = fontGroup->MakeTextRun(NS_ConvertUTF8toUTF16(nsDependentCString(test->string)));
}
gfxFontTestStore::NewStore();
textRun->Draw(ctx, gfxPoint(0,0), 0, length, nsnull, nsnull, nsnull);
textRun->Draw(ctx, gfxPoint(0,0));
gfxFontTestStore *s = gfxFontTestStore::CurrentStore();
if (!test->Check(s)) {
@ -338,10 +311,6 @@ main (int argc, char **argv) {
int passed = 0;
int failed = 0;
#ifdef MOZ_WIDGET_GTK2
gtk_init(&argc, &argv);
#endif
// Initialize XPCOM
nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
if (NS_FAILED(rv))

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

@ -131,7 +131,6 @@ SetupTests()
t->Expect ("win32", "Arial", GLYPHS(36, 37, 38, 39));
t->Expect ("macosx", "Helvetica", GLYPHS(36, 37, 38, 39));
t->Expect ("gtk2-pango", "Albany AMT", GLYPHS(36, 37, 38, 39));
/* Test 1 */
t = AddTest ("verdana,sans-serif",
@ -155,61 +154,4 @@ SetupTests()
t->Expect ("win32", "Arial:700", GLYPHS(36, 37, 38, 39));
t->Expect ("macosx", "Helvetica-Bold", GLYPHS(36, 37, 38, 39));
t->Expect ("gtk2-pango", "Albany AMT Bold", GLYPHS(36, 37, 38, 39));
/* Test 3: RTL Arabic with a ligature and leading and trailing whitespace */
t = AddTest ("sans-serif",
style_western_normal_16,
S_UTF8,
" \xd8\xaa\xd9\x85 ");
t->SetRTL();
t->Expect ("macosx", "Helvetica", GLYPHS(3));
t->Expect ("macosx", "AlBayan", GLYPHS(47));
t->Expect ("macosx", "Helvetica", GLYPHS(3));
/* Test 4: LTR Arabic with leading and trailing whitespace */
t = AddTest ("sans-serif",
style_western_normal_16,
S_UTF8,
" \xd9\x85\xd8\xaa ");
t->Expect ("macosx", "Helvetica", GLYPHS(3));
t->Expect ("macosx", "AlBayan", GLYPHS(2, 47));
t->Expect ("macosx", "Helvetica", GLYPHS(3));
/* Test 5: RTL ASCII with leading whitespace */
t = AddTest ("sans-serif",
style_western_normal_16,
S_ASCII,
" ab");
t->SetRTL();
t->Expect ("macosx", "Helvetica", GLYPHS(3, 68, 69));
t->Expect ("win32", "Arial", GLYPHS(3, 68, 69));
t->Expect ("gtk2-pango", "Albany AMT", GLYPHS(3, 68, 69));
/* Test 6: RTL ASCII with trailing whitespace */
t = AddTest ("sans-serif",
style_western_normal_16,
S_ASCII,
"ab ");
t->SetRTL();
t->Expect ("macosx", "Helvetica", GLYPHS(68, 69, 3));
t->Expect ("win32", "Arial", GLYPHS(68, 69, 3));
t->Expect ("gtk2-pango", "Albany AMT", GLYPHS(68, 69, 3));
/* Test 7: Simple ASCII ligature */
/* Do we have a Windows font with ligatures? Can we use DejaVu Sans? */
t = AddTest ("sans-serif",
style_western_normal_16,
S_ASCII,
"fi");
t->Expect ("macosx", "Helvetica", GLYPHS(192));
/* Test 8: DEVANAGARI VOWEL I reordering */
/* The glyph for DEVANAGARI VOWEL I 2367 (101) is displayed before the glyph for 2361 (99) */
t = AddTest ("sans-serif",
style_western_normal_16,
S_UTF8,
"\xe0\xa4\x9a\xe0\xa4\xbe\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x8f"); // 2330 2366 2361 2367 2319
t->Expect ("macosx", "DevanagariMT", GLYPHS(71, 100, 101, 99, 60));
t->Expect ("win32", "Mangal", GLYPHS(133, 545, 465, 161, 102));
}

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

@ -3,8 +3,6 @@
#include "gfxASurface.h"
#include "gfxImageSurface.h"
#include "cairo.h"
int
GetASurfaceRefCount(gfxASurface *s) {
NS_ADDREF(s);
@ -42,7 +40,7 @@ TestNewSurface () {
int failures = 0;
int destroyed = 0;
nsRefPtr<gfxASurface> s = new gfxImageSurface (gfxIntSize(10, 10), gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxASurface> s = new gfxImageSurface (gfxASurface::ImageFormatARGB32, 10, 10);
cairo_surface_t *cs = s->CairoSurface();
cairo_surface_set_user_data (cs, &destruction_key, &destroyed, SurfaceDestroyNotifier);