Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / core / SkGlyphRun.cpp
1 /*
2  * Copyright 2018 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 #include "src/core/SkGlyphRun.h"
9
10 #include "include/core/SkFont.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkRSXform.h"
13 #include "include/core/SkTextBlob.h"
14 #include "src/core/SkDevice.h"
15 #include "src/core/SkFontPriv.h"
16 #include "src/core/SkScalerCache.h"
17 #include "src/core/SkStrikeCache.h"
18 #include "src/core/SkStrikeSpec.h"
19 #include "src/core/SkTextBlobPriv.h"
20 #include "src/core/SkUtils.h"
21
22 // -- SkGlyphRun -----------------------------------------------------------------------------------
23 SkGlyphRun::SkGlyphRun(const SkFont& font,
24                        SkSpan<const SkPoint> positions,
25                        SkSpan<const SkGlyphID> glyphIDs,
26                        SkSpan<const char> text,
27                        SkSpan<const uint32_t> clusters,
28                        SkSpan<const SkVector> scaledRotations)
29         : fSource{SkMakeZip(glyphIDs, positions)}
30         , fText{text}
31         , fClusters{clusters}
32         , fScaledRotations{scaledRotations}
33         , fFont{font} {}
34
35 SkGlyphRun::SkGlyphRun(const SkGlyphRun& that, const SkFont& font)
36     : fSource{that.fSource}
37     , fText{that.fText}
38     , fClusters{that.fClusters}
39     , fFont{font} {}
40
41 SkRect SkGlyphRun::sourceBounds(const SkPaint& paint) const {
42     SkASSERT(this->runSize() > 0);
43     const SkRect fontBounds = SkFontPriv::GetFontBounds(fFont);
44
45     if (fontBounds.isEmpty()) {
46         // Empty font bounds are likely a font bug.  TightBounds has a better chance of
47         // producing useful results in this case.
48         auto [strikeSpec, strikeToSourceScale] = SkStrikeSpec::MakeCanonicalized(fFont, &paint);
49         SkBulkGlyphMetrics metrics{strikeSpec};
50         SkSpan<const SkGlyph*> glyphs = metrics.glyphs(this->glyphsIDs());
51         if (fScaledRotations.empty()) {
52             // No RSXForm data - glyphs x/y aligned.
53             auto scaleAndTranslateRect =
54                 [scale = strikeToSourceScale](const SkRect& in, const SkPoint& pos) {
55                     return SkRect::MakeLTRB(in.left()   * scale + pos.x(),
56                                             in.top()    * scale + pos.y(),
57                                             in.right()  * scale + pos.x(),
58                                             in.bottom() * scale + pos.y());
59                 };
60
61             SkRect bounds = SkRect::MakeEmpty();
62             for (auto [pos, glyph] : SkMakeZip(this->positions(), glyphs)) {
63                 if (SkRect r = glyph->rect(); !r.isEmpty()) {
64                     bounds.join(scaleAndTranslateRect(r, pos));
65                 }
66             }
67             return bounds;
68         } else {
69             // RSXForm - glyphs can be any scale or rotation.
70             SkRect bounds = SkRect::MakeEmpty();
71             for (auto [pos, scaleRotate, glyph] :
72                     SkMakeZip(this->positions(), fScaledRotations, glyphs)) {
73                 if (!glyph->rect().isEmpty()) {
74                     SkMatrix xform = SkMatrix().setRSXform(
75                             SkRSXform{pos.x(), pos.y(), scaleRotate.x(), scaleRotate.y()});
76                     xform.preScale(strikeToSourceScale, strikeToSourceScale);
77                     bounds.join(xform.mapRect(glyph->rect()));
78                 }
79             }
80             return bounds;
81         }
82     }
83
84     // Use conservative bounds. All glyph have a box of fontBounds size.
85     if (fScaledRotations.empty()) {
86         SkRect bounds;
87         bounds.setBounds(this->positions().data(), SkCount(this->positions()));
88         bounds.fLeft   += fontBounds.left();
89         bounds.fTop    += fontBounds.top();
90         bounds.fRight  += fontBounds.right();
91         bounds.fBottom += fontBounds.bottom();
92         return bounds;
93     } else {
94         // RSXForm case glyphs can be any scale or rotation.
95         SkRect bounds;
96         bounds.setEmpty();
97         for (auto [pos, scaleRotate] : SkMakeZip(this->positions(), fScaledRotations)) {
98             const SkRSXform xform{pos.x(), pos.y(), scaleRotate.x(), scaleRotate.y()};
99             bounds.join(SkMatrix().setRSXform(xform).mapRect(fontBounds));
100         }
101         return bounds;
102     }
103 }
104
105 // -- SkGlyphRunList -------------------------------------------------------------------------------
106 SkGlyphRunList::SkGlyphRunList(
107         const SkTextBlob* blob,
108         SkRect bounds,
109         SkPoint origin,
110         SkSpan<const SkGlyphRun> glyphRunList,
111         SkGlyphRunBuilder* builder)
112         : fGlyphRuns{glyphRunList}
113         , fOriginalTextBlob{blob}
114         , fSourceBounds{bounds}
115         , fOrigin{origin}
116         , fBuilder{builder} {}
117
118 SkGlyphRunList::SkGlyphRunList(const SkGlyphRun& glyphRun,
119                                const SkRect& bounds,
120                                SkPoint origin,
121                                SkGlyphRunBuilder* builder)
122         : fGlyphRuns{SkSpan<const SkGlyphRun>{&glyphRun, 1}}
123         , fOriginalTextBlob{nullptr}
124         , fSourceBounds{bounds}
125         , fOrigin{origin}
126         , fBuilder{builder} {}
127
128 uint64_t SkGlyphRunList::uniqueID() const {
129     return fOriginalTextBlob != nullptr ? fOriginalTextBlob->uniqueID()
130                                         : SK_InvalidUniqueID;
131 }
132
133 bool SkGlyphRunList::anyRunsLCD() const {
134     for (const auto& r : fGlyphRuns) {
135         if (r.font().getEdging() == SkFont::Edging::kSubpixelAntiAlias) {
136             return true;
137         }
138     }
139     return false;
140 }
141
142 void SkGlyphRunList::temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const {
143     SkASSERT(fOriginalTextBlob != nullptr);
144     fOriginalTextBlob->notifyAddedToCache(cacheID);
145 }
146
147 sk_sp<SkTextBlob> SkGlyphRunList::makeBlob() const {
148     SkTextBlobBuilder builder;
149     for (auto& run : *this) {
150         SkTextBlobBuilder::RunBuffer buffer;
151         if (run.scaledRotations().empty()) {
152             if (run.text().empty()) {
153                 buffer = builder.allocRunPos(run.font(), run.runSize(), nullptr);
154             } else {
155                 buffer = builder.allocRunTextPos(run.font(), run.runSize(), run.text().size(), nullptr);
156                 auto text = run.text();
157                 memcpy(buffer.utf8text, text.data(), text.size_bytes());
158                 auto clusters = run.clusters();
159                 memcpy(buffer.clusters, clusters.data(), clusters.size_bytes());
160             }
161             auto positions = run.positions();
162             memcpy(buffer.points(), positions.data(), positions.size_bytes());
163         } else {
164             buffer = builder.allocRunRSXform(run.font(), run.runSize());
165             for (auto [xform, pos, sr] : SkMakeZip(buffer.xforms(),
166                                                    run.positions(),
167                                                    run.scaledRotations())) {
168                 xform = SkRSXform::Make(sr.x(), sr.y(), pos.x(), pos.y());
169             }
170         }
171         auto glyphIDs = run.glyphsIDs();
172         memcpy(buffer.glyphs, glyphIDs.data(), glyphIDs.size_bytes());
173     }
174     return builder.make();
175 }
176
177 // -- SkGlyphRunBuilder ----------------------------------------------------------------------------
178 SkGlyphRunList SkGlyphRunBuilder::makeGlyphRunList(
179         const SkGlyphRun& run, SkRect bounds, SkPoint origin) {
180     return SkGlyphRunList{run, bounds, origin, this};
181 }
182
183 static SkSpan<const SkPoint> draw_text_positions(
184         const SkFont& font, SkSpan<const SkGlyphID> glyphIDs, SkPoint origin, SkPoint* buffer) {
185     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(font);
186     SkBulkGlyphMetrics storage{strikeSpec};
187     auto glyphs = storage.glyphs(glyphIDs);
188
189     SkPoint* positionCursor = buffer;
190     SkPoint endOfLastGlyph = origin;
191     for (auto glyph : glyphs) {
192         *positionCursor++ = endOfLastGlyph;
193         endOfLastGlyph += glyph->advanceVector();
194     }
195     return SkMakeSpan(buffer, glyphIDs.size());
196 }
197
198 const SkGlyphRunList& SkGlyphRunBuilder::textToGlyphRunList(
199         const SkFont& font, const SkPaint& paint,
200         const void* bytes, size_t byteLength, SkPoint origin,
201         SkTextEncoding encoding) {
202     auto glyphIDs = textToGlyphIDs(font, bytes, byteLength, encoding);
203     SkRect bounds = SkRect::MakeEmpty();
204     this->prepareBuffers(glyphIDs.size(), 0);
205     if (!glyphIDs.empty()) {
206         SkSpan<const SkPoint> positions = draw_text_positions(font, glyphIDs, {0, 0}, fPositions);
207         this->makeGlyphRun(font,
208                            glyphIDs,
209                            positions,
210                            SkSpan<const char>{},
211                            SkSpan<const uint32_t>{},
212                            SkSpan<const SkVector>{});
213         bounds = fGlyphRunListStorage.front().sourceBounds(paint);
214     }
215
216     return this->setGlyphRunList(nullptr, bounds.makeOffset(origin), origin);
217 }
218
219 const SkGlyphRunList& SkGlyphRunBuilder::blobToGlyphRunList(
220         const SkTextBlob& blob, SkPoint origin) {
221     // Pre-size all the buffers, so they don't move during processing.
222     this->initialize(blob);
223
224     SkPoint* positionCursor = fPositions;
225     SkVector* scaledRotationsCursor = fScaledRotations;
226     for (SkTextBlobRunIterator it(&blob); !it.done(); it.next()) {
227         size_t runSize = it.glyphCount();
228         if (runSize == 0 || !SkFontPriv::IsFinite(it.font())) {
229             // If no glyphs or the font is not finite, don't add the run.
230             continue;
231         }
232
233         const SkFont& font = it.font();
234         auto glyphIDs = SkSpan<const SkGlyphID>{it.glyphs(), runSize};
235
236         SkSpan<const SkPoint> positions;
237         SkSpan<const SkVector> scaledRotations;
238         switch (it.positioning()) {
239             case SkTextBlobRunIterator::kDefault_Positioning: {
240                 positions = draw_text_positions(font, glyphIDs, it.offset(), positionCursor);
241                 positionCursor += positions.size();
242                 break;
243             }
244             case SkTextBlobRunIterator::kHorizontal_Positioning: {
245                 positions = SkMakeSpan(positionCursor, runSize);
246                 for (auto x : SkSpan<const SkScalar>{it.pos(), glyphIDs.size()}) {
247                     *positionCursor++ = SkPoint::Make(x, it.offset().y());
248                 }
249                 break;
250             }
251             case SkTextBlobRunIterator::kFull_Positioning: {
252                 positions = SkMakeSpan(it.points(), runSize);
253                 break;
254             }
255             case SkTextBlobRunIterator::kRSXform_Positioning: {
256                 positions = SkMakeSpan(positionCursor, runSize);
257                 scaledRotations = SkMakeSpan(scaledRotationsCursor, runSize);
258                 for (const SkRSXform& xform : SkMakeSpan(it.xforms(), runSize)) {
259                     *positionCursor++ = {xform.fTx, xform.fTy};
260                     *scaledRotationsCursor++ = {xform.fSCos, xform.fSSin};
261                 }
262                 break;
263             }
264         }
265
266         this->makeGlyphRun(
267                 font,
268                 glyphIDs,
269                 positions,
270                 SkSpan<const char>(it.text(), it.textSize()),
271                 SkSpan<const uint32_t>(it.clusters(), runSize),
272                 scaledRotations);
273     }
274
275     return this->setGlyphRunList(&blob, blob.bounds().makeOffset(origin), origin);
276 }
277
278 std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>>
279 SkGlyphRunBuilder::convertRSXForm(SkSpan<const SkRSXform> xforms) {
280     const int count = SkCount(xforms);
281     this->prepareBuffers(count, count);
282     auto positions = SkMakeSpan(fPositions.get(), count);
283     auto scaledRotations = SkMakeSpan(fScaledRotations.get(), count);
284     for (auto [pos, sr, xform] : SkMakeZip(positions, scaledRotations, xforms)) {
285         auto [scos, ssin, tx, ty] = xform;
286         pos = {tx, ty};
287         sr = {scos, ssin};
288     }
289     return {positions, scaledRotations};
290 }
291
292 void SkGlyphRunBuilder::initialize(const SkTextBlob& blob) {
293     int positionCount = 0;
294     int rsxFormCount = 0;
295     for (SkTextBlobRunIterator it(&blob); !it.done(); it.next()) {
296         if (it.positioning() != SkTextBlobRunIterator::kFull_Positioning) {
297             positionCount += it.glyphCount();
298         }
299         if (it.positioning() == SkTextBlobRunIterator::kRSXform_Positioning) {
300             rsxFormCount += it.glyphCount();
301         }
302     }
303
304     prepareBuffers(positionCount, rsxFormCount);
305 }
306
307 void SkGlyphRunBuilder::prepareBuffers(int positionCount, int RSXFormCount) {
308     if (positionCount > fMaxTotalRunSize) {
309         fMaxTotalRunSize = positionCount;
310         fPositions.reset(fMaxTotalRunSize);
311     }
312
313     if (RSXFormCount > fMaxScaledRotations) {
314         fMaxScaledRotations = RSXFormCount;
315         fScaledRotations.reset(RSXFormCount);
316     }
317
318     fGlyphRunListStorage.clear();
319 }
320
321 SkSpan<const SkGlyphID> SkGlyphRunBuilder::textToGlyphIDs(
322         const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding encoding) {
323     if (encoding != SkTextEncoding::kGlyphID) {
324         int count = font.countText(bytes, byteLength, encoding);
325         if (count > 0) {
326             fScratchGlyphIDs.resize(count);
327             font.textToGlyphs(bytes, byteLength, encoding, fScratchGlyphIDs.data(), count);
328             return SkMakeSpan(fScratchGlyphIDs);
329         } else {
330             return SkSpan<const SkGlyphID>();
331         }
332     } else {
333         return SkSpan<const SkGlyphID>((const SkGlyphID*)bytes, byteLength / 2);
334     }
335 }
336
337 void SkGlyphRunBuilder::makeGlyphRun(
338         const SkFont& font,
339         SkSpan<const SkGlyphID> glyphIDs,
340         SkSpan<const SkPoint> positions,
341         SkSpan<const char> text,
342         SkSpan<const uint32_t> clusters,
343         SkSpan<const SkVector> scaledRotations) {
344
345     // Ignore empty runs.
346     if (!glyphIDs.empty()) {
347         fGlyphRunListStorage.emplace_back(
348                 font,
349                 positions,
350                 glyphIDs,
351                 text,
352                 clusters,
353                 scaledRotations);
354     }
355 }
356
357 const SkGlyphRunList& SkGlyphRunBuilder::setGlyphRunList(
358         const SkTextBlob* blob, const SkRect& bounds, SkPoint origin) {
359     fGlyphRunList.emplace(blob, bounds, origin, SkMakeSpan(fGlyphRunListStorage), this);
360     return fGlyphRunList.value();
361 }