Coverage Report

Created: 2021-08-22 09:07

/src/skia/modules/skparagraph/include/TextStyle.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2019 Google LLC.
2
#ifndef TextStyle_DEFINED
3
#define TextStyle_DEFINED
4
5
#include <vector>
6
#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"
11
#include "include/core/SkScalar.h"
12
#include "modules/skparagraph/include/DartTypes.h"
13
#include "modules/skparagraph/include/TextShadow.h"
14
15
// TODO: Make it external so the other platforms (Android) could use it
16
#define DEFAULT_FONT_FAMILY "sans-serif"
17
18
namespace skia {
19
namespace textlayout {
20
21
0
static inline bool nearlyZero(SkScalar x, SkScalar tolerance = SK_ScalarNearlyZero) {
22
0
    if (SkScalarIsFinite(x)) {
23
0
        return SkScalarNearlyZero(x, tolerance);
24
0
    }
25
0
    return false;
26
0
}
Unexecuted instantiation: FuzzSkParagraph.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: FontCollection.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: ParagraphBuilderImpl.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: ParagraphCache.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: ParagraphImpl.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: ParagraphStyle.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: Run.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: TextLine.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: TextStyle.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: TextWrapper.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: Decorations.cpp:skia::textlayout::nearlyZero(float, float)
Unexecuted instantiation: OneLineShaper.cpp:skia::textlayout::nearlyZero(float, float)
27
28
32.0k
static inline bool nearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance = SK_ScalarNearlyZero) {
29
32.0k
    if (SkScalarIsFinite(x) && SkScalarIsFinite(x)) {
30
32.0k
        return SkScalarNearlyEqual(x, y, tolerance);
31
32.0k
    }
32
    // Inf == Inf, anything else is false
33
0
    return x == y;
34
0
}
Unexecuted instantiation: FuzzSkParagraph.cpp:skia::textlayout::nearlyEqual(float, float, float)
Unexecuted instantiation: FontCollection.cpp:skia::textlayout::nearlyEqual(float, float, float)
Unexecuted instantiation: ParagraphBuilderImpl.cpp:skia::textlayout::nearlyEqual(float, float, float)
ParagraphCache.cpp:skia::textlayout::nearlyEqual(float, float, float)
Line
Count
Source
28
13.7k
static inline bool nearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance = SK_ScalarNearlyZero) {
29
13.7k
    if (SkScalarIsFinite(x) && SkScalarIsFinite(x)) {
30
13.7k
        return SkScalarNearlyEqual(x, y, tolerance);
31
13.7k
    }
32
    // Inf == Inf, anything else is false
33
0
    return x == y;
34
0
}
Unexecuted instantiation: ParagraphImpl.cpp:skia::textlayout::nearlyEqual(float, float, float)
Unexecuted instantiation: ParagraphStyle.cpp:skia::textlayout::nearlyEqual(float, float, float)
Unexecuted instantiation: Run.cpp:skia::textlayout::nearlyEqual(float, float, float)
Unexecuted instantiation: TextLine.cpp:skia::textlayout::nearlyEqual(float, float, float)
TextStyle.cpp:skia::textlayout::nearlyEqual(float, float, float)
Line
Count
Source
28
18.3k
static inline bool nearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance = SK_ScalarNearlyZero) {
29
18.3k
    if (SkScalarIsFinite(x) && SkScalarIsFinite(x)) {
30
18.3k
        return SkScalarNearlyEqual(x, y, tolerance);
31
18.3k
    }
32
    // Inf == Inf, anything else is false
33
0
    return x == y;
34
0
}
Unexecuted instantiation: TextWrapper.cpp:skia::textlayout::nearlyEqual(float, float, float)
Unexecuted instantiation: Decorations.cpp:skia::textlayout::nearlyEqual(float, float, float)
Unexecuted instantiation: OneLineShaper.cpp:skia::textlayout::nearlyEqual(float, float, float)
35
36
// Multiple decorations can be applied at once. Ex: Underline and overline is
37
// (0x1 | 0x2)
38
enum TextDecoration {
39
    kNoDecoration = 0x0,
40
    kUnderline = 0x1,
41
    kOverline = 0x2,
42
    kLineThrough = 0x4,
43
};
44
constexpr TextDecoration AllTextDecorations[] = {
45
        kNoDecoration,
46
        kUnderline,
47
        kOverline,
48
        kLineThrough,
49
};
50
51
enum TextDecorationStyle { kSolid, kDouble, kDotted, kDashed, kWavy };
52
53
enum TextDecorationMode { kGaps, kThrough };
54
55
enum StyleType {
56
    kNone,
57
    kAllAttributes,
58
    kFont,
59
    kForeground,
60
    kBackground,
61
    kShadow,
62
    kDecorations,
63
    kLetterSpacing,
64
    kWordSpacing
65
};
66
67
struct Decoration {
68
    TextDecoration fType;
69
    TextDecorationMode fMode;
70
    SkColor fColor;
71
    TextDecorationStyle fStyle;
72
    SkScalar fThicknessMultiplier;
73
74
10.4k
    bool operator==(const Decoration& other) const {
75
10.4k
        return this->fType == other.fType &&
76
10.4k
               this->fMode == other.fMode &&
77
10.4k
               this->fColor == other.fColor &&
78
10.4k
               this->fStyle == other.fStyle &&
79
10.4k
               this->fThicknessMultiplier == other.fThicknessMultiplier;
80
10.4k
    }
81
};
82
83
/// Where to vertically align the placeholder relative to the surrounding text.
84
enum class PlaceholderAlignment {
85
  /// Match the baseline of the placeholder with the baseline.
86
  kBaseline,
87
88
  /// Align the bottom edge of the placeholder with the baseline such that the
89
  /// placeholder sits on top of the baseline.
90
  kAboveBaseline,
91
92
  /// Align the top edge of the placeholder with the baseline specified in
93
  /// such that the placeholder hangs below the baseline.
94
  kBelowBaseline,
95
96
  /// Align the top edge of the placeholder with the top edge of the font.
97
  /// When the placeholder is very tall, the extra space will hang from
98
  /// the top and extend through the bottom of the line.
99
  kTop,
100
101
  /// Align the bottom edge of the placeholder with the top edge of the font.
102
  /// When the placeholder is very tall, the extra space will rise from
103
  /// the bottom and extend through the top of the line.
104
  kBottom,
105
106
  /// Align the middle of the placeholder with the middle of the text. When the
107
  /// placeholder is very tall, the extra space will grow equally from
108
  /// the top and bottom of the line.
109
  kMiddle,
110
};
111
112
struct FontFeature {
113
0
    FontFeature(const SkString name, int value) : fName(name), fValue(value) {}
114
0
    bool operator==(const FontFeature& that) const {
115
0
        return fName == that.fName && fValue == that.fValue;
116
0
    }
117
    SkString fName;
118
    int fValue;
119
};
120
121
struct PlaceholderStyle {
122
4.02k
    PlaceholderStyle() = default;
123
    PlaceholderStyle(SkScalar width, SkScalar height, PlaceholderAlignment alignment,
124
                     TextBaseline baseline, SkScalar offset)
125
            : fWidth(width)
126
            , fHeight(height)
127
            , fAlignment(alignment)
128
            , fBaseline(baseline)
129
0
            , fBaselineOffset(offset) {}
130
131
    bool equals(const PlaceholderStyle&) const;
132
133
    SkScalar fWidth = 0;
134
    SkScalar fHeight = 0;
135
    PlaceholderAlignment fAlignment = PlaceholderAlignment::kBaseline;
136
    TextBaseline fBaseline = TextBaseline::kAlphabetic;
137
    // Distance from the top edge of the rect to the baseline position. This
138
    // baseline will be aligned against the alphabetic baseline of the surrounding
139
    // text.
140
    //
141
    // Positive values drop the baseline lower (positions the rect higher) and
142
    // small or negative values will cause the rect to be positioned underneath
143
    // the line. When baseline == height, the bottom edge of the rect will rest on
144
    // the alphabetic baseline.
145
    SkScalar fBaselineOffset = 0;
146
};
147
148
class TextStyle {
149
public:
150
80.3k
    TextStyle() = default;
151
    TextStyle(const TextStyle& other, bool placeholder);
152
153
    bool equals(const TextStyle& other) const;
154
    bool equalsByFonts(const TextStyle& that) const;
155
    bool matchOneAttribute(StyleType styleType, const TextStyle& other) const;
156
10.4k
    bool operator==(const TextStyle& rhs) const { return this->equals(rhs); }
157
158
    // Colors
159
0
    SkColor getColor() const { return fColor; }
160
0
    void setColor(SkColor color) { fColor = color; }
161
162
0
    bool hasForeground() const { return fHasForeground; }
163
0
    SkPaint getForeground() const { return fForeground; }
164
0
    void setForegroundColor(SkPaint paint) {
165
0
        fHasForeground = true;
166
0
        fForeground = std::move(paint);
167
0
    }
168
0
    void clearForegroundColor() { fHasForeground = false; }
169
170
0
    bool hasBackground() const { return fHasBackground; }
171
0
    SkPaint getBackground() const { return fBackground; }
172
0
    void setBackgroundColor(SkPaint paint) {
173
0
        fHasBackground = true;
174
0
        fBackground = std::move(paint);
175
0
    }
176
0
    void clearBackgroundColor() { fHasBackground = false; }
177
178
    // Decorations
179
0
    Decoration getDecoration() const { return fDecoration; }
180
0
    TextDecoration getDecorationType() const { return fDecoration.fType; }
181
0
    TextDecorationMode getDecorationMode() const { return fDecoration.fMode; }
182
0
    SkColor getDecorationColor() const { return fDecoration.fColor; }
183
0
    TextDecorationStyle getDecorationStyle() const { return fDecoration.fStyle; }
184
0
    SkScalar getDecorationThicknessMultiplier() const {
185
0
        return fDecoration.fThicknessMultiplier;
186
0
    }
187
0
    void setDecoration(TextDecoration decoration) { fDecoration.fType = decoration; }
188
0
    void setDecorationMode(TextDecorationMode mode) { fDecoration.fMode = mode; }
189
0
    void setDecorationStyle(TextDecorationStyle style) { fDecoration.fStyle = style; }
190
0
    void setDecorationColor(SkColor color) { fDecoration.fColor = color; }
191
0
    void setDecorationThicknessMultiplier(SkScalar m) { fDecoration.fThicknessMultiplier = m; }
192
193
    // Weight/Width/Slant
194
191k
    SkFontStyle getFontStyle() const { return fFontStyle; }
195
0
    void setFontStyle(SkFontStyle fontStyle) { fFontStyle = fontStyle; }
196
197
    // Shadows
198
0
    size_t getShadowNumber() const { return fTextShadows.size(); }
199
0
    std::vector<TextShadow> getShadows() const { return fTextShadows; }
200
0
    void addShadow(TextShadow shadow) { fTextShadows.emplace_back(shadow); }
201
0
    void resetShadows() { fTextShadows.clear(); }
202
203
    // Font features
204
0
    size_t getFontFeatureNumber() const { return fFontFeatures.size(); }
205
72.4k
    std::vector<FontFeature> getFontFeatures() const { return fFontFeatures; }
206
    void addFontFeature(const SkString& fontFeature, int value)
207
0
        { fFontFeatures.emplace_back(fontFeature, value); }
208
0
    void resetFontFeatures() { fFontFeatures.clear(); }
209
210
18.7k
    SkScalar getFontSize() const { return fFontSize; }
211
0
    void setFontSize(SkScalar size) { fFontSize = size; }
212
213
76.4k
    const std::vector<SkString>& getFontFamilies() const { return fFontFamilies; }
214
14.6k
    void setFontFamilies(std::vector<SkString> families) {
215
14.6k
        fFontFamilies = std::move(families);
216
14.6k
    }
217
218
0
    void setHeight(SkScalar height) { fHeight = height; }
219
14.7k
    SkScalar getHeight() const { return fHeightOverride ? fHeight : 0; }
220
221
0
    void setHeightOverride(bool heightOverride) { fHeightOverride = heightOverride; }
222
61.7k
    bool getHeightOverride() const { return fHeightOverride; }
223
224
0
    void setHalfLeading(bool halfLeading) { fHalfLeading = halfLeading; }
225
57.6k
    bool getHalfLeading() const { return fHalfLeading; }
226
227
0
    void setLetterSpacing(SkScalar letterSpacing) { fLetterSpacing = letterSpacing; }
228
14.7k
    SkScalar getLetterSpacing() const { return fLetterSpacing; }
229
230
0
    void setWordSpacing(SkScalar wordSpacing) { fWordSpacing = wordSpacing; }
231
14.7k
    SkScalar getWordSpacing() const { return fWordSpacing; }
232
233
0
    SkTypeface* getTypeface() const { return fTypeface.get(); }
234
0
    sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
235
0
    void setTypeface(sk_sp<SkTypeface> typeface) { fTypeface = std::move(typeface); }
236
237
130k
    SkString getLocale() const { return fLocale; }
238
0
    void setLocale(const SkString& locale) { fLocale = locale; }
239
240
0
    TextBaseline getTextBaseline() const { return fTextBaseline; }
241
0
    void setTextBaseline(TextBaseline baseline) { fTextBaseline = baseline; }
242
243
    void getFontMetrics(SkFontMetrics* metrics) const;
244
245
19.3k
    bool isPlaceholder() const { return fIsPlaceholder; }
246
0
    void setPlaceholder() { fIsPlaceholder = true; }
247
248
private:
249
    static const std::vector<SkString> kDefaultFontFamilies;
250
251
    Decoration fDecoration = {
252
            TextDecoration::kNoDecoration,
253
            // TODO: switch back to kGaps when (if) switching flutter to skparagraph
254
            TextDecorationMode::kThrough,
255
            // It does not make sense to draw a transparent object, so we use this as a default
256
            // value to indicate no decoration color was set.
257
            SK_ColorTRANSPARENT, TextDecorationStyle::kSolid,
258
            // Thickness is applied as a multiplier to the default thickness of the font.
259
            1.0f};
260
261
    SkFontStyle fFontStyle;
262
263
    std::vector<SkString> fFontFamilies = kDefaultFontFamilies;
264
265
    SkScalar fFontSize = 14.0;
266
    SkScalar fHeight = 1.0;
267
    bool fHeightOverride = false;
268
    // true: half leading.
269
    // false: scale ascent/descent with fHeight.
270
    bool fHalfLeading = false;
271
    SkString fLocale = {};
272
    SkScalar fLetterSpacing = 0.0;
273
    SkScalar fWordSpacing = 0.0;
274
275
    TextBaseline fTextBaseline = TextBaseline::kAlphabetic;
276
277
    SkColor fColor = SK_ColorWHITE;
278
    bool fHasBackground = false;
279
    SkPaint fBackground;
280
    bool fHasForeground = false;
281
    SkPaint fForeground;
282
283
    std::vector<TextShadow> fTextShadows;
284
285
    sk_sp<SkTypeface> fTypeface;
286
    bool fIsPlaceholder = false;
287
288
    std::vector<FontFeature> fFontFeatures;
289
};
290
291
typedef size_t TextIndex;
292
typedef SkRange<size_t> TextRange;
293
const SkRange<size_t> EMPTY_TEXT = EMPTY_RANGE;
294
295
struct Block {
296
57.6k
    Block() = default;
297
12.9k
    Block(size_t start, size_t end, const TextStyle& style) : fRange(start, end), fStyle(style) {}
298
0
    Block(TextRange textRange, const TextStyle& style) : fRange(textRange), fStyle(style) {}
299
300
0
    void add(TextRange tail) {
301
0
        SkASSERT(fRange.end == tail.start);
302
0
        fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
303
0
    }
304
305
    TextRange fRange = EMPTY_RANGE;
306
    TextStyle fStyle;
307
};
308
309
310
typedef size_t BlockIndex;
311
typedef SkRange<size_t> BlockRange;
312
const size_t EMPTY_BLOCK = EMPTY_INDEX;
313
const SkRange<size_t> EMPTY_BLOCKS = EMPTY_RANGE;
314
315
struct Placeholder {
316
    Placeholder() = default;
317
    Placeholder(size_t start, size_t end, const PlaceholderStyle& style, const TextStyle& textStyle,
318
                BlockRange blocksBefore, TextRange textBefore)
319
            : fRange(start, end)
320
            , fStyle(style)
321
            , fTextStyle(textStyle)
322
            , fBlocksBefore(blocksBefore)
323
4.02k
            , fTextBefore(textBefore) {}
324
325
    TextRange fRange = EMPTY_RANGE;
326
    PlaceholderStyle fStyle;
327
    TextStyle fTextStyle;
328
    BlockRange fBlocksBefore;
329
    TextRange fTextBefore;
330
};
331
332
}  // namespace textlayout
333
}  // namespace skia
334
335
#endif  // TextStyle_DEFINED