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) |
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) != (r
ect.height() > 0))) { |
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(CanvasRenderingContext2DState::F
illPaintType, DrawShadowAndForeground); |
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), CanvasRenderingContext2DState::FillPaintType, Opaque); |
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(CanvasRenderingContext2DState::F
illPaintType, DrawForegroundOnly); |
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(CanvasRenderingContext2DStat
e::FillPaintType, DrawShadowAndForeground); |
| 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), CanvasRenderingContext2DState::StrokePaintType, Opaque); |
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(CanvasRenderingContext2DState::S
trokePaintType, DrawForegroundOnly); |
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(CanvasRenderingContext2DStat
e::StrokePaintType, DrawShadowAndForeground); |
| 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, CanvasRenderingContext2DState::PaintType pai
ntType, OpacityMode bitmapOpacity) |
| 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, bitma
pOpacity); |
| 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, b
itmapOpacity); |
| 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 |