1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsTextRunTransformations.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,175 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef NSTEXTRUNTRANSFORMATIONS_H_ 1.10 +#define NSTEXTRUNTRANSFORMATIONS_H_ 1.11 + 1.12 +#include "mozilla/Attributes.h" 1.13 +#include "mozilla/MemoryReporting.h" 1.14 +#include "gfxFont.h" 1.15 + 1.16 +class nsTransformedTextRun; 1.17 +class nsStyleContext; 1.18 + 1.19 +class nsTransformingTextRunFactory { 1.20 +public: 1.21 + virtual ~nsTransformingTextRunFactory() {} 1.22 + 1.23 + // Default 8-bit path just transforms to Unicode and takes that path 1.24 + nsTransformedTextRun* MakeTextRun(const uint8_t* aString, uint32_t aLength, 1.25 + const gfxFontGroup::Parameters* aParams, 1.26 + gfxFontGroup* aFontGroup, uint32_t aFlags, 1.27 + nsStyleContext** aStyles, bool aOwnsFactory = true); 1.28 + nsTransformedTextRun* MakeTextRun(const char16_t* aString, uint32_t aLength, 1.29 + const gfxFontGroup::Parameters* aParams, 1.30 + gfxFontGroup* aFontGroup, uint32_t aFlags, 1.31 + nsStyleContext** aStyles, bool aOwnsFactory = true); 1.32 + 1.33 + virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) = 0; 1.34 +}; 1.35 + 1.36 +/** 1.37 + * Builds textruns that render their text using a font-variant (i.e., 1.38 + * smallcaps). 1.39 + */ 1.40 +class nsFontVariantTextRunFactory : public nsTransformingTextRunFactory { 1.41 +public: 1.42 + virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) MOZ_OVERRIDE; 1.43 +}; 1.44 + 1.45 +/** 1.46 + * Builds textruns that transform the text in some way (e.g., capitalize) 1.47 + * and then render the text using some other textrun implementation. 1.48 + */ 1.49 +class nsCaseTransformTextRunFactory : public nsTransformingTextRunFactory { 1.50 +public: 1.51 + // We could add an optimization here so that when there is no inner 1.52 + // factory, no title-case conversion, and no upper-casing of SZLIG, we override 1.53 + // MakeTextRun (after making it virtual in the superclass) and have it 1.54 + // just convert the string to uppercase or lowercase and create the textrun 1.55 + // via the fontgroup. 1.56 + 1.57 + // Takes ownership of aInnerTransformTextRunFactory 1.58 + nsCaseTransformTextRunFactory(nsTransformingTextRunFactory* aInnerTransformingTextRunFactory, 1.59 + bool aAllUppercase = false) 1.60 + : mInnerTransformingTextRunFactory(aInnerTransformingTextRunFactory), 1.61 + mAllUppercase(aAllUppercase) {} 1.62 + 1.63 + virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) MOZ_OVERRIDE; 1.64 + 1.65 +protected: 1.66 + nsAutoPtr<nsTransformingTextRunFactory> mInnerTransformingTextRunFactory; 1.67 + bool mAllUppercase; 1.68 +}; 1.69 + 1.70 +/** 1.71 + * So that we can reshape as necessary, we store enough information 1.72 + * to fully rebuild the textrun contents. 1.73 + */ 1.74 +class nsTransformedTextRun : public gfxTextRun { 1.75 +public: 1.76 + static nsTransformedTextRun *Create(const gfxTextRunFactory::Parameters* aParams, 1.77 + nsTransformingTextRunFactory* aFactory, 1.78 + gfxFontGroup* aFontGroup, 1.79 + const char16_t* aString, uint32_t aLength, 1.80 + const uint32_t aFlags, nsStyleContext** aStyles, 1.81 + bool aOwnsFactory); 1.82 + 1.83 + ~nsTransformedTextRun() { 1.84 + if (mOwnsFactory) { 1.85 + delete mFactory; 1.86 + } 1.87 + } 1.88 + 1.89 + void SetCapitalization(uint32_t aStart, uint32_t aLength, 1.90 + bool* aCapitalization, 1.91 + gfxContext* aRefContext); 1.92 + virtual bool SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength, 1.93 + uint8_t* aBreakBefore, 1.94 + gfxContext* aRefContext); 1.95 + /** 1.96 + * Called after SetCapitalization and SetPotentialLineBreaks 1.97 + * are done and before we request any data from the textrun. Also always 1.98 + * called after a Create. 1.99 + */ 1.100 + void FinishSettingProperties(gfxContext* aRefContext) 1.101 + { 1.102 + if (mNeedsRebuild) { 1.103 + mNeedsRebuild = false; 1.104 + mFactory->RebuildTextRun(this, aRefContext); 1.105 + } 1.106 + } 1.107 + 1.108 + // override the gfxTextRun impls to account for additional members here 1.109 + virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) MOZ_MUST_OVERRIDE; 1.110 + virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) MOZ_MUST_OVERRIDE; 1.111 + 1.112 + nsTransformingTextRunFactory *mFactory; 1.113 + nsTArray<nsRefPtr<nsStyleContext> > mStyles; 1.114 + nsTArray<bool> mCapitalize; 1.115 + nsString mString; 1.116 + bool mOwnsFactory; 1.117 + bool mNeedsRebuild; 1.118 + 1.119 +private: 1.120 + nsTransformedTextRun(const gfxTextRunFactory::Parameters* aParams, 1.121 + nsTransformingTextRunFactory* aFactory, 1.122 + gfxFontGroup* aFontGroup, 1.123 + const char16_t* aString, uint32_t aLength, 1.124 + const uint32_t aFlags, nsStyleContext** aStyles, 1.125 + bool aOwnsFactory) 1.126 + : gfxTextRun(aParams, aLength, aFontGroup, aFlags), 1.127 + mFactory(aFactory), mString(aString, aLength), 1.128 + mOwnsFactory(aOwnsFactory), mNeedsRebuild(true) 1.129 + { 1.130 + mCharacterGlyphs = reinterpret_cast<CompressedGlyph*>(this + 1); 1.131 + 1.132 + uint32_t i; 1.133 + for (i = 0; i < aLength; ++i) { 1.134 + mStyles.AppendElement(aStyles[i]); 1.135 + } 1.136 + } 1.137 +}; 1.138 + 1.139 +/** 1.140 + * Copy a given textrun, but merge certain characters into a single logical 1.141 + * character. Glyphs for a character are added to the glyph list for the previous 1.142 + * character and then the merged character is eliminated. Visually the results 1.143 + * are identical. 1.144 + * 1.145 + * This is used for text-transform:uppercase when we encounter a SZLIG, 1.146 + * whose uppercase form is "SS", or other ligature or precomposed form 1.147 + * that expands to multiple codepoints during case transformation, 1.148 + * and for Greek text when combining diacritics have been deleted. 1.149 + * 1.150 + * This function is unable to merge characters when they occur in different 1.151 + * glyph runs. This only happens in tricky edge cases where a character was 1.152 + * decomposed by case-mapping (e.g. there's no precomposed uppercase version 1.153 + * of an accented lowercase letter), and then font-matching caused the 1.154 + * diacritics to be assigned to a different font than the base character. 1.155 + * In this situation, the diacritic(s) get discarded, which is less than 1.156 + * ideal, but they probably weren't going to render very well anyway. 1.157 + * Bug 543200 will improve this by making font-matching operate on entire 1.158 + * clusters instead of individual codepoints. 1.159 + * 1.160 + * For simplicity, this produces a textrun containing all DetailedGlyphs, 1.161 + * no simple glyphs. So don't call it unless you really have merging to do. 1.162 + * 1.163 + * @param aCharsToMerge when aCharsToMerge[i] is true, this character in aSrc 1.164 + * is merged into the previous character 1.165 + * 1.166 + * @param aDeletedChars when aDeletedChars[i] is true, the character at this 1.167 + * position in aDest was deleted (has no corresponding char in aSrc) 1.168 + */ 1.169 +void 1.170 +MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc, 1.171 + const bool* aCharsToMerge, const bool* aDeletedChars); 1.172 + 1.173 +gfxTextRunFactory::Parameters 1.174 +GetParametersForInner(nsTransformedTextRun* aTextRun, uint32_t* aFlags, 1.175 + gfxContext* aRefContext); 1.176 + 1.177 + 1.178 +#endif /*NSTEXTRUNTRANSFORMATIONS_H_*/