blob: 85ab4288d3229fbedcc2a495454fff254ff7cd70 [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
92struct PlaceholderStyle {
93 PlaceholderStyle() { }
94 PlaceholderStyle(SkScalar width, SkScalar height, PlaceholderAlignment alignment,
95 TextBaseline baseline, SkScalar offset)
96 : fWidth(width)
97 , fHeight(height)
98 , fAlignment(alignment)
99 , fBaseline(baseline)
100 , fBaselineOffset(offset) {}
101
102 SkScalar fWidth = 0;
103 SkScalar fHeight = 0;
104
105 PlaceholderAlignment fAlignment;
106
107 TextBaseline fBaseline;
108
109 // Distance from the top edge of the rect to the baseline position. This
110 // baseline will be aligned against the alphabetic baseline of the surrounding
111 // text.
112 //
113 // Positive values drop the baseline lower (positions the rect higher) and
114 // small or negative values will cause the rect to be positioned underneath
115 // the line. When baseline == height, the bottom edge of the rect will rest on
116 // the alphabetic baseline.
117 SkScalar fBaselineOffset = 0;
118};
119
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400120class TextStyle {
121public:
122 TextStyle();
Julia Lavrova916a9042019-08-08 16:51:27 -0400123 TextStyle(const TextStyle& other, bool placeholder);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400124 ~TextStyle() = default;
125
126 bool equals(const TextStyle& other) const;
127 bool matchOneAttribute(StyleType styleType, const TextStyle& other) const;
128 bool operator==(const TextStyle& rhs) const { return this->equals(rhs); }
129
130 // Colors
131 SkColor getColor() const { return fColor; }
132 void setColor(SkColor color) { fColor = color; }
133
134 bool hasForeground() const { return fHasForeground; }
135 SkPaint getForeground() const { return fForeground; }
136 void setForegroundColor(SkPaint paint) {
137 fHasForeground = true;
138 fForeground = std::move(paint);
139 }
140 void clearForegroundColor() { fHasForeground = false; }
141
142 bool hasBackground() const { return fHasBackground; }
143 SkPaint getBackground() const { return fBackground; }
144 void setBackgroundColor(SkPaint paint) {
145 fHasBackground = true;
146 fBackground = std::move(paint);
147 }
148 void clearBackgroundColor() { fHasBackground = false; }
149
150 // Decorations
Julia Lavrova5207f352019-06-21 12:22:32 -0400151 Decoration getDecoration() const { return fDecoration; }
152 TextDecoration getDecorationType() const { return fDecoration.fType; }
153 SkColor getDecorationColor() const { return fDecoration.fColor; }
154 TextDecorationStyle getDecorationStyle() const { return fDecoration.fStyle; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400155 SkScalar getDecorationThicknessMultiplier() const {
Julia Lavrova5207f352019-06-21 12:22:32 -0400156 return fDecoration.fThicknessMultiplier;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400157 }
Julia Lavrova5207f352019-06-21 12:22:32 -0400158 void setDecoration(TextDecoration decoration) { fDecoration.fType = decoration; }
159 void setDecorationStyle(TextDecorationStyle style) { fDecoration.fStyle = style; }
160 void setDecorationColor(SkColor color) { fDecoration.fColor = color; }
161 void setDecorationThicknessMultiplier(SkScalar m) { fDecoration.fThicknessMultiplier = m; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400162
163 // Weight/Width/Slant
164 SkFontStyle getFontStyle() const { return fFontStyle; }
165 void setFontStyle(SkFontStyle fontStyle) { fFontStyle = fontStyle; }
166
167 // Shadows
168 size_t getShadowNumber() const { return fTextShadows.size(); }
169 std::vector<TextShadow> getShadows() const { return fTextShadows; }
170 void addShadow(TextShadow shadow) { fTextShadows.emplace_back(shadow); }
171 void resetShadows() { fTextShadows.clear(); }
172
173 SkScalar getFontSize() const { return fFontSize; }
174 void setFontSize(SkScalar size) { fFontSize = size; }
175
176 const std::vector<SkString>& getFontFamilies() const { return fFontFamilies; }
177 void setFontFamilies(std::vector<SkString> families) {
178 fFontFamilies = std::move(families);
179 }
180
181 void setHeight(SkScalar height) { fHeight = height; }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400182 SkScalar getHeight() const { return fHeightOverride ? fHeight : 0; }
183
184 void setHeightOverride(bool heightOverride) { fHeightOverride = heightOverride; }
185 bool getHeightOverride() const { return fHeightOverride; }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400186
187 void setLetterSpacing(SkScalar letterSpacing) { fLetterSpacing = letterSpacing; }
188 SkScalar getLetterSpacing() const { return fLetterSpacing; }
189
190 void setWordSpacing(SkScalar wordSpacing) { fWordSpacing = wordSpacing; }
191 SkScalar getWordSpacing() const { return fWordSpacing; }
192
193 SkTypeface* getTypeface() const { return fTypeface.get(); }
194 sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
195 void setTypeface(sk_sp<SkTypeface> typeface) { fTypeface = std::move(typeface); }
196
197 SkString getLocale() const { return fLocale; }
198 void setLocale(const SkString& locale) { fLocale = locale; }
199
200 TextBaseline getTextBaseline() const { return fTextBaseline; }
201 void setTextBaseline(TextBaseline baseline) { fTextBaseline = baseline; }
202
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400203 void getFontMetrics(SkFontMetrics* metrics) const;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400204
Julia Lavrova916a9042019-08-08 16:51:27 -0400205 bool isPlaceholder() const { return fIsPlaceholder; }
206 void setPlaceholder() { fIsPlaceholder = true; }
207
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400208private:
Julia Lavrova916a9042019-08-08 16:51:27 -0400209
Julia Lavrova5207f352019-06-21 12:22:32 -0400210 Decoration fDecoration;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400211
212 SkFontStyle fFontStyle;
213
214 std::vector<SkString> fFontFamilies;
215 SkScalar fFontSize;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400216 SkScalar fHeight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400217 bool fHeightOverride;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400218 SkString fLocale;
219 SkScalar fLetterSpacing;
220 SkScalar fWordSpacing;
221
222 TextBaseline fTextBaseline;
223
224 SkColor fColor;
225 bool fHasBackground;
226 SkPaint fBackground;
227 bool fHasForeground;
228 SkPaint fForeground;
229
230 std::vector<TextShadow> fTextShadows;
231
232 sk_sp<SkTypeface> fTypeface;
Julia Lavrova916a9042019-08-08 16:51:27 -0400233 bool fIsPlaceholder;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400234};
Julia Lavrova5207f352019-06-21 12:22:32 -0400235
236typedef size_t TextIndex;
237typedef SkRange<size_t> TextRange;
238const SkRange<size_t> EMPTY_TEXT = EMPTY_RANGE;
239
240
241struct Block {
242 Block() : fRange(EMPTY_RANGE), fStyle() { }
Julia Lavrova916a9042019-08-08 16:51:27 -0400243 Block(size_t start, size_t end, const TextStyle& style) : fRange(start, end), fStyle(style) {}
244 Block(TextRange textRange, const TextStyle& style) : fRange(textRange), fStyle(style) {}
245
246 Block(const Block& other) {
247 fRange = other.fRange;
248 fStyle = other.fStyle;
249 }
Julia Lavrova5207f352019-06-21 12:22:32 -0400250
251 void add(TextRange tail) {
252 SkASSERT(fRange.end == tail.start);
253 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
254 }
255 TextRange fRange;
256 TextStyle fStyle;
257};
258
Julia Lavrova916a9042019-08-08 16:51:27 -0400259
260typedef size_t BlockIndex;
261typedef SkRange<size_t> BlockRange;
262const size_t EMPTY_BLOCK = EMPTY_INDEX;
263const SkRange<size_t> EMPTY_BLOCKS = EMPTY_RANGE;
264
265struct Placeholder {
266 Placeholder() : fRange(EMPTY_RANGE), fStyle() {}
267
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400268 Placeholder(size_t start, size_t end, const PlaceholderStyle& style, const TextStyle& textStyle,
269 BlockRange blocksBefore, TextRange textBefore)
Julia Lavrova916a9042019-08-08 16:51:27 -0400270 : fRange(start, end)
271 , fStyle(style)
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400272 , fTextStyle(textStyle)
Julia Lavrova916a9042019-08-08 16:51:27 -0400273 , fBlocksBefore(blocksBefore)
274 , fTextBefore(textBefore) {}
275
276 Placeholder(const Placeholder& other) {
277 fRange = other.fRange;
278 fStyle = other.fStyle;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400279 fTextStyle = other.fTextStyle;
Julia Lavrova916a9042019-08-08 16:51:27 -0400280 fBlocksBefore = other.fBlocksBefore;
281 fTextBefore = other.fTextBefore;
282 }
283
284 TextRange fRange;
285 PlaceholderStyle fStyle;
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400286 TextStyle fTextStyle;
Julia Lavrova916a9042019-08-08 16:51:27 -0400287 BlockRange fBlocksBefore;
288 TextRange fTextBefore;
289};
290
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400291} // namespace textlayout
292} // namespace skia
293
294#endif // TextStyle_DEFINED