WebCore/rendering/RenderSVGImage.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2     Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
       
     3     Copyright (C) 2006 Apple Computer, Inc.
       
     4     Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
       
     5     Copyright (C) 2007, 2008, 2009 Rob Buis <buis@kde.org>
       
     6     Copyright (C) 2009, Google, Inc.
       
     7     Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
       
     8 
       
     9     This library is free software; you can redistribute it and/or
       
    10     modify it under the terms of the GNU Library General Public
       
    11     License as published by the Free Software Foundation; either
       
    12     version 2 of the License, or (at your option) any later version.
       
    13 
       
    14     This library is distributed in the hope that it will be useful,
       
    15     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    17     Library General Public License for more details.
       
    18 
       
    19     You should have received a copy of the GNU Library General Public License
       
    20     along with this library; see the file COPYING.LIB.  If not, write to
       
    21     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    22     Boston, MA 02110-1301, USA.
       
    23 */
       
    24 
       
    25 #include "config.h"
       
    26 
       
    27 #if ENABLE(SVG)
       
    28 #include "RenderSVGImage.h"
       
    29 
       
    30 #include "Attr.h"
       
    31 #include "FloatConversion.h"
       
    32 #include "FloatQuad.h"
       
    33 #include "GraphicsContext.h"
       
    34 #include "PointerEventsHitRules.h"
       
    35 #include "RenderLayer.h"
       
    36 #include "RenderSVGResourceContainer.h"
       
    37 #include "RenderSVGResourceFilter.h"
       
    38 #include "SVGImageElement.h"
       
    39 #include "SVGLength.h"
       
    40 #include "SVGPreserveAspectRatio.h"
       
    41 #include "SVGRenderSupport.h"
       
    42 
       
    43 namespace WebCore {
       
    44 
       
    45 RenderSVGImage::RenderSVGImage(SVGImageElement* impl)
       
    46     : RenderImage(impl)
       
    47     , m_needsTransformUpdate(true)
       
    48 {
       
    49 }
       
    50 
       
    51 void RenderSVGImage::layout()
       
    52 {
       
    53     ASSERT(needsLayout());
       
    54 
       
    55     LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
       
    56     SVGImageElement* image = static_cast<SVGImageElement*>(node());
       
    57 
       
    58     if (m_needsTransformUpdate) {
       
    59         m_localTransform = image->animatedLocalTransform();
       
    60         m_needsTransformUpdate = false;
       
    61     }
       
    62 
       
    63     // minimum height
       
    64     setHeight(errorOccurred() ? intrinsicSize().height() : 0);
       
    65 
       
    66     calcWidth();
       
    67     calcHeight();
       
    68 
       
    69     // FIXME: Optimize caching the repaint rects.
       
    70     m_localBounds = FloatRect(image->x().value(image), image->y().value(image), image->width().value(image), image->height().value(image));
       
    71     m_cachedLocalRepaintRect = FloatRect();
       
    72 
       
    73     // Invalidate all resources of this client, if we changed something.
       
    74     if (m_everHadLayout && selfNeedsLayout())
       
    75         RenderSVGResource::invalidateAllResourcesOfRenderer(this);
       
    76 
       
    77     repainter.repaintAfterLayout();
       
    78     setNeedsLayout(false);
       
    79 }
       
    80 
       
    81 void RenderSVGImage::paint(PaintInfo& paintInfo, int, int)
       
    82 {
       
    83     if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN)
       
    84         return;
       
    85 
       
    86     paintInfo.context->save();
       
    87     paintInfo.context->concatCTM(localToParentTransform());
       
    88 
       
    89     if (paintInfo.phase == PaintPhaseForeground) {
       
    90         PaintInfo savedInfo(paintInfo);
       
    91 
       
    92         if (SVGRenderSupport::prepareToRenderSVGContent(this, paintInfo)) {
       
    93             FloatRect destRect = m_localBounds;
       
    94             FloatRect srcRect(0, 0, image()->width(), image()->height());
       
    95 
       
    96             SVGImageElement* imageElt = static_cast<SVGImageElement*>(node());
       
    97             if (imageElt->preserveAspectRatio().align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE)
       
    98                 imageElt->preserveAspectRatio().transformRect(destRect, srcRect);
       
    99 
       
   100             paintInfo.context->drawImage(image(), DeviceColorSpace, destRect, srcRect);
       
   101         }
       
   102         SVGRenderSupport::finishRenderSVGContent(this, paintInfo, savedInfo.context);
       
   103     }
       
   104 
       
   105     if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth())
       
   106         paintOutline(paintInfo.context, 0, 0, width(), height());
       
   107 
       
   108     paintInfo.context->restore();
       
   109 }
       
   110 
       
   111 void RenderSVGImage::destroy()
       
   112 {
       
   113     RenderSVGResource::invalidateAllResourcesOfRenderer(this);
       
   114     RenderImage::destroy();
       
   115 }
       
   116 
       
   117 bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
       
   118 {
       
   119     // We only draw in the forground phase, so we only hit-test then.
       
   120     if (hitTestAction != HitTestForeground)
       
   121         return false;
       
   122 
       
   123     PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, request, style()->pointerEvents());
       
   124     bool isVisible = (style()->visibility() == VISIBLE);
       
   125     if (isVisible || !hitRules.requireVisible) {
       
   126         FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
       
   127             
       
   128         if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
       
   129             return false;
       
   130 
       
   131         if (hitRules.canHitFill) {
       
   132             if (m_localBounds.contains(localPoint)) {
       
   133                 updateHitTestResult(result, roundedIntPoint(localPoint));
       
   134                 return true;
       
   135             }
       
   136         }
       
   137     }
       
   138 
       
   139     return false;
       
   140 }
       
   141 
       
   142 bool RenderSVGImage::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction)
       
   143 {
       
   144     ASSERT_NOT_REACHED();
       
   145     return false;
       
   146 }
       
   147 
       
   148 FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const
       
   149 {
       
   150     // If we already have a cached repaint rect, return that
       
   151     if (!m_cachedLocalRepaintRect.isEmpty())
       
   152         return m_cachedLocalRepaintRect;
       
   153 
       
   154     m_cachedLocalRepaintRect = m_localBounds;
       
   155     SVGRenderSupport::intersectRepaintRectWithResources(this, m_cachedLocalRepaintRect);
       
   156 
       
   157     return m_cachedLocalRepaintRect;
       
   158 }
       
   159 
       
   160 void RenderSVGImage::imageChanged(WrappedImagePtr image, const IntRect* rect)
       
   161 {
       
   162     RenderImage::imageChanged(image, rect);
       
   163 #if ENABLE(FILTERS)
       
   164     // The image resource defaults to nullImage until the resource arrives.
       
   165     // This empty image may be cached by SVG filter effects which must be invalidated.
       
   166     if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document(), style()->svgStyle()->filterResource()))
       
   167         filter->invalidateClient(this);
       
   168 #endif
       
   169     repaint();
       
   170 }
       
   171 
       
   172 IntRect RenderSVGImage::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
       
   173 {
       
   174     return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
       
   175 }
       
   176 
       
   177 void RenderSVGImage::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed)
       
   178 {
       
   179     SVGRenderSupport::computeRectForRepaint(this, repaintContainer, repaintRect, fixed);
       
   180 }
       
   181 
       
   182 void RenderSVGImage::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const
       
   183 {
       
   184     SVGRenderSupport::mapLocalToContainer(this, repaintContainer, fixed, useTransforms, transformState);
       
   185 }
       
   186 
       
   187 void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, int, int)
       
   188 {
       
   189     // this is called from paint() after the localTransform has already been applied
       
   190     IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates());
       
   191     if (!contentRect.isEmpty())
       
   192         rects.append(contentRect);
       
   193 }
       
   194 
       
   195 void RenderSVGImage::absoluteRects(Vector<IntRect>&, int, int)
       
   196 {
       
   197     // This code path should never be taken for SVG, as we're assuming useTransforms=true everywhere, absoluteQuads should be used.
       
   198     ASSERT_NOT_REACHED();
       
   199 }
       
   200 
       
   201 void RenderSVGImage::absoluteQuads(Vector<FloatQuad>& quads)
       
   202 {
       
   203     quads.append(localToAbsoluteQuad(strokeBoundingBox()));
       
   204 }
       
   205 
       
   206 }
       
   207 
       
   208 #endif // ENABLE(SVG)