Code

r13108@tres: ted | 2006-07-30 12:27:51 -0700
[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 \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