Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* libcdr
3 : * Version: MPL 1.1 / GPLv2+ / LGPLv2+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License or as specified alternatively below. You may obtain a copy of
8 : * the License at http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * Major Contributor(s):
16 : * Copyright (C) 2011 Fridrich Strba <fridrich.strba@bluewin.ch>
17 : *
18 : *
19 : * All Rights Reserved.
20 : *
21 : * For minor contributions see the git repository.
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
25 : * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
26 : * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
27 : * instead of those above.
28 : */
29 :
30 : #include <libwpd-stream/libwpd-stream.h>
31 : #include <locale.h>
32 : #include <math.h>
33 : #include <set>
34 : #include <string.h>
35 : #include <stdlib.h>
36 : #include "libcdr_utils.h"
37 : #include "CDRInternalStream.h"
38 : #include "CMXParser.h"
39 : #include "CDRCollector.h"
40 : #include "CDRDocumentStructure.h"
41 : #include "CMXDocumentStructure.h"
42 :
43 : #ifndef DUMP_PREVIEW_IMAGE
44 : #define DUMP_PREVIEW_IMAGE 0
45 : #endif
46 :
47 : #ifndef M_PI
48 : #define M_PI 3.14159265358979323846
49 : #endif
50 :
51 0 : libcdr::CMXParser::CMXParser(libcdr::CDRCollector *collector)
52 : : CommonParser(collector),
53 : m_bigEndian(false), m_unit(0),
54 : m_scale(0.0), m_xmin(0.0), m_xmax(0.0), m_ymin(0.0), m_ymax(0.0),
55 : m_indexSectionOffset(0), m_infoSectionOffset(0), m_thumbnailOffset(0),
56 0 : m_fillIndex(0), m_nextInstructionOffset(0) {}
57 :
58 0 : libcdr::CMXParser::~CMXParser()
59 : {
60 0 : }
61 :
62 0 : bool libcdr::CMXParser::parseRecords(WPXInputStream *input, long size, unsigned level)
63 : {
64 0 : if (!input)
65 : {
66 0 : return false;
67 : }
68 0 : m_collector->collectLevel(level);
69 0 : long endPosition = -1;
70 0 : if (size > 0)
71 0 : endPosition = input->tell() + size;
72 0 : while (!input->atEOS() && (endPosition < 0 || input->tell() < endPosition))
73 : {
74 0 : if (!parseRecord(input, level))
75 0 : return false;
76 : }
77 0 : return true;
78 : }
79 :
80 0 : bool libcdr::CMXParser::parseRecord(WPXInputStream *input, unsigned level)
81 : {
82 0 : if (!input)
83 : {
84 0 : return false;
85 : }
86 : try
87 : {
88 0 : m_collector->collectLevel(level);
89 0 : while (!input->atEOS() && readU8(input) == 0)
90 : {
91 : }
92 0 : if (!input->atEOS())
93 0 : input->seek(-1, WPX_SEEK_CUR);
94 : else
95 0 : return true;
96 0 : unsigned fourCC = readU32(input);
97 0 : unsigned length = readU32(input);
98 0 : long endPosition = input->tell() + length;
99 :
100 : CDR_DEBUG_MSG(("Record: level %u %s, length: 0x%.8x (%u)\n", level, toFourCC(fourCC), length, length));
101 :
102 0 : if (fourCC == FOURCC_RIFF || fourCC == FOURCC_RIFX || fourCC == FOURCC_LIST)
103 : {
104 : #ifdef DEBUG
105 : unsigned listType = readU32(input);
106 : #else
107 0 : input->seek(4, WPX_SEEK_CUR);
108 : #endif
109 : CDR_DEBUG_MSG(("CMX listType: %s\n", toFourCC(listType)));
110 0 : unsigned dataSize = length-4;
111 0 : if (!parseRecords(input, dataSize, level+1))
112 0 : return false;
113 : }
114 : else
115 0 : readRecord(fourCC, length, input);
116 :
117 0 : if (input->tell() < endPosition)
118 0 : input->seek(endPosition, WPX_SEEK_SET);
119 0 : return true;
120 : }
121 0 : catch (...)
122 : {
123 0 : return false;
124 : }
125 : }
126 :
127 0 : void libcdr::CMXParser::readRecord(unsigned fourCC, unsigned &length, WPXInputStream *input)
128 : {
129 0 : long recordEnd = input->tell() + length;
130 0 : switch (fourCC)
131 : {
132 : case FOURCC_cont:
133 0 : readCMXHeader(input);
134 0 : break;
135 : case FOURCC_DISP:
136 0 : readDisp(input, length);
137 0 : break;
138 : case FOURCC_page:
139 0 : readPage(input, length);
140 0 : break;
141 : case FOURCC_ccmm:
142 0 : readCcmm(input, recordEnd);
143 0 : break;
144 : default:
145 0 : break;
146 : }
147 0 : if (input->tell() < recordEnd)
148 0 : input->seek(recordEnd, WPX_SEEK_SET);
149 0 : }
150 :
151 0 : void libcdr::CMXParser::readCMXHeader(WPXInputStream *input)
152 : {
153 0 : WPXString tmpString;
154 0 : unsigned i = 0;
155 0 : for (i = 0; i < 32; i++)
156 0 : tmpString.append((char)readU8(input));
157 : CDR_DEBUG_MSG(("CMX File ID: %s\n", tmpString.cstr()));
158 0 : tmpString.clear();
159 0 : for (i = 0; i < 16; i++)
160 0 : tmpString.append((char)readU8(input));
161 : CDR_DEBUG_MSG(("CMX Platform: %s\n", tmpString.cstr()));
162 0 : tmpString.clear();
163 0 : for (i = 0; i < 4; i++)
164 0 : tmpString.append((char)readU8(input));
165 : CDR_DEBUG_MSG(("CMX Byte Order: %s\n", tmpString.cstr()));
166 0 : if (4 == atoi(tmpString.cstr()))
167 0 : m_bigEndian = true;
168 0 : tmpString.clear();
169 0 : for (i = 0; i < 2; i++)
170 0 : tmpString.append((char)readU8(input));
171 : CDR_DEBUG_MSG(("CMX Coordinate Size: %s\n", tmpString.cstr()));
172 0 : unsigned short coordSize = (unsigned short)atoi(tmpString.cstr());
173 0 : switch (coordSize)
174 : {
175 : case 2:
176 0 : m_precision = libcdr::PRECISION_16BIT;
177 0 : break;
178 : case 4:
179 0 : m_precision = libcdr::PRECISION_32BIT;
180 0 : break;
181 : default:
182 0 : m_precision = libcdr::PRECISION_UNKNOWN;
183 0 : break;
184 : }
185 0 : tmpString.clear();
186 0 : for (i = 0; i < 4; i++)
187 0 : tmpString.append((char)readU8(input));
188 : CDR_DEBUG_MSG(("CMX Version Major: %s\n", tmpString.cstr()));
189 0 : tmpString.clear();
190 0 : for (i = 0; i < 4; i++)
191 0 : tmpString.append((char)readU8(input));
192 : CDR_DEBUG_MSG(("CMX Version Minor: %s\n", tmpString.cstr()));
193 0 : m_unit = readU16(input, m_bigEndian);
194 : CDR_DEBUG_MSG(("CMX Base Units: %u\n", m_unit));
195 0 : m_scale = readDouble(input, m_bigEndian);
196 : CDR_DEBUG_MSG(("CMX Units Scale: %.9f\n", m_scale));
197 0 : input->seek(12, WPX_SEEK_CUR);
198 0 : m_indexSectionOffset = readU32(input, m_bigEndian);
199 0 : m_infoSectionOffset = readU32(input, m_bigEndian);
200 0 : m_thumbnailOffset = readU32(input, m_bigEndian);
201 : #ifdef DEBUG
202 : CDRBBox box = readBBox(input);
203 : #endif
204 : CDR_DEBUG_MSG(("CMX Offsets: index section 0x%.8x, info section: 0x%.8x, thumbnail: 0x%.8x\n",
205 : m_indexSectionOffset, m_infoSectionOffset, m_thumbnailOffset));
206 0 : CDR_DEBUG_MSG(("CMX Bounding Box: x: %f, y: %f, w: %f, h: %f\n", box.m_x, box.m_y, box.m_w, box.m_h));
207 0 : }
208 :
209 0 : void libcdr::CMXParser::readDisp(WPXInputStream *input, unsigned length)
210 : {
211 0 : WPXBinaryData previewImage;
212 0 : previewImage.append(0x42);
213 0 : previewImage.append(0x4d);
214 :
215 0 : previewImage.append((unsigned char)((length+8) & 0x000000ff));
216 0 : previewImage.append((unsigned char)(((length+8) & 0x0000ff00) >> 8));
217 0 : previewImage.append((unsigned char)(((length+8) & 0x00ff0000) >> 16));
218 0 : previewImage.append((unsigned char)(((length+8) & 0xff000000) >> 24));
219 :
220 0 : previewImage.append(0x00);
221 0 : previewImage.append(0x00);
222 0 : previewImage.append(0x00);
223 0 : previewImage.append(0x00);
224 :
225 0 : long startPosition = input->tell();
226 0 : input->seek(0x18, WPX_SEEK_CUR);
227 0 : int lengthX = length + 10 - readU32(input);
228 0 : input->seek(startPosition, WPX_SEEK_SET);
229 :
230 0 : previewImage.append((unsigned char)((lengthX) & 0x000000ff));
231 0 : previewImage.append((unsigned char)(((lengthX) & 0x0000ff00) >> 8));
232 0 : previewImage.append((unsigned char)(((lengthX) & 0x00ff0000) >> 16));
233 0 : previewImage.append((unsigned char)(((lengthX) & 0xff000000) >> 24));
234 :
235 0 : input->seek(4, WPX_SEEK_CUR);
236 0 : for (unsigned i = 4; i<length; i++)
237 0 : previewImage.append(readU8(input));
238 : #if DUMP_PREVIEW_IMAGE
239 : FILE *f = fopen("previewImage.bmp", "wb");
240 : if (f)
241 : {
242 : const unsigned char *tmpBuffer = previewImage.getDataBuffer();
243 : for (unsigned long k = 0; k < previewImage.size(); k++)
244 : fprintf(f, "%c",tmpBuffer[k]);
245 : fclose(f);
246 : }
247 : #endif
248 0 : }
249 :
250 0 : void libcdr::CMXParser::readCcmm(WPXInputStream * /* input */, long &recordEnd)
251 : {
252 0 : if (m_thumbnailOffset == (unsigned)-1)
253 0 : recordEnd += 0x10;
254 0 : }
255 :
256 0 : void libcdr::CMXParser::readPage(WPXInputStream *input, unsigned length)
257 : {
258 0 : long endPosition = length + input->tell();
259 0 : while (!input->atEOS() && endPosition > input->tell())
260 : {
261 0 : long startPosition = input->tell();
262 0 : int instructionSize = readS16(input, m_bigEndian);
263 0 : if (instructionSize < 0)
264 0 : instructionSize = readS32(input, m_bigEndian);
265 0 : m_nextInstructionOffset = startPosition+instructionSize;
266 0 : short instructionCode = abs(readS16(input, m_bigEndian));
267 : CDR_DEBUG_MSG(("CMXParser::readPage - instructionSize %i, instructionCode %i\n", instructionSize, instructionCode));
268 0 : switch (instructionCode)
269 : {
270 : case CMX_Command_BeginPage:
271 0 : readBeginPage(input);
272 0 : break;
273 : case CMX_Command_BeginLayer:
274 0 : readBeginLayer(input);
275 0 : break;
276 : case CMX_Command_BeginGroup:
277 0 : readBeginGroup(input);
278 0 : break;
279 : case CMX_Command_PolyCurve:
280 0 : readPolyCurve(input);
281 0 : break;
282 : case CMX_Command_Ellipse:
283 0 : readEllipse(input);
284 0 : break;
285 : case CMX_Command_Rectangle:
286 0 : readRectangle(input);
287 0 : break;
288 : case CMX_Command_JumpAbsolute:
289 0 : readJumpAbsolute(input);
290 0 : break;
291 : default:
292 0 : break;
293 : }
294 0 : input->seek(m_nextInstructionOffset, WPX_SEEK_SET);
295 : }
296 0 : }
297 :
298 0 : void libcdr::CMXParser::readBeginPage(WPXInputStream *input)
299 : {
300 0 : CDRBBox box;
301 0 : CDRTransform matrix;
302 0 : unsigned flags = 0;
303 0 : if (m_precision == libcdr::PRECISION_32BIT)
304 : {
305 0 : unsigned char tagId = 0;
306 0 : unsigned short tagLength = 0;
307 0 : do
308 : {
309 0 : long startOffset = input->tell();
310 0 : tagId = readU8(input, m_bigEndian);
311 0 : if (tagId == CMX_Tag_EndTag)
312 : {
313 : CDR_DEBUG_MSG((" CMXParser::readBeginPage - tagId %i\n", tagId));
314 0 : break;
315 : }
316 0 : tagLength = readU16(input, m_bigEndian);
317 : CDR_DEBUG_MSG((" CMXParser::readBeginPage - tagId %i, tagLength %u\n", tagId, tagLength));
318 0 : switch (tagId)
319 : {
320 : case CMX_Tag_BeginPage_PageSpecification:
321 0 : input->seek(2, WPX_SEEK_CUR);
322 0 : flags = readU32(input, m_bigEndian);
323 0 : box = readBBox(input);
324 0 : break;
325 : case CMX_Tag_BeginPage_Matrix:
326 0 : matrix = readMatrix(input);
327 0 : break;
328 : default:
329 0 : break;
330 : }
331 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
332 : }
333 : while (tagId != CMX_Tag_EndTag);
334 : }
335 0 : else if (m_precision == libcdr::PRECISION_16BIT)
336 : {
337 0 : input->seek(2, WPX_SEEK_CUR);
338 0 : flags = readU32(input, m_bigEndian);
339 0 : box = readBBox(input);
340 : }
341 : else
342 0 : return;
343 0 : m_collector->collectPage(0);
344 0 : m_collector->collectFlags(flags, true);
345 0 : m_collector->collectPageSize(box.getWidth(), box.getHeight(), box.getMinX(), box.getMinY());
346 : }
347 0 : void libcdr::CMXParser::readBeginLayer(WPXInputStream * /* input */)
348 : {
349 0 : }
350 0 : void libcdr::CMXParser::readBeginGroup(WPXInputStream * /* input */)
351 : {
352 0 : }
353 :
354 0 : void libcdr::CMXParser::readPolyCurve(WPXInputStream *input)
355 : {
356 0 : unsigned pointNum = 0;
357 0 : std::vector<std::pair<double, double> > points;
358 0 : std::vector<unsigned char> pointTypes;
359 0 : if (m_precision == libcdr::PRECISION_32BIT)
360 : {
361 0 : unsigned char tagId = 0;
362 0 : unsigned short tagLength = 0;
363 0 : do
364 : {
365 0 : long startOffset = input->tell();
366 0 : tagId = readU8(input, m_bigEndian);
367 0 : if (tagId == CMX_Tag_EndTag)
368 : {
369 : CDR_DEBUG_MSG((" CMXParser::readPolyCurve - tagId %i\n", tagId));
370 0 : break;
371 : }
372 0 : tagLength = readU16(input, m_bigEndian);
373 : CDR_DEBUG_MSG((" CMXParser::readPolyCurve - tagId %i, tagLength %u\n", tagId, tagLength));
374 0 : switch (tagId)
375 : {
376 : case CMX_Tag_PolyCurve_RenderingAttr:
377 0 : readRenderingAttributes(input);
378 0 : break;
379 : case CMX_Tag_PolyCurve_PointList:
380 0 : pointNum = readU16(input);
381 0 : for (unsigned i = 0; i < pointNum; ++i)
382 : {
383 0 : std::pair<double, double> point;
384 0 : point.first = readCoordinate(input, m_bigEndian);
385 0 : point.second = readCoordinate(input, m_bigEndian);
386 0 : points.push_back(point);
387 : }
388 0 : for (unsigned j = 0; j < pointNum; ++j)
389 0 : pointTypes.push_back(readU8(input, m_bigEndian));
390 : default:
391 0 : break;
392 : }
393 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
394 : }
395 : while (tagId != CMX_Tag_EndTag);
396 : }
397 0 : else if (m_precision == libcdr::PRECISION_16BIT)
398 : {
399 0 : readRenderingAttributes(input);
400 0 : pointNum = readU16(input);
401 0 : for (unsigned i = 0; i < pointNum; ++i)
402 : {
403 0 : std::pair<double, double> point;
404 0 : point.first = readCoordinate(input, m_bigEndian);
405 0 : point.second = readCoordinate(input, m_bigEndian);
406 0 : points.push_back(point);
407 : }
408 0 : for (unsigned j = 0; j < pointNum; ++j)
409 0 : pointTypes.push_back(readU8(input, m_bigEndian));
410 : }
411 : else
412 0 : return;
413 :
414 0 : m_collector->collectObject(1);
415 0 : outputPath(points, pointTypes);
416 0 : m_collector->collectLevel(1);
417 : }
418 :
419 0 : void libcdr::CMXParser::readEllipse(WPXInputStream *input)
420 : {
421 0 : double angle1 = 0.0;
422 0 : double angle2 = 0.0;
423 0 : double rotation = 0.0;
424 0 : bool pie = false;
425 :
426 0 : double cx = 0.0;
427 0 : double cy = 0.0;
428 0 : double rx = 0.0;
429 0 : double ry = 0.0;
430 :
431 0 : if (m_precision == libcdr::PRECISION_32BIT)
432 : {
433 0 : unsigned char tagId = 0;
434 0 : unsigned short tagLength = 0;
435 0 : do
436 : {
437 0 : long startOffset = input->tell();
438 0 : tagId = readU8(input, m_bigEndian);
439 0 : if (tagId == CMX_Tag_EndTag)
440 : {
441 : CDR_DEBUG_MSG((" CMXParser::readEllipse - tagId %i\n", tagId));
442 0 : break;
443 : }
444 0 : tagLength = readU16(input, m_bigEndian);
445 : CDR_DEBUG_MSG((" CMXParser::readEllipse - tagId %i, tagLength %u\n", tagId, tagLength));
446 0 : switch (tagId)
447 : {
448 : case CMX_Tag_Ellips_RenderingAttr:
449 0 : readRenderingAttributes(input);
450 0 : break;
451 : case CMX_Tag_Ellips_EllipsSpecification:
452 0 : cx = readCoordinate(input, m_bigEndian);
453 0 : cy = readCoordinate(input, m_bigEndian);
454 0 : rx = readCoordinate(input, m_bigEndian) / 2.0;
455 0 : ry = readCoordinate(input, m_bigEndian) / 2.0;
456 0 : angle1 = readAngle(input, m_bigEndian);
457 0 : angle2 = readAngle(input, m_bigEndian);
458 0 : rotation = readAngle(input, m_bigEndian);
459 0 : pie = (0 != readU8(input, m_bigEndian));
460 : default:
461 0 : break;
462 : }
463 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
464 : }
465 : while (tagId != CMX_Tag_EndTag);
466 : }
467 0 : else if (m_precision == libcdr::PRECISION_16BIT)
468 : {
469 0 : cx = readCoordinate(input, m_bigEndian);
470 0 : cy = readCoordinate(input, m_bigEndian);
471 0 : rx = readCoordinate(input, m_bigEndian) / 2.0;
472 0 : ry = readCoordinate(input, m_bigEndian) / 2.0;
473 0 : angle1 = readAngle(input, m_bigEndian);
474 0 : angle2 = readAngle(input, m_bigEndian);
475 0 : rotation = readAngle(input, m_bigEndian);
476 0 : pie = (0 != readU8(input, m_bigEndian));
477 : }
478 : else
479 0 : return;
480 :
481 0 : m_collector->collectObject(1);
482 0 : if (angle1 != angle2)
483 : {
484 0 : if (angle2 < angle1)
485 0 : angle2 += 2*M_PI;
486 0 : double x0 = cx + rx*cos(angle1);
487 0 : double y0 = cy - ry*sin(angle1);
488 :
489 0 : double x1 = cx + rx*cos(angle2);
490 0 : double y1 = cy - ry*sin(angle2);
491 :
492 0 : bool largeArc = (angle2 - angle1 > M_PI || angle2 - angle1 < -M_PI);
493 :
494 0 : m_collector->collectMoveTo(x0, y0);
495 0 : m_collector->collectArcTo(rx, ry, largeArc, true, x1, y1);
496 0 : if (pie)
497 : {
498 0 : m_collector->collectLineTo(cx, cy);
499 0 : m_collector->collectLineTo(x0, y0);
500 0 : m_collector->collectClosePath();
501 : }
502 : }
503 : else
504 : {
505 0 : double x0 = cx + rx;
506 0 : double y0 = cy;
507 :
508 0 : double x1 = cx;
509 0 : double y1 = cy - ry;
510 :
511 0 : m_collector->collectMoveTo(x0, y0);
512 0 : m_collector->collectArcTo(rx, ry, false, true, x1, y1);
513 0 : m_collector->collectArcTo(rx, ry, true, true, x0, y0);
514 : }
515 0 : m_collector->collectRotate(rotation, cx, cy);
516 0 : m_collector->collectLevel(1);
517 : }
518 :
519 0 : void libcdr::CMXParser::readRectangle(WPXInputStream *input)
520 : {
521 0 : double cx = 0.0;
522 0 : double cy = 0.0;
523 0 : double width = 0.0;
524 0 : double height = 0.0;
525 0 : double radius = 0.0;
526 0 : double angle = 0.0;
527 0 : if (m_precision == libcdr::PRECISION_32BIT)
528 : {
529 0 : unsigned char tagId = 0;
530 0 : unsigned short tagLength = 0;
531 0 : do
532 : {
533 0 : long startOffset = input->tell();
534 0 : tagId = readU8(input, m_bigEndian);
535 0 : if (tagId == CMX_Tag_EndTag)
536 : {
537 : CDR_DEBUG_MSG((" CMXParser::readRectangle - tagId %i\n", tagId));
538 0 : break;
539 : }
540 0 : tagLength = readU16(input, m_bigEndian);
541 : CDR_DEBUG_MSG((" CMXParser::readRectangle - tagId %i, tagLength %u\n", tagId, tagLength));
542 0 : switch (tagId)
543 : {
544 : case CMX_Tag_Rectangle_RenderingAttr:
545 0 : readRenderingAttributes(input);
546 0 : break;
547 : case CMX_Tag_Rectangle_RectangleSpecification:
548 0 : cx = readCoordinate(input, m_bigEndian);
549 0 : cy = readCoordinate(input, m_bigEndian);
550 0 : width = readCoordinate(input, m_bigEndian);
551 0 : height = readCoordinate(input, m_bigEndian);
552 0 : radius = readCoordinate(input, m_bigEndian);
553 0 : angle = readAngle(input, m_bigEndian);
554 0 : break;
555 : default:
556 0 : break;
557 : }
558 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
559 : }
560 : while (tagId != CMX_Tag_EndTag);
561 : }
562 0 : else if (m_precision == libcdr::PRECISION_16BIT)
563 : {
564 0 : input->seek(3, WPX_SEEK_CUR);
565 0 : cx = readCoordinate(input, m_bigEndian);
566 0 : cy = readCoordinate(input, m_bigEndian);
567 0 : width = readCoordinate(input, m_bigEndian);
568 0 : height = readCoordinate(input, m_bigEndian);
569 0 : radius = readCoordinate(input, m_bigEndian);
570 0 : angle = readAngle(input, m_bigEndian);
571 : }
572 : else
573 0 : return;
574 :
575 0 : m_collector->collectObject(1);
576 0 : double x0 = cx - width / 2.0;
577 0 : double y0 = cy - height / 2.0;
578 0 : double x1 = cx + width / 2.0;
579 0 : double y1 = cy + height / 2.0;
580 0 : if (radius > 0.0)
581 : {
582 0 : m_collector->collectMoveTo(x0, y0-radius);
583 0 : m_collector->collectLineTo(x0, y1+radius);
584 0 : m_collector->collectQuadraticBezier(x0, y1, x0+radius, y1);
585 0 : m_collector->collectLineTo(x1-radius, y1);
586 0 : m_collector->collectQuadraticBezier(x1, y1, x1, y1+radius);
587 0 : m_collector->collectLineTo(x1, y0-radius);
588 0 : m_collector->collectQuadraticBezier(x1, y0, x1-radius, y0);
589 0 : m_collector->collectLineTo(x0+radius, y0);
590 0 : m_collector->collectQuadraticBezier(x0, y0, x0, y0-radius);
591 : }
592 : else
593 : {
594 0 : m_collector->collectMoveTo(x0, y0);
595 0 : m_collector->collectLineTo(x0, y1);
596 0 : m_collector->collectLineTo(x1, y1);
597 0 : m_collector->collectLineTo(x1, y0);
598 0 : m_collector->collectLineTo(x0, y0);
599 : }
600 0 : m_collector->collectRotate(angle, cx, cy);
601 0 : m_collector->collectLevel(1);
602 : }
603 :
604 0 : libcdr::CDRTransform libcdr::CMXParser::readMatrix(WPXInputStream *input)
605 : {
606 0 : CDRTransform matrix;
607 0 : unsigned short type = readU16(input, m_bigEndian);
608 0 : switch (type)
609 : {
610 : case 2: // general matrix
611 : {
612 0 : double v0 = readDouble(input, m_bigEndian);
613 0 : double v3 = readDouble(input, m_bigEndian);
614 0 : double v1 = readDouble(input, m_bigEndian);
615 0 : double v4 = readDouble(input, m_bigEndian);
616 0 : double x0 = readDouble(input, m_bigEndian);
617 0 : double y0 = readDouble(input, m_bigEndian);
618 0 : return libcdr::CDRTransform(v0, v1, x0, v3, v4, y0);
619 : }
620 : default: // identity matrix for the while
621 0 : return matrix;
622 : }
623 : }
624 :
625 0 : libcdr::CDRBBox libcdr::CMXParser::readBBox(WPXInputStream *input)
626 : {
627 0 : double x0 = readCoordinate(input, m_bigEndian);
628 0 : double y0 = readCoordinate(input, m_bigEndian);
629 0 : double x1 = readCoordinate(input, m_bigEndian);
630 0 : double y1 = readCoordinate(input, m_bigEndian);
631 0 : CDRBBox box(x0, y0, x1, y1);
632 0 : return box;
633 : }
634 :
635 0 : void libcdr::CMXParser::readFill(WPXInputStream *input)
636 : {
637 0 : unsigned char tagId = 0;
638 0 : unsigned short tagLength = 0;
639 0 : unsigned fillIdentifier = readU16(input, m_bigEndian);
640 0 : switch (fillIdentifier)
641 : {
642 : case 1:
643 0 : if (m_precision == libcdr::PRECISION_32BIT)
644 : {
645 0 : do
646 : {
647 0 : long startOffset = input->tell();
648 0 : tagId = readU8(input, m_bigEndian);
649 : if (tagId == CMX_Tag_EndTag)
650 : {
651 : CDR_DEBUG_MSG((" Solid fill - tagId %i\n", tagId));
652 : }
653 0 : tagLength = readU16(input, m_bigEndian);
654 : CDR_DEBUG_MSG((" Solid fill - tagId %i, tagLength %u\n", tagId, tagLength));
655 0 : switch (tagId)
656 : {
657 : case CMX_Tag_RenderAttr_FillSpec_Uniform:
658 0 : readU32(input, m_bigEndian);
659 0 : readU32(input, m_bigEndian);
660 0 : break;
661 : default:
662 0 : break;
663 : }
664 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
665 : }
666 : while (tagId != CMX_Tag_EndTag);
667 : }
668 0 : else if (m_precision == libcdr::PRECISION_16BIT)
669 : {
670 0 : readU32(input, m_bigEndian);
671 0 : readU32(input, m_bigEndian);
672 : }
673 0 : break;
674 : case 2:
675 0 : break;
676 : case 6:
677 0 : break;
678 : case 7:
679 0 : break;
680 : case 8:
681 0 : break;
682 : case 9:
683 0 : break;
684 : case 10:
685 0 : break;
686 : case 11:
687 0 : break;
688 : default:
689 0 : break;
690 : }
691 0 : }
692 :
693 0 : void libcdr::CMXParser::readRenderingAttributes(WPXInputStream *input)
694 : {
695 0 : unsigned char tagId = 0;
696 0 : unsigned short tagLength = 0;
697 0 : unsigned char bitMask = readU8(input, m_bigEndian);
698 0 : if (bitMask & 0x01) // fill
699 : {
700 0 : if (m_precision == libcdr::PRECISION_32BIT)
701 : {
702 0 : do
703 : {
704 0 : long startOffset = input->tell();
705 0 : tagId = readU8(input, m_bigEndian);
706 0 : if (tagId == CMX_Tag_EndTag)
707 : {
708 : CDR_DEBUG_MSG((" Fill specification - tagId %i\n", tagId));
709 0 : break;
710 : }
711 0 : tagLength = readU16(input, m_bigEndian);
712 : CDR_DEBUG_MSG((" Fill specification - tagId %i, tagLength %u\n", tagId, tagLength));
713 0 : switch (tagId)
714 : {
715 :
716 : default:
717 0 : break;
718 : }
719 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
720 : }
721 : while (tagId != CMX_Tag_EndTag);
722 : }
723 0 : else if (m_precision == libcdr::PRECISION_16BIT)
724 0 : readFill(input);
725 : }
726 0 : if (bitMask & 0x02) // outline
727 : {
728 0 : if (m_precision == libcdr::PRECISION_32BIT)
729 : {
730 0 : do
731 : {
732 0 : long startOffset = input->tell();
733 0 : tagId = readU8(input, m_bigEndian);
734 0 : if (tagId == CMX_Tag_EndTag)
735 : {
736 : CDR_DEBUG_MSG((" Outline specification - tagId %i\n", tagId));
737 0 : break;
738 : }
739 0 : tagLength = readU16(input, m_bigEndian);
740 : CDR_DEBUG_MSG((" Outline specification - tagId %i, tagLength %u\n", tagId, tagLength));
741 0 : switch (tagId)
742 : {
743 : case CMX_Tag_RenderAttr_OutlineSpec:
744 0 : m_collector->collectOutlId(readU16(input, m_bigEndian));
745 0 : break;
746 : default:
747 0 : break;
748 : }
749 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
750 : }
751 : while (tagId != CMX_Tag_EndTag);
752 : }
753 0 : else if (m_precision == libcdr::PRECISION_16BIT)
754 0 : m_collector->collectOutlId(readU16(input, m_bigEndian));
755 : }
756 0 : if (bitMask & 0x04) // lens
757 : {
758 0 : if (m_precision == libcdr::PRECISION_32BIT)
759 : {
760 0 : do
761 : {
762 0 : long startOffset = input->tell();
763 0 : tagId = readU8(input, m_bigEndian);
764 0 : if (tagId == CMX_Tag_EndTag)
765 : {
766 : CDR_DEBUG_MSG((" Lens specification - tagId %i\n", tagId));
767 0 : break;
768 : }
769 0 : tagLength = readU16(input, m_bigEndian);
770 : CDR_DEBUG_MSG((" Lens specification - tagId %i, tagLength %u\n", tagId, tagLength));
771 0 : switch (tagId)
772 : {
773 : default:
774 0 : break;
775 : }
776 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
777 : }
778 : while (tagId != CMX_Tag_EndTag);
779 : }
780 : }
781 0 : if (bitMask & 0x08) // canvas
782 : {
783 0 : if (m_precision == libcdr::PRECISION_32BIT)
784 : {
785 0 : do
786 : {
787 0 : long startOffset = input->tell();
788 0 : tagId = readU8(input, m_bigEndian);
789 0 : if (tagId == CMX_Tag_EndTag)
790 : {
791 : CDR_DEBUG_MSG((" Canvas specification - tagId %i\n", tagId));
792 0 : break;
793 : }
794 0 : tagLength = readU16(input, m_bigEndian);
795 : CDR_DEBUG_MSG((" Canvas specification - tagId %i, tagLength %u\n", tagId, tagLength));
796 0 : switch (tagId)
797 : {
798 : default:
799 0 : break;
800 : }
801 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
802 : }
803 : while (tagId != CMX_Tag_EndTag);
804 : }
805 : }
806 0 : if (bitMask & 0x10) // container
807 : {
808 0 : if (m_precision == libcdr::PRECISION_32BIT)
809 : {
810 0 : do
811 : {
812 0 : long startOffset = input->tell();
813 0 : tagId = readU8(input, m_bigEndian);
814 0 : if (tagId == CMX_Tag_EndTag)
815 : {
816 : CDR_DEBUG_MSG((" Container specification - tagId %i\n", tagId));
817 0 : break;
818 : }
819 0 : tagLength = readU16(input, m_bigEndian);
820 : CDR_DEBUG_MSG((" Container specification - tagId %i, tagLength %u\n", tagId, tagLength));
821 0 : switch (tagId)
822 : {
823 : default:
824 0 : break;
825 : }
826 0 : input->seek(startOffset + tagLength, WPX_SEEK_SET);
827 : }
828 : while (tagId != CMX_Tag_EndTag);
829 : }
830 : }
831 0 : }
832 :
833 0 : void libcdr::CMXParser::readJumpAbsolute(WPXInputStream *input)
834 : {
835 0 : if (m_precision == libcdr::PRECISION_32BIT)
836 : {
837 0 : unsigned char tagId = 0;
838 0 : unsigned short tagLength = 0;
839 0 : do
840 : {
841 0 : long endOffset = input->tell() + tagLength;
842 0 : tagId = readU8(input, m_bigEndian);
843 0 : if (tagId == CMX_Tag_EndTag)
844 : {
845 : CDR_DEBUG_MSG((" CMXParser::readJumpAbsolute - tagId %i\n", tagId));
846 0 : break;
847 : }
848 0 : tagLength = readU16(input, m_bigEndian);
849 : CDR_DEBUG_MSG((" CMXParser::readJumpAbsolute - tagId %i, tagLength %u\n", tagId, tagLength));
850 0 : switch (tagId)
851 : {
852 : case CMX_Tag_JumpAbsolute_Offset:
853 0 : m_nextInstructionOffset = readU32(input, m_bigEndian);
854 : default:
855 0 : break;
856 : }
857 0 : input->seek(endOffset, WPX_SEEK_SET);
858 : }
859 : while (tagId != CMX_Tag_EndTag);
860 : }
861 0 : else if (m_precision == libcdr::PRECISION_16BIT)
862 0 : m_nextInstructionOffset = readU32(input, m_bigEndian);
863 : else
864 0 : return;
865 0 : }
866 :
867 : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|