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

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

Issue 1008173003: Move SkPaint mangement for 2D canvas into CanvasRenderingContext2DState (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: fixup2 Created 5 years, 9 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 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1183 c->drawRect(rect, clearPaint); 1183 c->drawRect(rect, clearPaint);
1184 didDraw(dirtyRect); 1184 didDraw(dirtyRect);
1185 } 1185 }
1186 } 1186 }
1187 1187
1188 if (m_hitRegionManager) { 1188 if (m_hitRegionManager) {
1189 m_hitRegionManager->removeHitRegionsInRect(rect, state().transform()); 1189 m_hitRegionManager->removeHitRegionsInRect(rect, state().transform());
1190 } 1190 }
1191 } 1191 }
1192 1192
1193 // FIXME(crbug.com/425531): Funtional.h cannot handle override function signatur e. 1193 static void drawRectOnCanvas(const FloatRect& rect, SkCanvas* canvas, const SkPa int* paint)
Justin Novosad 2015/03/19 19:45:29 This function is significantly different from 1st
1194 static void fillRectOnContext(GraphicsContext* context, const FloatRect& rect)
1195 { 1194 {
1196 context->fillRect(rect); 1195 if (paint->getStyle() == SkPaint::kStroke_Style && ((rect.width() > 0) ^ (re ct.height() > 0))) {
Stephen White 2015/03/19 20:35:17 Suggest (A != B) instead of xor'ing bools.
Justin Novosad 2015/03/19 21:03:36 Acknowledged.
1197 } 1196 // When stroking, we must skip the zero-dimension segments
1197 SkPath path;
1198 path.moveTo(rect.x(), rect.y());
1199 path.lineTo(rect.maxX(), rect.maxY());
1200 path.close();
1201 canvas->drawPath(path, *paint);
1202 return;
1203 }
1198 1204
1199 static void strokeRectOnContext(GraphicsContext* context, const FloatRect& rect) 1205 canvas->drawRect(rect, *paint);
1200 {
1201 context->strokeRect(rect);
1202 } 1206 }
1203 1207
1204 void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei ght) 1208 void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei ght)
1205 { 1209 {
1206 if (!validateRectForCanvas(x, y, width, height)) 1210 if (!validateRectForCanvas(x, y, width, height))
1207 return; 1211 return;
1208 1212
1209 GraphicsContext* c = drawingContext(); 1213 if (!drawingCanvas())
1210 if (!c)
1211 return; 1214 return;
1212 if (!state().isTransformInvertible()) 1215 if (!state().isTransformInvertible())
1213 return; 1216 return;
1214 SkIRect clipBounds; 1217 SkIRect clipBounds;
1215 if (!drawingCanvas()->getClipDeviceBounds(&clipBounds)) 1218 if (!drawingCanvas()->getClipDeviceBounds(&clipBounds))
1216 return; 1219 return;
1217 1220
1218 // from the HTML5 Canvas spec: 1221 // from the HTML5 Canvas spec:
1219 // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing 1222 // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing
1220 // If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint n othing 1223 // If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint n othing
1221 Gradient* gradient = c->fillGradient(); 1224 CanvasGradient* gradient = state().fillStyle()->canvasGradient();
1222 if (gradient && gradient->isZeroSize()) 1225 if (gradient && gradient->gradient()->isZeroSize())
1223 return; 1226 return;
1224 1227
1225 FloatRect rect(x, y, width, height); 1228 FloatRect rect(x, y, width, height);
1226 if (rectContainsTransformedRect(rect, clipBounds)) { 1229 if (rectContainsTransformedRect(rect, clipBounds)) {
1227 checkOverdraw(rect, &c->fillPaint(), NoImage, ClipFill); 1230 const SkPaint* paint = state().getPaint(FillPaintType, DrawShadowAndFore ground, DrawLooperShadowStrategy);
1228 c->fillRect(rect); 1231 checkOverdraw(rect, paint, NoImage, ClipFill);
1232 drawRectOnCanvas(rect, drawingCanvas(), paint);
1229 didDraw(clipBounds); 1233 didDraw(clipBounds);
1230 } else if (isFullCanvasCompositeMode(state().globalComposite())) { 1234 } else if (isFullCanvasCompositeMode(state().globalComposite())) {
1231 fullCanvasCompositedDraw(bind(&fillRectOnContext, c, rect)); 1235 fullCanvasCompositedDraw(bind<SkCanvas*, const SkPaint*>(drawRectOnCanva s, rect), FillPaintType, DrawLooperShadowStrategy);
1232 didDraw(clipBounds); 1236 didDraw(clipBounds);
1233 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) { 1237 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) {
1234 clearCanvas(); 1238 clearCanvas();
1235 c->clearShadow(); // Takes care of signaling the overdraw 1239 const SkPaint* paint = state().getPaint(FillPaintType, DrawForegroundOnl y, DrawLooperShadowStrategy);
1236 c->fillRect(rect); 1240 drawRectOnCanvas(rect, drawingCanvas(), paint);
1237 applyShadow(DrawShadowAndForeground);
1238 didDraw(clipBounds); 1241 didDraw(clipBounds);
1239 } else { 1242 } else {
1240 SkIRect dirtyRect; 1243 SkIRect dirtyRect;
1241 if (computeDirtyRect(rect, clipBounds, &dirtyRect)) { 1244 if (computeDirtyRect(rect, clipBounds, &dirtyRect)) {
1242 c->fillRect(rect); 1245 const SkPaint* paint = state().getPaint(FillPaintType, DrawShadowAnd Foreground, DrawLooperShadowStrategy);
1246 drawRectOnCanvas(rect, drawingCanvas(), paint);
1243 didDraw(dirtyRect); 1247 didDraw(dirtyRect);
1244 } 1248 }
1245 } 1249 }
1246 } 1250 }
1247 1251
1248 void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h eight) 1252 void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h eight)
1249 { 1253 {
1250 if (!validateRectForCanvas(x, y, width, height)) 1254 if (!validateRectForCanvas(x, y, width, height))
1251 return; 1255 return;
1252 1256
1253 if (!(state().lineWidth() >= 0)) 1257 if (!(state().lineWidth() >= 0))
1254 return; 1258 return;
1255 1259
1256 GraphicsContext* c = drawingContext(); 1260 if (!drawingCanvas())
1257 if (!c)
1258 return; 1261 return;
1262
1259 if (!state().isTransformInvertible()) 1263 if (!state().isTransformInvertible())
1260 return; 1264 return;
1265
1261 SkIRect clipBounds; 1266 SkIRect clipBounds;
1262 if (!drawingCanvas()->getClipDeviceBounds(&clipBounds)) 1267 if (!drawingCanvas()->getClipDeviceBounds(&clipBounds))
1263 return; 1268 return;
1264 1269
1265 // If gradient size is zero, then paint nothing. 1270 // If gradient size is zero, then paint nothing.
1266 Gradient* gradient = c->strokeGradient(); 1271 CanvasGradient* gradient = state().strokeStyle()->canvasGradient();
1267 if (gradient && gradient->isZeroSize()) 1272 if (gradient && gradient->gradient()->isZeroSize())
1268 return; 1273 return;
1269 1274
1270 FloatRect rect(x, y, width, height); 1275 FloatRect rect(x, y, width, height);
1271 if (isFullCanvasCompositeMode(state().globalComposite())) { 1276 if (isFullCanvasCompositeMode(state().globalComposite())) {
1272 fullCanvasCompositedDraw(bind(&strokeRectOnContext, c, rect)); 1277 fullCanvasCompositedDraw(bind<SkCanvas*, const SkPaint*>(drawRectOnCanva s, rect), StrokePaintType, DrawLooperShadowStrategy);
1273 didDraw(clipBounds); 1278 didDraw(clipBounds);
1274 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) { 1279 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) {
1275 clearCanvas(); 1280 clearCanvas();
1276 c->clearShadow(); 1281 const SkPaint* paint = state().getPaint(StrokePaintType, DrawForegroundO nly, DrawLooperShadowStrategy);
1277 c->strokeRect(rect); 1282 drawRectOnCanvas(rect, drawingCanvas(), paint);
1278 applyShadow(DrawShadowAndForeground);
1279 didDraw(clipBounds); 1283 didDraw(clipBounds);
1280 } else { 1284 } else {
1281 FloatRect boundingRect = rect; 1285 FloatRect boundingRect = rect;
1282 boundingRect.inflate(state().lineWidth() / 2); 1286 boundingRect.inflate(state().lineWidth() / 2);
1283 SkIRect dirtyRect; 1287 SkIRect dirtyRect;
1284 if (computeDirtyRect(boundingRect, clipBounds, &dirtyRect)) { 1288 if (computeDirtyRect(boundingRect, clipBounds, &dirtyRect)) {
1285 c->strokeRect(rect); 1289 const SkPaint* paint = state().getPaint(StrokePaintType, DrawShadowA ndForeground, DrawLooperShadowStrategy);
1290 drawRectOnCanvas(rect, drawingCanvas(), paint);
1286 didDraw(dirtyRect); 1291 didDraw(dirtyRect);
1287 } 1292 }
1288 } 1293 }
1289 } 1294 }
1290 1295
1291 void CanvasRenderingContext2D::applyShadow(ShadowMode shadowMode) 1296 void CanvasRenderingContext2D::applyShadow(ShadowMode shadowMode)
1292 { 1297 {
1293 GraphicsContext* c = drawingContext(); 1298 GraphicsContext* c = drawingContext();
1294 if (!c) 1299 if (!c)
1295 return; 1300 return;
1296 1301
1297 if (shouldDrawShadows()) { 1302 if (state().shouldDrawShadows()) {
1298 c->setShadow(state().shadowOffset(), state().shadowBlur(), state().shado wColor(), 1303 c->setShadow(state().shadowOffset(), state().shadowBlur(), state().shado wColor(),
1299 DrawLooperBuilder::ShadowIgnoresTransforms, DrawLooperBuilder::Shado wRespectsAlpha, shadowMode); 1304 DrawLooperBuilder::ShadowIgnoresTransforms, DrawLooperBuilder::Shado wRespectsAlpha, shadowMode);
1300 } else { 1305 } else {
1301 c->clearShadow(); 1306 c->clearShadow();
1302 } 1307 }
1303 } 1308 }
1304 1309
1305 bool CanvasRenderingContext2D::shouldDrawShadows() const
1306 {
1307 return alphaChannel(state().shadowColor()) && (state().shadowBlur() || !stat e().shadowOffset().isZero());
1308 }
1309
1310 static inline FloatRect normalizeRect(const FloatRect& rect) 1310 static inline FloatRect normalizeRect(const FloatRect& rect)
1311 { 1311 {
1312 return FloatRect(std::min(rect.x(), rect.maxX()), 1312 return FloatRect(std::min(rect.x(), rect.maxX()),
1313 std::min(rect.y(), rect.maxY()), 1313 std::min(rect.y(), rect.maxY()),
1314 std::max(rect.width(), -rect.width()), 1314 std::max(rect.width(), -rect.width()),
1315 std::max(rect.height(), -rect.height())); 1315 std::max(rect.height(), -rect.height()));
1316 } 1316 }
1317 1317
1318 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect) 1318 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect)
1319 { 1319 {
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1492 drawingCanvas()->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); 1492 drawingCanvas()->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK);
1493 } 1493 }
1494 1494
1495 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const SkIRect& transformedRect) const 1495 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect , const SkIRect& transformedRect) const
1496 { 1496 {
1497 FloatQuad quad(rect); 1497 FloatQuad quad(rect);
1498 FloatQuad transformedQuad(FloatRect(transformedRect.x(), transformedRect.y() , transformedRect.width(), transformedRect.height())); 1498 FloatQuad transformedQuad(FloatRect(transformedRect.x(), transformedRect.y() , transformedRect.width(), transformedRect.height()));
1499 return state().transform().mapQuad(quad).containsQuad(transformedQuad); 1499 return state().transform().mapQuad(quad).containsQuad(transformedQuad);
1500 } 1500 }
1501 1501
1502 void CanvasRenderingContext2D::fullCanvasCompositedDraw(PassOwnPtr<Function<void (SkCanvas*, const SkPaint*)>> draw, CanvasPaintType paintType, CanvasShadowStrat egy shadowStrategy)
Stephen White 2015/03/19 20:35:16 It looks like the shadowStrategy is always DrawLoo
Justin Novosad 2015/03/19 21:03:36 It will be needed for drawImage
Stephen White 2015/03/19 22:47:54 The idea was to hide the looper/imagefilter distin
1503 {
1504 ASSERT(isFullCanvasCompositeMode(state().globalComposite()));
1505 ASSERT(draw);
1506
1507 SkCanvas* c = drawingCanvas();
1508 ASSERT(c);
1509
1510 SkPaint layerPaint;
1511 layerPaint.setXfermodeMode(state().globalComposite());
1512 if (state().shouldDrawShadows()) {
1513 // unroll into two independently composited passes if drawing shadows
1514 c->saveLayer(0, &layerPaint);
1515 SkPaint shadowPaint = *state().getPaint(paintType, DrawShadowOnly, shado wStrategy);
1516 shadowPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
1517 (*draw)(c, &shadowPaint);
1518 c->restore();
1519 }
1520
1521 c->saveLayer(0, &layerPaint);
1522 SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroundOnly, s hadowStrategy);
1523 foregroundPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
1524 (*draw)(c, &foregroundPaint);
1525 c->restore();
1526 }
1527
1502 void CanvasRenderingContext2D::fullCanvasCompositedDraw(PassOwnPtr<Closure> draw ) 1528 void CanvasRenderingContext2D::fullCanvasCompositedDraw(PassOwnPtr<Closure> draw )
1503 { 1529 {
1504 ASSERT(isFullCanvasCompositeMode(state().globalComposite())); 1530 ASSERT(isFullCanvasCompositeMode(state().globalComposite()));
1505 1531
1506 GraphicsContext* c = drawingContext(); 1532 GraphicsContext* c = drawingContext();
1507 ASSERT(c); 1533 ASSERT(c);
1508 1534
1509 if (shouldDrawShadows()) { 1535 if (state().shouldDrawShadows()) {
1510 // unroll into two independently composited passes if drawing shadows 1536 // unroll into two independently composited passes if drawing shadows
1511 c->beginLayer(1, state().globalComposite()); 1537 c->beginLayer(1, state().globalComposite());
1512 c->setCompositeOperation(SkXfermode::kSrcOver_Mode); 1538 c->setCompositeOperation(SkXfermode::kSrcOver_Mode);
1513 applyShadow(DrawShadowOnly); 1539 applyShadow(DrawShadowOnly);
1514 (*draw)(); 1540 (*draw)();
1515 c->setCompositeOperation(state().globalComposite()); 1541 c->setCompositeOperation(state().globalComposite());
1516 c->endLayer(); 1542 c->endLayer();
1517 } 1543 }
1518 1544
1519 c->beginLayer(1, state().globalComposite()); 1545 c->beginLayer(1, state().globalComposite());
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1607 *dirtyRect = canvasIRect; 1633 *dirtyRect = canvasIRect;
1608 1634
1609 return true; 1635 return true;
1610 } 1636 }
1611 1637
1612 void CanvasRenderingContext2D::didDraw(const SkIRect& dirtyRect) 1638 void CanvasRenderingContext2D::didDraw(const SkIRect& dirtyRect)
1613 { 1639 {
1614 if (dirtyRect.isEmpty()) 1640 if (dirtyRect.isEmpty())
1615 return; 1641 return;
1616 1642
1617 if (ExpensiveCanvasHeuristicParameters::BlurredShadowsAreExpensive && should DrawShadows() && state().shadowBlur() > 0) { 1643 if (ExpensiveCanvasHeuristicParameters::BlurredShadowsAreExpensive && state( ).shouldDrawShadows() && state().shadowBlur() > 0) {
1618 ImageBuffer* buffer = canvas()->buffer(); 1644 ImageBuffer* buffer = canvas()->buffer();
1619 if (buffer) 1645 if (buffer)
1620 buffer->setHasExpensiveOp(); 1646 buffer->setHasExpensiveOp();
1621 } 1647 }
1622 1648
1623 canvas()->didDraw(SkRect::Make(dirtyRect)); 1649 canvas()->didDraw(SkRect::Make(dirtyRect));
1624 } 1650 }
1625 1651
1626 SkCanvas* CanvasRenderingContext2D::drawingCanvas() const 1652 SkCanvas* CanvasRenderingContext2D::drawingCanvas() const
1627 { 1653 {
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
2411 if (imageType == NonOpaqueImage) 2437 if (imageType == NonOpaqueImage)
2412 return; 2438 return;
2413 if (alpha < 0xFF) 2439 if (alpha < 0xFF)
2414 return; 2440 return;
2415 } 2441 }
2416 2442
2417 canvas()->buffer()->willOverwriteCanvas(); 2443 canvas()->buffer()->willOverwriteCanvas();
2418 } 2444 }
2419 2445
2420 } // namespace blink 2446 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698