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