michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef NSTEXTRUNTRANSFORMATIONS_H_ michael@0: #define NSTEXTRUNTRANSFORMATIONS_H_ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "gfxFont.h" michael@0: michael@0: class nsTransformedTextRun; michael@0: class nsStyleContext; michael@0: michael@0: class nsTransformingTextRunFactory { michael@0: public: michael@0: virtual ~nsTransformingTextRunFactory() {} michael@0: michael@0: // Default 8-bit path just transforms to Unicode and takes that path michael@0: nsTransformedTextRun* MakeTextRun(const uint8_t* aString, uint32_t aLength, michael@0: const gfxFontGroup::Parameters* aParams, michael@0: gfxFontGroup* aFontGroup, uint32_t aFlags, michael@0: nsStyleContext** aStyles, bool aOwnsFactory = true); michael@0: nsTransformedTextRun* MakeTextRun(const char16_t* aString, uint32_t aLength, michael@0: const gfxFontGroup::Parameters* aParams, michael@0: gfxFontGroup* aFontGroup, uint32_t aFlags, michael@0: nsStyleContext** aStyles, bool aOwnsFactory = true); michael@0: michael@0: virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) = 0; michael@0: }; michael@0: michael@0: /** michael@0: * Builds textruns that render their text using a font-variant (i.e., michael@0: * smallcaps). michael@0: */ michael@0: class nsFontVariantTextRunFactory : public nsTransformingTextRunFactory { michael@0: public: michael@0: virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) MOZ_OVERRIDE; michael@0: }; michael@0: michael@0: /** michael@0: * Builds textruns that transform the text in some way (e.g., capitalize) michael@0: * and then render the text using some other textrun implementation. michael@0: */ michael@0: class nsCaseTransformTextRunFactory : public nsTransformingTextRunFactory { michael@0: public: michael@0: // We could add an optimization here so that when there is no inner michael@0: // factory, no title-case conversion, and no upper-casing of SZLIG, we override michael@0: // MakeTextRun (after making it virtual in the superclass) and have it michael@0: // just convert the string to uppercase or lowercase and create the textrun michael@0: // via the fontgroup. michael@0: michael@0: // Takes ownership of aInnerTransformTextRunFactory michael@0: nsCaseTransformTextRunFactory(nsTransformingTextRunFactory* aInnerTransformingTextRunFactory, michael@0: bool aAllUppercase = false) michael@0: : mInnerTransformingTextRunFactory(aInnerTransformingTextRunFactory), michael@0: mAllUppercase(aAllUppercase) {} michael@0: michael@0: virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) MOZ_OVERRIDE; michael@0: michael@0: protected: michael@0: nsAutoPtr mInnerTransformingTextRunFactory; michael@0: bool mAllUppercase; michael@0: }; michael@0: michael@0: /** michael@0: * So that we can reshape as necessary, we store enough information michael@0: * to fully rebuild the textrun contents. michael@0: */ michael@0: class nsTransformedTextRun : public gfxTextRun { michael@0: public: michael@0: static nsTransformedTextRun *Create(const gfxTextRunFactory::Parameters* aParams, michael@0: nsTransformingTextRunFactory* aFactory, michael@0: gfxFontGroup* aFontGroup, michael@0: const char16_t* aString, uint32_t aLength, michael@0: const uint32_t aFlags, nsStyleContext** aStyles, michael@0: bool aOwnsFactory); michael@0: michael@0: ~nsTransformedTextRun() { michael@0: if (mOwnsFactory) { michael@0: delete mFactory; michael@0: } michael@0: } michael@0: michael@0: void SetCapitalization(uint32_t aStart, uint32_t aLength, michael@0: bool* aCapitalization, michael@0: gfxContext* aRefContext); michael@0: virtual bool SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength, michael@0: uint8_t* aBreakBefore, michael@0: gfxContext* aRefContext); michael@0: /** michael@0: * Called after SetCapitalization and SetPotentialLineBreaks michael@0: * are done and before we request any data from the textrun. Also always michael@0: * called after a Create. michael@0: */ michael@0: void FinishSettingProperties(gfxContext* aRefContext) michael@0: { michael@0: if (mNeedsRebuild) { michael@0: mNeedsRebuild = false; michael@0: mFactory->RebuildTextRun(this, aRefContext); michael@0: } michael@0: } michael@0: michael@0: // override the gfxTextRun impls to account for additional members here michael@0: virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) MOZ_MUST_OVERRIDE; michael@0: virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) MOZ_MUST_OVERRIDE; michael@0: michael@0: nsTransformingTextRunFactory *mFactory; michael@0: nsTArray > mStyles; michael@0: nsTArray mCapitalize; michael@0: nsString mString; michael@0: bool mOwnsFactory; michael@0: bool mNeedsRebuild; michael@0: michael@0: private: michael@0: nsTransformedTextRun(const gfxTextRunFactory::Parameters* aParams, michael@0: nsTransformingTextRunFactory* aFactory, michael@0: gfxFontGroup* aFontGroup, michael@0: const char16_t* aString, uint32_t aLength, michael@0: const uint32_t aFlags, nsStyleContext** aStyles, michael@0: bool aOwnsFactory) michael@0: : gfxTextRun(aParams, aLength, aFontGroup, aFlags), michael@0: mFactory(aFactory), mString(aString, aLength), michael@0: mOwnsFactory(aOwnsFactory), mNeedsRebuild(true) michael@0: { michael@0: mCharacterGlyphs = reinterpret_cast(this + 1); michael@0: michael@0: uint32_t i; michael@0: for (i = 0; i < aLength; ++i) { michael@0: mStyles.AppendElement(aStyles[i]); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: /** michael@0: * Copy a given textrun, but merge certain characters into a single logical michael@0: * character. Glyphs for a character are added to the glyph list for the previous michael@0: * character and then the merged character is eliminated. Visually the results michael@0: * are identical. michael@0: * michael@0: * This is used for text-transform:uppercase when we encounter a SZLIG, michael@0: * whose uppercase form is "SS", or other ligature or precomposed form michael@0: * that expands to multiple codepoints during case transformation, michael@0: * and for Greek text when combining diacritics have been deleted. michael@0: * michael@0: * This function is unable to merge characters when they occur in different michael@0: * glyph runs. This only happens in tricky edge cases where a character was michael@0: * decomposed by case-mapping (e.g. there's no precomposed uppercase version michael@0: * of an accented lowercase letter), and then font-matching caused the michael@0: * diacritics to be assigned to a different font than the base character. michael@0: * In this situation, the diacritic(s) get discarded, which is less than michael@0: * ideal, but they probably weren't going to render very well anyway. michael@0: * Bug 543200 will improve this by making font-matching operate on entire michael@0: * clusters instead of individual codepoints. michael@0: * michael@0: * For simplicity, this produces a textrun containing all DetailedGlyphs, michael@0: * no simple glyphs. So don't call it unless you really have merging to do. michael@0: * michael@0: * @param aCharsToMerge when aCharsToMerge[i] is true, this character in aSrc michael@0: * is merged into the previous character michael@0: * michael@0: * @param aDeletedChars when aDeletedChars[i] is true, the character at this michael@0: * position in aDest was deleted (has no corresponding char in aSrc) michael@0: */ michael@0: void michael@0: MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc, michael@0: const bool* aCharsToMerge, const bool* aDeletedChars); michael@0: michael@0: gfxTextRunFactory::Parameters michael@0: GetParametersForInner(nsTransformedTextRun* aTextRun, uint32_t* aFlags, michael@0: gfxContext* aRefContext); michael@0: michael@0: michael@0: #endif /*NSTEXTRUNTRANSFORMATIONS_H_*/