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

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

Issue 1070943002: [SkTextBlob] Custom run font record (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: review comments Created 5 years, 8 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/SkTypes.h ('k') | no next file » | 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 "SkTextBlob.h" 8 #include "SkTextBlob.h"
9 9
10 #include "SkReadBuffer.h" 10 #include "SkReadBuffer.h"
11 #include "SkTypeface.h" 11 #include "SkTypeface.h"
12 #include "SkWriteBuffer.h" 12 #include "SkWriteBuffer.h"
13 13
14 namespace {
15
16 // TODO(fmalita): replace with SkFont.
17 class RunFont : SkNoncopyable {
18 public:
19 RunFont(const SkPaint& paint)
20 : fSize(paint.getTextSize())
21 , fScaleX(paint.getTextScaleX())
22 , fTypeface(SkSafeRef(paint.getTypeface()))
23 , fSkewX(paint.getTextSkewX())
24 , fHinting(paint.getHinting())
25 , fFlags(paint.getFlags() & kFlagsMask) { }
26
27 void applyToPaint(SkPaint* paint) const {
28 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
29 paint->setTypeface(fTypeface.get());
30 paint->setTextSize(fSize);
31 paint->setTextScaleX(fScaleX);
32 paint->setTextSkewX(fSkewX);
33 paint->setHinting(static_cast<SkPaint::Hinting>(fHinting));
34
35 paint->setFlags((paint->getFlags() & ~kFlagsMask) | fFlags);
36 }
37
38 bool operator==(const RunFont& other) const {
39 return fTypeface == other.fTypeface
40 && fSize == other.fSize
41 && fScaleX == other.fScaleX
42 && fSkewX == other.fSkewX
43 && fHinting == other.fHinting
44 && fFlags == other.fFlags;
45 }
46
47 bool operator!=(const RunFont& other) const {
48 return !(*this == other);
49 }
50 private:
51 const static uint32_t kFlagsMask =
52 SkPaint::kAntiAlias_Flag |
53 SkPaint::kUnderlineText_Flag |
54 SkPaint::kStrikeThruText_Flag |
55 SkPaint::kFakeBoldText_Flag |
56 SkPaint::kLinearText_Flag |
57 SkPaint::kSubpixelText_Flag |
58 SkPaint::kDevKernText_Flag |
59 SkPaint::kLCDRenderText_Flag |
60 SkPaint::kEmbeddedBitmapText_Flag |
61 SkPaint::kAutoHinting_Flag |
62 SkPaint::kVerticalText_Flag |
63 SkPaint::kGenA8FromLCD_Flag |
64 SkPaint::kDistanceFieldTextTEMP_Flag;
65
66 SkScalar fSize;
67 SkScalar fScaleX;
68
69 // Keep this SkAutoTUnref off the first position, to avoid interfering with SkNoncopyable
70 // empty baseclass optimization (http://code.google.com/p/skia/issues/detail ?id=3694).
71 SkAutoTUnref<SkTypeface> fTypeface;
72 SkScalar fSkewX;
73
74 SK_COMPILE_ASSERT(SkPaint::kFull_Hinting < 4, insufficient_hinting_bits);
75 uint32_t fHinting : 2;
76 SK_COMPILE_ASSERT((kFlagsMask & 0xffff) == kFlagsMask, insufficient_flags_bi ts);
77 uint32_t fFlags : 16;
78
79 typedef SkNoncopyable INHERITED;
80 };
81
82 struct RunFontStorageEquivalent {
83 SkScalar fSize, fScaleX;
84 void* fTypeface;
85 SkScalar fSkewX;
86 uint32_t fFlags;
87 };
88 SK_COMPILE_ASSERT(sizeof(RunFont) == sizeof(RunFontStorageEquivalent), runfont_s hould_stay_packed);
89
90 } // anonymous namespace
91
14 // 92 //
15 // Textblob data is laid out into externally-managed storage as follows: 93 // Textblob data is laid out into externally-managed storage as follows:
16 // 94 //
17 // -------------------------------------------------------------------------- --- 95 // -------------------------------------------------------------------------- ---
18 // | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ... 96 // | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ...
19 // -------------------------------------------------------------------------- --- 97 // -------------------------------------------------------------------------- ---
20 // 98 //
21 // Each run record describes a text blob run, and can be used to determine the (implicit) 99 // Each run record describes a text blob run, and can be used to determine the (implicit)
22 // location of the following record. 100 // location of the following record.
23 101
24 SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;) 102 SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;)
25 103
26 class SkTextBlob::RunRecord { 104 class SkTextBlob::RunRecord {
27 public: 105 public:
28 RunRecord(uint32_t count, const SkPoint& offset, const SkPaint& font, GlyphP ositioning pos) 106 RunRecord(uint32_t count, const SkPoint& offset, const SkPaint& font, GlyphP ositioning pos)
29 : fCount(count) 107 : fFont(font)
108 , fCount(count)
30 , fOffset(offset) 109 , fOffset(offset)
31 , fFont(font)
32 , fPositioning(pos) { 110 , fPositioning(pos) {
33 SkDEBUGCODE(fMagic = kRunRecordMagic); 111 SkDEBUGCODE(fMagic = kRunRecordMagic);
34 } 112 }
35 113
36 uint32_t glyphCount() const { 114 uint32_t glyphCount() const {
37 return fCount; 115 return fCount;
38 } 116 }
39 117
40 const SkPoint& offset() const { 118 const SkPoint& offset() const {
41 return fOffset; 119 return fOffset;
42 } 120 }
43 121
44 const SkPaint& font() const { 122 const RunFont& font() const {
45 return fFont; 123 return fFont;
46 } 124 }
47 125
48 GlyphPositioning positioning() const { 126 GlyphPositioning positioning() const {
49 return fPositioning; 127 return fPositioning;
50 } 128 }
51 129
52 uint16_t* glyphBuffer() const { 130 uint16_t* glyphBuffer() const {
53 // Glyph are stored immediately following the record. 131 // Glyph are stored immediately following the record.
54 return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1); 132 return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 fCount += count; 171 fCount += count;
94 172
95 // Move the initial pos scalars to their new location. 173 // Move the initial pos scalars to their new location.
96 size_t copySize = initialCount * sizeof(SkScalar) * ScalarsPerGlyph(fPos itioning); 174 size_t copySize = initialCount * sizeof(SkScalar) * ScalarsPerGlyph(fPos itioning);
97 SkASSERT((uint8_t*)posBuffer() + copySize <= (uint8_t*)Next(this)); 175 SkASSERT((uint8_t*)posBuffer() + copySize <= (uint8_t*)Next(this));
98 176
99 // memmove, as the buffers may overlap 177 // memmove, as the buffers may overlap
100 memmove(posBuffer(), initialPosBuffer, copySize); 178 memmove(posBuffer(), initialPosBuffer, copySize);
101 } 179 }
102 180
181 RunFont fFont;
103 uint32_t fCount; 182 uint32_t fCount;
104 SkPoint fOffset; 183 SkPoint fOffset;
105 SkPaint fFont;
106 GlyphPositioning fPositioning; 184 GlyphPositioning fPositioning;
107 185
108 SkDEBUGCODE(unsigned fMagic;) 186 SkDEBUGCODE(unsigned fMagic;)
109 }; 187 };
110 188
111 static int32_t gNextID = 1; 189 static int32_t gNextID = 1;
112 static int32_t next_id() { 190 static int32_t next_id() {
113 int32_t id; 191 int32_t id;
114 do { 192 do {
115 id = sk_atomic_inc(&gNextID); 193 id = sk_atomic_inc(&gNextID);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 } 333 }
256 334
257 SkTextBlob::GlyphPositioning SkTextBlob::RunIterator::positioning() const { 335 SkTextBlob::GlyphPositioning SkTextBlob::RunIterator::positioning() const {
258 SkASSERT(!this->done()); 336 SkASSERT(!this->done());
259 return fCurrentRun->positioning(); 337 return fCurrentRun->positioning();
260 } 338 }
261 339
262 void SkTextBlob::RunIterator::applyFontToPaint(SkPaint* paint) const { 340 void SkTextBlob::RunIterator::applyFontToPaint(SkPaint* paint) const {
263 SkASSERT(!this->done()); 341 SkASSERT(!this->done());
264 342
265 const SkPaint& font = fCurrentRun->font(); 343 fCurrentRun->font().applyToPaint(paint);
266
267 paint->setTypeface(font.getTypeface());
268 paint->setTextEncoding(font.getTextEncoding());
269 paint->setTextSize(font.getTextSize());
270 paint->setTextScaleX(font.getTextScaleX());
271 paint->setTextSkewX(font.getTextSkewX());
272 paint->setHinting(font.getHinting());
273
274 uint32_t flagsMask = SkPaint::kAntiAlias_Flag
275 | SkPaint::kUnderlineText_Flag
276 | SkPaint::kStrikeThruText_Flag
277 | SkPaint::kFakeBoldText_Flag
278 | SkPaint::kLinearText_Flag
279 | SkPaint::kSubpixelText_Flag
280 | SkPaint::kDevKernText_Flag
281 | SkPaint::kLCDRenderText_Flag
282 | SkPaint::kEmbeddedBitmapText_Flag
283 | SkPaint::kAutoHinting_Flag
284 | SkPaint::kVerticalText_Flag
285 | SkPaint::kGenA8FromLCD_Flag
286 | SkPaint::kDistanceFieldTextTEMP_Flag;
287 paint->setFlags((paint->getFlags() & ~flagsMask) | (font.getFlags() & flagsM ask));
288 } 344 }
289 345
290 SkTextBlobBuilder::SkTextBlobBuilder() 346 SkTextBlobBuilder::SkTextBlobBuilder()
291 : fStorageSize(0) 347 : fStorageSize(0)
292 , fStorageUsed(0) 348 , fStorageUsed(0)
293 , fRunCount(0) 349 , fRunCount(0)
294 , fDeferredBounds(false) 350 , fDeferredBounds(false)
295 , fLastRun(0) { 351 , fLastRun(0) {
296 fBounds.setEmpty(); 352 fBounds.setEmpty();
297 } 353 }
298 354
299 SkTextBlobBuilder::~SkTextBlobBuilder() { 355 SkTextBlobBuilder::~SkTextBlobBuilder() {
300 if (NULL != fStorage.get()) { 356 if (NULL != fStorage.get()) {
301 // We are abandoning runs and must destruct the associated font data. 357 // We are abandoning runs and must destruct the associated font data.
302 // The easiest way to accomplish that is to use the blob destructor. 358 // The easiest way to accomplish that is to use the blob destructor.
303 build()->unref(); 359 build()->unref();
304 } 360 }
305 } 361 }
306 362
307 SkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) { 363 SkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) {
308 SkASSERT(SkTextBlob::kDefault_Positioning == run.positioning()); 364 SkASSERT(SkTextBlob::kDefault_Positioning == run.positioning());
309 365
310 SkRect bounds; 366 SkRect bounds;
311 run.font().measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t ), &bounds); 367 SkPaint paint;
368 run.font().applyToPaint(&paint);
369 paint.measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t), &b ounds);
312 370
313 return bounds.makeOffset(run.offset().x(), run.offset().y()); 371 return bounds.makeOffset(run.offset().x(), run.offset().y());
314 } 372 }
315 373
316 SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run ) { 374 SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run ) {
317 SkASSERT(run.glyphCount() > 0); 375 SkASSERT(run.glyphCount() > 0);
318 SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() || 376 SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() ||
319 SkTextBlob::kHorizontal_Positioning == run.positioning()); 377 SkTextBlob::kHorizontal_Positioning == run.positioning());
320 378
321 // First, compute the glyph position bbox. 379 // First, compute the glyph position bbox.
(...skipping 17 matching lines...) Expand all
339 const SkPoint* glyphPosPts = reinterpret_cast<const SkPoint*>(run.posBuf fer()); 397 const SkPoint* glyphPosPts = reinterpret_cast<const SkPoint*>(run.posBuf fer());
340 SkASSERT((void*)(glyphPosPts + run.glyphCount()) <= SkTextBlob::RunRecor d::Next(&run)); 398 SkASSERT((void*)(glyphPosPts + run.glyphCount()) <= SkTextBlob::RunRecor d::Next(&run));
341 399
342 bounds.setBounds(glyphPosPts, run.glyphCount()); 400 bounds.setBounds(glyphPosPts, run.glyphCount());
343 } break; 401 } break;
344 default: 402 default:
345 SkFAIL("unsupported positioning mode"); 403 SkFAIL("unsupported positioning mode");
346 } 404 }
347 405
348 // Expand by typeface glyph bounds. 406 // Expand by typeface glyph bounds.
349 const SkRect fontBounds = run.font().getFontBounds(); 407 SkPaint paint;
408 run.font().applyToPaint(&paint);
409 const SkRect fontBounds = paint.getFontBounds();
350 bounds.fLeft += fontBounds.left(); 410 bounds.fLeft += fontBounds.left();
351 bounds.fTop += fontBounds.top(); 411 bounds.fTop += fontBounds.top();
352 bounds.fRight += fontBounds.right(); 412 bounds.fRight += fontBounds.right();
353 bounds.fBottom += fontBounds.bottom(); 413 bounds.fBottom += fontBounds.bottom();
354 414
355 // Offset by run position. 415 // Offset by run position.
356 return bounds.makeOffset(run.offset().x(), run.offset().y()); 416 return bounds.makeOffset(run.offset().x(), run.offset().y());
357 } 417 }
358 418
359 void SkTextBlobBuilder::updateDeferredBounds() { 419 void SkTextBlobBuilder::updateDeferredBounds() {
360 SkASSERT(!fDeferredBounds || fRunCount > 0); 420 SkASSERT(!fDeferredBounds || fRunCount > 0);
361 421
362 if (!fDeferredBounds) { 422 if (!fDeferredBounds) {
363 return; 423 return;
364 } 424 }
365 425
366 SkASSERT(fLastRun >= sizeof(SkTextBlob)); 426 SkASSERT(fLastRun >= sizeof(SkTextBlob));
367 SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStora ge.get() + 427 SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStora ge.get() +
368 fLastR un); 428 fLastR un);
369 SkASSERT(SkPaint::kGlyphID_TextEncoding == run->font().getTextEncoding());
370 429
371 // FIXME: we should also use conservative bounds for kDefault_Positioning. 430 // FIXME: we should also use conservative bounds for kDefault_Positioning.
372 SkRect runBounds = SkTextBlob::kDefault_Positioning == run->positioning() ? 431 SkRect runBounds = SkTextBlob::kDefault_Positioning == run->positioning() ?
373 TightRunBounds(*run) : ConservativeRunBounds(*run); 432 TightRunBounds(*run) : ConservativeRunBounds(*run);
374 fBounds.join(runBounds); 433 fBounds.join(runBounds);
375 fDeferredBounds = false; 434 fDeferredBounds = false;
376 } 435 }
377 436
378 void SkTextBlobBuilder::reserve(size_t size) { 437 void SkTextBlobBuilder::reserve(size_t size) {
379 // We don't currently pre-allocate, but maybe someday... 438 // We don't currently pre-allocate, but maybe someday...
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 594
536 fStorageUsed = 0; 595 fStorageUsed = 0;
537 fStorageSize = 0; 596 fStorageSize = 0;
538 fRunCount = 0; 597 fRunCount = 0;
539 fLastRun = 0; 598 fLastRun = 0;
540 fBounds.setEmpty(); 599 fBounds.setEmpty();
541 600
542 return blob; 601 return blob;
543 } 602 }
544 603
OLDNEW
« no previous file with comments | « include/core/SkTypes.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698