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 858153007: Conservative blob bounds cleanup (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: review comments 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 | « no previous file | 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"
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 299
300 SkTextBlobBuilder::~SkTextBlobBuilder() { 300 SkTextBlobBuilder::~SkTextBlobBuilder() {
301 if (NULL != fStorage.get()) { 301 if (NULL != fStorage.get()) {
302 // We are abandoning runs and must destruct the associated font data. 302 // We are abandoning runs and must destruct the associated font data.
303 // 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.
304 build()->unref(); 304 build()->unref();
305 } 305 }
306 } 306 }
307 307
308 SkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) { 308 SkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) {
309 SkASSERT(SkTextBlob::kDefault_Positioning == run.positioning());
310
309 SkRect bounds; 311 SkRect bounds;
310 312 run.font().measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t ), &bounds);
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 313
345 return bounds.makeOffset(run.offset().x(), run.offset().y()); 314 return bounds.makeOffset(run.offset().x(), run.offset().y());
346 } 315 }
347 316
348 SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run ) { 317 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); 318 SkASSERT(run.glyphCount() > 0);
354 SkASSERT((void*)(glyphPos + run.glyphCount() * posScalars) <= 319 SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() ||
355 SkTextBlob::RunRecord::Next(&run)); 320 SkTextBlob::kHorizontal_Positioning == run.positioning());
356 321
357 // First, compute the glyph position bbox. 322 // First, compute the glyph position bbox.
358 SkRect bounds = SkRect::MakeXYWH(glyphPos[0], (2 == posScalars) ? glyphPos[1 ] : 0, 0, 0); 323 SkRect bounds;
359 for (unsigned i = 1; i < run.glyphCount(); ++i) { 324 switch (run.positioning()) {
360 SkScalar xpos = glyphPos[i * posScalars]; 325 case SkTextBlob::kHorizontal_Positioning: {
361 SkScalar ypos = (2 == posScalars) ? glyphPos[i * posScalars + 1] : 0; 326 const SkScalar* glyphPos = run.posBuffer();
362 bounds.growToInclude(xpos, ypos); 327 SkASSERT((void*)(glyphPos + run.glyphCount()) <= SkTextBlob::RunRecord:: Next(&run));
328
329 SkScalar minX = *glyphPos;
330 SkScalar maxX = *glyphPos;
331 for (unsigned i = 1; i < run.glyphCount(); ++i) {
332 SkScalar x = glyphPos[i];
333 minX = SkMinScalar(x, minX);
334 maxX = SkMaxScalar(x, maxX);
335 }
336
337 bounds.setLTRB(minX, 0, maxX, 0);
338 } break;
339 case SkTextBlob::kFull_Positioning: {
340 const SkPoint* glyphPosPts = reinterpret_cast<const SkPoint*>(run.posBuf fer());
341 SkASSERT((void*)(glyphPosPts + run.glyphCount()) <= SkTextBlob::RunRecor d::Next(&run));
342
343 bounds.setBounds(glyphPosPts, run.glyphCount());
344 } break;
345 default:
346 SkFAIL("unsupported positioning mode");
363 } 347 }
364 348
365 // Expand by typeface glyph bounds. 349 // Expand by typeface glyph bounds.
366 const SkRect fontBounds = run.font().getFontBounds(); 350 const SkRect fontBounds = run.font().getFontBounds();
367 bounds.fLeft += fontBounds.left(); 351 bounds.fLeft += fontBounds.left();
368 bounds.fTop += fontBounds.top(); 352 bounds.fTop += fontBounds.top();
369 bounds.fRight += fontBounds.right(); 353 bounds.fRight += fontBounds.right();
370 bounds.fBottom += fontBounds.bottom(); 354 bounds.fBottom += fontBounds.bottom();
371 355
372 // Offset by run position. 356 // Offset by run position.
373 return bounds.makeOffset(run.offset().x(), run.offset().y()); 357 return bounds.makeOffset(run.offset().x(), run.offset().y());
374 } 358 }
375 359
376 void SkTextBlobBuilder::updateDeferredBounds() { 360 void SkTextBlobBuilder::updateDeferredBounds() {
377 SkASSERT(!fDeferredBounds || fRunCount > 0); 361 SkASSERT(!fDeferredBounds || fRunCount > 0);
378 362
379 if (!fDeferredBounds) { 363 if (!fDeferredBounds) {
380 return; 364 return;
381 } 365 }
382 366
383 SkASSERT(fLastRun >= sizeof(SkTextBlob)); 367 SkASSERT(fLastRun >= sizeof(SkTextBlob));
384 SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStora ge.get() + 368 SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStora ge.get() +
385 fLastR un); 369 fLastR un);
386 SkASSERT(SkPaint::kGlyphID_TextEncoding == run->font().getTextEncoding()); 370 SkASSERT(SkPaint::kGlyphID_TextEncoding == run->font().getTextEncoding());
387 371
388 SkRect runBounds; 372 // FIXME: we should also use conservative bounds for kDefault_Positioning.
389 #ifdef SK_SUPPORT_LEGACY_BLOB_BOUNDS 373 SkRect runBounds = SkTextBlob::kDefault_Positioning == run->positioning() ?
390 runBounds = TightRunBounds(*run); 374 TightRunBounds(*run) : ConservativeRunBounds(*run);
391 #else
392 // FIXME: conservative bounds for default positioning?
393 if (SkTextBlob::kDefault_Positioning == run->positioning()) {
394 runBounds = TightRunBounds(*run);
395 } else {
396 runBounds = ConservativeRunBounds(*run);
397 }
398 #endif
399
400 fBounds.join(runBounds); 375 fBounds.join(runBounds);
401 fDeferredBounds = false; 376 fDeferredBounds = false;
402 } 377 }
403 378
404 void SkTextBlobBuilder::reserve(size_t size) { 379 void SkTextBlobBuilder::reserve(size_t size) {
405 // We don't currently pre-allocate, but maybe someday... 380 // We don't currently pre-allocate, but maybe someday...
406 if (fStorageUsed + size <= fStorageSize) { 381 if (fStorageUsed + size <= fStorageSize) {
407 return; 382 return;
408 } 383 }
409 384
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 536
562 fStorageUsed = 0; 537 fStorageUsed = 0;
563 fStorageSize = 0; 538 fStorageSize = 0;
564 fRunCount = 0; 539 fRunCount = 0;
565 fLastRun = 0; 540 fLastRun = 0;
566 fBounds.setEmpty(); 541 fBounds.setEmpty();
567 542
568 return blob; 543 return blob;
569 } 544 }
570 545
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698