OLD | NEW |
| (Empty) |
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 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> | |
9 * | |
10 * This library is free software; you can redistribute it and/or | |
11 * modify it under the terms of the GNU Library General Public | |
12 * License as published by the Free Software Foundation; either | |
13 * version 2 of the License, or (at your option) any later version. | |
14 * | |
15 * This library is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 * Library General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU Library General Public License | |
21 * along with this library; see the file COPYING.LIB. If not, write to | |
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
23 * Boston, MA 02110-1301, USA. | |
24 */ | |
25 | |
26 #include "config.h" | |
27 | |
28 #include "core/rendering/svg/RenderSVGImage.h" | |
29 | |
30 #include "core/layout/ImageQualityController.h" | |
31 #include "core/layout/LayoutImageResource.h" | |
32 #include "core/layout/PointerEventsHitRules.h" | |
33 #include "core/layout/svg/LayoutSVGResourceContainer.h" | |
34 #include "core/layout/svg/SVGLayoutSupport.h" | |
35 #include "core/layout/svg/SVGResources.h" | |
36 #include "core/layout/svg/SVGResourcesCache.h" | |
37 #include "core/paint/SVGImagePainter.h" | |
38 #include "core/svg/SVGImageElement.h" | |
39 #include "platform/LengthFunctions.h" | |
40 #include "third_party/skia/include/core/SkPicture.h" | |
41 | |
42 namespace blink { | |
43 | |
44 RenderSVGImage::RenderSVGImage(SVGImageElement* impl) | |
45 : RenderSVGModelObject(impl) | |
46 , m_needsBoundariesUpdate(true) | |
47 , m_needsTransformUpdate(true) | |
48 , m_imageResource(LayoutImageResource::create()) | |
49 { | |
50 m_imageResource->initialize(this); | |
51 } | |
52 | |
53 RenderSVGImage::~RenderSVGImage() | |
54 { | |
55 } | |
56 | |
57 void RenderSVGImage::destroy() | |
58 { | |
59 ImageQualityController::remove(this); | |
60 m_imageResource->shutdown(); | |
61 RenderSVGModelObject::destroy(); | |
62 } | |
63 | |
64 FloatSize RenderSVGImage::computeImageViewportSize(ImageResource& cachedImage) c
onst | |
65 { | |
66 if (toSVGImageElement(element())->preserveAspectRatio()->currentValue()->ali
gn() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) | |
67 return m_objectBoundingBox.size(); | |
68 | |
69 // Images with preserveAspectRatio=none should force non-uniform | |
70 // scaling. This can be achieved by setting the image's container size to | |
71 // its viewport size (i.e. if a viewBox is available - use that - else use i
ntrinsic size.) | |
72 // See: http://www.w3.org/TR/SVG/single-page.html, 7.8 The 'preserveAspectRa
tio' attribute. | |
73 Length intrinsicWidth; | |
74 Length intrinsicHeight; | |
75 FloatSize intrinsicRatio; | |
76 cachedImage.computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intr
insicRatio); | |
77 return intrinsicRatio; | |
78 } | |
79 | |
80 static bool containerSizeIsSetForRenderer(ImageResource& cachedImage, const Layo
utObject* renderer) | |
81 { | |
82 const Image* image = cachedImage.image(); | |
83 // If a container size has been specified for this renderer, then | |
84 // imageForRenderer() will return the SVGImageForContainer while image() | |
85 // will return the underlying SVGImage. | |
86 return !image->isSVGImage() || image != cachedImage.imageForRenderer(rendere
r); | |
87 } | |
88 | |
89 bool RenderSVGImage::updateImageViewport() | |
90 { | |
91 SVGImageElement* image = toSVGImageElement(element()); | |
92 FloatRect oldBoundaries = m_objectBoundingBox; | |
93 | |
94 SVGLengthContext lengthContext(image); | |
95 m_objectBoundingBox = FloatRect(image->x()->currentValue()->value(lengthCont
ext), image->y()->currentValue()->value(lengthContext), image->width()->currentV
alue()->value(lengthContext), image->height()->currentValue()->value(lengthConte
xt)); | |
96 bool boundsChanged = oldBoundaries != m_objectBoundingBox; | |
97 | |
98 bool updatedViewport = false; | |
99 ImageResource* cachedImage = m_imageResource->cachedImage(); | |
100 if (cachedImage && cachedImage->usesImageContainerSize()) { | |
101 FloatSize imageViewportSize = computeImageViewportSize(*cachedImage); | |
102 if (LayoutSize(imageViewportSize) != m_imageResource->imageSize(style()-
>effectiveZoom()) | |
103 || !containerSizeIsSetForRenderer(*cachedImage, this)) { | |
104 m_imageResource->setContainerSizeForRenderer(roundedIntSize(imageVie
wportSize)); | |
105 updatedViewport = true; | |
106 } | |
107 } | |
108 | |
109 m_needsBoundariesUpdate |= boundsChanged; | |
110 return updatedViewport || boundsChanged; | |
111 } | |
112 | |
113 void RenderSVGImage::layout() | |
114 { | |
115 ASSERT(needsLayout()); | |
116 | |
117 updateImageViewport(); | |
118 | |
119 bool transformOrBoundariesUpdate = m_needsTransformUpdate || m_needsBoundari
esUpdate; | |
120 if (m_needsTransformUpdate) { | |
121 m_localTransform = toSVGImageElement(element())->calculateAnimatedLocalT
ransform(); | |
122 m_needsTransformUpdate = false; | |
123 } | |
124 | |
125 if (m_needsBoundariesUpdate) { | |
126 m_bufferedForeground.clear(); | |
127 | |
128 m_paintInvalidationBoundingBox = m_objectBoundingBox; | |
129 SVGLayoutSupport::intersectPaintInvalidationRectWithResources(this, m_pa
intInvalidationBoundingBox); | |
130 | |
131 m_needsBoundariesUpdate = false; | |
132 } | |
133 | |
134 // Invalidate all resources of this client if our layout changed. | |
135 if (everHadLayout() && selfNeedsLayout()) | |
136 SVGResourcesCache::clientLayoutChanged(this); | |
137 | |
138 // If our bounds changed, notify the parents. | |
139 if (transformOrBoundariesUpdate) | |
140 RenderSVGModelObject::setNeedsBoundariesUpdate(); | |
141 | |
142 clearNeedsLayout(); | |
143 } | |
144 | |
145 void RenderSVGImage::paint(const PaintInfo& paintInfo, const LayoutPoint&) | |
146 { | |
147 SVGImagePainter(*this).paint(paintInfo); | |
148 } | |
149 | |
150 bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResu
lt& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) | |
151 { | |
152 // We only draw in the forground phase, so we only hit-test then. | |
153 if (hitTestAction != HitTestForeground) | |
154 return false; | |
155 | |
156 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING,
request, style()->pointerEvents()); | |
157 bool isVisible = (style()->visibility() == VISIBLE); | |
158 if (isVisible || !hitRules.requireVisible) { | |
159 FloatPoint localPoint; | |
160 if (!SVGLayoutSupport::transformToUserSpaceAndCheckClipping(this, localT
oParentTransform(), pointInParent, localPoint)) | |
161 return false; | |
162 | |
163 if (hitRules.canHitFill || hitRules.canHitBoundingBox) { | |
164 if (m_objectBoundingBox.contains(localPoint)) { | |
165 updateHitTestResult(result, roundedLayoutPoint(localPoint)); | |
166 return true; | |
167 } | |
168 } | |
169 } | |
170 | |
171 return false; | |
172 } | |
173 | |
174 void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*) | |
175 { | |
176 // The image resource defaults to nullImage until the resource arrives. | |
177 // This empty image may be cached by SVG resources which must be invalidated
. | |
178 if (SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObj
ect(this)) | |
179 resources->removeClientFromCache(this); | |
180 | |
181 // Eventually notify parent resources, that we've changed. | |
182 LayoutSVGResourceContainer::markForLayoutAndParentResourceInvalidation(this,
false); | |
183 | |
184 // Update the SVGImageCache sizeAndScales entry in case image loading finish
ed after layout. | |
185 // (https://bugs.webkit.org/show_bug.cgi?id=99489) | |
186 m_objectBoundingBox = FloatRect(); | |
187 updateImageViewport(); | |
188 | |
189 m_bufferedForeground.clear(); | |
190 | |
191 setShouldDoFullPaintInvalidation(); | |
192 } | |
193 | |
194 void RenderSVGImage::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPo
int&) const | |
195 { | |
196 // this is called from paint() after the localTransform has already been app
lied | |
197 LayoutRect contentRect = LayoutRect(paintInvalidationRectInLocalCoordinates(
)); | |
198 if (!contentRect.isEmpty()) | |
199 rects.append(contentRect); | |
200 } | |
201 | |
202 } // namespace blink | |
OLD | NEW |