| 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 |