blob: 88223a55e744ff968fb25618a941ac14e30f51ff [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
112 SkScalar fWidth = 0;
113 SkScalar fHeight = 0;
114
115 PlaceholderAlignment fAlignment;
116
117 TextBaseline fBaseline;
118
119 // Distance from the top edge of the rect to the baseline position. This
120 // baseline will be aligned against the alphabetic baseline of the surrounding
121 // text.
122 //
123 // Positive values drop the baseline lower (positions the rect higher) and
124 // small or negative values will cause the rect to be positioned underneath
125 // the line. When baseline == height, the bottom edge of the rect will rest on
126 // the alphabetic baseline.
127 SkScalar fBaselineOffset = 0;
128};
129
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400130class TextStyle {
131public:
132 TextStyle();
Julia Lavrova916a9042019-08-08 16:51:27 -0400133 TextStyle(const TextStyle& other, bool placeholder);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400134 ~TextStyle() = default;
135
136 bool equals(const TextStyle& other) const;
137 bool matchOneAttribute(StyleType styleType, const TextStyle& other) const;
138 bool operator==(const TextStyle& rhs) const { return this->equals(rhs); }
139
140 // Colors
141 SkColor getColor() const { return fColor; }
142 void setColor(SkColor color) { fColor = color; }
143
144 bool hasForeground() const { return fHasForeground; }
145 SkPaint getForeground() const { return fForeground; }
146 void setForegroundColor(SkPaint paint) {
147 fHasForeground = true;
148 fForeground = std::move(paint);
149 }
150 void clearForegroundColor() { fHasForeground = false; }
151
152 bool hasBackground() const { return fHasBackground; }
153 SkPaint getBackground() const { return fBackground; }
154 void setBackgroundColor(SkPaint paint) {
155 fHasBackground = true;
156 fBackground = std::move(paint);
157 }
158 void clearBackgroundColor() { fHasBackground = false; }
159
160 // Decorations
Julia Lavrova5207f352019-06-21 12:22:32 -0400161 Decoration getDecoration() const { return fDecoration; }
162 TextDecoration getDecorationType() const { return fDecoration.fType; }
163 SkColor getDecorationColor() const { return fDecoration.fColor; }
164 TextDecorationStyle getDecorationStyle() const { return fDecoration.fStyle; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400165 SkScalar getDecorationThicknessMultiplier() const {
Julia Lavrova5207f352019-06-21 12:22:32 -0400166 return fDecoration.fThicknessMultiplier;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400167 }
Julia Lavrova5207f352019-06-21 12:22:32 -0400168 void setDecoration(TextDecoration decoration) { fDecoration.fType = decoration; }
169 void setDecorationStyle(TextDecorationStyle style) { fDecoration.fStyle = style; }
170 void setDecorationColor(SkColor color) { fDecoration.fColor = color; }
171 void setDecorationThicknessMultiplier(SkScalar m) { fDecoration.fThicknessMultiplier = m; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400172
173 // Weight/Width/Slant
174 SkFontStyle getFontStyle() const { return fFontStyle; }
175 void setFontStyle(SkFontStyle fontStyle) { fFontStyle = fontStyle; }
176
177 // Shadows
178 size_t getShadowNumber() const { return fTextShadows.size(); }
179 std::vector<TextShadow> getShadows() const { return fTextShadows; }
180 void addShadow(TextShadow shadow) { fTextShadows.emplace_back(shadow); }
181 void resetShadows() { fTextShadows.clear(); }
182
Julia Lavrovac5313e62019-12-10 12:11:17 -0500183 // Font features
184 size_t getFontFeatureNumber() const { return fFontFeatures.size(); }
185 std::vector<FontFeature> getFontFeatures() const { return fFontFeatures; }
186 void addFontFeature(const SkString& fontFeature, int value)
187 { fFontFeatures.emplace_back(fontFeature, value); }
188 void resetFontFeatures() { fFontFeatures.clear(); }
189
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400190 SkScalar getFontSize() const { return fFontSize; }
191 void setFontSize(SkScalar size) { fFontSize = size; }
192
193 const std::vector<SkString>& getFontFamilies() const { return fFontFamilies; }
194 void setFontFamilies(std::vector<SkString> families) {
195 fFontFamilies = std::move(families);
196 }
197
198 void setHeight(SkScalar height) { fHeight = height; }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400199 SkScalar getHeight() const { return fHeightOverride ? fHeight : 0; }
200
201 void setHeightOverride(bool heightOverride) { fHeightOverride = heightOverride; }
202 bool getHeightOverride() const { return fHeightOverride; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400203
204 void setLetterSpacing(SkScalar letterSpacing) { fLetterSpacing = letterSpacing; }
205 SkScalar getLetterSpacing() const { return fLetterSpacing; }
206
207 void setWordSpacing(SkScalar wordSpacing) { fWordSpacing = wordSpacing; }
208 SkScalar getWordSpacing() const { return fWordSpacing; }
209
210 SkTypeface* getTypeface() const { return fTypeface.get(); }
211 sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
212 void setTypeface(sk_sp<SkTypeface> typeface) { fTypeface = std::move(typeface); }
213
214 SkString getLocale() const { return fLocale; }
215 void setLocale(const SkString& locale) { fLocale = locale; }
216
217 TextBaseline getTextBaseline() const { return fTextBaseline; }
218 void setTextBaseline(TextBaseline baseline) { fTextBaseline = baseline; }
219
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400220 void getFontMetrics(SkFontMetrics* metrics) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400221
Julia Lavrova916a9042019-08-08 16:51:27 -0400222 bool isPlaceholder() const { return fIsPlaceholder; }
223 void setPlaceholder() { fIsPlaceholder = true; }
224
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400225private:
Julia Lavrova916a9042019-08-08 16:51:27 -0400226
Julia Lavrova5207f352019-06-21 12:22:32 -0400227 Decoration fDecoration;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400228
229 SkFontStyle fFontStyle;
230
231 std::vector<SkString> fFontFamilies;
232 SkScalar fFontSize;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400233 SkScalar fHeight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400234 bool fHeightOverride;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400235 SkString fLocale;
236 SkScalar fLetterSpacing;
237 SkScalar fWordSpacing;
238
239 TextBaseline fTextBaseline;
240
241 SkColor fColor;
242 bool fHasBackground;
243 SkPaint fBackground;
244 bool fHasForeground;
245 SkPaint fForeground;
246
247 std::vector<TextShadow> fTextShadows;
248
249 sk_sp<SkTypeface> fTypeface;
Julia Lavrova916a9042019-08-08 16:51:27 -0400250 bool fIsPlaceholder;
Julia Lavrovac5313e62019-12-10 12:11:17 -0500251
252 std::vector<FontFeature> fFontFeatures;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400253};
Julia Lavrova5207f352019-06-21 12:22:32 -0400254
255typedef size_t TextIndex;
256typedef SkRange<size_t> TextRange;
257const SkRange<size_t> EMPTY_TEXT = EMPTY_RANGE;
258
259
260struct Block {
261 Block() : fRange(EMPTY_RANGE), fStyle() { }
Julia Lavrova916a9042019-08-08 16:51:27 -0400262 Block(size_t start, size_t end, const TextStyle& style) : fRange(start, end), fStyle(style) {}
263 Block(TextRange textRange, const TextStyle& style) : fRange(textRange), fStyle(style) {}
264
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500265 Block(const Block& other) : fRange(other.fRange), fStyle(other.fStyle) {}
Julia Lavrova5207f352019-06-21 12:22:32 -0400266
267 void add(TextRange tail) {
268 SkASSERT(fRange.end == tail.start);
269 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
270 }
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500271
Julia Lavrova5207f352019-06-21 12:22:32 -0400272 TextRange fRange;
273 TextStyle fStyle;
274};
275
Julia Lavrova916a9042019-08-08 16:51:27 -0400276
277typedef size_t BlockIndex;
278typedef SkRange<size_t> BlockRange;
279const size_t EMPTY_BLOCK = EMPTY_INDEX;
280const SkRange<size_t> EMPTY_BLOCKS = EMPTY_RANGE;
281
282struct Placeholder {
283 Placeholder() : fRange(EMPTY_RANGE), fStyle() {}
284
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400285 Placeholder(size_t start, size_t end, const PlaceholderStyle& style, const TextStyle& textStyle,
286 BlockRange blocksBefore, TextRange textBefore)
Julia Lavrova916a9042019-08-08 16:51:27 -0400287 : fRange(start, end)
288 , fStyle(style)
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400289 , fTextStyle(textStyle)
Julia Lavrova916a9042019-08-08 16:51:27 -0400290 , fBlocksBefore(blocksBefore)
291 , fTextBefore(textBefore) {}
292
Julia Lavrova90bfd1c2019-12-04 11:43:32 -0500293 Placeholder(const Placeholder& other)
294 : fRange(other.fRange)
295 , fStyle(other.fStyle)
296 , fTextStyle(other.fTextStyle)
297 , fBlocksBefore(other.fBlocksBefore)
298 , fTextBefore(other.fTextBefore) {}
Julia Lavrova916a9042019-08-08 16:51:27 -0400299
300 TextRange fRange;
301 PlaceholderStyle fStyle;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400302 TextStyle fTextStyle;
Julia Lavrova916a9042019-08-08 16:51:27 -0400303 BlockRange fBlocksBefore;
304 TextRange fTextBefore;
305};
306
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400307} // namespace textlayout
308} // namespace skia
309
310#endif // TextStyle_DEFINED