2006-02-11 Eric Seidel <eseidel@apple.com>
[WebKit-https.git] / WebCore / ksvg2 / misc / KCanvasRenderingStyle.cpp
1 /*
2     Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3                   2004, 2005 Rob Buis <buis@kde.org>
4                         2006 Alexander Kellett <lypanov@kde.org>
5
6     This file is part of the KDE project
7
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Library General Public
10     License as published by the Free Software Foundation; either
11     version 2 of the License, or (at your option) any later version.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Library General Public License for more details.
17
18     You should have received a copy of the GNU Library General Public License
19     aint with this library; see the file COPYING.LIB.  If not, write to
20     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21     Boston, MA 02111-1307, USA.
22 */
23
24 #include "config.h"
25 #if SVG_SUPPORT
26
27 #include <render_object.h>
28
29 #include <kcanvas/KCanvas.h>
30 #include <kcanvas/KCanvasPath.h>
31 #include <kcanvas/device/KRenderingDevice.h>
32 #include <kcanvas/device/KRenderingFillPainter.h>
33 #include <kcanvas/device/KRenderingStrokePainter.h>
34 #include <kcanvas/device/KRenderingPaintServerSolid.h>
35 #include <kcanvas/device/KRenderingPaintServerGradient.h>
36 #include <kcanvas/device/KRenderingPaintServer.h>
37
38 #include "DocumentImpl.h"
39 #include "PlatformString.h"
40 #include "render_style.h"
41 #include "css_valueimpl.h"
42
43 #include "ksvg.h"
44 #include "SVGLengthImpl.h"
45 #include "SVGStyledElementImpl.h"
46 #include "KCanvasRenderingStyle.h"
47 #include "SVGRenderStyle.h"
48
49 namespace WebCore {
50
51 static KRenderingPaintServerSolid* sharedSolidPaintServer()
52 {
53     static KRenderingPaintServerSolid* _sharedSolidPaintServer = 0;
54     if (!_sharedSolidPaintServer)
55         _sharedSolidPaintServer = static_cast<KRenderingPaintServerSolid *>(QPainter::renderingDevice()->createPaintServer(PS_SOLID));
56     return _sharedSolidPaintServer;
57 }
58
59 bool KSVGPainterFactory::isFilled(const RenderStyle *style)
60 {
61     SVGPaintImpl *fill = style->svgStyle()->fillPaint();
62     if (fill && fill->paintType() == SVG_PAINTTYPE_NONE)
63         return false;
64     return true;
65 }
66
67 KRenderingPaintServer *KSVGPainterFactory::fillPaintServer(const RenderStyle* style, const RenderObject* item)
68 {
69     if (!isFilled(style))
70         return 0;
71
72     SVGPaintImpl *fill = style->svgStyle()->fillPaint();
73
74     KRenderingPaintServer *fillPaintServer;
75     if (!fill) {
76         // initial value (black)
77         fillPaintServer = sharedSolidPaintServer();
78         static_cast<KRenderingPaintServerSolid *>(fillPaintServer)->setColor(Color::black);
79     } else if (fill->paintType() == SVG_PAINTTYPE_URI) {
80         DOMString id(fill->uri());
81         fillPaintServer = getPaintServerById(item->document(), id.qstring().mid(1));
82         if (item && fillPaintServer && item->isRenderPath())
83             fillPaintServer->addClient(static_cast<const RenderPath*>(item));
84     } else {
85         fillPaintServer = sharedSolidPaintServer();
86         KRenderingPaintServerSolid *fillPaintServerSolid = static_cast<KRenderingPaintServerSolid *>(fillPaintServer);
87         if (fill->paintType() == SVG_PAINTTYPE_CURRENTCOLOR)
88             fillPaintServerSolid->setColor(style->color());
89         else
90             fillPaintServerSolid->setColor(fill->color());
91     }
92
93     return fillPaintServer;
94 }
95
96
97 bool KSVGPainterFactory::isStroked(const RenderStyle *style)
98 {
99     SVGPaintImpl *stroke = style->svgStyle()->strokePaint();
100     if (!stroke || stroke->paintType() == SVG_PAINTTYPE_NONE)
101         return false;
102     return true;
103 }
104
105 KRenderingPaintServer *KSVGPainterFactory::strokePaintServer(const RenderStyle* style, const RenderObject* item)
106 {
107     if (!isStroked(style))
108         return 0;
109
110     SVGPaintImpl *stroke = style->svgStyle()->strokePaint();
111
112     KRenderingPaintServer *strokePaintServer;
113     if (stroke && stroke->paintType() == SVG_PAINTTYPE_URI) {
114         DOMString id(stroke->uri());
115         strokePaintServer = getPaintServerById(item->document(), id.qstring().mid(1));
116         if(item && strokePaintServer && item->isRenderPath())
117             strokePaintServer->addClient(static_cast<const RenderPath*>(item));
118     } else {
119         strokePaintServer = sharedSolidPaintServer();
120         KRenderingPaintServerSolid *strokePaintServerSolid = static_cast<KRenderingPaintServerSolid *>(strokePaintServer);
121         if (stroke->paintType() == SVG_PAINTTYPE_CURRENTCOLOR)
122             strokePaintServerSolid->setColor(style->color());
123         else
124             strokePaintServerSolid->setColor(stroke->color());
125     }
126
127     return strokePaintServer;
128 }
129
130 double KSVGPainterFactory::cssPrimitiveToLength(const RenderObject* item, CSSValueImpl *value, double defaultValue)
131 {
132     CSSPrimitiveValueImpl *primitive = static_cast<CSSPrimitiveValueImpl *>(value);
133
134     unsigned short cssType = (primitive ? primitive->primitiveType() : (unsigned short) CSSPrimitiveValue::CSS_UNKNOWN);
135     if(!(cssType > CSSPrimitiveValue::CSS_UNKNOWN && cssType <= CSSPrimitiveValue::CSS_PC))
136         return defaultValue;
137
138     if(cssType == CSSPrimitiveValue::CSS_PERCENTAGE)
139     {
140         SVGElementImpl *element = static_cast<SVGElementImpl *>(item->element());
141         SVGElementImpl *viewportElement = (element ? element->viewportElement() : 0);
142         if(viewportElement)
143         {
144             double result = primitive->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) / 100.0;
145             return SVGHelper::PercentageOfViewport(result, viewportElement, LM_OTHER);
146         }
147     }
148
149     return primitive->computeLengthFloat(const_cast<RenderStyle *>(item->style()));
150 }
151
152 KRenderingStrokePainter KSVGPainterFactory::strokePainter(const RenderStyle* style, const RenderObject* item)
153 {
154     KRenderingStrokePainter strokePainter;
155
156     strokePainter.setOpacity(style->svgStyle()->strokeOpacity());
157     strokePainter.setStrokeWidth(KSVGPainterFactory::cssPrimitiveToLength(item, style->svgStyle()->strokeWidth(), 1.0));
158
159     CSSValueListImpl *dashes = style->svgStyle()->strokeDashArray();
160     if (dashes) {
161         CSSPrimitiveValueImpl *dash = 0;
162         KCDashArray array;
163         unsigned long len = dashes->length();
164         for (unsigned long i = 0; i < len; i++) {
165             dash = static_cast<CSSPrimitiveValueImpl *>(dashes->item(i));
166             if (dash)
167                 array.append((float) dash->computeLengthFloat(const_cast<RenderStyle *>(style)));
168         }
169
170         strokePainter.setDashArray(array);
171         strokePainter.setDashOffset(KSVGPainterFactory::cssPrimitiveToLength(item, style->svgStyle()->strokeDashOffset(), 0.0));
172     }
173
174     strokePainter.setStrokeMiterLimit(style->svgStyle()->strokeMiterLimit());
175     strokePainter.setStrokeCapStyle((KCCapStyle) style->svgStyle()->capStyle());
176     strokePainter.setStrokeJoinStyle((KCJoinStyle) style->svgStyle()->joinStyle());
177
178     return strokePainter;
179 }
180
181 KRenderingFillPainter KSVGPainterFactory::fillPainter(const RenderStyle* style, const RenderObject* item)
182 {
183     KRenderingFillPainter fillPainter;
184     
185     fillPainter.setFillRule(style->svgStyle()->fillRule() == WR_NONZERO ? RULE_NONZERO : RULE_EVENODD);
186     fillPainter.setOpacity(style->svgStyle()->fillOpacity());
187
188     return fillPainter;
189 }
190
191 }
192
193 // vim:ts=4:noet
194 #endif // SVG_SUPPORT
195