Coverage Report

Created: 2024-05-20 07:14

/src/skia/modules/skparagraph/src/TextStyle.cpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2019 Google LLC.
2
#include "include/core/SkColor.h"
3
#include "include/core/SkFontStyle.h"
4
#include "modules/skparagraph/include/TextStyle.h"
5
6
namespace skia {
7
namespace textlayout {
8
9
const std::vector<SkString>* TextStyle::kDefaultFontFamilies =
10
        new std::vector<SkString>{SkString(DEFAULT_FONT_FAMILY)};
11
12
0
TextStyle TextStyle::cloneForPlaceholder() {
13
0
    TextStyle result;
14
0
    result.fColor = fColor;
15
0
    result.fFontSize = fFontSize;
16
0
    result.fFontFamilies = fFontFamilies;
17
0
    result.fDecoration = fDecoration;
18
0
    result.fHasBackground = fHasBackground;
19
0
    result.fHasForeground = fHasForeground;
20
0
    result.fBackground = fBackground;
21
0
    result.fForeground = fForeground;
22
0
    result.fHeightOverride = fHeightOverride;
23
0
    result.fIsPlaceholder = true;
24
0
    result.fFontFeatures = fFontFeatures;
25
0
    result.fHalfLeading = fHalfLeading;
26
0
    result.fBaselineShift = fBaselineShift;
27
0
    result.fFontArguments = fFontArguments;
28
0
    return result;
29
0
}
30
31
0
bool TextStyle::equals(const TextStyle& other) const {
32
33
0
    if (fIsPlaceholder || other.fIsPlaceholder) {
34
0
        return false;
35
0
    }
36
37
0
    if (fColor != other.fColor) {
38
0
        return false;
39
0
    }
40
0
    if (!(fDecoration == other.fDecoration)) {
41
0
        return false;
42
0
    }
43
0
    if (!(fFontStyle == other.fFontStyle)) {
44
0
        return false;
45
0
    }
46
0
    if (fFontFamilies != other.fFontFamilies) {
47
0
        return false;
48
0
    }
49
0
    if (fLetterSpacing != other.fLetterSpacing) {
50
0
        return false;
51
0
    }
52
0
    if (fWordSpacing != other.fWordSpacing) {
53
0
        return false;
54
0
    }
55
0
    if (fHeight != other.fHeight) {
56
0
        return false;
57
0
    }
58
0
    if (fHeightOverride != other.fHeightOverride) {
59
0
        return false;
60
0
    }
61
0
    if (fHalfLeading != other.fHalfLeading) {
62
0
        return false;
63
0
    }
64
0
    if (fBaselineShift != other.fBaselineShift) {
65
0
        return false;
66
0
    }
67
0
    if (fFontSize != other.fFontSize) {
68
0
        return false;
69
0
    }
70
0
    if (fLocale != other.fLocale) {
71
0
        return false;
72
0
    }
73
0
    if (fHasForeground != other.fHasForeground || fForeground != other.fForeground) {
74
0
        return false;
75
0
    }
76
0
    if (fHasBackground != other.fHasBackground || fBackground != other.fBackground) {
77
0
        return false;
78
0
    }
79
0
    if (fTextShadows.size() != other.fTextShadows.size()) {
80
0
        return false;
81
0
    }
82
0
    for (size_t i = 0; i < fTextShadows.size(); ++i) {
83
0
        if (fTextShadows[i] != other.fTextShadows[i]) {
84
0
            return false;
85
0
        }
86
0
    }
87
0
    if (fFontFeatures.size() != other.fFontFeatures.size()) {
88
0
        return false;
89
0
    }
90
0
    for (size_t i = 0; i < fFontFeatures.size(); ++i) {
91
0
        if (!(fFontFeatures[i] == other.fFontFeatures[i])) {
92
0
            return false;
93
0
        }
94
0
    }
95
0
    if (fFontArguments != other.fFontArguments) {
96
0
        return false;
97
0
    }
98
99
0
    return true;
100
0
}
101
102
0
bool TextStyle::equalsByFonts(const TextStyle& that) const {
103
104
0
    return !fIsPlaceholder && !that.fIsPlaceholder &&
105
0
           fFontStyle == that.fFontStyle &&
106
0
           fFontFamilies == that.fFontFamilies &&
107
0
           fFontFeatures == that.fFontFeatures &&
108
0
           fFontArguments == that.getFontArguments() &&
109
0
           nearlyEqual(fLetterSpacing, that.fLetterSpacing) &&
110
0
           nearlyEqual(fWordSpacing, that.fWordSpacing) &&
111
0
           nearlyEqual(fHeight, that.fHeight) &&
112
0
           nearlyEqual(fBaselineShift, that.fBaselineShift) &&
113
0
           nearlyEqual(fFontSize, that.fFontSize) &&
114
0
           fLocale == that.fLocale;
115
0
}
116
117
0
bool TextStyle::matchOneAttribute(StyleType styleType, const TextStyle& other) const {
118
0
    switch (styleType) {
119
0
        case kForeground:
120
0
            return (!fHasForeground && !other.fHasForeground && fColor == other.fColor) ||
121
0
                   ( fHasForeground &&  other.fHasForeground && fForeground == other.fForeground);
122
123
0
        case kBackground:
124
0
            return (!fHasBackground && !other.fHasBackground) ||
125
0
                   ( fHasBackground &&  other.fHasBackground && fBackground == other.fBackground);
126
127
0
        case kShadow:
128
0
            if (fTextShadows.size() != other.fTextShadows.size()) {
129
0
                return false;
130
0
            }
131
132
0
            for (int32_t i = 0; i < SkToInt(fTextShadows.size()); ++i) {
133
0
                if (fTextShadows[i] != other.fTextShadows[i]) {
134
0
                    return false;
135
0
                }
136
0
            }
137
0
            return true;
138
139
0
        case kDecorations:
140
0
            return this->fDecoration == other.fDecoration;
141
142
0
        case kLetterSpacing:
143
0
            return fLetterSpacing == other.fLetterSpacing;
144
145
0
        case kWordSpacing:
146
0
            return fWordSpacing == other.fWordSpacing;
147
148
0
        case kAllAttributes:
149
0
            return this->equals(other);
150
151
0
        case kFont:
152
            // TODO: should not we take typefaces in account?
153
0
            return fFontStyle == other.fFontStyle &&
154
0
                   fLocale == other.fLocale &&
155
0
                   fFontFamilies == other.fFontFamilies &&
156
0
                   fFontSize == other.fFontSize &&
157
0
                   fHeight == other.fHeight &&
158
0
                   fHalfLeading == other.fHalfLeading &&
159
0
                   fBaselineShift == other.fBaselineShift &&
160
0
                   fFontArguments == other.fFontArguments;
161
0
        default:
162
0
            SkASSERT(false);
163
0
            return false;
164
0
    }
165
0
}
166
167
0
void TextStyle::getFontMetrics(SkFontMetrics* metrics) const {
168
0
    SkFont font(fTypeface, fFontSize);
169
0
    font.setEdging(SkFont::Edging::kAntiAlias);
170
0
    font.setSubpixel(true);
171
0
    font.setHinting(SkFontHinting::kSlight);
172
0
    font.getMetrics(metrics);
173
0
    if (fHeightOverride) {
174
0
        auto multiplier = fHeight * fFontSize;
175
0
        auto height = metrics->fDescent - metrics->fAscent + metrics->fLeading;
176
0
        metrics->fAscent = (metrics->fAscent - metrics->fLeading / 2) * multiplier / height;
177
0
        metrics->fDescent = (metrics->fDescent + metrics->fLeading / 2) * multiplier / height;
178
179
0
    } else {
180
0
        metrics->fAscent = (metrics->fAscent - metrics->fLeading / 2);
181
0
        metrics->fDescent = (metrics->fDescent + metrics->fLeading / 2);
182
0
    }
183
    // If we shift the baseline we need to make sure the shifted text fits the line
184
0
    metrics->fAscent += fBaselineShift;
185
0
    metrics->fDescent += fBaselineShift;
186
0
}
187
188
0
void TextStyle::setFontArguments(const std::optional<SkFontArguments>& args) {
189
0
    if (!args) {
190
0
        fFontArguments.reset();
191
0
        return;
192
0
    }
193
194
0
    fFontArguments.emplace(*args);
195
0
}
196
197
0
bool PlaceholderStyle::equals(const PlaceholderStyle& other) const {
198
0
    return nearlyEqual(fWidth, other.fWidth) &&
199
0
           nearlyEqual(fHeight, other.fHeight) &&
200
0
           fAlignment == other.fAlignment &&
201
0
           fBaseline == other.fBaseline &&
202
0
           (fAlignment != PlaceholderAlignment::kBaseline ||
203
0
            nearlyEqual(fBaselineOffset, other.fBaselineOffset));
204
0
}
205
206
}  // namespace textlayout
207
}  // namespace skia