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.
4
5 #include "config.h"
6 #include "core/paint/SVGImagePainter.h"
7
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/GraphicsContextStateSaver.h"
18
19 namespace blink {
20
paint(PaintInfo & paintInfo)21 void SVGImagePainter::paint(PaintInfo& paintInfo)
22 {
23 ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderSVGImage);
24
25 if (paintInfo.phase != PaintPhaseForeground
26 || m_renderSVGImage.style()->visibility() == HIDDEN
27 || !m_renderSVGImage.imageResource()->hasImage())
28 return;
29
30 FloatRect boundingBox = m_renderSVGImage.paintInvalidationRectInLocalCoordinates();
31 if (!SVGRenderSupport::paintInfoIntersectsPaintInvalidationRect(boundingBox, m_renderSVGImage.localToParentTransform(), paintInfo))
32 return;
33
34 PaintInfo childPaintInfo(paintInfo);
35 GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);
36
37 childPaintInfo.applyTransform(m_renderSVGImage.localToParentTransform(), &stateSaver);
38
39 if (!m_renderSVGImage.objectBoundingBox().isEmpty()) {
40 // SVGRenderingContext may taint the state - make sure we're always saving.
41 stateSaver.saveIfNeeded();
42
43 SVGRenderingContext renderingContext(&m_renderSVGImage, childPaintInfo);
44 if (renderingContext.isRenderingPrepared()) {
45 if (m_renderSVGImage.style()->svgStyle().bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_renderSVGImage.bufferedForeground()))
46 return;
47
48 paintForeground(m_renderSVGImage, childPaintInfo);
49 }
50 }
51
52 if (m_renderSVGImage.style()->outlineWidth())
53 ObjectPainter(m_renderSVGImage).paintOutline(childPaintInfo, IntRect(boundingBox));
54 }
55
paintForeground(RenderSVGImage & renderer,PaintInfo & paintInfo)56 void SVGImagePainter::paintForeground(RenderSVGImage& renderer, PaintInfo& paintInfo)
57 {
58 RefPtr<Image> image = renderer.imageResource()->image();
59 FloatRect destRect = renderer.objectBoundingBox();
60 FloatRect srcRect(0, 0, image->width(), image->height());
61
62 SVGImageElement* imageElement = toSVGImageElement(renderer.element());
63 imageElement->preserveAspectRatio()->currentValue()->transformRect(destRect, srcRect);
64
65 InterpolationQuality interpolationQuality = InterpolationDefault;
66 if (renderer.style()->svgStyle().bufferedRendering() != BR_STATIC)
67 interpolationQuality = ImageQualityController::imageQualityController()->chooseInterpolationQuality(paintInfo.context, &renderer, image.get(), image.get(), LayoutSize(destRect.size()));
68
69 InterpolationQuality previousInterpolationQuality = paintInfo.context->imageInterpolationQuality();
70 paintInfo.context->setImageInterpolationQuality(interpolationQuality);
71 paintInfo.context->drawImage(image.get(), destRect, srcRect, CompositeSourceOver);
72 paintInfo.context->setImageInterpolationQuality(previousInterpolationQuality);
73 }
74
75 } // namespace blink
76