OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/canvas2d/BaseRenderingContext2D.h" | 5 #include "modules/canvas2d/BaseRenderingContext2D.h" |
6 | 6 |
7 #include "bindings/core/v8/ExceptionMessages.h" | 7 #include "bindings/core/v8/ExceptionMessages.h" |
8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
9 #include "core/css/cssom/CSSURLImageValue.h" | 9 #include "core/css/cssom/CSSURLImageValue.h" |
10 #include "core/css/parser/CSSParser.h" | 10 #include "core/css/parser/CSSParser.h" |
11 #include "core/frame/ImageBitmap.h" | 11 #include "core/frame/ImageBitmap.h" |
12 #include "core/html/HTMLCanvasElement.h" | 12 #include "core/html/HTMLCanvasElement.h" |
13 #include "core/html/HTMLImageElement.h" | 13 #include "core/html/HTMLImageElement.h" |
14 #include "core/html/HTMLVideoElement.h" | 14 #include "core/html/HTMLVideoElement.h" |
15 #include "core/html/ImageData.h" | 15 #include "core/html/ImageData.h" |
16 #include "core/offscreencanvas/OffscreenCanvas.h" | 16 #include "core/offscreencanvas/OffscreenCanvas.h" |
17 #include "modules/canvas2d/CanvasGradient.h" | 17 #include "modules/canvas2d/CanvasGradient.h" |
18 #include "modules/canvas2d/CanvasPattern.h" | 18 #include "modules/canvas2d/CanvasPattern.h" |
19 #include "modules/canvas2d/CanvasStyle.h" | 19 #include "modules/canvas2d/CanvasStyle.h" |
20 #include "modules/canvas2d/Path2D.h" | 20 #include "modules/canvas2d/Path2D.h" |
21 #include "platform/Histogram.h" | 21 #include "platform/Histogram.h" |
22 #include "platform/RuntimeEnabledFeatures.h" | 22 #include "platform/RuntimeEnabledFeatures.h" |
23 #include "platform/geometry/FloatQuad.h" | 23 #include "platform/geometry/FloatQuad.h" |
24 #include "platform/graphics/Color.h" | 24 #include "platform/graphics/Color.h" |
25 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" | 25 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" |
26 #include "platform/graphics/Image.h" | 26 #include "platform/graphics/Image.h" |
27 #include "platform/graphics/ImageBuffer.h" | 27 #include "platform/graphics/ImageBuffer.h" |
28 #include "platform/graphics/StrokeData.h" | 28 #include "platform/graphics/StrokeData.h" |
| 29 #include "platform/graphics/paint/PaintCanvas.h" |
| 30 #include "platform/graphics/paint/PaintFlags.h" |
29 #include "platform/graphics/skia/SkiaUtils.h" | 31 #include "platform/graphics/skia/SkiaUtils.h" |
30 | 32 |
31 namespace blink { | 33 namespace blink { |
32 | 34 |
33 BaseRenderingContext2D::BaseRenderingContext2D() | 35 BaseRenderingContext2D::BaseRenderingContext2D() |
34 : m_clipAntialiasing(NotAntiAliased) { | 36 : m_clipAntialiasing(NotAntiAliased) { |
35 m_stateStack.push_back(CanvasRenderingContext2DState::create()); | 37 m_stateStack.push_back(CanvasRenderingContext2DState::create()); |
36 } | 38 } |
37 | 39 |
38 BaseRenderingContext2D::~BaseRenderingContext2D() {} | 40 BaseRenderingContext2D::~BaseRenderingContext2D() {} |
(...skipping 12 matching lines...) Expand all Loading... |
51 m_stateStack.back()->restore(); | 53 m_stateStack.back()->restore(); |
52 m_stateStack.push_back(CanvasRenderingContext2DState::create( | 54 m_stateStack.push_back(CanvasRenderingContext2DState::create( |
53 state(), CanvasRenderingContext2DState::DontCopyClipList)); | 55 state(), CanvasRenderingContext2DState::DontCopyClipList)); |
54 // Set the new state's unrealized count to 0, because it has no outstanding | 56 // Set the new state's unrealized count to 0, because it has no outstanding |
55 // saves. | 57 // saves. |
56 // We need to do this explicitly because the copy constructor and operator= | 58 // We need to do this explicitly because the copy constructor and operator= |
57 // used by the Vector operations copy the unrealized count from the previous | 59 // used by the Vector operations copy the unrealized count from the previous |
58 // state (in turn necessary to support correct resizing and unwinding of the | 60 // state (in turn necessary to support correct resizing and unwinding of the |
59 // stack). | 61 // stack). |
60 m_stateStack.back()->resetUnrealizedSaveCount(); | 62 m_stateStack.back()->resetUnrealizedSaveCount(); |
61 SkCanvas* canvas = drawingCanvas(); | 63 PaintCanvas* canvas = drawingCanvas(); |
62 if (canvas) | 64 if (canvas) |
63 canvas->save(); | 65 canvas->save(); |
64 validateStateStack(); | 66 validateStateStack(); |
65 } | 67 } |
66 } | 68 } |
67 | 69 |
68 void BaseRenderingContext2D::save() { | 70 void BaseRenderingContext2D::save() { |
69 m_stateStack.back()->save(); | 71 m_stateStack.back()->save(); |
70 } | 72 } |
71 | 73 |
72 void BaseRenderingContext2D::restore() { | 74 void BaseRenderingContext2D::restore() { |
73 validateStateStack(); | 75 validateStateStack(); |
74 if (state().hasUnrealizedSaves()) { | 76 if (state().hasUnrealizedSaves()) { |
75 // We never realized the save, so just record that it was unnecessary. | 77 // We never realized the save, so just record that it was unnecessary. |
76 m_stateStack.back()->restore(); | 78 m_stateStack.back()->restore(); |
77 return; | 79 return; |
78 } | 80 } |
79 ASSERT(m_stateStack.size() >= 1); | 81 ASSERT(m_stateStack.size() >= 1); |
80 if (m_stateStack.size() <= 1) | 82 if (m_stateStack.size() <= 1) |
81 return; | 83 return; |
82 m_path.transform(state().transform()); | 84 m_path.transform(state().transform()); |
83 m_stateStack.pop_back(); | 85 m_stateStack.pop_back(); |
84 m_stateStack.back()->clearResolvedFilter(); | 86 m_stateStack.back()->clearResolvedFilter(); |
85 m_path.transform(state().transform().inverse()); | 87 m_path.transform(state().transform().inverse()); |
86 SkCanvas* c = drawingCanvas(); | 88 PaintCanvas* c = drawingCanvas(); |
87 if (c) | 89 if (c) |
88 c->restore(); | 90 c->restore(); |
89 | 91 |
90 validateStateStack(); | 92 validateStateStack(); |
91 } | 93 } |
92 | 94 |
93 void BaseRenderingContext2D::restoreMatrixClipStack(SkCanvas* c) const { | 95 void BaseRenderingContext2D::restoreMatrixClipStack(PaintCanvas* c) const { |
94 if (!c) | 96 if (!c) |
95 return; | 97 return; |
96 HeapVector<Member<CanvasRenderingContext2DState>>::const_iterator currState; | 98 HeapVector<Member<CanvasRenderingContext2DState>>::const_iterator currState; |
97 DCHECK(m_stateStack.begin() < m_stateStack.end()); | 99 DCHECK(m_stateStack.begin() < m_stateStack.end()); |
98 for (currState = m_stateStack.begin(); currState < m_stateStack.end(); | 100 for (currState = m_stateStack.begin(); currState < m_stateStack.end(); |
99 currState++) { | 101 currState++) { |
100 c->setMatrix(SkMatrix::I()); | 102 c->setMatrix(SkMatrix::I()); |
101 if (currState->get()) { | 103 if (currState->get()) { |
102 currState->get()->playbackClips(c); | 104 currState->get()->playbackClips(c); |
103 c->setMatrix(affineTransformToSkMatrix(currState->get()->transform())); | 105 c->setMatrix(affineTransformToSkMatrix(currState->get()->transform())); |
104 } | 106 } |
105 c->save(); | 107 c->save(); |
106 } | 108 } |
107 c->restore(); | 109 c->restore(); |
108 validateStateStack(); | 110 validateStateStack(); |
109 } | 111 } |
110 | 112 |
111 void BaseRenderingContext2D::unwindStateStack() { | 113 void BaseRenderingContext2D::unwindStateStack() { |
112 if (size_t stackSize = m_stateStack.size()) { | 114 if (size_t stackSize = m_stateStack.size()) { |
113 if (SkCanvas* skCanvas = existingDrawingCanvas()) { | 115 if (PaintCanvas* skCanvas = existingDrawingCanvas()) { |
114 while (--stackSize) | 116 while (--stackSize) |
115 skCanvas->restore(); | 117 skCanvas->restore(); |
116 } | 118 } |
117 } | 119 } |
118 } | 120 } |
119 | 121 |
120 void BaseRenderingContext2D::reset() { | 122 void BaseRenderingContext2D::reset() { |
121 validateStateStack(); | 123 validateStateStack(); |
122 unwindStateStack(); | 124 unwindStateStack(); |
123 m_stateStack.resize(1); | 125 m_stateStack.resize(1); |
124 m_stateStack.front() = CanvasRenderingContext2DState::create(); | 126 m_stateStack.front() = CanvasRenderingContext2DState::create(); |
125 m_path.clear(); | 127 m_path.clear(); |
126 if (SkCanvas* c = existingDrawingCanvas()) { | 128 if (PaintCanvas* c = existingDrawingCanvas()) { |
127 // The canvas should always have an initial/unbalanced save frame, which | 129 // The canvas should always have an initial/unbalanced save frame, which |
128 // we use to reset the top level matrix and clip here. | 130 // we use to reset the top level matrix and clip here. |
129 DCHECK_EQ(c->getSaveCount(), 2); | 131 DCHECK_EQ(c->getSaveCount(), 2); |
130 c->restore(); | 132 c->restore(); |
131 c->save(); | 133 c->save(); |
132 DCHECK(c->getTotalMatrix().isIdentity()); | 134 DCHECK(c->getTotalMatrix().isIdentity()); |
133 #if DCHECK_IS_ON() | 135 #if DCHECK_IS_ON() |
134 SkIRect clipBounds; | 136 SkIRect clipBounds; |
135 DCHECK(c->getDeviceClipBounds(&clipBounds)); | 137 DCHECK(c->getDeviceClipBounds(&clipBounds)); |
136 DCHECK(clipBounds == c->imageInfo().bounds()); | 138 DCHECK(clipBounds == c->imageInfo().bounds()); |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 } | 420 } |
419 | 421 |
420 void BaseRenderingContext2D::setCurrentTransform( | 422 void BaseRenderingContext2D::setCurrentTransform( |
421 SVGMatrixTearOff* matrixTearOff) { | 423 SVGMatrixTearOff* matrixTearOff) { |
422 const AffineTransform& transform = matrixTearOff->value(); | 424 const AffineTransform& transform = matrixTearOff->value(); |
423 setTransform(transform.a(), transform.b(), transform.c(), transform.d(), | 425 setTransform(transform.a(), transform.b(), transform.c(), transform.d(), |
424 transform.e(), transform.f()); | 426 transform.e(), transform.f()); |
425 } | 427 } |
426 | 428 |
427 void BaseRenderingContext2D::scale(double sx, double sy) { | 429 void BaseRenderingContext2D::scale(double sx, double sy) { |
428 SkCanvas* c = drawingCanvas(); | 430 PaintCanvas* c = drawingCanvas(); |
429 if (!c) | 431 if (!c) |
430 return; | 432 return; |
431 | 433 |
432 if (!std::isfinite(sx) || !std::isfinite(sy)) | 434 if (!std::isfinite(sx) || !std::isfinite(sy)) |
433 return; | 435 return; |
434 | 436 |
435 AffineTransform newTransform = state().transform(); | 437 AffineTransform newTransform = state().transform(); |
436 newTransform.scaleNonUniform(sx, sy); | 438 newTransform.scaleNonUniform(sx, sy); |
437 if (state().transform() == newTransform) | 439 if (state().transform() == newTransform) |
438 return; | 440 return; |
439 | 441 |
440 modifiableState().setTransform(newTransform); | 442 modifiableState().setTransform(newTransform); |
441 if (!state().isTransformInvertible()) | 443 if (!state().isTransformInvertible()) |
442 return; | 444 return; |
443 | 445 |
444 c->scale(sx, sy); | 446 c->scale(sx, sy); |
445 m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy)); | 447 m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy)); |
446 } | 448 } |
447 | 449 |
448 void BaseRenderingContext2D::rotate(double angleInRadians) { | 450 void BaseRenderingContext2D::rotate(double angleInRadians) { |
449 SkCanvas* c = drawingCanvas(); | 451 PaintCanvas* c = drawingCanvas(); |
450 if (!c) | 452 if (!c) |
451 return; | 453 return; |
452 | 454 |
453 if (!std::isfinite(angleInRadians)) | 455 if (!std::isfinite(angleInRadians)) |
454 return; | 456 return; |
455 | 457 |
456 AffineTransform newTransform = state().transform(); | 458 AffineTransform newTransform = state().transform(); |
457 newTransform.rotateRadians(angleInRadians); | 459 newTransform.rotateRadians(angleInRadians); |
458 if (state().transform() == newTransform) | 460 if (state().transform() == newTransform) |
459 return; | 461 return; |
460 | 462 |
461 modifiableState().setTransform(newTransform); | 463 modifiableState().setTransform(newTransform); |
462 if (!state().isTransformInvertible()) | 464 if (!state().isTransformInvertible()) |
463 return; | 465 return; |
464 c->rotate(angleInRadians * (180.0 / piFloat)); | 466 c->rotate(angleInRadians * (180.0 / piFloat)); |
465 m_path.transform(AffineTransform().rotateRadians(-angleInRadians)); | 467 m_path.transform(AffineTransform().rotateRadians(-angleInRadians)); |
466 } | 468 } |
467 | 469 |
468 void BaseRenderingContext2D::translate(double tx, double ty) { | 470 void BaseRenderingContext2D::translate(double tx, double ty) { |
469 SkCanvas* c = drawingCanvas(); | 471 PaintCanvas* c = drawingCanvas(); |
470 if (!c) | 472 if (!c) |
471 return; | 473 return; |
472 if (!state().isTransformInvertible()) | 474 if (!state().isTransformInvertible()) |
473 return; | 475 return; |
474 | 476 |
475 if (!std::isfinite(tx) || !std::isfinite(ty)) | 477 if (!std::isfinite(tx) || !std::isfinite(ty)) |
476 return; | 478 return; |
477 | 479 |
478 AffineTransform newTransform = state().transform(); | 480 AffineTransform newTransform = state().transform(); |
479 newTransform.translate(tx, ty); | 481 newTransform.translate(tx, ty); |
480 if (state().transform() == newTransform) | 482 if (state().transform() == newTransform) |
481 return; | 483 return; |
482 | 484 |
483 modifiableState().setTransform(newTransform); | 485 modifiableState().setTransform(newTransform); |
484 if (!state().isTransformInvertible()) | 486 if (!state().isTransformInvertible()) |
485 return; | 487 return; |
486 c->translate(tx, ty); | 488 c->translate(tx, ty); |
487 m_path.transform(AffineTransform().translate(-tx, -ty)); | 489 m_path.transform(AffineTransform().translate(-tx, -ty)); |
488 } | 490 } |
489 | 491 |
490 void BaseRenderingContext2D::transform(double m11, | 492 void BaseRenderingContext2D::transform(double m11, |
491 double m12, | 493 double m12, |
492 double m21, | 494 double m21, |
493 double m22, | 495 double m22, |
494 double dx, | 496 double dx, |
495 double dy) { | 497 double dy) { |
496 SkCanvas* c = drawingCanvas(); | 498 PaintCanvas* c = drawingCanvas(); |
497 if (!c) | 499 if (!c) |
498 return; | 500 return; |
499 | 501 |
500 if (!std::isfinite(m11) || !std::isfinite(m21) || !std::isfinite(dx) || | 502 if (!std::isfinite(m11) || !std::isfinite(m21) || !std::isfinite(dx) || |
501 !std::isfinite(m12) || !std::isfinite(m22) || !std::isfinite(dy)) | 503 !std::isfinite(m12) || !std::isfinite(m22) || !std::isfinite(dy)) |
502 return; | 504 return; |
503 | 505 |
504 AffineTransform transform(m11, m12, m21, m22, dx, dy); | 506 AffineTransform transform(m11, m12, m21, m22, dx, dy); |
505 AffineTransform newTransform = state().transform() * transform; | 507 AffineTransform newTransform = state().transform() * transform; |
506 if (state().transform() == newTransform) | 508 if (state().transform() == newTransform) |
507 return; | 509 return; |
508 | 510 |
509 modifiableState().setTransform(newTransform); | 511 modifiableState().setTransform(newTransform); |
510 if (!state().isTransformInvertible()) | 512 if (!state().isTransformInvertible()) |
511 return; | 513 return; |
512 | 514 |
513 c->concat(affineTransformToSkMatrix(transform)); | 515 c->concat(affineTransformToSkMatrix(transform)); |
514 m_path.transform(transform.inverse()); | 516 m_path.transform(transform.inverse()); |
515 } | 517 } |
516 | 518 |
517 void BaseRenderingContext2D::resetTransform() { | 519 void BaseRenderingContext2D::resetTransform() { |
518 SkCanvas* c = drawingCanvas(); | 520 PaintCanvas* c = drawingCanvas(); |
519 if (!c) | 521 if (!c) |
520 return; | 522 return; |
521 | 523 |
522 AffineTransform ctm = state().transform(); | 524 AffineTransform ctm = state().transform(); |
523 bool invertibleCTM = state().isTransformInvertible(); | 525 bool invertibleCTM = state().isTransformInvertible(); |
524 // It is possible that CTM is identity while CTM is not invertible. | 526 // It is possible that CTM is identity while CTM is not invertible. |
525 // When CTM becomes non-invertible, realizeSaves() can make CTM identity. | 527 // When CTM becomes non-invertible, realizeSaves() can make CTM identity. |
526 if (ctm.isIdentity() && invertibleCTM) | 528 if (ctm.isIdentity() && invertibleCTM) |
527 return; | 529 return; |
528 | 530 |
529 // resetTransform() resolves the non-invertible CTM state. | 531 // resetTransform() resolves the non-invertible CTM state. |
530 modifiableState().resetTransform(); | 532 modifiableState().resetTransform(); |
531 c->setMatrix(affineTransformToSkMatrix(baseTransform())); | 533 c->setMatrix(affineTransformToSkMatrix(baseTransform())); |
532 | 534 |
533 if (invertibleCTM) | 535 if (invertibleCTM) |
534 m_path.transform(ctm); | 536 m_path.transform(ctm); |
535 // When else, do nothing because all transform methods didn't update m_path | 537 // When else, do nothing because all transform methods didn't update m_path |
536 // when CTM became non-invertible. | 538 // when CTM became non-invertible. |
537 // It means that resetTransform() restores m_path just before CTM became | 539 // It means that resetTransform() restores m_path just before CTM became |
538 // non-invertible. | 540 // non-invertible. |
539 } | 541 } |
540 | 542 |
541 void BaseRenderingContext2D::setTransform(double m11, | 543 void BaseRenderingContext2D::setTransform(double m11, |
542 double m12, | 544 double m12, |
543 double m21, | 545 double m21, |
544 double m22, | 546 double m22, |
545 double dx, | 547 double dx, |
546 double dy) { | 548 double dy) { |
547 SkCanvas* c = drawingCanvas(); | 549 PaintCanvas* c = drawingCanvas(); |
548 if (!c) | 550 if (!c) |
549 return; | 551 return; |
550 | 552 |
551 if (!std::isfinite(m11) || !std::isfinite(m21) || !std::isfinite(dx) || | 553 if (!std::isfinite(m11) || !std::isfinite(m21) || !std::isfinite(dx) || |
552 !std::isfinite(m12) || !std::isfinite(m22) || !std::isfinite(dy)) | 554 !std::isfinite(m12) || !std::isfinite(m22) || !std::isfinite(dy)) |
553 return; | 555 return; |
554 | 556 |
555 resetTransform(); | 557 resetTransform(); |
556 transform(m11, m12, m21, m22, dx, dy); | 558 transform(m11, m12, m21, m22, dx, dy); |
557 } | 559 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 SkPath skPath = path.getSkPath(); | 617 SkPath skPath = path.getSkPath(); |
616 FloatRect bounds = path.boundingRect(); | 618 FloatRect bounds = path.boundingRect(); |
617 skPath.setFillType(fillType); | 619 skPath.setFillType(fillType); |
618 | 620 |
619 if (paintType == CanvasRenderingContext2DState::StrokePaintType) | 621 if (paintType == CanvasRenderingContext2DState::StrokePaintType) |
620 inflateStrokeRect(bounds); | 622 inflateStrokeRect(bounds); |
621 | 623 |
622 if (!drawingCanvas()) | 624 if (!drawingCanvas()) |
623 return; | 625 return; |
624 | 626 |
625 if (draw([&skPath](SkCanvas* c, const SkPaint* paint) // draw lambda | 627 if (draw([&skPath](PaintCanvas* c, const PaintFlags* paint) // draw lambda |
626 { c->drawPath(skPath, *paint); }, | 628 { c->drawPath(skPath, *paint); }, |
627 [](const SkIRect& rect) // overdraw test lambda | 629 [](const SkIRect& rect) // overdraw test lambda |
628 { return false; }, | 630 { return false; }, |
629 bounds, paintType)) { | 631 bounds, paintType)) { |
630 if (isPathExpensive(path)) { | 632 if (isPathExpensive(path)) { |
631 ImageBuffer* buffer = imageBuffer(); | 633 ImageBuffer* buffer = imageBuffer(); |
632 if (buffer) | 634 if (buffer) |
633 buffer->setHasExpensiveOp(); | 635 buffer->setHasExpensiveOp(); |
634 } | 636 } |
635 } | 637 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 double width, | 677 double width, |
676 double height) { | 678 double height) { |
677 trackDrawCall(FillRect, nullptr, width, height); | 679 trackDrawCall(FillRect, nullptr, width, height); |
678 if (!validateRectForCanvas(x, y, width, height)) | 680 if (!validateRectForCanvas(x, y, width, height)) |
679 return; | 681 return; |
680 | 682 |
681 if (!drawingCanvas()) | 683 if (!drawingCanvas()) |
682 return; | 684 return; |
683 | 685 |
684 SkRect rect = SkRect::MakeXYWH(x, y, width, height); | 686 SkRect rect = SkRect::MakeXYWH(x, y, width, height); |
685 draw([&rect](SkCanvas* c, const SkPaint* paint) // draw lambda | 687 draw([&rect](PaintCanvas* c, const PaintFlags* paint) // draw lambda |
686 { c->drawRect(rect, *paint); }, | 688 { c->drawRect(rect, *paint); }, |
687 [&rect, this](const SkIRect& clipBounds) // overdraw test lambda | 689 [&rect, this](const SkIRect& clipBounds) // overdraw test lambda |
688 { return rectContainsTransformedRect(rect, clipBounds); }, | 690 { return rectContainsTransformedRect(rect, clipBounds); }, |
689 rect, CanvasRenderingContext2DState::FillPaintType); | 691 rect, CanvasRenderingContext2DState::FillPaintType); |
690 } | 692 } |
691 | 693 |
692 static void strokeRectOnCanvas(const FloatRect& rect, | 694 static void strokeRectOnCanvas(const FloatRect& rect, |
693 SkCanvas* canvas, | 695 PaintCanvas* canvas, |
694 const SkPaint* paint) { | 696 const PaintFlags* paint) { |
695 ASSERT(paint->getStyle() == SkPaint::kStroke_Style); | 697 ASSERT(paint->getStyle() == SkPaint::kStroke_Style); |
696 if ((rect.width() > 0) != (rect.height() > 0)) { | 698 if ((rect.width() > 0) != (rect.height() > 0)) { |
697 // When stroking, we must skip the zero-dimension segments | 699 // When stroking, we must skip the zero-dimension segments |
698 SkPath path; | 700 SkPath path; |
699 path.moveTo(rect.x(), rect.y()); | 701 path.moveTo(rect.x(), rect.y()); |
700 path.lineTo(rect.maxX(), rect.maxY()); | 702 path.lineTo(rect.maxX(), rect.maxY()); |
701 path.close(); | 703 path.close(); |
702 canvas->drawPath(path, *paint); | 704 canvas->drawPath(path, *paint); |
703 return; | 705 return; |
704 } | 706 } |
705 canvas->drawRect(rect, *paint); | 707 canvas->drawRect(rect, *paint); |
706 } | 708 } |
707 | 709 |
708 void BaseRenderingContext2D::strokeRect(double x, | 710 void BaseRenderingContext2D::strokeRect(double x, |
709 double y, | 711 double y, |
710 double width, | 712 double width, |
711 double height) { | 713 double height) { |
712 trackDrawCall(StrokeRect, nullptr, width, height); | 714 trackDrawCall(StrokeRect, nullptr, width, height); |
713 if (!validateRectForCanvas(x, y, width, height)) | 715 if (!validateRectForCanvas(x, y, width, height)) |
714 return; | 716 return; |
715 | 717 |
716 if (!drawingCanvas()) | 718 if (!drawingCanvas()) |
717 return; | 719 return; |
718 | 720 |
719 SkRect rect = SkRect::MakeXYWH(x, y, width, height); | 721 SkRect rect = SkRect::MakeXYWH(x, y, width, height); |
720 FloatRect bounds = rect; | 722 FloatRect bounds = rect; |
721 inflateStrokeRect(bounds); | 723 inflateStrokeRect(bounds); |
722 draw([&rect](SkCanvas* c, const SkPaint* paint) // draw lambda | 724 draw([&rect](PaintCanvas* c, const PaintFlags* paint) // draw lambda |
723 { strokeRectOnCanvas(rect, c, paint); }, | 725 { strokeRectOnCanvas(rect, c, paint); }, |
724 [](const SkIRect& clipBounds) // overdraw test lambda | 726 [](const SkIRect& clipBounds) // overdraw test lambda |
725 { return false; }, | 727 { return false; }, |
726 bounds, CanvasRenderingContext2DState::StrokePaintType); | 728 bounds, CanvasRenderingContext2DState::StrokePaintType); |
727 } | 729 } |
728 | 730 |
729 void BaseRenderingContext2D::clipInternal(const Path& path, | 731 void BaseRenderingContext2D::clipInternal(const Path& path, |
730 const String& windingRuleString) { | 732 const String& windingRuleString) { |
731 SkCanvas* c = drawingCanvas(); | 733 PaintCanvas* c = drawingCanvas(); |
732 if (!c) { | 734 if (!c) { |
733 return; | 735 return; |
734 } | 736 } |
735 if (!state().isTransformInvertible()) { | 737 if (!state().isTransformInvertible()) { |
736 return; | 738 return; |
737 } | 739 } |
738 | 740 |
739 SkPath skPath = path.getSkPath(); | 741 SkPath skPath = path.getSkPath(); |
740 skPath.setFillType(parseWinding(windingRuleString)); | 742 skPath.setFillType(parseWinding(windingRuleString)); |
741 modifiableState().clipPath(skPath, m_clipAntialiasing); | 743 modifiableState().clipPath(skPath, m_clipAntialiasing); |
(...skipping 24 matching lines...) Expand all Loading... |
766 const double y, | 768 const double y, |
767 const String& windingRuleString) { | 769 const String& windingRuleString) { |
768 return isPointInPathInternal(domPath->path(), x, y, windingRuleString); | 770 return isPointInPathInternal(domPath->path(), x, y, windingRuleString); |
769 } | 771 } |
770 | 772 |
771 bool BaseRenderingContext2D::isPointInPathInternal( | 773 bool BaseRenderingContext2D::isPointInPathInternal( |
772 const Path& path, | 774 const Path& path, |
773 const double x, | 775 const double x, |
774 const double y, | 776 const double y, |
775 const String& windingRuleString) { | 777 const String& windingRuleString) { |
776 SkCanvas* c = drawingCanvas(); | 778 PaintCanvas* c = drawingCanvas(); |
777 if (!c) | 779 if (!c) |
778 return false; | 780 return false; |
779 if (!state().isTransformInvertible()) | 781 if (!state().isTransformInvertible()) |
780 return false; | 782 return false; |
781 | 783 |
782 FloatPoint point(x, y); | 784 FloatPoint point(x, y); |
783 if (!std::isfinite(point.x()) || !std::isfinite(point.y())) | 785 if (!std::isfinite(point.x()) || !std::isfinite(point.y())) |
784 return false; | 786 return false; |
785 AffineTransform ctm = state().transform(); | 787 AffineTransform ctm = state().transform(); |
786 FloatPoint transformedPoint = ctm.inverse().mapPoint(point); | 788 FloatPoint transformedPoint = ctm.inverse().mapPoint(point); |
787 | 789 |
788 return path.contains(transformedPoint, | 790 return path.contains(transformedPoint, |
789 SkFillTypeToWindRule(parseWinding(windingRuleString))); | 791 SkFillTypeToWindRule(parseWinding(windingRuleString))); |
790 } | 792 } |
791 | 793 |
792 bool BaseRenderingContext2D::isPointInStroke(const double x, const double y) { | 794 bool BaseRenderingContext2D::isPointInStroke(const double x, const double y) { |
793 return isPointInStrokeInternal(m_path, x, y); | 795 return isPointInStrokeInternal(m_path, x, y); |
794 } | 796 } |
795 | 797 |
796 bool BaseRenderingContext2D::isPointInStroke(Path2D* domPath, | 798 bool BaseRenderingContext2D::isPointInStroke(Path2D* domPath, |
797 const double x, | 799 const double x, |
798 const double y) { | 800 const double y) { |
799 return isPointInStrokeInternal(domPath->path(), x, y); | 801 return isPointInStrokeInternal(domPath->path(), x, y); |
800 } | 802 } |
801 | 803 |
802 bool BaseRenderingContext2D::isPointInStrokeInternal(const Path& path, | 804 bool BaseRenderingContext2D::isPointInStrokeInternal(const Path& path, |
803 const double x, | 805 const double x, |
804 const double y) { | 806 const double y) { |
805 SkCanvas* c = drawingCanvas(); | 807 PaintCanvas* c = drawingCanvas(); |
806 if (!c) | 808 if (!c) |
807 return false; | 809 return false; |
808 if (!state().isTransformInvertible()) | 810 if (!state().isTransformInvertible()) |
809 return false; | 811 return false; |
810 | 812 |
811 FloatPoint point(x, y); | 813 FloatPoint point(x, y); |
812 if (!std::isfinite(point.x()) || !std::isfinite(point.y())) | 814 if (!std::isfinite(point.x()) || !std::isfinite(point.y())) |
813 return false; | 815 return false; |
814 AffineTransform ctm = state().transform(); | 816 AffineTransform ctm = state().transform(); |
815 FloatPoint transformedPoint = ctm.inverse().mapPoint(point); | 817 FloatPoint transformedPoint = ctm.inverse().mapPoint(point); |
(...skipping 12 matching lines...) Expand all Loading... |
828 | 830 |
829 void BaseRenderingContext2D::clearRect(double x, | 831 void BaseRenderingContext2D::clearRect(double x, |
830 double y, | 832 double y, |
831 double width, | 833 double width, |
832 double height) { | 834 double height) { |
833 m_usageCounters.numClearRectCalls++; | 835 m_usageCounters.numClearRectCalls++; |
834 | 836 |
835 if (!validateRectForCanvas(x, y, width, height)) | 837 if (!validateRectForCanvas(x, y, width, height)) |
836 return; | 838 return; |
837 | 839 |
838 SkCanvas* c = drawingCanvas(); | 840 PaintCanvas* c = drawingCanvas(); |
839 if (!c) | 841 if (!c) |
840 return; | 842 return; |
841 if (!state().isTransformInvertible()) | 843 if (!state().isTransformInvertible()) |
842 return; | 844 return; |
843 | 845 |
844 SkIRect clipBounds; | 846 SkIRect clipBounds; |
845 if (!c->getDeviceClipBounds(&clipBounds)) | 847 if (!c->getDeviceClipBounds(&clipBounds)) |
846 return; | 848 return; |
847 | 849 |
848 SkPaint clearPaint; | 850 PaintFlags clearPaint; |
849 clearPaint.setBlendMode(SkBlendMode::kClear); | 851 clearPaint.setBlendMode(SkBlendMode::kClear); |
850 clearPaint.setStyle(SkPaint::kFill_Style); | 852 clearPaint.setStyle(PaintFlags::kFill_Style); |
851 FloatRect rect(x, y, width, height); | 853 FloatRect rect(x, y, width, height); |
852 | 854 |
853 if (rectContainsTransformedRect(rect, clipBounds)) { | 855 if (rectContainsTransformedRect(rect, clipBounds)) { |
854 checkOverdraw(rect, &clearPaint, CanvasRenderingContext2DState::NoImage, | 856 checkOverdraw(rect, &clearPaint, CanvasRenderingContext2DState::NoImage, |
855 ClipFill); | 857 ClipFill); |
856 if (drawingCanvas()) | 858 if (drawingCanvas()) |
857 drawingCanvas()->drawRect(rect, clearPaint); | 859 drawingCanvas()->drawRect(rect, clearPaint); |
858 didDraw(clipBounds); | 860 didDraw(clipBounds); |
859 } else { | 861 } else { |
860 SkIRect dirtyRect; | 862 SkIRect dirtyRect; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 if (!imageSourceInternal) | 991 if (!imageSourceInternal) |
990 return; | 992 return; |
991 drawImage(executionContext, imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, | 993 drawImage(executionContext, imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, |
992 dh, exceptionState); | 994 dh, exceptionState); |
993 } | 995 } |
994 | 996 |
995 bool BaseRenderingContext2D::shouldDrawImageAntialiased( | 997 bool BaseRenderingContext2D::shouldDrawImageAntialiased( |
996 const FloatRect& destRect) const { | 998 const FloatRect& destRect) const { |
997 if (!state().shouldAntialias()) | 999 if (!state().shouldAntialias()) |
998 return false; | 1000 return false; |
999 SkCanvas* c = drawingCanvas(); | 1001 PaintCanvas* c = drawingCanvas(); |
1000 ASSERT(c); | 1002 ASSERT(c); |
1001 | 1003 |
1002 const SkMatrix& ctm = c->getTotalMatrix(); | 1004 const SkMatrix& ctm = c->getTotalMatrix(); |
1003 // Don't disable anti-aliasing if we're rotated or skewed. | 1005 // Don't disable anti-aliasing if we're rotated or skewed. |
1004 if (!ctm.rectStaysRect()) | 1006 if (!ctm.rectStaysRect()) |
1005 return true; | 1007 return true; |
1006 // Check if the dimensions of the destination are "small" (less than one | 1008 // Check if the dimensions of the destination are "small" (less than one |
1007 // device pixel). To prevent sudden drop-outs. Since we know that | 1009 // device pixel). To prevent sudden drop-outs. Since we know that |
1008 // kRectStaysRect_Mask is set, the matrix either has scale and no skew or | 1010 // kRectStaysRect_Mask is set, the matrix either has scale and no skew or |
1009 // vice versa. We can query the kAffine_Mask flag to determine which case | 1011 // vice versa. We can query the kAffine_Mask flag to determine which case |
(...skipping 15 matching lines...) Expand all Loading... |
1025 static bool isDrawScalingDown(const FloatRect& srcRect, | 1027 static bool isDrawScalingDown(const FloatRect& srcRect, |
1026 const FloatRect& dstRect, | 1028 const FloatRect& dstRect, |
1027 float xScaleSquared, | 1029 float xScaleSquared, |
1028 float yScaleSquared) { | 1030 float yScaleSquared) { |
1029 return dstRect.width() * dstRect.width() * xScaleSquared < | 1031 return dstRect.width() * dstRect.width() * xScaleSquared < |
1030 srcRect.width() * srcRect.width() && | 1032 srcRect.width() * srcRect.width() && |
1031 dstRect.height() * dstRect.height() * yScaleSquared < | 1033 dstRect.height() * dstRect.height() * yScaleSquared < |
1032 srcRect.height() * srcRect.height(); | 1034 srcRect.height() * srcRect.height(); |
1033 } | 1035 } |
1034 | 1036 |
1035 void BaseRenderingContext2D::drawImageInternal(SkCanvas* c, | 1037 void BaseRenderingContext2D::drawImageInternal(PaintCanvas* c, |
1036 CanvasImageSource* imageSource, | 1038 CanvasImageSource* imageSource, |
1037 Image* image, | 1039 Image* image, |
1038 const FloatRect& srcRect, | 1040 const FloatRect& srcRect, |
1039 const FloatRect& dstRect, | 1041 const FloatRect& dstRect, |
1040 const SkPaint* paint) { | 1042 const PaintFlags* paint) { |
1041 if (imageSource->isSVGSource()) { | 1043 if (imageSource->isSVGSource()) { |
1042 trackDrawCall(DrawVectorImage, nullptr, dstRect.width(), dstRect.height()); | 1044 trackDrawCall(DrawVectorImage, nullptr, dstRect.width(), dstRect.height()); |
1043 } else { | 1045 } else { |
1044 trackDrawCall(DrawBitmapImage, nullptr, dstRect.width(), dstRect.height()); | 1046 trackDrawCall(DrawBitmapImage, nullptr, dstRect.width(), dstRect.height()); |
1045 } | 1047 } |
1046 | 1048 |
1047 int initialSaveCount = c->getSaveCount(); | 1049 int initialSaveCount = c->getSaveCount(); |
1048 SkPaint imagePaint = *paint; | 1050 PaintFlags imagePaint = *paint; |
1049 | 1051 |
1050 if (paint->getImageFilter()) { | 1052 if (paint->getImageFilter()) { |
1051 SkMatrix ctm = c->getTotalMatrix(); | 1053 SkMatrix ctm = c->getTotalMatrix(); |
1052 SkMatrix invCtm; | 1054 SkMatrix invCtm; |
1053 if (!ctm.invert(&invCtm)) { | 1055 if (!ctm.invert(&invCtm)) { |
1054 // There is an earlier check for invertibility, but the arithmetic | 1056 // There is an earlier check for invertibility, but the arithmetic |
1055 // in AffineTransform is not exactly identical, so it is possible | 1057 // in AffineTransform is not exactly identical, so it is possible |
1056 // for SkMatrix to find the transform to be non-invertible at this stage. | 1058 // for SkMatrix to find the transform to be non-invertible at this stage. |
1057 // crbug.com/504687 | 1059 // crbug.com/504687 |
1058 return; | 1060 return; |
1059 } | 1061 } |
1060 c->save(); | 1062 c->save(); |
1061 c->concat(invCtm); | 1063 c->concat(invCtm); |
1062 SkRect bounds = dstRect; | 1064 SkRect bounds = dstRect; |
1063 ctm.mapRect(&bounds); | 1065 ctm.mapRect(&bounds); |
1064 SkPaint layerPaint; | 1066 PaintFlags layerPaint; |
1065 layerPaint.setBlendMode(paint->getBlendMode()); | 1067 layerPaint.setBlendMode(paint->getBlendMode()); |
1066 layerPaint.setImageFilter(paint->refImageFilter()); | 1068 layerPaint.setImageFilter(paint->refImageFilter()); |
1067 | 1069 |
1068 c->saveLayer(&bounds, &layerPaint); | 1070 c->saveLayer(&bounds, &layerPaint); |
1069 c->concat(ctm); | 1071 c->concat(ctm); |
1070 imagePaint.setBlendMode(SkBlendMode::kSrcOver); | 1072 imagePaint.setBlendMode(SkBlendMode::kSrcOver); |
1071 imagePaint.setImageFilter(nullptr); | 1073 imagePaint.setImageFilter(nullptr); |
1072 } | 1074 } |
1073 | 1075 |
1074 if (!imageSmoothingEnabled() && | 1076 if (!imageSmoothingEnabled() && |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 1302 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
1301 CustomCountHistogram, scopedUsCounterOthersCPU, | 1303 CustomCountHistogram, scopedUsCounterOthersCPU, |
1302 new CustomCountHistogram("Blink.Canvas.DrawImage.Others.CPU", 0, | 1304 new CustomCountHistogram("Blink.Canvas.DrawImage.Others.CPU", 0, |
1303 10000000, 50)); | 1305 10000000, 50)); |
1304 timer.emplace(scopedUsCounterOthersCPU); | 1306 timer.emplace(scopedUsCounterOthersCPU); |
1305 } | 1307 } |
1306 } | 1308 } |
1307 | 1309 |
1308 draw( | 1310 draw( |
1309 [this, &imageSource, &image, &srcRect, dstRect]( | 1311 [this, &imageSource, &image, &srcRect, dstRect]( |
1310 SkCanvas* c, const SkPaint* paint) // draw lambda | 1312 PaintCanvas* c, const PaintFlags* paint) // draw lambda |
1311 { | 1313 { |
1312 drawImageInternal(c, imageSource, image.get(), srcRect, dstRect, paint); | 1314 drawImageInternal(c, imageSource, image.get(), srcRect, dstRect, paint); |
1313 }, | 1315 }, |
1314 [this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda | 1316 [this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda |
1315 { return rectContainsTransformedRect(dstRect, clipBounds); }, | 1317 { return rectContainsTransformedRect(dstRect, clipBounds); }, |
1316 dstRect, CanvasRenderingContext2DState::ImagePaintType, | 1318 dstRect, CanvasRenderingContext2DState::ImagePaintType, |
1317 imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage | 1319 imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage |
1318 : CanvasRenderingContext2DState::NonOpaqueImage); | 1320 : CanvasRenderingContext2DState::NonOpaqueImage); |
1319 | 1321 |
1320 validateStateStack(); | 1322 validateStateStack(); |
(...skipping 16 matching lines...) Expand all Loading... |
1337 } | 1339 } |
1338 | 1340 |
1339 if (originClean() && wouldTaintOrigin(imageSource, executionContext)) | 1341 if (originClean() && wouldTaintOrigin(imageSource, executionContext)) |
1340 setOriginTainted(); | 1342 setOriginTainted(); |
1341 } | 1343 } |
1342 | 1344 |
1343 void BaseRenderingContext2D::clearCanvas() { | 1345 void BaseRenderingContext2D::clearCanvas() { |
1344 FloatRect canvasRect(0, 0, width(), height()); | 1346 FloatRect canvasRect(0, 0, width(), height()); |
1345 checkOverdraw(canvasRect, 0, CanvasRenderingContext2DState::NoImage, | 1347 checkOverdraw(canvasRect, 0, CanvasRenderingContext2DState::NoImage, |
1346 ClipFill); | 1348 ClipFill); |
1347 SkCanvas* c = drawingCanvas(); | 1349 PaintCanvas* c = drawingCanvas(); |
1348 if (c) | 1350 if (c) |
1349 c->clear(hasAlpha() ? SK_ColorTRANSPARENT : SK_ColorBLACK); | 1351 c->clear(hasAlpha() ? SK_ColorTRANSPARENT : SK_ColorBLACK); |
1350 } | 1352 } |
1351 | 1353 |
1352 bool BaseRenderingContext2D::rectContainsTransformedRect( | 1354 bool BaseRenderingContext2D::rectContainsTransformedRect( |
1353 const FloatRect& rect, | 1355 const FloatRect& rect, |
1354 const SkIRect& transformedRect) const { | 1356 const SkIRect& transformedRect) const { |
1355 FloatQuad quad(rect); | 1357 FloatQuad quad(rect); |
1356 FloatQuad transformedQuad(FloatRect(transformedRect.x(), transformedRect.y(), | 1358 FloatQuad transformedQuad(FloatRect(transformedRect.x(), transformedRect.y(), |
1357 transformedRect.width(), | 1359 transformedRect.width(), |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1713 | 1715 |
1714 void BaseRenderingContext2D::setImageSmoothingQuality(const String& quality) { | 1716 void BaseRenderingContext2D::setImageSmoothingQuality(const String& quality) { |
1715 if (quality == state().imageSmoothingQuality()) | 1717 if (quality == state().imageSmoothingQuality()) |
1716 return; | 1718 return; |
1717 | 1719 |
1718 modifiableState().setImageSmoothingQuality(quality); | 1720 modifiableState().setImageSmoothingQuality(quality); |
1719 } | 1721 } |
1720 | 1722 |
1721 void BaseRenderingContext2D::checkOverdraw( | 1723 void BaseRenderingContext2D::checkOverdraw( |
1722 const SkRect& rect, | 1724 const SkRect& rect, |
1723 const SkPaint* paint, | 1725 const PaintFlags* paint, |
1724 CanvasRenderingContext2DState::ImageType imageType, | 1726 CanvasRenderingContext2DState::ImageType imageType, |
1725 DrawType drawType) { | 1727 DrawType drawType) { |
1726 SkCanvas* c = drawingCanvas(); | 1728 PaintCanvas* c = drawingCanvas(); |
1727 if (!c || !imageBuffer()->isRecording()) | 1729 if (!c || !imageBuffer()->isRecording()) |
1728 return; | 1730 return; |
1729 | 1731 |
1730 SkRect deviceRect; | 1732 SkRect deviceRect; |
1731 if (drawType == UntransformedUnclippedFill) { | 1733 if (drawType == UntransformedUnclippedFill) { |
1732 deviceRect = rect; | 1734 deviceRect = rect; |
1733 } else { | 1735 } else { |
1734 ASSERT(drawType == ClipFill); | 1736 ASSERT(drawType == ClipFill); |
1735 if (state().hasComplexClip()) | 1737 if (state().hasComplexClip()) |
1736 return; | 1738 return; |
(...skipping 18 matching lines...) Expand all Loading... |
1755 SkBlendMode mode = paint->getBlendMode(); | 1757 SkBlendMode mode = paint->getBlendMode(); |
1756 isSourceOver = mode == SkBlendMode::kSrcOver; | 1758 isSourceOver = mode == SkBlendMode::kSrcOver; |
1757 if (!isSourceOver && mode != SkBlendMode::kSrc && | 1759 if (!isSourceOver && mode != SkBlendMode::kSrc && |
1758 mode != SkBlendMode::kClear) | 1760 mode != SkBlendMode::kClear) |
1759 return; // The code below only knows how to handle Src, SrcOver, and | 1761 return; // The code below only knows how to handle Src, SrcOver, and |
1760 // Clear | 1762 // Clear |
1761 | 1763 |
1762 alpha = paint->getAlpha(); | 1764 alpha = paint->getAlpha(); |
1763 | 1765 |
1764 if (isSourceOver && imageType == CanvasRenderingContext2DState::NoImage) { | 1766 if (isSourceOver && imageType == CanvasRenderingContext2DState::NoImage) { |
1765 SkShader* shader = paint->getShader(); | 1767 PaintShader* shader = paint->getShader(); |
1766 if (shader) { | 1768 if (shader) { |
1767 if (shader->isOpaque() && alpha == 0xFF) | 1769 if (shader->isOpaque() && alpha == 0xFF) |
1768 imageBuffer()->willOverwriteCanvas(); | 1770 imageBuffer()->willOverwriteCanvas(); |
1769 return; | 1771 return; |
1770 } | 1772 } |
1771 } | 1773 } |
1772 } | 1774 } |
1773 | 1775 |
1774 if (isSourceOver) { | 1776 if (isSourceOver) { |
1775 // With source over, we need to certify that alpha == 0xFF for all pixels | 1777 // With source over, we need to certify that alpha == 0xFF for all pixels |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2017 ExpensiveCanvasHeuristicParameters::ShadowFixedCost[index] * | 2019 ExpensiveCanvasHeuristicParameters::ShadowFixedCost[index] * |
2018 m_usageCounters.numBlurredShadows + | 2020 m_usageCounters.numBlurredShadows + |
2019 ExpensiveCanvasHeuristicParameters:: | 2021 ExpensiveCanvasHeuristicParameters:: |
2020 ShadowVariableCostPerAreaTimesShadowBlurSquared[index] * | 2022 ShadowVariableCostPerAreaTimesShadowBlurSquared[index] * |
2021 m_usageCounters.boundingBoxAreaTimesShadowBlurSquared; | 2023 m_usageCounters.boundingBoxAreaTimesShadowBlurSquared; |
2022 | 2024 |
2023 return basicCostOfDrawCalls + fillTypeAdjustment + shadowAdjustment; | 2025 return basicCostOfDrawCalls + fillTypeAdjustment + shadowAdjustment; |
2024 } | 2026 } |
2025 | 2027 |
2026 } // namespace blink | 2028 } // namespace blink |
OLD | NEW |