OLD | NEW |
1 /** | 1 /** |
2 * Copyright (C) 2007 Rob Buis <buis@kde.org> | 2 * Copyright (C) 2007 Rob Buis <buis@kde.org> |
3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> | 3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> |
4 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> | 4 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> |
5 * Copyright (C) 2009 Google, Inc. All rights reserved. | 5 * Copyright (C) 2009 Google, Inc. All rights reserved. |
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
11 * version 2 of the License, or (at your option) any later version. | 11 * version 2 of the License, or (at your option) any later version. |
12 * | 12 * |
13 * This library is distributed in the hope that it will be useful, | 13 * This library is distributed in the hope that it will be useful, |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 * Library General Public License for more details. | 16 * Library General Public License for more details. |
17 * | 17 * |
18 * You should have received a copy of the GNU Library General Public License | 18 * You should have received a copy of the GNU Library General Public License |
19 * along with this library; see the file COPYING.LIB. If not, write to | 19 * along with this library; see the file COPYING.LIB. If not, write to |
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
21 * Boston, MA 02110-1301, USA. | 21 * Boston, MA 02110-1301, USA. |
22 */ | 22 */ |
23 | 23 |
24 #ifndef SVGRenderSupport_h | 24 #ifndef SVGRenderSupport_h |
25 #define SVGRenderSupport_h | 25 #define SVGRenderSupport_h |
26 | 26 |
27 #include "core/rendering/PaintInfo.h" | |
28 #include "core/rendering/svg/RenderSVGRoot.h" | |
29 #include "core/rendering/svg/RenderSVGShape.h" | |
30 #include "core/rendering/svg/RenderSVGText.h" | |
31 #include "core/rendering/svg/RenderSVGViewportContainer.h" | |
32 #include "core/rendering/svg/SVGResources.h" | |
33 #include "core/rendering/svg/SVGResourcesCache.h" | |
34 | |
35 namespace WebCore { | 27 namespace WebCore { |
36 | 28 |
| 29 class AffineTransform; |
37 class FloatPoint; | 30 class FloatPoint; |
38 class FloatRect; | 31 class FloatRect; |
| 32 class GraphicsContext; |
39 class ImageBuffer; | 33 class ImageBuffer; |
40 class LayoutRect; | 34 class LayoutRect; |
| 35 struct PaintInfo; |
41 class RenderBoxModelObject; | 36 class RenderBoxModelObject; |
42 class RenderGeometryMap; | 37 class RenderGeometryMap; |
43 class RenderLayerModelObject; | 38 class RenderLayerModelObject; |
44 class RenderObject; | 39 class RenderObject; |
45 class RenderStyle; | 40 class RenderStyle; |
46 class RenderSVGRoot; | 41 class RenderSVGRoot; |
| 42 class StrokeData; |
47 class TransformState; | 43 class TransformState; |
48 | 44 |
49 class SVGRenderSupport { | 45 class SVGRenderSupport { |
50 public: | 46 public: |
51 // Shares child layouting code between RenderSVGRoot/RenderSVG(Hidden)Contai
ner | 47 // Shares child layouting code between RenderSVGRoot/RenderSVG(Hidden)Contai
ner |
52 template <typename RenderObjectType> | 48 static void layoutChildren(RenderObject*, bool selfNeedsLayout); |
53 static void layoutChildren(RenderObjectType*, bool selfNeedsLayout); | |
54 | 49 |
55 // Layout resources used by this node. | 50 // Layout resources used by this node. |
56 static void layoutResourcesIfNeeded(const RenderObject*); | 51 static void layoutResourcesIfNeeded(const RenderObject*); |
57 | 52 |
58 // Helper function determining wheter overflow is hidden | 53 // Helper function determining wheter overflow is hidden |
59 static bool isOverflowHidden(const RenderObject*); | 54 static bool isOverflowHidden(const RenderObject*); |
60 | 55 |
61 // Calculates the repaintRect in combination with filter, clipper and masker
in local coordinates. | 56 // Calculates the repaintRect in combination with filter, clipper and masker
in local coordinates. |
62 static void intersectRepaintRectWithResources(const RenderObject*, FloatRect
&); | 57 static void intersectRepaintRectWithResources(const RenderObject*, FloatRect
&); |
63 | 58 |
64 // Determines whether a container needs to be laid out because it's filtered
and a child is being laid out. | 59 // Determines whether a container needs to be laid out because it's filtered
and a child is being laid out. |
65 static bool filtersForceContainerLayout(RenderObject*); | 60 static bool filtersForceContainerLayout(RenderObject*); |
66 | 61 |
67 // Determines whether the passed point lies in a clipping area | 62 // Determines whether the passed point lies in a clipping area |
68 static bool pointInClippingArea(RenderObject*, const FloatPoint&); | 63 static bool pointInClippingArea(RenderObject*, const FloatPoint&); |
69 | 64 |
70 template <typename RenderObjectType> | 65 static void computeContainerBoundingBoxes(const RenderObject* container, Flo
atRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundi
ngBox, FloatRect& repaintBoundingBox); |
71 static void computeContainerBoundingBoxes(const RenderObjectType* container,
FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBo
undingBox, FloatRect& repaintBoundingBox); | |
72 | 66 |
73 static bool paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect
, const AffineTransform& localTransform, const PaintInfo&); | 67 static bool paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect
, const AffineTransform& localTransform, const PaintInfo&); |
74 | 68 |
75 // Important functions used by nearly all SVG renderers centralizing coordin
ate transformations / repaint rect calculations | 69 // Important functions used by nearly all SVG renderers centralizing coordin
ate transformations / repaint rect calculations |
76 static LayoutRect clippedOverflowRectForRepaint(const RenderObject*, const R
enderLayerModelObject* repaintContainer); | 70 static LayoutRect clippedOverflowRectForRepaint(const RenderObject*, const R
enderLayerModelObject* repaintContainer); |
77 static void computeFloatRectForRepaint(const RenderObject*, const RenderLaye
rModelObject* repaintContainer, FloatRect&, bool fixed); | 71 static void computeFloatRectForRepaint(const RenderObject*, const RenderLaye
rModelObject* repaintContainer, FloatRect&, bool fixed); |
78 static void mapLocalToContainer(const RenderObject*, const RenderLayerModelO
bject* repaintContainer, TransformState&, bool* wasFixed = 0); | 72 static void mapLocalToContainer(const RenderObject*, const RenderLayerModelO
bject* repaintContainer, TransformState&, bool* wasFixed = 0); |
79 static const RenderObject* pushMappingToContainer(const RenderObject*, const
RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&); | 73 static const RenderObject* pushMappingToContainer(const RenderObject*, const
RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&); |
80 static bool checkForSVGRepaintDuringLayout(RenderObject*); | 74 static bool checkForSVGRepaintDuringLayout(RenderObject*); |
81 | 75 |
(...skipping 10 matching lines...) Expand all Loading... |
92 // Helper method for determining if a RenderObject marked as text (isText()=
= true) | 86 // Helper method for determining if a RenderObject marked as text (isText()=
= true) |
93 // can/will be rendered as part of a <text>. | 87 // can/will be rendered as part of a <text>. |
94 static bool isRenderableTextNode(const RenderObject*); | 88 static bool isRenderableTextNode(const RenderObject*); |
95 | 89 |
96 private: | 90 private: |
97 static void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& obje
ctBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox); | 91 static void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& obje
ctBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox); |
98 static void invalidateResourcesOfChildren(RenderObject* start); | 92 static void invalidateResourcesOfChildren(RenderObject* start); |
99 static bool layoutSizeOfNearestViewportChanged(const RenderObject* start); | 93 static bool layoutSizeOfNearestViewportChanged(const RenderObject* start); |
100 }; | 94 }; |
101 | 95 |
102 template <typename RenderObjectType> | |
103 void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObjectType* con
tainer, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& s
trokeBoundingBox, FloatRect& repaintBoundingBox) | |
104 { | |
105 objectBoundingBox = FloatRect(); | |
106 objectBoundingBoxValid = false; | |
107 strokeBoundingBox = FloatRect(); | |
108 | |
109 // When computing the strokeBoundingBox, we use the repaintRects of the cont
ainer's children so that the container's stroke includes | |
110 // the resources applied to the children (such as clips and filters). This a
llows filters applied to containers to correctly bound | |
111 // the children, and also improves inlining of SVG content, as the stroke bo
und is used in that situation also. | |
112 for (RenderObject* current = container->firstChild(); current; current = cur
rent->nextSibling()) { | |
113 if (current->isSVGHiddenContainer()) | |
114 continue; | |
115 | |
116 const AffineTransform& transform = current->localToParentTransform(); | |
117 updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, curre
nt, | |
118 transform.mapRect(current->objectBoundingBox())); | |
119 strokeBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoo
rdinates())); | |
120 } | |
121 | |
122 repaintBoundingBox = strokeBoundingBox; | |
123 } | |
124 | |
125 template <typename RenderObjectType> | |
126 void SVGRenderSupport::layoutChildren(RenderObjectType* start, bool selfNeedsLay
out) | |
127 { | |
128 bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start); | |
129 bool transformChanged = transformToRootChanged(start); | |
130 HashSet<RenderObject*> notlayoutedObjects; | |
131 | |
132 for (RenderObject* child = start->firstChild(); child; child = child->nextSi
bling()) { | |
133 bool needsLayout = selfNeedsLayout; | |
134 bool childEverHadLayout = child->everHadLayout(); | |
135 | |
136 if (transformChanged) { | |
137 // If the transform changed we need to update the text metrics (note
: this also happens for layoutSizeChanged=true). | |
138 if (child->isSVGText()) | |
139 toRenderSVGText(child)->setNeedsTextMetricsUpdate(); | |
140 needsLayout = true; | |
141 } | |
142 | |
143 if (layoutSizeChanged) { | |
144 // When selfNeedsLayout is false and the layout size changed, we hav
e to check whether this child uses relative lengths | |
145 if (SVGElement* element = child->node()->isSVGElement() ? toSVGEleme
nt(child->node()) : 0) { | |
146 if (element->hasRelativeLengths()) { | |
147 // When the layout size changed and when using relative valu
es tell the RenderSVGShape to update its shape object | |
148 if (child->isSVGShape()) { | |
149 toRenderSVGShape(child)->setNeedsShapeUpdate(); | |
150 } else if (child->isSVGText()) { | |
151 toRenderSVGText(child)->setNeedsTextMetricsUpdate(); | |
152 toRenderSVGText(child)->setNeedsPositioningValuesUpdate(
); | |
153 } | |
154 | |
155 needsLayout = true; | |
156 } | |
157 } | |
158 } | |
159 | |
160 SubtreeLayoutScope layoutScope(*child); | |
161 // Resource containers are nasty: they can invalidate clients outside th
e current SubtreeLayoutScope. | |
162 // Since they only care about viewport size changes (to resolve their re
lative lengths), we trigger | |
163 // their invalidation directly from SVGSVGElement::svgAttributeChange()
or at a higher | |
164 // SubtreeLayoutScope (in RenderView::layout()). | |
165 if (needsLayout && !child->isSVGResourceContainer()) | |
166 layoutScope.setNeedsLayout(child); | |
167 | |
168 layoutResourcesIfNeeded(child); | |
169 | |
170 if (child->needsLayout()) { | |
171 child->layout(); | |
172 // Renderers are responsible for repainting themselves when changing
, except | |
173 // for the initial paint to avoid potential double-painting caused b
y non-sensical "old" bounds. | |
174 // We could handle this in the individual objects, but for now it's
easier to have | |
175 // parent containers call repaint(). (RenderBlock::layout* has simi
lar logic.) | |
176 if (!childEverHadLayout && !RuntimeEnabledFeatures::repaintAfterLayo
utEnabled()) | |
177 child->repaint(); | |
178 } else if (layoutSizeChanged) { | |
179 notlayoutedObjects.add(child); | |
180 } | |
181 } | |
182 | |
183 if (!layoutSizeChanged) { | |
184 ASSERT(notlayoutedObjects.isEmpty()); | |
185 return; | |
186 } | |
187 | |
188 // If the layout size changed, invalidate all resources of all children that
didn't go through the layout() code path. | |
189 HashSet<RenderObject*>::iterator end = notlayoutedObjects.end(); | |
190 for (HashSet<RenderObject*>::iterator it = notlayoutedObjects.begin(); it !=
end; ++it) | |
191 invalidateResourcesOfChildren(*it); | |
192 } | |
193 | |
194 // Update a bounding box taking into account the validity of the other bounding
box. | |
195 inline void SVGRenderSupport::updateObjectBoundingBox(FloatRect& objectBoundingB
ox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBo
x) | |
196 { | |
197 bool otherValid = other->isSVGContainer() ? toRenderSVGContainer(other)->isO
bjectBoundingBoxValid() : true; | |
198 if (!otherValid) | |
199 return; | |
200 | |
201 if (!objectBoundingBoxValid) { | |
202 objectBoundingBox = otherBoundingBox; | |
203 objectBoundingBoxValid = true; | |
204 return; | |
205 } | |
206 | |
207 objectBoundingBox.uniteEvenIfEmpty(otherBoundingBox); | |
208 } | |
209 | |
210 inline void SVGRenderSupport::invalidateResourcesOfChildren(RenderObject* start) | |
211 { | |
212 ASSERT(!start->needsLayout()); | |
213 if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObj
ect(start)) | |
214 resources->removeClientFromCache(start, false); | |
215 | |
216 for (RenderObject* child = start->slowFirstChild(); child; child = child->ne
xtSibling()) | |
217 invalidateResourcesOfChildren(child); | |
218 } | |
219 | |
220 inline bool SVGRenderSupport::layoutSizeOfNearestViewportChanged(const RenderObj
ect* start) | |
221 { | |
222 while (start && !start->isSVGRoot() && !start->isSVGViewportContainer()) | |
223 start = start->parent(); | |
224 | |
225 ASSERT(start); | |
226 ASSERT(start->isSVGRoot() || start->isSVGViewportContainer()); | |
227 if (start->isSVGViewportContainer()) | |
228 return toRenderSVGViewportContainer(start)->isLayoutSizeChanged(); | |
229 | |
230 return toRenderSVGRoot(start)->isLayoutSizeChanged(); | |
231 } | |
232 | |
233 } // namespace WebCore | 96 } // namespace WebCore |
234 | 97 |
235 #endif // SVGRenderSupport_h | 98 #endif // SVGRenderSupport_h |
OLD | NEW |