blob: 2d9c12a67275094796b0ad89095080d5a62d322b [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/paint/SVGImagePainter.h"
#include "core/paint/ObjectPainter.h"
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/ImageQualityController.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderImageResource.h"
#include "core/rendering/svg/RenderSVGImage.h"
#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/svg/SVGImageElement.h"
#include "platform/graphics/DisplayList.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
namespace blink {
void SVGImagePainter::paint(PaintInfo& paintInfo)
{
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderSVGImage);
if (paintInfo.phase != PaintPhaseForeground
|| m_renderSVGImage.style()->visibility() == HIDDEN
|| !m_renderSVGImage.imageResource()->hasImage())
return;
FloatRect invalBox = m_renderSVGImage.paintInvalidationRectInLocalCoordinates();
if (!SVGRenderSupport::paintInfoIntersectsPaintInvalidationRect(invalBox, m_renderSVGImage.localToParentTransform(), paintInfo))
return;
PaintInfo childPaintInfo(paintInfo);
GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);
childPaintInfo.applyTransform(m_renderSVGImage.localToParentTransform(), &stateSaver);
FloatRect boundingBox = m_renderSVGImage.objectBoundingBox();
if (!boundingBox.isEmpty()) {
// SVGRenderingContext may taint the state - make sure we're always saving.
stateSaver.saveIfNeeded();
SVGRenderingContext renderingContext(&m_renderSVGImage, childPaintInfo);
if (renderingContext.isRenderingPrepared()) {
if (m_renderSVGImage.style()->svgStyle().bufferedRendering() != BR_STATIC) {
paintForeground(childPaintInfo);
} else {
RefPtr<DisplayList>& bufferedForeground = m_renderSVGImage.bufferedForeground();
if (!bufferedForeground) {
childPaintInfo.context->beginRecording(boundingBox);
paintForeground(childPaintInfo);
bufferedForeground = childPaintInfo.context->endRecording();
}
childPaintInfo.context->drawDisplayList(bufferedForeground.get());
}
}
}
if (m_renderSVGImage.style()->outlineWidth())
ObjectPainter(m_renderSVGImage).paintOutline(childPaintInfo, IntRect(invalBox));
}
void SVGImagePainter::paintForeground(PaintInfo& paintInfo)
{
RefPtr<Image> image = m_renderSVGImage.imageResource()->image();
FloatRect destRect = m_renderSVGImage.objectBoundingBox();
FloatRect srcRect(0, 0, image->width(), image->height());
SVGImageElement* imageElement = toSVGImageElement(m_renderSVGImage.element());
imageElement->preserveAspectRatio()->currentValue()->transformRect(destRect, srcRect);
InterpolationQuality interpolationQuality = InterpolationDefault;
if (m_renderSVGImage.style()->svgStyle().bufferedRendering() != BR_STATIC)
interpolationQuality = ImageQualityController::imageQualityController()->chooseInterpolationQuality(paintInfo.context, &m_renderSVGImage, image.get(), image.get(), LayoutSize(destRect.size()));
InterpolationQuality previousInterpolationQuality = paintInfo.context->imageInterpolationQuality();
paintInfo.context->setImageInterpolationQuality(interpolationQuality);
paintInfo.context->drawImage(image.get(), destRect, srcRect, CompositeSourceOver);
paintInfo.context->setImageInterpolationQuality(previousInterpolationQuality);
}
} // namespace blink