|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef NSTEXTRUNTRANSFORMATIONS_H_ |
|
7 #define NSTEXTRUNTRANSFORMATIONS_H_ |
|
8 |
|
9 #include "mozilla/Attributes.h" |
|
10 #include "mozilla/MemoryReporting.h" |
|
11 #include "gfxFont.h" |
|
12 |
|
13 class nsTransformedTextRun; |
|
14 class nsStyleContext; |
|
15 |
|
16 class nsTransformingTextRunFactory { |
|
17 public: |
|
18 virtual ~nsTransformingTextRunFactory() {} |
|
19 |
|
20 // Default 8-bit path just transforms to Unicode and takes that path |
|
21 nsTransformedTextRun* MakeTextRun(const uint8_t* aString, uint32_t aLength, |
|
22 const gfxFontGroup::Parameters* aParams, |
|
23 gfxFontGroup* aFontGroup, uint32_t aFlags, |
|
24 nsStyleContext** aStyles, bool aOwnsFactory = true); |
|
25 nsTransformedTextRun* MakeTextRun(const char16_t* aString, uint32_t aLength, |
|
26 const gfxFontGroup::Parameters* aParams, |
|
27 gfxFontGroup* aFontGroup, uint32_t aFlags, |
|
28 nsStyleContext** aStyles, bool aOwnsFactory = true); |
|
29 |
|
30 virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) = 0; |
|
31 }; |
|
32 |
|
33 /** |
|
34 * Builds textruns that render their text using a font-variant (i.e., |
|
35 * smallcaps). |
|
36 */ |
|
37 class nsFontVariantTextRunFactory : public nsTransformingTextRunFactory { |
|
38 public: |
|
39 virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) MOZ_OVERRIDE; |
|
40 }; |
|
41 |
|
42 /** |
|
43 * Builds textruns that transform the text in some way (e.g., capitalize) |
|
44 * and then render the text using some other textrun implementation. |
|
45 */ |
|
46 class nsCaseTransformTextRunFactory : public nsTransformingTextRunFactory { |
|
47 public: |
|
48 // We could add an optimization here so that when there is no inner |
|
49 // factory, no title-case conversion, and no upper-casing of SZLIG, we override |
|
50 // MakeTextRun (after making it virtual in the superclass) and have it |
|
51 // just convert the string to uppercase or lowercase and create the textrun |
|
52 // via the fontgroup. |
|
53 |
|
54 // Takes ownership of aInnerTransformTextRunFactory |
|
55 nsCaseTransformTextRunFactory(nsTransformingTextRunFactory* aInnerTransformingTextRunFactory, |
|
56 bool aAllUppercase = false) |
|
57 : mInnerTransformingTextRunFactory(aInnerTransformingTextRunFactory), |
|
58 mAllUppercase(aAllUppercase) {} |
|
59 |
|
60 virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) MOZ_OVERRIDE; |
|
61 |
|
62 protected: |
|
63 nsAutoPtr<nsTransformingTextRunFactory> mInnerTransformingTextRunFactory; |
|
64 bool mAllUppercase; |
|
65 }; |
|
66 |
|
67 /** |
|
68 * So that we can reshape as necessary, we store enough information |
|
69 * to fully rebuild the textrun contents. |
|
70 */ |
|
71 class nsTransformedTextRun : public gfxTextRun { |
|
72 public: |
|
73 static nsTransformedTextRun *Create(const gfxTextRunFactory::Parameters* aParams, |
|
74 nsTransformingTextRunFactory* aFactory, |
|
75 gfxFontGroup* aFontGroup, |
|
76 const char16_t* aString, uint32_t aLength, |
|
77 const uint32_t aFlags, nsStyleContext** aStyles, |
|
78 bool aOwnsFactory); |
|
79 |
|
80 ~nsTransformedTextRun() { |
|
81 if (mOwnsFactory) { |
|
82 delete mFactory; |
|
83 } |
|
84 } |
|
85 |
|
86 void SetCapitalization(uint32_t aStart, uint32_t aLength, |
|
87 bool* aCapitalization, |
|
88 gfxContext* aRefContext); |
|
89 virtual bool SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength, |
|
90 uint8_t* aBreakBefore, |
|
91 gfxContext* aRefContext); |
|
92 /** |
|
93 * Called after SetCapitalization and SetPotentialLineBreaks |
|
94 * are done and before we request any data from the textrun. Also always |
|
95 * called after a Create. |
|
96 */ |
|
97 void FinishSettingProperties(gfxContext* aRefContext) |
|
98 { |
|
99 if (mNeedsRebuild) { |
|
100 mNeedsRebuild = false; |
|
101 mFactory->RebuildTextRun(this, aRefContext); |
|
102 } |
|
103 } |
|
104 |
|
105 // override the gfxTextRun impls to account for additional members here |
|
106 virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) MOZ_MUST_OVERRIDE; |
|
107 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) MOZ_MUST_OVERRIDE; |
|
108 |
|
109 nsTransformingTextRunFactory *mFactory; |
|
110 nsTArray<nsRefPtr<nsStyleContext> > mStyles; |
|
111 nsTArray<bool> mCapitalize; |
|
112 nsString mString; |
|
113 bool mOwnsFactory; |
|
114 bool mNeedsRebuild; |
|
115 |
|
116 private: |
|
117 nsTransformedTextRun(const gfxTextRunFactory::Parameters* aParams, |
|
118 nsTransformingTextRunFactory* aFactory, |
|
119 gfxFontGroup* aFontGroup, |
|
120 const char16_t* aString, uint32_t aLength, |
|
121 const uint32_t aFlags, nsStyleContext** aStyles, |
|
122 bool aOwnsFactory) |
|
123 : gfxTextRun(aParams, aLength, aFontGroup, aFlags), |
|
124 mFactory(aFactory), mString(aString, aLength), |
|
125 mOwnsFactory(aOwnsFactory), mNeedsRebuild(true) |
|
126 { |
|
127 mCharacterGlyphs = reinterpret_cast<CompressedGlyph*>(this + 1); |
|
128 |
|
129 uint32_t i; |
|
130 for (i = 0; i < aLength; ++i) { |
|
131 mStyles.AppendElement(aStyles[i]); |
|
132 } |
|
133 } |
|
134 }; |
|
135 |
|
136 /** |
|
137 * Copy a given textrun, but merge certain characters into a single logical |
|
138 * character. Glyphs for a character are added to the glyph list for the previous |
|
139 * character and then the merged character is eliminated. Visually the results |
|
140 * are identical. |
|
141 * |
|
142 * This is used for text-transform:uppercase when we encounter a SZLIG, |
|
143 * whose uppercase form is "SS", or other ligature or precomposed form |
|
144 * that expands to multiple codepoints during case transformation, |
|
145 * and for Greek text when combining diacritics have been deleted. |
|
146 * |
|
147 * This function is unable to merge characters when they occur in different |
|
148 * glyph runs. This only happens in tricky edge cases where a character was |
|
149 * decomposed by case-mapping (e.g. there's no precomposed uppercase version |
|
150 * of an accented lowercase letter), and then font-matching caused the |
|
151 * diacritics to be assigned to a different font than the base character. |
|
152 * In this situation, the diacritic(s) get discarded, which is less than |
|
153 * ideal, but they probably weren't going to render very well anyway. |
|
154 * Bug 543200 will improve this by making font-matching operate on entire |
|
155 * clusters instead of individual codepoints. |
|
156 * |
|
157 * For simplicity, this produces a textrun containing all DetailedGlyphs, |
|
158 * no simple glyphs. So don't call it unless you really have merging to do. |
|
159 * |
|
160 * @param aCharsToMerge when aCharsToMerge[i] is true, this character in aSrc |
|
161 * is merged into the previous character |
|
162 * |
|
163 * @param aDeletedChars when aDeletedChars[i] is true, the character at this |
|
164 * position in aDest was deleted (has no corresponding char in aSrc) |
|
165 */ |
|
166 void |
|
167 MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc, |
|
168 const bool* aCharsToMerge, const bool* aDeletedChars); |
|
169 |
|
170 gfxTextRunFactory::Parameters |
|
171 GetParametersForInner(nsTransformedTextRun* aTextRun, uint32_t* aFlags, |
|
172 gfxContext* aRefContext); |
|
173 |
|
174 |
|
175 #endif /*NSTEXTRUNTRANSFORMATIONS_H_*/ |