From 5d0896ff66c83495c4b32efe574d85ca729f5611 Mon Sep 17 00:00:00 2001 From: "roc+%cs.cmu.edu" Date: Tue, 20 Mar 2007 03:00:11 +0000 Subject: [PATCH] Backout the last couple of gfx checkins because the bugs and patches were mixed up. I'll reland. --- gfx/thebes/Makefile.in | 2 +- gfx/thebes/public/gfxAtsuiFonts.h | 11 +- gfx/thebes/public/gfxFont.h | 44 +-- gfx/thebes/public/gfxPangoFonts.h | 2 - gfx/thebes/src/gfxAtsuiFonts.cpp | 409 +++++++++------------ gfx/thebes/src/gfxFont.cpp | 186 +++++----- gfx/thebes/src/gfxPangoFonts.cpp | 71 +--- gfx/thebes/src/gfxWindowsFonts.cpp | 31 +- gfx/thebes/test/Makefile.in | 25 +- gfx/thebes/test/gfxFontSelectionTest.cpp | 53 +-- gfx/thebes/test/gfxFontSelectionTests.h | 58 --- gfx/thebes/test/gfxSurfaceRefCountTest.cpp | 4 +- 12 files changed, 341 insertions(+), 555 deletions(-) diff --git a/gfx/thebes/Makefile.in b/gfx/thebes/Makefile.in index 0a57d8dc362f..fd77f371ea65 100644 --- a/gfx/thebes/Makefile.in +++ b/gfx/thebes/Makefile.in @@ -11,7 +11,7 @@ MODULE = thebes DIRS = public src ifdef ENABLE_TESTS -TOOL_DIRS += test +# TOOL_DIRS += test endif include $(topsrcdir)/config/rules.mk diff --git a/gfx/thebes/public/gfxAtsuiFonts.h b/gfx/thebes/public/gfxAtsuiFonts.h index 3ef2cabd6d1d..fe4784ebc8b1 100644 --- a/gfx/thebes/public/gfxAtsuiFonts.h +++ b/gfx/thebes/public/gfxAtsuiFonts.h @@ -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; }; diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h index d7dabea78b17..806fc3131436 100644 --- a/gfx/thebes/public/gfxFont.h +++ b/gfx/thebes/public/gfxFont.h @@ -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; }; diff --git a/gfx/thebes/public/gfxPangoFonts.h b/gfx/thebes/public/gfxPangoFonts.h index 9216b8c27aff..4f473227071b 100644 --- a/gfx/thebes/public/gfxPangoFonts.h +++ b/gfx/thebes/public/gfxPangoFonts.h @@ -82,8 +82,6 @@ public: PRBool aTightBoundingBox, Spacing *aSpacing); - virtual nsString GetUniqueName(); - protected: PangoFontDescription *mPangoFontDesc; PangoContext *mPangoCtx; diff --git a/gfx/thebes/src/gfxAtsuiFonts.cpp b/gfx/thebes/src/gfxAtsuiFonts.cpp index 9a20b193809d..0e8c82d98981 100644 --- a/gfx/thebes/src/gfxAtsuiFonts.cpp +++ b/gfx/thebes/src/gfxAtsuiFonts.cpp @@ -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(aString), reinterpret_cast(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 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 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 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); diff --git a/gfx/thebes/src/gfxFont.cpp b/gfx/thebes/src/gfxFont.cpp index 4b15897b10fe..56596f4fd780 100644 --- a/gfx/thebes/src/gfxFont.cpp +++ b/gfx/thebes/src/gfxFont.cpp @@ -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 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 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()); } } -} +} \ No newline at end of file diff --git a/gfx/thebes/src/gfxPangoFonts.cpp b/gfx/thebes/src/gfxPangoFonts.cpp index 0eadd1d8824f..32f5192274a5 100644 --- a/gfx/thebes/src/gfxPangoFonts.cpp +++ b/gfx/thebes/src/gfxPangoFonts.cpp @@ -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 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 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 diff --git a/gfx/thebes/src/gfxWindowsFonts.cpp b/gfx/thebes/src/gfxWindowsFonts.cpp index 72d10c193219..bdeecad9ef24 100644 --- a/gfx/thebes/src/gfxWindowsFonts.cpp +++ b/gfx/thebes/src/gfxWindowsFonts.cpp @@ -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 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); } diff --git a/gfx/thebes/test/Makefile.in b/gfx/thebes/test/Makefile.in index ce396db5a885..44e0af4f9486 100644 --- a/gfx/thebes/test/Makefile.in +++ b/gfx/thebes/test/Makefile.in @@ -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 diff --git a/gfx/thebes/test/gfxFontSelectionTest.cpp b/gfx/thebes/test/gfxFontSelectionTest.cpp index 2cbe1ddf7842..de8e9ff64608 100644 --- a/gfx/thebes/test/gfxFontSelectionTest.cpp +++ b/gfx/thebes/test/gfxFontSelectionTest.cpp @@ -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 expectItems; }; @@ -230,7 +215,7 @@ MakeContext () nsRefPtr 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 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 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, ¶ms); + 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, ¶ms); + 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)) diff --git a/gfx/thebes/test/gfxFontSelectionTests.h b/gfx/thebes/test/gfxFontSelectionTests.h index 5e0d79aa6875..234a00e7c50d 100644 --- a/gfx/thebes/test/gfxFontSelectionTests.h +++ b/gfx/thebes/test/gfxFontSelectionTests.h @@ -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)); } diff --git a/gfx/thebes/test/gfxSurfaceRefCountTest.cpp b/gfx/thebes/test/gfxSurfaceRefCountTest.cpp index f4b66142bd04..366087a0e8d6 100644 --- a/gfx/thebes/test/gfxSurfaceRefCountTest.cpp +++ b/gfx/thebes/test/gfxSurfaceRefCountTest.cpp @@ -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 s = new gfxImageSurface (gfxIntSize(10, 10), gfxASurface::ImageFormatARGB32); + nsRefPtr s = new gfxImageSurface (gfxASurface::ImageFormatARGB32, 10, 10); cairo_surface_t *cs = s->CairoSurface(); cairo_surface_set_user_data (cs, &destruction_key, &destroyed, SurfaceDestroyNotifier);