1dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block/* 2dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Copyright (C) 2004, 2005, 2006, 2007, 2008 Rob Buis <buis@kde.org> 4dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 5dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * 6dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * This library is free software; you can redistribute it and/or 7dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * modify it under the terms of the GNU Library General Public 8dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * License as published by the Free Software Foundation; either 9dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * version 2 of the License, or (at your option) any later version. 10dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * 11dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * This library is distributed in the hope that it will be useful, 12dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * but WITHOUT ANY WARRANTY; without even the implied warranty of 13dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Library General Public License for more details. 15dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * 16dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * You should have received a copy of the GNU Library General Public License 17dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * along with this library; see the file COPYING.LIB. If not, write to 18dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Boston, MA 02110-1301, USA. 20dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block */ 21dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 22dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "config.h" 23db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block 246c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen#if ENABLE(SVG) 25dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderSVGResourceMarker.h" 26dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 27dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "GraphicsContext.h" 28dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderSVGContainer.h" 29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGElement.h" 30dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGMarkerElement.h" 31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGRenderSupport.h" 32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGStyledElement.h" 33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGStyledTransformableElement.h" 34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocknamespace WebCore { 36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockRenderSVGResourceType RenderSVGResourceMarker::s_resourceType = MarkerResourceType; 38dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 3921939df44de1705786c545cd1bf519d47250322dBen MurdochRenderSVGResourceMarker::RenderSVGResourceMarker(SVGMarkerElement* node) 4021939df44de1705786c545cd1bf519d47250322dBen Murdoch : RenderSVGResourceContainer(node) 41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 44dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockRenderSVGResourceMarker::~RenderSVGResourceMarker() 45dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 48dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid RenderSVGResourceMarker::layout() 49dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 50db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block // Invalidate all resources if our layout changed. 51db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block if (m_everHadLayout && selfNeedsLayout()) 52f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick removeAllClientsFromCache(); 53db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block 54dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // RenderSVGHiddenContainer overwrites layout(). We need the 55dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // layouting of RenderSVGContainer for calculating local 56dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // transformations and repaint. 57dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderSVGContainer::layout(); 58dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 59dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 60f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid RenderSVGResourceMarker::removeAllClientsFromCache(bool markForInvalidation) 61dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 62f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); 63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 65f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid RenderSVGResourceMarker::removeClientFromCache(RenderObject* client, bool markForInvalidation) 66dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 67db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block ASSERT(client); 68f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); 69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid RenderSVGResourceMarker::applyViewportClip(PaintInfo& paintInfo) 72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 73ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block if (SVGRenderSupport::isOverflowHidden(this)) 74dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block paintInfo.context->clip(m_viewport); 75dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockFloatRect RenderSVGResourceMarker::markerBoundaries(const AffineTransform& markerTransformation) const 78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 79dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block FloatRect coordinates = RenderSVGContainer::repaintRectInLocalCoordinates(); 80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 81dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Map repaint rect into parent coordinate space, in which the marker boundaries have to be evaluated 82dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block coordinates = localToParentTransform().mapRect(coordinates); 83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 84dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return markerTransformation.mapRect(coordinates); 85dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 87dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockconst AffineTransform& RenderSVGResourceMarker::localToParentTransform() const 88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_localToParentTransform = AffineTransform::translation(m_viewport.x(), m_viewport.y()) * viewportTransform(); 90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return m_localToParentTransform; 91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // If this class were ever given a localTransform(), then the above would read: 922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // return viewportTranslation * localTransform() * viewportTransform(); 93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockFloatPoint RenderSVGResourceMarker::referencePoint() const 96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); 98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(marker); 99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return FloatPoint(marker->refX().value(marker), marker->refY().value(marker)); 101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfloat RenderSVGResourceMarker::angle() const 104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); 106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(marker); 107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block float angle = -1; 109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (marker->orientType() == SVGMarkerElement::SVG_MARKER_ORIENT_ANGLE) 110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block angle = marker->orientAngle().value(); 111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return angle; 113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockAffineTransform RenderSVGResourceMarker::markerTransformation(const FloatPoint& origin, float autoAngle, float strokeWidth) const 116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); 118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(marker); 119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block float markerAngle = angle(); 121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block bool useStrokeWidth = (marker->markerUnits() == SVGMarkerElement::SVG_MARKERUNITS_STROKEWIDTH); 122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block AffineTransform transform; 124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block transform.translate(origin.x(), origin.y()); 125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block transform.rotate(markerAngle == -1 ? autoAngle : markerAngle); 126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block transform = markerContentTransformation(transform, referencePoint(), useStrokeWidth ? strokeWidth : -1); 127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return transform; 128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 130ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blockvoid RenderSVGResourceMarker::draw(PaintInfo& paintInfo, const AffineTransform& transform) 131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 132ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block PaintInfo info(paintInfo); 133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block info.context->save(); 134ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block info.applyTransform(transform); 135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderSVGContainer::paint(info, 0, 0); 136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block info.context->restore(); 137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockAffineTransform RenderSVGResourceMarker::markerContentTransformation(const AffineTransform& contentTransformation, const FloatPoint& origin, float strokeWidth) const 140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 141dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // The 'origin' coordinate maps to SVGs refX/refY, given in coordinates relative to the viewport established by the marker 142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block FloatPoint mappedOrigin = viewportTransform().mapPoint(origin); 143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block AffineTransform transformation = contentTransformation; 145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (strokeWidth != -1) 146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block transformation.scaleNonUniform(strokeWidth, strokeWidth); 147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block transformation.translate(-mappedOrigin.x(), -mappedOrigin.y()); 149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return transformation; 150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockAffineTransform RenderSVGResourceMarker::viewportTransform() const 153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); 155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(marker); 156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return marker->viewBoxToViewTransform(m_viewport.width(), m_viewport.height()); 158dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 160dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid RenderSVGResourceMarker::calcViewport() 161dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 162dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!selfNeedsLayout()) 163dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 164dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 165dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); 166dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(marker); 167dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block float w = marker->markerWidth().value(marker); 169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block float h = marker->markerHeight().value(marker); 170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_viewport = FloatRect(0, 0, w, h); 171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 1746c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1756c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen#endif // ENABLE(SVG) 176