1 /*
2 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #if ENABLE(SVG)
27 #include "SVGResourceMarker.h"
28
29 #include "AffineTransform.h"
30 #include "GraphicsContext.h"
31 #include "RenderSVGViewportContainer.h"
32 #include "TextStream.h"
33
34 namespace WebCore
35 {
36
SVGResourceMarker()37 SVGResourceMarker::SVGResourceMarker()
38 : SVGResource()
39 , m_refX(0.0)
40 , m_refY(0.0)
41 , m_angle(-1) // just like using setAutoAngle()
42 , m_marker(0)
43 , m_useStrokeWidth(true)
44 {
45 }
46
~SVGResourceMarker()47 SVGResourceMarker::~SVGResourceMarker()
48 {
49 }
50
setMarker(RenderSVGViewportContainer * marker)51 void SVGResourceMarker::setMarker(RenderSVGViewportContainer *marker)
52 {
53 m_marker = marker;
54 }
55
setRef(double refX,double refY)56 void SVGResourceMarker::setRef(double refX, double refY)
57 {
58 m_refX = refX;
59 m_refY = refY;
60 }
61
draw(GraphicsContext * context,const FloatRect & rect,double x,double y,double strokeWidth,double angle)62 void SVGResourceMarker::draw(GraphicsContext *context, const FloatRect &rect, double x, double y, double strokeWidth, double angle)
63 {
64 if (!m_marker) {
65 return;
66 }
67
68 static HashSet<SVGResourceMarker *> currentlyDrawingMarkers;
69
70 // avoid drawing circular marker references
71 if (currentlyDrawingMarkers.contains(this)) {
72 return;
73 }
74
75 currentlyDrawingMarkers.add(this);
76
77 AffineTransform transform;
78 transform.translate(x, y);
79 transform.rotate(m_angle > -1 ? m_angle : angle);
80
81 // refX and refY are given in coordinates relative to the viewport established by the marker, yet they affect
82 // the translation performed on the viewport itself.
83 AffineTransform viewportTransform;
84 if (m_useStrokeWidth) {
85 viewportTransform.scale(strokeWidth, strokeWidth);
86 }
87 viewportTransform *= m_marker->viewportTransform();
88 double refX, refY;
89 viewportTransform.map(m_refX, m_refY, &refX, &refY);
90 transform.translate(-refX, -refY);
91
92 if (m_useStrokeWidth) {
93 transform.scale(strokeWidth, strokeWidth);
94 }
95
96 // FIXME: PaintInfo should be passed into this method instead of being created here
97 // FIXME: bounding box fractions are lost
98 RenderObject::PaintInfo info(context, enclosingIntRect(rect), PaintPhaseForeground, 0, 0, 0);
99
100 context->save();
101 context->concatCTM(transform);
102 m_marker->setDrawsContents(true);
103 m_marker->paint(info, 0, 0);
104 m_marker->setDrawsContents(false);
105 context->restore();
106
107 m_cachedBounds = transform.mapRect(m_marker->absoluteClippedOverflowRect());
108
109 currentlyDrawingMarkers.remove(this);
110 }
111
cachedBounds() const112 FloatRect SVGResourceMarker::cachedBounds() const
113 {
114 return m_cachedBounds;
115 }
116
externalRepresentation(TextStream & ts) const117 TextStream &SVGResourceMarker::externalRepresentation(TextStream &ts) const
118 {
119 ts << "[type=MARKER]"
120 << " [angle=";
121
122 if (angle() == -1) {
123 ts << "auto" << "]";
124 } else {
125 ts << angle() << "]";
126 }
127
128 ts << " [ref x=" << refX() << " y=" << refY() << "]";
129 return ts;
130 }
131
getMarkerById(Document * document,const AtomicString & id)132 SVGResourceMarker *getMarkerById(Document *document, const AtomicString &id)
133 {
134 SVGResource *resource = getResourceById(document, id);
135 if (resource && resource->isMarker()) {
136 return static_cast<SVGResourceMarker *>(resource);
137 }
138
139 return 0;
140 }
141
142 } // namespace WebCore
143
144 #endif
145