Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/core/SkTextBlob.cpp

Issue 2084533004: SkTextBlob: Begin implementing Extended TextBlob API (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/core/SkTextBlob.h ('k') | src/core/SkTextBlobRunIterator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkTextBlobRunIterator.h" 8 #include "SkTextBlobRunIterator.h"
9 9
10 #include "SkReadBuffer.h" 10 #include "SkReadBuffer.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 98
99 // 99 //
100 // Textblob data is laid out into externally-managed storage as follows: 100 // Textblob data is laid out into externally-managed storage as follows:
101 // 101 //
102 // -------------------------------------------------------------------------- --- 102 // -------------------------------------------------------------------------- ---
103 // | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ... 103 // | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ...
104 // -------------------------------------------------------------------------- --- 104 // -------------------------------------------------------------------------- ---
105 // 105 //
106 // Each run record describes a text blob run, and can be used to determine the (implicit) 106 // Each run record describes a text blob run, and can be used to determine the (implicit)
107 // location of the following record. 107 // location of the following record.
108 //
109 // Extended Textblob runs have more data after the Pos[] array:
110 //
111 // -------------------------------------------------------------------------
112 // ... | RunRecord | Glyphs[] | Pos[] | TextSize | Clusters[] | Text[] | ...
113 // -------------------------------------------------------------------------
114 //
115 // To determine the length of the extended run data, the TextSize must be read.
116 //
117 // Extended Textblob runs may be mixed with non-extended runs.
108 118
109 SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;) 119 SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;)
110 120
121 namespace {
122 struct RunRecordStorageEquivalent {
123 RunFont fFont;
124 SkPoint fOffset;
125 uint32_t fCount;
126 uint32_t fFlags;
127 SkDEBUGCODE(unsigned fMagic;)
128 };
129 }
130
111 class SkTextBlob::RunRecord { 131 class SkTextBlob::RunRecord {
112 public: 132 public:
113 RunRecord(uint32_t count, const SkPoint& offset, const SkPaint& font, GlyphP ositioning pos) 133 RunRecord(uint32_t count, uint32_t textSize, const SkPoint& offset, const S kPaint& font, GlyphPositioning pos)
114 : fFont(font) 134 : fFont(font)
115 , fCount(count) 135 , fCount(count)
116 , fOffset(offset) 136 , fOffset(offset)
117 , fPositioning(pos) { 137 , fPositioning(pos)
138 , fExtended(textSize > 0) {
118 SkDEBUGCODE(fMagic = kRunRecordMagic); 139 SkDEBUGCODE(fMagic = kRunRecordMagic);
140 if (textSize > 0) {
141 *this->textSizePtr() = textSize;
142 }
119 } 143 }
120 144
121 uint32_t glyphCount() const { 145 uint32_t glyphCount() const {
122 return fCount; 146 return fCount;
123 } 147 }
124 148
125 const SkPoint& offset() const { 149 const SkPoint& offset() const {
126 return fOffset; 150 return fOffset;
127 } 151 }
128 152
129 const RunFont& font() const { 153 const RunFont& font() const {
130 return fFont; 154 return fFont;
131 } 155 }
132 156
133 GlyphPositioning positioning() const { 157 GlyphPositioning positioning() const {
134 return fPositioning; 158 return fPositioning;
135 } 159 }
136 160
137 uint16_t* glyphBuffer() const { 161 uint16_t* glyphBuffer() const {
138 // Glyph are stored immediately following the record. 162 static_assert(SkIsAlignPtr(sizeof(RunRecord)), "");
163 // Glyphs are stored immediately following the record.
139 return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1); 164 return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1);
140 } 165 }
141 166
142 SkScalar* posBuffer() const { 167 SkScalar* posBuffer() const {
143 // Position scalars follow the (aligned) glyph buffer. 168 // Position scalars follow the (aligned) glyph buffer.
144 return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyp hBuffer()) + 169 return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyp hBuffer()) +
145 SkAlign4(fCount * sizeof(uint16_t))); 170 SkAlign4(fCount * sizeof(uint16_t)));
146 } 171 }
147 172
148 static size_t StorageSize(int glyphCount, SkTextBlob::GlyphPositioning posit ioning) { 173 uint32_t textSize() const { return fExtended ? *this->textSizePtr() : 0; }
174
175 uint32_t* clusterBuffer() const {
176 // clusters follow the textSize.
177 return fExtended ? 1 + this->textSizePtr() : nullptr;
178 }
179
180 char* textBuffer() const {
181 if (!fExtended) { return nullptr; }
182 return reinterpret_cast<char*>(this->clusterBuffer() + fCount);
183 }
184
185 static size_t StorageSize(int glyphCount, int textSize,
186 SkTextBlob::GlyphPositioning positioning) {
187 static_assert(SkIsAlign4(sizeof(SkScalar)), "SkScalar size alignment");
149 // RunRecord object + (aligned) glyph buffer + position buffer 188 // RunRecord object + (aligned) glyph buffer + position buffer
150 return SkAlignPtr(sizeof(SkTextBlob::RunRecord) 189 size_t size = sizeof(SkTextBlob::RunRecord)
151 + SkAlign4(glyphCount* sizeof(uint16_t)) 190 + SkAlign4(glyphCount* sizeof(uint16_t))
152 + glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(positi oning)); 191 + PosCount(glyphCount, positioning) * sizeof(SkScalar);
192 if (textSize > 0) { // Extended run.
193 size += sizeof(uint32_t)
194 + sizeof(uint32_t) * glyphCount
195 + textSize;
196 }
197 return SkAlignPtr(size);
153 } 198 }
154 199
155 static const RunRecord* First(const SkTextBlob* blob) { 200 static const RunRecord* First(const SkTextBlob* blob) {
156 // The first record (if present) is stored following the blob object. 201 // The first record (if present) is stored following the blob object.
157 return reinterpret_cast<const RunRecord*>(blob + 1); 202 return reinterpret_cast<const RunRecord*>(blob + 1);
158 } 203 }
159 204
160 static const RunRecord* Next(const RunRecord* run) { 205 static const RunRecord* Next(const RunRecord* run) {
161 return reinterpret_cast<const RunRecord*>(reinterpret_cast<const uint8_t *>(run) 206 return reinterpret_cast<const RunRecord*>(
162 + StorageSize(run->glyphCount(), run->positioning())); 207 reinterpret_cast<const uint8_t*>(run)
208 + StorageSize(run->glyphCount(), run->textSize(), run->positioni ng()));
163 } 209 }
164 210
165 void validate(const uint8_t* storageTop) const { 211 void validate(const uint8_t* storageTop) const {
166 SkASSERT(kRunRecordMagic == fMagic); 212 SkASSERT(kRunRecordMagic == fMagic);
167 SkASSERT((uint8_t*)Next(this) <= storageTop); 213 SkASSERT((uint8_t*)Next(this) <= storageTop);
214
168 SkASSERT(glyphBuffer() + fCount <= (uint16_t*)posBuffer()); 215 SkASSERT(glyphBuffer() + fCount <= (uint16_t*)posBuffer());
169 SkASSERT(posBuffer() + fCount * ScalarsPerGlyph(fPositioning) <= (SkScal ar*)Next(this)); 216 SkASSERT(posBuffer() + fCount * ScalarsPerGlyph(fPositioning) <= (SkScal ar*)Next(this));
217 if (fExtended) {
218 SkASSERT(textSize() > 0);
219 SkASSERT(textSizePtr() < (uint32_t*)Next(this));
220 SkASSERT(clusterBuffer() < (uint32_t*)Next(this));
221 SkASSERT(textBuffer() + textSize() <= (char*)Next(this));
222 }
223 static_assert(sizeof(SkTextBlob::RunRecord) == sizeof(RunRecordStorageEq uivalent),
224 "runrecord_should_stay_packed");
170 } 225 }
171 226
172 private: 227 private:
173 friend class SkTextBlobBuilder; 228 friend class SkTextBlobBuilder;
174 229
230 static size_t PosCount(int glyphCount,
231 SkTextBlob::GlyphPositioning positioning) {
232 return glyphCount * ScalarsPerGlyph(positioning);
233 }
234
235 uint32_t* textSizePtr() const {
236 // textSize follows the position buffer.
237 SkASSERT(fExtended);
238 return (uint32_t*)(&this->posBuffer()[PosCount(fCount, fPositioning)]);
239 }
240
175 void grow(uint32_t count) { 241 void grow(uint32_t count) {
176 SkScalar* initialPosBuffer = posBuffer(); 242 SkScalar* initialPosBuffer = posBuffer();
177 uint32_t initialCount = fCount; 243 uint32_t initialCount = fCount;
178 fCount += count; 244 fCount += count;
179 245
180 // Move the initial pos scalars to their new location. 246 // Move the initial pos scalars to their new location.
181 size_t copySize = initialCount * sizeof(SkScalar) * ScalarsPerGlyph(fPos itioning); 247 size_t copySize = initialCount * sizeof(SkScalar) * ScalarsPerGlyph(fPos itioning);
182 SkASSERT((uint8_t*)posBuffer() + copySize <= (uint8_t*)Next(this)); 248 SkASSERT((uint8_t*)posBuffer() + copySize <= (uint8_t*)Next(this));
183 249
184 // memmove, as the buffers may overlap 250 // memmove, as the buffers may overlap
185 memmove(posBuffer(), initialPosBuffer, copySize); 251 memmove(posBuffer(), initialPosBuffer, copySize);
186 } 252 }
187 253
188 RunFont fFont; 254 RunFont fFont;
189 uint32_t fCount; 255 uint32_t fCount;
190 SkPoint fOffset; 256 SkPoint fOffset;
191 GlyphPositioning fPositioning; 257 GlyphPositioning fPositioning;
258 bool fExtended;
192 259
193 SkDEBUGCODE(unsigned fMagic;) 260 SkDEBUGCODE(unsigned fMagic;)
194 }; 261 };
195 262
196 static int32_t gNextID = 1; 263 static int32_t gNextID = 1;
197 static int32_t next_id() { 264 static int32_t next_id() {
198 int32_t id; 265 int32_t id;
199 do { 266 do {
200 id = sk_atomic_inc(&gNextID); 267 id = sk_atomic_inc(&gNextID);
201 } while (id == SK_InvalidGenID); 268 } while (id == SK_InvalidGenID);
202 return id; 269 return id;
203 } 270 }
204 271
205 SkTextBlob::SkTextBlob(int runCount, const SkRect& bounds) 272 SkTextBlob::SkTextBlob(int runCount, const SkRect& bounds)
206 : fRunCount(runCount) 273 : fRunCount(runCount)
207 , fBounds(bounds) 274 , fBounds(bounds)
208 , fUniqueID(next_id()) { 275 , fUniqueID(next_id()) {
209 } 276 }
210 277
211 SkTextBlob::~SkTextBlob() { 278 SkTextBlob::~SkTextBlob() {
212 const RunRecord* run = RunRecord::First(this); 279 const RunRecord* run = RunRecord::First(this);
213 for (int i = 0; i < fRunCount; ++i) { 280 for (int i = 0; i < fRunCount; ++i) {
214 const RunRecord* nextRun = RunRecord::Next(run); 281 const RunRecord* nextRun = RunRecord::Next(run);
215 SkDEBUGCODE(run->validate((uint8_t*)this + fStorageSize);) 282 SkDEBUGCODE(run->validate((uint8_t*)this + fStorageSize);)
216 run->~RunRecord(); 283 run->~RunRecord();
217 run = nextRun; 284 run = nextRun;
218 } 285 }
219 } 286 }
220 287
288 namespace {
289 union PositioningAndExtended {
290 int32_t intValue;
291 struct {
292 SkTextBlob::GlyphPositioning positioning;
293 bool extended;
294 uint16_t padding;
295 };
296 };
297 } // namespace
298
221 void SkTextBlob::flatten(SkWriteBuffer& buffer) const { 299 void SkTextBlob::flatten(SkWriteBuffer& buffer) const {
222 int runCount = fRunCount; 300 int runCount = fRunCount;
223 301
224 buffer.write32(runCount); 302 buffer.write32(runCount);
225 buffer.writeRect(fBounds); 303 buffer.writeRect(fBounds);
226 304
227 SkPaint runPaint; 305 SkPaint runPaint;
228 SkTextBlobRunIterator it(this); 306 SkTextBlobRunIterator it(this);
229 while (!it.done()) { 307 while (!it.done()) {
230 SkASSERT(it.glyphCount() > 0); 308 SkASSERT(it.glyphCount() > 0);
231 309
232 buffer.write32(it.glyphCount()); 310 buffer.write32(it.glyphCount());
233 buffer.write32(it.positioning()); 311 PositioningAndExtended pe;
312 pe.intValue = 0;
313 pe.positioning = it.positioning();
314 SkASSERT((int32_t)it.positioning() == pe.intValue); // backwards compat .
315
316 uint32_t textSize = it.textSize();
317 pe.extended = textSize > 0;
318 buffer.write32(pe.intValue);
319 if (pe.extended) {
320 buffer.write32(textSize);
321 }
234 buffer.writePoint(it.offset()); 322 buffer.writePoint(it.offset());
235 // This should go away when switching to SkFont 323 // This should go away when switching to SkFont
236 it.applyFontToPaint(&runPaint); 324 it.applyFontToPaint(&runPaint);
237 buffer.writePaint(runPaint); 325 buffer.writePaint(runPaint);
238 326
239 buffer.writeByteArray(it.glyphs(), it.glyphCount() * sizeof(uint16_t)); 327 buffer.writeByteArray(it.glyphs(), it.glyphCount() * sizeof(uint16_t));
240 buffer.writeByteArray(it.pos(), 328 buffer.writeByteArray(it.pos(),
241 it.glyphCount() * sizeof(SkScalar) * ScalarsPerGlyph(it.positioning( ))); 329 it.glyphCount() * sizeof(SkScalar) * ScalarsPerGlyph(it.positioning( )));
330 if (pe.extended) {
331 buffer.writeByteArray(it.clusters(), sizeof(uint32_t) * it.glyphCoun t());
332 buffer.writeByteArray(it.text(), it.textSize());
333 }
242 334
243 it.next(); 335 it.next();
244 SkDEBUGCODE(runCount--); 336 SkDEBUGCODE(runCount--);
245 } 337 }
246 SkASSERT(0 == runCount); 338 SkASSERT(0 == runCount);
247 } 339 }
248 340
249 sk_sp<SkTextBlob> SkTextBlob::MakeFromBuffer(SkReadBuffer& reader) { 341 sk_sp<SkTextBlob> SkTextBlob::MakeFromBuffer(SkReadBuffer& reader) {
250 int runCount = reader.read32(); 342 int runCount = reader.read32();
251 if (runCount < 0) { 343 if (runCount < 0) {
252 return nullptr; 344 return nullptr;
253 } 345 }
254 346
255 SkRect bounds; 347 SkRect bounds;
256 reader.readRect(&bounds); 348 reader.readRect(&bounds);
257 349
258 SkTextBlobBuilder blobBuilder; 350 SkTextBlobBuilder blobBuilder;
259 for (int i = 0; i < runCount; ++i) { 351 for (int i = 0; i < runCount; ++i) {
260 int glyphCount = reader.read32(); 352 int glyphCount = reader.read32();
261 GlyphPositioning pos = static_cast<GlyphPositioning>(reader.read32()); 353
354 PositioningAndExtended pe;
355 pe.intValue = reader.read32();
356 GlyphPositioning pos = pe.positioning;
262 if (glyphCount <= 0 || pos > kFull_Positioning) { 357 if (glyphCount <= 0 || pos > kFull_Positioning) {
263 return nullptr; 358 return nullptr;
264 } 359 }
360 uint32_t textSize = pe.extended ? (uint32_t)reader.read32() : 0;
265 361
266 SkPoint offset; 362 SkPoint offset;
267 reader.readPoint(&offset); 363 reader.readPoint(&offset);
268 SkPaint font; 364 SkPaint font;
269 reader.readPaint(&font); 365 reader.readPaint(&font);
270 366
271 const SkTextBlobBuilder::RunBuffer* buf = nullptr; 367 const SkTextBlobBuilder::RunBuffer* buf = nullptr;
272 switch (pos) { 368 switch (pos) {
273 case kDefault_Positioning: 369 case kDefault_Positioning:
274 buf = &blobBuilder.allocRun(font, glyphCount, offset.x(), offset.y() , &bounds); 370 buf = &blobBuilder.allocRunText(font, glyphCount, offset.x(), offset .y(),
371 textSize, SkString(), &bounds);
275 break; 372 break;
276 case kHorizontal_Positioning: 373 case kHorizontal_Positioning:
277 buf = &blobBuilder.allocRunPosH(font, glyphCount, offset.y(), &bound s); 374 buf = &blobBuilder.allocRunTextPosH(font, glyphCount, offset.y(),
375 textSize, SkString(), &bounds);
278 break; 376 break;
279 case kFull_Positioning: 377 case kFull_Positioning:
280 buf = &blobBuilder.allocRunPos(font, glyphCount, &bounds); 378 buf = &blobBuilder.allocRunTextPos(font, glyphCount, textSize, SkStr ing(), &bounds);
281 break; 379 break;
282 default: 380 default:
283 return nullptr; 381 return nullptr;
284 } 382 }
285 383
286 if (!reader.readByteArray(buf->glyphs, glyphCount * sizeof(uint16_t)) || 384 if (!reader.readByteArray(buf->glyphs, glyphCount * sizeof(uint16_t)) ||
287 !reader.readByteArray(buf->pos, 385 !reader.readByteArray(buf->pos,
288 glyphCount * sizeof(SkScalar) * ScalarsPerGlyp h(pos))) { 386 glyphCount * sizeof(SkScalar) * ScalarsPerGlyp h(pos))) {
289 return nullptr; 387 return nullptr;
290 } 388 }
389
390 if (pe.extended) {
391 if (!reader.readByteArray(buf->clusters, glyphCount * sizeof(uint32_ t)) ||
392 !reader.readByteArray(buf->utf8text, textSize)) {
393 return nullptr;
394 }
395 }
291 } 396 }
292 397
293 return blobBuilder.make(); 398 return blobBuilder.make();
294 } 399 }
295 400
296 unsigned SkTextBlob::ScalarsPerGlyph(GlyphPositioning pos) { 401 unsigned SkTextBlob::ScalarsPerGlyph(GlyphPositioning pos) {
297 // GlyphPositioning values are directly mapped to scalars-per-glyph. 402 // GlyphPositioning values are directly mapped to scalars-per-glyph.
298 SkASSERT(pos <= 2); 403 SkASSERT(pos <= 2);
299 return pos; 404 return pos;
300 } 405 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 SkASSERT(!this->done()); 448 SkASSERT(!this->done());
344 return fCurrentRun->positioning(); 449 return fCurrentRun->positioning();
345 } 450 }
346 451
347 void SkTextBlobRunIterator::applyFontToPaint(SkPaint* paint) const { 452 void SkTextBlobRunIterator::applyFontToPaint(SkPaint* paint) const {
348 SkASSERT(!this->done()); 453 SkASSERT(!this->done());
349 454
350 fCurrentRun->font().applyToPaint(paint); 455 fCurrentRun->font().applyToPaint(paint);
351 } 456 }
352 457
458 uint32_t* SkTextBlobRunIterator::clusters() const {
459 SkASSERT(!this->done());
460 return fCurrentRun->clusterBuffer();
461 }
462 uint32_t SkTextBlobRunIterator::textSize() const {
463 SkASSERT(!this->done());
464 return fCurrentRun->textSize();
465 }
466 char* SkTextBlobRunIterator::text() const {
467 SkASSERT(!this->done());
468 return fCurrentRun->textBuffer();
469 }
470
471
353 bool SkTextBlobRunIterator::isLCD() const { 472 bool SkTextBlobRunIterator::isLCD() const {
354 return SkToBool(fCurrentRun->font().flags() & SkPaint::kLCDRenderText_Flag); 473 return SkToBool(fCurrentRun->font().flags() & SkPaint::kLCDRenderText_Flag);
355 } 474 }
356 475
357 SkTextBlobBuilder::SkTextBlobBuilder() 476 SkTextBlobBuilder::SkTextBlobBuilder()
358 : fStorageSize(0) 477 : fStorageSize(0)
359 , fStorageUsed(0) 478 , fStorageUsed(0)
360 , fRunCount(0) 479 , fRunCount(0)
361 , fDeferredBounds(false) 480 , fDeferredBounds(false)
362 , fLastRun(0) { 481 , fLastRun(0) {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 if (0 == fLastRun) { 625 if (0 == fLastRun) {
507 SkASSERT(0 == fRunCount); 626 SkASSERT(0 == fRunCount);
508 return false; 627 return false;
509 } 628 }
510 629
511 SkASSERT(fLastRun >= sizeof(SkTextBlob)); 630 SkASSERT(fLastRun >= sizeof(SkTextBlob));
512 SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStora ge.get() + 631 SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStora ge.get() +
513 fLastR un); 632 fLastR un);
514 SkASSERT(run->glyphCount() > 0); 633 SkASSERT(run->glyphCount() > 0);
515 634
635 if (run->textSize() != 0) {
636 return false;
637 }
638
516 if (run->positioning() != positioning 639 if (run->positioning() != positioning
517 || run->font() != font 640 || run->font() != font
518 || (run->glyphCount() + count < run->glyphCount())) { 641 || (run->glyphCount() + count < run->glyphCount())) {
519 return false; 642 return false;
520 } 643 }
521 644
522 // we can merge same-font/same-positioning runs in the following cases: 645 // we can merge same-font/same-positioning runs in the following cases:
523 // * fully positioned run following another fully positioned run 646 // * fully positioned run following another fully positioned run
524 // * horizontally postioned run following another horizontally positioned run with the same 647 // * horizontally postioned run following another horizontally positioned run with the same
525 // y-offset 648 // y-offset
526 if (SkTextBlob::kFull_Positioning != positioning 649 if (SkTextBlob::kFull_Positioning != positioning
527 && (SkTextBlob::kHorizontal_Positioning != positioning 650 && (SkTextBlob::kHorizontal_Positioning != positioning
528 || run->offset().y() != offset.y())) { 651 || run->offset().y() != offset.y())) {
529 return false; 652 return false;
530 } 653 }
531 654
532 size_t sizeDelta = SkTextBlob::RunRecord::StorageSize(run->glyphCount() + co unt, positioning) - 655 size_t sizeDelta = SkTextBlob::RunRecord::StorageSize(run->glyphCount() + co unt, 0, positioning) -
533 SkTextBlob::RunRecord::StorageSize(run->glyphCount(), pos itioning); 656 SkTextBlob::RunRecord::StorageSize(run->glyphCount(), 0, positioning);
534 this->reserve(sizeDelta); 657 this->reserve(sizeDelta);
535 658
536 // reserve may have realloced 659 // reserve may have realloced
537 run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + fLastRun); 660 run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + fLastRun);
538 uint32_t preMergeCount = run->glyphCount(); 661 uint32_t preMergeCount = run->glyphCount();
539 run->grow(count); 662 run->grow(count);
540 663
541 // Callers expect the buffers to point at the newly added slice, ant not at the beginning. 664 // Callers expect the buffers to point at the newly added slice, ant not at the beginning.
542 fCurrentRunBuffer.glyphs = run->glyphBuffer() + preMergeCount; 665 fCurrentRunBuffer.glyphs = run->glyphBuffer() + preMergeCount;
543 fCurrentRunBuffer.pos = run->posBuffer() 666 fCurrentRunBuffer.pos = run->posBuffer()
544 + preMergeCount * SkTextBlob::ScalarsPerGlyph(position ing); 667 + preMergeCount * SkTextBlob::ScalarsPerGlyph(position ing);
545 668
546 fStorageUsed += sizeDelta; 669 fStorageUsed += sizeDelta;
547 670
548 SkASSERT(fStorageUsed <= fStorageSize); 671 SkASSERT(fStorageUsed <= fStorageSize);
549 run->validate(fStorage.get() + fStorageUsed); 672 run->validate(fStorage.get() + fStorageUsed);
550 673
551 return true; 674 return true;
552 } 675 }
553 676
554 void SkTextBlobBuilder::allocInternal(const SkPaint &font, 677 void SkTextBlobBuilder::allocInternal(const SkPaint &font,
555 SkTextBlob::GlyphPositioning positioning, 678 SkTextBlob::GlyphPositioning positioning,
556 int count, SkPoint offset, const SkRect* b ounds) { 679 int count, int textSize, SkPoint offset, c onst SkRect* bounds) {
557 SkASSERT(count > 0); 680 SkASSERT(count > 0);
681 SkASSERT(textSize >= 0);
558 SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding()); 682 SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding());
559 683 if (textSize != 0 || !this->mergeRun(font, positioning, count, offset)) {
560 if (!this->mergeRun(font, positioning, count, offset)) {
561 this->updateDeferredBounds(); 684 this->updateDeferredBounds();
562 685
563 size_t runSize = SkTextBlob::RunRecord::StorageSize(count, positioning); 686 size_t runSize = SkTextBlob::RunRecord::StorageSize(count, textSize, pos itioning);
564 this->reserve(runSize); 687 this->reserve(runSize);
565 688
566 SkASSERT(fStorageUsed >= sizeof(SkTextBlob)); 689 SkASSERT(fStorageUsed >= sizeof(SkTextBlob));
567 SkASSERT(fStorageUsed + runSize <= fStorageSize); 690 SkASSERT(fStorageUsed + runSize <= fStorageSize);
568 691
569 SkTextBlob::RunRecord* run = new (fStorage.get() + fStorageUsed) 692 SkTextBlob::RunRecord* run = new (fStorage.get() + fStorageUsed)
570 SkTextBlob::RunRecord(count, offset, fo nt, positioning); 693 SkTextBlob::RunRecord(count, textSize, offset, font, positioning);
571
572 fCurrentRunBuffer.glyphs = run->glyphBuffer(); 694 fCurrentRunBuffer.glyphs = run->glyphBuffer();
573 fCurrentRunBuffer.pos = run->posBuffer(); 695 fCurrentRunBuffer.pos = run->posBuffer();
696 fCurrentRunBuffer.utf8text = run->textBuffer();
697 fCurrentRunBuffer.clusters = run->clusterBuffer();
574 698
575 fLastRun = fStorageUsed; 699 fLastRun = fStorageUsed;
576 fStorageUsed += runSize; 700 fStorageUsed += runSize;
577 fRunCount++; 701 fRunCount++;
578 702
579 SkASSERT(fStorageUsed <= fStorageSize); 703 SkASSERT(fStorageUsed <= fStorageSize);
580 run->validate(fStorage.get() + fStorageUsed); 704 run->validate(fStorage.get() + fStorageUsed);
581 } 705 }
582 706 SkASSERT(textSize > 0 || nullptr == fCurrentRunBuffer.utf8text);
707 SkASSERT(textSize > 0 || nullptr == fCurrentRunBuffer.clusters);
583 if (!fDeferredBounds) { 708 if (!fDeferredBounds) {
584 if (bounds) { 709 if (bounds) {
585 fBounds.join(*bounds); 710 fBounds.join(*bounds);
586 } else { 711 } else {
587 fDeferredBounds = true; 712 fDeferredBounds = true;
588 } 713 }
589 } 714 }
590 } 715 }
591 716
592 const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRun(const SkPaint& f ont, int count, 717 const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunText(const SkPain t& font, int count,
593 SkScalar x, SkSc alar y, 718 SkScalar x, SkScalar y,
594 const SkRect* bo unds) { 719 int textByte Count,
595 this->allocInternal(font, SkTextBlob::kDefault_Positioning, count, SkPoint:: Make(x, y), bounds); 720 SkString lan g,
596 721 const SkRect * bounds) {
722 this->allocInternal(font, SkTextBlob::kDefault_Positioning, count, textByteC ount, SkPoint::Make(x, y), bounds);
597 return fCurrentRunBuffer; 723 return fCurrentRunBuffer;
598 } 724 }
599 725
600 const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPosH(const SkPain t& font, int count, 726 const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunTextPosH(const Sk Paint& font, int count,
601 SkScalar y, 727 SkScalar y,
602 const SkRect * bounds) { 728 int text ByteCount,
603 this->allocInternal(font, SkTextBlob::kHorizontal_Positioning, count, SkPoin t::Make(0, y), 729 SkString lang,
730 const Sk Rect* bounds) {
731 this->allocInternal(font, SkTextBlob::kHorizontal_Positioning, count, textBy teCount, SkPoint::Make(0, y),
604 bounds); 732 bounds);
605 733
606 return fCurrentRunBuffer; 734 return fCurrentRunBuffer;
607 } 735 }
608 736
609 const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPos(const SkPaint & font, int count, 737 const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunTextPos(const SkP aint& font, int count,
610 const SkRect *bounds) { 738 int textB yteCount,
611 this->allocInternal(font, SkTextBlob::kFull_Positioning, count, SkPoint::Mak e(0, 0), bounds); 739 SkString lang,
740 const SkR ect *bounds) {
741 this->allocInternal(font, SkTextBlob::kFull_Positioning, count, textByteCount , SkPoint::Make(0, 0), bounds);
612 742
613 return fCurrentRunBuffer; 743 return fCurrentRunBuffer;
614 } 744 }
615 745
616 sk_sp<SkTextBlob> SkTextBlobBuilder::make() { 746 sk_sp<SkTextBlob> SkTextBlobBuilder::make() {
617 SkASSERT((fRunCount > 0) == (nullptr != fStorage.get())); 747 SkASSERT((fRunCount > 0) == (nullptr != fStorage.get()));
618 748
619 this->updateDeferredBounds(); 749 this->updateDeferredBounds();
620 750
621 if (0 == fRunCount) { 751 if (0 == fRunCount) {
622 SkASSERT(nullptr == fStorage.get()); 752 SkASSERT(nullptr == fStorage.get());
623 fStorageUsed = sizeof(SkTextBlob); 753 fStorageUsed = sizeof(SkTextBlob);
624 fStorage.realloc(fStorageUsed); 754 fStorage.realloc(fStorageUsed);
625 } 755 }
626 756
627 SkTextBlob* blob = new (fStorage.release()) SkTextBlob(fRunCount, fBounds); 757 SkTextBlob* blob = new (fStorage.release()) SkTextBlob(fRunCount, fBounds);
628 SkDEBUGCODE(const_cast<SkTextBlob*>(blob)->fStorageSize = fStorageSize;) 758 SkDEBUGCODE(const_cast<SkTextBlob*>(blob)->fStorageSize = fStorageSize;)
629 759
630 SkDEBUGCODE( 760 SkDEBUGCODE(
631 size_t validateSize = sizeof(SkTextBlob); 761 size_t validateSize = sizeof(SkTextBlob);
632 const SkTextBlob::RunRecord* run = SkTextBlob::RunRecord::First(blob); 762 const SkTextBlob::RunRecord* run = SkTextBlob::RunRecord::First(blob);
633 for (int i = 0; i < fRunCount; ++i) { 763 for (int i = 0; i < fRunCount; ++i) {
634 validateSize += SkTextBlob::RunRecord::StorageSize(run->fCount, run- >fPositioning); 764 validateSize += SkTextBlob::RunRecord::StorageSize(
765 run->fCount, run->textSize(), run->fPositioning);
635 run->validate(reinterpret_cast<const uint8_t*>(blob) + fStorageUsed) ; 766 run->validate(reinterpret_cast<const uint8_t*>(blob) + fStorageUsed) ;
636 run = SkTextBlob::RunRecord::Next(run); 767 run = SkTextBlob::RunRecord::Next(run);
637 } 768 }
638 SkASSERT(validateSize == fStorageUsed); 769 SkASSERT(validateSize == fStorageUsed);
639 ) 770 )
640 771
641 fStorageUsed = 0; 772 fStorageUsed = 0;
642 fStorageSize = 0; 773 fStorageSize = 0;
643 fRunCount = 0; 774 fRunCount = 0;
644 fLastRun = 0; 775 fLastRun = 0;
645 fBounds.setEmpty(); 776 fBounds.setEmpty();
646 777
647 return sk_sp<SkTextBlob>(blob); 778 return sk_sp<SkTextBlob>(blob);
648 } 779 }
OLDNEW
« no previous file with comments | « include/core/SkTextBlob.h ('k') | src/core/SkTextBlobRunIterator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698