Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: Source/core/html/canvas/CanvasRenderingContext2D.cpp

Issue 907453003: Move overdraw tracking code from GraphicsContext to CanvasRenderingContext2D (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: fix test copypasta Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 static const char ltr[] = "ltr"; 83 static const char ltr[] = "ltr";
84 static const double TryRestoreContextInterval = 0.5; 84 static const double TryRestoreContextInterval = 0.5;
85 static const unsigned MaxTryRestoreContextAttempts = 4; 85 static const unsigned MaxTryRestoreContextAttempts = 4;
86 static const unsigned FetchedFontsCacheLimit = 50; 86 static const unsigned FetchedFontsCacheLimit = 50;
87 87
88 static bool contextLostRestoredEventsEnabled() 88 static bool contextLostRestoredEventsEnabled()
89 { 89 {
90 return RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); 90 return RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled();
91 } 91 }
92 92
93 // Drawing methods need to use this instead of SkAutoCanvasRestore in case overd raw
94 // detection substitutes the recording canvas (to discard overdrawn draw calls).
95 class CanvasRenderingContext2DAutoRestoreSkCanvas {
96 public:
97 CanvasRenderingContext2DAutoRestoreSkCanvas(CanvasRenderingContext2D* contex t)
98 : m_context(context)
99 {
100 ASSERT(m_context);
101 SkCanvas* c = m_context->drawingCanvas();
102 if (c) {
103 m_saveCount = c->getSaveCount();
104 }
105 }
106
107 ~CanvasRenderingContext2DAutoRestoreSkCanvas()
108 {
109 SkCanvas* c = m_context->drawingCanvas();
110 if (c)
111 c->restoreToCount(m_saveCount);
112 m_context->validateStateStack();
113 }
114 private:
115 CanvasRenderingContext2D* m_context;
116 int m_saveCount;
117 };
118
93 CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, co nst CanvasContextCreationAttributes& attrs, Document& document) 119 CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, co nst CanvasContextCreationAttributes& attrs, Document& document)
94 : CanvasRenderingContext(canvas) 120 : CanvasRenderingContext(canvas)
95 , m_usesCSSCompatibilityParseMode(document.inQuirksMode()) 121 , m_usesCSSCompatibilityParseMode(document.inQuirksMode())
96 , m_clipAntialiasing(NotAntiAliased) 122 , m_clipAntialiasing(NotAntiAliased)
97 , m_hasAlpha(attrs.alpha()) 123 , m_hasAlpha(attrs.alpha())
98 , m_isContextLost(false) 124 , m_isContextLost(false)
99 , m_contextRestorable(true) 125 , m_contextRestorable(true)
100 , m_tryRestoreContextAttemptCount(0) 126 , m_tryRestoreContextAttemptCount(0)
101 , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchC ontextLostEvent) 127 , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchC ontextLostEvent)
102 , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispa tchContextRestoredEvent) 128 , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispa tchContextRestoredEvent)
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 , m_globalComposite(SkXfermode::kSrcOver_Mode) 302 , m_globalComposite(SkXfermode::kSrcOver_Mode)
277 , m_invertibleCTM(true) 303 , m_invertibleCTM(true)
278 , m_lineDashOffset(0) 304 , m_lineDashOffset(0)
279 , m_imageSmoothingEnabled(true) 305 , m_imageSmoothingEnabled(true)
280 , m_textAlign(StartTextAlign) 306 , m_textAlign(StartTextAlign)
281 , m_textBaseline(AlphabeticTextBaseline) 307 , m_textBaseline(AlphabeticTextBaseline)
282 , m_direction(DirectionInherit) 308 , m_direction(DirectionInherit)
283 , m_unparsedFont(defaultFont) 309 , m_unparsedFont(defaultFont)
284 , m_realizedFont(false) 310 , m_realizedFont(false)
285 , m_hasClip(false) 311 , m_hasClip(false)
312 , m_hasComplexClip(false)
286 { 313 {
287 } 314 }
288 315
289 CanvasRenderingContext2D::State::State(const State& other, ClipListCopyMode mode ) 316 CanvasRenderingContext2D::State::State(const State& other, ClipListCopyMode mode )
290 : CSSFontSelectorClient() 317 : CSSFontSelectorClient()
291 , m_unrealizedSaveCount(other.m_unrealizedSaveCount) 318 , m_unrealizedSaveCount(other.m_unrealizedSaveCount)
292 , m_unparsedStrokeColor(other.m_unparsedStrokeColor) 319 , m_unparsedStrokeColor(other.m_unparsedStrokeColor)
293 , m_unparsedFillColor(other.m_unparsedFillColor) 320 , m_unparsedFillColor(other.m_unparsedFillColor)
294 , m_strokeStyle(other.m_strokeStyle) 321 , m_strokeStyle(other.m_strokeStyle)
295 , m_fillStyle(other.m_fillStyle) 322 , m_fillStyle(other.m_fillStyle)
(...skipping 10 matching lines...) Expand all
306 , m_invertibleCTM(other.m_invertibleCTM) 333 , m_invertibleCTM(other.m_invertibleCTM)
307 , m_lineDashOffset(other.m_lineDashOffset) 334 , m_lineDashOffset(other.m_lineDashOffset)
308 , m_imageSmoothingEnabled(other.m_imageSmoothingEnabled) 335 , m_imageSmoothingEnabled(other.m_imageSmoothingEnabled)
309 , m_textAlign(other.m_textAlign) 336 , m_textAlign(other.m_textAlign)
310 , m_textBaseline(other.m_textBaseline) 337 , m_textBaseline(other.m_textBaseline)
311 , m_direction(other.m_direction) 338 , m_direction(other.m_direction)
312 , m_unparsedFont(other.m_unparsedFont) 339 , m_unparsedFont(other.m_unparsedFont)
313 , m_font(other.m_font) 340 , m_font(other.m_font)
314 , m_realizedFont(other.m_realizedFont) 341 , m_realizedFont(other.m_realizedFont)
315 , m_hasClip(other.m_hasClip) 342 , m_hasClip(other.m_hasClip)
343 , m_hasComplexClip(other.m_hasComplexClip)
316 { 344 {
317 if (mode == CopyClipList) { 345 if (mode == CopyClipList) {
318 m_clipList = other.m_clipList; 346 m_clipList = other.m_clipList;
319 } 347 }
320 if (m_realizedFont) 348 if (m_realizedFont)
321 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); 349 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this);
322 } 350 }
323 351
324 CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons t State& other) 352 CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons t State& other)
325 { 353 {
(...skipping 22 matching lines...) Expand all
348 m_transform = other.m_transform; 376 m_transform = other.m_transform;
349 m_invertibleCTM = other.m_invertibleCTM; 377 m_invertibleCTM = other.m_invertibleCTM;
350 m_imageSmoothingEnabled = other.m_imageSmoothingEnabled; 378 m_imageSmoothingEnabled = other.m_imageSmoothingEnabled;
351 m_textAlign = other.m_textAlign; 379 m_textAlign = other.m_textAlign;
352 m_textBaseline = other.m_textBaseline; 380 m_textBaseline = other.m_textBaseline;
353 m_direction = other.m_direction; 381 m_direction = other.m_direction;
354 m_unparsedFont = other.m_unparsedFont; 382 m_unparsedFont = other.m_unparsedFont;
355 m_font = other.m_font; 383 m_font = other.m_font;
356 m_realizedFont = other.m_realizedFont; 384 m_realizedFont = other.m_realizedFont;
357 m_hasClip = other.m_hasClip; 385 m_hasClip = other.m_hasClip;
386 m_hasComplexClip = other.m_hasComplexClip;
358 m_clipList = other.m_clipList; 387 m_clipList = other.m_clipList;
359 388
360 if (m_realizedFont) 389 if (m_realizedFont)
361 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); 390 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this);
362 391
363 return *this; 392 return *this;
364 } 393 }
365 394
366 CanvasRenderingContext2D::State::~State() 395 CanvasRenderingContext2D::State::~State()
367 { 396 {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 } else if (style.isCanvasPattern()) { 564 } else if (style.isCanvasPattern()) {
536 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn(); 565 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn();
537 566
538 if (canvas()->originClean() && !canvasPattern->originClean()) 567 if (canvas()->originClean() && !canvasPattern->originClean())
539 canvas()->setOriginTainted(); 568 canvas()->setOriginTainted();
540 569
541 canvasStyle = CanvasStyle::createFromPattern(canvasPattern); 570 canvasStyle = CanvasStyle::createFromPattern(canvasPattern);
542 } 571 }
543 572
544 ASSERT(canvasStyle); 573 ASSERT(canvasStyle);
545
546 SkCanvas* c = drawingCanvas(); 574 SkCanvas* c = drawingCanvas();
547 realizeSaves(c);
548 modifiableState().m_fillStyle = canvasStyle.release();
549 if (!c) 575 if (!c)
550 return; 576 return;
577 realizeSaves(c);
578
579 modifiableState().m_fillStyle = canvasStyle.release();
580 modifiableState().m_unparsedFillColor = colorString;
551 state().m_fillStyle->applyFillColor(drawingContext()); 581 state().m_fillStyle->applyFillColor(drawingContext());
552 modifiableState().m_unparsedFillColor = colorString;
553 } 582 }
554 583
555 float CanvasRenderingContext2D::lineWidth() const 584 float CanvasRenderingContext2D::lineWidth() const
556 { 585 {
557 return state().m_lineWidth; 586 return state().m_lineWidth;
558 } 587 }
559 588
560 void CanvasRenderingContext2D::setLineWidth(float width) 589 void CanvasRenderingContext2D::setLineWidth(float width)
561 { 590 {
562 if (!std::isfinite(width) || width <= 0) 591 if (!std::isfinite(width) || width <= 0)
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 1144
1116 SkPath skPath = path.skPath(); 1145 SkPath skPath = path.skPath();
1117 skPath.setFillType(parseWinding(windingRuleString)); 1146 skPath.setFillType(parseWinding(windingRuleString));
1118 ImageBuffer* buffer = canvas()->buffer(); 1147 ImageBuffer* buffer = canvas()->buffer();
1119 if (buffer && buffer->needsClipTracking()) { 1148 if (buffer && buffer->needsClipTracking()) {
1120 modifiableState().m_clipList.clipPath(skPath, m_clipAntialiasing, affine TransformToSkMatrix(state().m_transform)); 1149 modifiableState().m_clipList.clipPath(skPath, m_clipAntialiasing, affine TransformToSkMatrix(state().m_transform));
1121 } 1150 }
1122 1151
1123 c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAlias ed); 1152 c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAlias ed);
1124 if (!skPath.isRect(0)) 1153 if (!skPath.isRect(0))
1125 drawingContext()->setHasComplexClip(); 1154 modifiableState().m_hasComplexClip = true;
1126 modifiableState().m_hasClip = true; 1155 modifiableState().m_hasClip = true;
1127 } 1156 }
1128 1157
1129 void CanvasRenderingContext2D::clip(const String& windingRuleString) 1158 void CanvasRenderingContext2D::clip(const String& windingRuleString)
1130 { 1159 {
1131 clipInternal(m_path, windingRuleString); 1160 clipInternal(m_path, windingRuleString);
1132 } 1161 }
1133 1162
1134 void CanvasRenderingContext2D::clip(Path2D* domPath, const String& windingRuleSt ring) 1163 void CanvasRenderingContext2D::clip(Path2D* domPath, const String& windingRuleSt ring)
1135 { 1164 {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1229 pathRect, ScrollAlignment::alignCenterAlways, ScrollAlignment::alignTopA lways); 1258 pathRect, ScrollAlignment::alignCenterAlways, ScrollAlignment::alignTopA lways);
1230 1259
1231 // TODO: should implement "inform the user" that the caret and/or 1260 // 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 1261 // selection the specified rectangle of the canvas. See http://crbug.com/357 987
1233 } 1262 }
1234 1263
1235 void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he ight) 1264 void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he ight)
1236 { 1265 {
1237 if (!validateRectForCanvas(x, y, width, height)) 1266 if (!validateRectForCanvas(x, y, width, height))
1238 return; 1267 return;
1239 GraphicsContext* context = drawingContext(); 1268
1240 if (!context) 1269 GraphicsContext* c = drawingContext();
1270 if (!c)
1241 return; 1271 return;
1242 if (!state().m_invertibleCTM) 1272 if (!state().m_invertibleCTM)
1243 return; 1273 return;
1244 FloatRect rect(x, y, width, height);
1245 1274
1246 FloatRect dirtyRect; 1275 c->clearShadow();
1247 if (!computeDirtyRect(rect, &dirtyRect)) 1276 c->setAlphaAsFloat(1);
1248 return; 1277 c->setCompositeOperation(SkXfermode::kClear_Mode);
1249 1278
1250 context->clearShadow(); 1279 // call to didDraw is taken care of in fillRect
1251 context->setAlphaAsFloat(1); 1280 fillRect(x, y, width, height);
1252 context->setCompositeOperation(SkXfermode::kSrcOver_Mode);
1253
1254 context->clearRect(rect);
1255 if (m_hitRegionManager)
1256 m_hitRegionManager->removeHitRegionsInRect(rect, state().m_transform);
1257 1281
1258 applyShadow(DrawShadowAndForeground); 1282 applyShadow(DrawShadowAndForeground);
1259 context->setAlphaAsFloat(state().m_globalAlpha); 1283 c->setAlphaAsFloat(state().m_globalAlpha);
1260 context->setCompositeOperation(state().m_globalComposite); 1284 c->setCompositeOperation(state().m_globalComposite);
1261 1285
1262 validateStateStack(); 1286 if (m_hitRegionManager) {
1263 didDraw(dirtyRect); 1287 FloatRect rect(x, y, width, height);
1288 m_hitRegionManager->removeHitRegionsInRect(rect, state().m_transform);
1289 }
1264 } 1290 }
1265 1291
1266 // FIXME(crbug.com/425531): Funtional.h cannot handle override function signatur e. 1292 // FIXME(crbug.com/425531): Funtional.h cannot handle override function signatur e.
1267 static void fillRectOnContext(GraphicsContext* context, const FloatRect& rect) 1293 static void fillRectOnContext(GraphicsContext* context, const FloatRect& rect)
1268 { 1294 {
1269 context->fillRect(rect); 1295 context->fillRect(rect);
1270 } 1296 }
1271 1297
1272 static void strokeRectOnContext(GraphicsContext* context, const FloatRect& rect) 1298 static void strokeRectOnContext(GraphicsContext* context, const FloatRect& rect)
1273 { 1299 {
(...skipping 16 matching lines...) Expand all
1290 1316
1291 // from the HTML5 Canvas spec: 1317 // from the HTML5 Canvas spec:
1292 // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing 1318 // 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 1319 // If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint n othing
1294 Gradient* gradient = c->fillGradient(); 1320 Gradient* gradient = c->fillGradient();
1295 if (gradient && gradient->isZeroSize()) 1321 if (gradient && gradient->isZeroSize())
1296 return; 1322 return;
1297 1323
1298 FloatRect rect(x, y, width, height); 1324 FloatRect rect(x, y, width, height);
1299 if (rectContainsTransformedRect(rect, clipBounds)) { 1325 if (rectContainsTransformedRect(rect, clipBounds)) {
1326 checkOverdraw(rect, &c->fillPaint(), NoImage, ClipFill);
1300 c->fillRect(rect); 1327 c->fillRect(rect);
1301 didDraw(clipBounds); 1328 didDraw(clipBounds);
1302 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { 1329 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
1303 fullCanvasCompositedDraw(bind(&fillRectOnContext, c, rect)); 1330 fullCanvasCompositedDraw(bind(&fillRectOnContext, c, rect));
1304 didDraw(clipBounds); 1331 didDraw(clipBounds);
1305 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { 1332 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) {
1306 clearCanvas(); 1333 clearCanvas();
1307 c->clearShadow(); 1334 c->clearShadow(); // Takes care of signaling the overdraw
1308 c->fillRect(rect); 1335 c->fillRect(rect);
1309 applyShadow(DrawShadowAndForeground); 1336 applyShadow(DrawShadowAndForeground);
1310 didDraw(clipBounds); 1337 didDraw(clipBounds);
1311 } else { 1338 } else {
1312 FloatRect dirtyRect; 1339 FloatRect dirtyRect;
1313 if (computeDirtyRect(rect, clipBounds, &dirtyRect)) { 1340 if (computeDirtyRect(rect, clipBounds, &dirtyRect)) {
1314 c->fillRect(rect); 1341 c->fillRect(rect);
1315 didDraw(dirtyRect); 1342 didDraw(dirtyRect);
1316 } 1343 }
1317 } 1344 }
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1418 return value.getAsImageBitmap().get(); 1445 return value.getAsImageBitmap().get();
1419 ASSERT_NOT_REACHED(); 1446 ASSERT_NOT_REACHED();
1420 return nullptr; 1447 return nullptr;
1421 } 1448 }
1422 1449
1423 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, float x, float y, ExceptionState& exceptionState) 1450 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, float x, float y, ExceptionState& exceptionState)
1424 { 1451 {
1425 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); 1452 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
1426 FloatSize sourceRectSize = imageSourceInternal->sourceSize(); 1453 FloatSize sourceRectSize = imageSourceInternal->sourceSize();
1427 FloatSize destRectSize = imageSourceInternal->defaultDestinationSize(); 1454 FloatSize destRectSize = imageSourceInternal->defaultDestinationSize();
1428 drawImageInternal(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceR ectSize.height(), x, y, destRectSize.width(), destRectSize.height(), exceptionSt ate); 1455 drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize. height(), x, y, destRectSize.width(), destRectSize.height(), exceptionState);
1429 } 1456 }
1430 1457
1431 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, 1458 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce,
1432 float x, float y, float width, float height, ExceptionState& exceptionState) 1459 float x, float y, float width, float height, ExceptionState& exceptionState)
1433 { 1460 {
1434 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); 1461 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
1435 FloatSize sourceRectSize = imageSourceInternal->sourceSize(); 1462 FloatSize sourceRectSize = imageSourceInternal->sourceSize();
1436 drawImageInternal(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceR ectSize.height(), x, y, width, height, exceptionState); 1463 drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize. height(), x, y, width, height, exceptionState);
1437 } 1464 }
1438 1465
1439 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, 1466 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce,
1440 float sx, float sy, float sw, float sh, 1467 float sx, float sy, float sw, float sh,
1441 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) 1468 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1442 { 1469 {
1443 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); 1470 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
1444 drawImageInternal(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, excep tionState); 1471 drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionStat e);
1445 } 1472 }
1446 1473
1447 static void drawVideo(SkCanvas* c, GraphicsContext* gc, CanvasImageSource* image Source, FloatRect srcRect, FloatRect dstRect) 1474 static void drawVideo(SkCanvas* c, GraphicsContext* gc, CanvasImageSource* image Source, FloatRect srcRect, FloatRect dstRect)
1448 { 1475 {
1449 HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource); 1476 HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource);
1450 c->save(); 1477 c->save();
1451 c->clipRect(WebCoreFloatRectToSKRect(dstRect)); 1478 c->clipRect(WebCoreFloatRectToSKRect(dstRect));
1452 c->translate(dstRect.x(), dstRect.y()); 1479 c->translate(dstRect.x(), dstRect.y());
1453 c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.heigh t()); 1480 c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.heigh t());
1454 c->translate(-srcRect.x(), -srcRect.y()); 1481 c->translate(-srcRect.x(), -srcRect.y());
1455 video->paintCurrentFrameInContext(gc, IntRect(IntPoint(), IntSize(video->vid eoWidth(), video->videoHeight()))); 1482 video->paintCurrentFrameInContext(gc, IntRect(IntPoint(), IntSize(video->vid eoWidth(), video->videoHeight())));
1456 c->restore(); 1483 c->restore();
1457 } 1484 }
1458 1485
1459 static void drawImageOnContext(SkCanvas* c, GraphicsContext* gc, CanvasImageSour ce* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRec t) 1486 static void drawImageOnContext(SkCanvas* c, GraphicsContext* gc, CanvasImageSour ce* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRec t)
1460 { 1487 {
1461 if (!imageSource->isVideoElement()) { 1488 if (!imageSource->isVideoElement()) {
1462 gc->drawImage(image, dstRect, srcRect, gc->compositeOperation()); 1489 gc->drawImage(image, dstRect, srcRect, gc->compositeOperation());
1463 } else { 1490 } else {
1464 drawVideo(c, gc, static_cast<HTMLVideoElement*>(imageSource), srcRect, d stRect); 1491 drawVideo(c, gc, static_cast<HTMLVideoElement*>(imageSource), srcRect, d stRect);
1465 } 1492 }
1466 } 1493 }
1467 1494
1468 void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource, 1495 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
1469 float sx, float sy, float sw, float sh, 1496 float sx, float sy, float sw, float sh,
1470 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) 1497 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1471 { 1498 {
1472 RefPtr<Image> image; 1499 RefPtr<Image> image;
1473 SourceImageStatus sourceImageStatus = InvalidSourceImageStatus; 1500 SourceImageStatus sourceImageStatus = InvalidSourceImageStatus;
1474 if (!imageSource->isVideoElement()) { 1501 if (!imageSource->isVideoElement()) {
1475 SourceImageMode mode = canvas() == imageSource ? CopySourceImageIfVolati le : DontCopySourceImage; // Thunking for == 1502 SourceImageMode mode = canvas() == imageSource ? CopySourceImageIfVolati le : DontCopySourceImage; // Thunking for ==
1476 image = imageSource->getSourceImageForCanvas(mode, &sourceImageStatus); 1503 image = imageSource->getSourceImageForCanvas(mode, &sourceImageStatus);
1477 if (sourceImageStatus == UndecodableSourceImageStatus) 1504 if (sourceImageStatus == UndecodableSourceImageStatus)
1478 exceptionState.throwDOMException(InvalidStateError, "The HTMLImageEl ement provided is in the 'broken' state."); 1505 exceptionState.throwDOMException(InvalidStateError, "The HTMLImageEl ement provided is in the 'broken' state.");
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1511 1538
1512 // FIXME: crbug.com/447218 1539 // FIXME: crbug.com/447218
1513 // We make the destination canvas fall out of display list mode by calling 1540 // 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 1541 // 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 1542 // copyOnWrite when the source canvas is animated and consumed at a rate hig her than the
1516 // presentation frame rate of the destination canvas. 1543 // presentation frame rate of the destination canvas.
1517 if (imageSource->isCanvasElement()) 1544 if (imageSource->isCanvasElement())
1518 canvas()->buffer()->willAccessPixels(); 1545 canvas()->buffer()->willAccessPixels();
1519 1546
1520 if (rectContainsTransformedRect(dstRect, clipBounds)) { 1547 if (rectContainsTransformedRect(dstRect, clipBounds)) {
1548 checkOverdraw(dstRect, &c->fillPaint(), imageSource->isOpaque() ? Opaque Image : NonOpaqueImage, ClipFill);
1521 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); 1549 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect);
1522 didDraw(clipBounds); 1550 didDraw(clipBounds);
1523 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { 1551 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
1524 fullCanvasCompositedDraw(bind(&drawImageOnContext, drawingCanvas(), c, i mageSource, image.get(), srcRect, dstRect)); 1552 fullCanvasCompositedDraw(bind(&drawImageOnContext, drawingCanvas(), c, i mageSource, image.get(), srcRect, dstRect));
1525 didDraw(clipBounds); 1553 didDraw(clipBounds);
1526 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) { 1554 } else if (state().m_globalComposite == SkXfermode::kSrc_Mode) {
1527 clearCanvas(); 1555 clearCanvas(); // takes care of signaling an overdraw
1528 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect); 1556 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect , dstRect);
1529 didDraw(clipBounds); 1557 didDraw(clipBounds);
1530 } else { 1558 } else {
1531 FloatRect dirtyRect; 1559 FloatRect dirtyRect;
1532 if (computeDirtyRect(dstRect, clipBounds, &dirtyRect)) { 1560 if (computeDirtyRect(dstRect, clipBounds, &dirtyRect)) {
1533 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), src Rect, dstRect); 1561 drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), src Rect, dstRect);
1534 didDraw(dirtyRect); 1562 didDraw(dirtyRect);
1535 } 1563 }
1536 } 1564 }
1537 1565
1538 validateStateStack(); 1566 validateStateStack();
1539 1567
1540 if (sourceImageStatus == ExternalSourceImageStatus && isAccelerated() && can vas()->buffer()) 1568 if (sourceImageStatus == ExternalSourceImageStatus && isAccelerated() && can vas()->buffer())
1541 canvas()->buffer()->flush(); 1569 canvas()->buffer()->flush();
1542 1570
1543 if (canvas()->originClean() && wouldTaintOrigin(imageSource)) 1571 if (canvas()->originClean() && wouldTaintOrigin(imageSource))
1544 canvas()->setOriginTainted(); 1572 canvas()->setOriginTainted();
1545 } 1573 }
1546 1574
1547 void CanvasRenderingContext2D::clearCanvas() 1575 void CanvasRenderingContext2D::clearCanvas()
1548 { 1576 {
1549 FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); 1577 FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height());
1550 SkCanvas* c = drawingCanvas(); 1578 SkCanvas* c = drawingCanvas();
1551 if (!c) 1579 if (!c)
1552 return; 1580 return;
1553 1581
1554 c->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); 1582 checkOverdraw(canvasRect, 0, NoImage, ClipFill);
1583 // Must not use 'c' beyond this point in case checkOverdraw substitutes the recording
1584 // canvas in order to clear a draw command backlog.
1585 drawingCanvas()->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK);
1555 } 1586 }
1556 1587
1557 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const FloatRect& transformedRect) const 1588 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const FloatRect& transformedRect) const
1558 { 1589 {
1559 FloatQuad quad(rect); 1590 FloatQuad quad(rect);
1560 FloatQuad transformedQuad(transformedRect); 1591 FloatQuad transformedQuad(transformedRect);
1561 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad); 1592 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad);
1562 } 1593 }
1563 1594
1564 void CanvasRenderingContext2D::fullCanvasCompositedDraw(PassOwnPtr<Closure> draw ) 1595 void CanvasRenderingContext2D::fullCanvasCompositedDraw(PassOwnPtr<Closure> draw )
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 clipRect.intersect(IntRect(0, 0, data->width(), data->height())); 1815 clipRect.intersect(IntRect(0, 0, data->width(), data->height()));
1785 IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy)); 1816 IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy));
1786 IntRect destRect = enclosingIntRect(clipRect); 1817 IntRect destRect = enclosingIntRect(clipRect);
1787 destRect.move(destOffset); 1818 destRect.move(destOffset);
1788 destRect.intersect(IntRect(IntPoint(), buffer->size())); 1819 destRect.intersect(IntRect(IntPoint(), buffer->size()));
1789 if (destRect.isEmpty()) 1820 if (destRect.isEmpty())
1790 return; 1821 return;
1791 IntRect sourceRect(destRect); 1822 IntRect sourceRect(destRect);
1792 sourceRect.move(-destOffset); 1823 sourceRect.move(-destOffset);
1793 1824
1825 checkOverdraw(destRect, 0, NoImage, UntransformedUnclippedFill);
1826
1794 buffer->putByteArray(Unmultiplied, data->data()->data(), IntSize(data->width (), data->height()), sourceRect, IntPoint(destOffset)); 1827 buffer->putByteArray(Unmultiplied, data->data()->data(), IntSize(data->width (), data->height()), sourceRect, IntPoint(destOffset));
1795 1828
1796 didDraw(destRect); 1829 didDraw(destRect);
1797 } 1830 }
1798 1831
1799 String CanvasRenderingContext2D::font() const 1832 String CanvasRenderingContext2D::font() const
1800 { 1833 {
1801 if (!state().m_realizedFont) 1834 if (!state().m_realizedFont)
1802 return defaultFont; 1835 return defaultFont;
1803 1836
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
2130 TextRunPaintInfo textRunPaintInfo(textRun); 2163 TextRunPaintInfo textRunPaintInfo(textRun);
2131 textRunPaintInfo.bounds = FloatRect(location.x() - fontMetrics.height() / 2, 2164 textRunPaintInfo.bounds = FloatRect(location.x() - fontMetrics.height() / 2,
2132 location.y() - fontMetrics.ascent() - fo ntMetrics.lineGap(), 2165 location.y() - fontMetrics.ascent() - fo ntMetrics.lineGap(),
2133 width + fontMetrics.height(), 2166 width + fontMetrics.height(),
2134 fontMetrics.lineSpacing()); 2167 fontMetrics.lineSpacing());
2135 if (!fill) 2168 if (!fill)
2136 inflateStrokeRect(textRunPaintInfo.bounds); 2169 inflateStrokeRect(textRunPaintInfo.bounds);
2137 2170
2138 c->setTextDrawingMode(fill ? TextModeFill : TextModeStroke); 2171 c->setTextDrawingMode(fill ? TextModeFill : TextModeStroke);
2139 2172
2140 GraphicsContextStateSaver stateSaver(*c); 2173 CanvasRenderingContext2DAutoRestoreSkCanvas stateRestorer(this);
2141 if (useMaxWidth) { 2174 if (useMaxWidth) {
2142 c->translate(location.x(), location.y()); 2175 SkCanvas* canvas = drawingCanvas();
2176 canvas->save();
2177 canvas->translate(location.x(), location.y());
2143 // We draw when fontWidth is 0 so compositing operations (eg, a "copy" o p) still work. 2178 // We draw when fontWidth is 0 so compositing operations (eg, a "copy" o p) still work.
2144 c->scale((fontWidth > 0 ? (width / fontWidth) : 0), 1); 2179 canvas->scale((fontWidth > 0 ? (width / fontWidth) : 0), 1);
2145 location = FloatPoint(); 2180 location = FloatPoint();
2146 } 2181 }
2147 2182
2148 FloatRect clipBounds; 2183 FloatRect clipBounds;
2149 if (!c->getTransformedClipBounds(&clipBounds)) { 2184 if (!c->getTransformedClipBounds(&clipBounds)) {
2150 return; 2185 return;
2151 } 2186 }
2152 2187
2153 if (isFullCanvasCompositeMode(state().m_globalComposite)) { 2188 if (isFullCanvasCompositeMode(state().m_globalComposite)) {
2154 fullCanvasCompositedDraw(bind(&GraphicsContext::drawBidiText, c, font, t extRunPaintInfo, location, Font::UseFallbackIfFontNotReady)); 2189 fullCanvasCompositedDraw(bind(&GraphicsContext::drawBidiText, c, font, t extRunPaintInfo, location, Font::UseFallbackIfFontNotReady));
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
2375 } 2410 }
2376 2411
2377 unsigned CanvasRenderingContext2D::hitRegionsCount() const 2412 unsigned CanvasRenderingContext2D::hitRegionsCount() const
2378 { 2413 {
2379 if (m_hitRegionManager) 2414 if (m_hitRegionManager)
2380 return m_hitRegionManager->getHitRegionsCount(); 2415 return m_hitRegionManager->getHitRegionsCount();
2381 2416
2382 return 0; 2417 return 0;
2383 } 2418 }
2384 2419
2420 void CanvasRenderingContext2D::checkOverdraw(const SkRect& rect, const SkPaint* paint, ImageType imageType, DrawType drawType)
2421 {
2422 SkCanvas* c = drawingCanvas();
2423 if (!c || !canvas()->buffer()->isRecording())
2424 return;
2425
2426 SkRect deviceRect;
2427 if (drawType == UntransformedUnclippedFill) {
2428 deviceRect = rect;
2429 } else {
2430 ASSERT(drawType == ClipFill);
2431 if (state().m_hasComplexClip)
2432 return;
2433
2434 SkIRect skIBounds;
2435 if (!c->getClipDeviceBounds(&skIBounds))
2436 return;
2437 deviceRect = SkRect::Make(skIBounds);
2438 }
2439
2440 const SkImageInfo& imageInfo = c->imageInfo();
2441 if (!deviceRect.contains(SkRect::MakeWH(imageInfo.width(), imageInfo.height( ))))
2442 return;
2443
2444 bool isSourceOver = true;
2445 unsigned alpha = 0xFF;
2446 if (paint) {
2447 if (paint->getLooper() || paint->getImageFilter() || paint->getMaskFilte r())
2448 return;
2449
2450 SkXfermode* xfermode = paint->getXfermode();
2451 if (xfermode) {
2452 SkXfermode::Mode mode;
2453 if (xfermode->asMode(&mode)) {
2454 isSourceOver = mode == SkXfermode::kSrcOver_Mode;
2455 if (!isSourceOver && mode != SkXfermode::kSrc_Mode && mode != Sk Xfermode::kClear_Mode)
2456 return; // The code below only knows how to handle Src, SrcO ver, and Clear
2457 } else {
2458 // unknown xfermode
2459 ASSERT_NOT_REACHED();
2460 return;
2461 }
2462 }
2463
2464 alpha = paint->getAlpha();
2465
2466 if (isSourceOver && imageType == NoImage) {
2467 SkShader* shader = paint->getShader();
2468 if (shader) {
2469 if (shader->isOpaque() && alpha == 0xFF)
2470 canvas()->buffer()->willOverwriteCanvas();
2471 return;
2472 }
2473 }
2474 }
2475
2476 if (isSourceOver) {
2477 // With source over, we need to certify that alpha == 0xFF for all pixel s
2478 if (imageType == NonOpaqueImage)
2479 return;
2480 if (alpha < 0xFF)
2481 return;
2482 }
2483
2484 canvas()->buffer()->willOverwriteCanvas();
2485 }
2486
2385 } // namespace blink 2487 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/html/canvas/CanvasRenderingContext2D.h ('k') | Source/core/html/canvas/CanvasRenderingContext2DTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698