Code

Cleaned up virtual destructor problem and compile warnings.
[inkscape.git] / src / extension / internal / wpg-input.cpp
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