blob: 454dc3892a9b92520516d70fcaf4d7cacf42a268 [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
2#ifndef TextStyle_DEFINED
3#define TextStyle_DEFINED
4
5#include <vector>
Julia Lavrovaa3552c52019-05-30 16:12:56 -04006#include "include/core/SkColor.h"
7#include "include/core/SkFont.h"
8#include "include/core/SkFontMetrics.h"
9#include "include/core/SkFontStyle.h"
10#include "include/core/SkPaint.h"
Julia Lavrova916a9042019-08-08 16:51:27 -040011#include "include/core/SkScalar.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040012#include "modules/skparagraph/include/DartTypes.h"
13#include "modules/skparagraph/include/TextShadow.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040014
15// TODO: Make it external so the other platforms (Android) could use it
16#define DEFAULT_FONT_FAMILY "sans-serif"
17
18namespace skia {
19namespace textlayout {
20
21// Multiple decorations can be applied at once. Ex: Underline and overline is
22// (0x1 | 0x2)
23enum TextDecoration {
24 kNoDecoration = 0x0,
25 kUnderline = 0x1,
26 kOverline = 0x2,
27 kLineThrough = 0x4,
28};
Julia Lavrovab5c69a42019-07-11 09:34:39 -040029constexpr TextDecoration AllTextDecorations[] = {
Julia Lavrovaa3552c52019-05-30 16:12:56 -040030 kNoDecoration,
31 kUnderline,
32 kOverline,
33 kLineThrough,
34};
35
36enum TextDecorationStyle { kSolid, kDouble, kDotted, kDashed, kWavy };
37
38enum StyleType {
39 kAllAttributes,
Julia Lavrovaa3552c52019-05-30 16:12:56 -040040 kFont,
41 kForeground,
42 kBackground,
43 kShadow,
44 kDecorations,
45 kLetterSpacing,
46 kWordSpacing
47};
48
Julia Lavrova5207f352019-06-21 12:22:32 -040049struct Decoration {
50 TextDecoration fType;
51 SkColor fColor;
52 TextDecorationStyle fStyle;
53 SkScalar fThicknessMultiplier;
54
55 bool operator==(const Decoration& other) const {
56 return this->fType == other.fType &&
57 this->fColor == other.fColor &&
58 this->fStyle == other.fStyle &&
59 this->fThicknessMultiplier == other.fThicknessMultiplier;
60 }
61};
62
Julia Lavrova916a9042019-08-08 16:51:27 -040063/// Where to vertically align the placeholder relative to the surrounding text.
64enum class PlaceholderAlignment {
65 /// Match the baseline of the placeholder with the baseline.
66 kBaseline,
67
68 /// Align the bottom edge of the placeholder with the baseline such that the
69 /// placeholder sits on top of the baseline.
70 kAboveBaseline,
71
72 /// Align the top edge of the placeholder with the baseline specified in
73 /// such that the placeholder hangs below the baseline.
74 kBelowBaseline,
75
76 /// Align the top edge of the placeholder with the top edge of the font.
77 /// When the placeholder is very tall, the extra space will hang from
78 /// the top and extend through the bottom of the line.
79 kTop,
80
81 /// Align the bottom edge of the placeholder with the top edge of the font.
82 /// When the placeholder is very tall, the extra space will rise from
83 /// the bottom and extend through the top of the line.
84 kBottom,
85
86 /// Align the middle of the placeholder with the middle of the text. When the
87 /// placeholder is very tall, the extra space will grow equally from
88 /// the top and bottom of the line.
89 kMiddle,
90};
91
Julia Lavrovac5313e62019-12-10 12:11:17 -050092struct FontFeature {
93 FontFeature(const SkString name, int value) : fName(name), fValue(value) { }
94 FontFeature(const FontFeature& other) : fName(other.fName), fValue(other.fValue) { }
95 bool operator==(const FontFeature& other) const {
96 return fName == other.fName && fValue == other.fValue;
97 }
98 SkString fName;
99 int fValue;
100};
101
Julia Lavrova916a9042019-08-08 16:51:27 -0400102struct PlaceholderStyle {
103 PlaceholderStyle() { }
104 PlaceholderStyle(SkScalar width, SkScalar height, PlaceholderAlignment alignment,
105 TextBaseline baseline, SkScalar offset)
106 : fWidth(width)
107 , fHeight(height)
108 , fAlignment(alignment)
109 , fBaseline(baseline)
110 , fBaselineOffset(offset) {}
111
Julia Lavrova4cf18742020-01-14 13:24:45 -0500112 bool equals(const PlaceholderStyle& other) const;
113
Julia Lavrova916a9042019-08-08 16:51:27 -0400114 SkScalar fWidth = 0;
115 SkScalar fHeight = 0;
116
117 PlaceholderAlignment fAlignment;
118
119 TextBaseline fBaseline;
120
121 // Distance from the top edge of the rect to the baseline position. This
122 // baseline will be aligned against the alphabetic baseline of the surrounding
123 // text.
124 //
125 // Positive values drop the baseline lower (positions the rect higher) and
126 // small or negative values will cause the rect to be positioned underneath
127 // the line. When baseline == height, the bottom edge of the rect will rest on
128 // the alphabetic baseline.
129 SkScalar fBaselineOffset = 0;
130};
131
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400132class TextStyle {
133public:
134 TextStyle();
Julia Lavrova916a9042019-08-08 16:51:27 -0400135 TextStyle(const TextStyle& other, bool placeholder);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400136 ~TextStyle() = default;
137
138 bool equals(const TextStyle& other) const;
Julia Lavrova4cf18742020-01-14 13:24:45 -0500139 bool equalsByFonts(const TextStyle& that) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400140 bool matchOneAttribute(StyleType styleType, const TextStyle& other) const;
141 bool operator==(const TextStyle& rhs) const { return this->equals(rhs); }
142
143 // Colors
144 SkColor getColor() const { return fColor; }
145 void setColor(SkColor color) { fColor = color; }
146
147 bool hasForeground() const { return fHasForeground; }
148 SkPaint getForeground() const { return fForeground; }
149 void setForegroundColor(SkPaint paint) {
150 fHasForeground = true;
151 fForeground = std::move(paint);
152 }
153 void clearForegroundColor() { fHasForeground = false; }
154
155 bool hasBackground() const { return fHasBackground; }
156 SkPaint getBackground() const { return fBackground; }
157 void setBackgroundColor(SkPaint paint) {
158 fHasBackground = true;
159 fBackground = std::move(paint);
160 }
161 void clearBackgroundColor() { fHasBackground = false; }
162
163 // Decorations
Julia Lavrova5207f352019-06-21 12:22:32 -0400164 Decoration getDecoration() const { return fDecoration; }
165 TextDecoration getDecorationType() const { return fDecoration.fType; }
166 SkColor getDecorationColor() const { return fDecoration.fColor; }
167 TextDecorationStyle getDecorationStyle() const { return fDecoration.fStyle; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400168 SkScalar getDecorationThicknessMultiplier() const {
Julia Lavrova5207f352019-06-21 12:22:32 -0400169 return fDecoration.fThicknessMultiplier;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400170 }
Julia Lavrova5207f352019-06-21 12:22:32 -0400171 void setDecoration(TextDecoration decoration) { fDecoration.fType = decoration; }
172 void setDecorationStyle(TextDecorationStyle style) { fDecoration.fStyle = style; }
173 void setDecorationColor(SkColor color) { fDecoration.fColor = color; }
174 void setDecorationThicknessMultiplier(SkScalar m) { fDecoration.fThicknessMultiplier = m; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400175
176 // Weight/Width/Slant
177 SkFontStyle getFontStyle() const { return fFontStyle; }
178 void setFontStyle(SkFontStyle fontStyle) { fFontStyle = fontStyle; }
179
180 // Shadows
181 size_t getShadowNumber() const { return fTextShadows.size(); }
182 std::vector<TextShadow> getShadows() const { return fTextShadows; }
183 void addShadow(TextShadow shadow) { fTextShadows.emplace_back(shadow); }
184 void resetShadows() { fTextShadows.clear(); }
185
Julia Lavrovac5313e62019-12-10 12:11:17 -0500186 // Font features
187 size_t getFontFeatureNumber() const { return fFontFeatures.size(); }
188 std::vector<FontFeature> getFontFeatures() const { return fFontFeatures; }
189 void addFontFeature(const SkString& fontFeature, int value)
190 { fFontFeatures.emplace_back(fontFeature, value); }
191 void resetFontFeatures() { fFontFeatures.clear(); }
192
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400193 SkScalar getFontSize() const { return fFontSize; }
194 void setFontSize(SkScalar size) { fFontSize = size; }
195
196 const std::vector<SkString>& getFontFamilies() const { return fFontFamilies; }
197 void setFontFamilies(std::vector<SkString> families) {
198 fFontFamilies = std::move(families);
199 }
200
201 void setHeight(SkScalar height) { fHeight = height; }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400202 SkScalar getHeight() const { return fHeightOverride ? fHeight : 0; }
203
204 void setHeightOverride(bool heightOverride) { fHeightOverride = heightOverride; }
205 bool getHeightOverride() const { return fHeightOverride; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400206
207 void setLetterSpacing(SkScalar letterSpacing) { fLetterSpacing = letterSpacing; }
208 SkScalar getLetterSpacing() const { return fLetterSpacing; }
209
210 void setWordSpacing(SkScalar wordSpacing) { fWordSpacing = wordSpacing; }
211 SkScalar getWordSpacing() const { return fWordSpacing; }
212
213 SkTypeface* getTypeface() const { return fTypeface.get(); }
214 sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
215 void setTypeface(sk_sp<SkTypeface> typeface) { fTypeface = std::move(typeface); }
216
217 SkString getLocale() const { return fLocale; }
218 void setLocale(const SkString& locale) { fLocale = locale; }
219
220 TextBaseline getTextBaseline() const { return fTextBaseline; }
221 void setTextBaseline(TextBaseline baseline) { fTextBaseline = baseline; }
222
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400223 void getFontMetrics(SkFontMetrics* metrics) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400224
Julia Lavrova916a9042019-08-08 16:51:27 -0400225 bool isPlaceholder() const { return fIsPlaceholder; }
226 void setPlaceholder() { fIsPlaceholder = true; }
227
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400228private:
Julia Lavrova916a9042019-08-08 16:51:27 -0400229
Julia Lavrova5207f352019-06-21 12:22:32 -0400230 Decoration fDecoration;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400231
232 SkFontStyle fFontStyle;
233
234 std::vector<SkString> fFontFamilies;
235 SkScalar fFontSize;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400236 SkScalar fHeight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400237 bool fHeightOverride;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400238 SkString fLocale;
239 SkScalar fLetterSpacing;
240 SkScalar fWordSpacing;
241
242 TextBaseline fTextBaseline;
243
244 SkColor fColor;
245 bool fHasBackground;
246 SkPaint fBackground;
247 bool fHasForeground;
248 SkPaint fForeground;
249
250 std::vector<TextShadow> fTextShadows;
251
252 sk_sp<SkTypeface> fTypeface;
Julia Lavrova916a9042019-08-08 16:51:27 -0400253 bool fIsPlaceholder;
Julia Lavrovac5313e62019-12-10 12:11:17 -0500254
255 std::vector<FontFeature> fFontFeatures;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400256};
Julia Lavrova5207f352019-06-21 12:22:32 -0400257
258typedef size_t TextIndex;
259typedef SkRange<size_t> TextRange;
260const SkRange<size_t> EMPTY_TEXT = EMPTY_RANGE;
261
262
263struct Block {
264 Block() : fRange(EMPTY_RANGE), fStyle() { }
Julia Lavrova916a9042019-08-08 16:51:27 -0400265 Block(size_t start, size_t end, const TextStyle& style) : fRange(start, end), fStyle(style) {}
266 Block(TextRange textRange, const TextStyle& style) : fRange(textRange), fStyle(style) {}
267
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500268 Block(const Block& other) : fRange(other.fRange), fStyle(other.fStyle) {}
Julia Lavrova5207f352019-06-21 12:22:32 -0400269
270 void add(TextRange tail) {
271 SkASSERT(fRange.end == tail.start);
272 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
273 }
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500274
Julia Lavrova5207f352019-06-21 12:22:32 -0400275 TextRange fRange;
276 TextStyle fStyle;
277};
278
Julia Lavrova916a9042019-08-08 16:51:27 -0400279
280typedef size_t BlockIndex;
281typedef SkRange<size_t> BlockRange;
282const size_t EMPTY_BLOCK = EMPTY_INDEX;
283const SkRange<size_t> EMPTY_BLOCKS = EMPTY_RANGE;
284
285struct Placeholder {
286 Placeholder() : fRange(EMPTY_RANGE), fStyle() {}
287
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400288 Placeholder(size_t start, size_t end, const PlaceholderStyle& style, const TextStyle& textStyle,
289 BlockRange blocksBefore, TextRange textBefore)
Julia Lavrova916a9042019-08-08 16:51:27 -0400290 : fRange(start, end)
291 , fStyle(style)
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400292 , fTextStyle(textStyle)
Julia Lavrova916a9042019-08-08 16:51:27 -0400293 , fBlocksBefore(blocksBefore)
294 , fTextBefore(textBefore) {}
295
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500296 Placeholder(const Placeholder& other)
297 : fRange(other.fRange)
298 , fStyle(other.fStyle)
299 , fTextStyle(other.fTextStyle)
300 , fBlocksBefore(other.fBlocksBefore)
301 , fTextBefore(other.fTextBefore) {}
Julia Lavrova916a9042019-08-08 16:51:27 -0400302
303 TextRange fRange;
304 PlaceholderStyle fStyle;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400305 TextStyle fTextStyle;
Julia Lavrova916a9042019-08-08 16:51:27 -0400306 BlockRange fBlocksBefore;
307 TextRange fTextBefore;
308};
309
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400310} // namespace textlayout
311} // namespace skia
312
313#endif // TextStyle_DEFINED