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
146 {
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)
212 {
213 }
215 bool WPG2Parser::parse()
216 {
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;
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)
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;
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;
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));
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 }
394 if(m_exit) break;
396 m_input->seek(nextPos);
397 }
399 return m_success;
400 }
402 #if defined(DEBUG)
403 static const char* describePrecision(unsigned char precision)
404 {
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;
413 }
415 static const char* describeGradient(unsigned char gradientType)
416 {
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;
434 }
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()
441 {
442 unsigned int horizontalUnit = readU16();
443 unsigned int verticalUnit = readU16();
444 unsigned char precision = readU8();
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 }
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);
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)
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;
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));
504 double width = (TO_DOUBLE(m_width)) / m_xres;
505 double height = (TO_DOUBLE(m_height)) / m_yres;
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 };
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 }
541 }
543 void WPG2Parser::handleEndWPG()
544 {
545 // sentinel
546 if(m_layerOpened)
547 m_painter->endLayer(m_layerId);
549 m_painter->endDocument();
550 m_exit = true;
551 }
553 void WPG2Parser::handleLayer()
554 {
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));
565 }
567 void WPG2Parser::handleCompoundPolygon()
568 {
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;
577 }
578 void WPG2Parser::flushCompoundPolygon()
579 {
580 WPGGroupContext& context = m_groupStack.top();
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);
590 }
592 void WPG2Parser::handlePenStyleDefinition()
593 {
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));
609 }
611 // TODO
612 void WPG2Parser::handlePatternDefinition()
613 {
614 WPG_DEBUG_MSG(("PatternDefinition\n"));
615 }
617 void WPG2Parser::handleColorPalette()
618 {
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 }
632 }
634 void WPG2Parser::handleDPColorPalette()
635 {
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 }
649 }
651 void WPG2Parser::handlePenForeColor()
652 {
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));
661 }
663 void WPG2Parser::handleDPPenForeColor()
664 {
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));
674 }
676 void WPG2Parser::handlePenBackColor()
677 {
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));
686 }
688 void WPG2Parser::handleDPPenBackColor()
689 {
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));
699 }
701 void WPG2Parser::handlePenStyle()
702 {
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()));
710 }
712 void WPG2Parser::handlePenSize()
713 {
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));
722 }
724 void WPG2Parser::handleDPPenSize()
725 {
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));
734 }
736 void WPG2Parser::handleBrushGradient()
737 {
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)
750 // TODO: get gradient extent
752 m_gradientAngle = angleInteger + (double)angleFraction/65536.0;
753 m_gradientRef.x = xref;
754 m_gradientRef.y = yref;
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")));
760 }
762 void WPG2Parser::handleDPBrushGradient()
763 {
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)
776 // TODO: get gradient extent (in double precision)
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")));
786 }
788 void WPG2Parser::handleBrushForeColor()
789 {
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 }
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 }
849 }
851 void WPG2Parser::handleDPBrushForeColor()
852 {
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 }
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 }
912 }
914 void WPG2Parser::handleBrushBackColor()
915 {
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));
926 }
928 void WPG2Parser::handleDPBrushBackColor()
929 {
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));
941 }
943 void WPG2Parser::handleBrushPattern()
944 {
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));
953 }
955 void WPG2Parser::parseCharacterization(ObjectCharacterization* ch)
956 {
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;
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]));
1034 }
1036 void WPG2Parser::handlePolyline()
1037 {
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));
1088 }
1090 void WPG2Parser::handlePolycurve()
1091 {
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 }
1150 }
1152 void WPG2Parser::handleRectangle()
1153 {
1154 ObjectCharacterization objCh;
1155 parseCharacterization(&objCh);
1156 m_matrix = objCh.matrix;
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);
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);
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));
1192 }
1194 void WPG2Parser::handleArc()
1195 {
1196 ObjectCharacterization objCh;
1197 parseCharacterization(&objCh);
1198 m_matrix = objCh.matrix;
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;
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));
1235 }
1238 void WPG2Parser::resetPalette()
1239 {
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 }
1249 }