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

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