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

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

Issue 886473002: Conservative SkTextBlob bounds. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: minor cleanup Created 5 years, 10 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') | 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 "SkWriteBuffer.h" 12 #include "SkWriteBuffer.h"
12 13
13 // 14 //
14 // Textblob data is laid out into externally-managed storage as follows: 15 // Textblob data is laid out into externally-managed storage as follows:
15 // 16 //
16 // -------------------------------------------------------------------------- --- 17 // -------------------------------------------------------------------------- ---
17 // | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ... 18 // | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ...
18 // -------------------------------------------------------------------------- --- 19 // -------------------------------------------------------------------------- ---
19 // 20 //
20 // Each run record describes a text blob run, and can be used to determine the (implicit) 21 // Each run record describes a text blob run, and can be used to determine the (implicit)
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 } 298 }
298 299
299 SkTextBlobBuilder::~SkTextBlobBuilder() { 300 SkTextBlobBuilder::~SkTextBlobBuilder() {
300 if (NULL != fStorage.get()) { 301 if (NULL != fStorage.get()) {
301 // We are abandoning runs and must destruct the associated font data. 302 // We are abandoning runs and must destruct the associated font data.
302 // The easiest way to accomplish that is to use the blob destructor. 303 // The easiest way to accomplish that is to use the blob destructor.
303 build()->unref(); 304 build()->unref();
304 } 305 }
305 } 306 }
306 307
308 SkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) {
309 SkRect bounds;
310
311 if (SkTextBlob::kDefault_Positioning == run.positioning()) {
312 run.font().measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint 16_t), &bounds);
313 return bounds;
314 }
315
316 SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() ||
317 SkTextBlob::kHorizontal_Positioning == run.positioning());
318
319 SkAutoSTArray<16, SkRect> glyphBounds(run.glyphCount());
320 run.font().getTextWidths(run.glyphBuffer(),
321 run.glyphCount() * sizeof(uint16_t),
322 NULL,
323 glyphBounds.get());
324
325 bounds = SkRect::MakeEmpty();
326 SkScalar* glyphPos = run.posBuffer();
327 for (unsigned i = 0; i < run.glyphCount(); ++i) {
328 if (SkTextBlob::kFull_Positioning == run.positioning()) {
329 // [ x, y, x, y... ]
330 glyphBounds[i].offset(glyphPos[0], glyphPos[1]);
331 SkASSERT(2 == SkTextBlob::ScalarsPerGlyph(run.positioning()));
332 glyphPos += 2;
333 } else {
334 // [ x, x, x... ], const y applied by runBounds.offset(run->offset() ) later.
335 glyphBounds[i].offset(glyphPos[0], 0);
336 SkASSERT(1 == SkTextBlob::ScalarsPerGlyph(run.positioning()));
337 glyphPos += 1;
338 }
339
340 bounds.join(glyphBounds[i]);
341 }
342
343 SkASSERT((void*)glyphPos <= SkTextBlob::RunRecord::Next(&run));
344
345 return bounds.makeOffset(run.offset().x(), run.offset().y());
346 }
347
348 SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run ) {
349 const SkScalar* glyphPos = run.posBuffer();
350 int posScalars = SkTextBlob::ScalarsPerGlyph(run.positioning());
351
352 SkASSERT(1 == posScalars || 2 == posScalars);
353 SkASSERT(run.glyphCount() > 0);
354 SkASSERT((void*)(glyphPos + run.glyphCount() * posScalars) <=
355 SkTextBlob::RunRecord::Next(&run));
356
357 // First, compute the glyph position bbox.
358 SkRect bounds = SkRect::MakeXYWH(glyphPos[0], (2 == posScalars) ? glyphPos[1 ] : 0, 0, 0);
359 for (unsigned i = 1; i < run.glyphCount(); ++i) {
360 SkScalar xpos = glyphPos[i * posScalars];
361 SkScalar ypos = (2 == posScalars) ? glyphPos[i * posScalars + 1] : 0;
362 bounds.growToInclude(xpos, ypos);
363 }
364
365 // Expand by typeface glyph bounds.
366 const SkRect fontBounds = run.font().getFontBounds();
367 bounds.fLeft += fontBounds.left();
368 bounds.fTop += fontBounds.top();
369 bounds.fRight += fontBounds.right();
370 bounds.fBottom += fontBounds.bottom();
371
372 // Offset by run position.
373 return bounds.makeOffset(run.offset().x(), run.offset().y());
374 }
375
307 void SkTextBlobBuilder::updateDeferredBounds() { 376 void SkTextBlobBuilder::updateDeferredBounds() {
308 SkASSERT(!fDeferredBounds || fRunCount > 0); 377 SkASSERT(!fDeferredBounds || fRunCount > 0);
309 378
310 if (!fDeferredBounds) { 379 if (!fDeferredBounds) {
311 return; 380 return;
312 } 381 }
313 382
314 SkASSERT(fLastRun >= sizeof(SkTextBlob)); 383 SkASSERT(fLastRun >= sizeof(SkTextBlob));
315 SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStora ge.get() + 384 SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStora ge.get() +
316 fLastR un); 385 fLastR un);
317 SkASSERT(SkPaint::kGlyphID_TextEncoding == run->font().getTextEncoding()); 386 SkASSERT(SkPaint::kGlyphID_TextEncoding == run->font().getTextEncoding());
318 387
319 SkRect runBounds = SkRect::MakeEmpty(); 388 SkRect runBounds;
389 #ifdef SK_SUPPORT_LEGACY_BLOB_BOUNDS
390 runBounds = TightRunBounds(*run);
391 #else
392 // FIXME: conservative bounds for default positioning?
320 if (SkTextBlob::kDefault_Positioning == run->positioning()) { 393 if (SkTextBlob::kDefault_Positioning == run->positioning()) {
321 run->font().measureText(run->glyphBuffer(), 394 runBounds = TightRunBounds(*run);
322 run->glyphCount() * sizeof(uint16_t),
323 &runBounds);
324 } else { 395 } else {
325 SkASSERT(SkTextBlob::kFull_Positioning == run->positioning() || 396 runBounds = ConservativeRunBounds(*run);
326 SkTextBlob::kHorizontal_Positioning == run->positioning());
327
328 SkAutoSTArray<16, SkRect> glyphBounds(run->glyphCount());
329 run->font().getTextWidths(run->glyphBuffer(),
330 run->glyphCount() * sizeof(uint16_t),
331 NULL,
332 glyphBounds.get());
333
334 SkScalar* glyphOffset = run->posBuffer();
335 for (unsigned i = 0; i < run->glyphCount(); ++i) {
336 if (SkTextBlob::kFull_Positioning == run->positioning()) {
337 // [ x, y, x, y... ]
338 glyphBounds[i].offset(glyphOffset[0], glyphOffset[1]);
339 SkASSERT(2 == SkTextBlob::ScalarsPerGlyph(run->positioning()));
340 glyphOffset += 2;
341 } else {
342 // [ x, x, x... ], const y applied by runBounds.offset(run->offs et()) later.
343 glyphBounds[i].offset(glyphOffset[0], 0);
344 SkASSERT(1 == SkTextBlob::ScalarsPerGlyph(run->positioning()));
345 glyphOffset += 1;
346 }
347
348 runBounds.join(glyphBounds[i]);
349 }
350
351 SkASSERT((void*)glyphOffset <= SkTextBlob::RunRecord::Next(run));
352 } 397 }
353 398 #endif
354 runBounds.offset(run->offset());
355 399
356 fBounds.join(runBounds); 400 fBounds.join(runBounds);
357 fDeferredBounds = false; 401 fDeferredBounds = false;
358 } 402 }
359 403
360 void SkTextBlobBuilder::reserve(size_t size) { 404 void SkTextBlobBuilder::reserve(size_t size) {
361 // We don't currently pre-allocate, but maybe someday... 405 // We don't currently pre-allocate, but maybe someday...
362 if (fStorageUsed + size <= fStorageSize) { 406 if (fStorageUsed + size <= fStorageSize) {
363 return; 407 return;
364 } 408 }
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 561
518 fStorageUsed = 0; 562 fStorageUsed = 0;
519 fStorageSize = 0; 563 fStorageSize = 0;
520 fRunCount = 0; 564 fRunCount = 0;
521 fLastRun = 0; 565 fLastRun = 0;
522 fBounds.setEmpty(); 566 fBounds.setEmpty();
523 567
524 return blob; 568 return blob;
525 } 569 }
526 570
OLDNEW
« no previous file with comments | « include/core/SkTextBlob.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698