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