blob: 61909656c02add6414b386245f30842146c99eab [file] [log] [blame]
Herb Derby41f4f312018-06-06 17:45:53 +00001/*
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 "SkGlyphRun.h"
9
10#include <algorithm>
Mike Klein79aea6a2018-06-11 10:45:26 -040011#include <new>
Herb Derby41f4f312018-06-06 17:45:53 +000012#include <tuple>
13
Herb Derby59d997a2018-06-07 12:44:09 -040014#include "SkDevice.h"
Herb Derby41f4f312018-06-06 17:45:53 +000015#include "SkDraw.h"
16#include "SkGlyphCache.h"
Hal Canaryfdcfb8b2018-06-13 09:42:32 -040017#include "SkMSAN.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040018#include "SkMakeUnique.h"
Herb Derby41f4f312018-06-06 17:45:53 +000019#include "SkPaint.h"
20#include "SkPaintPriv.h"
21#include "SkStrikeCache.h"
Herb Derbyb9177cf2018-06-18 19:13:37 -040022#include "SkTextBlob.h"
23#include "SkTextBlobRunIterator.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040024#include "SkTo.h"
Herb Derby41f4f312018-06-06 17:45:53 +000025#include "SkUtils.h"
26
Herb Derbyb9177cf2018-06-18 19:13:37 -040027namespace {
Herb Derby4ffa0272018-06-04 15:49:15 -040028static SkTypeface::Encoding convert_encoding(SkPaint::TextEncoding encoding) {
Herb Derby41f4f312018-06-06 17:45:53 +000029 switch (encoding) {
30 case SkPaint::kUTF8_TextEncoding: return SkTypeface::kUTF8_Encoding;
31 case SkPaint::kUTF16_TextEncoding: return SkTypeface::kUTF16_Encoding;
32 case SkPaint::kUTF32_TextEncoding: return SkTypeface::kUTF32_Encoding;
33 default: return SkTypeface::kUTF32_Encoding;
34 }
35}
Herb Derbyb9177cf2018-06-18 19:13:37 -040036} // namespace
37
Herb Derby41f4f312018-06-06 17:45:53 +000038
Herb Derby59d997a2018-06-07 12:44:09 -040039// -- SkGlyphSet ----------------------------------------------------------------------------------
Herb Derbyb9177cf2018-06-18 19:13:37 -040040uint32_t SkGlyphSet::uniqueSize() {
41 // The size is how big the vector is grown since being passed into reuse.
42 return fUniqueGlyphIDs->size() - fStartOfUniqueIDs;
43}
44
Herb Derby4ffa0272018-06-04 15:49:15 -040045uint16_t SkGlyphSet::add(SkGlyphID glyphID) {
46 static constexpr SkGlyphID kUndefGlyph{0};
47
48 if (glyphID >= fUniverseSize) {
49 glyphID = kUndefGlyph;
50 }
51
52 if (glyphID >= fIndices.size()) {
53 fIndices.resize(glyphID + 1);
54 }
55
56 auto index = fIndices[glyphID];
Herb Derbyb9177cf2018-06-18 19:13:37 -040057
58 // Remember we start at the end of what ever was passed in.
59 if (index < this->uniqueSize() && (*fUniqueGlyphIDs)[fStartOfUniqueIDs + index] == glyphID) {
Herb Derby4ffa0272018-06-04 15:49:15 -040060 return index;
61 }
62
Herb Derbyb9177cf2018-06-18 19:13:37 -040063 uint16_t newIndex = SkTo<uint16_t>(this->uniqueSize());
Herb Derby59d997a2018-06-07 12:44:09 -040064 fUniqueGlyphIDs->push_back(glyphID);
Herb Derby4ffa0272018-06-04 15:49:15 -040065 fIndices[glyphID] = newIndex;
66 return newIndex;
67}
68
Herb Derby59d997a2018-06-07 12:44:09 -040069void SkGlyphSet::reuse(uint32_t glyphUniverseSize, std::vector<SkGlyphID>* uniqueGlyphIDs) {
Herb Derby4ffa0272018-06-04 15:49:15 -040070 SkASSERT(glyphUniverseSize <= (1 << 16));
71 fUniverseSize = glyphUniverseSize;
Herb Derby59d997a2018-06-07 12:44:09 -040072 fUniqueGlyphIDs = uniqueGlyphIDs;
Herb Derby149b5412018-06-21 20:03:04 +000073
Herb Derbyb9177cf2018-06-18 19:13:37 -040074 // Capture the vector end to act as the start of a new unique id vector.
75 fStartOfUniqueIDs = uniqueGlyphIDs->size();
76
77 // If we're hanging onto these arrays for a long time, we don't want their size to drift
78 // endlessly upwards. It's unusual to see a typeface with more than 4096 possible glyphs.
Herb Derby4ffa0272018-06-04 15:49:15 -040079 if (glyphUniverseSize < 4096 && fIndices.size() > 4096) {
80 fIndices.resize(4096);
81 fIndices.shrink_to_fit();
82 }
83
84 // No need to clear fIndices here... SkGlyphSet's set insertion algorithm is designed to work
85 // correctly even when the fIndexes buffer is uninitialized!
Herb Derby59d997a2018-06-07 12:44:09 -040086}
87
Herb Derby9d85d632018-06-18 16:25:52 -040088// -- SkGlyphRun -----------------------------------------------------------------------------------
Herb Derbyb9177cf2018-06-18 19:13:37 -040089SkGlyphRun::SkGlyphRun(SkSpan<uint16_t> denseIndex,
90 SkSpan<SkPoint> positions,
91 SkSpan<SkGlyphID> scratchGlyphs,
92 SkSpan<SkGlyphID> uniqueGlyphIDs,
93 SkSpan<const char> text,
94 SkSpan<uint32_t> clusters)
95 : fDenseIndex{denseIndex}, fPositions{positions}
96 , fTemporaryShuntGlyphIDs{scratchGlyphs}
97 , fUniqueGlyphIDs{uniqueGlyphIDs}
98 , fText{text}
99 , fClusters{clusters} {
100 SkASSERT(denseIndex.size() == positions.size());
101 SkASSERT(denseIndex.size() == scratchGlyphs.size());
102}
103
Herb Derby9d85d632018-06-18 16:25:52 -0400104
105void SkGlyphRun::temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device) {
106
107 auto pos = (const SkScalar*) fPositions.data();
108
109 device->drawPosText(
110 fTemporaryShuntGlyphIDs.data(), fDenseIndex.size() * sizeof(SkGlyphID),
111 pos, 2, SkPoint::Make(0, 0), paint);
112}
113
114void SkGlyphRun::temporaryShuntToCallback(TemporaryShuntCallback callback) {
115 auto bytes = (const char *)fTemporaryShuntGlyphIDs.data();
116 auto pos = (const SkScalar*)fPositions.data();
117 callback(this->runSize(), bytes, pos);
118}
119
Herb Derbyb9177cf2018-06-18 19:13:37 -0400120// -- SkGlyphRunList -------------------------------------------------------------------------------
121SkGlyphRunList::SkGlyphRunList(SkSpan<SkGlyphRun> glyphRuns, uint64_t uniqueID)
122 : fUniqueID{uniqueID}
123 , fGlyphRuns{glyphRuns} { }
Herb Derby9d85d632018-06-18 16:25:52 -0400124
Herb Derby59d997a2018-06-07 12:44:09 -0400125// -- SkGlyphRunBuilder ----------------------------------------------------------------------------
126void SkGlyphRunBuilder::prepareDrawText(
127 const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin) {
Herb Derbyb9177cf2018-06-18 19:13:37 -0400128 this->initialize();
129 SkSpan<const char> originalText((const char*)bytes, byteLength);
130 if (paint.getTextEncoding() != SkPaint::kUTF8_TextEncoding) {
131 originalText = SkSpan<const char>();
132 }
133 this->drawText(paint, bytes, byteLength, origin, originalText, SkSpan<uint32_t>());
134}
Herb Derby59d997a2018-06-07 12:44:09 -0400135
Herb Derbyb9177cf2018-06-18 19:13:37 -0400136void SkGlyphRunBuilder::prepareDrawPosTextH(const SkPaint& paint, const void* bytes,
137 size_t byteLength, const SkScalar* xpos,
138 SkScalar constY) {
139 this->initialize();
140 this->drawPosTextH(
141 paint, bytes, byteLength, xpos, constY, SkSpan<const char>(), SkSpan<uint32_t>());
142}
143
144void SkGlyphRunBuilder::prepareDrawPosText(const SkPaint& paint, const void* bytes,
145 size_t byteLength, const SkPoint* pos) {
146 this->initialize();
147 this->drawPosText(paint, bytes, byteLength, pos, SkSpan<const char>(), SkSpan<uint32_t>());
148}
149
150void SkGlyphRunBuilder::prepareTextBlob(
151 const SkPaint& paint, const SkTextBlob& blob, SkPoint origin) {
152 this->initialize();
153 fUniqueID = blob.uniqueID();
154
155 SkPaint runPaint = paint;
156
157 for (SkTextBlobRunIterator it(&blob); !it.done(); it.next()) {
158 // applyFontToPaint() always overwrites the exact same attributes,
159 // so it is safe to not re-seed the paint for this reason.
160 it.applyFontToPaint(&runPaint);
161
162 // These better be glyphs
163 SkASSERT(runPaint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
164
165 auto text = SkSpan<const char>(it.text(), it.textSize());
166 auto clusters = SkSpan<uint32_t>(it.clusters(), it.glyphCount());
167 size_t glyphLen = it.glyphCount() * sizeof(SkGlyphID);
168 const SkPoint& offset = it.offset();
169
170 switch (it.positioning()) {
171 case SkTextBlob::kDefault_Positioning: {
172 auto dtOrigin = origin + offset;
173 this->drawText(runPaint, it.glyphs(), glyphLen, dtOrigin, text, clusters);
174 }
175 break;
176 case SkTextBlob::kHorizontal_Positioning: {
177 auto constY = origin.y() + offset.y();
178 this->drawPosTextH(
179 runPaint, it.glyphs(), glyphLen, it.pos(), constY, text, clusters);
180 }
181 break;
182 case SkTextBlob::kFull_Positioning:
183 this->drawPosText(
184 runPaint, it.glyphs(), glyphLen, (const SkPoint*)it.pos(), text, clusters);
185 break;
186 default:
187 SK_ABORT("unhandled positioning mode");
188 }
189 }
190}
191
192SkGlyphRun* SkGlyphRunBuilder::useGlyphRun() {
193 auto glyphRunList = this->useGlyphRunList();
194 SkASSERT(glyphRunList->size() == 1);
195 return &(*glyphRunList)[0];
196}
197
198SkGlyphRunList* SkGlyphRunBuilder::useGlyphRunList() {
199 new ((void*)&fScratchGlyphRunList) SkGlyphRunList{SkSpan<SkGlyphRun>(fGlyphRuns), fUniqueID};
200 return &fScratchGlyphRunList;
201}
202
203size_t SkGlyphRunBuilder::runSize() const { return fDenseIndex.size() - fLastDenseIndex; }
204
205size_t SkGlyphRunBuilder::uniqueSize() const { return fUniqueGlyphs.size() - fLastUniqueIndex; }
206
207void SkGlyphRunBuilder::initialize() {
208 fUniqueID = 0;
209 fDenseIndex.clear();
210 fPositions.clear();
211 fUniqueGlyphs.clear();
212 fGlyphRuns.clear();
213 fLastDenseIndex = 0;
214 fLastUniqueIndex = 0;
215}
216
217SkGlyphID* SkGlyphRunBuilder::addDenseAndUnique(
218 const SkPaint& paint, const void* bytes, size_t byteLength) {
219
220 size_t runSize = 0;
221 SkGlyphID* glyphIDs = nullptr;
222 auto encoding = paint.getTextEncoding();
223 auto typeface = SkPaintPriv::GetTypefaceOrDefault(paint);
224 if (encoding != SkPaint::kGlyphID_TextEncoding) {
225 auto tfEncoding = convert_encoding(encoding);
226 int utfSize = SkUTFN_CountUnichars(tfEncoding, bytes, byteLength);
227 if (utfSize > 0) {
228 runSize = SkTo<size_t>(utfSize);
229 fScratchGlyphIDs.resize(runSize);
230 typeface->charsToGlyphs(bytes, tfEncoding, fScratchGlyphIDs.data(), runSize);
231 glyphIDs = fScratchGlyphIDs.data();
232 }
233 } else {
234 runSize = byteLength / 2;
235 glyphIDs = (SkGlyphID*)bytes;
236 }
237
238 SkASSERT(glyphIDs != nullptr);
239
240 if (runSize > 0) {
241 fGlyphSet.reuse(typeface->countGlyphs(), &fUniqueGlyphs);
242 for (size_t i = 0; i < runSize; i++) {
243 fDenseIndex.push_back(fGlyphSet.add(glyphIDs[i]));
244 }
245 }
246
247 return glyphIDs;
248}
249
250void SkGlyphRunBuilder::addGlyphRunToList(
251 SkGlyphID* temporaryShuntGlyphIDs, SkSpan<const char> text, SkSpan<uint32_t> clusters) {
252
253 // Ignore empty runs.
254 if (fDenseIndex.size() != fLastDenseIndex) {
255 auto runSize = this->runSize();
256 auto uniqueSize = this->uniqueSize();
257
258 fGlyphRuns.emplace_back(
259 SkSpan<uint16_t>(&fDenseIndex[fLastDenseIndex], runSize),
260 SkSpan<SkPoint>(&fPositions[fLastDenseIndex], runSize),
261 SkSpan<SkGlyphID>(temporaryShuntGlyphIDs, runSize),
262 SkSpan<SkGlyphID>(&fUniqueGlyphs[fLastDenseIndex], uniqueSize),
263 text,
264 clusters);
265
266 fLastDenseIndex = fDenseIndex.size();
267 fLastUniqueIndex = fUniqueGlyphs.size();
268 }
269}
270
271void SkGlyphRunBuilder::drawText(
272 const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin,
273 SkSpan<const char> text, SkSpan<uint32_t> clusters) {
274
275 SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength);
Herb Derby59d997a2018-06-07 12:44:09 -0400276
277 fScratchAdvances.resize(this->uniqueSize());
278 {
279 auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(paint);
280 cache->getAdvances(SkSpan<SkGlyphID>{fUniqueGlyphs}, fScratchAdvances.data());
281 }
282
283 SkPoint endOfLastGlyph = origin;
284
285 for (size_t i = 0; i < this->runSize(); i++) {
286 fPositions.push_back(endOfLastGlyph);
287 endOfLastGlyph += fScratchAdvances[fDenseIndex[i]];
288 }
289
290 if (paint.getTextAlign() != SkPaint::kLeft_Align) {
291 SkVector len = endOfLastGlyph - origin;
292 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
293 len.scale(SK_ScalarHalf);
294 }
Herb Derbyb9177cf2018-06-18 19:13:37 -0400295 for (size_t i = fLastDenseIndex; i < this->runSize(); i++) {
Herb Derby59d997a2018-06-07 12:44:09 -0400296 fPositions[i] -= len;
297 }
298 }
299
Herb Derbyb9177cf2018-06-18 19:13:37 -0400300 this->addGlyphRunToList(temporaryShuntGlyphIDs, text, clusters);
Herb Derby59d997a2018-06-07 12:44:09 -0400301}
302
Herb Derbyb9177cf2018-06-18 19:13:37 -0400303void SkGlyphRunBuilder::drawPosTextH(const SkPaint& paint, const void* bytes,
304 size_t byteLength, const SkScalar* xpos,
305 SkScalar constY,
306 SkSpan<const char> text, SkSpan<uint32_t> clusters) {
Herb Derby59d997a2018-06-07 12:44:09 -0400307
Herb Derbyb9177cf2018-06-18 19:13:37 -0400308 SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength);
Herb Derby59d997a2018-06-07 12:44:09 -0400309
310 for (size_t i = 0; i < runSize(); i++) {
311 fPositions.push_back(SkPoint::Make(xpos[i], constY));
312 }
Herb Derbyb9177cf2018-06-18 19:13:37 -0400313
314 this->addGlyphRunToList(temporaryShuntGlyphIDs, text, clusters);
Herb Derby59d997a2018-06-07 12:44:09 -0400315}
316
Herb Derbyb9177cf2018-06-18 19:13:37 -0400317void SkGlyphRunBuilder::drawPosText(const SkPaint& paint, const void* bytes,
318 size_t byteLength, const SkPoint* pos,
319 SkSpan<const char> text, SkSpan<uint32_t> clusters) {
320 SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength);
Herb Derby59d997a2018-06-07 12:44:09 -0400321
322 for (size_t i = 0; i < runSize(); i++) {
323 fPositions.push_back(pos[i]);
324 }
Herb Derby59d997a2018-06-07 12:44:09 -0400325
Herb Derbyb9177cf2018-06-18 19:13:37 -0400326 this->addGlyphRunToList(temporaryShuntGlyphIDs, text, clusters);
Herb Derby59d997a2018-06-07 12:44:09 -0400327}
328
329