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 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 , m_globalComposite(SkXfermode::kSrcOver_Mode) | 276 , m_globalComposite(SkXfermode::kSrcOver_Mode) |
277 , m_invertibleCTM(true) | 277 , m_invertibleCTM(true) |
278 , m_lineDashOffset(0) | 278 , m_lineDashOffset(0) |
279 , m_imageSmoothingEnabled(true) | 279 , m_imageSmoothingEnabled(true) |
280 , m_textAlign(StartTextAlign) | 280 , m_textAlign(StartTextAlign) |
281 , m_textBaseline(AlphabeticTextBaseline) | 281 , m_textBaseline(AlphabeticTextBaseline) |
282 , m_direction(DirectionInherit) | 282 , m_direction(DirectionInherit) |
283 , m_unparsedFont(defaultFont) | 283 , m_unparsedFont(defaultFont) |
284 , m_realizedFont(false) | 284 , m_realizedFont(false) |
285 , m_hasClip(false) | 285 , m_hasClip(false) |
286 , m_hasComplexClip(false) | |
286 { | 287 { |
287 } | 288 } |
288 | 289 |
289 CanvasRenderingContext2D::State::State(const State& other, ClipListCopyMode mode ) | 290 CanvasRenderingContext2D::State::State(const State& other, ClipListCopyMode mode ) |
290 : CSSFontSelectorClient() | 291 : CSSFontSelectorClient() |
291 , m_unrealizedSaveCount(other.m_unrealizedSaveCount) | 292 , m_unrealizedSaveCount(other.m_unrealizedSaveCount) |
292 , m_unparsedStrokeColor(other.m_unparsedStrokeColor) | 293 , m_unparsedStrokeColor(other.m_unparsedStrokeColor) |
293 , m_unparsedFillColor(other.m_unparsedFillColor) | 294 , m_unparsedFillColor(other.m_unparsedFillColor) |
294 , m_strokeStyle(other.m_strokeStyle) | 295 , m_strokeStyle(other.m_strokeStyle) |
295 , m_fillStyle(other.m_fillStyle) | 296 , m_fillStyle(other.m_fillStyle) |
(...skipping 10 matching lines...) Expand all Loading... | |
306 , m_invertibleCTM(other.m_invertibleCTM) | 307 , m_invertibleCTM(other.m_invertibleCTM) |
307 , m_lineDashOffset(other.m_lineDashOffset) | 308 , m_lineDashOffset(other.m_lineDashOffset) |
308 , m_imageSmoothingEnabled(other.m_imageSmoothingEnabled) | 309 , m_imageSmoothingEnabled(other.m_imageSmoothingEnabled) |
309 , m_textAlign(other.m_textAlign) | 310 , m_textAlign(other.m_textAlign) |
310 , m_textBaseline(other.m_textBaseline) | 311 , m_textBaseline(other.m_textBaseline) |
311 , m_direction(other.m_direction) | 312 , m_direction(other.m_direction) |
312 , m_unparsedFont(other.m_unparsedFont) | 313 , m_unparsedFont(other.m_unparsedFont) |
313 , m_font(other.m_font) | 314 , m_font(other.m_font) |
314 , m_realizedFont(other.m_realizedFont) | 315 , m_realizedFont(other.m_realizedFont) |
315 , m_hasClip(other.m_hasClip) | 316 , m_hasClip(other.m_hasClip) |
317 , m_hasComplexClip(other.m_hasComplexClip) | |
316 { | 318 { |
317 if (mode == CopyClipList) { | 319 if (mode == CopyClipList) { |
318 m_clipList = other.m_clipList; | 320 m_clipList = other.m_clipList; |
319 } | 321 } |
320 if (m_realizedFont) | 322 if (m_realizedFont) |
321 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); | 323 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); |
322 } | 324 } |
323 | 325 |
324 CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons t State& other) | 326 CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons t State& other) |
325 { | 327 { |
(...skipping 22 matching lines...) Expand all Loading... | |
348 m_transform = other.m_transform; | 350 m_transform = other.m_transform; |
349 m_invertibleCTM = other.m_invertibleCTM; | 351 m_invertibleCTM = other.m_invertibleCTM; |
350 m_imageSmoothingEnabled = other.m_imageSmoothingEnabled; | 352 m_imageSmoothingEnabled = other.m_imageSmoothingEnabled; |
351 m_textAlign = other.m_textAlign; | 353 m_textAlign = other.m_textAlign; |
352 m_textBaseline = other.m_textBaseline; | 354 m_textBaseline = other.m_textBaseline; |
353 m_direction = other.m_direction; | 355 m_direction = other.m_direction; |
354 m_unparsedFont = other.m_unparsedFont; | 356 m_unparsedFont = other.m_unparsedFont; |
355 m_font = other.m_font; | 357 m_font = other.m_font; |
356 m_realizedFont = other.m_realizedFont; | 358 m_realizedFont = other.m_realizedFont; |
357 m_hasClip = other.m_hasClip; | 359 m_hasClip = other.m_hasClip; |
360 m_hasComplexClip = other.m_hasComplexClip; | |
358 m_clipList = other.m_clipList; | 361 m_clipList = other.m_clipList; |
359 | 362 |
360 if (m_realizedFont) | 363 if (m_realizedFont) |
361 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); | 364 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); |
362 | 365 |
363 return *this; | 366 return *this; |
364 } | 367 } |
365 | 368 |
366 CanvasRenderingContext2D::State::~State() | 369 CanvasRenderingContext2D::State::~State() |
367 { | 370 { |
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1115 | 1118 |
1116 SkPath skPath = path.skPath(); | 1119 SkPath skPath = path.skPath(); |
1117 skPath.setFillType(parseWinding(windingRuleString)); | 1120 skPath.setFillType(parseWinding(windingRuleString)); |
1118 ImageBuffer* buffer = canvas()->buffer(); | 1121 ImageBuffer* buffer = canvas()->buffer(); |
1119 if (buffer && buffer->needsClipTracking()) { | 1122 if (buffer && buffer->needsClipTracking()) { |
1120 modifiableState().m_clipList.clipPath(skPath, m_clipAntialiasing, affine TransformToSkMatrix(state().m_transform)); | 1123 modifiableState().m_clipList.clipPath(skPath, m_clipAntialiasing, affine TransformToSkMatrix(state().m_transform)); |
1121 } | 1124 } |
1122 | 1125 |
1123 c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAlias ed); | 1126 c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAlias ed); |
1124 if (!skPath.isRect(0)) | 1127 if (!skPath.isRect(0)) |
1125 drawingContext()->setHasComplexClip(); | 1128 modifiableState().m_hasComplexClip = true; |
1126 modifiableState().m_hasClip = true; | 1129 modifiableState().m_hasClip = true; |
1127 } | 1130 } |
1128 | 1131 |
1129 void CanvasRenderingContext2D::clip(const String& windingRuleString) | 1132 void CanvasRenderingContext2D::clip(const String& windingRuleString) |
1130 { | 1133 { |
1131 clipInternal(m_path, windingRuleString); | 1134 clipInternal(m_path, windingRuleString); |
1132 } | 1135 } |
1133 | 1136 |
1134 void CanvasRenderingContext2D::clip(Path2D* domPath, const String& windingRuleSt ring) | 1137 void CanvasRenderingContext2D::clip(Path2D* domPath, const String& windingRuleSt ring) |
1135 { | 1138 { |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1290 | 1293 |
1291 // from the HTML5 Canvas spec: | 1294 // from the HTML5 Canvas spec: |
1292 // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing | 1295 // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing |
1293 // If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint n othing | 1296 // If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint n othing |
1294 Gradient* gradient = c->fillGradient(); | 1297 Gradient* gradient = c->fillGradient(); |
1295 if (gradient && gradient->isZeroSize()) | 1298 if (gradient && gradient->isZeroSize()) |
1296 return; | 1299 return; |
1297 | 1300 |
1298 FloatRect rect(x, y, width, height); | 1301 FloatRect rect(x, y, width, height); |
1299 if (rectContainsTransformedRect(rect, clipBounds)) { | 1302 if (rectContainsTransformedRect(rect, clipBounds)) { |
1303 checkOverdraw(rect, &c->fillPaint(), NoImage, ClipFill); | |
1300 c->fillRect(rect); | 1304 c->fillRect(rect); |
1301 didDraw(clipBounds); | 1305 didDraw(clipBounds); |
1302 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { | 1306 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { |
1303 fullCanvasCompositedDraw(bind(&fillRectOnContext, c, rect)); | 1307 fullCanvasCompositedDraw(bind(&fillRectOnContext, c, rect)); |
1304 didDraw(clipBounds); | 1308 didDraw(clipBounds); |
1305 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { | 1309 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { |
1306 clearCanvas(); | 1310 clearCanvas(); |
1307 c->clearShadow(); | 1311 c->clearShadow(); // Takes care of signaling the overdraw |
1308 c->fillRect(rect); | 1312 c->fillRect(rect); |
1309 applyShadow(DrawShadowAndForeground); | 1313 applyShadow(DrawShadowAndForeground); |
1310 didDraw(clipBounds); | 1314 didDraw(clipBounds); |
1311 } else { | 1315 } else { |
1312 FloatRect dirtyRect; | 1316 FloatRect dirtyRect; |
1313 if (computeDirtyRect(rect, clipBounds, &dirtyRect)) { | 1317 if (computeDirtyRect(rect, clipBounds, &dirtyRect)) { |
1314 c->fillRect(rect); | 1318 c->fillRect(rect); |
1315 didDraw(dirtyRect); | 1319 didDraw(dirtyRect); |
1316 } | 1320 } |
1317 } | 1321 } |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1511 | 1515 |
1512 // FIXME: crbug.com/447218 | 1516 // FIXME: crbug.com/447218 |
1513 // We make the destination canvas fall out of display list mode by calling | 1517 // We make the destination canvas fall out of display list mode by calling |
1514 // willAccessPixels. This is to prevent run-away memory consumption caused b y SkSurface | 1518 // willAccessPixels. This is to prevent run-away memory consumption caused b y SkSurface |
1515 // copyOnWrite when the source canvas is animated and consumed at a rate hig her than the | 1519 // copyOnWrite when the source canvas is animated and consumed at a rate hig her than the |
1516 // presentation frame rate of the destination canvas. | 1520 // presentation frame rate of the destination canvas. |
1517 if (imageSource->isCanvasElement()) | 1521 if (imageSource->isCanvasElement()) |
1518 canvas()->buffer()->willAccessPixels(); | 1522 canvas()->buffer()->willAccessPixels(); |
1519 | 1523 |
1520 if (rectContainsTransformedRect(dstRect, clipBounds)) { | 1524 if (rectContainsTransformedRect(dstRect, clipBounds)) { |
1525 checkOverdraw(dstRect, &c->fillPaint(), imageSource->isOpaque() ? Opaque Image : NonOpaqueImage, NormalFill); | |
dshwang
2015/02/06 19:10:37
Why drawImage uses NormalFill while fillRect use C
Justin Novosad
2015/02/06 19:37:31
You are right. And this was the only place NormalF
| |
1521 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); | 1526 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); |
1522 didDraw(clipBounds); | 1527 didDraw(clipBounds); |
1523 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { | 1528 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { |
1524 fullCanvasCompositedDraw(bind(&drawImageOnContext, drawingCanvas(), c, i mageSource, image.get(), srcRect, dstRect)); | 1529 fullCanvasCompositedDraw(bind(&drawImageOnContext, drawingCanvas(), c, i mageSource, image.get(), srcRect, dstRect)); |
1525 didDraw(clipBounds); | 1530 didDraw(clipBounds); |
1526 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { | 1531 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { |
1527 clearCanvas(); | 1532 clearCanvas(); // takes care of signaling an overdraw |
1528 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); | 1533 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); |
1529 didDraw(clipBounds); | 1534 didDraw(clipBounds); |
1530 } else { | 1535 } else { |
1531 FloatRect dirtyRect; | 1536 FloatRect dirtyRect; |
1532 if (computeDirtyRect(dstRect, clipBounds, &dirtyRect)) { | 1537 if (computeDirtyRect(dstRect, clipBounds, &dirtyRect)) { |
1533 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), src Rect, dstRect); | 1538 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), src Rect, dstRect); |
1534 didDraw(dirtyRect); | 1539 didDraw(dirtyRect); |
1535 } | 1540 } |
1536 } | 1541 } |
1537 | 1542 |
1538 validateStateStack(); | 1543 validateStateStack(); |
1539 | 1544 |
1540 if (sourceImageStatus == ExternalSourceImageStatus && isAccelerated() && can vas()->buffer()) | 1545 if (sourceImageStatus == ExternalSourceImageStatus && isAccelerated() && can vas()->buffer()) |
1541 canvas()->buffer()->flush(); | 1546 canvas()->buffer()->flush(); |
1542 | 1547 |
1543 if (canvas()->originClean() && wouldTaintOrigin(imageSource)) | 1548 if (canvas()->originClean() && wouldTaintOrigin(imageSource)) |
1544 canvas()->setOriginTainted(); | 1549 canvas()->setOriginTainted(); |
1545 } | 1550 } |
1546 | 1551 |
1547 void CanvasRenderingContext2D::clearCanvas() | 1552 void CanvasRenderingContext2D::clearCanvas() |
1548 { | 1553 { |
1549 FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); | 1554 FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); |
1550 SkCanvas* c = drawingCanvas(); | 1555 SkCanvas* c = drawingCanvas(); |
1551 if (!c) | 1556 if (!c) |
1552 return; | 1557 return; |
1553 | 1558 |
1559 checkOverdraw(canvasRect, 0, NoImage, ClipFill); | |
1554 c->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); | 1560 c->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); |
1555 } | 1561 } |
1556 | 1562 |
1557 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const FloatRect& transformedRect) const | 1563 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const FloatRect& transformedRect) const |
1558 { | 1564 { |
1559 FloatQuad quad(rect); | 1565 FloatQuad quad(rect); |
1560 FloatQuad transformedQuad(transformedRect); | 1566 FloatQuad transformedQuad(transformedRect); |
1561 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad); | 1567 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad); |
1562 } | 1568 } |
1563 | 1569 |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1784 clipRect.intersect(IntRect(0, 0, data->width(), data->height())); | 1790 clipRect.intersect(IntRect(0, 0, data->width(), data->height())); |
1785 IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy)); | 1791 IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy)); |
1786 IntRect destRect = enclosingIntRect(clipRect); | 1792 IntRect destRect = enclosingIntRect(clipRect); |
1787 destRect.move(destOffset); | 1793 destRect.move(destOffset); |
1788 destRect.intersect(IntRect(IntPoint(), buffer->size())); | 1794 destRect.intersect(IntRect(IntPoint(), buffer->size())); |
1789 if (destRect.isEmpty()) | 1795 if (destRect.isEmpty()) |
1790 return; | 1796 return; |
1791 IntRect sourceRect(destRect); | 1797 IntRect sourceRect(destRect); |
1792 sourceRect.move(-destOffset); | 1798 sourceRect.move(-destOffset); |
1793 | 1799 |
1800 checkOverdraw(destRect, 0, NoImage, UntransformedUnclippedFill); | |
1801 | |
1794 buffer->putByteArray(Unmultiplied, data->data()->data(), IntSize(data->width (), data->height()), sourceRect, IntPoint(destOffset)); | 1802 buffer->putByteArray(Unmultiplied, data->data()->data(), IntSize(data->width (), data->height()), sourceRect, IntPoint(destOffset)); |
1795 | 1803 |
1796 didDraw(destRect); | 1804 didDraw(destRect); |
1797 } | 1805 } |
1798 | 1806 |
1799 String CanvasRenderingContext2D::font() const | 1807 String CanvasRenderingContext2D::font() const |
1800 { | 1808 { |
1801 if (!state().m_realizedFont) | 1809 if (!state().m_realizedFont) |
1802 return defaultFont; | 1810 return defaultFont; |
1803 | 1811 |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2375 } | 2383 } |
2376 | 2384 |
2377 unsigned CanvasRenderingContext2D::hitRegionsCount() const | 2385 unsigned CanvasRenderingContext2D::hitRegionsCount() const |
2378 { | 2386 { |
2379 if (m_hitRegionManager) | 2387 if (m_hitRegionManager) |
2380 return m_hitRegionManager->getHitRegionsCount(); | 2388 return m_hitRegionManager->getHitRegionsCount(); |
2381 | 2389 |
2382 return 0; | 2390 return 0; |
2383 } | 2391 } |
2384 | 2392 |
2393 void CanvasRenderingContext2D::checkOverdraw(const SkRect& rect, const SkPaint* paint, ImageType imageType, DrawType drawType) | |
2394 { | |
2395 SkCanvas* c = drawingCanvas(); | |
2396 if (!c || !canvas()->buffer()->isRecording()) | |
2397 return; | |
2398 | |
2399 SkRect deviceRect; | |
2400 if (drawType == UntransformedUnclippedFill) { | |
2401 deviceRect = rect; | |
2402 } else if (drawType == ClipFill) { | |
2403 if (state().m_hasComplexClip) | |
2404 return; | |
2405 | |
2406 SkIRect skIBounds; | |
2407 if (!c->getClipDeviceBounds(&skIBounds)) | |
2408 return; | |
2409 deviceRect = SkRect::Make(skIBounds); | |
2410 } else { | |
2411 // FIXME: Early out if rotate/skew. To be thorough, we could compute | |
2412 // an enclsed rect, but that would probably be overkill. | |
dshwang
2015/02/06 19:10:37
s/enclsed/enclosed/
Justin Novosad
2015/02/06 19:37:31
Acknowledged.
| |
2413 const SkMatrix& ctm = c->getTotalMatrix(); | |
2414 if (!ctm.rectStaysRect()) | |
2415 return; | |
2416 | |
2417 if (state().m_hasComplexClip) | |
2418 return; | |
2419 | |
2420 ctm.mapRect(&deviceRect, rect); | |
2421 SkIRect skIBounds; | |
2422 if (!c->getClipDeviceBounds(&skIBounds)) | |
2423 return; | |
2424 SkRect skBounds = SkRect::Make(skIBounds); | |
2425 if (!deviceRect.intersect(skBounds)) | |
2426 return; | |
2427 } | |
2428 | |
2429 const SkImageInfo& imageInfo = c->imageInfo(); | |
2430 if (!deviceRect.contains(SkRect::MakeWH(imageInfo.width(), imageInfo.height( )))) | |
2431 return; | |
2432 | |
2433 bool isSourceOver = true; | |
2434 unsigned alpha = 0xFF; | |
2435 if (paint) { | |
2436 if (paint->getLooper() || paint->getImageFilter() || paint->getMaskFilte r()) | |
2437 return; | |
2438 | |
2439 SkXfermode* xfermode = paint->getXfermode(); | |
2440 if (xfermode) { | |
2441 SkXfermode::Mode mode; | |
2442 if (xfermode->asMode(&mode)) { | |
2443 isSourceOver = mode == SkXfermode::kSrcOver_Mode; | |
2444 if (!isSourceOver && mode != SkXfermode::kSrc_Mode && mode != Sk Xfermode::kClear_Mode) | |
2445 return; // The code below only knows how to handle Src, SrcO ver, and Clear | |
2446 } else { | |
2447 // unknown xfermode | |
dshwang
2015/02/06 19:10:37
ASSERT_NOT_REACHED?
Justin Novosad
2015/02/06 19:37:31
Acknowledged.
| |
2448 return; | |
2449 } | |
2450 } | |
2451 | |
2452 if (isSourceOver) { | |
2453 // With source over, we need to certify that alpha == 0xFF for all p ixels | |
2454 SkColorFilter* colorFilter = paint->getColorFilter(); | |
2455 if (colorFilter && !(colorFilter->getFlags() & SkColorFilter::kAlpha Unchanged_Flag)) | |
2456 return; | |
2457 | |
2458 SkShader* shader = paint->getShader(); | |
2459 if (shader) { | |
2460 // Shader overrides bitmap and paint color, so we can end here | |
2461 if (shader->isOpaque()) | |
dshwang
2015/02/06 19:10:37
don't we need to consider alpha even if shader is
Justin Novosad
2015/02/06 19:37:31
Did some digging in the code. In skia-land, the sh
| |
2462 canvas()->buffer()->willOverwriteCanvas(); | |
2463 return; | |
2464 } | |
2465 } | |
2466 | |
2467 alpha = paint->getAlpha(); | |
2468 } | |
2469 | |
2470 if (isSourceOver) { | |
2471 // With source over, we need to certify that alpha == 0xFF for all pixel s | |
2472 if (imageType == NonOpaqueImage) | |
2473 return; | |
2474 if (imageType == NoImage && alpha < 0xFF) | |
2475 return; | |
dshwang
2015/02/06 19:10:37
Can we overdraw when imageType == OpaqueImage && a
Justin Novosad
2015/02/06 19:37:31
Yep, Made the same mistake here as with shaders ab
| |
2476 } | |
2477 | |
2478 canvas()->buffer()->willOverwriteCanvas(); | |
2479 } | |
2480 | |
2385 } // namespace blink | 2481 } // namespace blink |
OLD | NEW |