blob: dacabb404f064515826f2e44522c71f937dc89cc [file] [log] [blame]
bungeman@google.combbe50132012-07-24 20:33:21 +00001/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkGlyph_DEFINED
9#define SkGlyph_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkPath.h"
12#include "include/core/SkTypes.h"
13#include "include/private/SkChecksum.h"
14#include "include/private/SkFixed.h"
15#include "include/private/SkTo.h"
16#include "src/core/SkMask.h"
Herb Derby7c5a8062017-01-20 11:59:03 -050017
Herb Derby82191632018-10-24 14:49:26 -040018class SkArenaAlloc;
Herb Derby5fd955e2019-01-16 11:23:29 -050019class SkStrike;
Herb Derbyf4958ce2018-11-27 13:17:02 -050020class SkScalerContext;
bungeman@google.combbe50132012-07-24 20:33:21 +000021
22// needs to be != to any valid SkMask::Format
23#define MASK_FORMAT_UNKNOWN (0xFF)
24#define MASK_FORMAT_JUST_ADVANCE MASK_FORMAT_UNKNOWN
25
Herb Derby8207b642019-05-23 11:35:56 -040026/** SkGlyphID + subpixel-pos */
27struct SkPackedGlyphID {
28 static constexpr uint32_t kImpossibleID = ~0u;
herbb69d0e02015-02-25 06:47:06 -080029 enum {
Herb Derby8207b642019-05-23 11:35:56 -040030 kSubBits = 2u,
31 kSubMask = ((1u << kSubBits) - 1),
32 kSubShift = 24u, // must be large enough for glyphs and unichars
33 kCodeMask = ((1u << kSubShift) - 1),
herbb69d0e02015-02-25 06:47:06 -080034 // relative offsets for X and Y subpixel bits
35 kSubShiftX = kSubBits,
36 kSubShiftY = 0
37 };
38
Herb Derby8207b642019-05-23 11:35:56 -040039 constexpr explicit SkPackedGlyphID(SkGlyphID glyphID)
40 : fID{glyphID} { }
41
42 constexpr SkPackedGlyphID(SkGlyphID glyphID, SkFixed x, SkFixed y)
43 : fID {PackIDXY(glyphID, x, y)} {
44 SkASSERT(fID != kImpossibleID);
Ben Wagner6e9ac122016-11-11 14:31:06 -050045 }
46
Herb Derby8207b642019-05-23 11:35:56 -040047 constexpr SkPackedGlyphID(SkGlyphID code, SkIPoint pt)
48 : SkPackedGlyphID(code, pt.fX, pt.fY) { }
Ben Wagner6e9ac122016-11-11 14:31:06 -050049
Herb Derby8207b642019-05-23 11:35:56 -040050 constexpr SkPackedGlyphID() : fID{kImpossibleID} {}
Ben Wagner6e9ac122016-11-11 14:31:06 -050051
Herb Derby8207b642019-05-23 11:35:56 -040052 bool operator==(const SkPackedGlyphID& that) const {
Ben Wagner6e9ac122016-11-11 14:31:06 -050053 return fID == that.fID;
54 }
Herb Derby8207b642019-05-23 11:35:56 -040055 bool operator!=(const SkPackedGlyphID& that) const {
Ben Wagner6e9ac122016-11-11 14:31:06 -050056 return !(*this == that);
57 }
Herb Derby8207b642019-05-23 11:35:56 -040058 bool operator<(SkPackedGlyphID that) const {
Herb Derbyefbf00c2018-03-14 11:53:40 -040059 return this->fID < that.fID;
60 }
Ben Wagner6e9ac122016-11-11 14:31:06 -050061
62 uint32_t code() const {
63 return fID & kCodeMask;
64 }
65
Herb Derby82191632018-10-24 14:49:26 -040066 uint32_t value() const {
Herb Derbyefbf00c2018-03-14 11:53:40 -040067 return fID;
68 }
69
Ben Wagner6e9ac122016-11-11 14:31:06 -050070 SkFixed getSubXFixed() const {
71 return SubToFixed(ID2SubX(fID));
72 }
73
74 SkFixed getSubYFixed() const {
75 return SubToFixed(ID2SubY(fID));
76 }
77
78 uint32_t hash() const {
79 return SkChecksum::CheapMix(fID);
80 }
81
Khushal4010c792018-06-13 09:44:23 -070082 SkString dump() const {
83 SkString str;
84 str.appendf("code: %d, x: %d, y:%d", code(), getSubXFixed(), getSubYFixed());
85 return str;
86 }
87
Ben Wagner6e9ac122016-11-11 14:31:06 -050088private:
Herb Derby8207b642019-05-23 11:35:56 -040089 static constexpr uint32_t PackIDXY(SkGlyphID glyphID, SkFixed x, SkFixed y) {
90 return (FixedToSub(x) << (kSubShift + kSubShiftX))
91 | (FixedToSub(y) << (kSubShift + kSubShiftY))
92 | glyphID;
93 }
94
95 static constexpr unsigned ID2SubX(uint32_t id) {
Ben Wagner6e9ac122016-11-11 14:31:06 -050096 return id >> (kSubShift + kSubShiftX);
97 }
98
Herb Derby8207b642019-05-23 11:35:56 -040099 static constexpr unsigned ID2SubY(uint32_t id) {
Ben Wagner6e9ac122016-11-11 14:31:06 -0500100 return (id >> (kSubShift + kSubShiftY)) & kSubMask;
101 }
102
Herb Derby8207b642019-05-23 11:35:56 -0400103 static constexpr unsigned FixedToSub(SkFixed n) {
Ben Wagner6e9ac122016-11-11 14:31:06 -0500104 return (n >> (16 - kSubBits)) & kSubMask;
105 }
106
Herb Derby8207b642019-05-23 11:35:56 -0400107 static constexpr SkFixed SubToFixed(uint32_t sub) {
Ben Wagner6e9ac122016-11-11 14:31:06 -0500108 SkASSERT(sub <= kSubMask);
Herb Derby8207b642019-05-23 11:35:56 -0400109 return sub << (16u - kSubBits);
Ben Wagner6e9ac122016-11-11 14:31:06 -0500110 }
111
112 uint32_t fID;
113};
114
Herb Derby37216882019-06-13 17:24:24 -0400115struct SkGlyphPrototype;
Herb Derby82191632018-10-24 14:49:26 -0400116
Herb Derby37216882019-06-13 17:24:24 -0400117class SkGlyph {
Herb Derby82191632018-10-24 14:49:26 -0400118public:
Herb Derby8207b642019-05-23 11:35:56 -0400119 static constexpr SkFixed kSubpixelRound = SK_FixedHalf >> SkPackedGlyphID::kSubBits;
Herb Derby82191632018-10-24 14:49:26 -0400120
Herb Derby793818b2019-06-25 17:10:11 -0400121 constexpr explicit SkGlyph(SkPackedGlyphID id) : fID{id} { }
Herb Derby37216882019-06-13 17:24:24 -0400122 explicit SkGlyph(const SkGlyphPrototype& p);
123
Herb Derbye713a3c2019-06-11 14:32:06 -0400124 SkVector advanceVector() const { return SkVector{fAdvanceX, fAdvanceY}; }
125 SkScalar advanceX() const { return fAdvanceX; }
126 SkScalar advanceY() const { return fAdvanceY; }
127
Herb Derby82191632018-10-24 14:49:26 -0400128 SkGlyphID getGlyphID() const { return fID.code(); }
129 SkPackedGlyphID getPackedID() const { return fID; }
130 SkFixed getSubXFixed() const { return fID.getSubXFixed(); }
131 SkFixed getSubYFixed() const { return fID.getSubYFixed(); }
132
Herb Derby82191632018-10-24 14:49:26 -0400133 size_t rowBytes() const;
Herb Derby82191632018-10-24 14:49:26 -0400134 size_t rowBytesUsingFormat(SkMask::Format format) const;
135
136 // Call this to set all of the metrics fields to 0 (e.g. if the scaler
137 // encounters an error measuring a glyph). Note: this does not alter the
138 // fImage, fPath, fID, fMaskFormat fields.
139 void zeroMetrics();
140
Herb Derby990bfc72019-04-12 15:48:56 -0400141 SkMask mask() const;
Herb Derby82191632018-10-24 14:49:26 -0400142
Herb Derbyc48879e2019-04-11 15:22:38 -0400143 SkMask mask(SkPoint position) const;
144
Herb Derby9b06f212019-06-21 14:25:47 -0400145 // Image
146 // If we haven't already tried to associate an image with this glyph
147 // (i.e. setImageHasBeenCalled() returns false), then use the
148 // SkScalerContext or const void* argument to set the image.
149 bool setImage(SkArenaAlloc* alloc, SkScalerContext* scalerContext);
150 bool setImage(SkArenaAlloc* alloc, const void* image);
151
Herb Derby70190602019-06-24 14:53:59 -0400152 // Merge the from glyph into this glyph using alloc to allocate image data. Return true if
153 // image data was allocated. If the image for this glyph has not been initialized, then copy
154 // the width, height, top, left, format, and image into this glyph making a copy of the image
155 // using the alloc.
156 bool setMetricsAndImage(SkArenaAlloc* alloc, const SkGlyph& from);
157
Herb Derby9b06f212019-06-21 14:25:47 -0400158 // Returns true if the image has been set.
159 bool setImageHasBeenCalled() const {
160 return fImage != nullptr || this->isEmpty() || this->imageTooLarge();
161 }
162
163 // Return a pointer to the path if the image exists, otherwise return nullptr.
164 const void* image() const { SkASSERT(this->setImageHasBeenCalled()); return fImage; }
165
166 // Return the size of the image.
167 size_t imageSize() const;
168
169 // Path
Herb Derbyf0e75812019-06-12 11:14:50 -0400170 // If we haven't already tried to associate a path to this glyph
171 // (i.e. setPathHasBeenCalled() returns false), then use the
172 // SkScalerContext or SkPath argument to try to do so. N.B. this
173 // may still result in no path being associated with this glyph,
174 // e.g. if you pass a null SkPath or the typeface is bitmap-only.
175 //
176 // This setPath() call is sticky... once you call it, the glyph
177 // stays in its state permanently, ignoring any future calls.
178 //
179 // Returns true if this is the first time you called setPath()
180 // and there actually is a path; call path() to get it.
181 bool setPath(SkArenaAlloc* alloc, SkScalerContext* scalerContext);
182 bool setPath(SkArenaAlloc* alloc, const SkPath* path);
Herb Derbyf4958ce2018-11-27 13:17:02 -0500183
Herb Derbyf0e75812019-06-12 11:14:50 -0400184 // Returns true if that path has been set.
185 bool setPathHasBeenCalled() const { return fPathData != nullptr; }
Herbert Derby7218f1f2018-11-30 11:15:46 -0500186
Herb Derbyf0e75812019-06-12 11:14:50 -0400187 // Return a pointer to the path if it exists, otherwise return nullptr. Only works if the
188 // path was previously set.
189 const SkPath* path() const;
Herb Derby5dd7f842019-04-16 11:20:38 -0400190
Herb Derby37216882019-06-13 17:24:24 -0400191 // Format
192 bool isColor() const { return fMaskFormat == SkMask::kARGB32_Format; }
193 SkMask::Format maskFormat() const { return static_cast<SkMask::Format>(fMaskFormat); }
Herb Derby9b06f212019-06-21 14:25:47 -0400194 size_t formatAlignment() const;
Herb Derby37216882019-06-13 17:24:24 -0400195
Herb Derby71f2eb72019-06-19 15:57:39 -0400196 // Bounds
197 int maxDimension() const { return std::max(fWidth, fHeight); }
198 SkIRect iRect() const { return SkIRect::MakeXYWH(fLeft, fTop, fWidth, fHeight); }
199 SkRect rect() const { return SkRect::MakeXYWH(fLeft, fTop, fWidth, fHeight); }
200 int left() const { return fLeft; }
201 int top() const { return fTop; }
202 int width() const { return fWidth; }
203 int height() const { return fHeight; }
204 bool isEmpty() const {
205 // fHeight == 0 -> fWidth == 0;
206 SkASSERT(fHeight != 0 || fWidth == 0);
207 return fWidth == 0;
Herb Derbya5199992019-04-09 14:15:14 +0000208 }
Herb Derby9b06f212019-06-21 14:25:47 -0400209 bool imageTooLarge() const { return fWidth >= kMaxGlyphWidth; }
Herb Derbya5199992019-04-09 14:15:14 +0000210
Herb Derby11697dc2019-06-06 11:50:42 -0400211 // Make sure that the intercept information is on the glyph and return it, or return it if it
212 // already exists.
213 // * bounds - either end of the gap for the character.
214 // * scale, xPos - information about how wide the gap is.
215 // * array - accumulated gaps for many characters if not null.
216 // * count - the number of gaps.
217 void ensureIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos,
218 SkScalar* array, int* count, SkArenaAlloc* alloc);
219
Herb Derby82191632018-10-24 14:49:26 -0400220private:
Herb Derbye713a3c2019-06-11 14:32:06 -0400221 // There are two sides to an SkGlyph, the scaler side (things that create glyph data) have
222 // access to all the fields. Scalers are assumed to maintain all the SkGlyph invariants. The
223 // consumer side has a tighter interface.
Herb Derby37216882019-06-13 17:24:24 -0400224 friend class RandomScalerContext;
225 friend class SkScalerContext;
226 friend class SkScalerContextProxy;
227 friend class SkScalerContext_Empty;
Herb Derbye713a3c2019-06-11 14:32:06 -0400228 friend class SkScalerContext_FreeType;
Herb Derby37216882019-06-13 17:24:24 -0400229 friend class SkScalerContext_FreeType_Base;
Herb Derbycc5dc012019-06-11 13:48:41 -0400230 friend class SkScalerContext_DW;
Herb Derbye713a3c2019-06-11 14:32:06 -0400231 friend class SkScalerContext_GDI;
232 friend class SkScalerContext_Mac;
233 friend class SkStrikeClient;
Herb Derby37216882019-06-13 17:24:24 -0400234 friend class SkStrikeServer;
Herb Derbye713a3c2019-06-11 14:32:06 -0400235 friend class SkTestScalerContext;
236 friend class SkTestSVGScalerContext;
237 friend class TestSVGTypeface;
238 friend class TestTypeface;
Herb Derbyf6fca262019-01-09 15:13:54 -0500239
Herb Derby9b06f212019-06-21 14:25:47 -0400240 static constexpr uint16_t kMaxGlyphWidth = 1u << 13u;
241
caryclark0449bcf2016-02-09 13:25:45 -0800242 // Support horizontal and vertical skipping strike-through / underlines.
243 // The caller walks the linked list looking for a match. For a horizontal underline,
244 // the fBounds contains the top and bottom of the underline. The fInterval pair contains the
245 // beginning and end of of the intersection of the bounds and the glyph's path.
Herb Derby37216882019-06-13 17:24:24 -0400246 // If interval[0] >= interval[1], no intersection was found.
caryclark0449bcf2016-02-09 13:25:45 -0800247 struct Intercept {
248 Intercept* fNext;
249 SkScalar fBounds[2]; // for horz underlines, the boundaries in Y
250 SkScalar fInterval[2]; // the outside intersections of the axis and the glyph
251 };
252
253 struct PathData {
Herbert Derby9bd83462018-11-30 15:40:55 -0500254 Intercept* fIntercept{nullptr};
255 SkPath fPath;
256 bool fHasPath{false};
caryclark0449bcf2016-02-09 13:25:45 -0800257 };
258
Herb Derby793818b2019-06-25 17:10:11 -0400259 size_t allocImage(SkArenaAlloc* alloc);
260
261 // path == nullptr indicates that there is no path.
Herb Derbyf0e75812019-06-12 11:14:50 -0400262 void installPath(SkArenaAlloc* alloc, const SkPath* path);
263
Herb Derby793818b2019-06-25 17:10:11 -0400264 // The width and height of the glyph mask.
265 uint16_t fWidth = 0,
266 fHeight = 0;
267
268 // The offset from the glyphs origin on the baseline to the top left of the glyph mask.
269 int16_t fTop = 0,
270 fLeft = 0;
271
272 // fImage must remain null if the glyph is empty or if width > kMaxGlyphWidth.
273 void* fImage = nullptr;
274
Herb Derbyf0e75812019-06-12 11:14:50 -0400275 // Path data has tricky state. If the glyph isEmpty, then fPathData should always be nullptr,
276 // else if fPathData is not null, then a path has been requested. The fPath field of fPathData
277 // may still be null after the request meaning that there is no path for this glyph.
278 PathData* fPathData = nullptr;
279
Herb Derbye713a3c2019-06-11 14:32:06 -0400280 // The advance for this glyph.
281 float fAdvanceX = 0,
282 fAdvanceY = 0;
283
Herb Derby37216882019-06-13 17:24:24 -0400284 // This is a combination of SkMask::Format and SkGlyph state. The SkGlyph can be in one of two
285 // states, just the advances have been calculated, and all the metrics are available. The
286 // illegal mask format is used to signal that only the advances are available.
287 uint8_t fMaskFormat = MASK_FORMAT_UNKNOWN;
288
Herb Derbycc5dc012019-06-11 13:48:41 -0400289 // Used by the DirectWrite scaler to track state.
290 int8_t fForceBW = 0;
291
Herb Derby793818b2019-06-25 17:10:11 -0400292 const SkPackedGlyphID fID;
bungeman@google.combbe50132012-07-24 20:33:21 +0000293};
bungeman@google.combbe50132012-07-24 20:33:21 +0000294
Herb Derby37216882019-06-13 17:24:24 -0400295struct SkGlyphPrototype {
296 SkPackedGlyphID id;
297
298 float advanceX = 0,
299 advanceY = 0;
300
301 // The width and height of the glyph mask.
302 uint16_t width = 0,
303 height = 0;
304
305 // The offset from the glyphs origin on the baseline to the top left of the glyph mask.
306 int16_t left = 0,
307 top = 0;
308
309 SkMask::Format maskFormat = SkMask::kBW_Format;
310
Herb Derby9b06f212019-06-21 14:25:47 -0400311 bool forceBW = false;
Herb Derby37216882019-06-13 17:24:24 -0400312};
313
bungeman@google.combbe50132012-07-24 20:33:21 +0000314#endif