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 "WPG1Parser.h"
29 #include "WPGPaintInterface.h"
30 #include "libwpg_utils.h"
32 static const unsigned char defaultWPG1PaletteRed[] = {
33 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x7F,
34 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
35 0x00, 0x14, 0x20, 0x2C, 0x38, 0x45, 0x51, 0x61,
36 0x71, 0x82, 0x92, 0xA2, 0xB6, 0xCB, 0xE3, 0xFF,
37 0x00, 0x41, 0x7D, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF,
38 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0x7D, 0x41,
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 0x7D, 0x9E, 0xBE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
41 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xBE, 0x9E,
42 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
43 0xB6, 0xC7, 0xDB, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF,
44 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xDB, 0xC7,
45 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
46 0x00, 0x1C, 0x38, 0x55, 0x71, 0x71, 0x71, 0x71,
47 0x71, 0x71, 0x71, 0x71, 0x71, 0x55, 0x38, 0x1C,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x38, 0x45, 0x55, 0x61, 0x71, 0x71, 0x71, 0x71,
50 0x71, 0x71, 0x71, 0x71, 0x71, 0x61, 0x55, 0x45,
51 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
52 0x51, 0x59, 0x61, 0x69, 0x71, 0x71, 0x71, 0x71,
53 0x71, 0x71, 0x71, 0x71, 0x71, 0x69, 0x61, 0x59,
54 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
55 0x00, 0x10, 0x20, 0x30, 0x41, 0x41, 0x41, 0x41,
56 0x41, 0x41, 0x41, 0x41, 0x41, 0x30, 0x20, 0x10,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x20, 0x28, 0x30, 0x38, 0x41, 0x41, 0x41, 0x41,
59 0x41, 0x41, 0x41, 0x41, 0x41, 0x38, 0x30, 0x28,
60 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
61 0x3C, 0x30, 0x34, 0x3C, 0x41, 0x41, 0x41, 0x41,
62 0x41, 0x41, 0x41, 0x41, 0x41, 0x3C, 0x34, 0x30,
63 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 };
67 static const unsigned char defaultWPG1PaletteGreen[] = {
68 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x3F, 0x7F,
69 0xC0, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
70 0x00, 0x14, 0x20, 0x2C, 0x38, 0x45, 0x51, 0x61,
71 0x71, 0x82, 0x92, 0xA2, 0xB6, 0xCB, 0xE3, 0xFF,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x41, 0x7D, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF,
74 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0x7D, 0x41,
75 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
76 0x7D, 0x9E, 0xBE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
77 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xBE, 0x9E,
78 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
79 0xB6, 0xC7, 0xDB, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF,
80 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xDB, 0xC7,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x1C, 0x38, 0x55, 0x71, 0x71, 0x71, 0x71,
83 0x71, 0x71, 0x71, 0x71, 0x71, 0x55, 0x38, 0x1C,
84 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
85 0x38, 0x45, 0x55, 0x61, 0x71, 0x71, 0x71, 0x71,
86 0x71, 0x71, 0x71, 0x71, 0x71, 0x61, 0x55, 0x45,
87 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
88 0x51, 0x59, 0x61, 0x69, 0x71, 0x71, 0x71, 0x71,
89 0x71, 0x71, 0x71, 0x71, 0x71, 0x69, 0x61, 0x59,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x10, 0x20, 0x30, 0x41, 0x41, 0x41, 0x41,
92 0x41, 0x41, 0x41, 0x41, 0x41, 0x30, 0x20, 0x10,
93 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
94 0x20, 0x28, 0x30, 0x38, 0x41, 0x41, 0x41, 0x41,
95 0x41, 0x41, 0x41, 0x41, 0x41, 0x38, 0x30, 0x28,
96 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C,
97 0x3C, 0x30, 0x34, 0x3C, 0x41, 0x41, 0x41, 0x41,
98 0x41, 0x41, 0x41, 0x41, 0x41, 0x3C, 0x34, 0x30,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 };
102 static const unsigned char defaultWPG1PaletteBlue[] = {
103 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F,
104 0xC0, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
105 0x00, 0x14, 0x20, 0x2C, 0x38, 0x45, 0x51, 0x61,
106 0x71, 0x82, 0x92, 0xA2, 0xB6, 0xCB, 0xE3, 0xFF,
107 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0x7D, 0x41,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x41, 0x7D, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF,
110 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xBE, 0x9E,
111 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
112 0x7D, 0x9E, 0xBE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
113 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xDB, 0xC7,
114 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
115 0xB6, 0xC7, 0xDB, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF,
116 0x71, 0x71, 0x71, 0x71, 0x71, 0x55, 0x38, 0x1C,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x1C, 0x38, 0x55, 0x71, 0x71, 0x71, 0x71,
119 0x71, 0x71, 0x71, 0x71, 0x71, 0x61, 0x55, 0x45,
120 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
121 0x38, 0x45, 0x55, 0x61, 0x71, 0x71, 0x71, 0x71,
122 0x71, 0x71, 0x71, 0x71, 0x71, 0x69, 0x61, 0x59,
123 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
124 0x51, 0x59, 0x61, 0x69, 0x71, 0x71, 0x71, 0x71,
125 0x41, 0x41, 0x41, 0x41, 0x41, 0x30, 0x20, 0x10,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x10, 0x20, 0x30, 0x41, 0x41, 0x41, 0x41,
128 0x41, 0x41, 0x41, 0x41, 0x41, 0x38, 0x30, 0x28,
129 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
130 0x20, 0x28, 0x30, 0x38, 0x41, 0x41, 0x41, 0x41,
131 0x41, 0x41, 0x41, 0x41, 0x41, 0x3C, 0x34, 0x30,
132 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C,
133 0x2C, 0x30, 0x34, 0x3C, 0x41, 0x41, 0x41, 0x41,
134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 };
138 WPG1Parser::WPG1Parser(WPGInputStream *input, WPGPaintInterface* painter):
139 WPGXParser(input, painter),
140 m_success(true), m_exit(false),
141 m_width(0), m_height(0)
142 {
143 }
145 bool WPG1Parser::parse()
146 {
147 typedef void (WPG1Parser::*Method)();
149 struct RecordHandler
150 {
151 int type;
152 const char *name;
153 Method handler;
154 };
156 static const struct RecordHandler handlers[] =
157 {
158 { 0x01, "Fill Attributes", &WPG1Parser::handleFillAttributes },
159 { 0x02, "Line Attributes", &WPG1Parser::handleLineAttributes },
160 { 0x03, "Marker Atttibutes", 0 },
161 { 0x04, "Polymarker", 0 },
162 { 0x05, "Line", &WPG1Parser::handleLine },
163 { 0x06, "Polyline", &WPG1Parser::handlePolyline },
164 { 0x07, "Rectangle", &WPG1Parser::handleRectangle },
165 { 0x08, "Polygon", &WPG1Parser::handlePolygon },
166 { 0x09, "Ellipse", &WPG1Parser::handleEllipse },
167 { 0x0e, "Colormap", &WPG1Parser::handleColormap },
168 { 0x0f, "Start WPG", &WPG1Parser::handleStartWPG },
169 { 0x10, "End WPG", &WPG1Parser::handleEndWPG },
170 { 0x00, 0, 0 } // end marker
171 };
173 // initialization
174 m_success = true;
175 m_exit = false;
177 // default style
178 m_pen.foreColor = WPGColor(0,0,0);
179 m_pen.backColor = WPGColor(0,0,0);
180 m_pen.width = 0.001;
181 m_pen.height = 0.001;
182 m_pen.solid = true;
183 m_pen.dashArray = WPGDashArray();
184 m_brush.foreColor = WPGColor(0,0,0);
185 m_brush.backColor = WPGColor(0,0,0);
186 resetPalette();
188 while(!m_input->atEnd())
189 {
190 long recordPos = m_input->tell();
191 int recordType = readU8();
192 int length = readVariableLengthInteger();
193 long nextPos = m_input->tell() + length;
194 #if !defined(DEBUG)
195 (void)recordPos;
196 #endif // !defined(DEBUG)
198 // search function to handler this record
199 int index = -1;
200 for(int i = 0; (index < 0) && handlers[i].name; i++)
201 if(handlers[i].type == recordType)
202 index = i;
204 WPG_DEBUG_MSG(("\n"));
205 if(index < 0)
206 WPG_DEBUG_MSG(("Unknown record type 0x%02x at %d size %d\n",
207 recordType, recordPos, length));
208 else
209 {
210 Method recordHandler = handlers[index].handler;
211 if(!recordHandler)
212 WPG_DEBUG_MSG(("Record '%s' (ignored) type 0x%02x at %d size %d\n",
213 handlers[index].name, recordType, recordPos, length));
214 else
215 {
216 WPG_DEBUG_MSG(("Record '%s' type 0x%02x at %d size %d\n",
217 handlers[index].name, recordType, recordPos, length));
219 // invoke the handler for this record
220 (this->*recordHandler)();
221 }
222 }
224 //if(m_input->tell() > nextPos)
225 {
226 //WPG_DEBUG_MSG(("Record 0x%x consumes more bytes than necessary!\n", recordType));
227 WPG_DEBUG_MSG(("Current stream position: %d\n", m_input->tell()));
228 }
230 if(m_exit) break;
232 m_input->seek(nextPos);
233 }
235 return m_success;
236 }
238 void WPG1Parser::handleStartWPG()
239 {
240 unsigned char version = readU8();
241 unsigned char bitFlags = readU8();
242 (void)version;
243 (void)bitFlags;
244 m_width = readU16();
245 m_height = readU16();
247 double width = (double)m_width / 1200.0;
248 double height = (double)m_height / 1200.0;
249 m_painter->startDocument(width, height);
251 WPG_DEBUG_MSG(("StartWPG\n"));
252 }
254 void WPG1Parser::handleEndWPG()
255 {
256 m_painter->endDocument();
257 m_exit = true;
259 WPG_DEBUG_MSG(("EndWPG\n"));
260 }
262 void WPG1Parser::handleColormap()
263 {
264 unsigned startIndex = readU16();
265 unsigned numEntries = readU16();
267 WPG_DEBUG_MSG(("Colormap\n"));
268 for(int i = 0; i < static_cast<int>(numEntries); i++)
269 {
270 WPGColor color;
271 color.red = readU8();
272 color.green = readU8();
273 color.blue = readU8();
274 m_colorPalette[startIndex+i] = color;
275 WPG_DEBUG_MSG(("Index#%d: RGB %d %d %d\n", startIndex+i, color.red, color.green, color.blue));
276 }
277 }
279 void WPG1Parser::handleFillAttributes()
280 {
281 unsigned char style = readU8();
282 unsigned char color = readU8();
284 if(style == 0)
285 m_brush.style = WPGBrush::NoBrush;
286 if(style == 1)
287 m_brush.style = WPGBrush::Solid;
289 m_brush.foreColor = m_colorPalette[color];
291 WPG_DEBUG_MSG(("Fill Attributes\n"));
292 WPG_DEBUG_MSG((" Fill style: %d\n", style));
293 WPG_DEBUG_MSG((" Fill color index: %d\n", color));
294 }
296 void WPG1Parser::handleLineAttributes()
297 {
298 unsigned char style = readU8();
299 unsigned char color = readU8();
300 unsigned int width = readU16();
302 m_pen.solid = style != 0;
303 m_pen.foreColor = m_colorPalette[color];
304 m_pen.width = (double)width / 1200.0;
306 WPG_DEBUG_MSG(("Line Attributes\n"));
307 WPG_DEBUG_MSG((" Line style: %d\n", style));
308 WPG_DEBUG_MSG((" Line color index: %d\n", color));
309 WPG_DEBUG_MSG((" Line width: %d\n", width));
310 }
312 void WPG1Parser::handleLine()
313 {
314 int sx = readS16();
315 int sy = readS16();
316 int ex = readS16();
317 int ey = readS16();
319 WPGPointArray points;
320 points.add(WPGPoint((double)sx/1200.0, (double)(m_height-sy)/1200.0));
321 points.add(WPGPoint((double)ex/1200.0, (double)(m_height-ey)/1200.0));
323 m_painter->setBrush(m_brush);
324 m_painter->setPen(m_pen);
325 m_painter->drawPolygon(points);
327 WPG_DEBUG_MSG(("Line\n"));
328 WPG_DEBUG_MSG((" Starting point: %d,%d\n", sx, sy));
329 WPG_DEBUG_MSG((" End point: %d,%d\n", ex, ey));
330 }
332 void WPG1Parser::handlePolyline()
333 {
334 unsigned int count = readU16();
336 WPGPointArray points;
337 for(unsigned int i = 0; i < count; i++ )
338 {
339 long x = readS16();
340 long y = readS16();
341 points.add(WPGPoint((double)x/1200.0, (double)(m_height-y)/1200.0));
342 }
344 m_painter->setBrush(WPGBrush()); // not filled
345 m_painter->setPen(m_pen);
346 m_painter->drawPolygon(points);
348 WPG_DEBUG_MSG(("Polyline\n"));
349 }
351 void WPG1Parser::handleRectangle()
352 {
353 int x = readS16();
354 int y = readS16();
355 int w = readS16();
356 int h = readS16();
358 WPGRect rect;
359 rect.x1 = (double)x/1200.0;
360 rect.y1 = (double)(m_height-y)/1200.0;
361 rect.x2 = rect.x1 + (double)w/1200.0;
362 rect.y2 = rect.y1 + (double)h/1200.0;
364 m_painter->setBrush(m_brush);
365 m_painter->setPen(m_pen);
366 m_painter->drawRectangle(rect, 0, 0);
368 WPG_DEBUG_MSG(("Line\n"));
369 WPG_DEBUG_MSG((" Corner point: %d,%d\n", x, y));
370 WPG_DEBUG_MSG((" Width: %d\n", w));
371 WPG_DEBUG_MSG((" Height: %d\n", h));
372 }
374 void WPG1Parser::handlePolygon()
375 {
376 unsigned int count = readU16();
378 WPGPointArray points;
379 for(unsigned int i = 0; i < count; i++ )
380 {
381 long x = readS16();
382 long y = readS16();
383 points.add(WPGPoint((double)x/1200.0, (double)(m_height-y)/1200.0));
384 }
386 m_painter->setBrush(m_brush);
387 m_painter->setPen(m_pen);
388 m_painter->drawPolygon(points);
390 WPG_DEBUG_MSG(("Polygon\n"));
391 }
393 void WPG1Parser::handleEllipse()
394 {
395 int cx = readS16();
396 int cy = readS16();
397 int rx = readS16();
398 int ry = readS16();
400 WPGPoint center;
401 center.x = (double)cx/1200.0;
402 center.y = (double)(m_height-cy)/1200.0;
404 double radx = (double)rx/1200.0;
405 double rady = (double)ry/1200.0;
407 m_painter->setBrush(m_brush);
408 m_painter->setPen(m_pen);
409 m_painter->drawEllipse(center, radx, rady);
411 WPG_DEBUG_MSG(("Ellipse\n"));
412 WPG_DEBUG_MSG((" Center point: %d,%d\n", cx, cy));
413 WPG_DEBUG_MSG((" Radius x: %d\n", rx));
414 WPG_DEBUG_MSG((" Radius y: %d\n", ry));
415 }
417 void WPG1Parser::resetPalette()
418 {
419 m_colorPalette.clear();
420 for (int i=0; i<256; i++)
421 {
422 WPGColor color;
423 color.red = defaultWPG1PaletteRed[i];
424 color.green = defaultWPG1PaletteGreen[i];
425 color.blue = defaultWPG1PaletteBlue[i];
426 m_colorPalette[i] = color;
427 }
428 }