| OLD | NEW | 
|---|
| 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 349 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 360 | 360 | 
| 361 SkTextBlobBuilder::~SkTextBlobBuilder() { | 361 SkTextBlobBuilder::~SkTextBlobBuilder() { | 
| 362     if (nullptr != fStorage.get()) { | 362     if (nullptr != fStorage.get()) { | 
| 363         // We are abandoning runs and must destruct the associated font data. | 363         // We are abandoning runs and must destruct the associated font data. | 
| 364         // The easiest way to accomplish that is to use the blob destructor. | 364         // The easiest way to accomplish that is to use the blob destructor. | 
| 365         build()->unref(); | 365         build()->unref(); | 
| 366     } | 366     } | 
| 367 } | 367 } | 
| 368 | 368 | 
| 369 SkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) { | 369 SkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) { | 
| 370     SkASSERT(SkTextBlob::kDefault_Positioning == run.positioning()); |  | 
| 371 |  | 
| 372     SkRect bounds; | 370     SkRect bounds; | 
| 373     SkPaint paint; | 371     SkPaint paint; | 
| 374     run.font().applyToPaint(&paint); | 372     run.font().applyToPaint(&paint); | 
| 375     paint.measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t), &b
     ounds); | 373 | 
|  | 374     if (SkTextBlob::kDefault_Positioning == run.positioning()) { | 
|  | 375         paint.measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t)
     , &bounds); | 
|  | 376         return bounds.makeOffset(run.offset().x(), run.offset().y()); | 
|  | 377     } | 
|  | 378 | 
|  | 379     SkAutoSTArray<16, SkRect> glyphBounds(run.glyphCount()); | 
|  | 380     paint.getTextWidths(run.glyphBuffer(), | 
|  | 381                         run.glyphCount() * sizeof(uint16_t), | 
|  | 382                         NULL, | 
|  | 383                         glyphBounds.get()); | 
|  | 384 | 
|  | 385     SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() || | 
|  | 386              SkTextBlob::kHorizontal_Positioning == run.positioning()); | 
|  | 387     // kFull_Positioning       => [ x, y, x, y... ] | 
|  | 388     // kHorizontal_Positioning => [ x, x, x... ] | 
|  | 389     //                            (const y applied by runBounds.offset(run->offs
     et()) later) | 
|  | 390     const SkScalar horizontalConstY = 0; | 
|  | 391     const SkScalar* glyphPosX = run.posBuffer(); | 
|  | 392     const SkScalar* glyphPosY = (run.positioning() == SkTextBlob::kFull_Position
     ing) ? | 
|  | 393                                                       glyphPosX + 1 : &horizonta
     lConstY; | 
|  | 394     const unsigned posXInc = SkTextBlob::ScalarsPerGlyph(run.positioning()); | 
|  | 395     const unsigned posYInc = (run.positioning() == SkTextBlob::kFull_Positioning
     ) ? | 
