1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "core/paint/SVGImagePainter.h"
8 #include "core/paint/ObjectPainter.h"
9 #include "core/rendering/GraphicsContextAnnotator.h"
10 #include "core/rendering/ImageQualityController.h"
11 #include "core/rendering/PaintInfo.h"
12 #include "core/rendering/RenderImageResource.h"
13 #include "core/rendering/svg/RenderSVGImage.h"
14 #include "core/rendering/svg/SVGRenderSupport.h"
15 #include "core/rendering/svg/SVGRenderingContext.h"
16 #include "core/svg/SVGImageElement.h"
17 #include "platform/graphics/DisplayList.h"
18 #include "platform/graphics/GraphicsContext.h"
19 #include "platform/graphics/GraphicsContextStateSaver.h"
23 void SVGImagePainter::paint(PaintInfo& paintInfo)
25 ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderSVGImage);
27 if (paintInfo.phase != PaintPhaseForeground
28 || m_renderSVGImage.style()->visibility() == HIDDEN
29 || !m_renderSVGImage.imageResource()->hasImage())
32 FloatRect invalBox = m_renderSVGImage.paintInvalidationRectInLocalCoordinates();
33 if (!SVGRenderSupport::paintInfoIntersectsPaintInvalidationRect(invalBox, m_renderSVGImage.localToParentTransform(), paintInfo))
36 PaintInfo childPaintInfo(paintInfo);
37 GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);
39 childPaintInfo.applyTransform(m_renderSVGImage.localToParentTransform(), &stateSaver);
41 FloatRect boundingBox = m_renderSVGImage.objectBoundingBox();
42 if (!boundingBox.isEmpty()) {
43 // SVGRenderingContext may taint the state - make sure we're always saving.
44 stateSaver.saveIfNeeded();
46 SVGRenderingContext renderingContext(&m_renderSVGImage, childPaintInfo);
47 if (renderingContext.isRenderingPrepared()) {
48 if (m_renderSVGImage.style()->svgStyle().bufferedRendering() != BR_STATIC) {
49 paintForeground(childPaintInfo);
51 RefPtr<DisplayList>& bufferedForeground = m_renderSVGImage.bufferedForeground();
52 if (!bufferedForeground) {
53 childPaintInfo.context->beginRecording(boundingBox);
54 paintForeground(childPaintInfo);
55 bufferedForeground = childPaintInfo.context->endRecording();
58 childPaintInfo.context->drawDisplayList(bufferedForeground.get());
63 if (m_renderSVGImage.style()->outlineWidth())
64 ObjectPainter(m_renderSVGImage).paintOutline(childPaintInfo, IntRect(invalBox));
67 void SVGImagePainter::paintForeground(PaintInfo& paintInfo)
69 RefPtr<Image> image = m_renderSVGImage.imageResource()->image();
70 FloatRect destRect = m_renderSVGImage.objectBoundingBox();
71 FloatRect srcRect(0, 0, image->width(), image->height());
73 SVGImageElement* imageElement = toSVGImageElement(m_renderSVGImage.element());
74 imageElement->preserveAspectRatio()->currentValue()->transformRect(destRect, srcRect);
76 InterpolationQuality interpolationQuality = InterpolationDefault;
77 if (m_renderSVGImage.style()->svgStyle().bufferedRendering() != BR_STATIC)
78 interpolationQuality = ImageQualityController::imageQualityController()->chooseInterpolationQuality(paintInfo.context, &m_renderSVGImage, image.get(), image.get(), LayoutSize(destRect.size()));
80 InterpolationQuality previousInterpolationQuality = paintInfo.context->imageInterpolationQuality();
81 paintInfo.context->setImageInterpolationQuality(interpolationQuality);
82 paintInfo.context->drawImage(image.get(), destRect, srcRect, CompositeSourceOver);
83 paintInfo.context->setImageInterpolationQuality(previousInterpolationQuality);