darin@apple.com | 640fa30 | 2008-02-15 05:03:55 +0000 | [diff] [blame] | 1 | /* |
rwlbuis@webkit.org | 32a5f4c | 2008-07-09 20:36:45 +0000 | [diff] [blame] | 2 | * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org> |
krit@webkit.org | 5fcb898 | 2011-01-08 20:54:58 +0000 | [diff] [blame] | 3 | * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> |
| 4 | * Copyright (C) 2007 Eric Seidel <eric@webkit.org> |
| 5 | * Copyright (C) 2009 Google, Inc. All rights reserved. |
| 6 | * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> |
krit@webkit.org | 6e42616 | 2010-02-26 18:02:26 +0000 | [diff] [blame] | 7 | * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
oliver | b3a02bf | 2007-10-12 11:36:01 +0000 | [diff] [blame] | 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 |
ddkilzer | cd662e6 | 2007-11-03 13:35:52 +0000 | [diff] [blame] | 21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 22 | * Boston, MA 02110-1301, USA. |
oliver | b3a02bf | 2007-10-12 11:36:01 +0000 | [diff] [blame] | 23 | */ |
| 24 | |
| 25 | #include "config.h" |
oliver | f69ac65 | 2007-10-12 13:37:01 +0000 | [diff] [blame] | 26 | #include "SVGRenderSupport.h" |
| 27 | |
zimmermann@webkit.org | e62f8ac | 2010-04-24 12:47:00 +0000 | [diff] [blame] | 28 | #include "NodeRenderStyle.h" |
akling@apple.com | dce4d53 | 2014-01-05 11:45:54 +0000 | [diff] [blame] | 29 | #include "RenderElement.h" |
simon.fraser@apple.com | ca41ec6 | 2012-05-25 21:42:32 +0000 | [diff] [blame] | 30 | #include "RenderGeometryMap.h" |
akling@apple.com | dce4d53 | 2014-01-05 11:45:54 +0000 | [diff] [blame] | 31 | #include "RenderIterator.h" |
eric@webkit.org | b35848a | 2010-06-10 08:33:22 +0000 | [diff] [blame] | 32 | #include "RenderLayer.h" |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 33 | #include "RenderSVGImage.h" |
krit@webkit.org | 6e42616 | 2010-02-26 18:02:26 +0000 | [diff] [blame] | 34 | #include "RenderSVGResourceClipper.h" |
krit@webkit.org | 5703bb2 | 2010-04-20 12:52:54 +0000 | [diff] [blame] | 35 | #include "RenderSVGResourceFilter.h" |
krit@webkit.org | 39cab22 | 2010-03-28 16:01:18 +0000 | [diff] [blame] | 36 | #include "RenderSVGResourceMarker.h" |
krit@webkit.org | 0b226d6 | 2010-02-18 23:12:30 +0000 | [diff] [blame] | 37 | #include "RenderSVGResourceMasker.h" |
zimmermann@webkit.org | 853c648 | 2010-07-06 07:28:44 +0000 | [diff] [blame] | 38 | #include "RenderSVGRoot.h" |
commit-queue@webkit.org | 8006680 | 2012-02-22 20:31:11 +0000 | [diff] [blame] | 39 | #include "RenderSVGText.h" |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 40 | #include "RenderSVGTransformableContainer.h" |
krit@webkit.org | ef8159d | 2012-02-08 19:19:03 +0000 | [diff] [blame] | 41 | #include "RenderSVGViewportContainer.h" |
zimmermann@webkit.org | b984a40 | 2010-07-29 13:50:51 +0000 | [diff] [blame] | 42 | #include "SVGResources.h" |
commit-queue@webkit.org | b22ae9f | 2011-11-15 01:43:16 +0000 | [diff] [blame] | 43 | #include "SVGResourcesCache.h" |
eric@webkit.org | abec5ee | 2009-05-05 08:14:44 +0000 | [diff] [blame] | 44 | #include "TransformState.h" |
oliver | b3a02bf | 2007-10-12 11:36:01 +0000 | [diff] [blame] | 45 | |
| 46 | namespace WebCore { |
| 47 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 48 | FloatRect SVGRenderSupport::repaintRectForRendererInLocalCoordinatesExcludingSVGShadow(const RenderElement& renderer) |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 49 | { |
| 50 | // FIXME: Add support for RenderSVGBlock. |
| 51 | |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 52 | if (is<RenderSVGModelObject>(renderer)) |
| 53 | return downcast<RenderSVGModelObject>(renderer).repaintRectInLocalCoordinatesExcludingSVGShadow(); |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 54 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 55 | return renderer.repaintRectInLocalCoordinates(); |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 56 | } |
| 57 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 58 | LayoutRect SVGRenderSupport::clippedOverflowRectForRepaint(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer) |
eric@webkit.org | abec5ee | 2009-05-05 08:14:44 +0000 | [diff] [blame] | 59 | { |
| 60 | // Return early for any cases where we don't actually paint |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 61 | if (renderer.style().visibility() != VISIBLE && !renderer.enclosingLayer()->hasVisibleContent()) |
leviw@chromium.org | 4da729d | 2011-08-15 19:07:58 +0000 | [diff] [blame] | 62 | return LayoutRect(); |
eric@webkit.org | abec5ee | 2009-05-05 08:14:44 +0000 | [diff] [blame] | 63 | |
| 64 | // Pass our local paint rect to computeRectForRepaint() which will |
| 65 | // map to parent coords and recurse up the parent chain. |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 66 | FloatRect repaintRect = repaintRectForRendererInLocalCoordinatesExcludingSVGShadow(renderer); |
| 67 | const SVGRenderStyle& svgStyle = renderer.style().svgStyle(); |
akling@apple.com | 148c287 | 2013-11-02 05:01:08 +0000 | [diff] [blame] | 68 | if (const ShadowData* shadow = svgStyle.shadow()) |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 69 | shadow->adjustRectForShadow(repaintRect); |
zalan@apple.com | 6d4f959 | 2015-10-07 21:14:16 +0000 | [diff] [blame] | 70 | return enclosingLayoutRect(renderer.computeFloatRectForRepaint(repaintRect, repaintContainer)); |
eric@webkit.org | abec5ee | 2009-05-05 08:14:44 +0000 | [diff] [blame] | 71 | } |
| 72 | |
zalan@apple.com | 6d4f959 | 2015-10-07 21:14:16 +0000 | [diff] [blame] | 73 | FloatRect SVGRenderSupport::computeFloatRectForRepaint(const RenderElement& renderer, const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed) |
eric@webkit.org | abec5ee | 2009-05-05 08:14:44 +0000 | [diff] [blame] | 74 | { |
zalan@apple.com | 6d4f959 | 2015-10-07 21:14:16 +0000 | [diff] [blame] | 75 | FloatRect adjustedRect = repaintRect; |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 76 | const SVGRenderStyle& svgStyle = renderer.style().svgStyle(); |
akling@apple.com | 148c287 | 2013-11-02 05:01:08 +0000 | [diff] [blame] | 77 | if (const ShadowData* shadow = svgStyle.shadow()) |
zalan@apple.com | 6d4f959 | 2015-10-07 21:14:16 +0000 | [diff] [blame] | 78 | shadow->adjustRectForShadow(adjustedRect); |
| 79 | adjustedRect.inflate(renderer.style().outlineWidth()); |
zimmermann@webkit.org | 08fae32 | 2010-02-11 20:53:39 +0000 | [diff] [blame] | 80 | |
zimmermann@webkit.org | 80d8963 | 2011-11-29 09:40:51 +0000 | [diff] [blame] | 81 | // Translate to coords in our parent renderer, and then call computeFloatRectForRepaint() on our parent. |
zalan@apple.com | 6d4f959 | 2015-10-07 21:14:16 +0000 | [diff] [blame] | 82 | adjustedRect = renderer.localToParentTransform().mapRect(adjustedRect); |
| 83 | return renderer.parent()->computeFloatRectForRepaint(adjustedRect, repaintContainer, fixed); |
eric@webkit.org | abec5ee | 2009-05-05 08:14:44 +0000 | [diff] [blame] | 84 | } |
| 85 | |
commit-queue@webkit.org | 0ab2522 | 2015-02-16 23:19:23 +0000 | [diff] [blame] | 86 | const RenderElement& SVGRenderSupport::localToParentTransform(const RenderElement& renderer, AffineTransform &transform) |
eric@webkit.org | abec5ee | 2009-05-05 08:14:44 +0000 | [diff] [blame] | 87 | { |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 88 | ASSERT(renderer.parent()); |
| 89 | auto& parent = *renderer.parent(); |
leviw@chromium.org | 248a715 | 2012-08-16 18:00:34 +0000 | [diff] [blame] | 90 | |
commit-queue@webkit.org | 0ab2522 | 2015-02-16 23:19:23 +0000 | [diff] [blame] | 91 | // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform |
| 92 | // to map an element from SVG viewport coordinates to CSS box coordinates. |
| 93 | if (is<RenderSVGRoot>(parent)) |
| 94 | transform = downcast<RenderSVGRoot>(parent).localToBorderBoxTransform() * renderer.localToParentTransform(); |
| 95 | else |
| 96 | transform = renderer.localToParentTransform(); |
| 97 | |
| 98 | return parent; |
| 99 | } |
| 100 | |
| 101 | void SVGRenderSupport::mapLocalToContainer(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed) |
| 102 | { |
| 103 | AffineTransform transform; |
| 104 | auto& parent = localToParentTransform(renderer, transform); |
| 105 | |
| 106 | transformState.applyTransform(transform); |
commit-queue@webkit.org | 5849cae | 2014-02-28 16:35:27 +0000 | [diff] [blame] | 107 | |
leviw@chromium.org | 63f7387 | 2012-10-11 23:47:28 +0000 | [diff] [blame] | 108 | MapCoordinatesFlags mode = UseTransforms; |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 109 | parent.mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); |
eric@webkit.org | abec5ee | 2009-05-05 08:14:44 +0000 | [diff] [blame] | 110 | } |
| 111 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 112 | const RenderElement* SVGRenderSupport::pushMappingToContainer(const RenderElement& renderer, const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) |
simon.fraser@apple.com | ca41ec6 | 2012-05-25 21:42:32 +0000 | [diff] [blame] | 113 | { |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 114 | ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != &renderer); |
simon.fraser@apple.com | ca41ec6 | 2012-05-25 21:42:32 +0000 | [diff] [blame] | 115 | |
commit-queue@webkit.org | 0ab2522 | 2015-02-16 23:19:23 +0000 | [diff] [blame] | 116 | AffineTransform transform; |
| 117 | auto& parent = localToParentTransform(renderer, transform); |
simon.fraser@apple.com | ca41ec6 | 2012-05-25 21:42:32 +0000 | [diff] [blame] | 118 | |
commit-queue@webkit.org | 0ab2522 | 2015-02-16 23:19:23 +0000 | [diff] [blame] | 119 | geometryMap.push(&renderer, transform); |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 120 | return &parent; |
simon.fraser@apple.com | ca41ec6 | 2012-05-25 21:42:32 +0000 | [diff] [blame] | 121 | } |
| 122 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 123 | bool SVGRenderSupport::checkForSVGRepaintDuringLayout(const RenderElement& renderer) |
pdr@google.com | 8e74d21 | 2012-11-07 19:26:57 +0000 | [diff] [blame] | 124 | { |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 125 | if (!renderer.checkForRepaintDuringLayout()) |
pdr@google.com | 8e74d21 | 2012-11-07 19:26:57 +0000 | [diff] [blame] | 126 | return false; |
| 127 | // When a parent container is transformed in SVG, all children will be painted automatically |
| 128 | // so we are able to skip redundant repaint checks. |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 129 | auto parent = renderer.parent(); |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 130 | return !(is<RenderSVGContainer>(parent) && downcast<RenderSVGContainer>(*parent).didTransformToRootUpdate()); |
pdr@google.com | 8e74d21 | 2012-11-07 19:26:57 +0000 | [diff] [blame] | 131 | } |
| 132 | |
commit-queue@webkit.org | 8b29eba | 2012-03-26 14:36:59 +0000 | [diff] [blame] | 133 | // Update a bounding box taking into account the validity of the other bounding box. |
| 134 | static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox) |
eric@webkit.org | 39ad358 | 2009-04-16 17:09:59 +0000 | [diff] [blame] | 135 | { |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 136 | bool otherValid = is<RenderSVGContainer>(*other) ? downcast<RenderSVGContainer>(*other).isObjectBoundingBoxValid() : true; |
commit-queue@webkit.org | 8b29eba | 2012-03-26 14:36:59 +0000 | [diff] [blame] | 137 | if (!otherValid) |
| 138 | return; |
commit-queue@webkit.org | ce5c120 | 2012-01-18 03:16:47 +0000 | [diff] [blame] | 139 | |
commit-queue@webkit.org | 8b29eba | 2012-03-26 14:36:59 +0000 | [diff] [blame] | 140 | if (!objectBoundingBoxValid) { |
| 141 | objectBoundingBox = otherBoundingBox; |
| 142 | objectBoundingBoxValid = true; |
| 143 | return; |
| 144 | } |
| 145 | |
| 146 | objectBoundingBox.uniteEvenIfEmpty(otherBoundingBox); |
| 147 | } |
| 148 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 149 | void SVGRenderSupport::computeContainerBoundingBoxes(const RenderElement& container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox) |
commit-queue@webkit.org | 8b29eba | 2012-03-26 14:36:59 +0000 | [diff] [blame] | 150 | { |
schenney@chromium.org | 73c4307 | 2012-06-15 15:37:12 +0000 | [diff] [blame] | 151 | objectBoundingBox = FloatRect(); |
| 152 | objectBoundingBoxValid = false; |
| 153 | strokeBoundingBox = FloatRect(); |
| 154 | |
| 155 | // When computing the strokeBoundingBox, we use the repaintRects of the container's children so that the container's stroke includes |
| 156 | // the resources applied to the children (such as clips and filters). This allows filters applied to containers to correctly bound |
| 157 | // the children, and also improves inlining of SVG content, as the stroke bound is used in that situation also. |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 158 | for (RenderObject* current = container.firstChild(); current; current = current->nextSibling()) { |
zimmermann@webkit.org | 41e5b7d | 2010-09-01 07:15:17 +0000 | [diff] [blame] | 159 | if (current->isSVGHiddenContainer()) |
| 160 | continue; |
| 161 | |
commit-queue@webkit.org | 9a59685 | 2014-07-13 06:35:21 +0000 | [diff] [blame] | 162 | // Don't include elements in the union that do not render. |
cdumez@apple.com | e162849 | 2014-10-18 00:21:40 +0000 | [diff] [blame] | 163 | if (is<RenderSVGShape>(*current) && downcast<RenderSVGShape>(*current).isRenderingDisabled()) |
commit-queue@webkit.org | 9a59685 | 2014-07-13 06:35:21 +0000 | [diff] [blame] | 164 | continue; |
| 165 | |
zimmermann@webkit.org | 53660b4 | 2010-09-01 12:32:29 +0000 | [diff] [blame] | 166 | const AffineTransform& transform = current->localToParentTransform(); |
| 167 | if (transform.isIdentity()) { |
commit-queue@webkit.org | 8b29eba | 2012-03-26 14:36:59 +0000 | [diff] [blame] | 168 | updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox()); |
schenney@chromium.org | 73c4307 | 2012-06-15 15:37:12 +0000 | [diff] [blame] | 169 | strokeBoundingBox.unite(current->repaintRectInLocalCoordinates()); |
zimmermann@webkit.org | 53660b4 | 2010-09-01 12:32:29 +0000 | [diff] [blame] | 170 | } else { |
commit-queue@webkit.org | 8b29eba | 2012-03-26 14:36:59 +0000 | [diff] [blame] | 171 | updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox())); |
schenney@chromium.org | 73c4307 | 2012-06-15 15:37:12 +0000 | [diff] [blame] | 172 | strokeBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates())); |
zimmermann@webkit.org | 49f8fa2 | 2010-07-01 09:47:01 +0000 | [diff] [blame] | 173 | } |
eric@webkit.org | 39ad358 | 2009-04-16 17:09:59 +0000 | [diff] [blame] | 174 | } |
schenney@chromium.org | 73c4307 | 2012-06-15 15:37:12 +0000 | [diff] [blame] | 175 | |
| 176 | repaintBoundingBox = strokeBoundingBox; |
zimmermann@webkit.org | 53660b4 | 2010-09-01 12:32:29 +0000 | [diff] [blame] | 177 | } |
eric@webkit.org | 39ad358 | 2009-04-16 17:09:59 +0000 | [diff] [blame] | 178 | |
zimmermann@webkit.org | 53660b4 | 2010-09-01 12:32:29 +0000 | [diff] [blame] | 179 | bool SVGRenderSupport::paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo& paintInfo) |
| 180 | { |
| 181 | if (localTransform.isIdentity()) |
| 182 | return localRepaintRect.intersects(paintInfo.rect); |
| 183 | |
| 184 | return localTransform.mapRect(localRepaintRect).intersects(paintInfo.rect); |
eric@webkit.org | 39ad358 | 2009-04-16 17:09:59 +0000 | [diff] [blame] | 185 | } |
| 186 | |
commit-queue@webkit.org | b3a3e3b | 2016-01-21 17:50:26 +0000 | [diff] [blame] | 187 | RenderSVGRoot* SVGRenderSupport::findTreeRootObject(RenderElement& start) |
zimmermann@webkit.org | 853c648 | 2010-07-06 07:28:44 +0000 | [diff] [blame] | 188 | { |
commit-queue@webkit.org | b3a3e3b | 2016-01-21 17:50:26 +0000 | [diff] [blame] | 189 | return lineageOfType<RenderSVGRoot>(start).first(); |
| 190 | } |
| 191 | |
| 192 | const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderElement& start) |
| 193 | { |
| 194 | return lineageOfType<RenderSVGRoot>(start).first(); |
zimmermann@webkit.org | 853c648 | 2010-07-06 07:28:44 +0000 | [diff] [blame] | 195 | } |
| 196 | |
akling@apple.com | 83ccacb | 2014-02-03 09:02:55 +0000 | [diff] [blame] | 197 | static inline void invalidateResourcesOfChildren(RenderElement& renderer) |
zimmermann@webkit.org | cff3134 | 2010-08-13 10:03:22 +0000 | [diff] [blame] | 198 | { |
akling@apple.com | 83ccacb | 2014-02-03 09:02:55 +0000 | [diff] [blame] | 199 | ASSERT(!renderer.needsLayout()); |
akling@apple.com | 2e79f74 | 2014-09-05 19:25:57 +0000 | [diff] [blame] | 200 | if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) |
akling@apple.com | 83ccacb | 2014-02-03 09:02:55 +0000 | [diff] [blame] | 201 | resources->removeClientFromCache(renderer, false); |
zimmermann@webkit.org | cff3134 | 2010-08-13 10:03:22 +0000 | [diff] [blame] | 202 | |
akling@apple.com | 83ccacb | 2014-02-03 09:02:55 +0000 | [diff] [blame] | 203 | for (auto& child : childrenOfType<RenderElement>(renderer)) |
| 204 | invalidateResourcesOfChildren(child); |
zimmermann@webkit.org | cff3134 | 2010-08-13 10:03:22 +0000 | [diff] [blame] | 205 | } |
| 206 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 207 | static inline bool layoutSizeOfNearestViewportChanged(const RenderElement& renderer) |
krit@webkit.org | ef8159d | 2012-02-08 19:19:03 +0000 | [diff] [blame] | 208 | { |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 209 | const RenderElement* start = &renderer; |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 210 | while (start && !is<RenderSVGRoot>(*start) && !is<RenderSVGViewportContainer>(*start)) |
krit@webkit.org | ef8159d | 2012-02-08 19:19:03 +0000 | [diff] [blame] | 211 | start = start->parent(); |
| 212 | |
| 213 | ASSERT(start); |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 214 | if (is<RenderSVGViewportContainer>(*start)) |
| 215 | return downcast<RenderSVGViewportContainer>(*start).isLayoutSizeChanged(); |
krit@webkit.org | ef8159d | 2012-02-08 19:19:03 +0000 | [diff] [blame] | 216 | |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 217 | return downcast<RenderSVGRoot>(*start).isLayoutSizeChanged(); |
krit@webkit.org | ef8159d | 2012-02-08 19:19:03 +0000 | [diff] [blame] | 218 | } |
| 219 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 220 | bool SVGRenderSupport::transformToRootChanged(RenderElement* ancestor) |
commit-queue@webkit.org | 0827c37 | 2012-02-24 00:52:35 +0000 | [diff] [blame] | 221 | { |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 222 | while (ancestor && !is<RenderSVGRoot>(*ancestor)) { |
| 223 | if (is<RenderSVGTransformableContainer>(*ancestor)) |
| 224 | return downcast<RenderSVGTransformableContainer>(*ancestor).didTransformToRootUpdate(); |
| 225 | if (is<RenderSVGViewportContainer>(*ancestor)) |
| 226 | return downcast<RenderSVGViewportContainer>(*ancestor).didTransformToRootUpdate(); |
commit-queue@webkit.org | 0827c37 | 2012-02-24 00:52:35 +0000 | [diff] [blame] | 227 | ancestor = ancestor->parent(); |
| 228 | } |
| 229 | |
| 230 | return false; |
| 231 | } |
| 232 | |
commit-queue@webkit.org | b3a3e3b | 2016-01-21 17:50:26 +0000 | [diff] [blame] | 233 | void SVGRenderSupport::layoutDifferentRootIfNeeded(const RenderElement& renderer) |
| 234 | { |
| 235 | if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) { |
| 236 | auto* svgRoot = SVGRenderSupport::findTreeRootObject(renderer); |
| 237 | ASSERT(svgRoot); |
| 238 | resources->layoutDifferentRootIfNeeded(svgRoot); |
| 239 | } |
| 240 | } |
| 241 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 242 | void SVGRenderSupport::layoutChildren(RenderElement& start, bool selfNeedsLayout) |
zimmermann@webkit.org | d5d17b3 | 2010-01-14 03:05:30 +0000 | [diff] [blame] | 243 | { |
krit@webkit.org | ef8159d | 2012-02-08 19:19:03 +0000 | [diff] [blame] | 244 | bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start); |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 245 | bool transformChanged = transformToRootChanged(&start); |
timothy_horton@apple.com | 6712c51 | 2012-12-12 01:15:00 +0000 | [diff] [blame] | 246 | bool hasSVGShadow = rendererHasSVGShadow(start); |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 247 | bool needsBoundariesUpdate = start.needsBoundariesUpdate(); |
darin@apple.com | 738e9f5 | 2014-03-13 17:51:59 +0000 | [diff] [blame] | 248 | HashSet<RenderElement*> elementsThatDidNotReceiveLayout; |
zimmermann@webkit.org | 853c648 | 2010-07-06 07:28:44 +0000 | [diff] [blame] | 249 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 250 | for (RenderObject* child = start.firstChild(); child; child = child->nextSibling()) { |
zimmermann@webkit.org | d5d17b3 | 2010-01-14 03:05:30 +0000 | [diff] [blame] | 251 | bool needsLayout = selfNeedsLayout; |
eric@webkit.org | 31f20a9 | 2012-08-09 07:58:50 +0000 | [diff] [blame] | 252 | bool childEverHadLayout = child->everHadLayout(); |
zimmermann@webkit.org | 853c648 | 2010-07-06 07:28:44 +0000 | [diff] [blame] | 253 | |
timothy_horton@apple.com | 6712c51 | 2012-12-12 01:15:00 +0000 | [diff] [blame] | 254 | if (needsBoundariesUpdate && hasSVGShadow) { |
| 255 | // If we have a shadow, our shadow is baked into our children's cached boundaries, |
| 256 | // so they need to update. |
| 257 | child->setNeedsBoundariesUpdate(); |
| 258 | needsLayout = true; |
| 259 | } |
| 260 | |
commit-queue@webkit.org | 0827c37 | 2012-02-24 00:52:35 +0000 | [diff] [blame] | 261 | if (transformChanged) { |
| 262 | // If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true). |
cdumez@apple.com | f381449 | 2014-10-10 23:06:32 +0000 | [diff] [blame] | 263 | if (is<RenderSVGText>(*child)) |
| 264 | downcast<RenderSVGText>(*child).setNeedsTextMetricsUpdate(); |
commit-queue@webkit.org | 0827c37 | 2012-02-24 00:52:35 +0000 | [diff] [blame] | 265 | needsLayout = true; |
| 266 | } |
| 267 | |
zimmermann@webkit.org | 853c648 | 2010-07-06 07:28:44 +0000 | [diff] [blame] | 268 | if (layoutSizeChanged) { |
| 269 | // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths |
cdumez@apple.com | f381449 | 2014-10-10 23:06:32 +0000 | [diff] [blame] | 270 | if (SVGElement* element = is<SVGElement>(*child->node()) ? downcast<SVGElement>(child->node()) : nullptr) { |
ch.dumez@sisa.samsung.com | 7dd31bf | 2013-08-22 21:58:09 +0000 | [diff] [blame] | 271 | if (element->hasRelativeLengths()) { |
reni@webkit.org | f0d767a | 2011-11-30 15:49:02 +0000 | [diff] [blame] | 272 | // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object |
cdumez@apple.com | f381449 | 2014-10-10 23:06:32 +0000 | [diff] [blame] | 273 | if (is<RenderSVGShape>(*child)) |
| 274 | downcast<RenderSVGShape>(*child).setNeedsShapeUpdate(); |
| 275 | else if (is<RenderSVGText>(*child)) { |
| 276 | RenderSVGText& svgText = downcast<RenderSVGText>(*child); |
| 277 | svgText.setNeedsTextMetricsUpdate(); |
| 278 | svgText.setNeedsPositioningValuesUpdate(); |
zimmermann@webkit.org | fec8f1d | 2012-05-16 07:21:07 +0000 | [diff] [blame] | 279 | } |
zimmermann@webkit.org | 853c648 | 2010-07-06 07:28:44 +0000 | [diff] [blame] | 280 | |
| 281 | needsLayout = true; |
| 282 | } |
zimmermann@webkit.org | d5d17b3 | 2010-01-14 03:05:30 +0000 | [diff] [blame] | 283 | } |
| 284 | } |
| 285 | |
eric@webkit.org | 31f20a9 | 2012-08-09 07:58:50 +0000 | [diff] [blame] | 286 | if (needsLayout) |
antti@apple.com | ca2a8ff | 2013-10-04 04:04:35 +0000 | [diff] [blame] | 287 | child->setNeedsLayout(MarkOnlyThis); |
eric@webkit.org | 31f20a9 | 2012-08-09 07:58:50 +0000 | [diff] [blame] | 288 | |
| 289 | if (child->needsLayout()) { |
commit-queue@webkit.org | b3a3e3b | 2016-01-21 17:50:26 +0000 | [diff] [blame] | 290 | layoutDifferentRootIfNeeded(downcast<RenderElement>(*child)); |
cdumez@apple.com | f381449 | 2014-10-10 23:06:32 +0000 | [diff] [blame] | 291 | downcast<RenderElement>(*child).layout(); |
eric@webkit.org | 31f20a9 | 2012-08-09 07:58:50 +0000 | [diff] [blame] | 292 | // Renderers are responsible for repainting themselves when changing, except |
| 293 | // for the initial paint to avoid potential double-painting caused by non-sensical "old" bounds. |
| 294 | // We could handle this in the individual objects, but for now it's easier to have |
| 295 | // parent containers call repaint(). (RenderBlock::layout* has similar logic.) |
| 296 | if (!childEverHadLayout) |
| 297 | child->repaint(); |
cdumez@apple.com | f381449 | 2014-10-10 23:06:32 +0000 | [diff] [blame] | 298 | } else if (layoutSizeChanged && is<RenderElement>(*child)) |
| 299 | elementsThatDidNotReceiveLayout.add(downcast<RenderElement>(child)); |
zimmermann@webkit.org | d5d17b3 | 2010-01-14 03:05:30 +0000 | [diff] [blame] | 300 | |
zimmermann@webkit.org | d5d17b3 | 2010-01-14 03:05:30 +0000 | [diff] [blame] | 301 | ASSERT(!child->needsLayout()); |
| 302 | } |
zimmermann@webkit.org | cff3134 | 2010-08-13 10:03:22 +0000 | [diff] [blame] | 303 | |
| 304 | if (!layoutSizeChanged) { |
darin@apple.com | 738e9f5 | 2014-03-13 17:51:59 +0000 | [diff] [blame] | 305 | ASSERT(elementsThatDidNotReceiveLayout.isEmpty()); |
zimmermann@webkit.org | cff3134 | 2010-08-13 10:03:22 +0000 | [diff] [blame] | 306 | return; |
| 307 | } |
| 308 | |
| 309 | // If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path. |
darin@apple.com | 738e9f5 | 2014-03-13 17:51:59 +0000 | [diff] [blame] | 310 | for (auto* element : elementsThatDidNotReceiveLayout) |
| 311 | invalidateResourcesOfChildren(*element); |
zimmermann@webkit.org | d5d17b3 | 2010-01-14 03:05:30 +0000 | [diff] [blame] | 312 | } |
| 313 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 314 | bool SVGRenderSupport::isOverflowHidden(const RenderElement& renderer) |
zimmermann@webkit.org | 43b8cc9 | 2010-02-08 14:26:33 +0000 | [diff] [blame] | 315 | { |
zimmermann@webkit.org | 1ef0ade | 2010-02-09 16:08:18 +0000 | [diff] [blame] | 316 | // RenderSVGRoot should never query for overflow state - it should always clip itself to the initial viewport size. |
simon.fraser@apple.com | f63871d | 2015-10-10 02:20:52 +0000 | [diff] [blame] | 317 | ASSERT(!renderer.isDocumentElementRenderer()); |
zimmermann@webkit.org | 1ef0ade | 2010-02-09 16:08:18 +0000 | [diff] [blame] | 318 | |
commit-queue@webkit.org | d5054f1 | 2014-05-09 19:05:33 +0000 | [diff] [blame] | 319 | return renderer.style().overflowX() == OHIDDEN || renderer.style().overflowX() == OSCROLL; |
zimmermann@webkit.org | 43b8cc9 | 2010-02-08 14:26:33 +0000 | [diff] [blame] | 320 | } |
| 321 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 322 | bool SVGRenderSupport::rendererHasSVGShadow(const RenderObject& renderer) |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 323 | { |
| 324 | // FIXME: Add support for RenderSVGBlock. |
| 325 | |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 326 | if (is<RenderSVGModelObject>(renderer)) |
| 327 | return downcast<RenderSVGModelObject>(renderer).hasSVGShadow(); |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 328 | |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 329 | if (is<RenderSVGRoot>(renderer)) |
| 330 | return downcast<RenderSVGRoot>(renderer).hasSVGShadow(); |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 331 | |
| 332 | return false; |
| 333 | } |
| 334 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 335 | void SVGRenderSupport::setRendererHasSVGShadow(RenderObject& renderer, bool hasShadow) |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 336 | { |
| 337 | // FIXME: Add support for RenderSVGBlock. |
| 338 | |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 339 | if (is<RenderSVGModelObject>(renderer)) { |
| 340 | downcast<RenderSVGModelObject>(renderer).setHasSVGShadow(hasShadow); |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 341 | return; |
| 342 | } |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 343 | |
cdumez@apple.com | 2601e05 | 2014-10-10 18:02:32 +0000 | [diff] [blame] | 344 | if (is<RenderSVGRoot>(renderer)) |
| 345 | downcast<RenderSVGRoot>(renderer).setHasSVGShadow(hasShadow); |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 346 | } |
| 347 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 348 | void SVGRenderSupport::intersectRepaintRectWithShadows(const RenderElement& renderer, FloatRect& repaintRect) |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 349 | { |
| 350 | // Since -webkit-svg-shadow enables shadow drawing for its children, but its children |
| 351 | // don't inherit the shadow in their SVGRenderStyle, we need to search our parents for |
| 352 | // shadows in order to correctly compute our repaint rect. |
| 353 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 354 | auto currentObject = &renderer; |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 355 | |
| 356 | AffineTransform localToRootTransform; |
| 357 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 358 | while (currentObject && rendererHasSVGShadow(*currentObject)) { |
akling@apple.com | 827be9c | 2013-10-29 02:58:43 +0000 | [diff] [blame] | 359 | const RenderStyle& style = currentObject->style(); |
akling@apple.com | 148c287 | 2013-11-02 05:01:08 +0000 | [diff] [blame] | 360 | const SVGRenderStyle& svgStyle = style.svgStyle(); |
| 361 | if (const ShadowData* shadow = svgStyle.shadow()) |
| 362 | shadow->adjustRectForShadow(repaintRect); |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 363 | |
| 364 | repaintRect = currentObject->localToParentTransform().mapRect(repaintRect); |
| 365 | localToRootTransform *= currentObject->localToParentTransform(); |
| 366 | |
| 367 | currentObject = currentObject->parent(); |
| 368 | }; |
| 369 | |
| 370 | if (localToRootTransform.isIdentity()) |
| 371 | return; |
| 372 | |
commit-queue@webkit.org | 759ff2e | 2015-12-01 20:26:05 +0000 | [diff] [blame] | 373 | AffineTransform rootToLocalTransform = localToRootTransform.inverse().valueOr(AffineTransform()); |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 374 | repaintRect = rootToLocalTransform.mapRect(repaintRect); |
| 375 | } |
| 376 | |
akling@apple.com | f67100c | 2013-10-24 18:41:42 +0000 | [diff] [blame] | 377 | void SVGRenderSupport::intersectRepaintRectWithResources(const RenderElement& renderer, FloatRect& repaintRect) |
eric@webkit.org | 55e39b2 | 2009-04-28 19:37:32 +0000 | [diff] [blame] | 378 | { |
akling@apple.com | 2e79f74 | 2014-09-05 19:25:57 +0000 | [diff] [blame] | 379 | auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer); |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 380 | if (!resources) |
zimmermann@webkit.org | b984a40 | 2010-07-29 13:50:51 +0000 | [diff] [blame] | 381 | return; |
zimmermann@webkit.org | b984a40 | 2010-07-29 13:50:51 +0000 | [diff] [blame] | 382 | |
zimmermann@webkit.org | b984a40 | 2010-07-29 13:50:51 +0000 | [diff] [blame] | 383 | if (RenderSVGResourceFilter* filter = resources->filter()) |
| 384 | repaintRect = filter->resourceBoundingBox(renderer); |
eric@webkit.org | 55e39b2 | 2009-04-28 19:37:32 +0000 | [diff] [blame] | 385 | |
zimmermann@webkit.org | b984a40 | 2010-07-29 13:50:51 +0000 | [diff] [blame] | 386 | if (RenderSVGResourceClipper* clipper = resources->clipper()) |
| 387 | repaintRect.intersect(clipper->resourceBoundingBox(renderer)); |
| 388 | |
| 389 | if (RenderSVGResourceMasker* masker = resources->masker()) |
| 390 | repaintRect.intersect(masker->resourceBoundingBox(renderer)); |
krit@webkit.org | 4dc21c1 | 2009-12-30 08:10:44 +0000 | [diff] [blame] | 391 | } |
| 392 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 393 | bool SVGRenderSupport::filtersForceContainerLayout(const RenderElement& renderer) |
commit-queue@webkit.org | 17807a9 | 2011-11-11 23:40:57 +0000 | [diff] [blame] | 394 | { |
| 395 | // If any of this container's children need to be laid out, and a filter is applied |
| 396 | // to the container, we need to repaint the entire container. |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 397 | if (!renderer.normalChildNeedsLayout()) |
commit-queue@webkit.org | 17807a9 | 2011-11-11 23:40:57 +0000 | [diff] [blame] | 398 | return false; |
| 399 | |
akling@apple.com | 2e79f74 | 2014-09-05 19:25:57 +0000 | [diff] [blame] | 400 | auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer); |
commit-queue@webkit.org | 17807a9 | 2011-11-11 23:40:57 +0000 | [diff] [blame] | 401 | if (!resources || !resources->filter()) |
| 402 | return false; |
| 403 | |
| 404 | return true; |
| 405 | } |
| 406 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 407 | bool SVGRenderSupport::pointInClippingArea(const RenderElement& renderer, const FloatPoint& point) |
krit@webkit.org | 21317bb | 2010-06-06 12:26:45 +0000 | [diff] [blame] | 408 | { |
krit@webkit.org | 21317bb | 2010-06-06 12:26:45 +0000 | [diff] [blame] | 409 | // We just take clippers into account to determine if a point is on the node. The Specification may |
| 410 | // change later and we also need to check maskers. |
akling@apple.com | 2e79f74 | 2014-09-05 19:25:57 +0000 | [diff] [blame] | 411 | auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer); |
zimmermann@webkit.org | b984a40 | 2010-07-29 13:50:51 +0000 | [diff] [blame] | 412 | if (!resources) |
| 413 | return true; |
| 414 | |
| 415 | if (RenderSVGResourceClipper* clipper = resources->clipper()) |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 416 | return clipper->hitTestClipContent(renderer.objectBoundingBox(), point); |
krit@webkit.org | 21317bb | 2010-06-06 12:26:45 +0000 | [diff] [blame] | 417 | |
| 418 | return true; |
| 419 | } |
| 420 | |
akling@apple.com | 88c9a52 | 2013-10-29 17:17:22 +0000 | [diff] [blame] | 421 | void SVGRenderSupport::applyStrokeStyleToContext(GraphicsContext* context, const RenderStyle& style, const RenderElement& renderer) |
zimmermann@webkit.org | 555112d | 2010-04-24 11:42:46 +0000 | [diff] [blame] | 422 | { |
zimmermann@webkit.org | 51cbd13 | 2010-08-06 11:21:20 +0000 | [diff] [blame] | 423 | ASSERT(context); |
akling@apple.com | 88c9a52 | 2013-10-29 17:17:22 +0000 | [diff] [blame] | 424 | ASSERT(renderer.element()); |
| 425 | ASSERT(renderer.element()->isSVGElement()); |
zimmermann@webkit.org | 555112d | 2010-04-24 11:42:46 +0000 | [diff] [blame] | 426 | |
akling@apple.com | 148c287 | 2013-11-02 05:01:08 +0000 | [diff] [blame] | 427 | const SVGRenderStyle& svgStyle = style.svgStyle(); |
zimmermann@webkit.org | 51cbd13 | 2010-08-06 11:21:20 +0000 | [diff] [blame] | 428 | |
cdumez@apple.com | 7487b35 | 2014-09-23 00:55:05 +0000 | [diff] [blame] | 429 | SVGLengthContext lengthContext(downcast<SVGElement>(renderer.element())); |
krit@webkit.org | 3b6d18c | 2014-08-18 18:18:16 +0000 | [diff] [blame] | 430 | context->setStrokeThickness(lengthContext.valueForLength(svgStyle.strokeWidth())); |
akling@apple.com | 148c287 | 2013-11-02 05:01:08 +0000 | [diff] [blame] | 431 | context->setLineCap(svgStyle.capStyle()); |
| 432 | context->setLineJoin(svgStyle.joinStyle()); |
| 433 | if (svgStyle.joinStyle() == MiterJoin) |
| 434 | context->setMiterLimit(svgStyle.strokeMiterLimit()); |
zimmermann@webkit.org | 51cbd13 | 2010-08-06 11:21:20 +0000 | [diff] [blame] | 435 | |
akling@apple.com | 148c287 | 2013-11-02 05:01:08 +0000 | [diff] [blame] | 436 | const Vector<SVGLength>& dashes = svgStyle.strokeDashArray(); |
eric@webkit.org | 24ac406 | 2010-04-26 10:05:10 +0000 | [diff] [blame] | 437 | if (dashes.isEmpty()) |
| 438 | context->setStrokeStyle(SolidStroke); |
zimmermann@webkit.org | 51cbd13 | 2010-08-06 11:21:20 +0000 | [diff] [blame] | 439 | else { |
| 440 | DashArray dashArray; |
akling@apple.com | 88c9a52 | 2013-10-29 17:17:22 +0000 | [diff] [blame] | 441 | dashArray.reserveInitialCapacity(dashes.size()); |
darin@apple.com | 738e9f5 | 2014-03-13 17:51:59 +0000 | [diff] [blame] | 442 | for (auto& dash : dashes) |
| 443 | dashArray.uncheckedAppend(dash.value(lengthContext)); |
zimmermann@webkit.org | 51cbd13 | 2010-08-06 11:21:20 +0000 | [diff] [blame] | 444 | |
krit@webkit.org | 3b6d18c | 2014-08-18 18:18:16 +0000 | [diff] [blame] | 445 | context->setLineDash(dashArray, lengthContext.valueForLength(svgStyle.strokeDashOffset())); |
zimmermann@webkit.org | 51cbd13 | 2010-08-06 11:21:20 +0000 | [diff] [blame] | 446 | } |
zimmermann@webkit.org | 555112d | 2010-04-24 11:42:46 +0000 | [diff] [blame] | 447 | } |
| 448 | |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 449 | void SVGRenderSupport::childAdded(RenderElement& parent, RenderObject& child) |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 450 | { |
| 451 | SVGRenderSupport::setRendererHasSVGShadow(child, SVGRenderSupport::rendererHasSVGShadow(parent) || SVGRenderSupport::rendererHasSVGShadow(child)); |
| 452 | } |
| 453 | |
commit-queue@webkit.org | b668ca2 | 2014-02-18 17:10:37 +0000 | [diff] [blame] | 454 | void SVGRenderSupport::styleChanged(RenderElement& renderer, const RenderStyle* oldStyle) |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 455 | { |
akling@apple.com | 559147c | 2013-11-09 11:32:57 +0000 | [diff] [blame] | 456 | auto parent = renderer.parent(); |
| 457 | SVGRenderSupport::setRendererHasSVGShadow(renderer, (parent && SVGRenderSupport::rendererHasSVGShadow(*parent)) || renderer.style().svgStyle().shadow()); |
commit-queue@webkit.org | b668ca2 | 2014-02-18 17:10:37 +0000 | [diff] [blame] | 458 | |
| 459 | #if ENABLE(CSS_COMPOSITING) |
| 460 | if (renderer.element() && renderer.element()->isSVGElement() && (!oldStyle || renderer.style().hasBlendMode() != oldStyle->hasBlendMode())) |
| 461 | SVGRenderSupport::updateMaskedAncestorShouldIsolateBlending(renderer); |
| 462 | #else |
| 463 | UNUSED_PARAM(oldStyle); |
| 464 | #endif |
timothy_horton@apple.com | 314822f | 2012-11-08 02:58:21 +0000 | [diff] [blame] | 465 | } |
| 466 | |
commit-queue@webkit.org | b668ca2 | 2014-02-18 17:10:37 +0000 | [diff] [blame] | 467 | #if ENABLE(CSS_COMPOSITING) |
| 468 | bool SVGRenderSupport::isolatesBlending(const RenderStyle& style) |
| 469 | { |
dino@apple.com | d75816f | 2015-08-19 20:22:50 +0000 | [diff] [blame] | 470 | return style.svgStyle().isolatesBlending() || style.hasFilter() || style.hasBlendMode() || style.opacity() < 1.0f; |
commit-queue@webkit.org | b668ca2 | 2014-02-18 17:10:37 +0000 | [diff] [blame] | 471 | } |
| 472 | |
| 473 | void SVGRenderSupport::updateMaskedAncestorShouldIsolateBlending(const RenderElement& renderer) |
| 474 | { |
| 475 | ASSERT(renderer.element()); |
| 476 | ASSERT(renderer.element()->isSVGElement()); |
| 477 | |
| 478 | bool maskedAncestorShouldIsolateBlending = renderer.style().hasBlendMode(); |
darin@apple.com | 738e9f5 | 2014-03-13 17:51:59 +0000 | [diff] [blame] | 479 | for (auto* ancestor = renderer.element()->parentElement(); ancestor && ancestor->isSVGElement(); ancestor = ancestor->parentElement()) { |
cdumez@apple.com | 7487b35 | 2014-09-23 00:55:05 +0000 | [diff] [blame] | 480 | if (!downcast<SVGElement>(*ancestor).isSVGGraphicsElement() || !isolatesBlending(*ancestor->computedStyle())) |
commit-queue@webkit.org | b668ca2 | 2014-02-18 17:10:37 +0000 | [diff] [blame] | 481 | continue; |
| 482 | |
| 483 | if (ancestor->computedStyle()->svgStyle().hasMasker()) |
cdumez@apple.com | 11b6805 | 2014-09-25 17:25:43 +0000 | [diff] [blame] | 484 | downcast<SVGGraphicsElement>(*ancestor).setShouldIsolateBlending(maskedAncestorShouldIsolateBlending); |
commit-queue@webkit.org | b668ca2 | 2014-02-18 17:10:37 +0000 | [diff] [blame] | 485 | |
| 486 | return; |
| 487 | } |
| 488 | } |
| 489 | #endif |
krit@webkit.org | 6e42616 | 2010-02-26 18:02:26 +0000 | [diff] [blame] | 490 | } |