OLD | NEW |
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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 if (intrinsicSize.isEmpty()) | 187 if (intrinsicSize.isEmpty()) |
188 intrinsicSize = rootElement->currentViewBoxRect().size(); | 188 intrinsicSize = rootElement->currentViewBoxRect().size(); |
189 | 189 |
190 if (!intrinsicSize.isEmpty()) | 190 if (!intrinsicSize.isEmpty()) |
191 return expandedIntSize(intrinsicSize); | 191 return expandedIntSize(intrinsicSize); |
192 | 192 |
193 // As last resort, use CSS replaced element fallback size. | 193 // As last resort, use CSS replaced element fallback size. |
194 return IntSize(300, 150); | 194 return IntSize(300, 150); |
195 } | 195 } |
196 | 196 |
197 void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize contai
nerSize, float zoom, const FloatRect& dstRect, | 197 void SVGImage::drawForContainer(SkCanvas* canvas, const SkPaint& paint, const Fl
oatSize containerSize, float zoom, const FloatRect& dstRect, |
198 const FloatRect& srcRect, SkXfermode::Mode compositeOp) | 198 const FloatRect& srcRect) |
199 { | 199 { |
200 if (!m_page) | 200 if (!m_page) |
201 return; | 201 return; |
202 | 202 |
203 // Temporarily disable the image observer to prevent changeInRect() calls du
e re-laying out the image. | 203 // Temporarily disable the image observer to prevent changeInRect() calls du
e re-laying out the image. |
204 ImageObserverDisabler imageObserverDisabler(this); | 204 ImageObserverDisabler imageObserverDisabler(this); |
205 | 205 |
206 IntSize roundedContainerSize = roundedIntSize(containerSize); | 206 IntSize roundedContainerSize = roundedIntSize(containerSize); |
207 setContainerSize(roundedContainerSize); | 207 setContainerSize(roundedContainerSize); |
208 | 208 |
209 FloatRect scaledSrc = srcRect; | 209 FloatRect scaledSrc = srcRect; |
210 scaledSrc.scale(1 / zoom); | 210 scaledSrc.scale(1 / zoom); |
211 | 211 |
212 // Compensate for the container size rounding by adjusting the source rect. | 212 // Compensate for the container size rounding by adjusting the source rect. |
213 FloatSize adjustedSrcSize = scaledSrc.size(); | 213 FloatSize adjustedSrcSize = scaledSrc.size(); |
214 adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(),
roundedContainerSize.height() / containerSize.height()); | 214 adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(),
roundedContainerSize.height() / containerSize.height()); |
215 scaledSrc.setSize(adjustedSrcSize); | 215 scaledSrc.setSize(adjustedSrcSize); |
216 | 216 |
217 draw(context, dstRect, scaledSrc, compositeOp, DoNotRespectImageOrientation)
; | 217 bool shouldClampToSourceRect = true; |
| 218 draw(canvas, paint, dstRect, scaledSrc, DoNotRespectImageOrientation, should
ClampToSourceRect); |
218 } | 219 } |
219 | 220 |
220 bool SVGImage::bitmapForCurrentFrame(SkBitmap* bitmap) | 221 bool SVGImage::bitmapForCurrentFrame(SkBitmap* bitmap) |
221 { | 222 { |
222 if (!m_page) | 223 if (!m_page) |
223 return false; | 224 return false; |
224 | 225 |
225 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size()); | 226 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size()); |
226 if (!buffer) | 227 if (!buffer) |
227 return false; | 228 return false; |
228 | 229 |
229 drawForContainer(buffer->context(), size(), 1, rect(), rect(), SkXfermode::k
SrcOver_Mode); | 230 SkPaint paint; |
| 231 drawForContainer(buffer->canvas(), paint, size(), 1, rect(), rect()); |
230 | 232 |
231 *bitmap = buffer->bitmap(); | 233 *bitmap = buffer->bitmap(); |
232 return true; | 234 return true; |
233 } | 235 } |
234 | 236 |
235 void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize
containerSize, | 237 void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize
containerSize, |
236 float zoom, const FloatRect& srcRect, const FloatSize& tileScale, const Floa
tPoint& phase, | 238 float zoom, const FloatRect& srcRect, const FloatSize& tileScale, const Floa
tPoint& phase, |
237 SkXfermode::Mode compositeOp, const FloatRect& dstRect, | 239 SkXfermode::Mode compositeOp, const FloatRect& dstRect, |
238 const IntSize& repeatSpacing) | 240 const IntSize& repeatSpacing) |
239 { | 241 { |
240 // Tile adjusted for scaling/stretch. | 242 // Tile adjusted for scaling/stretch. |
241 FloatRect tile(srcRect); | 243 FloatRect tile(srcRect); |
242 tile.scale(tileScale.width(), tileScale.height()); | 244 tile.scale(tileScale.width(), tileScale.height()); |
243 | 245 |
244 // Expand the tile to account for repeat spacing. | 246 // Expand the tile to account for repeat spacing. |
245 FloatRect spacedTile(tile); | 247 FloatRect spacedTile(tile); |
246 spacedTile.expand(repeatSpacing); | 248 spacedTile.expand(repeatSpacing); |
247 | 249 |
248 SkPictureBuilder patternPicture(spacedTile); | 250 SkPictureBuilder patternPicture(spacedTile); |
249 { | 251 { |
250 DrawingRecorder patternPictureRecorder(patternPicture.context(), *this,
DisplayItem::Type::SVGImage, spacedTile); | 252 DrawingRecorder patternPictureRecorder(patternPicture.context(), *this,
DisplayItem::Type::SVGImage, spacedTile); |
251 if (!patternPictureRecorder.canUseCachedDrawing()) { | 253 if (!patternPictureRecorder.canUseCachedDrawing()) { |
252 // When generating an expanded tile, make sure we don't draw into th
e spacing area. | 254 // When generating an expanded tile, make sure we don't draw into th
e spacing area. |
253 if (tile != spacedTile) | 255 if (tile != spacedTile) |
254 patternPicture.context().clip(tile); | 256 patternPicture.context().clip(tile); |
255 drawForContainer(&patternPicture.context(), containerSize, zoom, til
e, srcRect, SkXfermode::kSrcOver_Mode); | 257 SkPaint paint; |
| 258 drawForContainer(patternPicture.context().canvas(), paint, container
Size, zoom, tile, srcRect); |
256 } | 259 } |
257 } | 260 } |
258 RefPtr<const SkPicture> tilePicture = patternPicture.endRecording(); | 261 RefPtr<const SkPicture> tilePicture = patternPicture.endRecording(); |
259 | 262 |
260 SkMatrix patternTransform; | 263 SkMatrix patternTransform; |
261 patternTransform.setTranslate(phase.x() + spacedTile.x(), phase.y() + spaced
Tile.y()); | 264 patternTransform.setTranslate(phase.x() + spacedTile.x(), phase.y() + spaced
Tile.y()); |
262 RefPtr<SkShader> patternShader = adoptRef(SkShader::CreatePictureShader( | 265 RefPtr<SkShader> patternShader = adoptRef(SkShader::CreatePictureShader( |
263 tilePicture.get(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMod
e, | 266 tilePicture.get(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMod
e, |
264 &patternTransform, nullptr)); | 267 &patternTransform, nullptr)); |
265 | 268 |
266 SkPaint paint; | 269 SkPaint paint; |
267 paint.setShader(patternShader.get()); | 270 paint.setShader(patternShader.get()); |
268 paint.setXfermodeMode(compositeOp); | 271 paint.setXfermodeMode(compositeOp); |
269 paint.setColorFilter(context->colorFilter()); | 272 paint.setColorFilter(context->colorFilter()); |
270 context->drawRect(dstRect, paint); | 273 context->drawRect(dstRect, paint); |
271 } | 274 } |
272 | 275 |
273 void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const Fl
oatRect& srcRect, SkXfermode::Mode compositeOp, RespectImageOrientationEnum) | 276 static bool drawNeedsLayer(const SkPaint& paint) |
| 277 { |
| 278 if (SkColorGetA(paint.getColor()) < 255) |
| 279 return true; |
| 280 |
| 281 SkXfermode::Mode xfermode; |
| 282 if (SkXfermode::AsMode(paint.getXfermode(), &xfermode)) { |
| 283 if (xfermode != SkXfermode::kSrcOver_Mode) |
| 284 return true; |
| 285 } |
| 286 |
| 287 return false; |
| 288 } |
| 289 |
| 290 void SVGImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dst
Rect, const FloatRect& srcRect, RespectImageOrientationEnum, bool /*shouldClampT
oSourceRect*/) |
274 { | 291 { |
275 if (!m_page) | 292 if (!m_page) |
276 return; | 293 return; |
277 | 294 |
278 float opacity = context->getNormalizedAlpha() / 255.f; | |
279 | |
280 FrameView* view = frameView(); | 295 FrameView* view = frameView(); |
281 view->resize(containerSize()); | 296 view->resize(containerSize()); |
282 | 297 |
283 // Always call scrollToFragment, even if the url is empty, because | 298 // Always call scrollToFragment, even if the url is empty, because |
284 // there may have been a previous url/fragment that needs to be reset. | 299 // there may have been a previous url/fragment that needs to be reset. |
285 view->scrollToFragment(m_url); | 300 view->scrollToFragment(m_url); |
286 | 301 |
| 302 SkPictureBuilder imagePicture(dstRect); |
287 { | 303 { |
288 DisplayItemListContextRecorder contextRecorder(*context); | 304 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 OwnPtr<CompositingRecorder> compositingRecorder; | |
295 if (hasCompositing || opacity < 1) | |
296 compositingRecorder = adoptPtr(new CompositingRecorder(paintContext,
*this, compositeOp, opacity)); | |
297 | 305 |
298 // We can only draw the entire frame, clipped to the rect we want. So co
mpute where the top left | 306 // 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. | 307 // 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()); | 308 FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / sr
cRect.height()); |
301 FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.
location().y() * scale.height()); | 309 FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.
location().y() * scale.height()); |
302 FloatPoint destOffset = dstRect.location() - topLeftOffset; | 310 FloatPoint destOffset = dstRect.location() - topLeftOffset; |
303 AffineTransform transform = AffineTransform::translation(destOffset.x(),
destOffset.y()); | 311 AffineTransform transform = AffineTransform::translation(destOffset.x(),
destOffset.y()); |
304 transform.scale(scale.width(), scale.height()); | 312 transform.scale(scale.width(), scale.height()); |
305 TransformRecorder transformRecorder(paintContext, *this, transform); | 313 TransformRecorder transformRecorder(imagePicture.context(), *this, trans
form); |
306 | 314 |
307 view->updateLayoutAndStyleForPainting(); | 315 view->updateLayoutAndStyleForPainting(); |
308 view->paint(&paintContext, enclosingIntRect(srcRect)); | 316 view->paint(&imagePicture.context(), enclosingIntRect(srcRect)); |
309 ASSERT(!view->needsLayout()); | 317 ASSERT(!view->needsLayout()); |
310 } | 318 } |
311 | 319 |
| 320 { |
| 321 SkAutoCanvasRestore ar(canvas, false); |
| 322 if (drawNeedsLayer(paint)) { |
| 323 SkRect layerRect = dstRect; |
| 324 canvas->saveLayer(&layerRect, &paint); |
| 325 } |
| 326 RefPtr<const SkPicture> recording = imagePicture.endRecording(); |
| 327 canvas->drawPicture(recording.get()); |
| 328 } |
| 329 |
312 if (imageObserver()) | 330 if (imageObserver()) |
313 imageObserver()->didDraw(this); | 331 imageObserver()->didDraw(this); |
314 | 332 |
315 // Start any (SMIL) animations if needed. This will restart or continue | 333 // Start any (SMIL) animations if needed. This will restart or continue |
316 // animations if preceded by calls to resetAnimation or stopAnimation | 334 // animations if preceded by calls to resetAnimation or stopAnimation |
317 // respectively. | 335 // respectively. |
318 startAnimation(); | 336 startAnimation(); |
319 } | 337 } |
320 | 338 |
321 LayoutBox* SVGImage::embeddedContentBox() const | 339 LayoutBox* SVGImage::embeddedContentBox() const |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 | 486 |
469 return m_page; | 487 return m_page; |
470 } | 488 } |
471 | 489 |
472 String SVGImage::filenameExtension() const | 490 String SVGImage::filenameExtension() const |
473 { | 491 { |
474 return "svg"; | 492 return "svg"; |
475 } | 493 } |
476 | 494 |
477 } | 495 } |
OLD | NEW |