OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. |
3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) |
4 * Copyright (C) 2007 Alp Toker <alp@atoker.com> | 4 * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | 5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> |
6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> | 6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> |
7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved. | 8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved. |
9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. | 9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. |
10 * | 10 * |
(...skipping 861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
872 c->saveLayer(nullptr, &compositePaint); | 872 c->saveLayer(nullptr, &compositePaint); |
873 SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroundOnly, i mageType); | 873 SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroundOnly, i mageType); |
874 foregroundPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | 874 foregroundPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); |
875 c->setMatrix(ctm); | 875 c->setMatrix(ctm); |
876 drawFunc(c, &foregroundPaint); | 876 drawFunc(c, &foregroundPaint); |
877 c->restore(); | 877 c->restore(); |
878 c->setMatrix(ctm); | 878 c->setMatrix(ctm); |
879 } | 879 } |
880 | 880 |
881 template<typename DrawFunc, typename ContainsFunc> | 881 template<typename DrawFunc, typename ContainsFunc> |
882 bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc & drawCoversClipBounds, CanvasDeferralMode deferralMode, const SkRect& bounds, C anvasRenderingContext2DState::PaintType paintType, CanvasRenderingContext2DState ::ImageType imageType) | 882 bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc & drawCoversClipBounds, const SkRect& bounds, CanvasRenderingContext2DState::Pai ntType paintType, CanvasRenderingContext2DState::ImageType imageType) |
883 { | 883 { |
884 if (!state().isTransformInvertible()) | 884 if (!state().isTransformInvertible()) |
885 return false; | 885 return false; |
886 | 886 |
887 SkIRect clipBounds; | 887 SkIRect clipBounds; |
888 // Deliberately not using 'deferralMode' in the call to drawingCanvas below because | |
889 // a) The call does not write anything so we do not care about the write mod e here | |
890 // b) We want to avoid flushing before the call to checkOverdraw (below), ot herwise | |
891 // we could be supressing an overdraw optimization. | |
892 if (!drawingCanvas()->getClipDeviceBounds(&clipBounds)) | 888 if (!drawingCanvas()->getClipDeviceBounds(&clipBounds)) |
893 return false; | 889 return false; |
894 | 890 |
895 // If gradient size is zero, then paint nothing. | 891 // If gradient size is zero, then paint nothing. |
896 CanvasStyle* style = state().style(paintType); | 892 CanvasStyle* style = state().style(paintType); |
897 if (style) { | 893 if (style) { |
898 CanvasGradient* gradient = style->canvasGradient(); | 894 CanvasGradient* gradient = style->canvasGradient(); |
899 if (gradient && gradient->gradient()->isZeroSize()) | 895 if (gradient && gradient->gradient()->isZeroSize()) |
900 return false; | 896 return false; |
901 } | 897 } |
902 | 898 |
903 if (isFullCanvasCompositeMode(state().globalComposite()) || state().hasFilte r()) { | 899 if (isFullCanvasCompositeMode(state().globalComposite()) || state().hasFilte r()) { |
904 compositedDraw(drawFunc, drawingCanvas(deferralMode), paintType, imageTy pe); | 900 compositedDraw(drawFunc, drawingCanvas(), paintType, imageType); |
905 didDraw(clipBounds); | 901 didDraw(clipBounds); |
906 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) { | 902 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) { |
907 clearCanvas(); // takes care of checkOvewrdraw() | 903 clearCanvas(); // takes care of checkOvewrdraw() |
908 const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, i mageType); | 904 const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, i mageType); |
909 drawFunc(drawingCanvas(deferralMode), paint); | 905 drawFunc(drawingCanvas(), paint); |
910 didDraw(clipBounds); | 906 didDraw(clipBounds); |
911 } else { | 907 } else { |
912 SkIRect dirtyRect; | 908 SkIRect dirtyRect; |
913 if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { | 909 if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { |
914 const SkPaint* paint = state().getPaint(paintType, DrawShadowAndFore ground, imageType); | 910 const SkPaint* paint = state().getPaint(paintType, DrawShadowAndFore ground, imageType); |
915 if (paintType != CanvasRenderingContext2DState::StrokePaintType && d rawCoversClipBounds(clipBounds)) | 911 if (paintType != CanvasRenderingContext2DState::StrokePaintType && d rawCoversClipBounds(clipBounds)) |
916 checkOverdraw(bounds, paint, imageType, ClipFill); | 912 checkOverdraw(bounds, paint, imageType, ClipFill); |
917 drawFunc(drawingCanvas(deferralMode), paint); | 913 drawFunc(drawingCanvas(), paint); |
918 didDraw(dirtyRect); | 914 didDraw(dirtyRect); |
919 } | 915 } |
920 } | 916 } |
921 return true; | 917 return true; |
922 } | 918 } |
923 | 919 |
924 static bool isPathExpensive(const Path& path) | 920 static bool isPathExpensive(const Path& path) |
925 { | 921 { |
926 const SkPath& skPath = path.skPath(); | 922 const SkPath& skPath = path.skPath(); |
927 if (ExpensiveCanvasHeuristicParameters::ConcavePathsAreExpensive && !skPath. isConvex()) | 923 if (ExpensiveCanvasHeuristicParameters::ConcavePathsAreExpensive && !skPath. isConvex()) |
(...skipping 21 matching lines...) Expand all Loading... | |
949 return; | 945 return; |
950 | 946 |
951 if (draw( | 947 if (draw( |
952 [&skPath, this](SkCanvas* c, const SkPaint* paint) // draw lambda | 948 [&skPath, this](SkCanvas* c, const SkPaint* paint) // draw lambda |
953 { | 949 { |
954 c->drawPath(skPath, *paint); | 950 c->drawPath(skPath, *paint); |
955 }, | 951 }, |
956 [](const SkIRect& rect) // overdraw test lambda | 952 [](const SkIRect& rect) // overdraw test lambda |
957 { | 953 { |
958 return false; | 954 return false; |
959 }, AllowDeferredCanvas, bounds, paintType)) { | 955 }, bounds, paintType)) { |
960 if (isPathExpensive(path)) { | 956 if (isPathExpensive(path)) { |
961 ImageBuffer* buffer = canvas()->buffer(); | 957 ImageBuffer* buffer = canvas()->buffer(); |
962 if (buffer) | 958 if (buffer) |
963 buffer->setHasExpensiveOp(); | 959 buffer->setHasExpensiveOp(); |
964 } | 960 } |
965 } | 961 } |
966 } | 962 } |
967 | 963 |
968 static SkPath::FillType parseWinding(const String& windingRuleString) | 964 static SkPath::FillType parseWinding(const String& windingRuleString) |
969 { | 965 { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1006 | 1002 |
1007 SkRect rect = SkRect::MakeXYWH(x, y, width, height); | 1003 SkRect rect = SkRect::MakeXYWH(x, y, width, height); |
1008 draw( | 1004 draw( |
1009 [&rect, this](SkCanvas* c, const SkPaint* paint) // draw lambda | 1005 [&rect, this](SkCanvas* c, const SkPaint* paint) // draw lambda |
1010 { | 1006 { |
1011 c->drawRect(rect, *paint); | 1007 c->drawRect(rect, *paint); |
1012 }, | 1008 }, |
1013 [&rect, this](const SkIRect& clipBounds) // overdraw test lambda | 1009 [&rect, this](const SkIRect& clipBounds) // overdraw test lambda |
1014 { | 1010 { |
1015 return rectContainsTransformedRect(rect, clipBounds); | 1011 return rectContainsTransformedRect(rect, clipBounds); |
1016 }, AllowDeferredCanvas, rect, CanvasRenderingContext2DState::FillPaintTy pe); | 1012 }, rect, CanvasRenderingContext2DState::FillPaintType); |
1017 } | 1013 } |
1018 | 1014 |
1019 static void strokeRectOnCanvas(const FloatRect& rect, SkCanvas* canvas, const Sk Paint* paint) | 1015 static void strokeRectOnCanvas(const FloatRect& rect, SkCanvas* canvas, const Sk Paint* paint) |
1020 { | 1016 { |
1021 ASSERT(paint->getStyle() == SkPaint::kStroke_Style); | 1017 ASSERT(paint->getStyle() == SkPaint::kStroke_Style); |
1022 if ((rect.width() > 0) != (rect.height() > 0)) { | 1018 if ((rect.width() > 0) != (rect.height() > 0)) { |
1023 // When stroking, we must skip the zero-dimension segments | 1019 // When stroking, we must skip the zero-dimension segments |
1024 SkPath path; | 1020 SkPath path; |
1025 path.moveTo(rect.x(), rect.y()); | 1021 path.moveTo(rect.x(), rect.y()); |
1026 path.lineTo(rect.maxX(), rect.maxY()); | 1022 path.lineTo(rect.maxX(), rect.maxY()); |
(...skipping 16 matching lines...) Expand all Loading... | |
1043 FloatRect bounds = rect; | 1039 FloatRect bounds = rect; |
1044 inflateStrokeRect(bounds); | 1040 inflateStrokeRect(bounds); |
1045 draw( | 1041 draw( |
1046 [&rect, this](SkCanvas* c, const SkPaint* paint) // draw lambda | 1042 [&rect, this](SkCanvas* c, const SkPaint* paint) // draw lambda |
1047 { | 1043 { |
1048 strokeRectOnCanvas(rect, c, paint); | 1044 strokeRectOnCanvas(rect, c, paint); |
1049 }, | 1045 }, |
1050 [](const SkIRect& clipBounds) // overdraw test lambda | 1046 [](const SkIRect& clipBounds) // overdraw test lambda |
1051 { | 1047 { |
1052 return false; | 1048 return false; |
1053 }, AllowDeferredCanvas, bounds, CanvasRenderingContext2DState::StrokePai ntType); | 1049 }, bounds, CanvasRenderingContext2DState::StrokePaintType); |
1054 } | 1050 } |
1055 | 1051 |
1056 void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind ingRuleString) | 1052 void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind ingRuleString) |
1057 { | 1053 { |
1058 SkCanvas* c = drawingCanvas(); | 1054 SkCanvas* c = drawingCanvas(); |
1059 if (!c) { | 1055 if (!c) { |
1060 return; | 1056 return; |
1061 } | 1057 } |
1062 if (!state().isTransformInvertible()) { | 1058 if (!state().isTransformInvertible()) { |
1063 return; | 1059 return; |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1385 FloatRect srcRect = normalizeRect(FloatRect(sx, sy, sw, sh)); | 1381 FloatRect srcRect = normalizeRect(FloatRect(sx, sy, sw, sh)); |
1386 FloatRect dstRect = normalizeRect(FloatRect(dx, dy, dw, dh)); | 1382 FloatRect dstRect = normalizeRect(FloatRect(dx, dy, dw, dh)); |
1387 | 1383 |
1388 clipRectsToImageRect(FloatRect(FloatPoint(), imageSource->elementSize()), &s rcRect, &dstRect); | 1384 clipRectsToImageRect(FloatRect(FloatPoint(), imageSource->elementSize()), &s rcRect, &dstRect); |
1389 | 1385 |
1390 imageSource->adjustDrawRects(&srcRect, &dstRect); | 1386 imageSource->adjustDrawRects(&srcRect, &dstRect); |
1391 | 1387 |
1392 if (srcRect.isEmpty()) | 1388 if (srcRect.isEmpty()) |
1393 return; | 1389 return; |
1394 | 1390 |
1395 CanvasDeferralMode deferralMode = imageSource->isVideoElement() ? ForceImmed iateCanvas : AllowDeferredCanvas; | 1391 // FIXME: crbug.com/447218 |
Stephen White
2015/08/14 15:10:48
Nit: this bug is marked as fixed. Also, it's about
| |
1392 // We make the destination canvas fall out of display list mode by forcing | |
1393 // immediate rendering. This is to prevent run-away memory consumption cause d by SkSurface | |
1394 // copyOnWrite when the source canvas is animated and consumed at a rate hig her than the | |
1395 // presentation frame rate of the destination canvas. | |
1396 if (imageSource->isVideoElement() || imageSource->isCanvasElement()) | |
1397 canvas()->disableDeferral(); | |
1396 | 1398 |
1397 validateStateStack(); | 1399 validateStateStack(); |
1398 | 1400 |
1399 draw( | 1401 draw( |
1400 [this, &imageSource, &image, &srcRect, dstRect](SkCanvas* c, const SkPai nt* paint) // draw lambda | 1402 [this, &imageSource, &image, &srcRect, dstRect](SkCanvas* c, const SkPai nt* paint) // draw lambda |
1401 { | 1403 { |
1402 drawImageInternal(c, imageSource, image.get(), srcRect, dstRect, pai nt); | 1404 drawImageInternal(c, imageSource, image.get(), srcRect, dstRect, pai nt); |
1403 }, | 1405 }, |
1404 [this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda | 1406 [this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda |
1405 { | 1407 { |
1406 return rectContainsTransformedRect(dstRect, clipBounds); | 1408 return rectContainsTransformedRect(dstRect, clipBounds); |
1407 }, deferralMode, dstRect, CanvasRenderingContext2DState::ImagePaintType, | 1409 }, dstRect, CanvasRenderingContext2DState::ImagePaintType, |
1408 imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage : C anvasRenderingContext2DState::NonOpaqueImage); | 1410 imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage : C anvasRenderingContext2DState::NonOpaqueImage); |
1409 | 1411 |
1410 validateStateStack(); | 1412 validateStateStack(); |
1411 | 1413 |
1412 bool isExpensive = false; | 1414 bool isExpensive = false; |
1413 | 1415 |
1414 if (ExpensiveCanvasHeuristicParameters::SVGImageSourcesAreExpensive && image && image->isSVGImage()) | 1416 if (ExpensiveCanvasHeuristicParameters::SVGImageSourcesAreExpensive && image && image->isSVGImage()) |
1415 isExpensive = true; | 1417 isExpensive = true; |
1416 | 1418 |
1417 if (imageSource->elementSize().width() * imageSource->elementSize().height() > canvas()->width() * canvas()->height() * ExpensiveCanvasHeuristicParameters:: ExpensiveImageSizeRatio) | 1419 if (imageSource->elementSize().width() * imageSource->elementSize().height() > canvas()->width() * canvas()->height() * ExpensiveCanvasHeuristicParameters:: ExpensiveImageSizeRatio) |
1418 isExpensive = true; | 1420 isExpensive = true; |
1419 | 1421 |
1420 if (isExpensive) { | 1422 if (isExpensive) { |
1421 ImageBuffer* buffer = canvas()->buffer(); | 1423 ImageBuffer* buffer = canvas()->buffer(); |
1422 if (buffer) | 1424 if (buffer) |
1423 buffer->setHasExpensiveOp(); | 1425 buffer->setHasExpensiveOp(); |
1424 } | 1426 } |
1425 | 1427 |
1426 if (imageSource->isCanvasElement()) { | 1428 if (imageSource->isCanvasElement() && static_cast<HTMLCanvasElement*>(imageS ource)->is3D()) { |
1427 if (static_cast<HTMLCanvasElement*>(imageSource)->is3D()) { | 1429 // WebGL to 2D canvas: must flush graphics context to prevent a race |
1428 // WebGL to 2D canvas: must flush graphics context to prevent a race | 1430 // FIXME: crbug.com/516331 Fix the underlying synchronization issue so t his flush can be eliminated. |
1429 // FIXME: crbug.com/516331 Fix the underlying synchronization issue so this flush can be eliminated. | 1431 canvas()->buffer()->flushGpu(); |
1430 canvas()->buffer()->flushGpu(); | |
1431 } else { | |
1432 // FIXME: crbug.com/447218 | |
1433 // We make the destination canvas fall out of display list mode by c alling | |
1434 // flush. This is to prevent run-away memory consumption caused by S kSurface | |
1435 // copyOnWrite when the source canvas is animated and consumed at a rate higher than the | |
1436 // presentation frame rate of the destination canvas. | |
1437 canvas()->buffer()->flush(); | |
1438 } | |
1439 } | 1432 } |
1440 | 1433 |
1441 if (canvas()->originClean() && wouldTaintOrigin(imageSource)) | 1434 if (canvas()->originClean() && wouldTaintOrigin(imageSource)) |
1442 canvas()->setOriginTainted(); | 1435 canvas()->setOriginTainted(); |
1443 } | 1436 } |
1444 | 1437 |
1445 void CanvasRenderingContext2D::clearCanvas() | 1438 void CanvasRenderingContext2D::clearCanvas() |
1446 { | 1439 { |
1447 FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); | 1440 FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); |
1448 checkOverdraw(canvasRect, 0, CanvasRenderingContext2DState::NoImage, ClipFil l); | 1441 checkOverdraw(canvasRect, 0, CanvasRenderingContext2DState::NoImage, ClipFil l); |
1449 if (drawingCanvas()) | 1442 SkCanvas* c = drawingCanvas(); |
1450 drawingCanvas()->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK) ; | 1443 if (c) |
1444 c->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); | |
1451 } | 1445 } |
1452 | 1446 |
1453 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const SkIRect& transformedRect) const | 1447 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const SkIRect& transformedRect) const |
1454 { | 1448 { |
1455 FloatQuad quad(rect); | 1449 FloatQuad quad(rect); |
1456 FloatQuad transformedQuad(FloatRect(transformedRect.x(), transformedRect.y() , transformedRect.width(), transformedRect.height())); | 1450 FloatQuad transformedQuad(FloatRect(transformedRect.x(), transformedRect.y() , transformedRect.width(), transformedRect.height())); |
1457 return state().transform().mapQuad(quad).containsQuad(transformedQuad); | 1451 return state().transform().mapQuad(quad).containsQuad(transformedQuad); |
1458 } | 1452 } |
1459 | 1453 |
1460 CanvasGradient* CanvasRenderingContext2D::createLinearGradient(float x0, float y 0, float x1, float y1) | 1454 CanvasGradient* CanvasRenderingContext2D::createLinearGradient(float x0, float y 0, float x1, float y1) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1546 | 1540 |
1547 if (ExpensiveCanvasHeuristicParameters::BlurredShadowsAreExpensive && state( ).shouldDrawShadows() && state().shadowBlur() > 0) { | 1541 if (ExpensiveCanvasHeuristicParameters::BlurredShadowsAreExpensive && state( ).shouldDrawShadows() && state().shadowBlur() > 0) { |
1548 ImageBuffer* buffer = canvas()->buffer(); | 1542 ImageBuffer* buffer = canvas()->buffer(); |
1549 if (buffer) | 1543 if (buffer) |
1550 buffer->setHasExpensiveOp(); | 1544 buffer->setHasExpensiveOp(); |
1551 } | 1545 } |
1552 | 1546 |
1553 canvas()->didDraw(SkRect::Make(dirtyRect)); | 1547 canvas()->didDraw(SkRect::Make(dirtyRect)); |
1554 } | 1548 } |
1555 | 1549 |
1556 SkCanvas* CanvasRenderingContext2D::drawingCanvas(CanvasDeferralMode deferralMod e) const | 1550 SkCanvas* CanvasRenderingContext2D::drawingCanvas() const |
1557 { | 1551 { |
1558 if (isContextLost()) | 1552 if (isContextLost()) |
1559 return nullptr; | 1553 return nullptr; |
1560 return deferralMode == ForceImmediateCanvas ? canvas()->immediateDrawingCanv as() : canvas()->drawingCanvas(); | 1554 return canvas()->drawingCanvas(); |
1561 } | 1555 } |
1562 | 1556 |
1563 ImageData* CanvasRenderingContext2D::createImageData(ImageData* imageData) const | 1557 ImageData* CanvasRenderingContext2D::createImageData(ImageData* imageData) const |
1564 { | 1558 { |
1565 return ImageData::create(imageData->size()); | 1559 return ImageData::create(imageData->size()); |
1566 } | 1560 } |
1567 | 1561 |
1568 ImageData* CanvasRenderingContext2D::createImageData(float sw, float sh, Excepti onState& exceptionState) const | 1562 ImageData* CanvasRenderingContext2D::createImageData(float sw, float sh, Excepti onState& exceptionState) const |
1569 { | 1563 { |
1570 if (!sw || !sh) { | 1564 if (!sw || !sh) { |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2013 | 2007 |
2014 draw( | 2008 draw( |
2015 [&font, this, &textRunPaintInfo, &location](SkCanvas* c, const SkPaint* paint) // draw lambda | 2009 [&font, this, &textRunPaintInfo, &location](SkCanvas* c, const SkPaint* paint) // draw lambda |
2016 { | 2010 { |
2017 font.drawBidiText(c, textRunPaintInfo, location, Font::UseFallbackIf FontNotReady, cDeviceScaleFactor, *paint); | 2011 font.drawBidiText(c, textRunPaintInfo, location, Font::UseFallbackIf FontNotReady, cDeviceScaleFactor, *paint); |
2018 }, | 2012 }, |
2019 [](const SkIRect& rect) // overdraw test lambda | 2013 [](const SkIRect& rect) // overdraw test lambda |
2020 { | 2014 { |
2021 return false; | 2015 return false; |
2022 }, | 2016 }, |
2023 AllowDeferredCanvas, textRunPaintInfo.bounds, paintType); | 2017 textRunPaintInfo.bounds, paintType); |
2024 } | 2018 } |
2025 | 2019 |
2026 void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const | 2020 void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const |
2027 { | 2021 { |
2028 // Fast approximation of the stroke's bounding rect. | 2022 // Fast approximation of the stroke's bounding rect. |
2029 // This yields a slightly oversized rect but is very fast | 2023 // This yields a slightly oversized rect but is very fast |
2030 // compared to Path::strokeBoundingRect(). | 2024 // compared to Path::strokeBoundingRect(). |
2031 static const float root2 = sqrtf(2); | 2025 static const float root2 = sqrtf(2); |
2032 float delta = state().lineWidth() / 2; | 2026 float delta = state().lineWidth() / 2; |
2033 if (state().lineJoin() == MiterJoin) | 2027 if (state().lineJoin() == MiterJoin) |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2317 if (imageType == CanvasRenderingContext2DState::NonOpaqueImage) | 2311 if (imageType == CanvasRenderingContext2DState::NonOpaqueImage) |
2318 return; | 2312 return; |
2319 if (alpha < 0xFF) | 2313 if (alpha < 0xFF) |
2320 return; | 2314 return; |
2321 } | 2315 } |
2322 | 2316 |
2323 canvas()->buffer()->willOverwriteCanvas(); | 2317 canvas()->buffer()->willOverwriteCanvas(); |
2324 } | 2318 } |
2325 | 2319 |
2326 } // namespace blink | 2320 } // namespace blink |
OLD | NEW |