Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / layout / generic / nsTextRunTransformations.h
blob915211c6af0e7daebbef2fdb753bbe3489aa2d2e
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef NSTEXTRUNTRANSFORMATIONS_H_
8 #define NSTEXTRUNTRANSFORMATIONS_H_
10 #include "mozilla/Attributes.h"
11 #include "mozilla/MemoryReporting.h"
12 #include "mozilla/UniquePtr.h"
13 #include "gfxTextRun.h"
14 #include "mozilla/ComputedStyle.h"
15 #include "nsPresContext.h"
16 #include "nsStyleStruct.h"
18 class nsTransformedTextRun;
20 struct nsTransformedCharStyle final {
21 NS_INLINE_DECL_REFCOUNTING(nsTransformedCharStyle)
23 explicit nsTransformedCharStyle(mozilla::ComputedStyle* aStyle,
24 nsPresContext* aPresContext)
25 : mFont(aStyle->StyleFont()->mFont),
26 mLanguage(aStyle->StyleFont()->mLanguage),
27 mPresContext(aPresContext),
28 mTextTransform(aStyle->StyleText()->mTextTransform),
29 mMathVariant(aStyle->StyleFont()->mMathVariant),
30 mExplicitLanguage(aStyle->StyleFont()->mExplicitLanguage) {}
32 nsFont mFont;
33 RefPtr<nsAtom> mLanguage;
34 RefPtr<nsPresContext> mPresContext;
35 mozilla::StyleTextTransform mTextTransform;
36 mozilla::StyleMathVariant mMathVariant;
37 bool mExplicitLanguage;
38 bool mForceNonFullWidth = false;
39 bool mMaskPassword = false;
41 private:
42 ~nsTransformedCharStyle() = default;
43 nsTransformedCharStyle(const nsTransformedCharStyle& aOther) = delete;
44 nsTransformedCharStyle& operator=(const nsTransformedCharStyle& aOther) =
45 delete;
48 class nsTransformingTextRunFactory {
49 public:
50 virtual ~nsTransformingTextRunFactory() = default;
52 // Default 8-bit path just transforms to Unicode and takes that path
53 already_AddRefed<nsTransformedTextRun> MakeTextRun(
54 const uint8_t* aString, uint32_t aLength,
55 const gfxFontGroup::Parameters* aParams, gfxFontGroup* aFontGroup,
56 mozilla::gfx::ShapedTextFlags aFlags, nsTextFrameUtils::Flags aFlags2,
57 nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles, bool aOwnsFactory);
59 already_AddRefed<nsTransformedTextRun> MakeTextRun(
60 const char16_t* aString, uint32_t aLength,
61 const gfxFontGroup::Parameters* aParams, gfxFontGroup* aFontGroup,
62 mozilla::gfx::ShapedTextFlags aFlags, nsTextFrameUtils::Flags aFlags2,
63 nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles, bool aOwnsFactory);
65 virtual void RebuildTextRun(nsTransformedTextRun* aTextRun,
66 mozilla::gfx::DrawTarget* aRefDrawTarget,
67 gfxMissingFontRecorder* aMFR) = 0;
70 /**
71 * Builds textruns that transform the text in some way (e.g., capitalize)
72 * and then render the text using some other textrun implementation.
73 * This factory also supports "text-security" transforms that convert all
74 * characters to a single symbol.
76 class nsCaseTransformTextRunFactory : public nsTransformingTextRunFactory {
77 public:
78 // We could add an optimization here so that when there is no inner
79 // factory, no title-case conversion, and no upper-casing of SZLIG, we
80 // override MakeTextRun (after making it virtual in the superclass) and have
81 // it just convert the string to uppercase or lowercase and create the textrun
82 // via the fontgroup.
84 // Takes ownership of aInnerTransformTextRunFactory
85 nsCaseTransformTextRunFactory(mozilla::UniquePtr<nsTransformingTextRunFactory>
86 aInnerTransformingTextRunFactory,
87 bool aAllUppercase, char16_t aMaskChar)
88 : mInnerTransformingTextRunFactory(
89 std::move(aInnerTransformingTextRunFactory)),
90 mAllUppercase(aAllUppercase),
91 mMaskChar(aMaskChar) {}
93 virtual void RebuildTextRun(nsTransformedTextRun* aTextRun,
94 mozilla::gfx::DrawTarget* aRefDrawTarget,
95 gfxMissingFontRecorder* aMFR) override;
97 // Perform a transformation on the given string, writing the result into
98 // aConvertedString. If aGlobalTransform is passed, the transform is global
99 // and aLanguage is used to determine any language-specific behavior;
100 // otherwise, an nsTransformedTextRun should be passed in as aTextRun and its
101 // styles will be used to determine the transform(s) to be applied.
102 // If such an input textrun is provided, then its line-breaks and styles
103 // will be copied to the output arrays, which must also be provided by
104 // the caller. For the global transform usage (no input textrun), these are
105 // ignored.
106 // If aMaskChar is non-zero, it is used as a "masking" character to replace
107 // all characters in the text (for -webkit-text-security).
108 // If aCaseTransformsOnly is true, then only the upper/lower/capitalize
109 // transformations are performed; full-width and full-size-kana are ignored.
110 // If `aTextRun` is not nullptr and characters which are styled with setting
111 // `nsTransformedCharStyle::mMaskPassword` to true, they are replaced with
112 // password mask characters and are not transformed (i.e., won't be added
113 // or merged for the specified transform). However, unmasked characters
114 // whose `nsTransformedCharStyle::mMaskPassword` is set to false are
115 // transformed normally.
116 // Note that "masking" behavior may be triggered either by
117 // -webkit-text-security, resulting in a non-zero aMaskChar being passed,
118 // or by <input type=password>, which results in the editor code setting
119 // nsTransformedCharStyle::mMaskPassword. (The latter mechanism enables the
120 // editor to temporarily reveal the just-entered character during typing,
121 // whereas simply setting aMaskChar would unconditionally mask all the text.)
122 static bool TransformString(
123 const nsAString& aString, nsString& aConvertedString,
124 const mozilla::Maybe<mozilla::StyleTextTransform>& aGlobalTransform,
125 char16_t aMaskChar, bool aCaseTransformsOnly, const nsAtom* aLanguage,
126 nsTArray<bool>& aCharsToMergeArray, nsTArray<bool>& aDeletedCharsArray,
127 const nsTransformedTextRun* aTextRun = nullptr,
128 uint32_t aOffsetInTextRun = 0,
129 nsTArray<uint8_t>* aCanBreakBeforeArray = nullptr,
130 nsTArray<RefPtr<nsTransformedCharStyle>>* aStyleArray = nullptr);
132 protected:
133 mozilla::UniquePtr<nsTransformingTextRunFactory>
134 mInnerTransformingTextRunFactory;
135 bool mAllUppercase;
136 char16_t mMaskChar;
140 * So that we can reshape as necessary, we store enough information
141 * to fully rebuild the textrun contents.
143 class nsTransformedTextRun final : public gfxTextRun {
144 public:
145 static already_AddRefed<nsTransformedTextRun> Create(
146 const gfxTextRunFactory::Parameters* aParams,
147 nsTransformingTextRunFactory* aFactory, gfxFontGroup* aFontGroup,
148 const char16_t* aString, uint32_t aLength,
149 const mozilla::gfx::ShapedTextFlags aFlags,
150 const nsTextFrameUtils::Flags aFlags2,
151 nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles, bool aOwnsFactory);
153 ~nsTransformedTextRun() {
154 if (mOwnsFactory) {
155 delete mFactory;
159 void SetCapitalization(uint32_t aStart, uint32_t aLength,
160 bool* aCapitalization);
161 virtual bool SetPotentialLineBreaks(Range aRange,
162 const uint8_t* aBreakBefore) override;
164 * Called after SetCapitalization and SetPotentialLineBreaks
165 * are done and before we request any data from the textrun. Also always
166 * called after a Create.
168 void FinishSettingProperties(mozilla::gfx::DrawTarget* aRefDrawTarget,
169 gfxMissingFontRecorder* aMFR) {
170 if (mNeedsRebuild) {
171 mNeedsRebuild = false;
172 mFactory->RebuildTextRun(this, aRefDrawTarget, aMFR);
176 // override the gfxTextRun impls to account for additional members here
177 virtual size_t SizeOfExcludingThis(
178 mozilla::MallocSizeOf aMallocSizeOf) override;
179 virtual size_t SizeOfIncludingThis(
180 mozilla::MallocSizeOf aMallocSizeOf) override;
182 nsTransformingTextRunFactory* mFactory;
183 nsTArray<RefPtr<nsTransformedCharStyle>> mStyles;
184 nsTArray<bool> mCapitalize;
185 nsString mString;
186 bool mOwnsFactory;
187 bool mNeedsRebuild;
189 private:
190 nsTransformedTextRun(const gfxTextRunFactory::Parameters* aParams,
191 nsTransformingTextRunFactory* aFactory,
192 gfxFontGroup* aFontGroup, const char16_t* aString,
193 uint32_t aLength,
194 const mozilla::gfx::ShapedTextFlags aFlags,
195 const nsTextFrameUtils::Flags aFlags2,
196 nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
197 bool aOwnsFactory)
198 : gfxTextRun(aParams, aLength, aFontGroup, aFlags, aFlags2),
199 mFactory(aFactory),
200 mStyles(std::move(aStyles)),
201 mString(aString, aLength),
202 mOwnsFactory(aOwnsFactory),
203 mNeedsRebuild(true) {
204 mCharacterGlyphs = reinterpret_cast<CompressedGlyph*>(this + 1);
209 * Copy a given textrun, but merge certain characters into a single logical
210 * character. Glyphs for a character are added to the glyph list for the
211 * previous character and then the merged character is eliminated. Visually the
212 * results are identical.
214 * This is used for text-transform:uppercase when we encounter a SZLIG,
215 * whose uppercase form is "SS", or other ligature or precomposed form
216 * that expands to multiple codepoints during case transformation,
217 * and for Greek text when combining diacritics have been deleted.
219 * This function is unable to merge characters when they occur in different
220 * glyph runs. This only happens in tricky edge cases where a character was
221 * decomposed by case-mapping (e.g. there's no precomposed uppercase version
222 * of an accented lowercase letter), and then font-matching caused the
223 * diacritics to be assigned to a different font than the base character.
224 * In this situation, the diacritic(s) get discarded, which is less than
225 * ideal, but they probably weren't going to render very well anyway.
226 * Bug 543200 will improve this by making font-matching operate on entire
227 * clusters instead of individual codepoints.
229 * For simplicity, this produces a textrun containing all DetailedGlyphs,
230 * no simple glyphs. So don't call it unless you really have merging to do.
232 * @param aCharsToMerge when aCharsToMerge[i] is true, this character in aSrc
233 * is merged into the previous character
235 * @param aDeletedChars when aDeletedChars[i] is true, the character at this
236 * position in aDest was deleted (has no corresponding char in aSrc)
238 void MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc,
239 const bool* aCharsToMerge,
240 const bool* aDeletedChars);
242 gfxTextRunFactory::Parameters GetParametersForInner(
243 nsTransformedTextRun* aTextRun, mozilla::gfx::ShapedTextFlags* aFlags,
244 mozilla::gfx::DrawTarget* aRefDrawTarget);
246 #endif /*NSTEXTRUNTRANSFORMATIONS_H_*/