|  | 396                                                    posXInc : 0; | 
|  | 397 | 
|  | 398     bounds.setEmpty(); | 
|  | 399     for (unsigned i = 0; i < run.glyphCount(); ++i) { | 
|  | 400         bounds.join(glyphBounds[i].makeOffset(*glyphPosX, *glyphPosY)); | 
|  | 401         glyphPosX += posXInc; | 
|  | 402         glyphPosY += posYInc; | 
|  | 403     } | 
|  | 404 | 
|  | 405     SkASSERT((void*)glyphPosX <= SkTextBlob::RunRecord::Next(&run)); | 
|  | 406     SkASSERT(run.positioning() == SkTextBlob::kHorizontal_Positioning || | 
|  | 407              (void*)glyphPosY <= SkTextBlob::RunRecord::Next(&run)); | 
| 376 | 408 | 
| 377     return bounds.makeOffset(run.offset().x(), run.offset().y()); | 409     return bounds.makeOffset(run.offset().x(), run.offset().y()); | 
| 378 } | 410 } | 
| 379 | 411 | 
| 380 SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run
     ) { | 412 SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run
     ) { | 
| 381     SkASSERT(run.glyphCount() > 0); | 413     SkASSERT(run.glyphCount() > 0); | 
| 382     SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() || | 414     SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() || | 
| 383              SkTextBlob::kHorizontal_Positioning == run.positioning()); | 415              SkTextBlob::kHorizontal_Positioning == run.positioning()); | 
| 384 | 416 | 
| 385     // First, compute the glyph position bbox. | 417     SkPaint paint; | 
|  | 418     run.font().applyToPaint(&paint); | 
|  | 419     const SkRect fontBounds = paint.getFontBounds(); | 
|  | 420     if (fontBounds.isEmpty()) { | 
|  | 421         // Empty font bounds are likely a font bug.  TightBounds has a better ch
     ance of | 
|  | 422         // producing useful results in this case. | 
|  | 423         return TightRunBounds(run); | 
|  | 424     } | 
|  | 425 | 
|  | 426     // Compute the glyph position bbox. | 
| 386     SkRect bounds; | 427     SkRect bounds; | 
| 387     switch (run.positioning()) { | 428     switch (run.positioning()) { | 
| 388     case SkTextBlob::kHorizontal_Positioning: { | 429     case SkTextBlob::kHorizontal_Positioning: { | 
| 389         const SkScalar* glyphPos = run.posBuffer(); | 430         const SkScalar* glyphPos = run.posBuffer(); | 
| 390         SkASSERT((void*)(glyphPos + run.glyphCount()) <= SkTextBlob::RunRecord::
     Next(&run)); | 431         SkASSERT((void*)(glyphPos + run.glyphCount()) <= SkTextBlob::RunRecord::
     Next(&run)); | 
| 391 | 432 | 
| 392         SkScalar minX = *glyphPos; | 433         SkScalar minX = *glyphPos; | 
| 393         SkScalar maxX = *glyphPos; | 434         SkScalar maxX = *glyphPos; | 
| 394         for (unsigned i = 1; i < run.glyphCount(); ++i) { | 435         for (unsigned i = 1; i < run.glyphCount(); ++i) { | 
| 395             SkScalar x = glyphPos[i]; | 436             SkScalar x = glyphPos[i]; | 
| 396             minX = SkMinScalar(x, minX); | 437             minX = SkMinScalar(x, minX); | 
| 397             maxX = SkMaxScalar(x, maxX); | 438             maxX = SkMaxScalar(x, maxX); | 
| 398         } | 439         } | 
| 399 | 440 | 
| 400         bounds.setLTRB(minX, 0, maxX, 0); | 441         bounds.setLTRB(minX, 0, maxX, 0); | 
| 401     } break; | 442     } break; | 
| 402     case SkTextBlob::kFull_Positioning: { | 443     case SkTextBlob::kFull_Positioning: { | 
| 403         const SkPoint* glyphPosPts = reinterpret_cast<const SkPoint*>(run.posBuf
     fer()); | 444         const SkPoint* glyphPosPts = reinterpret_cast<const SkPoint*>(run.posBuf
     fer()); | 
| 404         SkASSERT((void*)(glyphPosPts + run.glyphCount()) <= SkTextBlob::RunRecor
     d::Next(&run)); | 445         SkASSERT((void*)(glyphPosPts + run.glyphCount()) <= SkTextBlob::RunRecor
     d::Next(&run)); | 
| 405 | 446 | 
| 406         bounds.setBounds(glyphPosPts, run.glyphCount()); | 447         bounds.setBounds(glyphPosPts, run.glyphCount()); | 
| 407     } break; | 448     } break; | 
| 408     default: | 449     default: | 
| 409         SkFAIL("unsupported positioning mode"); | 450         SkFAIL("unsupported positioning mode"); | 
| 410     } | 451     } | 
| 411 | 452 | 
| 412     // Expand by typeface glyph bounds. | 453     // Expand by typeface glyph bounds. | 
| 413     SkPaint paint; |  | 
| 414     run.font().applyToPaint(&paint); |  | 
| 415     const SkRect fontBounds = paint.getFontBounds(); |  | 
| 416     bounds.fLeft   += fontBounds.left(); | 454     bounds.fLeft   += fontBounds.left(); | 
| 417     bounds.fTop    += fontBounds.top(); | 455     bounds.fTop    += fontBounds.top(); | 
| 418     bounds.fRight  += fontBounds.right(); | 456     bounds.fRight  += fontBounds.right(); | 
| 419     bounds.fBottom += fontBounds.bottom(); | 457     bounds.fBottom += fontBounds.bottom(); | 
| 420 | 458 | 
| 421     // Offset by run position. | 459     // Offset by run position. | 
| 422     return bounds.makeOffset(run.offset().x(), run.offset().y()); | 460     return bounds.makeOffset(run.offset().x(), run.offset().y()); | 
| 423 } | 461 } | 
| 424 | 462 | 
| 425 void SkTextBlobBuilder::updateDeferredBounds() { | 463 void SkTextBlobBuilder::updateDeferredBounds() { | 
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 599 | 637 | 
| 600     fStorageUsed = 0; | 638     fStorageUsed = 0; | 
| 601     fStorageSize = 0; | 639     fStorageSize = 0; | 
| 602     fRunCount = 0; | 640     fRunCount = 0; | 
| 603     fLastRun = 0; | 641     fLastRun = 0; | 
| 604     fBounds.setEmpty(); | 642     fBounds.setEmpty(); | 
| 605 | 643 | 
| 606     return blob; | 644     return blob; | 
| 607 } | 645 } | 
| 608 | 646 | 
| OLD | NEW | 
|---|