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 #include "document.h"\r
47 \r
48 #include "libwpg/libwpg.h"\r
49 #include "libwpg/WPGStreamImplementation.h"\r
50 \r
51 using namespace libwpg;\r
52 \r
53 namespace Inkscape {\r
54 namespace Extension {\r
55 namespace Internal {\r
56 \r
57 class InkscapePainter : public libwpg::WPGPaintInterface {\r
58 public:\r
59 InkscapePainter();\r
60 \r
61 void startDocument(double imageWidth, double imageHeight);\r
62 void endDocument();\r
63 void startLayer(unsigned int id);\r
64 void endLayer(unsigned int id);\r
65 \r
66 void setPen(const WPGPen& pen);\r
67 void setBrush(const WPGBrush& brush);\r
68 void setFillRule(FillRule rule);\r
69 \r
70 void drawRectangle(const WPGRect& rect, double rx, double ry);\r
71 void drawEllipse(const WPGPoint& center, double rx, double ry);\r
72 void drawPolygon(const WPGPointArray& vertices);\r
73 void drawPath(const WPGPath& path);\r
74 \r
75 private:\r
76 WPGPen m_pen;\r
77 WPGBrush m_brush;\r
78 FillRule m_fillRule;\r
79 int m_gradientIndex;\r
80 void writeStyle();\r
81 void printf (char * fmt, ...) {\r
82 va_list args;\r
83 va_start(args, fmt);\r
84 gchar * buf = g_strdup_vprintf(fmt, args);\r
85 va_end(args);\r
86 if (buf) {\r
87 document += buf;\r
88 g_free(buf);\r
89 }\r
90 }\r
91 \r
92 public:\r
93 Glib::ustring document;\r
94 };\r
95 \r
96 InkscapePainter::InkscapePainter(): m_fillRule(AlternatingFill), m_gradientIndex(1)\r
97 {\r
98 }\r
99 \r
100 void InkscapePainter::startDocument(double width, double height) \r
101 {\r
102 document = "";\r
103 printf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");\r
104 printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"");\r
105 printf(" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");\r
106 \r
107 // printf("<!-- Created with wpg2svg/libwpg %s -->\n", LIBWPG_VERSION_STRING);\r
108 \r
109 printf("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" ");\r
110 printf("xmlns:xlink=\"http://www.w3.org/1999/xlink\" "); \r
111 printf("width=\"%g\" height=\"%f\" >\n", 72*width, 72*height);\r
112 \r
113 m_gradientIndex = 1;\r
114 }\r
115 \r
116 void InkscapePainter::endDocument()\r
117 {\r
118 printf("</svg>\n");\r
119 }\r
120 \r
121 void InkscapePainter::setPen(const WPGPen& pen)\r
122 {\r
123 m_pen = pen;\r
124 }\r
125 \r
126 void InkscapePainter::setBrush(const WPGBrush& brush)\r
127 {\r
128 m_brush = brush;\r
129 \r
130 if(m_brush.style == WPGBrush::Gradient)\r
131 {\r
132 double angle = m_brush.gradient.angle();\r
133 \r
134 printf("<defs>\n");\r
135 printf(" <linearGradient id=\"grad%d\" >\n", m_gradientIndex++);\r
136 for(unsigned c = 0; c < m_brush.gradient.count(); c++)\r
137 {\r
138 // round to nearest percentage\r
139 int ofs = (int)(100.0*m_brush.gradient.stopOffset(c)+0.5);\r
140 \r
141 WPGColor color = m_brush.gradient.stopColor(c);\r
142 printf(" <stop offset=\"%d%%\" stop-color=\"#%02x%02x%02x\" />\n",\r
143 ofs, color.red, color.green, color.blue);\r
144 }\r
145 printf(" </linearGradient>\n");\r
146 \r
147 // not a simple horizontal gradient\r
148 if(angle != -90.0)\r
149 {\r
150 printf(" <linearGradient xlink:href=\"#grad%d\"", m_gradientIndex-1);\r
151 printf(" id=\"grad%d\" ", m_gradientIndex++);\r
152 printf("x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" "); \r
153 printf("gradientTransform=\"rotate(%f)\" ", angle);\r
154 printf("gradientUnits=\"objectBoundingBox\" >\n");\r
155 printf(" </linearGradient>\n");\r
156 }\r
157 \r
158 printf("</defs>\n");\r
159 }\r
160 }\r
161 \r
162 void InkscapePainter::setFillRule(FillRule rule)\r
163 {\r
164 m_fillRule = rule;\r
165 }\r
166 \r
167 void InkscapePainter::startLayer(unsigned int id)\r
168 {\r
169 printf("<g id=\"Layer%d\" >\n", id);\r
170 }\r
171 \r
172 void InkscapePainter::endLayer(unsigned int)\r
173 {\r
174 printf("</g>\n");\r
175 }\r
176 \r
177 void InkscapePainter::drawRectangle(const WPGRect& rect, double rx, double ry)\r
178 {\r
179 printf("<rect ");\r
180 printf("x=\"%f\" y=\"%f\" ", 72*rect.x1, 72*rect.y1);\r
181 printf("width=\"%f\" height=\"%f\" ", 72*rect.width(), 72*rect.height());\r
182 if((rx !=0) || (ry !=0))\r
183 printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);\r
184 writeStyle();\r
185 printf("/>\n");\r
186 }\r
187 \r
188 void InkscapePainter::drawEllipse(const WPGPoint& center, double rx, double ry)\r
189 {\r
190 printf("<ellipse ");\r
191 printf("cx=\"%f\" cy=\"%f\" ", 72*center.x, 72*center.y);\r
192 printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);\r
193 writeStyle();\r
194 printf("/>\n");\r
195 }\r
196 \r
197 void InkscapePainter::drawPolygon(const WPGPointArray& vertices)\r
198 {\r
199 if(vertices.count() < 2)\r
200 return;\r
201 \r
202 if(vertices.count() == 2)\r
203 {\r
204 const WPGPoint& p1 = vertices[0];\r
205 const WPGPoint& p2 = vertices[1];\r
206 printf("<line ");\r
207 printf("x1=\"%f\" y1=\"%f\" ", 72*p1.x, 72*p1.y);\r
208 printf("x2=\"%f\" y2=\"%f\"\n", 72*p2.x, 72*p2.y);\r
209 writeStyle();\r
210 printf("/>\n");\r
211 }\r
212 else\r
213 {\r
214 printf("<polyline ");\r
215 printf("points=\"");\r
216 for(unsigned i = 0; i < vertices.count(); i++)\r
217 {\r
218 printf("%f %f", 72*vertices[i].x, 72*vertices[i].y);\r
219 if(i < vertices.count()-1) printf(", ");\r
220 }\r
221 printf("\"\n");\r
222 writeStyle();\r
223 printf("/>\n");\r
224 }\r
225 }\r
226 \r
227 void InkscapePainter::drawPath(const WPGPath& path)\r
228 {\r
229 printf("<path d=\"");\r
230 for(unsigned i = 0; i < path.count(); i++)\r
231 {\r
232 WPGPathElement element = path.element(i);\r
233 WPGPoint point = element.point;\r
234 switch(element.type)\r
235 {\r
236 case WPGPathElement::MoveToElement:\r
237 printf("\n M%f,%f ", 72*point.x, 72*point.y );\r
238 break;\r
239 \r
240 case WPGPathElement::LineToElement:\r
241 printf("\n L%f,%f ", 72*point.x, 72*point.y );\r
242 break;\r
243 \r
244 case WPGPathElement::CurveToElement:\r
245 printf("C");\r
246 printf("%f,%f ", 72*element.extra1.x, 72*element.extra1.y );\r
247 printf("%f,%f ", 72*element.extra2.x, 72*element.extra2.y );\r
248 printf("%f,%f", 72*point.x, 72*point.y );\r
249 break;\r
250 \r
251 default:\r
252 break;\r
253 }\r
254 }\r
255 \r
256 if(path.closed)\r
257 printf("Z");\r
258 \r
259 printf("\" \n");\r
260 writeStyle();\r
261 printf("/>\n");\r
262 }\r
263 \r
264 // create "style" attribute based on current pen and brush\r
265 void InkscapePainter::writeStyle()\r
266 {\r
267 printf("style=\"");\r
268 \r
269 const WPGColor& color = m_pen.foreColor;\r
270 printf("stroke-width: %f; ", 72*m_pen.width);\r
271 if(m_pen.width > 0.0)\r
272 {\r
273 printf("stroke: rgb(%d,%d,%d); ", color.red, color.green, color.blue);\r
274 if(color.alpha != 0)\r
275 // alpha = 0 means opacity = 1.0, alpha = 256 means opacity = 0\r
276 printf("stroke-opacity: %f; ", 1.0-(color.alpha/256.0));\r
277 }\r
278 \r
279 if(!m_pen.solid)\r
280 {\r
281 printf("stroke-dasharray: ");\r
282 for(unsigned i = 0; i < m_pen.dashArray.count(); i++)\r
283 {\r
284 printf("%f", 72*m_pen.dashArray.at(i)*m_pen.width);\r
285 if(i < m_pen.dashArray.count()-1) \r
286 printf(", ");\r
287 }\r
288 printf("; ");\r
289 }\r
290 \r
291 if(m_brush.style == WPGBrush::NoBrush)\r
292 printf("fill: none; ");\r
293 \r
294 if(m_fillRule == InkscapePainter::WindingFill)\r
295 printf("fill-rule: nonzero; ");\r
296 else if(m_fillRule == InkscapePainter::AlternatingFill)\r
297 printf("fill-rule: evenodd; ");\r
298 \r
299 if(m_brush.style == WPGBrush::Gradient)\r
300 printf("fill: url(#grad%d); ", m_gradientIndex-1);\r
301 \r
302 if(m_brush.style == WPGBrush::Solid)\r
303 printf("fill: rgb(%d,%d,%d); ", m_brush.foreColor.red, \r
304 m_brush.foreColor.green, m_brush.foreColor.blue);\r
305 \r
306 printf("\""); // style\r
307 }\r
308 \r
309 SPDocument *\r
310 WpgInput::open(Inkscape::Extension::Input * mod, const gchar * uri) {\r
311 WPGInputStream* input = new WPGFileStream(uri);\r
312 if (input->isOle()) {\r
313 WPGInputStream* olestream = input->getWPGOleStream();\r
314 if (olestream) {\r
315 delete input;\r
316 input = olestream;\r
317 }\r
318 }\r
319 \r
320 if (!WPGraphics::isSupported(input)) {\r
321 //! \todo Dialog here\r
322 // fprintf(stderr, "ERROR: Unsupported file format (unsupported version) or file is encrypted!\n");\r
323 // printf("I'm giving up not supported\n");\r
324 return NULL;\r
325 }\r
326 \r
327 InkscapePainter painter;\r
328 WPGraphics::parse(input, &painter);\r
329 \r
330 //printf("I've got a doc: \n%s", painter.document.c_str());\r
331 \r
332 return sp_document_new_from_mem(painter.document.c_str(), strlen(painter.document.c_str()), TRUE);\r
333 }\r
334 \r
335 #include "clear-n_.h"\r
336 \r
337 void\r
338 WpgInput::init(void) {\r
339 Inkscape::Extension::Extension * ext;\r
340 \r
341 ext = Inkscape::Extension::build_from_mem(\r
342 "<inkscape-extension>\n"\r
343 "<name>" N_("WPG Input") "</name>\n"\r
344 "<id>org.inkscape.input.wpg</id>\n"\r
345 "<input>\n"\r
346 "<extension>.wpg</extension>\n"\r
347 "<mimetype>image/x-wpg</mimetype>\n"\r
348 "<filetypename>" N_("WordPerfect Graphics (*.wpg)") "</filetypename>\n"\r
349 "<filetypetooltip>" N_("Vector graphics format used by Corel WordPerfect") "</filetypetooltip>\n"\r
350 "</input>\n"\r
351 "</inkscape-extension>", new WpgInput());\r
352 } // init\r
353 \r
354 } } } /* namespace Inkscape, Extension, Implementation */\r
355 \r
356 /*\r
357 Local Variables:\r
358 mode:c++\r
359 c-file-style:"stroustrup"\r
360 c-file-offsets:((innamespace . 0)(inline-open . 0))\r
361 indent-tabs-mode:nil\r
362 fill-column:99\r
363 End:\r
364 */\r
365 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r