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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1229 pathRect, ScrollAlignment::alignCenterAlways, ScrollAlignment::alignTopA lways); | 1232 pathRect, ScrollAlignment::alignCenterAlways, ScrollAlignment::alignTopA lways); |
1230 | 1233 |
1231 // TODO: should implement "inform the user" that the caret and/or | 1234 // TODO: should implement "inform the user" that the caret and/or |
1232 // selection the specified rectangle of the canvas. See http://crbug.com/357 987 | 1235 // selection the specified rectangle of the canvas. See http://crbug.com/357 987 |
1233 } | 1236 } |
1234 | 1237 |
1235 void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he ight) | 1238 void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he ight) |
1236 { | 1239 { |
1237 if (!validateRectForCanvas(x, y, width, height)) | 1240 if (!validateRectForCanvas(x, y, width, height)) |
1238 return; | 1241 return; |
1239 GraphicsContext* context = drawingContext(); | |
1240 if (!context) | |
1241 return; | |
1242 if (!state().m_invertibleCTM) | |
1243 return; | |
1244 FloatRect rect(x, y, width, height); | |
1245 | 1242 |
1246 FloatRect dirtyRect; | 1243 GraphicsContext* c = drawingContext(); |
1247 if (!computeDirtyRect(rect, &dirtyRect)) | 1244 if (!c) |
1248 return; | 1245 return; |
1249 | 1246 |
1250 context->clearShadow(); | 1247 c->clearShadow(); |
1251 context->setAlphaAsFloat(1); | 1248 c->setAlphaAsFloat(1); |
1252 context->setCompositeOperation(SkXfermode::kSrcOver_Mode); | 1249 c->setCompositeOperation(SkXfermode::kClear_Mode); |
1253 | 1250 |
1254 context->clearRect(rect); | 1251 fillRect(x, y, width, height); |
1255 if (m_hitRegionManager) | |
1256 m_hitRegionManager->removeHitRegionsInRect(rect, state().m_transform); | |
1257 | 1252 |
1258 applyShadow(DrawShadowAndForeground); | 1253 applyShadow(DrawShadowAndForeground); |
1259 context->setAlphaAsFloat(state().m_globalAlpha); | 1254 c->setAlphaAsFloat(state().m_globalAlpha); |
1260 context->setCompositeOperation(state().m_globalComposite); | 1255 c->setCompositeOperation(state().m_globalComposite); |
1261 | 1256 |
1262 validateStateStack(); | 1257 if (m_hitRegionManager) { |
1263 didDraw(dirtyRect); | 1258 FloatRect rect(x, y, width, height); |
1259 m_hitRegionManager->removeHitRegionsInRect(rect, state().m_transform); | |
Ken Russell (switch to Gerrit)
2015/02/11 10:11:44
Why was the check removed above of whether the sta
Justin Novosad
2015/02/11 18:59:54
Good catch, my thinking was that we already check
| |
1260 } | |
dshwang
2015/02/11 08:37:52
why didDraw is removed?
Justin Novosad
2015/02/11 18:59:54
didDraw is taken care of by fillRect now. I'll add
| |
1264 } | 1261 } |
1265 | 1262 |
1266 // FIXME(crbug.com/425531): Funtional.h cannot handle override function signatur e. | 1263 // FIXME(crbug.com/425531): Funtional.h cannot handle override function signatur e. |
1267 static void fillRectOnContext(GraphicsContext* context, const FloatRect& rect) | 1264 static void fillRectOnContext(GraphicsContext* context, const FloatRect& rect) |
1268 { | 1265 { |
1269 context->fillRect(rect); | 1266 context->fillRect(rect); |
1270 } | 1267 } |
1271 | 1268 |
1272 static void strokeRectOnContext(GraphicsContext* context, const FloatRect& rect) | 1269 static void strokeRectOnContext(GraphicsContext* context, const FloatRect& rect) |
1273 { | 1270 { |
(...skipping 16 matching lines...) Expand all Loading... | |
1290 | 1287 |
1291 // from the HTML5 Canvas spec: | 1288 // from the HTML5 Canvas spec: |
1292 // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing | 1289 // 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 | 1290 // If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint n othing |
1294 Gradient* gradient = c->fillGradient(); | 1291 Gradient* gradient = c->fillGradient(); |
1295 if (gradient && gradient->isZeroSize()) | 1292 if (gradient && gradient->isZeroSize()) |
1296 return; | 1293 return; |
1297 | 1294 |
1298 FloatRect rect(x, y, width, height); | 1295 FloatRect rect(x, y, width, height); |
1299 if (rectContainsTransformedRect(rect, clipBounds)) { | 1296 if (rectContainsTransformedRect(rect, clipBounds)) { |
1297 checkOverdraw(rect, &c->fillPaint(), NoImage, ClipFill); | |
1300 c->fillRect(rect); | 1298 c->fillRect(rect); |
1301 didDraw(clipBounds); | 1299 didDraw(clipBounds); |
1302 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { | 1300 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { |
1303 fullCanvasCompositedDraw(bind(&fillRectOnContext, c, rect)); | 1301 fullCanvasCompositedDraw(bind(&fillRectOnContext, c, rect)); |
1304 didDraw(clipBounds); | 1302 didDraw(clipBounds); |
1305 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { | 1303 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { |
1306 clearCanvas(); | 1304 clearCanvas(); |
1307 c->clearShadow(); | 1305 c->clearShadow(); // Takes care of signaling the overdraw |
1308 c->fillRect(rect); | 1306 c->fillRect(rect); |
1309 applyShadow(DrawShadowAndForeground); | 1307 applyShadow(DrawShadowAndForeground); |
1310 didDraw(clipBounds); | 1308 didDraw(clipBounds); |
1311 } else { | 1309 } else { |
1312 FloatRect dirtyRect; | 1310 FloatRect dirtyRect; |
1313 if (computeDirtyRect(rect, clipBounds, &dirtyRect)) { | 1311 if (computeDirtyRect(rect, clipBounds, &dirtyRect)) { |
1314 c->fillRect(rect); | 1312 c->fillRect(rect); |
1315 didDraw(dirtyRect); | 1313 didDraw(dirtyRect); |
1316 } | 1314 } |
1317 } | 1315 } |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1418 return value.getAsImageBitmap().get(); | 1416 return value.getAsImageBitmap().get(); |
1419 ASSERT_NOT_REACHED(); | 1417 ASSERT_NOT_REACHED(); |
1420 return nullptr; | 1418 return nullptr; |
1421 } | 1419 } |
1422 | 1420 |
1423 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, float x, float y, ExceptionState& exceptionState) | 1421 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, float x, float y, ExceptionState& exceptionState) |
1424 { | 1422 { |
1425 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); | 1423 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); |
1426 FloatSize sourceRectSize = imageSourceInternal->sourceSize(); | 1424 FloatSize sourceRectSize = imageSourceInternal->sourceSize(); |
1427 FloatSize destRectSize = imageSourceInternal->defaultDestinationSize(); | 1425 FloatSize destRectSize = imageSourceInternal->defaultDestinationSize(); |
1428 drawImageInternal(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceR ectSize.height(), x, y, destRectSize.width(), destRectSize.height(), exceptionSt ate); | 1426 drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize. height(), x, y, destRectSize.width(), destRectSize.height(), exceptionState); |
1429 } | 1427 } |
1430 | 1428 |
1431 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, | 1429 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, |
1432 float x, float y, float width, float height, ExceptionState& exceptionState) | 1430 float x, float y, float width, float height, ExceptionState& exceptionState) |
1433 { | 1431 { |
1434 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); | 1432 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); |
1435 FloatSize sourceRectSize = imageSourceInternal->sourceSize(); | 1433 FloatSize sourceRectSize = imageSourceInternal->sourceSize(); |
1436 drawImageInternal(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceR ectSize.height(), x, y, width, height, exceptionState); | 1434 drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize. height(), x, y, width, height, exceptionState); |
1437 } | 1435 } |
1438 | 1436 |
1439 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, | 1437 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, |
1440 float sx, float sy, float sw, float sh, | 1438 float sx, float sy, float sw, float sh, |
1441 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) | 1439 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) |
1442 { | 1440 { |
1443 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); | 1441 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); |
1444 drawImageInternal(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, excep tionState); | 1442 drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionStat e); |
1445 } | 1443 } |
1446 | 1444 |
1447 static void drawVideo(SkCanvas* c, GraphicsContext* gc, CanvasImageSource* image Source, FloatRect srcRect, FloatRect dstRect) | 1445 static void drawVideo(SkCanvas* c, GraphicsContext* gc, CanvasImageSource* image Source, FloatRect srcRect, FloatRect dstRect) |
1448 { | 1446 { |
1449 HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource); | 1447 HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource); |
1450 c->save(); | 1448 c->save(); |
1451 c->clipRect(WebCoreFloatRectToSKRect(dstRect)); | 1449 c->clipRect(WebCoreFloatRectToSKRect(dstRect)); |
1452 c->translate(dstRect.x(), dstRect.y()); | 1450 c->translate(dstRect.x(), dstRect.y()); |
1453 c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.heigh t()); | 1451 c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.heigh t()); |
1454 c->translate(-srcRect.x(), -srcRect.y()); | 1452 c->translate(-srcRect.x(), -srcRect.y()); |
1455 video->paintCurrentFrameInContext(gc, IntRect(IntPoint(), IntSize(video->vid eoWidth(), video->videoHeight()))); | 1453 video->paintCurrentFrameInContext(gc, IntRect(IntPoint(), IntSize(video->vid eoWidth(), video->videoHeight()))); |
1456 c->restore(); | 1454 c->restore(); |
1457 } | 1455 } |
1458 | 1456 |
1459 static void drawImageOnContext(SkCanvas* c, GraphicsContext* gc, CanvasImageSour ce* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRec t) | 1457 static void drawImageOnContext(SkCanvas* c, GraphicsContext* gc, CanvasImageSour ce* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRec t) |
1460 { | 1458 { |
1461 if (!imageSource->isVideoElement()) { | 1459 if (!imageSource->isVideoElement()) { |
1462 gc->drawImage(image, dstRect, srcRect, gc->compositeOperation()); | 1460 gc->drawImage(image, dstRect, srcRect, gc->compositeOperation()); |
1463 } else { | 1461 } else { |
1464 drawVideo(c, gc, static_cast<HTMLVideoElement*>(imageSource), srcRect, d stRect); | 1462 drawVideo(c, gc, static_cast<HTMLVideoElement*>(imageSource), srcRect, d stRect); |
1465 } | 1463 } |
1466 } | 1464 } |
1467 | 1465 |
1468 void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource, | 1466 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, |
1469 float sx, float sy, float sw, float sh, | 1467 float sx, float sy, float sw, float sh, |
1470 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) | 1468 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) |
1471 { | 1469 { |
1472 RefPtr<Image> image; | 1470 RefPtr<Image> image; |
1473 SourceImageStatus sourceImageStatus = InvalidSourceImageStatus; | 1471 SourceImageStatus sourceImageStatus = InvalidSourceImageStatus; |
1474 if (!imageSource->isVideoElement()) { | 1472 if (!imageSource->isVideoElement()) { |
1475 SourceImageMode mode = canvas() == imageSource ? CopySourceImageIfVolati le : DontCopySourceImage; // Thunking for == | 1473 SourceImageMode mode = canvas() == imageSource ? CopySourceImageIfVolati le : DontCopySourceImage; // Thunking for == |
1476 image = imageSource->getSourceImageForCanvas(mode, &sourceImageStatus); | 1474 image = imageSource->getSourceImageForCanvas(mode, &sourceImageStatus); |
1477 if (sourceImageStatus == UndecodableSourceImageStatus) | 1475 if (sourceImageStatus == UndecodableSourceImageStatus) |
1478 exceptionState.throwDOMException(InvalidStateError, "The HTMLImageEl ement provided is in the 'broken' state."); | 1476 exceptionState.throwDOMException(InvalidStateError, "The HTMLImageEl ement provided is in the 'broken' state."); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1511 | 1509 |
1512 // FIXME: crbug.com/447218 | 1510 // FIXME: crbug.com/447218 |
1513 // We make the destination canvas fall out of display list mode by calling | 1511 // 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 | 1512 // 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 | 1513 // copyOnWrite when the source canvas is animated and consumed at a rate hig her than the |
1516 // presentation frame rate of the destination canvas. | 1514 // presentation frame rate of the destination canvas. |
1517 if (imageSource->isCanvasElement()) | 1515 if (imageSource->isCanvasElement()) |
1518 canvas()->buffer()->willAccessPixels(); | 1516 canvas()->buffer()->willAccessPixels(); |
1519 | 1517 |
1520 if (rectContainsTransformedRect(dstRect, clipBounds)) { | 1518 if (rectContainsTransformedRect(dstRect, clipBounds)) { |
1519 checkOverdraw(dstRect, &c->fillPaint(), imageSource->isOpaque() ? Opaque Image : NonOpaqueImage, ClipFill); | |
1521 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); | 1520 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); |
1522 didDraw(clipBounds); | 1521 didDraw(clipBounds); |
1523 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { | 1522 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { |
1524 fullCanvasCompositedDraw(bind(&drawImageOnContext, drawingCanvas(), c, i mageSource, image.get(), srcRect, dstRect)); | 1523 fullCanvasCompositedDraw(bind(&drawImageOnContext, drawingCanvas(), c, i mageSource, image.get(), srcRect, dstRect)); |
1525 didDraw(clipBounds); | 1524 didDraw(clipBounds); |
1526 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { | 1525 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { |
1527 clearCanvas(); | 1526 clearCanvas(); // takes care of signaling an overdraw |
1528 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); | 1527 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); |
1529 didDraw(clipBounds); | 1528 didDraw(clipBounds); |
1530 } else { | 1529 } else { |
1531 FloatRect dirtyRect; | 1530 FloatRect dirtyRect; |
1532 if (computeDirtyRect(dstRect, clipBounds, &dirtyRect)) { | 1531 if (computeDirtyRect(dstRect, clipBounds, &dirtyRect)) { |
1533 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), src Rect, dstRect); | 1532 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), src Rect, dstRect); |
1534 didDraw(dirtyRect); | 1533 didDraw(dirtyRect); |
1535 } | 1534 } |
1536 } | 1535 } |
1537 | 1536 |
1538 validateStateStack(); | 1537 validateStateStack(); |
1539 | 1538 |
1540 if (sourceImageStatus == ExternalSourceImageStatus && isAccelerated() && can vas()->buffer()) | 1539 if (sourceImageStatus == ExternalSourceImageStatus && isAccelerated() && can vas()->buffer()) |
1541 canvas()->buffer()->flush(); | 1540 canvas()->buffer()->flush(); |
1542 | 1541 |
1543 if (canvas()->originClean() && wouldTaintOrigin(imageSource)) | 1542 if (canvas()->originClean() && wouldTaintOrigin(imageSource)) |
1544 canvas()->setOriginTainted(); | 1543 canvas()->setOriginTainted(); |
1545 } | 1544 } |
1546 | 1545 |
1547 void CanvasRenderingContext2D::clearCanvas() | 1546 void CanvasRenderingContext2D::clearCanvas() |
1548 { | 1547 { |
1549 FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); | 1548 FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); |
1550 SkCanvas* c = drawingCanvas(); | 1549 SkCanvas* c = drawingCanvas(); |
1551 if (!c) | 1550 if (!c) |
1552 return; | 1551 return; |
1553 | 1552 |
1553 checkOverdraw(canvasRect, 0, NoImage, ClipFill); | |
1554 c->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); | 1554 c->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); |
1555 } | 1555 } |
1556 | 1556 |
1557 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const FloatRect& transformedRect) const | 1557 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const FloatRect& transformedRect) const |
1558 { | 1558 { |
1559 FloatQuad quad(rect); | 1559 FloatQuad quad(rect); |
1560 FloatQuad transformedQuad(transformedRect); | 1560 FloatQuad transformedQuad(transformedRect); |
1561 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad); | 1561 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad); |
1562 } | 1562 } |
1563 | 1563 |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1784 clipRect.intersect(IntRect(0, 0, data->width(), data->height())); | 1784 clipRect.intersect(IntRect(0, 0, data->width(), data->height())); |
1785 IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy)); | 1785 IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy)); |
1786 IntRect destRect = enclosingIntRect(clipRect); | 1786 IntRect destRect = enclosingIntRect(clipRect); |
1787 destRect.move(destOffset); | 1787 destRect.move(destOffset); |
1788 destRect.intersect(IntRect(IntPoint(), buffer->size())); | 1788 destRect.intersect(IntRect(IntPoint(), buffer->size())); |
1789 if (destRect.isEmpty()) | 1789 if (destRect.isEmpty()) |
1790 return; | 1790 return; |
1791 IntRect sourceRect(destRect); | 1791 IntRect sourceRect(destRect); |
1792 sourceRect.move(-destOffset); | 1792 sourceRect.move(-destOffset); |
1793 | 1793 |
1794 checkOverdraw(destRect, 0, NoImage, UntransformedUnclippedFill); | |
1795 | |
1794 buffer->putByteArray(Unmultiplied, data->data()->data(), IntSize(data->width (), data->height()), sourceRect, IntPoint(destOffset)); | 1796 buffer->putByteArray(Unmultiplied, data->data()->data(), IntSize(data->width (), data->height()), sourceRect, IntPoint(destOffset)); |
1795 | 1797 |
1796 didDraw(destRect); | 1798 didDraw(destRect); |
1797 } | 1799 } |
1798 | 1800 |
1799 String CanvasRenderingContext2D::font() const | 1801 String CanvasRenderingContext2D::font() const |
1800 { | 1802 { |
1801 if (!state().m_realizedFont) | 1803 if (!state().m_realizedFont) |
1802 return defaultFont; | 1804 return defaultFont; |
1803 | 1805 |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2375 } | 2377 } |
2376 | 2378 |
2377 unsigned CanvasRenderingContext2D::hitRegionsCount() const | 2379 unsigned CanvasRenderingContext2D::hitRegionsCount() const |
2378 { | 2380 { |
2379 if (m_hitRegionManager) | 2381 if (m_hitRegionManager) |
2380 return m_hitRegionManager->getHitRegionsCount(); | 2382 return m_hitRegionManager->getHitRegionsCount(); |
2381 | 2383 |
2382 return 0; | 2384 return 0; |
2383 } | 2385 } |
2384 | 2386 |
2387 void CanvasRenderingContext2D::checkOverdraw(const SkRect& rect, const SkPaint* paint, ImageType imageType, DrawType drawType) | |
2388 { | |
2389 SkCanvas* c = drawingCanvas(); | |
2390 if (!c || !canvas()->buffer()->isRecording()) | |
Stephen Chennney
2015/02/11 14:33:20
There's a lot of implicit non-null here. As writte
Justin Novosad
2015/02/11 18:59:54
Those checks are taken care of in drawingCanvas().
Stephen Chennney
2015/02/11 19:29:47
OK.
| |
2391 return; | |
2392 | |
2393 SkRect deviceRect; | |
2394 if (drawType == UntransformedUnclippedFill) { | |
2395 deviceRect = rect; | |
2396 } else { | |
2397 ASSERT(drawType == ClipFill); | |
2398 if (state().m_hasComplexClip) | |
2399 return; | |
2400 | |
2401 SkIRect skIBounds; | |
2402 if (!c->getClipDeviceBounds(&skIBounds)) | |
2403 return; | |
2404 deviceRect = SkRect::Make(skIBounds); | |
2405 } | |
2406 | |
2407 const SkImageInfo& imageInfo = c->imageInfo(); | |
2408 if (!deviceRect.contains(SkRect::MakeWH(imageInfo.width(), imageInfo.height( )))) | |
2409 return; | |
2410 | |
2411 bool isSourceOver = true; | |
2412 unsigned alpha = 0xFF; | |
2413 if (paint) { | |
2414 if (paint->getLooper() || paint->getImageFilter() || paint->getMaskFilte r()) | |
2415 return; | |
2416 | |
2417 SkXfermode* xfermode = paint->getXfermode(); | |
2418 if (xfermode) { | |
2419 SkXfermode::Mode mode; | |
2420 if (xfermode->asMode(&mode)) { | |
2421 isSourceOver = mode == SkXfermode::kSrcOver_Mode; | |
2422 if (!isSourceOver && mode != SkXfermode::kSrc_Mode && mode != Sk Xfermode::kClear_Mode) | |
2423 return; // The code below only knows how to handle Src, SrcO ver, and Clear | |
2424 } else { | |
2425 // unknown xfermode | |
2426 ASSERT_NOT_REACHED(); | |
2427 return; | |
2428 } | |
2429 } | |
2430 | |
2431 alpha = paint->getAlpha(); | |
2432 | |
2433 if (isSourceOver && imageType == NoImage) { | |
2434 SkShader* shader = paint->getShader(); | |
2435 if (shader) { | |
2436 if (shader->isOpaque() && alpha == 0xFF) | |
2437 canvas()->buffer()->willOverwriteCanvas(); | |
2438 return; | |
2439 } | |
2440 } | |
2441 } | |
2442 | |
2443 if (isSourceOver) { | |
2444 // With source over, we need to certify that alpha == 0xFF for all pixel s | |
2445 if (imageType == NonOpaqueImage) | |
2446 return; | |
2447 if (alpha < 0xFF) | |
2448 return; | |
2449 } | |
2450 | |
2451 canvas()->buffer()->willOverwriteCanvas(); | |
2452 } | |
2453 | |
2385 } // namespace blink | 2454 } // namespace blink |
OLD | NEW |