2006-09-27 Eric Seidel <eric@eseidel.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 #ifdef SVG_SUPPORT
26
27 #include "CSSValueList.h"
28 #include "Document.h"
29 #include "KCanvasRenderingStyle.h"
30 #include "KRenderingDevice.h"
31 #include "KRenderingFillPainter.h"
32 #include "KRenderingPaintServerGradient.h"
33 #include "KRenderingPaintServerSolid.h"
34 #include "KRenderingStrokePainter.h"
35 #include "RenderObject.h"
36 #include "SVGLength.h"
37 #include "SVGRenderStyle.h"
38 #include "SVGStyledElement.h"
39 #include "ksvg.h"
40
41 namespace WebCore {
42
43 static KRenderingPaintServerSolid* sharedSolidPaintServer()
44 {
45     static KRenderingPaintServerSolid* _sharedSolidPaintServer = 0;
46     if (!_sharedSolidPaintServer)
47         _sharedSolidPaintServer = static_cast<KRenderingPaintServerSolid*>(renderingDevice()->createPaintServer(PS_SOLID));
48     return _sharedSolidPaintServer;
49 }
50
51 bool KSVGPainterFactory::isFilled(const RenderStyle* style)
52 {
53     if (style->svgStyle()->fillPaint()->paintType() == SVGPaint::SVG_PAINTTYPE_NONE)
54         return false;
55     return true;
56 }
57
58 KRenderingPaintServer* KSVGPainterFactory::fillPaintServer(const RenderStyle* style, const RenderObject* item)
59 {
60     if (!isFilled(style))
61         return 0;
62
63     SVGPaint* fill = style->svgStyle()->fillPaint();
64
65     KRenderingPaintServer* fillPaintServer = 0;
66     if (fill->paintType() == SVGPaint::SVG_PAINTTYPE_URI) {
67         fillPaintServer = getPaintServerById(item->document(), AtomicString(fill->uri().substring(1)));
68         if (fillPaintServer && item->isRenderPath())
69             fillPaintServer->addClient(static_cast<const RenderPath*>(item));
70         if (!fillPaintServer) {
71             // default value (black), see bug 11017
72             fillPaintServer = sharedSolidPaintServer();
73             static_cast<KRenderingPaintServerSolid*>(fillPaintServer)->setColor(Color::black);
74         }
75     } else {
76         fillPaintServer = sharedSolidPaintServer();
77         KRenderingPaintServerSolid* fillPaintServerSolid = static_cast<KRenderingPaintServerSolid*>(fillPaintServer);
78         if (fill->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR)
79             fillPaintServerSolid->setColor(style->color());
80         else
81             fillPaintServerSolid->setColor(fill->color());
82     }
83     return fillPaintServer;
84 }
85
86
87 bool KSVGPainterFactory::isStroked(const RenderStyle* style)
88 {
89     if (style->svgStyle()->strokePaint()->paintType() == SVGPaint::SVG_PAINTTYPE_NONE)
90         return false;
91     return true;
92 }
93
94 KRenderingPaintServer* KSVGPainterFactory::strokePaintServer(const RenderStyle* style, const RenderObject* item)
95 {
96     if (!isStroked(style))
97         return 0;
98
99     SVGPaint* stroke = style->svgStyle()->strokePaint();
100
101     KRenderingPaintServer* strokePaintServer = 0;
102     if (stroke->paintType() == SVGPaint::SVG_PAINTTYPE_URI) {
103         strokePaintServer = getPaintServerById(item->document(), AtomicString(stroke->uri().substring(1)));
104         if (item && strokePaintServer && item->isRenderPath())
105             strokePaintServer->addClient(static_cast<const RenderPath*>(item));
106     } else {
107         strokePaintServer = sharedSolidPaintServer();
108         KRenderingPaintServerSolid* strokePaintServerSolid = static_cast<KRenderingPaintServerSolid*>(strokePaintServer);
109         if (stroke->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR)
110             strokePaintServerSolid->setColor(style->color());
111         else
112             strokePaintServerSolid->setColor(stroke->color());
113     }
114
115     return strokePaintServer;
116 }
117
118 double KSVGPainterFactory::cssPrimitiveToLength(const RenderObject* item, CSSValue *value, double defaultValue)
119 {
120     CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(value);
121
122     unsigned short cssType = (primitive ? primitive->primitiveType() : (unsigned short) CSSPrimitiveValue::CSS_UNKNOWN);
123     if (!(cssType > CSSPrimitiveValue::CSS_UNKNOWN && cssType <= CSSPrimitiveValue::CSS_PC))
124         return defaultValue;
125
126     if (cssType == CSSPrimitiveValue::CSS_PERCENTAGE) {
127         SVGElement* element = static_cast<SVGElement*>(item->element());
128         SVGElement* viewportElement = (element ? element->viewportElement() : 0);
129         if (viewportElement) {
130             double result = primitive->getFloatValue() / 100.0;
131             return SVGHelper::PercentageOfViewport(result, viewportElement, LM_OTHER);
132         }
133     }
134
135     return primitive->computeLengthFloat(const_cast<RenderStyle*>(item->style()));
136 }
137
138 KRenderingStrokePainter KSVGPainterFactory::strokePainter(const RenderStyle* style, const RenderObject* item)
139 {
140     KRenderingStrokePainter strokePainter;
141
142     strokePainter.setOpacity(style->svgStyle()->strokeOpacity());
143     strokePainter.setStrokeWidth(KSVGPainterFactory::cssPrimitiveToLength(item, style->svgStyle()->strokeWidth(), 1.0));
144
145     CSSValueList* dashes = style->svgStyle()->strokeDashArray();
146     if (dashes) {
147         CSSPrimitiveValue* dash = 0;
148         KCDashArray array;
149         unsigned long len = dashes->length();
150         for (unsigned long i = 0; i < len; i++) {
151             dash = static_cast<CSSPrimitiveValue*>(dashes->item(i));
152             if (dash)
153                 array.append((float) dash->computeLengthFloat(const_cast<RenderStyle*>(style)));
154         }
155
156         strokePainter.setDashArray(array);
157         strokePainter.setDashOffset(KSVGPainterFactory::cssPrimitiveToLength(item, style->svgStyle()->strokeDashOffset(), 0.0));
158     }
159
160     strokePainter.setStrokeMiterLimit(style->svgStyle()->strokeMiterLimit());
161     strokePainter.setStrokeCapStyle((KCCapStyle) style->svgStyle()->capStyle());
162     strokePainter.setStrokeJoinStyle((KCJoinStyle) style->svgStyle()->joinStyle());
163
164     return strokePainter;
165 }
166
167 KRenderingFillPainter KSVGPainterFactory::fillPainter(const RenderStyle* style, const RenderObject* item)
168 {
169     KRenderingFillPainter fillPainter;
170     
171     fillPainter.setFillRule(style->svgStyle()->fillRule());
172     fillPainter.setOpacity(style->svgStyle()->fillOpacity());
173
174     return fillPainter;
175 }
176
177 }
178
179 // vim:ts=4:noet
180 #endif // SVG_SUPPORT
181