Code

r13107@tres: ted | 2006-07-30 11:47:41 -0700
[inkscape.git] / src / extension / internal / wpg-input.cpp
1 /* libwpg\r
2  * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)\r
3  * Copyright (C) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)\r
4  *\r
5  * This library is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU Library General Public\r
7  * License as published by the Free Software Foundation; either\r
8  * version 2 of the License, or (at your option) any later version.\r
9  *\r
10  * This library is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
13  * Library General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU Library General Public\r
16  * License along with this library; if not, write to the Free Software\r
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA\r
18  *\r
19  * For further information visit http://libwpg.sourceforge.net\r
20  */\r
21 \r
22 /* "This product is not manufactured, approved, or supported by\r
23  * Corel Corporation or Corel Corporation Limited."\r
24  */\r
25 \r
26 #include <stdio.h>\r
27 \r
28 #include "libwpg/libwpg.h"\r
29 #include "libwpg/WPGStreamImplementation.h"\r
30 \r
31 using namespace libwpg;\r
32 \r
33 class InkscapePainter : public libwpg::WPGPaintInterface {\r
34 public:\r
35         InkscapePainter();\r
36 \r
37         void startDocument(double imageWidth, double imageHeight);\r
38         void endDocument();\r
39         void startLayer(unsigned int id);\r
40         void endLayer(unsigned int id);\r
41 \r
42         void setPen(const WPGPen& pen);\r
43         void setBrush(const WPGBrush& brush);\r
44         void setFillRule(FillRule rule);\r
45 \r
46         void drawRectangle(const WPGRect& rect, double rx, double ry);\r
47         void drawEllipse(const WPGPoint& center, double rx, double ry);\r
48         void drawPolygon(const WPGPointArray& vertices);\r
49         void drawPath(const WPGPath& path);\r
50 \r
51 private:\r
52         WPGPen m_pen;\r
53         WPGBrush m_brush;\r
54         FillRule m_fillRule;\r
55         int m_gradientIndex;\r
56         void writeStyle();\r
57 };\r
58 \r
59 InkscapePainter::InkscapePainter(): m_fillRule(AlternatingFill), m_gradientIndex(1)\r
60 {\r
61 }\r
62 \r
63 void InkscapePainter::startDocument(double width, double height) \r
64 {\r
65         printf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");\r
66         printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"");\r
67         printf(" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");\r
68 \r
69         printf("<!-- Created with wpg2svg/libwpg %s -->\n", LIBWPG_VERSION_STRING);\r
70 \r
71         printf("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" ");\r
72         printf("xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");        \r
73         printf("width=\"%g\" height=\"%f\" >\n", 72*width, 72*height);\r
74         \r
75         m_gradientIndex = 1;\r
76 }\r
77 \r
78 void InkscapePainter::endDocument()\r
79 {\r
80         printf("</svg>\n");\r
81 }\r
82 \r
83 void InkscapePainter::setPen(const WPGPen& pen)\r
84 {\r
85         m_pen = pen;\r
86 }\r
87 \r
88 void InkscapePainter::setBrush(const WPGBrush& brush)\r
89 {\r
90         m_brush = brush;\r
91         \r
92         if(m_brush.style == WPGBrush::Gradient)\r
93         {\r
94                 double angle = m_brush.gradient.angle();\r
95 \r
96                 printf("<defs>\n");\r
97                 printf("  <linearGradient id=\"grad%d\" >\n", m_gradientIndex++);\r
98                 for(unsigned c = 0; c < m_brush.gradient.count(); c++)\r
99                 {\r
100                         // round to nearest percentage\r
101                         int ofs = (int)(100.0*m_brush.gradient.stopOffset(c)+0.5);\r
102 \r
103                         WPGColor color = m_brush.gradient.stopColor(c);\r
104                         printf("    <stop offset=\"%d%%\" stop-color=\"#%02x%02x%02x\" />\n",\r
105                                 ofs, color.red, color.green, color.blue);\r
106                 }\r
107                 printf("  </linearGradient>\n");\r
108                 \r
109                 // not a simple horizontal gradient\r
110                 if(angle != -90.0)\r
111                 {\r
112                         printf("  <linearGradient xlink:href=\"#grad%d\"", m_gradientIndex-1);\r
113                         printf(" id=\"grad%d\" ", m_gradientIndex++);\r
114                         printf("x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" "); \r
115                         printf("gradientTransform=\"rotate(%f)\" ", angle);\r
116                         printf("gradientUnits=\"objectBoundingBox\" >\n");\r
117                         printf("  </linearGradient>\n");\r
118                 }\r
119                 \r
120                 printf("</defs>\n");\r
121         }\r
122 }\r
123 \r
124 void InkscapePainter::setFillRule(FillRule rule)\r
125 {\r
126         m_fillRule = rule;\r
127 }\r
128 \r
129 void InkscapePainter::startLayer(unsigned int id)\r
130 {\r
131         printf("<g id=\"Layer%d\" >\n", id);\r
132 }\r
133 \r
134 void InkscapePainter::endLayer(unsigned int)\r
135 {\r
136         printf("</g>\n");\r
137 }\r
138 \r
139 void InkscapePainter::drawRectangle(const WPGRect& rect, double rx, double ry)\r
140 {\r
141         printf("<rect ");\r
142         printf("x=\"%f\" y=\"%f\" ", 72*rect.x1, 72*rect.y1);\r
143         printf("width=\"%f\" height=\"%f\" ", 72*rect.width(), 72*rect.height());\r
144         if((rx !=0) || (ry !=0))\r
145                 printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);\r
146         writeStyle();\r
147         printf("/>\n");\r
148 }\r
149 \r
150 void InkscapePainter::drawEllipse(const WPGPoint& center, double rx, double ry)\r
151 {\r
152         printf("<ellipse ");\r
153         printf("cx=\"%f\" cy=\"%f\" ", 72*center.x, 72*center.y);\r
154         printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);\r
155         writeStyle();\r
156         printf("/>\n");\r
157 }\r
158 \r
159 void InkscapePainter::drawPolygon(const WPGPointArray& vertices)\r
160 {\r
161         if(vertices.count() < 2)\r
162                 return;\r
163 \r
164         if(vertices.count() == 2)\r
165         {\r
166                 const WPGPoint& p1 = vertices[0];\r
167                 const WPGPoint& p2 = vertices[1];\r
168                 printf("<line ");\r
169                 printf("x1=\"%f\"  y1=\"%f\" ", 72*p1.x, 72*p1.y);\r
170                 printf("x2=\"%f\"  y2=\"%f\"\n", 72*p2.x, 72*p2.y);\r
171                 writeStyle();\r
172                 printf("/>\n");\r
173         }\r
174         else\r
175         {\r
176                 printf("<polyline ");\r
177                 printf("points=\"");\r
178                 for(unsigned i = 0; i < vertices.count(); i++)\r
179                 {\r
180                         printf("%f %f", 72*vertices[i].x, 72*vertices[i].y);\r
181                         if(i < vertices.count()-1) printf(", ");\r
182                 }\r
183                 printf("\"\n");\r
184                 writeStyle();\r
185                 printf("/>\n");\r
186         }\r
187 }\r
188 \r
189 void InkscapePainter::drawPath(const WPGPath& path)\r
190 {\r
191         printf("<path d=\"");\r
192         for(unsigned i = 0; i < path.count(); i++)\r
193         {\r
194                 WPGPathElement element = path.element(i);\r
195                 WPGPoint point = element.point;\r
196                 switch(element.type)\r
197                 {\r
198                         case WPGPathElement::MoveToElement:\r
199                                 printf("\n M%f,%f ", 72*point.x, 72*point.y );\r
200                                 break;\r
201                                 \r
202                         case WPGPathElement::LineToElement:\r
203                                 printf("\n L%f,%f ", 72*point.x, 72*point.y );\r
204                                 break;\r
205                         \r
206                         case WPGPathElement::CurveToElement:\r
207                                 printf("C");\r
208                                 printf("%f,%f ", 72*element.extra1.x, 72*element.extra1.y );\r
209                                 printf("%f,%f ", 72*element.extra2.x, 72*element.extra2.y );\r
210                                 printf("%f,%f", 72*point.x, 72*point.y );\r
211                                 break;\r
212                         \r
213                         default:\r
214                                 break;\r
215                 }\r
216         }\r
217         printf("\" \n");\r
218         writeStyle();\r
219         printf("/>\n");\r
220 }\r
221 \r
222 // create "style" attribute based on current pen and brush\r
223 void InkscapePainter::writeStyle()\r
224 {\r
225         printf("style=\"");\r
226 \r
227         const WPGColor& color = m_pen.foreColor;\r
228         printf("stroke-width: %f; ", 72*m_pen.width);\r
229         if(m_pen.width > 0.0)\r
230         {\r
231                 printf("stroke: rgb(%d,%d,%d); ", color.red, color.green, color.blue);\r
232                 if(color.alpha != 0)\r
233                         // alpha = 0 means opacity = 1.0, alpha = 256 means opacity = 0\r
234                         printf("stroke-opacity: %f; ", 1.0-(color.alpha/256.0));\r
235         }\r
236 \r
237         if(!m_pen.solid)\r
238         {\r
239                 printf("stroke-dasharray: ");\r
240                 for(unsigned i = 0; i < m_pen.dashArray.count(); i++)\r
241                 {\r
242                         printf("%f", 72*m_pen.dashArray.at(i)*m_pen.width);\r
243                         if(i < m_pen.dashArray.count()-1) \r
244                                 printf(", ");\r
245                 }\r
246                 printf("; ");\r
247         }\r
248         \r
249         if(m_brush.style == WPGBrush::NoBrush)\r
250                 printf("fill: none; ");\r
251 \r
252         if(m_fillRule == InkscapePainter::WindingFill)\r
253                 printf("fill-rule: nonzero; ");\r
254         else if(m_fillRule == InkscapePainter::AlternatingFill)\r
255                 printf("fill-rule: evenodd; ");\r
256 \r
257         if(m_brush.style == WPGBrush::Gradient)\r
258                 printf("fill: url(#grad%d); ", m_gradientIndex-1);\r
259 \r
260         if(m_brush.style == WPGBrush::Solid)\r
261                 printf("fill: rgb(%d,%d,%d); ", m_brush.foreColor.red, \r
262                         m_brush.foreColor.green, m_brush.foreColor.blue);\r
263 \r
264         printf("\""); // style\r
265 }\r
266 \r
267 \r
268 int main(int argc, char *argv[])\r
269 {\r
270         if (argc < 2)\r
271         {\r
272                 printf("usage: wpg2svg <WordPerfect Graphic>\n");\r
273                 return -1;\r
274         }\r
275 \r
276         const char* filename = argv[1];\r
277         WPGInputStream* input = new WPGFileStream(filename);\r
278         if (input->isOle())\r
279         {\r
280                 WPGInputStream* olestream = input->getWPGOleStream();\r
281                 if (olestream)\r
282                 {\r
283                         delete input;\r
284                         input = olestream;\r
285                 }\r
286         }\r
287 \r
288         if (!WPGraphics::isSupported(input))\r
289         {\r
290                 fprintf(stderr, "ERROR: Unsupported file format (unsupported version) or file is encrypted!\n");\r
291                 return 1;\r
292         }\r
293         \r
294         InkscapePainter painter;\r
295         WPGraphics::parse(input, &painter);\r
296         \r
297         return 0;\r
298 }\r