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

Side by Side Diff: Source/core/svg/graphics/SVGImage.cpp

Issue 1093673002: Removing the dependency on GraphicsContext for drawing images in 2D canvas (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase Created 5 years, 6 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) 2006 Eric Seidel <eric@webkit.org> 2 * Copyright (C) 2006 Eric Seidel <eric@webkit.org>
3 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
4 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 4 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 #include "platform/TraceEvent.h" 52 #include "platform/TraceEvent.h"
53 #include "platform/geometry/IntRect.h" 53 #include "platform/geometry/IntRect.h"
54 #include "platform/graphics/GraphicsContext.h" 54 #include "platform/graphics/GraphicsContext.h"
55 #include "platform/graphics/ImageBuffer.h" 55 #include "platform/graphics/ImageBuffer.h"
56 #include "platform/graphics/ImageObserver.h" 56 #include "platform/graphics/ImageObserver.h"
57 #include "platform/graphics/paint/ClipRecorder.h" 57 #include "platform/graphics/paint/ClipRecorder.h"
58 #include "platform/graphics/paint/DisplayItemListContextRecorder.h" 58 #include "platform/graphics/paint/DisplayItemListContextRecorder.h"
59 #include "platform/graphics/paint/DrawingRecorder.h" 59 #include "platform/graphics/paint/DrawingRecorder.h"
60 #include "platform/graphics/paint/SkPictureBuilder.h" 60 #include "platform/graphics/paint/SkPictureBuilder.h"
61 #include "third_party/skia/include/core/SkPicture.h" 61 #include "third_party/skia/include/core/SkPicture.h"
62 #include "wtf/Optional.h"
63 #include "wtf/PassRefPtr.h" 62 #include "wtf/PassRefPtr.h"
64 63
65 namespace blink { 64 namespace blink {
66 65
67 SVGImage::SVGImage(ImageObserver* observer) 66 SVGImage::SVGImage(ImageObserver* observer)
68 : Image(observer) 67 : Image(observer)
69 { 68 {
70 } 69 }
71 70
72 SVGImage::~SVGImage() 71 SVGImage::~SVGImage()
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 if (intrinsicSize.isEmpty()) 186 if (intrinsicSize.isEmpty())
188 intrinsicSize = rootElement->currentViewBoxRect().size(); 187 intrinsicSize = rootElement->currentViewBoxRect().size();
189 188
190 if (!intrinsicSize.isEmpty()) 189 if (!intrinsicSize.isEmpty())
191 return expandedIntSize(intrinsicSize); 190 return expandedIntSize(intrinsicSize);
192 191
193 // As last resort, use CSS replaced element fallback size. 192 // As last resort, use CSS replaced element fallback size.
194 return IntSize(300, 150); 193 return IntSize(300, 150);
195 } 194 }
196 195
197 void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize contai nerSize, float zoom, const FloatRect& dstRect, 196 void SVGImage::drawForContainer(SkCanvas* canvas, const SkPaint& paint, const Fl oatSize containerSize, float zoom, const FloatRect& dstRect,
198 const FloatRect& srcRect, SkXfermode::Mode compositeOp) 197 const FloatRect& srcRect)
199 { 198 {
200 if (!m_page) 199 if (!m_page)
201 return; 200 return;
202 201
203 // Temporarily disable the image observer to prevent changeInRect() calls du e re-laying out the image. 202 // Temporarily disable the image observer to prevent changeInRect() calls du e re-laying out the image.
204 ImageObserverDisabler imageObserverDisabler(this); 203 ImageObserverDisabler imageObserverDisabler(this);
205 204
206 IntSize roundedContainerSize = roundedIntSize(containerSize); 205 IntSize roundedContainerSize = roundedIntSize(containerSize);
207 setContainerSize(roundedContainerSize); 206 setContainerSize(roundedContainerSize);
208 207
209 FloatRect scaledSrc = srcRect; 208 FloatRect scaledSrc = srcRect;
210 scaledSrc.scale(1 / zoom); 209 scaledSrc.scale(1 / zoom);
211 210
212 // Compensate for the container size rounding by adjusting the source rect. 211 // Compensate for the container size rounding by adjusting the source rect.
213 FloatSize adjustedSrcSize = scaledSrc.size(); 212 FloatSize adjustedSrcSize = scaledSrc.size();
214 adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height()); 213 adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height());
215 scaledSrc.setSize(adjustedSrcSize); 214 scaledSrc.setSize(adjustedSrcSize);
216 215
217 draw(context, dstRect, scaledSrc, compositeOp, DoNotRespectImageOrientation) ; 216 draw(canvas, paint, dstRect, scaledSrc, DoNotRespectImageOrientation, ClampI mageToSourceRect);
218 } 217 }
219 218
220 bool SVGImage::bitmapForCurrentFrame(SkBitmap* bitmap) 219 bool SVGImage::bitmapForCurrentFrame(SkBitmap* bitmap)
221 { 220 {
222 if (!m_page) 221 if (!m_page)
223 return false; 222 return false;
224 223
225 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size()); 224 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size());
226 if (!buffer) 225 if (!buffer)
227 return false; 226 return false;
228 227
229 drawForContainer(buffer->context(), size(), 1, rect(), rect(), SkXfermode::k SrcOver_Mode); 228 SkPaint paint;
229 drawForContainer(buffer->canvas(), paint, size(), 1, rect(), rect());
230 230
231 *bitmap = buffer->bitmap(); 231 *bitmap = buffer->bitmap();
232 return true; 232 return true;
233 } 233 }
234 234
235 void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize containerSize, 235 void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize containerSize,
236 float zoom, const FloatRect& srcRect, const FloatSize& tileScale, const Floa tPoint& phase, 236 float zoom, const FloatRect& srcRect, const FloatSize& tileScale, const Floa tPoint& phase,
237 SkXfermode::Mode compositeOp, const FloatRect& dstRect, 237 SkXfermode::Mode compositeOp, const FloatRect& dstRect,
238 const IntSize& repeatSpacing) 238 const IntSize& repeatSpacing)
239 { 239 {
240 // Tile adjusted for scaling/stretch. 240 // Tile adjusted for scaling/stretch.
241 FloatRect tile(srcRect); 241 FloatRect tile(srcRect);
242 tile.scale(tileScale.width(), tileScale.height()); 242 tile.scale(tileScale.width(), tileScale.height());
243 243
244 // Expand the tile to account for repeat spacing. 244 // Expand the tile to account for repeat spacing.
245 FloatRect spacedTile(tile); 245 FloatRect spacedTile(tile);
246 spacedTile.expand(repeatSpacing); 246 spacedTile.expand(repeatSpacing);
247 247
248 SkPictureBuilder patternPicture(spacedTile); 248 SkPictureBuilder patternPicture(spacedTile);
249 { 249 {
250 DrawingRecorder patternPictureRecorder(patternPicture.context(), *this, DisplayItem::Type::SVGImage, spacedTile); 250 DrawingRecorder patternPictureRecorder(patternPicture.context(), *this, DisplayItem::Type::SVGImage, spacedTile);
251 if (!patternPictureRecorder.canUseCachedDrawing()) { 251 if (!patternPictureRecorder.canUseCachedDrawing()) {
252 // When generating an expanded tile, make sure we don't draw into th e spacing area. 252 // When generating an expanded tile, make sure we don't draw into th e spacing area.
253 if (tile != spacedTile) 253 if (tile != spacedTile)
254 patternPicture.context().clip(tile); 254 patternPicture.context().clip(tile);
255 drawForContainer(&patternPicture.context(), containerSize, zoom, til e, srcRect, SkXfermode::kSrcOver_Mode); 255 SkPaint paint;
256 drawForContainer(patternPicture.context().canvas(), paint, container Size, zoom, tile, srcRect);
256 } 257 }
257 } 258 }
258 RefPtr<const SkPicture> tilePicture = patternPicture.endRecording(); 259 RefPtr<const SkPicture> tilePicture = patternPicture.endRecording();
259 260
260 SkMatrix patternTransform; 261 SkMatrix patternTransform;
261 patternTransform.setTranslate(phase.x() + spacedTile.x(), phase.y() + spaced Tile.y()); 262 patternTransform.setTranslate(phase.x() + spacedTile.x(), phase.y() + spaced Tile.y());
262 RefPtr<SkShader> patternShader = adoptRef(SkShader::CreatePictureShader( 263 RefPtr<SkShader> patternShader = adoptRef(SkShader::CreatePictureShader(
263 tilePicture.get(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMod e, 264 tilePicture.get(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMod e,
264 &patternTransform, nullptr)); 265 &patternTransform, nullptr));
265 266
266 SkPaint paint; 267 SkPaint paint;
267 paint.setShader(patternShader.get()); 268 paint.setShader(patternShader.get());
268 paint.setXfermodeMode(compositeOp); 269 paint.setXfermodeMode(compositeOp);
269 paint.setColorFilter(context->colorFilter()); 270 paint.setColorFilter(context->colorFilter());
270 context->drawRect(dstRect, paint); 271 context->drawRect(dstRect, paint);
271 } 272 }
272 273
273 void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const Fl oatRect& srcRect, SkXfermode::Mode compositeOp, RespectImageOrientationEnum) 274 static bool drawNeedsLayer(const SkPaint& paint)
275 {
276 if (SkColorGetA(paint.getColor()) < 255)
277 return true;
278
279 SkXfermode::Mode xfermode;
280 if (SkXfermode::AsMode(paint.getXfermode(), &xfermode)) {
281 if (xfermode != SkXfermode::kSrcOver_Mode)
282 return true;
283 }
284
285 return false;
286 }
287
288 void SVGImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dst Rect, const FloatRect& srcRect, RespectImageOrientationEnum, ImageClampingMode)
274 { 289 {
275 if (!m_page) 290 if (!m_page)
276 return; 291 return;
277 292
278 float opacity = context->getNormalizedAlpha() / 255.f;
279
280 FrameView* view = frameView(); 293 FrameView* view = frameView();
281 view->resize(containerSize()); 294 view->resize(containerSize());
282 295
283 // Always call scrollToFragment, even if the url is empty, because 296 // Always call scrollToFragment, even if the url is empty, because
284 // there may have been a previous url/fragment that needs to be reset. 297 // there may have been a previous url/fragment that needs to be reset.
285 view->scrollToFragment(m_url); 298 view->scrollToFragment(m_url);
286 299
300 SkPictureBuilder imagePicture(dstRect);
287 { 301 {
288 DisplayItemListContextRecorder contextRecorder(*context); 302 ClipRecorder clipRecorder(imagePicture.context(), *this, DisplayItem::Cl ipNodeImage, LayoutRect(enclosingIntRect(dstRect)));
289 GraphicsContext& paintContext = contextRecorder.context();
290
291 ClipRecorder clipRecorder(paintContext, *this, DisplayItem::ClipNodeImag e, LayoutRect(enclosingIntRect(dstRect)));
292
293 bool hasCompositing = compositeOp != SkXfermode::kSrcOver_Mode;
294 Optional<CompositingRecorder> compositingRecorder;
295 if (hasCompositing || opacity < 1)
296 compositingRecorder.emplace(paintContext, *this, compositeOp, opacit y);
297 303
298 // We can only draw the entire frame, clipped to the rect we want. So co mpute where the top left 304 // We can only draw the entire frame, clipped to the rect we want. So co mpute where the top left
299 // of the image would be if we were drawing without clipping, and transl ate accordingly. 305 // of the image would be if we were drawing without clipping, and transl ate accordingly.
300 FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / sr cRect.height()); 306 FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / sr cRect.height());
301 FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect. location().y() * scale.height()); 307 FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect. location().y() * scale.height());
302 FloatPoint destOffset = dstRect.location() - topLeftOffset; 308 FloatPoint destOffset = dstRect.location() - topLeftOffset;
303 AffineTransform transform = AffineTransform::translation(destOffset.x(), destOffset.y()); 309 AffineTransform transform = AffineTransform::translation(destOffset.x(), destOffset.y());
304 transform.scale(scale.width(), scale.height()); 310 transform.scale(scale.width(), scale.height());
305 TransformRecorder transformRecorder(paintContext, *this, transform); 311 TransformRecorder transformRecorder(imagePicture.context(), *this, trans form);
306 312
307 view->updateLayoutAndStyleForPainting(); 313 view->updateLayoutAndStyleForPainting();
308 view->paint(&paintContext, enclosingIntRect(srcRect)); 314 view->paint(&imagePicture.context(), enclosingIntRect(srcRect));
309 ASSERT(!view->needsLayout()); 315 ASSERT(!view->needsLayout());
310 } 316 }
311 317
318 {
319 SkAutoCanvasRestore ar(canvas, false);
320 if (drawNeedsLayer(paint)) {
321 SkRect layerRect = dstRect;
322 canvas->saveLayer(&layerRect, &paint);
323 }
324 RefPtr<const SkPicture> recording = imagePicture.endRecording();
325 canvas->drawPicture(recording.get());
326 }
327
312 if (imageObserver()) 328 if (imageObserver())
313 imageObserver()->didDraw(this); 329 imageObserver()->didDraw(this);
314 330
315 // Start any (SMIL) animations if needed. This will restart or continue 331 // Start any (SMIL) animations if needed. This will restart or continue
316 // animations if preceded by calls to resetAnimation or stopAnimation 332 // animations if preceded by calls to resetAnimation or stopAnimation
317 // respectively. 333 // respectively.
318 startAnimation(); 334 startAnimation();
319 } 335 }
320 336
321 LayoutBox* SVGImage::embeddedContentBox() const 337 LayoutBox* SVGImage::embeddedContentBox() const
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 484
469 return m_page; 485 return m_page;
470 } 486 }
471 487
472 String SVGImage::filenameExtension() const 488 String SVGImage::filenameExtension() const
473 { 489 {
474 return "svg"; 490 return "svg";
475 } 491 }
476 492
477 } 493 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698