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 "SkRecordDraw.h" | 8 #include "SkRecordDraw.h" |
9 #include "SkPatchUtils.h" | 9 #include "SkPatchUtils.h" |
10 #include "SkTypeface.h" | |
11 | 10 |
12 void SkRecordDraw(const SkRecord& record, | 11 void SkRecordDraw(const SkRecord& record, |
13 SkCanvas* canvas, | 12 SkCanvas* canvas, |
14 const SkBBoxHierarchy* bbh, | 13 const SkBBoxHierarchy* bbh, |
15 SkDrawPictureCallback* callback) { | 14 SkDrawPictureCallback* callback) { |
16 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); | 15 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); |
17 | 16 |
18 if (bbh) { | 17 if (bbh) { |
19 // Draw only ops that affect pixels in the canvas's current clip. | 18 // Draw only ops that affect pixels in the canvas's current clip. |
20 // The SkRecord and BBH were recorded in identity space. This canvas | 19 // The SkRecord and BBH were recorded in identity space. This canvas |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 left = SkMinScalar(left, op.xpos[i]); | 437 left = SkMinScalar(left, op.xpos[i]); |
439 right = SkMaxScalar(right, op.xpos[i]); | 438 right = SkMaxScalar(right, op.xpos[i]); |
440 } | 439 } |
441 SkRect dst = { left, op.y, right, op.y }; | 440 SkRect dst = { left, op.y, right, op.y }; |
442 AdjustTextForFontMetrics(&dst, op.paint); | 441 AdjustTextForFontMetrics(&dst, op.paint); |
443 return this->adjustAndMap(dst, &op.paint); | 442 return this->adjustAndMap(dst, &op.paint); |
444 } | 443 } |
445 Bounds bounds(const DrawTextOnPath& op) const { | 444 Bounds bounds(const DrawTextOnPath& op) const { |
446 SkRect dst = op.path.getBounds(); | 445 SkRect dst = op.path.getBounds(); |
447 | 446 |
448 // We don't know how the text will curve aroudn the path, so | 447 // Pad all sides by the maximum padding in any direction we'd normally a
pply. |
449 // pad all sides by the maximum padding in any direction we'd normally a
pply. | |
450 SkRect pad = { 0, 0, 0, 0}; | 448 SkRect pad = { 0, 0, 0, 0}; |
451 AdjustTextForFontMetrics(&pad, op.paint); | 449 AdjustTextForFontMetrics(&pad, op.paint); |
452 SkScalar max = SkTMax(SkTMax(-pad.fLeft, pad.fRight), | 450 |
453 SkTMax(-pad.fTop, pad.fBottom)); | 451 // That maximum padding happens to always be the right pad today. |
454 dst.outset(max, max); | 452 SkASSERT(pad.fLeft == -pad.fRight); |
| 453 SkASSERT(pad.fTop == -pad.fBottom); |
| 454 SkASSERT(pad.fRight > pad.fBottom); |
| 455 dst.outset(pad.fRight, pad.fRight); |
455 | 456 |
456 return this->adjustAndMap(dst, &op.paint); | 457 return this->adjustAndMap(dst, &op.paint); |
457 } | 458 } |
458 | 459 |
459 Bounds bounds(const DrawTextBlob& op) const { | 460 Bounds bounds(const DrawTextBlob& op) const { |
460 SkRect dst = op.blob->bounds(); | 461 SkRect dst = op.blob->bounds(); |
461 dst.offset(op.x, op.y); | 462 dst.offset(op.x, op.y); |
462 return this->adjustAndMap(dst, &op.paint); | 463 return this->adjustAndMap(dst, &op.paint); |
463 } | 464 } |
464 | 465 |
465 static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { | 466 static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { |
466 // rect was built from only the text's origin points, so we need | |
467 // to outset it by the worst-case bounds of the typeface. | |
468 #ifdef SK_DEBUG | 467 #ifdef SK_DEBUG |
469 SkRect correct = *rect; | 468 SkRect correct = *rect; |
470 #endif | 469 #endif |
471 SkAutoTUnref<SkTypeface> au; | 470 // crbug.com/373785 ~~> xPad = 4x yPad |
472 SkTypeface* tf = paint.getTypeface(); | 471 // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x |
473 if (!tf) { | 472 const SkScalar yPad = 2.5f * paint.getTextSize(), |
474 au.reset(SkTypeface::RefDefault()); | 473 xPad = 4.0f * yPad; |
475 tf = au.get(); | 474 rect->outset(xPad, yPad); |
476 } | |
477 const SkScalar size = paint.getTextSize(); | |
478 const SkRect tb = tf->getBounds(); | |
479 rect->fLeft += size * tb.fLeft; | |
480 rect->fRight += size * tb.fRight; | |
481 rect->fTop += size * tb.fTop; | |
482 rect->fBottom += size * tb.fBottom; | |
483 #ifdef SK_DEBUG | 475 #ifdef SK_DEBUG |
484 SkPaint::FontMetrics metrics; | 476 SkPaint::FontMetrics metrics; |
485 paint.getFontMetrics(&metrics); | 477 paint.getFontMetrics(&metrics); |
486 correct.fLeft += metrics.fXMin; | 478 correct.fLeft += metrics.fXMin; |
487 correct.fTop += metrics.fTop; | 479 correct.fTop += metrics.fTop; |
488 correct.fRight += metrics.fXMax; | 480 correct.fRight += metrics.fXMax; |
489 correct.fBottom += metrics.fBottom; | 481 correct.fBottom += metrics.fBottom; |
490 // See skia:2862 for why we ignore small text sizes. | 482 // See skia:2862 for why we ignore small text sizes. |
491 SkASSERTF(paint.getTextSize() < 0.001f || rect->contains(correct), | 483 SkASSERTF(paint.getTextSize() < 0.001f || rect->contains(correct), |
492 "%f %f %f %f vs. %f %f %f %f, text size %f\n", | 484 "%f %f %f %f vs. %f %f %f %f\n", |
493 size*tb.fLeft, size*tb.fTop, size*tb.fRight, size*tb.fBottom, | 485 -xPad, -yPad, +xPad, +yPad, |
494 metrics.fXMin, metrics.fTop, metrics.fXMax, metrics.fBottom, | 486 metrics.fXMin, metrics.fTop, metrics.fXMax, metrics.fBottom); |
495 paint.getTextSize()); | |
496 #endif | 487 #endif |
497 } | 488 } |
498 | 489 |
499 // Returns true if rect was meaningfully adjusted for the effects of paint, | 490 // Returns true if rect was meaningfully adjusted for the effects of paint, |
500 // false if the paint could affect the rect in unknown ways. | 491 // false if the paint could affect the rect in unknown ways. |
501 static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { | 492 static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { |
502 if (paint) { | 493 if (paint) { |
503 if (paint->canComputeFastBounds()) { | 494 if (paint->canComputeFastBounds()) { |
504 *rect = paint->computeFastBounds(*rect, rect); | 495 *rect = paint->computeFastBounds(*rect, rect); |
505 return true; | 496 return true; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. | 548 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. |
558 SkTDArray<SaveBounds> fSaveStack; | 549 SkTDArray<SaveBounds> fSaveStack; |
559 SkTDArray<unsigned> fControlIndices; | 550 SkTDArray<unsigned> fControlIndices; |
560 }; | 551 }; |
561 | 552 |
562 } // namespace SkRecords | 553 } // namespace SkRecords |
563 | 554 |
564 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { | 555 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { |
565 SkRecords::FillBounds(record, bbh); | 556 SkRecords::FillBounds(record, bbh); |
566 } | 557 } |
OLD | NEW |