Code

Cleaned up virtual destructor problem and compile warnings.
[inkscape.git] / src / extension / internal / libwpg / WPG2Parser.cpp
1 /* libwpg
2  * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
3  * Copyright (C) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)
4  * Copyright (C) 2004 Marc Oude Kotte (marc@solcon.nl)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the 
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
19  * Boston, MA  02111-1301 USA
20  *
21  * For further information visit http://libwpg.sourceforge.net
22  */
24 /* "This product is not manufactured, approved, or supported by
25  * Corel Corporation or Corel Corporation Limited."
26  */
28 #include "WPG2Parser.h"
29 #include "WPGPaintInterface.h"
30 #include "libwpg_utils.h"
32 #include <math.h>
33 #include <vector>
35 // MSVC++ 6.0 does not have the macro defined, so we define it
36 #ifndef M_PI
37 #define M_PI 3.14159265358979323846
38 #endif
40 static const unsigned char defaultWPG2PaletteRed[] = {
41         0x00, 0xFF, 0x7F, 0xBF, 0x00, 0x00, 0x00, 0x7F,
42         0x7F, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
43         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
44         0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
45         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
46         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
47         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
48         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
49         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
50         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
51         0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
52         0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
53         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
54         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
55         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
56         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
57         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
58         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
59         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
60         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
61         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
62         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
63         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
64         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
65         0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
66         0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
67         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
68         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
69         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
70         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
71         0x33, 0x47, 0x61, 0x73, 0x87, 0x9C, 0xB0, 0xC7,
72         0xCC, 0xD4, 0xDB, 0xE3, 0xE8, 0xF0, 0xF7, 0xFF,
73 };
75 static const unsigned char defaultWPG2PaletteGreen[] = {
76         0x00, 0xFF, 0x7F, 0xBF, 0x00, 0x7F, 0x7F, 0x00,
77         0x00, 0x7F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF,
78         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
79         0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
80         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
81         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
82         0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
83         0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
84         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
85         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
86         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
87         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
88         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
89         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
90         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
91         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
92         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
93         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
94         0x56, 0x64, 0x72, 0x80, 0x8E, 0x9C, 0xAA, 0xB1,
95         0xB8, 0xBF, 0xC6, 0xCD, 0xD4, 0xDB, 0xE2, 0xE9,
96         0x2B, 0x32, 0x39, 0x40, 0x47, 0x4E, 0x55, 0x63,
97         0x71, 0x7F, 0x8D, 0x9B, 0xA9, 0xB7, 0xC5, 0xD3,
98         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
99         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
100         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
101         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
102         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
103         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
104         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
105         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
106         0x29, 0x38, 0x45, 0x4F, 0x5C, 0x63, 0x69, 0xD4,
107         0x87, 0x8F, 0x9C, 0xA8, 0xB3, 0xC4, 0xCF, 0xE0,
108 };
110 static const unsigned char defaultWPG2PaletteBlue[] = {
111         0x00, 0xFF, 0x7F, 0xBF, 0x7F, 0x00, 0x7F, 0x00,
112         0x7F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
113         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
114         0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
115         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
116         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
117         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
118         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
119         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
120         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
121         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
122         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
123         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
124         0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
125         0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
126         0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
127         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
128         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
129         0x7B, 0x91, 0xA7, 0xB0, 0xD3, 0xE4, 0xFF, 0xFF,
130         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
131         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
132         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
133         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
134         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
135         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
136         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
137         0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
138         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
139         0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
140         0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
141         0x11, 0x17, 0x1C, 0x24, 0x29, 0x2B, 0x2B, 0x30,
142         0x47, 0x57, 0x69, 0x78, 0x8C, 0x9C, 0xB0, 0xC7,
143 };
145 class WPG2Parser::ObjectCharacterization
147 public:
148         bool taper;
149         bool translate;
150         bool skew;
151         bool scale;
152         bool rotate;
153         bool hasObjectId;
154         bool editLock;
155         bool windingRule;
156         bool filled;
157         bool closed;
158         bool framed;
160         unsigned long objectId;
161         unsigned long lockFlags;
162         long rotationAngle;
163         long sxcos;
164         long sycos;
165         long kxsin;
166         long kysin;
167         long txinteger;
168         short txfraction;
169         long tyinteger;
170         short tyfraction;
171         long px;
172         long py;
174         WPG2TransformMatrix matrix;
176         ObjectCharacterization():
177                 taper(false),
178                 translate(false),
179                 skew(false),
180                 scale(false),
181                 rotate(false),
182                 hasObjectId(false),
183                 editLock(false),
184                 windingRule(false),
185                 filled(false),
186                 closed(false),
187                 framed(true),
188                 objectId(0),
189                 lockFlags(0),
190                 rotationAngle(0),
191                 sxcos(0),
192                 sycos(0),
193                 kxsin(0),
194                 kysin(0),
195                 txinteger(0),
196                 txfraction(0),
197                 tyinteger(0),
198                 tyfraction(0),
199                 px(0),
200                 py(0)
201                         {}
202 };
204 WPG2Parser::WPG2Parser(WPGInputStream *input, WPGPaintInterface* painter):
205         WPGXParser(input, painter),
206         m_success(true), m_exit(false),
207         m_xres(1200), m_yres(1200),
208         m_xofs(0), m_yofs(0),
209         m_width(0), m_height(0),
210         m_doublePrecision(false),
211         m_layerOpened(false), m_layerId(0)
215 bool WPG2Parser::parse()
217         typedef void (WPG2Parser::*Method)();
219         struct RecordHandler
220         {
221                 int type;
222                 const char *name;
223                 Method handler;
224         };
226         static const struct RecordHandler handlers[] =
227         {
228                 { 0x01, "Start WPG",            &WPG2Parser::handleStartWPG },   
229                 { 0x02, "End WPG",              &WPG2Parser::handleEndWPG },     
230                 { 0x03, "Form Settings",        0 },     // ignored
231                 { 0x04, "Ruler Settings",       0 },     // ignored
232                 { 0x05, "Grid Settings",        0 },     // ignored
233                 { 0x06, "Layer",                &WPG2Parser::handleLayer },
234                 { 0x08, "Pen Style Definition", &WPG2Parser::handlePenStyleDefinition },
235                 { 0x09, "Pattern Definition",   0 },
236                 { 0x0a, "Comment",              0 },     // ignored
237                 { 0x0b, "Color Transfer",       0 },
238                 { 0x0c, "Color Palette",        &WPG2Parser::handleColorPalette },
239                 { 0x0d, "DP Color Palette",     &WPG2Parser::handleDPColorPalette },
240                 { 0x0e, "Bitmap Data",          0 },
241                 { 0x0f, "Text Data",            0 },
242                 { 0x10, "Chart Style",          0 },     // ignored
243                 { 0x11, "Chart Data",           0 },     // ignored
244                 { 0x12, "Object Image",         0 },
245                 { 0x15, "Polyline",             &WPG2Parser::handlePolyline },
246                 { 0x16, "Polyspline",           0 },
247                 { 0x17, "Polycurve",            &WPG2Parser::handlePolycurve },
248                 { 0x18, "Rectangle",            &WPG2Parser::handleRectangle },
249                 { 0x19, "Arc",                  &WPG2Parser::handleArc },
250                 { 0x1a, "Compound Polygon",     &WPG2Parser::handleCompoundPolygon },
251                 { 0x1b, "Bitmap",               0 },
252                 { 0x1c, "Text Line",            0 },
253                 { 0x1d, "Text Block",           0 },
254                 { 0x1e, "Text Path",            0 },
255                 { 0x1f, "Chart",                0 },
256                 { 0x20, "Group",                0 },
257                 { 0x21, "Object Capsule",       0 },
258                 { 0x22, "Font Settings",        0 },
259                 { 0x25, "Pen Fore Color",       &WPG2Parser::handlePenForeColor },
260                 { 0x26, "DP Pen Fore Color",    &WPG2Parser::handleDPPenForeColor },
261                 { 0x27, "Pen Back Color",       &WPG2Parser::handlePenBackColor },
262                 { 0x28, "DP Pen Back Color",    &WPG2Parser::handleDPPenBackColor },
263                 { 0x29, "Pen Style",            &WPG2Parser::handlePenStyle },
264                 { 0x2a, "Pen Pattern",          0 },
265                 { 0x2b, "Pen Size",             &WPG2Parser::handlePenSize },
266                 { 0x2c, "DP Pen Size",          &WPG2Parser::handleDPPenSize  },
267                 { 0x2d, "Line Cap",             0 },
268                 { 0x2e, "Line Join",            0 },
269                 { 0x2f, "Brush Gradient",       &WPG2Parser::handleBrushGradient },
270                 { 0x30, "DP Brush Gradient",    &WPG2Parser::handleDPBrushGradient },
271                 { 0x31, "Brush Fore Color",     &WPG2Parser::handleBrushForeColor },
272                 { 0x32, "DP Brush Fore Color",  &WPG2Parser::handleDPBrushForeColor },
273                 { 0x33, "Brush Back Color",     &WPG2Parser::handleBrushBackColor },
274                 { 0x34, "DP Brush Back Color",  &WPG2Parser::handleDPBrushBackColor },
275                 { 0x35, "Brush Pattern",        &WPG2Parser::handleBrushPattern },
276                 { 0x36, "Horizontal Line",      0 },
277                 { 0x37, "Vertical Line",        0 },
278                 { 0x38, "Poster Settings",      0 },
279                 { 0x39, "Image State",          0 },
280                 { 0x3a, "Envelope Definition",  0 },
281                 { 0x3b, "Envelope",             0 },
282                 { 0x3c, "Texture Definition",   0 },
283                 { 0x3d, "Brush Texture",        0 },
284                 { 0x3e, "Texture Alignment",    0 },
285                 { 0x3f, "Pen Texture ",         0 },
286                 { 0x00, 0, 0 } // end marker
287         };       
289         // initialization
290         m_success = true;
291         m_exit = false;
292         m_xres = m_yres = 1200;
293         m_doublePrecision = false;
294         m_layerOpened = false;
295         m_matrix = WPG2TransformMatrix();
296         m_groupStack = std::stack<WPGGroupContext>();
297         m_compoundMatrix = WPG2TransformMatrix();
298         m_compoundWindingRule = false;
299         m_compoundFilled = false;
300         m_compoundFramed = true;
301         m_compoundClosed = false;
302         
303         // default style
304         m_pen.foreColor = WPGColor(0,0,0);
305         m_pen.backColor = WPGColor(0,0,0);
306         m_pen.width = 0.001;
307         m_pen.height = 0.001;
308         m_pen.solid = true;
309         m_pen.dashArray = WPGDashArray();
310         m_brush.foreColor = WPGColor(0,0,0);
311         m_brush.backColor = WPGColor(0,0,0);
312         resetPalette();
314         while(!m_input->atEnd())
315         {
316                 long recordPos = m_input->tell();
317                 int recordClass = readU8();
318                 int recordType = readU8();
319                 int extension = readVariableLengthInteger();
320                 int length = readVariableLengthInteger();
321                 long nextPos = m_input->tell() + length;
322 #if !defined(DEBUG)
323                 (void)recordPos;
324                 (void)recordClass;
325 #endif // !defined(DEBUG)
326                 
327                 // inside a subgroup, one less sub record
328                 if(!m_groupStack.empty())
329                         m_groupStack.top().subIndex--;
331                 // search function to handler this record
332                 int index = -1;
333                 for(int i = 0; (index < 0) && handlers[i].name; i++)
334                         if(handlers[i].type == recordType)
335                                 index = i;
336                                 
337                 WPG_DEBUG_MSG(("\n"));
338                 if(index < 0)
339                 {
340                         WPG_DEBUG_MSG(("Unknown record type 0x%02x at %d  size %d  extension %d\n", 
341                                 recordType, recordPos, length, extension));
342                 }
343                 else
344                 {
345                         Method recordHandler = handlers[index].handler;
346                         
347                         if(!recordHandler)
348                                 WPG_DEBUG_MSG(("Record '%s' (ignored) type 0x%02x at %d  size %d  extension %d\n",
349                                         handlers[index].name, recordType, recordPos, length, extension));
350                         else
351                         {
352                                 WPG_DEBUG_MSG(("Record '%s' type 0x%02x at %d  size %d  extension %d\n", 
353                                         handlers[index].name, recordType, recordPos, length, extension));
354                                         
355                                 // invoke the handler for this record
356                                 (this->*recordHandler)();
357                         }
358                 }
360                 // the last subgroup
361                 if(!m_groupStack.empty())
362                 {
363                         WPGGroupContext& context = m_groupStack.top();
364                         if(context.subIndex == 0)
365                         {
366                                 if(context.isCompoundPolygon())
367                                         flushCompoundPolygon();
368                                 m_groupStack.pop();
369                         }
370                 }
372                 // we enter another subgroup, save the context to stack
373                 if(extension > 0)
374                 {
375                         WPGGroupContext context;
376                         context.parentType = recordType;
377                         context.subIndex = extension;
378                         if(context.isCompoundPolygon())
379                         {
380                                 context.compoundMatrix = m_compoundMatrix;
381                                 context.compoundFilled = m_compoundFilled;
382                                 context.compoundFramed = m_compoundFramed;
383                                 context.compoundClosed = m_compoundClosed;
384                         }
385                         m_groupStack.push(context);
386                 }
388                 //if(m_input->tell() > nextPos)
389                 {
390                         //WPG_DEBUG_MSG(("Record 0x%x consumes more bytes than necessary!\n", recordType));
391                         WPG_DEBUG_MSG(("Current stream position: %d\n", m_input->tell()));
392                 }
393         
394                 if(m_exit) break;
395                 
396                 m_input->seek(nextPos);
397         }
399         return m_success;
402 #if defined(DEBUG)
403 static const char* describePrecision(unsigned char precision)
405         const char* result = "Unknown";
406         switch(precision)
407         {
408                 case 0: result = "single"; break;
409                 case 1: result = "double"; break;
410                 default: break;
411         }
412         return result;
414         
415 static const char* describeGradient(unsigned char gradientType)
417         const char* result = "Unknown";
418         switch(gradientType)
419         {
420                 case 0: result = "None"; break;
421                 case 1: result = "Linear"; break;
422                 case 2: result = "Polygonal"; break;
423                 case 3: result = "Concentric Circles"; break;
424                 case 4: result = "Convergent Circles"; break;
425                 case 5: result = "Concentric Ellipses"; break;
426                 case 6: result = "Convergent Ellipses"; break; 
427                 case 7: result = "Concentric Squares"; break; 
428                 case 8: result = "Convergent Squares"; break; 
429                 case 9: result = "Concentric Rectangles"; break; 
430                 case 10: result = "Convergent Rectangles"; break;
431                 default: break;
432         }
433         return result;
435 #endif // defined(DEBUG)
437 #define TO_DOUBLE(x) ( (m_doublePrecision) ? ((double)(x)/65536.0) : (double)(x) )
438 #define TRANSFORM_XY(x,y) { m_matrix.transform((x),(y)); (x)-= m_xofs; (y)-= m_yofs; (y)=m_height-(y); }
440 void WPG2Parser::handleStartWPG()
442         unsigned int horizontalUnit = readU16();
443         unsigned int verticalUnit = readU16();
444         unsigned char precision = readU8();
445         
446         // sanity check
447         m_xres = horizontalUnit;
448         m_yres = verticalUnit;
449         if((horizontalUnit==0) || (verticalUnit==0))
450         {
451                 m_xres = m_yres = 1200;
452                 WPG_DEBUG_MSG(("Warning ! Insane unit of measure"));
453         }
454         
455         // danger if we do not recognize the precision code
456         if(precision != 0)
457         if(precision != 1)
458         {
459                 m_success = false;
460                 m_exit = true;
461                 return;
462         }
463         m_doublePrecision = (precision == 1);
464         
465         long viewportX1 = (m_doublePrecision) ? readS32() : readS16();
466         long viewportY1 = (m_doublePrecision) ? readS32() : readS16();
467         long viewportX2 = (m_doublePrecision) ? readS32() : readS16();
468         long viewportY2 = (m_doublePrecision) ? readS32() : readS16();
469 #if !defined(DEBUG)
470         (void)viewportX1;
471         (void)viewportY1;
472         (void)viewportX2;
473         (void)viewportY2;
474 #endif // !defined(DEBUG)
475         
476         long imageX1 = (m_doublePrecision) ? readS32() : readS16();
477         long imageY1 = (m_doublePrecision) ? readS32() : readS16();
478         long imageX2 = (m_doublePrecision) ? readS32() : readS16();
479         long imageY2 = (m_doublePrecision) ? readS32() : readS16();
481         // used to adjust coordinates   
482         m_xofs = (imageX1 < imageX2) ? imageX1 : imageX2;
483         m_yofs = (imageY1 < imageY2) ? imageY1 : imageX2;
484         m_width = (imageX2 > imageX1 ) ? imageX2-imageX1 : imageX1-imageX2;
485         m_height = (imageY2 > imageY1) ? imageY2-imageY1 : imageY1-imageY2;
486         
487         WPG_DEBUG_MSG(("StartWPG\n"));
488         WPG_DEBUG_MSG(("  Horizontal unit of measure : %d pixels/inch\n", horizontalUnit));
489         WPG_DEBUG_MSG(("    Vertical unit of measure : %d pixels/inch\n", verticalUnit));
490         WPG_DEBUG_MSG(("              Data precision : %d (%s)\n", precision, describePrecision(precision)));
491         WPG_DEBUG_MSG(("                 Viewport X1 : %d\n", viewportX1));
492         WPG_DEBUG_MSG(("                 Viewport Y1 : %d\n", viewportY1));
493         WPG_DEBUG_MSG(("                 Viewport X2 : %d\n", viewportX2));
494         WPG_DEBUG_MSG(("                 Viewport Y2 : %d\n", viewportY2));
495         WPG_DEBUG_MSG(("                    Image X1 : %d\n", imageX1));
496         WPG_DEBUG_MSG(("                    Image Y1 : %d\n", imageY1));
497         WPG_DEBUG_MSG(("                    Image X2 : %d\n", imageX2));
498         WPG_DEBUG_MSG(("                    Image Y2 : %d\n", imageY2));
499         WPG_DEBUG_MSG(("                    X offset : %d\n", m_xofs));
500         WPG_DEBUG_MSG(("                    Y offset : %d\n", m_yofs));
501         WPG_DEBUG_MSG(("                       width : %d\n", m_width));
502         WPG_DEBUG_MSG(("                      height : %d\n", m_height));
503         
504         double width = (TO_DOUBLE(m_width)) / m_xres;
505         double height = (TO_DOUBLE(m_height)) / m_yres;
506         
507         m_painter->startDocument(width, height);
509         static const int WPG2_defaultPenDashes[] = {
510                 1,   291,  0,                            // style #0 (actually solid)
511                 1,   218, 73,                            // style #1
512                 1,   145, 73,                            // style #2
513                 1,    73, 73,                            // style #3
514                 1,    36, 36,                            // style #4
515                 1,    18, 18,                            // style #5
516                 1,    18, 55,                            // style #6
517                 3,    18, 55,  18, 55, 18, 127,          // style #7
518                 2,   164, 55,  18, 55,                   // style #8
519                 3,   145, 36, 138, 36, 18,  36,          // style #9
520                 3,    91, 55,  91, 55, 18,  55,          // style #10
521                 4,    91, 36,  91, 36, 18,  36, 18, 36,  // style #11
522                 2,   182, 73,  73, 73,                   // style #12
523                 3,   182, 36,  55, 36, 55,  36,          // style #13
524                 3,   255, 73, 255, 73, 73,  73,          // style #14
525                 4,   273, 36, 273, 36, 55,  36, 55, 36,  // style #15
526                 0 // end marker
527         };
528         
529         // create default pen styles
530         int styleNo = 0;
531         for(int i = 0; i < static_cast<int>(sizeof(WPG2_defaultPenDashes)/sizeof(WPG2_defaultPenDashes[0]));)
532         {
533                 int segments = 2 * WPG2_defaultPenDashes[i++];
534                 if(segments == 0) break;
535                 WPGDashArray dashArray;
536                 for(int j = 0; j < segments; j++, i++)
537                         dashArray.add(WPG2_defaultPenDashes[i]*3.6/218.0);
538                 m_penStyles[styleNo] = dashArray;
539                 styleNo++; 
540         }
543 void WPG2Parser::handleEndWPG()
545         // sentinel
546         if(m_layerOpened)
547                 m_painter->endLayer(m_layerId);
549         m_painter->endDocument();
550         m_exit = true;
553 void WPG2Parser::handleLayer()
555         m_layerId = readU16();
557         // close previous one
558         if(m_layerOpened)
559                 m_painter->endLayer(m_layerId);
561         m_painter->startLayer(m_layerId);
562         m_layerOpened = true;
564         WPG_DEBUG_MSG(("  Layer Id: %d\n", m_layerId));
567 void WPG2Parser::handleCompoundPolygon()
569         ObjectCharacterization objCh;
570         parseCharacterization(&objCh);
572         m_compoundWindingRule = objCh.windingRule;
573         m_compoundMatrix = objCh.matrix;
574         m_compoundFilled = objCh.filled;
575         m_compoundFramed = objCh.framed;
576         m_compoundClosed = objCh.closed;
578 void WPG2Parser::flushCompoundPolygon()
580         WPGGroupContext& context = m_groupStack.top();
581         
582         m_painter->setBrush( context.compoundFilled ? m_brush : WPGBrush() );
583         m_painter->setPen( context.compoundFramed ? m_pen : WPGPen() );
584         if(context.compoundWindingRule)
585                 m_painter->setFillRule(WPGPaintInterface::WindingFill);
586         else
587                 m_painter->setFillRule(WPGPaintInterface::AlternatingFill);
588         context.compoundPath.closed = context.compoundClosed;
589         m_painter->drawPath(context.compoundPath);
592 void WPG2Parser::handlePenStyleDefinition()
594         unsigned int style = readU16();
595         unsigned int segments = readU16();
597         WPGDashArray dashArray;
598         for(unsigned i = 0; i < segments; i++)
599         {
600                 unsigned int p = (m_doublePrecision) ? readU32() : readU16();
601                 unsigned int q = (m_doublePrecision) ? readU32() : readU16();
602                 dashArray.add(TO_DOUBLE(p)*3.6/218.0);
603                 dashArray.add(TO_DOUBLE(q)*3.6/218.0);
604         }
605         m_penStyles[style] = dashArray;
607         WPG_DEBUG_MSG(("          Style : %d\n", style));
608         WPG_DEBUG_MSG(("  Segment pairs : %d\n", segments));
611 // TODO
612 void WPG2Parser::handlePatternDefinition()
614         WPG_DEBUG_MSG(("PatternDefinition\n"));
617 void WPG2Parser::handleColorPalette()
619         unsigned startIndex = readU16();
620         unsigned numEntries = readU16();
622         for(unsigned i = 0; i < numEntries; i++)
623         {
624                 WPGColor color;
625                 color.red = readU8();
626                 color.green = readU8();
627                 color.blue = readU8();
628                 color.alpha = readU8();
629                 m_colorPalette[startIndex+i] = color;
630                 WPG_DEBUG_MSG(("Index#%d: RGB %d %d %d\n", startIndex+i, color.red, color.green, color.blue));
631         }
634 void WPG2Parser::handleDPColorPalette()
636         unsigned startIndex = readU16();
637         unsigned numEntries = readU16();
639         for(int i = 0; i < static_cast<int>(numEntries); i++)
640         {
641                 WPGColor color;
642                 color.red = readU16() >> 8 ;
643                 color.green = readU16() >> 8 ;
644                 color.blue = readU16() >> 8 ;
645                 color.alpha = readU16() >> 8 ;
646                 m_colorPalette[startIndex+i] = color;
647                 WPG_DEBUG_MSG(("Index#%d: RGB %d %d %d\n", startIndex+i, color.red, color.green, color.blue));
648         }
651 void WPG2Parser::handlePenForeColor()
653         unsigned char red = readU8();
654         unsigned char green = readU8();
655         unsigned char blue = readU8();
656         unsigned char alpha = readU8();
658         m_pen.foreColor = WPGColor(red, green, blue, alpha);
660         WPG_DEBUG_MSG(("   Foreground color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
663 void WPG2Parser::handleDPPenForeColor()
665         // we just ignore the least significant 8 bits
666         unsigned int red = (m_doublePrecision)   ? readU16()>>8 : readU8();
667         unsigned int green = (m_doublePrecision) ? readU16()>>8 : readU8();
668         unsigned int blue = (m_doublePrecision)  ? readU16()>>8 : readU8();
669         unsigned int alpha = (m_doublePrecision) ? readU16()>>8 : readU8();
671         m_pen.foreColor = WPGColor(red, green, blue, alpha);
673         WPG_DEBUG_MSG(("   Foreground color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
676 void WPG2Parser::handlePenBackColor()
678         unsigned char red = readU8();
679         unsigned char green = readU8();
680         unsigned char blue = readU8();
681         unsigned char alpha = readU8();
683         m_pen.backColor = WPGColor(red, green, blue, alpha);
685         WPG_DEBUG_MSG(("   Background color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
688 void WPG2Parser::handleDPPenBackColor()
690         // we just ignore the least significant 8 bits
691         unsigned int red = (m_doublePrecision)   ? readU16()>>8 : readU8();
692         unsigned int green = (m_doublePrecision) ? readU16()>>8 : readU8();
693         unsigned int blue = (m_doublePrecision)  ? readU16()>>8 : readU8();
694         unsigned int alpha = (m_doublePrecision) ? readU16()>>8 : readU8();
696         m_pen.backColor = WPGColor(red, green, blue, alpha);
698         WPG_DEBUG_MSG(("   Background color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
701 void WPG2Parser::handlePenStyle()
703         unsigned int style = readU16();
705         m_pen.dashArray = m_penStyles[style];
706         m_pen.solid = (style == 0);
708         WPG_DEBUG_MSG(("   Pen style : %d\n", style));
709         WPG_DEBUG_MSG(("   Segments : %d\n", m_pen.dashArray.count()));
712 void WPG2Parser::handlePenSize()
714         unsigned int width = readU16();
715         unsigned int height = readU16();
717         m_pen.width = TO_DOUBLE(width) / m_xres;
718         m_pen.height = TO_DOUBLE(height) / m_yres;
720         WPG_DEBUG_MSG(("   Width: %d\n", width));
721         WPG_DEBUG_MSG(("   Height: %d\n", height));
724 void WPG2Parser::handleDPPenSize()
726         unsigned long width = readU32();
727         unsigned long height = readU32();
729         m_pen.width = TO_DOUBLE(width) / m_xres / 256;
730         m_pen.height = TO_DOUBLE(height) / m_yres / 256;
732         WPG_DEBUG_MSG(("   Width: %d\n", width));
733         WPG_DEBUG_MSG(("   Height: %d\n", height));
736 void WPG2Parser::handleBrushGradient()
738         unsigned angleFraction = readU16();
739         unsigned angleInteger = readU16();
740         unsigned xref = readU16();
741         unsigned yref = readU16();
742         unsigned flag = readU16();
743         bool granular = (flag & (1<<6)) == 1;
744         bool anchor = (flag & (1<<7)) == 1;
745 #if !defined(DEBUG)
746         (void)granular;
747         (void)anchor;
748 #endif // !defined(DEBUG)
749         
750         // TODO: get gradient extent
751         
752         m_gradientAngle = angleInteger + (double)angleFraction/65536.0;
753         m_gradientRef.x = xref;
754         m_gradientRef.y = yref;
755         
756         WPG_DEBUG_MSG(("       Gradient angle : %d.%d\n", angleInteger, angleFraction));
757         WPG_DEBUG_MSG(("   Gradient reference : %d.%d\n", xref, yref));
758         WPG_DEBUG_MSG(("   Granular : %s\n", (granular ? "yes" : "no")));
759         WPG_DEBUG_MSG(("   Anchored : %s\n", (anchor ? "yes" : "no")));
762 void WPG2Parser::handleDPBrushGradient()
764         unsigned angleFraction = readU16();
765         unsigned angleInteger = readU16();
766         unsigned xref = readU16();
767         unsigned yref = readU16();
768         unsigned flag = readU16();
769         bool granular = (flag & (1<<6)) == 1;
770         bool anchor = (flag & (1<<7)) == 1;
771 #if !defined(DEBUG)
772         (void)granular;
773         (void)anchor;
774 #endif // !defined(DEBUG)
775         
776         // TODO: get gradient extent (in double precision)
777         
778         m_gradientAngle = angleFraction + (double)angleInteger/65536.0;
779         m_gradientRef.x = xref;
780         m_gradientRef.y = yref;
782         WPG_DEBUG_MSG(("       Gradient angle : %d.%d\n", angleInteger, angleFraction));
783         WPG_DEBUG_MSG(("   Gradient reference : %d.%d\n", xref, yref));
784         WPG_DEBUG_MSG(("   Granular : %s\n", (granular ? "yes" : "no")));
785         WPG_DEBUG_MSG(("   Anchored : %s\n", (anchor ? "yes" : "no")));
788 void WPG2Parser::handleBrushForeColor()
790         unsigned char gradientType = readU8();
791         WPG_DEBUG_MSG(("   Gradient type : %d (%s)\n", gradientType, describeGradient(gradientType)));
793         if(gradientType == 0)
794         {
795                 unsigned char red = readU8();
796                 unsigned char green = readU8();
797                 unsigned char blue = readU8();
798                 unsigned char alpha = readU8();
799                 WPG_DEBUG_MSG(("   Foreground color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
801                 m_brush.foreColor = WPGColor(red, green, blue, alpha);
802                 if(m_brush.style != WPGBrush::Gradient)
803                         m_brush.style = WPGBrush::Solid;
804         }
805         else
806         {
807                 unsigned count = readU16();
808                 std::vector<WPGColor> colors;
809                 std::vector<double> positions;
810                 WPG_DEBUG_MSG(("  Gradient colors : %d\n", count));
812                 for(unsigned i = 0; i < count; i++)
813                 {
814                         unsigned char red = readU8();
815                         unsigned char green = readU8();
816                         unsigned char blue = readU8();
817                         unsigned char alpha = readU8();
818                         WPGColor color(red, green, blue, alpha);
819                         colors.push_back(color);
820                         WPG_DEBUG_MSG(("   Color #%d (RGBA): %d %d %d %d\n", i+1, red, green, blue, alpha));
821                 }
823                 for(unsigned j = 0; j < count-1; j++)
824                 {
825                         unsigned pos = readU16();
826                         positions.push_back(TO_DOUBLE(pos));
827                         WPG_DEBUG_MSG(("   Position #%d : %d\n", j+1, pos));
828                 }
829                 
830                 // looks like Corel Presentations only create 2 colors gradient
831                 // and they are actually in reverse order
832                 if(count == 2)
833                 {
834                         double xref = (double)m_gradientRef.x/65536.0;
835                         double yref = (double)m_gradientRef.y/65536.0;
836                         double angle = m_gradientAngle*M_PI/180.0;
837                         double tanangle = tan(angle);
838                         double ref = (tanangle<1e2) ? (yref+xref*tanangle)/(1+tanangle) : xref;
839                         WPGGradient gradient;
840                         gradient.setAngle(-m_gradientAngle); // upside down
841                         gradient.addStop(0, colors[1]);
842                         gradient.addStop(ref, colors[0]);
843                         if((m_gradientRef.x != 65535) && (m_gradientRef.y != 65536))
844                                 gradient.addStop(1, colors[1]);
845                         m_brush.gradient = gradient;
846                         m_brush.style = WPGBrush::Gradient;
847                 }
848         }
851 void WPG2Parser::handleDPBrushForeColor()
853         unsigned char gradientType = readU8();
854         WPG_DEBUG_MSG(("   Gradient type : %d (%s)\n", gradientType, describeGradient(gradientType)));
856         if(gradientType == 0)
857         {
858                 unsigned char red = (m_doublePrecision)   ? readU16()>>8 : readU8();
859                 unsigned char green = (m_doublePrecision)   ? readU16()>>8 : readU8();
860                 unsigned char blue = (m_doublePrecision)   ? readU16()>>8 : readU8();
861                 unsigned char alpha = (m_doublePrecision)   ? readU16()>>8 : readU8();
862                 WPG_DEBUG_MSG(("   Foreground color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
864                 m_brush.foreColor = WPGColor(red, green, blue, alpha);
865                 if(m_brush.style != WPGBrush::NoBrush)
866                         m_brush.style = WPGBrush::Solid;
867         }
868         else
869         {
870                 unsigned count = readU16();
871                 std::vector<WPGColor> colors;
872                 std::vector<double> positions;
873                 WPG_DEBUG_MSG(("  Gradient colors : %d\n", count));
875                 for(unsigned i = 0; i < count; i++)
876                 {
877                         unsigned char red = (m_doublePrecision)   ? readU16()>>8 : readU8();
878                         unsigned char green = (m_doublePrecision)   ? readU16()>>8 : readU8();
879                         unsigned char blue = (m_doublePrecision)   ? readU16()>>8 : readU8();
880                         unsigned char alpha = (m_doublePrecision)   ? readU16()>>8 : readU8();
881                         WPGColor color(red, green, blue, alpha);
882                         colors.push_back(color);
883                         WPG_DEBUG_MSG(("   Color #%d (RGBA): %d %d %d %d\n", i+1, red, green, blue, alpha));
884                 }
886                 for(unsigned j = 0; j < count-1; j++)
887                 {
888                         unsigned pos = readU16();
889                         positions.push_back(TO_DOUBLE(pos));
890                         WPG_DEBUG_MSG(("   Position #%d : %d\n", j+1, pos));
891                 }
892                 
893                 // looks like Corel Presentations only create 2 colors gradient
894                 // and they are actually in reverse order
895                 if(count == 2)
896                 {
897                         double xref = (double)m_gradientRef.x/65536.0;
898                         double yref = (double)m_gradientRef.y/65536.0;
899                         double angle = m_gradientAngle*M_PI/180.0;
900                         double tanangle = tan(angle);
901                         double ref = (tanangle<1e2) ? (yref+xref*tanangle)/(1+tanangle) : xref;
902                         WPGGradient gradient;
903                         gradient.setAngle(-m_gradientAngle); // upside down
904                         gradient.addStop(0, colors[1]);
905                         gradient.addStop(ref, colors[0]);
906                         if((m_gradientRef.x != 65535) && (m_gradientRef.y != 65536))
907                                 gradient.addStop(1, colors[1]);
908                         m_brush.gradient = gradient;
909                         m_brush.style = WPGBrush::Gradient;
910                 }
911         }
914 void WPG2Parser::handleBrushBackColor()
916         unsigned char red = readU8();
917         unsigned char green = readU8();
918         unsigned char blue = readU8();
919         unsigned char alpha = readU8();
921         m_brush.backColor = WPGColor(red, green, blue, alpha);
922         if(m_brush.style == WPGBrush::NoBrush)
923                 m_brush.style = WPGBrush::Solid;
925         WPG_DEBUG_MSG(("   Backround color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
928 void WPG2Parser::handleDPBrushBackColor()
930         // we just ignore the least significant 8 bits
931         unsigned int red = (m_doublePrecision)   ? readU16()>>8 : readU8();
932         unsigned int green = (m_doublePrecision) ? readU16()>>8 : readU8();
933         unsigned int blue = (m_doublePrecision)  ? readU16()>>8 : readU8();
934         unsigned int alpha = (m_doublePrecision) ? readU16()>>8 : readU8();
936         m_brush.backColor = WPGColor(red, green, blue, alpha);
937         if(m_brush.style == WPGBrush::NoBrush)
938                 m_brush.style = WPGBrush::Solid;
940         WPG_DEBUG_MSG(("   Background color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
943 void WPG2Parser::handleBrushPattern()
945         unsigned int pattern = readU16();
946 #if !defined(DEBUG)
947         (void)pattern;
948 #endif // !defined(DEBUG)
950         // TODO
952         WPG_DEBUG_MSG(("   Pattern : %d\n", pattern));
955 void WPG2Parser::parseCharacterization(ObjectCharacterization* ch)
957         // sanity check
958         if(!ch) return;
960         // identity
961         ch->matrix = WPG2TransformMatrix();
963         unsigned int flags = readU16();
964         ch->taper = (flags & 0x01) != 0;
965         ch->translate = (flags & 0x02) != 0;
966         ch->skew = (flags & 0x04) != 0;
967         ch->scale = (flags & 0x08) != 0;
968         ch->rotate = (flags & 0x10) != 0;
969         ch->hasObjectId = (flags & 0x20) != 0;
970         ch->editLock = (flags & 0x80) != 0;
971         ch->windingRule = (flags & (1<<12)) != 0;
972         ch->filled = (flags & (1<<13)) != 0;
973         ch->closed = (flags & (1<<14)) != 0;
974         ch->framed = (flags & (1<<15)) != 0;
975         
976         if(ch->editLock) ch->lockFlags = readU32();
978         // object ID can be 2 or 4 bytes
979         if(ch->hasObjectId) ch->objectId = readU16();
980         if(ch->objectId >> 15) ch->objectId = ((ch->objectId  & 0x7fff) << 16) | readU16();
982         if(ch->rotate) ch->rotationAngle = readS32();
984         if(ch->rotate || ch->scale)
985         {
986                 ch->sxcos = readS32();
987                 ch->sycos = readS32();
988                 ch->matrix.element[0][0] = (double)(ch->sxcos)/65536;
989                 ch->matrix.element[1][1] = (double)(ch->sxcos)/65536;
990         }
992         if(ch->rotate || ch->skew)
993         {
994                 ch->kxsin = readS32();
995                 ch->kysin = readS32();
996                 ch->matrix.element[1][0] = (double)(ch->kxsin)/65536;
997                 ch->matrix.element[0][1] = (double)(ch->kysin)/65536;
998         }
1000         if(ch->translate)
1001         {
1002                 ch->txfraction = readU16();
1003                 ch->txinteger = readS32();
1004                 ch->tyfraction = readU16();
1005                 ch->tyinteger = readS32();
1006                 ch->matrix.element[2][0] = (double)(ch->txinteger);
1007                 ch->matrix.element[2][1] = (double)(ch->tyinteger);
1008         }
1010         if(ch->taper)
1011         {
1012                 ch->px = readS32();
1013                 ch->py = readS32();
1014                 ch->matrix.element[0][2] = (double)(ch->px);
1015                 ch->matrix.element[1][2] = (double)(ch->py);
1016         }
1018         WPG_DEBUG_MSG(("ObjectCharacterization\n"));
1019         WPG_DEBUG_MSG(("       taper : %s\n", (ch->taper ? "yes" : "no")));
1020         WPG_DEBUG_MSG(("   translate : %s\n", (ch->translate ? "yes" : "no")));
1021         WPG_DEBUG_MSG(("        skew : %s\n", (ch->skew ? "yes" : "no")));
1022         WPG_DEBUG_MSG(("       scale : %s\n", (ch->scale ? "yes" : "no")));
1023         WPG_DEBUG_MSG(("      rotate : %s\n", (ch->rotate ? "yes" : "no")));
1024         WPG_DEBUG_MSG((" hasObjectId : %s\n", (ch->hasObjectId ? "yes" : "no")));
1025         WPG_DEBUG_MSG(("    editLock : %s\n", (ch->editLock ? "yes" : "no")));
1026         if(ch->editLock) WPG_DEBUG_MSG(("  lock flags : 0x%x\n", ch->lockFlags));
1027         if(ch->hasObjectId) WPG_DEBUG_MSG(("   object ID : 0x%x\n", ch->objectId));
1028         if(ch->translate) WPG_DEBUG_MSG(("    tx : %d %d\n", ch->txinteger, ch->txfraction));
1029         if(ch->translate) WPG_DEBUG_MSG(("    ty : %d %d\n", ch->tyinteger, ch->tyfraction));
1030         WPG_DEBUG_MSG(("transform matrix:\n"));
1031         WPG_DEBUG_MSG(("%f %f %f\n", ch->matrix.element[0][0], ch->matrix.element[0][1],ch->matrix.element[0][2]));
1032         WPG_DEBUG_MSG(("%f %f %f\n", ch->matrix.element[1][0], ch->matrix.element[1][1],ch->matrix.element[1][2]));
1033         WPG_DEBUG_MSG(("%f %f %f\n", ch->matrix.element[2][0], ch->matrix.element[2][1],ch->matrix.element[2][2]));
1036 void WPG2Parser::handlePolyline()
1038         ObjectCharacterization objCh;
1039         parseCharacterization(&objCh);
1040         m_matrix = objCh.matrix;
1042         bool insideCompound = m_groupStack.empty() ? false : 
1043                 m_groupStack.top().isCompoundPolygon();
1045         // inside a compound, so take the parent transformation into account
1046         if(insideCompound)
1047                 m_matrix.transformBy(m_groupStack.top().compoundMatrix); 
1049         unsigned long count = readU16();
1051         WPGPointArray points;
1052         for(unsigned long i = 0; i < count; i++ )
1053         {
1054                 long x = (m_doublePrecision) ? readS32() : readS16();
1055                 long y = (m_doublePrecision) ? readS32() : readS16();
1056                 TRANSFORM_XY(x,y);
1057                 WPGPoint p(TO_DOUBLE(x)/m_xres, TO_DOUBLE(y)/m_yres);
1058                 points.add(p);
1059         }
1061         if(insideCompound)
1062         {
1063                 if(count > 0)
1064                 {
1065                         // inside a compound ? convert it into path because for compound 
1066                         // we will only use paths
1067                         WPGPath& path = m_groupStack.top().compoundPath;
1068                         path.moveTo(points[0]);
1069                         for(unsigned long ii = 1; ii < count; ii++)
1070                                 path.lineTo(points[ii]);
1071                 }
1072         }
1073         else
1074         {
1075                 // otherwise draw directly
1076                 m_painter->setBrush( objCh.filled ? m_brush : WPGBrush() );
1077                 m_painter->setPen( objCh.framed ? m_pen : WPGPen() );
1078                 if(objCh.windingRule)
1079                         m_painter->setFillRule(WPGPaintInterface::WindingFill);
1080                 else
1081                         m_painter->setFillRule(WPGPaintInterface::AlternatingFill);
1082                 m_painter->drawPolygon(points);
1083         }
1085         WPG_DEBUG_MSG(("   Vertices count : %d\n", count));
1086         for(unsigned int j = 0; j < count; j++ )
1087                 WPG_DEBUG_MSG(("        Point #%d : %g,%g\n", j+1, points[j].x, points[j].y));
1090 void WPG2Parser::handlePolycurve()
1092         ObjectCharacterization objCh;
1093         parseCharacterization(&objCh);
1094         m_matrix = objCh.matrix;
1096         bool insideCompound = m_groupStack.empty() ? false : 
1097                 m_groupStack.top().isCompoundPolygon();
1099         // inside a compound, so take the parent transformation into account
1100         if(insideCompound)
1101                 m_matrix.transformBy(m_groupStack.top().compoundMatrix); 
1103         unsigned int count = readU16();
1105         WPGPointArray vertices;
1106         WPGPointArray controlPoints;
1107         for(int i = 0; i < static_cast<int>(count); i++ )
1108         {
1109                 long ix = (m_doublePrecision) ? readS32() : readS16();
1110                 long iy = (m_doublePrecision) ? readS32() : readS16();
1111                 TRANSFORM_XY(ix,iy);
1112                 WPGPoint initialPoint( TO_DOUBLE(ix)/m_xres, TO_DOUBLE(iy)/m_yres );
1114                 long ax = (m_doublePrecision) ? readS32() : readS16();
1115                 long ay = (m_doublePrecision) ? readS32() : readS16();
1116                 TRANSFORM_XY(ax,ay);
1117                 WPGPoint anchorPoint( TO_DOUBLE(ax)/m_xres, TO_DOUBLE(ay)/m_yres );
1119                 long tx = (m_doublePrecision) ? readS32() : readS16();
1120                 long ty = (m_doublePrecision) ? readS32() : readS16();
1121                 TRANSFORM_XY(tx,ty);
1122                 WPGPoint terminalPoint( TO_DOUBLE(tx)/m_xres, TO_DOUBLE(ty)/m_yres );
1124                 vertices.add(anchorPoint);
1125                 if(i > 0)
1126                         controlPoints.add(initialPoint);
1127                 controlPoints.add(terminalPoint);
1128         }
1130         WPGPath path;
1131         path.closed = objCh.closed;
1132         path.moveTo(vertices[0]);
1133         for(unsigned j = 1; j < vertices.count(); j++)
1134                 path.curveTo(controlPoints[j*2-2], controlPoints[j*2-1], vertices[j]);
1136         if(insideCompound)
1137                 // inside a compound ? just collect the path together
1138                 m_groupStack.top().compoundPath.append(path);
1139         else
1140         {
1141                 // otherwise draw directly
1142                 m_painter->setBrush( objCh.filled ? m_brush : WPGBrush() );
1143                 m_painter->setPen( objCh.framed ? m_pen : WPGPen() );
1144                 if(objCh.windingRule)
1145                         m_painter->setFillRule(WPGPaintInterface::WindingFill);
1146                 else
1147                         m_painter->setFillRule(WPGPaintInterface::AlternatingFill);
1148                 m_painter->drawPath(path);
1149         }
1152 void WPG2Parser::handleRectangle()
1154         ObjectCharacterization objCh;
1155         parseCharacterization(&objCh);
1156         m_matrix = objCh.matrix;
1157         
1158         long x1 = (m_doublePrecision) ? readS32() : readS16();
1159         long y1 = (m_doublePrecision) ? readS32() : readS16();
1160         TRANSFORM_XY(x1,y1);
1162         long x2 = (m_doublePrecision) ? readS32() : readS16();
1163         long y2 = (m_doublePrecision) ? readS32() : readS16();
1164         TRANSFORM_XY(x2,y2);
1165         
1166         long xs1 = (x1 <= x2) ? x1 : x2;
1167         long xs2 = (x1 <= x2) ? x2 : x1;
1168         long ys1 = (y1 <= y2) ? y1 : y2;
1169         long ys2 = (y1 <= y2) ? y2 : y1;
1171         long rx = (m_doublePrecision) ? readS32() : readS16();
1172         long ry = (m_doublePrecision) ? readS32() : readS16();
1174         WPGRect rect;
1175         rect.x1 = TO_DOUBLE(xs1) / m_xres;
1176         rect.x2 = TO_DOUBLE(xs2) / m_xres;
1177         rect.y1 = TO_DOUBLE(ys1) / m_yres;
1178         rect.y2 = TO_DOUBLE(ys2) / m_yres;
1179         double roundx = TO_DOUBLE(rx)/m_xres;
1180         double roundy = TO_DOUBLE(ry)/m_yres;
1182         m_painter->setBrush( objCh.filled ? m_brush : WPGBrush() );
1183         m_painter->setPen( objCh.framed ? m_pen : WPGPen() );
1184         m_painter->drawRectangle(rect, roundx, roundy);
1185         
1186         WPG_DEBUG_MSG(("      X1 : %d\n", x1));
1187         WPG_DEBUG_MSG(("      Y1 : %d\n", y1));
1188         WPG_DEBUG_MSG(("      X2 : %d\n", x2));
1189         WPG_DEBUG_MSG(("      Y2 : %d\n", y2));
1190         WPG_DEBUG_MSG((" Round X : %d\n", rx));
1191         WPG_DEBUG_MSG((" Round Y : %d\n", ry));
1194 void WPG2Parser::handleArc()
1196         ObjectCharacterization objCh;
1197         parseCharacterization(&objCh);
1198         m_matrix = objCh.matrix;
1199         
1200         long cx = (m_doublePrecision) ? readS32() : readS16();
1201         long cy = (m_doublePrecision) ? readS32() : readS16();
1203         long radx = (m_doublePrecision) ? readS32() : readS16();
1204         long rady = (m_doublePrecision) ? readS32() : readS16();
1206         long ix = (m_doublePrecision) ? readS32() : readS16();
1207         long iy = (m_doublePrecision) ? readS32() : readS16();
1208         TRANSFORM_XY(ix,iy);
1210         long ex = (m_doublePrecision) ? readS32() : readS16();
1211         long ey = (m_doublePrecision) ? readS32() : readS16();
1212         TRANSFORM_XY(ex,ey);
1214         if((ix==ex) && (iy==ey))
1215         {
1216                 WPGPoint center;
1217                 center.x = TO_DOUBLE(cx) / m_xres;
1218                 center.y = TO_DOUBLE(cy) / m_xres;
1219                 double rx = TO_DOUBLE(radx) / m_xres;
1220                 double ry = TO_DOUBLE(rady) / m_xres;
1221                 
1222                 m_painter->setBrush( objCh.filled ? m_brush : WPGBrush() );
1223                 m_painter->setPen( objCh.framed ? m_pen : WPGPen() );
1224                 m_painter->drawEllipse(center, rx, ry);
1225         }
1227         WPG_DEBUG_MSG(("   Center point x : %d\n", cx));
1228         WPG_DEBUG_MSG(("   Center point y : %d\n", cy));
1229         WPG_DEBUG_MSG(("         Radius x : %d\n", radx));
1230         WPG_DEBUG_MSG(("         Radius y : %d\n", rady));
1231         WPG_DEBUG_MSG(("  Initial point x : %d\n", ix));
1232         WPG_DEBUG_MSG(("  Initial point y : %d\n", iy));
1233         WPG_DEBUG_MSG(("      End point x : %d\n", ex));
1234         WPG_DEBUG_MSG(("      End point y : %d\n", ey));
1238 void WPG2Parser::resetPalette()
1240         m_colorPalette.clear();
1241         for (int i=0; i<256; i++)
1242         {
1243                 WPGColor color;
1244                 color.red = defaultWPG2PaletteRed[i];
1245                 color.green = defaultWPG2PaletteGreen[i];
1246                 color.blue = defaultWPG2PaletteBlue[i];
1247                 m_colorPalette[i] = color;
1248         }