Chromium Code Reviews| 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 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |