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 "libcdr_utils.h"
36 : #include "CDRDocumentStructure.h"
37 : #include "CDRInternalStream.h"
38 : #include "CDRParser.h"
39 : #include "CDRCollector.h"
40 : #include "CDRColorPalettes.h"
41 :
42 : #ifndef DUMP_PREVIEW_IMAGE
43 : #define DUMP_PREVIEW_IMAGE 0
44 : #endif
45 :
46 : #ifndef M_PI
47 : #define M_PI 3.14159265358979323846
48 : #endif
49 :
50 : namespace
51 : {
52 :
53 0 : unsigned getCDRVersion(char c)
54 : {
55 0 : if (c == 0x20)
56 0 : return 300;
57 0 : else if (c < 0x31)
58 0 : return 0;
59 0 : else if (c < 0x3a)
60 0 : return 100 * ((unsigned char)c - 0x30);
61 0 : else if (c < 0x41)
62 0 : return 0;
63 0 : return 100 * ((unsigned char)c - 0x37);
64 : }
65 :
66 : struct CDRStltRecord
67 : {
68 0 : CDRStltRecord()
69 : : parentId(0), fillId(0), outlId(0), fontRecId(0), alignId(0),
70 : intervalId(0), set5Id(0), set11Id(0), tabId(0),
71 0 : bulletId(0), identId(0), hyphenId(0), dropCapId(0) {}
72 : unsigned parentId;
73 : unsigned fillId;
74 : unsigned outlId;
75 : unsigned fontRecId;
76 : unsigned alignId;
77 : unsigned intervalId;
78 : unsigned set5Id;
79 : unsigned set11Id;
80 : unsigned tabId;
81 : unsigned bulletId;
82 : unsigned identId;
83 : unsigned hyphenId;
84 : unsigned dropCapId;
85 : };
86 :
87 : } // anonymous namespace
88 :
89 0 : libcdr::CDRParser::CDRParser(const std::vector<WPXInputStream *> &externalStreams, libcdr::CDRCollector *collector)
90 : : CommonParser(collector),
91 : m_externalStreams(externalStreams),
92 0 : m_version(0), m_fillId(0), m_outlId(0) {}
93 :
94 0 : libcdr::CDRParser::~CDRParser()
95 : {
96 0 : m_collector->collectLevel(0);
97 0 : }
98 :
99 0 : bool libcdr::CDRParser::parseWaldo(WPXInputStream *input)
100 : {
101 : try
102 : {
103 0 : input->seek(0, WPX_SEEK_SET);
104 0 : unsigned short magic = readU16(input);
105 0 : if (magic != 0x4c57)
106 0 : return false;
107 0 : m_version = 200;
108 0 : m_precision = libcdr::PRECISION_16BIT;
109 0 : if ('e' >= readU8(input))
110 0 : m_version = 100;
111 0 : input->seek(1, WPX_SEEK_CUR);
112 0 : std::vector<unsigned> offsets;
113 0 : unsigned i = 0;
114 0 : for (i = 0; i < 8; ++i)
115 0 : offsets.push_back(readU32(input));
116 0 : input->seek(1, WPX_SEEK_CUR);
117 0 : for (i = 0; i < 10; i++)
118 0 : offsets.push_back(readU32(input));
119 0 : input->seek(offsets[0], WPX_SEEK_SET);
120 : CDR_DEBUG_MSG(("CDRParser::parseWaldo, Mcfg offset 0x%x\n", (unsigned)input->tell()));
121 0 : readMcfg(input, 275);
122 0 : std::vector<WaldoRecordInfo> records;
123 0 : std::map<unsigned, WaldoRecordInfo> records2;
124 0 : std::map<unsigned, WaldoRecordInfo> records3;
125 0 : std::map<unsigned, WaldoRecordInfo> records4;
126 0 : std::map<unsigned, WaldoRecordInfo> records6;
127 0 : std::map<unsigned, WaldoRecordInfo> records8;
128 0 : std::map<unsigned, WaldoRecordInfo> records7;
129 0 : std::map<unsigned, WaldoRecordInfo> recordsOther;
130 0 : if (offsets[3])
131 : {
132 0 : input->seek(offsets[3], WPX_SEEK_SET);
133 0 : if (!gatherWaldoInformation(input, records, records2, records3, records4, records6, records7, records8, recordsOther))
134 0 : return false;
135 : }
136 0 : if (offsets[5])
137 : {
138 0 : input->seek(offsets[5], WPX_SEEK_SET);
139 0 : gatherWaldoInformation(input, records, records2, records3, records4, records6, records7, records8, recordsOther);
140 : }
141 0 : if (offsets[11])
142 : {
143 0 : input->seek(offsets[11], WPX_SEEK_SET);
144 0 : gatherWaldoInformation(input, records, records2, records3, records4, records6, records7, records8, recordsOther);
145 : }
146 0 : std::map<unsigned, WaldoRecordType1> records1;
147 0 : for (std::vector<WaldoRecordInfo>::iterator iterVec = records.begin(); iterVec != records.end(); ++iterVec)
148 : {
149 0 : input->seek(iterVec->offset, WPX_SEEK_SET);
150 0 : unsigned length = readU32(input);
151 0 : if (length != 0x18)
152 : {
153 : CDR_DEBUG_MSG(("Throwing GenericException\n"));
154 0 : throw GenericException();
155 : }
156 0 : unsigned short next = readU16(input);
157 0 : unsigned short previous = readU16(input);
158 0 : unsigned short child = readU16(input);
159 0 : unsigned short parent = readU16(input);
160 0 : input->seek(4, WPX_SEEK_CUR);
161 0 : unsigned short moreDataID = readU16(input);
162 0 : double x0 = readCoordinate(input);
163 0 : double y0 = readCoordinate(input);
164 0 : double x1 = readCoordinate(input);
165 0 : double y1 = readCoordinate(input);
166 0 : unsigned short flags = readU16(input);
167 0 : CDRTransform trafo;
168 0 : if (moreDataID)
169 : {
170 0 : std::map<unsigned, WaldoRecordInfo>::const_iterator iter7 = records7.find(moreDataID);
171 0 : if (iter7 != records7.end())
172 0 : input->seek(iter7->second.offset, WPX_SEEK_SET);
173 0 : input->seek(0x26, WPX_SEEK_CUR);
174 0 : double v0 = readFixedPoint(input);
175 0 : double v1 = readFixedPoint(input);
176 0 : double v2 = readFixedPoint(input) / 1000.0;
177 0 : double v3 = readFixedPoint(input);
178 0 : double v4 = readFixedPoint(input);
179 0 : double v5 = readFixedPoint(input) / 1000.0;
180 0 : trafo = CDRTransform(v0, v1, v2, v3, v4, v5);
181 : }
182 0 : records1[iterVec->id] = WaldoRecordType1(iterVec->id, next, previous, child, parent, flags, x0, y0, x1, y1, trafo);
183 : }
184 0 : std::map<unsigned, WaldoRecordInfo>::const_iterator iter;
185 0 : for (iter = records3.begin(); iter != records3.end(); ++iter)
186 0 : readWaldoRecord(input, iter->second);
187 0 : for (iter = records6.begin(); iter != records6.end(); ++iter)
188 0 : readWaldoRecord(input, iter->second);
189 0 : for (iter = records8.begin(); iter != records8.end(); ++iter)
190 0 : readWaldoRecord(input, iter->second);
191 0 : for (iter = recordsOther.begin(); iter != recordsOther.end(); ++iter)
192 0 : readWaldoRecord(input, iter->second);
193 0 : if (!records1.empty() && !records2.empty())
194 : {
195 :
196 0 : std::map<unsigned, WaldoRecordType1>::iterator iter1 = records1.find(1);
197 0 : std::stack<WaldoRecordType1> waldoStack;
198 0 : if (iter1 != records1.end())
199 : {
200 0 : waldoStack.push(iter1->second);
201 0 : m_collector->collectVect(waldoStack.size());
202 0 : parseWaldoStructure(input, waldoStack, records1, records2);
203 : }
204 0 : iter1 = records1.find(0);
205 0 : if (iter1 == records1.end())
206 0 : return false;
207 0 : waldoStack = std::stack<WaldoRecordType1>();
208 0 : waldoStack.push(iter1->second);
209 0 : m_collector->collectPage(waldoStack.size());
210 0 : if (!parseWaldoStructure(input, waldoStack, records1, records2))
211 0 : return false;
212 : }
213 0 : return true;
214 : }
215 0 : catch (...)
216 : {
217 0 : return false;
218 : }
219 : }
220 :
221 0 : bool libcdr::CDRParser::gatherWaldoInformation(WPXInputStream *input, std::vector<WaldoRecordInfo> &records, std::map<unsigned, WaldoRecordInfo> &records2,
222 : std::map<unsigned, WaldoRecordInfo> &records3, std::map<unsigned, WaldoRecordInfo> &records4,
223 : std::map<unsigned, WaldoRecordInfo> &records6, std::map<unsigned, WaldoRecordInfo> &records7,
224 : std::map<unsigned, WaldoRecordInfo> &records8, std::map<unsigned, WaldoRecordInfo> recordsOther)
225 : {
226 : try
227 : {
228 0 : unsigned short numRecords = readU16(input);
229 0 : for (; numRecords > 0 && !input->atEOS(); --numRecords)
230 : {
231 0 : unsigned char recordType = readU8(input);
232 0 : unsigned recordId = readU32(input);
233 0 : unsigned recordOffset = readU32(input);
234 0 : switch (recordType)
235 : {
236 : case 1:
237 0 : records.push_back(WaldoRecordInfo(recordType, recordId, recordOffset));
238 0 : break;
239 : case 2:
240 0 : records2[recordId] = WaldoRecordInfo(recordType, recordId, recordOffset);
241 0 : break;
242 : case 3:
243 0 : records3[recordId] = WaldoRecordInfo(recordType, recordId, recordOffset);
244 0 : break;
245 : case 4:
246 0 : records4[recordId] = WaldoRecordInfo(recordType, recordId, recordOffset);
247 0 : break;
248 : case 6:
249 0 : records6[recordId] = WaldoRecordInfo(recordType, recordId, recordOffset);
250 0 : break;
251 : case 7:
252 0 : records7[recordId] = WaldoRecordInfo(recordType, recordId, recordOffset);
253 0 : break;
254 : case 8:
255 0 : records8[recordId] = WaldoRecordInfo(recordType, recordId, recordOffset);
256 0 : break;
257 : default:
258 0 : recordsOther[recordId] = WaldoRecordInfo(recordType, recordId, recordOffset);
259 0 : break;
260 : }
261 : }
262 0 : return true;
263 : }
264 0 : catch (...)
265 : {
266 : CDR_DEBUG_MSG(("CDRParser::gatherWaldoInformation: something went wrong during information gathering\n"));
267 0 : return false;
268 : }
269 : }
270 :
271 :
272 0 : bool libcdr::CDRParser::parseWaldoStructure(WPXInputStream *input, std::stack<WaldoRecordType1> &waldoStack,
273 : const std::map<unsigned, WaldoRecordType1> &records1, std::map<unsigned, WaldoRecordInfo> &records2)
274 : {
275 0 : while (!waldoStack.empty())
276 : {
277 0 : m_collector->collectBBox(waldoStack.top().m_x0, waldoStack.top().m_y0, waldoStack.top().m_x1, waldoStack.top().m_y1);
278 0 : std::map<unsigned, WaldoRecordType1>::const_iterator iter1;
279 0 : if (waldoStack.top().m_flags & 0x01)
280 : {
281 0 : if (waldoStack.size() > 1)
282 : {
283 0 : m_collector->collectGroup(waldoStack.size());
284 0 : m_collector->collectSpnd(waldoStack.top().m_id);
285 0 : CDRTransforms trafos;
286 0 : trafos.append(waldoStack.top().m_trafo);
287 0 : m_collector->collectTransform(trafos, true);
288 : }
289 0 : iter1 = records1.find(waldoStack.top().m_child);
290 0 : if (iter1 == records1.end())
291 0 : return false;
292 0 : waldoStack.push(iter1->second);
293 0 : m_collector->collectLevel(waldoStack.size());
294 : }
295 : else
296 : {
297 0 : if (waldoStack.size() > 1)
298 0 : m_collector->collectObject(waldoStack.size());
299 0 : std::map<unsigned, WaldoRecordInfo>::const_iterator iter2 = records2.find(waldoStack.top().m_child);
300 0 : if (iter2 == records2.end())
301 0 : return false;
302 0 : readWaldoRecord(input, iter2->second);
303 0 : while (!waldoStack.empty() && !waldoStack.top().m_next)
304 0 : waldoStack.pop();
305 0 : m_collector->collectLevel(waldoStack.size());
306 0 : if (waldoStack.empty())
307 0 : return true;
308 0 : iter1 = records1.find(waldoStack.top().m_next);
309 0 : if (iter1 == records1.end())
310 0 : return false;
311 0 : waldoStack.top() = iter1->second;
312 : }
313 : }
314 0 : return true;
315 : }
316 :
317 0 : void libcdr::CDRParser::readWaldoRecord(WPXInputStream *input, const WaldoRecordInfo &info)
318 : {
319 : CDR_DEBUG_MSG(("CDRParser::readWaldoRecord, type %i, id %x, offset %x\n", info.type, info.id, info.offset));
320 0 : input->seek(info.offset, WPX_SEEK_SET);
321 0 : switch (info.type)
322 : {
323 : case 2:
324 : {
325 0 : unsigned length = readU32(input);
326 0 : readWaldoLoda(input, length);
327 : }
328 0 : break;
329 : case 3:
330 : {
331 0 : unsigned length = readU32(input);
332 0 : readWaldoBmp(input, length, info.id);
333 : }
334 0 : break;
335 : case 6:
336 0 : readWaldoBmpf(input, info.id);
337 0 : break;
338 : default:
339 0 : break;
340 : }
341 0 : }
342 :
343 0 : void libcdr::CDRParser::readWaldoTrfd(WPXInputStream *input)
344 : {
345 0 : if (m_version >= 400)
346 0 : return;
347 0 : double v0 = 0.0;
348 0 : double v1 = 0.0;
349 0 : double x0 = 0.0;
350 0 : double v3 = 0.0;
351 0 : double v4 = 0.0;
352 0 : double y0 = 0.0;
353 0 : if (m_version >= 300)
354 : {
355 0 : long startPosition = input->tell();
356 0 : input->seek(0x0a, WPX_SEEK_CUR);
357 0 : unsigned offset = readUnsigned(input);
358 0 : input->seek(startPosition+offset, WPX_SEEK_SET);
359 0 : v0 = readFixedPoint(input);
360 0 : v1 = readFixedPoint(input);
361 0 : x0 = (double)readS32(input) / 1000.0;
362 0 : v3 = readFixedPoint(input);
363 0 : v4 = readFixedPoint(input);
364 0 : y0 = (double)readS32(input) / 1000.0;
365 : }
366 : else
367 : {
368 0 : x0 = readCoordinate(input);
369 0 : y0 = readCoordinate(input);
370 0 : v0 = readFixedPoint(input);
371 0 : v1 = readFixedPoint(input);
372 0 : x0 += readFixedPoint(input) / 1000.0;
373 0 : v3 = readFixedPoint(input);
374 0 : v4 = readFixedPoint(input);
375 0 : y0 += readFixedPoint(input) / 1000.0;
376 : }
377 : CDR_DEBUG_MSG(("CDRParser::readWaldoTrfd %f %f %f %f %f %f %u\n", v0, v1, x0, v3, v4, y0, m_version));
378 0 : CDRTransforms trafos;
379 0 : trafos.append(v0, v1, x0, v3, v4, y0);
380 0 : m_collector->collectTransform(trafos, m_version < 400);
381 : }
382 :
383 0 : void libcdr::CDRParser::readWaldoLoda(WPXInputStream *input, unsigned length)
384 : {
385 0 : if (m_version >= 300)
386 0 : return;
387 0 : long startPosition = input->tell();
388 0 : readWaldoTrfd(input);
389 0 : unsigned chunkType = readU8(input);
390 0 : unsigned shapeOffset = readU16(input);
391 0 : unsigned outlOffset = readU16(input);
392 0 : unsigned fillOffset = readU16(input);
393 0 : if (outlOffset)
394 : {
395 0 : input->seek(startPosition + outlOffset, WPX_SEEK_SET);
396 0 : readWaldoOutl(input);
397 : }
398 0 : if (fillOffset)
399 : {
400 0 : input->seek(startPosition + fillOffset, WPX_SEEK_SET);
401 0 : readWaldoFill(input);
402 : }
403 0 : if (shapeOffset)
404 : {
405 0 : input->seek(startPosition + shapeOffset, WPX_SEEK_SET);
406 0 : if (chunkType == 0x00) // Rectangle
407 0 : readRectangle(input);
408 0 : else if (chunkType == 0x01) // Ellipse
409 0 : readEllipse(input);
410 0 : else if (chunkType == 0x02) // Line and curve
411 0 : readLineAndCurve(input);
412 : /* else if (chunkType == 0x03) // Text
413 : readText(input); */
414 0 : else if (chunkType == 0x04) // Bitmap
415 0 : readBitmap(input);
416 : }
417 0 : input->seek(startPosition + length, WPX_SEEK_SET);
418 : }
419 :
420 0 : bool libcdr::CDRParser::parseRecords(WPXInputStream *input, unsigned *blockLengths, unsigned level)
421 : {
422 0 : if (!input)
423 : {
424 0 : return false;
425 : }
426 0 : m_collector->collectLevel(level);
427 0 : while (!input->atEOS())
428 : {
429 0 : if (!parseRecord(input, blockLengths, level))
430 0 : return false;
431 : }
432 0 : return true;
433 : }
434 :
435 0 : bool libcdr::CDRParser::parseRecord(WPXInputStream *input, unsigned *blockLengths, unsigned level)
436 : {
437 0 : if (!input)
438 : {
439 0 : return false;
440 : }
441 : try
442 : {
443 0 : m_collector->collectLevel(level);
444 0 : while (!input->atEOS() && readU8(input) == 0)
445 : {
446 : }
447 0 : if (!input->atEOS())
448 0 : input->seek(-1, WPX_SEEK_CUR);
449 : else
450 0 : return true;
451 0 : unsigned fourCC = readU32(input);
452 0 : unsigned length = readU32(input);
453 0 : if (blockLengths)
454 0 : length=blockLengths[length];
455 0 : unsigned long position = input->tell();
456 0 : unsigned listType(0);
457 0 : if (fourCC == FOURCC_RIFF || fourCC == FOURCC_LIST)
458 : {
459 0 : listType = readU32(input);
460 0 : if (listType == FOURCC_stlt && m_version >= 700)
461 0 : fourCC = listType;
462 : else
463 0 : m_collector->collectOtherList();
464 : }
465 : CDR_DEBUG_MSG(("Record: level %u %s, length: 0x%.8x (%u)\n", level, toFourCC(fourCC), length, length));
466 :
467 0 : if (fourCC == FOURCC_RIFF || fourCC == FOURCC_LIST)
468 : {
469 : CDR_DEBUG_MSG(("CDR listType: %s\n", toFourCC(listType)));
470 0 : unsigned cmprsize = length-4;
471 0 : if (listType == FOURCC_cmpr)
472 : {
473 0 : cmprsize = readU32(input);
474 0 : input->seek(12, WPX_SEEK_CUR);
475 0 : if (readU32(input) != FOURCC_CPng)
476 0 : return false;
477 0 : if (readU16(input) != 1)
478 0 : return false;
479 0 : if (readU16(input) != 4)
480 0 : return false;
481 : }
482 0 : else if (listType == FOURCC_page)
483 0 : m_collector->collectPage(level);
484 0 : else if (listType == FOURCC_obj)
485 0 : m_collector->collectObject(level);
486 0 : else if (listType == FOURCC_grp)
487 0 : m_collector->collectGroup(level);
488 0 : else if ((listType & 0xffffff) == FOURCC_CDR || (listType & 0xffffff) == FOURCC_cdr)
489 : {
490 0 : m_version = getCDRVersion((listType & 0xff000000) >> 24);
491 0 : if (m_version < 600)
492 0 : m_precision = libcdr::PRECISION_16BIT;
493 : else
494 0 : m_precision = libcdr::PRECISION_32BIT;
495 : }
496 0 : else if (listType == FOURCC_vect || listType == FOURCC_clpt)
497 0 : m_collector->collectVect(level);
498 :
499 0 : bool compressed = (listType == FOURCC_cmpr ? true : false);
500 0 : CDRInternalStream tmpStream(input, cmprsize, compressed);
501 0 : if (!compressed)
502 : {
503 0 : if (!parseRecords(&tmpStream, blockLengths, level+1))
504 0 : return false;
505 : }
506 : else
507 : {
508 0 : std::vector<unsigned> tmpBlockLengths;
509 0 : unsigned blocksLength = length + position - input->tell();
510 0 : CDRInternalStream tmpBlocksStream(input, blocksLength, compressed);
511 0 : while (!tmpBlocksStream.atEOS())
512 0 : tmpBlockLengths.push_back(readU32(&tmpBlocksStream));
513 0 : if (!parseRecords(&tmpStream, tmpBlockLengths.size() ? &tmpBlockLengths[0] : 0, level+1))
514 0 : return false;
515 0 : }
516 : }
517 : else
518 0 : readRecord(fourCC, length, input);
519 :
520 0 : input->seek(position + length, WPX_SEEK_SET);
521 0 : return true;
522 : }
523 0 : catch (...)
524 : {
525 0 : return false;
526 : }
527 : }
528 :
529 0 : void libcdr::CDRParser::readRecord(unsigned fourCC, unsigned length, WPXInputStream *input)
530 : {
531 0 : long recordStart = input->tell();
532 0 : switch (fourCC)
533 : {
534 : case FOURCC_DISP:
535 0 : readDisp(input, length);
536 0 : break;
537 : case FOURCC_loda:
538 : case FOURCC_lobj:
539 0 : readLoda(input, length);
540 0 : break;
541 : case FOURCC_vrsn:
542 0 : readVersion(input, length);
543 0 : break;
544 : case FOURCC_trfd:
545 0 : readTrfd(input, length);
546 0 : break;
547 : case FOURCC_outl:
548 0 : readOutl(input, length);
549 0 : break;
550 : case FOURCC_fild:
551 : case FOURCC_fill:
552 0 : readFild(input, length);
553 0 : break;
554 : case FOURCC_arrw:
555 0 : break;
556 : case FOURCC_flgs:
557 0 : readFlags(input, length);
558 0 : break;
559 : case FOURCC_mcfg:
560 0 : readMcfg(input, length);
561 0 : break;
562 : case FOURCC_bmp:
563 0 : readBmp(input, length);
564 0 : break;
565 : case FOURCC_bmpf:
566 0 : readBmpf(input, length);
567 0 : break;
568 : case FOURCC_ppdt:
569 0 : readPpdt(input, length);
570 0 : break;
571 : case FOURCC_ftil:
572 0 : readFtil(input, length);
573 0 : break;
574 : case FOURCC_iccd:
575 0 : readIccd(input, length);
576 0 : break;
577 : case FOURCC_bbox:
578 0 : readBBox(input, length);
579 0 : break;
580 : case FOURCC_spnd:
581 0 : readSpnd(input, length);
582 0 : break;
583 : case FOURCC_uidr:
584 0 : readUidr(input, length);
585 0 : break;
586 : case FOURCC_vpat:
587 0 : readVpat(input, length);
588 0 : break;
589 : case FOURCC_font:
590 0 : readFont(input, length);
591 0 : break;
592 : case FOURCC_stlt:
593 0 : readStlt(input, length);
594 0 : break;
595 : case FOURCC_txsm:
596 0 : readTxsm(input, length);
597 0 : break;
598 : case FOURCC_styd:
599 0 : readStyd(input);
600 0 : break;
601 : default:
602 0 : break;
603 : }
604 0 : input->seek(recordStart + length, WPX_SEEK_CUR);
605 0 : }
606 :
607 0 : double libcdr::CDRParser::readRectCoord(WPXInputStream *input)
608 : {
609 0 : if (m_version < 1500)
610 0 : return readCoordinate(input);
611 0 : return readDouble(input) / 254000.0;
612 : }
613 :
614 0 : libcdr::CDRColor libcdr::CDRParser::readColor(WPXInputStream *input)
615 : {
616 0 : unsigned short colorModel = 0;
617 0 : unsigned colorValue = 0;
618 0 : if (m_version >= 500)
619 : {
620 0 : colorModel = readU16(input);
621 0 : if (colorModel == 0x19)
622 : {
623 0 : unsigned char r = 0;
624 0 : unsigned char g = 0;
625 0 : unsigned char b = 0;
626 0 : unsigned char c = 0;
627 0 : unsigned char m = 0;
628 0 : unsigned char y = 0;
629 0 : unsigned char k = 100;
630 0 : unsigned short paletteID = readU16(input);
631 0 : input->seek(4, WPX_SEEK_CUR);
632 0 : unsigned short ix = readU16(input);
633 0 : unsigned short tint = readU16(input);
634 0 : switch (paletteID)
635 : {
636 : case 0x08:
637 0 : if (ix > 0
638 : && ix <= sizeof(palette_19_08_C)/sizeof(palette_19_08_C[0])
639 : && ix <= sizeof(palette_19_08_M)/sizeof(palette_19_08_M[0])
640 : && ix <= sizeof(palette_19_08_Y)/sizeof(palette_19_08_Y[0])
641 : && ix <= sizeof(palette_19_08_K)/sizeof(palette_19_08_K[0]))
642 : {
643 0 : c = palette_19_08_C[ix-1];
644 0 : m = palette_19_08_M[ix-1];
645 0 : y = palette_19_08_Y[ix-1];
646 0 : k = palette_19_08_K[ix-1];
647 : }
648 0 : break;
649 : case 0x09:
650 0 : if (ix > 0
651 : && ix <= sizeof(palette_19_09_L)/sizeof(palette_19_09_L[0])
652 : && ix <= sizeof(palette_19_09_A)/sizeof(palette_19_09_A[0])
653 : && ix <= sizeof(palette_19_09_B)/sizeof(palette_19_09_B[0]))
654 : {
655 0 : colorValue = palette_19_09_B[ix-1];
656 0 : colorValue <<= 8;
657 0 : colorValue |= palette_19_09_A[ix-1];
658 0 : colorValue <<= 8;
659 0 : colorValue |= palette_19_09_L[ix-1];
660 : }
661 0 : break;
662 : case 0x0a:
663 0 : if (ix > 0
664 : && ix <= sizeof(palette_19_0A_C)/sizeof(palette_19_0A_C[0])
665 : && ix <= sizeof(palette_19_0A_M)/sizeof(palette_19_0A_M[0])
666 : && ix <= sizeof(palette_19_0A_Y)/sizeof(palette_19_0A_Y[0])
667 : && ix <= sizeof(palette_19_0A_K)/sizeof(palette_19_0A_K[0]))
668 : {
669 0 : c = palette_19_0A_C[ix-1];
670 0 : m = palette_19_0A_M[ix-1];
671 0 : y = palette_19_0A_Y[ix-1];
672 0 : k = palette_19_0A_K[ix-1];
673 : }
674 0 : break;
675 : case 0x0b:
676 0 : if (ix > 0
677 : && ix <= sizeof(palette_19_0B_C)/sizeof(palette_19_0B_C[0])
678 : && ix <= sizeof(palette_19_0B_M)/sizeof(palette_19_0B_M[0])
679 : && ix <= sizeof(palette_19_0B_Y)/sizeof(palette_19_0B_Y[0])
680 : && ix <= sizeof(palette_19_0B_K)/sizeof(palette_19_0B_K[0]))
681 : {
682 0 : c = palette_19_0B_C[ix-1];
683 0 : m = palette_19_0B_M[ix-1];
684 0 : y = palette_19_0B_Y[ix-1];
685 0 : k = palette_19_0B_K[ix-1];
686 : }
687 0 : break;
688 : case 0x11:
689 0 : if (ix > 0
690 : && ix <= sizeof(palette_19_11_C)/sizeof(palette_19_11_C[0])
691 : && ix <= sizeof(palette_19_11_M)/sizeof(palette_19_11_M[0])
692 : && ix <= sizeof(palette_19_11_Y)/sizeof(palette_19_11_Y[0])
693 : && ix <= sizeof(palette_19_11_K)/sizeof(palette_19_11_K[0]))
694 : {
695 0 : c = palette_19_11_C[ix-1];
696 0 : m = palette_19_11_M[ix-1];
697 0 : y = palette_19_11_Y[ix-1];
698 0 : k = palette_19_11_K[ix-1];
699 : }
700 0 : break;
701 : case 0x12:
702 0 : if (ix > 0
703 : && ix <= sizeof(palette_19_12_C)/sizeof(palette_19_12_C[0])
704 : && ix <= sizeof(palette_19_12_M)/sizeof(palette_19_12_M[0])
705 : && ix <= sizeof(palette_19_12_Y)/sizeof(palette_19_12_Y[0])
706 : && ix <= sizeof(palette_19_12_K)/sizeof(palette_19_12_K[0]))
707 : {
708 0 : c = palette_19_12_C[ix-1];
709 0 : m = palette_19_12_M[ix-1];
710 0 : y = palette_19_12_Y[ix-1];
711 0 : k = palette_19_12_K[ix-1];
712 : }
713 0 : break;
714 : case 0x14:
715 0 : if (ix > 0
716 : && ix <= sizeof(palette_19_14_C)/sizeof(palette_19_14_C[0])
717 : && ix <= sizeof(palette_19_14_M)/sizeof(palette_19_14_M[0])
718 : && ix <= sizeof(palette_19_14_Y)/sizeof(palette_19_14_Y[0])
719 : && ix <= sizeof(palette_19_14_K)/sizeof(palette_19_14_K[0]))
720 : {
721 0 : c = palette_19_14_C[ix-1];
722 0 : m = palette_19_14_M[ix-1];
723 0 : y = palette_19_14_Y[ix-1];
724 0 : k = palette_19_14_K[ix-1];
725 : }
726 0 : break;
727 : case 0x15:
728 0 : if (ix > 0
729 : && ix <= sizeof(palette_19_15_C)/sizeof(palette_19_15_C[0])
730 : && ix <= sizeof(palette_19_15_M)/sizeof(palette_19_15_M[0])
731 : && ix <= sizeof(palette_19_15_Y)/sizeof(palette_19_15_Y[0])
732 : && ix <= sizeof(palette_19_15_K)/sizeof(palette_19_15_K[0]))
733 : {
734 0 : c = palette_19_15_C[ix-1];
735 0 : m = palette_19_15_M[ix-1];
736 0 : y = palette_19_15_Y[ix-1];
737 0 : k = palette_19_15_K[ix-1];
738 : }
739 0 : break;
740 : case 0x16:
741 0 : if (ix > 0
742 : && ix <= sizeof(palette_19_16_C)/sizeof(palette_19_16_C[0])
743 : && ix <= sizeof(palette_19_16_M)/sizeof(palette_19_16_M[0])
744 : && ix <= sizeof(palette_19_16_Y)/sizeof(palette_19_16_Y[0])
745 : && ix <= sizeof(palette_19_16_K)/sizeof(palette_19_16_K[0]))
746 : {
747 0 : c = palette_19_16_C[ix-1];
748 0 : m = palette_19_16_M[ix-1];
749 0 : y = palette_19_16_Y[ix-1];
750 0 : k = palette_19_16_K[ix-1];
751 : }
752 0 : break;
753 : case 0x17:
754 0 : if (ix > 0
755 : && ix <= sizeof(palette_19_17_C)/sizeof(palette_19_17_C[0])
756 : && ix <= sizeof(palette_19_17_M)/sizeof(palette_19_17_M[0])
757 : && ix <= sizeof(palette_19_17_Y)/sizeof(palette_19_17_Y[0])
758 : && ix <= sizeof(palette_19_17_K)/sizeof(palette_19_17_K[0]))
759 : {
760 0 : c = palette_19_17_C[ix-1];
761 0 : m = palette_19_17_M[ix-1];
762 0 : y = palette_19_17_Y[ix-1];
763 0 : k = palette_19_17_K[ix-1];
764 : }
765 0 : break;
766 : case 0x1a:
767 0 : if (ix < sizeof(palette_19_1A_C)/sizeof(palette_19_1A_C[0])
768 : && ix < sizeof(palette_19_1A_M)/sizeof(palette_19_1A_M[0])
769 : && ix < sizeof(palette_19_1A_Y)/sizeof(palette_19_1A_Y[0])
770 : && ix < sizeof(palette_19_1A_K)/sizeof(palette_19_1A_K[0]))
771 : {
772 0 : c = palette_19_1A_C[ix];
773 0 : m = palette_19_1A_M[ix];
774 0 : y = palette_19_1A_Y[ix];
775 0 : k = palette_19_1A_K[ix];
776 : }
777 0 : break;
778 : case 0x1b:
779 0 : if (ix < sizeof(palette_19_1B_C)/sizeof(palette_19_1B_C[0])
780 : && ix < sizeof(palette_19_1B_M)/sizeof(palette_19_1B_M[0])
781 : && ix < sizeof(palette_19_1B_Y)/sizeof(palette_19_1B_Y[0])
782 : && ix < sizeof(palette_19_1B_K)/sizeof(palette_19_1B_K[0]))
783 : {
784 0 : c = palette_19_1B_C[ix];
785 0 : m = palette_19_1B_M[ix];
786 0 : y = palette_19_1B_Y[ix];
787 0 : k = palette_19_1B_K[ix];
788 : }
789 0 : break;
790 : case 0x1c:
791 0 : if (ix < sizeof(palette_19_1C_C)/sizeof(palette_19_1C_C[0])
792 : && ix < sizeof(palette_19_1C_M)/sizeof(palette_19_1C_M[0])
793 : && ix < sizeof(palette_19_1C_Y)/sizeof(palette_19_1C_Y[0])
794 : && ix < sizeof(palette_19_1C_K)/sizeof(palette_19_1C_K[0]))
795 : {
796 0 : c = palette_19_1C_C[ix];
797 0 : m = palette_19_1C_M[ix];
798 0 : y = palette_19_1C_Y[ix];
799 0 : k = palette_19_1C_K[ix];
800 : }
801 0 : break;
802 : case 0x1d:
803 0 : if (ix < sizeof(palette_19_1D_C)/sizeof(palette_19_1D_C[0])
804 : && ix < sizeof(palette_19_1D_M)/sizeof(palette_19_1D_M[0])
805 : && ix < sizeof(palette_19_1D_Y)/sizeof(palette_19_1D_Y[0])
806 : && ix < sizeof(palette_19_1D_K)/sizeof(palette_19_1D_K[0]))
807 : {
808 0 : c = palette_19_1D_C[ix];
809 0 : m = palette_19_1D_M[ix];
810 0 : y = palette_19_1D_Y[ix];
811 0 : k = palette_19_1D_K[ix];
812 : }
813 0 : break;
814 : case 0x1e:
815 0 : if (ix > 0
816 : && ix <= sizeof(palette_19_1E_R)/sizeof(palette_19_1E_R[0])
817 : && ix <= sizeof(palette_19_1E_G)/sizeof(palette_19_1E_G[0])
818 : && ix <= sizeof(palette_19_1E_B)/sizeof(palette_19_1E_B[0]))
819 : {
820 0 : r = palette_19_1E_R[ix-1];
821 0 : g = palette_19_1E_G[ix-1];
822 0 : b = palette_19_1E_B[ix-1];
823 : }
824 0 : break;
825 : case 0x1f:
826 0 : if (ix > 0
827 : && ix <= sizeof(palette_19_1F_R)/sizeof(palette_19_1F_R[0])
828 : && ix <= sizeof(palette_19_1F_G)/sizeof(palette_19_1F_G[0])
829 : && ix <= sizeof(palette_19_1F_B)/sizeof(palette_19_1F_B[0]))
830 : {
831 0 : r = palette_19_1F_R[ix-1];
832 0 : g = palette_19_1F_G[ix-1];
833 0 : b = palette_19_1F_B[ix-1];
834 : }
835 0 : break;
836 : case 0x20:
837 0 : if (ix > 0
838 : && ix <= sizeof(palette_19_20_R)/sizeof(palette_19_20_R[0])
839 : && ix <= sizeof(palette_19_20_G)/sizeof(palette_19_20_G[0])
840 : && ix <= sizeof(palette_19_20_B)/sizeof(palette_19_20_B[0]))
841 : {
842 0 : r = palette_19_20_R[ix-1];
843 0 : g = palette_19_20_G[ix-1];
844 0 : b = palette_19_20_B[ix-1];
845 : }
846 0 : break;
847 : case 0x23:
848 0 : if (ix > 0
849 : && ix <= sizeof(palette_19_23_C)/sizeof(palette_19_23_C[0])
850 : && ix <= sizeof(palette_19_23_M)/sizeof(palette_19_23_M[0])
851 : && ix <= sizeof(palette_19_23_Y)/sizeof(palette_19_23_Y[0])
852 : && ix <= sizeof(palette_19_23_K)/sizeof(palette_19_23_K[0]))
853 : {
854 0 : c = palette_19_23_C[ix-1];
855 0 : m = palette_19_23_M[ix-1];
856 0 : y = palette_19_23_Y[ix-1];
857 0 : k = palette_19_23_K[ix-1];
858 : }
859 0 : break;
860 : case 0x24:
861 0 : if (ix > 0
862 : && ix <= sizeof(palette_19_24_C)/sizeof(palette_19_24_C[0])
863 : && ix <= sizeof(palette_19_24_M)/sizeof(palette_19_24_M[0])
864 : && ix <= sizeof(palette_19_24_Y)/sizeof(palette_19_24_Y[0])
865 : && ix <= sizeof(palette_19_24_K)/sizeof(palette_19_24_K[0]))
866 : {
867 0 : c = palette_19_24_C[ix-1];
868 0 : m = palette_19_24_M[ix-1];
869 0 : y = palette_19_24_Y[ix-1];
870 0 : k = palette_19_24_K[ix-1];
871 : }
872 0 : break;
873 : case 0x25:
874 0 : if (ix > 0
875 : && ix <= sizeof(palette_19_25_C)/sizeof(palette_19_25_C[0])
876 : && ix <= sizeof(palette_19_25_M)/sizeof(palette_19_25_M[0])
877 : && ix <= sizeof(palette_19_25_Y)/sizeof(palette_19_25_Y[0])
878 : && ix <= sizeof(palette_19_25_K)/sizeof(palette_19_25_K[0]))
879 : {
880 0 : c = palette_19_25_C[ix-1];
881 0 : m = palette_19_25_M[ix-1];
882 0 : y = palette_19_25_Y[ix-1];
883 0 : k = palette_19_25_K[ix-1];
884 : }
885 0 : break;
886 : default:
887 0 : colorValue = tint;
888 0 : colorValue <<= 16;
889 0 : colorValue |= ix;
890 0 : break;
891 : }
892 :
893 0 : switch (paletteID)
894 : {
895 : case 0x08:
896 : case 0x0a:
897 : case 0x0b:
898 : case 0x11:
899 : case 0x12:
900 : case 0x14:
901 : case 0x15:
902 : case 0x16:
903 : case 0x17:
904 : case 0x1a:
905 : case 0x1b:
906 : case 0x1c:
907 : case 0x1d:
908 : case 0x23:
909 : case 0x24:
910 : case 0x25:
911 : {
912 0 : colorModel = 0x02; // CMYK100
913 0 : unsigned cyan = (unsigned)tint * (unsigned)c / 100;
914 0 : unsigned magenta = (unsigned)tint * (unsigned)m / 100;
915 0 : unsigned yellow = (unsigned)tint * (unsigned)y / 100;
916 0 : unsigned black = (unsigned)tint * (unsigned)k / 100;
917 0 : colorValue = (black & 0xff);
918 0 : colorValue <<= 8;
919 0 : colorValue |= (yellow & 0xff);
920 0 : colorValue <<= 8;
921 0 : colorValue |= (magenta & 0xff);
922 0 : colorValue <<= 8;
923 0 : colorValue |= (cyan & 0xff);
924 0 : break;
925 : }
926 : case 0x1e:
927 : case 0x1f:
928 : case 0x20:
929 : {
930 0 : colorModel = 0x05; // RGB
931 0 : unsigned red = (unsigned)tint * (unsigned)r + 255 * (100 - tint);
932 0 : unsigned green = (unsigned)tint * (unsigned)g + 255 * (100 - tint);
933 0 : unsigned blue = (unsigned )tint * (unsigned)b + 255 * (100 - tint);
934 0 : red /= 100;
935 0 : green /= 100;
936 0 : blue /= 100;
937 0 : colorValue = (blue & 0xff);
938 0 : colorValue <<= 8;
939 0 : colorValue |= (green & 0xff);
940 0 : colorValue <<= 8;
941 0 : colorValue |= (red & 0xff);
942 0 : break;
943 : }
944 : case 0x09:
945 0 : colorModel = 0x12; // L*a*b
946 0 : break;
947 : default:
948 0 : break;
949 : }
950 : }
951 0 : else if (colorModel == 0x0e)
952 : {
953 0 : unsigned short paletteID = readU16(input);
954 0 : input->seek(4, WPX_SEEK_CUR);
955 0 : unsigned short ix = readU16(input);
956 0 : unsigned short tint = readU16(input);
957 0 : switch (paletteID)
958 : {
959 : case 0x0c:
960 0 : if (ix > 0
961 : && ix <= sizeof(palette_0E_0C_L)/sizeof(palette_0E_0C_L[0])
962 : && ix <= sizeof(palette_0E_0C_A)/sizeof(palette_0E_0C_A[0])
963 : && ix <= sizeof(palette_0E_0C_B)/sizeof(palette_0E_0C_B[0]))
964 : {
965 0 : colorValue = palette_0E_0C_B[ix-1];
966 0 : colorValue <<= 8;
967 0 : colorValue |= palette_0E_0C_A[ix-1];
968 0 : colorValue <<= 8;
969 0 : colorValue |= palette_0E_0C_L[ix-1];
970 : }
971 0 : break;
972 : case 0x18:
973 0 : if (ix > 0
974 : && ix <= sizeof(palette_0E_18_L)/sizeof(palette_0E_18_L[0])
975 : && ix <= sizeof(palette_0E_18_A)/sizeof(palette_0E_18_A[0])
976 : && ix <= sizeof(palette_0E_18_B)/sizeof(palette_0E_18_B[0]))
977 : {
978 0 : colorValue = palette_0E_18_B[ix-1];
979 0 : colorValue <<= 8;
980 0 : colorValue |= palette_0E_18_A[ix-1];
981 0 : colorValue <<= 8;
982 0 : colorValue |= palette_0E_18_L[ix-1];
983 : }
984 0 : break;
985 : case 0x21:
986 0 : if (ix > 0
987 : && ix <= sizeof(palette_0E_21_L)/sizeof(palette_0E_21_L[0])
988 : && ix <= sizeof(palette_0E_21_A)/sizeof(palette_0E_21_A[0])
989 : && ix <= sizeof(palette_0E_21_B)/sizeof(palette_0E_21_B[0]))
990 : {
991 0 : colorValue = palette_0E_21_B[ix-1];
992 0 : colorValue <<= 8;
993 0 : colorValue |= palette_0E_21_A[ix-1];
994 0 : colorValue <<= 8;
995 0 : colorValue |= palette_0E_21_L[ix-1];
996 : }
997 0 : break;
998 : case 0x22:
999 0 : if (ix > 0
1000 : && ix <= sizeof(palette_0E_22_L)/sizeof(palette_0E_22_L[0])
1001 : && ix <= sizeof(palette_0E_22_A)/sizeof(palette_0E_22_A[0])
1002 : && ix <= sizeof(palette_0E_22_B)/sizeof(palette_0E_22_B[0]))
1003 : {
1004 0 : colorValue = palette_0E_22_B[ix-1];
1005 0 : colorValue <<= 8;
1006 0 : colorValue |= palette_0E_22_A[ix-1];
1007 0 : colorValue <<= 8;
1008 0 : colorValue |= palette_0E_22_L[ix-1];
1009 : }
1010 0 : break;
1011 : default:
1012 0 : colorValue = tint;
1013 0 : colorValue <<= 16;
1014 0 : colorValue |= ix;
1015 0 : break;
1016 : }
1017 :
1018 0 : switch (paletteID)
1019 : {
1020 : case 0x0c:
1021 : case 0x18:
1022 : case 0x21:
1023 : case 0x22:
1024 0 : colorModel = 0x12; // L*a*b
1025 0 : break;
1026 : default:
1027 0 : break;
1028 : }
1029 : }
1030 : else
1031 : {
1032 0 : input->seek(6, WPX_SEEK_CUR);
1033 0 : colorValue = readU32(input);
1034 : }
1035 : }
1036 0 : else if (m_version >= 400)
1037 : {
1038 0 : colorModel = readU16(input);
1039 0 : unsigned short c = readU16(input);
1040 0 : unsigned short m = readU16(input);
1041 0 : unsigned short y = readU16(input);
1042 0 : unsigned short k = readU16(input);
1043 0 : colorValue = (k & 0xff);
1044 0 : colorValue <<= 8;
1045 0 : colorValue |= (y & 0xff);
1046 0 : colorValue <<= 8;
1047 0 : colorValue |= (m & 0xff);
1048 0 : colorValue <<= 8;
1049 0 : colorValue |= (c & 0xff);
1050 0 : input->seek(2, WPX_SEEK_CUR);
1051 : }
1052 : else
1053 : {
1054 0 : colorModel = readU8(input);
1055 0 : colorValue = readU32(input);
1056 : }
1057 0 : return libcdr::CDRColor(colorModel, colorValue);
1058 : }
1059 :
1060 0 : void libcdr::CDRParser::readRectangle(WPXInputStream *input)
1061 : {
1062 0 : double x0 = readRectCoord(input);
1063 0 : double y0 = readRectCoord(input);
1064 0 : double r3 = 0.0;
1065 0 : double r2 = 0.0;
1066 0 : double r1 = 0.0;
1067 0 : double r0 = 0.0;
1068 0 : unsigned int corner_type = 0;
1069 0 : double scaleX = 1.0;
1070 0 : double scaleY = 1.0;
1071 :
1072 0 : if (m_version < 1500)
1073 : {
1074 0 : r3 = readRectCoord(input);
1075 0 : r2 = m_version < 900 ? r3 : readRectCoord(input);
1076 0 : r1 = m_version < 900 ? r3 : readRectCoord(input);
1077 0 : r0 = m_version < 900 ? r3 : readRectCoord(input);
1078 : }
1079 : else
1080 : {
1081 0 : scaleX = readDouble(input);
1082 0 : scaleY = readDouble(input);
1083 0 : unsigned int scale_with = readU8(input);
1084 0 : input->seek(7, WPX_SEEK_CUR);
1085 0 : if (scale_with == 0)
1086 : {
1087 0 : r3 = readDouble(input);
1088 0 : corner_type = readU8(input);
1089 0 : input->seek(15, WPX_SEEK_CUR);
1090 0 : r2 = readDouble(input);
1091 0 : input->seek(16, WPX_SEEK_CUR);
1092 0 : r1 = readDouble(input);
1093 0 : input->seek(16, WPX_SEEK_CUR);
1094 0 : r0 = readDouble(input);
1095 :
1096 0 : double width = fabs(x0*scaleX / 2.0);
1097 0 : double height = fabs(y0*scaleY / 2.0);
1098 0 : r3 *= width < height ? width : height;
1099 0 : r2 *= width < height ? width : height;
1100 0 : r1 *= width < height ? width : height;
1101 0 : r0 *= width < height ? width : height;
1102 : }
1103 : else
1104 : {
1105 0 : r3 = readRectCoord(input);
1106 0 : corner_type = readU8(input);
1107 0 : input->seek(15, WPX_SEEK_CUR);
1108 0 : r2 = readRectCoord(input);
1109 0 : input->seek(16, WPX_SEEK_CUR);
1110 0 : r1 = readRectCoord(input);
1111 0 : input->seek(16, WPX_SEEK_CUR);
1112 0 : r0 = readRectCoord(input);
1113 : }
1114 : }
1115 0 : if (r0 > 0.0)
1116 0 : m_collector->collectMoveTo(0.0, -r0/scaleY);
1117 : else
1118 0 : m_collector->collectMoveTo(0.0, 0.0);
1119 0 : if (r1 > 0.0)
1120 : {
1121 0 : m_collector->collectLineTo(0.0, y0+r1/scaleY);
1122 0 : if (corner_type == 0)
1123 0 : m_collector->collectQuadraticBezier(0.0, y0, r1/scaleX, y0);
1124 0 : else if (corner_type == 1)
1125 0 : m_collector->collectQuadraticBezier(r1/scaleX, y0+r1/scaleY, r1/scaleX, y0);
1126 0 : else if (corner_type == 2)
1127 0 : m_collector->collectLineTo(r1/scaleX, y0);
1128 : }
1129 : else
1130 0 : m_collector->collectLineTo(0.0, y0);
1131 0 : if (r2 > 0.0)
1132 : {
1133 0 : m_collector->collectLineTo(x0-r2/scaleX, y0);
1134 0 : if (corner_type == 0)
1135 0 : m_collector->collectQuadraticBezier(x0, y0, x0, y0+r2/scaleY);
1136 0 : else if (corner_type == 1)
1137 0 : m_collector->collectQuadraticBezier(x0-r2/scaleX, y0+r2/scaleY, x0, y0+r2/scaleY);
1138 0 : else if (corner_type == 2)
1139 0 : m_collector->collectLineTo(x0, y0+r2/scaleY);
1140 : }
1141 : else
1142 0 : m_collector->collectLineTo(x0, y0);
1143 0 : if (r3 > 0.0)
1144 : {
1145 0 : m_collector->collectLineTo(x0, -r3/scaleY);
1146 0 : if (corner_type == 0)
1147 0 : m_collector->collectQuadraticBezier(x0, 0.0, x0-r3/scaleX, 0.0);
1148 0 : else if (corner_type == 1)
1149 0 : m_collector->collectQuadraticBezier(x0-r3/scaleX, -r3/scaleY, x0-r3/scaleX, 0.0);
1150 0 : else if (corner_type == 2)
1151 0 : m_collector->collectLineTo(x0-r3/scaleX, 0.0);
1152 : }
1153 : else
1154 0 : m_collector->collectLineTo(x0, 0.0);
1155 0 : if (r0 > 0.0)
1156 : {
1157 0 : m_collector->collectLineTo(r0/scaleX, 0.0);
1158 0 : if (corner_type == 0)
1159 0 : m_collector->collectQuadraticBezier(0.0, 0.0, 0.0, -r0/scaleY);
1160 0 : else if (corner_type == 1)
1161 0 : m_collector->collectQuadraticBezier(r0/scaleX, -r0/scaleY, 0.0, -r0/scaleY);
1162 0 : else if (corner_type == 2)
1163 0 : m_collector->collectLineTo(0.0, -r0/scaleY);
1164 : }
1165 : else
1166 0 : m_collector->collectLineTo(0.0, 0.0);
1167 0 : m_collector->collectClosePath();
1168 0 : }
1169 :
1170 0 : void libcdr::CDRParser::readEllipse(WPXInputStream *input)
1171 : {
1172 : CDR_DEBUG_MSG(("CDRParser::readEllipse\n"));
1173 :
1174 0 : double x = readCoordinate(input);
1175 0 : double y = readCoordinate(input);
1176 0 : double angle1 = readAngle(input);
1177 0 : double angle2 = readAngle(input);
1178 0 : bool pie(0 != readUnsigned(input));
1179 :
1180 0 : double cx = x/2.0;
1181 0 : double cy = y/2.0;
1182 0 : double rx = fabs(cx);
1183 0 : double ry = fabs(cy);
1184 :
1185 0 : if (angle1 != angle2)
1186 : {
1187 0 : if (angle2 < angle1)
1188 0 : angle2 += 2*M_PI;
1189 0 : double x0 = cx + rx*cos(angle1);
1190 0 : double y0 = cy - ry*sin(angle1);
1191 :
1192 0 : double x1 = cx + rx*cos(angle2);
1193 0 : double y1 = cy - ry*sin(angle2);
1194 :
1195 0 : bool largeArc = (angle2 - angle1 > M_PI || angle2 - angle1 < -M_PI);
1196 :
1197 0 : m_collector->collectMoveTo(x0, y0);
1198 0 : m_collector->collectArcTo(rx, ry, largeArc, true, x1, y1);
1199 0 : if (pie)
1200 : {
1201 0 : m_collector->collectLineTo(cx, cy);
1202 0 : m_collector->collectLineTo(x0, y0);
1203 0 : m_collector->collectClosePath();
1204 : }
1205 : }
1206 : else
1207 : {
1208 0 : double x0 = cx + rx;
1209 0 : double y0 = cy;
1210 :
1211 0 : double x1 = cx;
1212 0 : double y1 = cy - ry;
1213 :
1214 0 : m_collector->collectMoveTo(x0, y0);
1215 0 : m_collector->collectArcTo(rx, ry, false, true, x1, y1);
1216 0 : m_collector->collectArcTo(rx, ry, true, true, x0, y0);
1217 0 : m_collector->collectClosePath();
1218 : }
1219 0 : }
1220 :
1221 0 : void libcdr::CDRParser::readDisp(WPXInputStream *input, unsigned length)
1222 : {
1223 0 : if (!_redirectX6Chunk(&input, length))
1224 0 : throw GenericException();
1225 : #if DUMP_PREVIEW_IMAGE
1226 : WPXBinaryData previewImage;
1227 : previewImage.append(0x42);
1228 : previewImage.append(0x4d);
1229 :
1230 : previewImage.append((unsigned char)((length+8) & 0x000000ff));
1231 : previewImage.append((unsigned char)(((length+8) & 0x0000ff00) >> 8));
1232 : previewImage.append((unsigned char)(((length+8) & 0x00ff0000) >> 16));
1233 : previewImage.append((unsigned char)(((length+8) & 0xff000000) >> 24));
1234 :
1235 : previewImage.append(0x00);
1236 : previewImage.append(0x00);
1237 : previewImage.append(0x00);
1238 : previewImage.append(0x00);
1239 :
1240 : long startPosition = input->tell();
1241 : input->seek(0x18, WPX_SEEK_CUR);
1242 : int lengthX = length + 10 - readU32(input);
1243 : input->seek(startPosition, WPX_SEEK_SET);
1244 :
1245 : previewImage.append((unsigned char)((lengthX) & 0x000000ff));
1246 : previewImage.append((unsigned char)(((lengthX) & 0x0000ff00) >> 8));
1247 : previewImage.append((unsigned char)(((lengthX) & 0x00ff0000) >> 16));
1248 : previewImage.append((unsigned char)(((lengthX) & 0xff000000) >> 24));
1249 :
1250 : input->seek(4, WPX_SEEK_CUR);
1251 : for (unsigned i = 4; i<length; i++)
1252 : previewImage.append(readU8(input));
1253 : FILE *f = fopen("previewImage.bmp", "wb");
1254 : if (f)
1255 : {
1256 : const unsigned char *tmpBuffer = previewImage.getDataBuffer();
1257 : for (unsigned long k = 0; k < previewImage.size(); k++)
1258 : fprintf(f, "%c",tmpBuffer[k]);
1259 : fclose(f);
1260 : }
1261 : #endif
1262 0 : }
1263 :
1264 0 : void libcdr::CDRParser::readLineAndCurve(WPXInputStream *input)
1265 : {
1266 : CDR_DEBUG_MSG(("CDRParser::readLineAndCurve\n"));
1267 :
1268 0 : unsigned short pointNum = readU16(input);
1269 0 : input->seek(2, WPX_SEEK_CUR);
1270 0 : std::vector<std::pair<double, double> > points;
1271 0 : std::vector<unsigned char> pointTypes;
1272 0 : for (unsigned j=0; j<pointNum; j++)
1273 : {
1274 0 : std::pair<double, double> point;
1275 0 : point.first = (double)readCoordinate(input);
1276 0 : point.second = (double)readCoordinate(input);
1277 0 : points.push_back(point);
1278 : }
1279 0 : for (unsigned k=0; k<pointNum; k++)
1280 0 : pointTypes.push_back(readU8(input));
1281 0 : outputPath(points, pointTypes);
1282 0 : }
1283 :
1284 0 : void libcdr::CDRParser::readPath(WPXInputStream *input)
1285 : {
1286 : CDR_DEBUG_MSG(("CDRParser::readPath\n"));
1287 :
1288 0 : input->seek(4, WPX_SEEK_CUR);
1289 0 : unsigned short pointNum = readU16(input)+readU16(input);
1290 0 : input->seek(16, WPX_SEEK_CUR);
1291 0 : std::vector<std::pair<double, double> > points;
1292 0 : std::vector<unsigned char> pointTypes;
1293 0 : for (unsigned j=0; j<pointNum; j++)
1294 : {
1295 0 : std::pair<double, double> point;
1296 0 : point.first = (double)readCoordinate(input);
1297 0 : point.second = (double)readCoordinate(input);
1298 0 : points.push_back(point);
1299 : }
1300 0 : for (unsigned k=0; k<pointNum; k++)
1301 0 : pointTypes.push_back(readU8(input));
1302 0 : outputPath(points, pointTypes);
1303 0 : }
1304 :
1305 0 : void libcdr::CDRParser::readBitmap(WPXInputStream *input)
1306 : {
1307 : CDR_DEBUG_MSG(("CDRParser::readBitmap\n"));
1308 :
1309 0 : double x1 = 0.0;
1310 0 : double y1 = 0.0;
1311 0 : double x2 = 0.0;
1312 0 : double y2 = 0.0;
1313 0 : unsigned imageId = 0;
1314 0 : if (m_version < 600)
1315 : {
1316 0 : x1 = readCoordinate(input);
1317 0 : y1 = readCoordinate(input);
1318 0 : x2 = 0.0;
1319 0 : y2 = 0.0;
1320 0 : if (m_version < 400)
1321 0 : input->seek(2, WPX_SEEK_CUR);
1322 0 : input->seek(8, WPX_SEEK_CUR);
1323 0 : imageId = readUnsigned(input);
1324 0 : input->seek(20, WPX_SEEK_CUR);
1325 0 : m_collector->collectMoveTo(x1, y1);
1326 0 : m_collector->collectLineTo(x1, y2);
1327 0 : m_collector->collectLineTo(x2, y2);
1328 0 : m_collector->collectLineTo(x2, y1);
1329 0 : m_collector->collectLineTo(x1, y1);
1330 : }
1331 : else
1332 : {
1333 0 : x1 = (double)readCoordinate(input);
1334 0 : y1 = (double)readCoordinate(input);
1335 0 : x2 = (double)readCoordinate(input);
1336 0 : y2 = (double)readCoordinate(input);
1337 0 : input->seek(16, WPX_SEEK_CUR);
1338 :
1339 0 : input->seek(16, WPX_SEEK_CUR);
1340 0 : imageId = readUnsigned(input);
1341 0 : if (m_version < 800)
1342 0 : input->seek(8, WPX_SEEK_CUR);
1343 0 : else if (m_version >= 800 && m_version < 900)
1344 0 : input->seek(12, WPX_SEEK_CUR);
1345 : else
1346 0 : input->seek(20, WPX_SEEK_CUR);
1347 :
1348 0 : unsigned short pointNum = readU16(input);
1349 0 : input->seek(2, WPX_SEEK_CUR);
1350 0 : std::vector<std::pair<double, double> > points;
1351 0 : std::vector<unsigned char> pointTypes;
1352 0 : for (unsigned j=0; j<pointNum; j++)
1353 : {
1354 0 : std::pair<double, double> point;
1355 0 : point.first = (double)readCoordinate(input);
1356 0 : point.second = (double)readCoordinate(input);
1357 0 : points.push_back(point);
1358 : }
1359 0 : for (unsigned k=0; k<pointNum; k++)
1360 0 : pointTypes.push_back(readU8(input));
1361 0 : outputPath(points, pointTypes);
1362 : }
1363 0 : m_collector->collectBitmap(imageId, x1, x2, y1, y2);
1364 0 : }
1365 :
1366 0 : void libcdr::CDRParser::readWaldoOutl(WPXInputStream *input)
1367 : {
1368 0 : if (m_version >= 400)
1369 0 : return;
1370 0 : unsigned short lineType = readU8(input);
1371 0 : lineType <<= 1;
1372 0 : double lineWidth = (double)readCoordinate(input);
1373 0 : double stretch = (double)readU16(input) / 100.0;
1374 0 : double angle = readAngle(input);
1375 0 : libcdr::CDRColor color = readColor(input);
1376 0 : input->seek(7, WPX_SEEK_CUR);
1377 0 : unsigned short numDash = readU8(input);
1378 0 : int fixPosition = input->tell();
1379 0 : std::vector<unsigned> dashArray;
1380 0 : for (unsigned short i = 0; i < numDash; ++i)
1381 0 : dashArray.push_back(readU8(input));
1382 0 : input->seek(fixPosition + 10, WPX_SEEK_SET);
1383 0 : unsigned short joinType = readU16(input);
1384 0 : unsigned short capsType = readU16(input);
1385 0 : unsigned startMarkerId = readU32(input);
1386 0 : unsigned endMarkerId = readU32(input);
1387 0 : m_collector->collectOutl(++m_outlId, lineType, capsType, joinType, lineWidth, stretch, angle, color, dashArray, startMarkerId, endMarkerId);
1388 0 : m_collector->collectOutlId(m_outlId);
1389 : }
1390 :
1391 0 : void libcdr::CDRParser::readWaldoFill(WPXInputStream *input)
1392 : {
1393 0 : if (m_version >= 400)
1394 0 : return;
1395 0 : unsigned short fillType = readU8(input);
1396 0 : libcdr::CDRColor color1;
1397 0 : libcdr::CDRColor color2;
1398 0 : libcdr::CDRImageFill imageFill;
1399 0 : libcdr::CDRGradient gradient;
1400 0 : switch (fillType)
1401 : {
1402 : case 1: // Solid
1403 : {
1404 0 : color1 = readColor(input);
1405 : }
1406 0 : break;
1407 : case 2: // Linear Gradient
1408 : {
1409 0 : gradient.m_type = 1;
1410 0 : gradient.m_angle = readAngle(input);
1411 0 : color1 = readColor(input);
1412 0 : color2 = readColor(input);
1413 0 : if (m_version >= 200)
1414 : {
1415 0 : input->seek(7, WPX_SEEK_CUR);
1416 0 : gradient.m_edgeOffset = readS16(input);
1417 0 : gradient.m_centerXOffset = readInteger(input);
1418 0 : gradient.m_centerYOffset = readInteger(input);
1419 : }
1420 0 : libcdr::CDRGradientStop stop;
1421 0 : stop.m_color = color1;
1422 0 : stop.m_offset = 0.0;
1423 0 : gradient.m_stops.push_back(stop);
1424 0 : stop.m_color = color2;
1425 0 : stop.m_offset = 1.0;
1426 0 : gradient.m_stops.push_back(stop);
1427 : }
1428 0 : break;
1429 : case 4: // Radial Gradient
1430 : {
1431 0 : gradient.m_type = 2;
1432 0 : fillType = 2;
1433 0 : gradient.m_angle = readAngle(input);
1434 0 : color1 = readColor(input);
1435 0 : color2 = readColor(input);
1436 0 : if (m_version >= 200)
1437 : {
1438 0 : input->seek(7, WPX_SEEK_CUR);
1439 0 : gradient.m_edgeOffset = readS16(input);
1440 0 : gradient.m_centerXOffset = readInteger(input);
1441 0 : gradient.m_centerYOffset = readInteger(input);
1442 : }
1443 0 : libcdr::CDRGradientStop stop;
1444 0 : stop.m_color = color1;
1445 0 : stop.m_offset = 0.0;
1446 0 : gradient.m_stops.push_back(stop);
1447 0 : stop.m_color = color2;
1448 0 : stop.m_offset = 1.0;
1449 0 : gradient.m_stops.push_back(stop);
1450 : }
1451 0 : break;
1452 : case 7: // Pattern
1453 : {
1454 0 : unsigned patternId = m_version < 300 ? readU16(input) : readU32(input);
1455 0 : double patternWidth = readCoordinate(input);
1456 0 : double patternHeight = readCoordinate(input);
1457 0 : double tileOffsetX = (double)readU16(input) / 100.0;
1458 0 : double tileOffsetY = (double)readU16(input) / 100.0;
1459 0 : double rcpOffset = (double)readU16(input) / 100.0;
1460 0 : input->seek(1, WPX_SEEK_CUR);
1461 0 : color1 = readColor(input);
1462 0 : color2 = readColor(input);
1463 0 : imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, false, tileOffsetX, tileOffsetY, rcpOffset, 0);
1464 : }
1465 0 : break;
1466 : case 10: // Full color
1467 : {
1468 0 : unsigned patternId = readU16(input);
1469 0 : double patternWidth = readCoordinate(input);
1470 0 : double patternHeight = readCoordinate(input);
1471 0 : double tileOffsetX = (double)readU16(input) / 100.0;
1472 0 : double tileOffsetY = (double)readU16(input) / 100.0;
1473 0 : double rcpOffset = (double)readU16(input) / 100.0;
1474 0 : input->seek(1, WPX_SEEK_CUR);
1475 0 : imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, false, tileOffsetX, tileOffsetY, rcpOffset, 0);
1476 : }
1477 0 : break;
1478 : default:
1479 0 : break;
1480 : }
1481 0 : m_collector->collectFild(++m_fillId, fillType, color1, color2, gradient, imageFill);
1482 0 : m_collector->collectFildId(m_fillId);
1483 : }
1484 :
1485 0 : void libcdr::CDRParser::readTrfd(WPXInputStream *input, unsigned length)
1486 : {
1487 0 : if (!_redirectX6Chunk(&input, length))
1488 0 : throw GenericException();
1489 0 : long startPosition = input->tell();
1490 0 : unsigned chunkLength = readUnsigned(input);
1491 0 : unsigned numOfArgs = readUnsigned(input);
1492 0 : unsigned startOfArgs = readUnsigned(input);
1493 0 : std::vector<unsigned> argOffsets(numOfArgs, 0);
1494 0 : unsigned i = 0;
1495 0 : input->seek(startPosition+startOfArgs, WPX_SEEK_SET);
1496 0 : while (i<numOfArgs)
1497 0 : argOffsets[i++] = readUnsigned(input);
1498 :
1499 0 : CDRTransforms trafos;
1500 0 : for (i=0; i < argOffsets.size(); i++)
1501 : {
1502 0 : input->seek(startPosition+argOffsets[i], WPX_SEEK_SET);
1503 0 : if (m_version >= 1300)
1504 0 : input->seek(8, WPX_SEEK_CUR);
1505 0 : unsigned short tmpType = readU16(input);
1506 0 : if (tmpType == 0x08) // trafo
1507 : {
1508 0 : double v0 = 0.0;
1509 0 : double v1 = 0.0;
1510 0 : double x0 = 0.0;
1511 0 : double v3 = 0.0;
1512 0 : double v4 = 0.0;
1513 0 : double y0 = 0.0;
1514 0 : if (m_version >= 600)
1515 0 : input->seek(6, WPX_SEEK_CUR);
1516 0 : if (m_version >= 500)
1517 : {
1518 0 : v0 = readDouble(input);
1519 0 : v1 = readDouble(input);
1520 0 : x0 = readDouble(input) / (m_version < 600 ? 1000.0 : 254000.0);
1521 0 : v3 = readDouble(input);
1522 0 : v4 = readDouble(input);
1523 0 : y0 = readDouble(input) / (m_version < 600 ? 1000.0 : 254000.0);
1524 : }
1525 : else
1526 : {
1527 0 : v0 = readFixedPoint(input);
1528 0 : v1 = readFixedPoint(input);
1529 0 : x0 = (double)readS32(input) / 1000.0;
1530 0 : v3 = readFixedPoint(input);
1531 0 : v4 = readFixedPoint(input);
1532 0 : y0 = (double)readS32(input) / 1000.0;
1533 : }
1534 0 : trafos.append(v0, v1, x0, v3, v4, y0);
1535 : }
1536 : else if (tmpType == 0x10)
1537 : {
1538 : #if 0
1539 : input->seek(6, WPX_SEEK_CUR);
1540 : unsigned short type = readU16(input);
1541 : double x = readCoordinate(input);
1542 : double y = readCoordinate(input);
1543 : unsigned subType = readU32(input);
1544 : if (!subType)
1545 : {
1546 : }
1547 : else
1548 : {
1549 : if (subType&1) // Smooth
1550 : {
1551 : }
1552 : if (subType&2) // Random
1553 : {
1554 : }
1555 : if (subType&4) // Local
1556 : {
1557 : }
1558 : }
1559 : unsigned opt1 = readU32(input);
1560 : unsigned opt2 = readU32(input);
1561 : #endif
1562 : }
1563 : }
1564 0 : if (!trafos.empty())
1565 0 : m_collector->collectTransform(trafos,m_version < 400);
1566 0 : input->seek(startPosition+chunkLength, WPX_SEEK_SET);
1567 0 : }
1568 :
1569 0 : void libcdr::CDRParser::readFild(WPXInputStream *input, unsigned length)
1570 : {
1571 0 : if (!_redirectX6Chunk(&input, length))
1572 0 : throw GenericException();
1573 0 : unsigned fillId = readU32(input);
1574 0 : unsigned short v13flag = 0;
1575 0 : if (m_version >= 1300)
1576 : {
1577 0 : input->seek(4, WPX_SEEK_CUR);
1578 0 : v13flag = readU16(input);
1579 0 : input->seek(2, WPX_SEEK_CUR);
1580 : }
1581 0 : unsigned short fillType = readU16(input);
1582 0 : libcdr::CDRColor color1;
1583 0 : libcdr::CDRColor color2;
1584 0 : libcdr::CDRImageFill imageFill;
1585 0 : libcdr::CDRGradient gradient;
1586 0 : switch (fillType)
1587 : {
1588 : case 1: // Solid
1589 : {
1590 0 : if (m_version >= 1300)
1591 0 : input->seek(13, WPX_SEEK_CUR);
1592 : else
1593 0 : input->seek(2, WPX_SEEK_CUR);
1594 0 : color1 = readColor(input);
1595 : }
1596 0 : break;
1597 : case 2: // Gradient
1598 : {
1599 0 : if (m_version >= 1300)
1600 0 : input->seek(8, WPX_SEEK_CUR);
1601 : else
1602 0 : input->seek(2, WPX_SEEK_CUR);
1603 0 : gradient.m_type = readU8(input);
1604 0 : if (m_version >= 1300)
1605 : {
1606 0 : input->seek(17, WPX_SEEK_CUR);
1607 0 : gradient.m_edgeOffset = readS16(input);
1608 : }
1609 0 : else if (m_version >= 600)
1610 : {
1611 0 : input->seek(19, WPX_SEEK_CUR);
1612 0 : gradient.m_edgeOffset = readS32(input);
1613 : }
1614 : else
1615 : {
1616 0 : input->seek(11, WPX_SEEK_CUR);
1617 0 : gradient.m_edgeOffset = readS16(input);
1618 : }
1619 0 : gradient.m_angle = readAngle(input);
1620 0 : gradient.m_centerXOffset = readInteger(input);
1621 0 : gradient.m_centerYOffset = readInteger(input);
1622 0 : if (m_version >= 600)
1623 0 : input->seek(2, WPX_SEEK_CUR);
1624 0 : gradient.m_mode = (unsigned short)(readUnsigned(input) & 0xffff);
1625 0 : gradient.m_midPoint = (double)readU8(input) / 100.0;
1626 0 : input->seek(1, WPX_SEEK_CUR);
1627 0 : unsigned short numStops = (unsigned short)(readUnsigned(input) & 0xffff);
1628 0 : if (m_version >= 1300)
1629 0 : input->seek(3, WPX_SEEK_CUR);
1630 0 : for (unsigned short i = 0; i < numStops; ++i)
1631 : {
1632 0 : libcdr::CDRGradientStop stop;
1633 0 : stop.m_color = readColor(input);
1634 0 : if (m_version >= 1300)
1635 : {
1636 0 : if (v13flag == 0x9e || (m_version >= 1600 && v13flag == 0x96))
1637 0 : input->seek(26, WPX_SEEK_CUR);
1638 : else
1639 0 : input->seek(5, WPX_SEEK_CUR);
1640 : }
1641 0 : stop.m_offset = (double)readUnsigned(input) / 100.0;
1642 0 : if (m_version >= 1300)
1643 0 : input->seek(3, WPX_SEEK_CUR);
1644 0 : gradient.m_stops.push_back(stop);
1645 : }
1646 : }
1647 0 : break;
1648 : case 7: // Pattern
1649 : {
1650 0 : if (m_version >= 1300)
1651 0 : input->seek(8, WPX_SEEK_CUR);
1652 : else
1653 0 : input->seek(2, WPX_SEEK_CUR);
1654 0 : unsigned patternId = readU32(input);
1655 0 : int tmpWidth = readInteger(input);
1656 0 : int tmpHeight = readInteger(input);
1657 0 : double tileOffsetX = 0.0;
1658 0 : double tileOffsetY = 0.0;
1659 0 : if (m_version < 900)
1660 : {
1661 0 : tileOffsetX = (double)readU16(input) / 100.0;
1662 0 : tileOffsetY = (double)readU16(input) / 100.0;
1663 : }
1664 : else
1665 0 : input->seek(4, WPX_SEEK_CUR);
1666 0 : double rcpOffset = (double)readU16(input) / 100.0;
1667 0 : unsigned char flags = readU8(input);
1668 0 : double patternWidth = (double)tmpWidth / (m_version < 600 ? 1000.0 : 254000.0);
1669 0 : double patternHeight = (double)tmpHeight / (m_version < 600 ? 1000.0 : 254000.0);
1670 0 : bool isRelative = false;
1671 0 : if ((flags & 0x04) && (m_version < 900))
1672 : {
1673 0 : isRelative = true;
1674 0 : patternWidth = (double)tmpWidth / 100.0;
1675 0 : patternHeight = (double)tmpHeight / 100.0;
1676 : }
1677 0 : if (m_version >= 1300)
1678 0 : input->seek(6, WPX_SEEK_CUR);
1679 : else
1680 0 : input->seek(1, WPX_SEEK_CUR);
1681 0 : color1 = readColor(input);
1682 0 : if (m_version >= 1300)
1683 : {
1684 0 : if (v13flag == 0x94 || (m_version >= 1600 && v13flag == 0x8c))
1685 0 : input->seek(31, WPX_SEEK_CUR);
1686 : else
1687 0 : input->seek(10, WPX_SEEK_CUR);
1688 : }
1689 0 : color2 = readColor(input);
1690 0 : imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1691 : }
1692 0 : break;
1693 : case 9: // bitmap
1694 : {
1695 0 : if (m_version < 600)
1696 0 : fillType = 10;
1697 0 : input->seek(2, WPX_SEEK_CUR);
1698 0 : unsigned patternId = readUnsigned(input);
1699 0 : if (m_version >= 1600)
1700 0 : input->seek(26, WPX_SEEK_CUR);
1701 0 : else if (m_version >= 1300)
1702 0 : input->seek(2, WPX_SEEK_CUR);
1703 0 : int tmpWidth = readUnsigned(input);
1704 0 : int tmpHeight = readUnsigned(input);
1705 0 : double tileOffsetX = 0.0;
1706 0 : double tileOffsetY = 0.0;
1707 0 : if (m_version < 900)
1708 : {
1709 0 : tileOffsetX = (double)readU16(input) / 100.0;
1710 0 : tileOffsetY = (double)readU16(input) / 100.0;
1711 : }
1712 : else
1713 0 : input->seek(4, WPX_SEEK_CUR);
1714 0 : double rcpOffset = (double)readU16(input) / 100.0;
1715 0 : unsigned char flags = readU8(input);
1716 0 : double patternWidth = (double)tmpWidth / (m_version < 600 ? 1000.0 :254000.0);
1717 0 : double patternHeight = (double)tmpHeight / (m_version < 600 ? 1000.0 :254000.0);
1718 0 : bool isRelative = false;
1719 0 : if ((flags & 0x04) && (m_version < 900))
1720 : {
1721 0 : isRelative = true;
1722 0 : patternWidth = (double)tmpWidth / 100.0;
1723 0 : patternHeight = (double)tmpHeight / 100.0;
1724 : }
1725 0 : if (m_version >= 1300)
1726 0 : input->seek(17, WPX_SEEK_CUR);
1727 : else
1728 0 : input->seek(21, WPX_SEEK_CUR);
1729 0 : if (m_version >= 600)
1730 0 : patternId = readUnsigned(input);
1731 0 : imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1732 : }
1733 0 : break;
1734 : case 10: // Full color
1735 : {
1736 0 : if (m_version >= 1300)
1737 : {
1738 0 : if (v13flag == 0x4e)
1739 0 : input->seek(28, WPX_SEEK_CUR);
1740 : else
1741 0 : input->seek(4, WPX_SEEK_CUR);
1742 : }
1743 : else
1744 0 : input->seek(2, WPX_SEEK_CUR);
1745 0 : unsigned patternId = readUnsigned(input);
1746 0 : int tmpWidth = readUnsigned(input);
1747 0 : int tmpHeight = readUnsigned(input);
1748 0 : double tileOffsetX = 0.0;
1749 0 : double tileOffsetY = 0.0;
1750 0 : if (m_version < 900)
1751 : {
1752 0 : tileOffsetX = (double)readU16(input) / 100.0;
1753 0 : tileOffsetY = (double)readU16(input) / 100.0;
1754 : }
1755 : else
1756 0 : input->seek(4, WPX_SEEK_CUR);
1757 0 : double rcpOffset = (double)readU16(input) / 100.0;
1758 0 : unsigned char flags = readU8(input);
1759 0 : double patternWidth = (double)tmpWidth / (m_version < 600 ? 1000.0 :254000.0);
1760 0 : double patternHeight = (double)tmpHeight / (m_version < 600 ? 1000.0 :254000.0);
1761 0 : bool isRelative = false;
1762 0 : if ((flags & 0x04) && (m_version < 900))
1763 : {
1764 0 : isRelative = true;
1765 0 : patternWidth = (double)tmpWidth / 100.0;
1766 0 : patternHeight = (double)tmpHeight / 100.0;
1767 : }
1768 0 : if (m_version >= 1300)
1769 0 : input->seek(17, WPX_SEEK_CUR);
1770 : else
1771 0 : input->seek(21, WPX_SEEK_CUR);
1772 0 : if (m_version >= 600)
1773 0 : patternId = readUnsigned(input);
1774 0 : imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1775 : }
1776 0 : break;
1777 : case 11: // Texture
1778 : {
1779 0 : if (m_version < 600)
1780 0 : fillType = 10;
1781 0 : if (m_version >= 1300)
1782 : {
1783 0 : if (v13flag == 0x18e)
1784 0 : input->seek(36, WPX_SEEK_CUR);
1785 : else
1786 0 : input->seek(1, WPX_SEEK_CUR);
1787 : }
1788 : else
1789 0 : input->seek(2, WPX_SEEK_CUR);
1790 0 : unsigned patternId = readU32(input);
1791 0 : double patternWidth = 1.0;
1792 0 : double patternHeight = 1.0;
1793 0 : bool isRelative = true;
1794 0 : double tileOffsetX = 0.0;
1795 0 : double tileOffsetY = 0.0;
1796 0 : double rcpOffset = 0.0;
1797 0 : unsigned char flags = 0;
1798 0 : if (m_version >= 600)
1799 : {
1800 0 : int tmpWidth = readUnsigned(input);
1801 0 : int tmpHeight = readUnsigned(input);
1802 0 : if (m_version < 900)
1803 : {
1804 0 : tileOffsetX = (double)readU16(input) / 100.0;
1805 0 : tileOffsetY = (double)readU16(input) / 100.0;
1806 : }
1807 : else
1808 0 : input->seek(4, WPX_SEEK_CUR);
1809 0 : rcpOffset = (double)readU16(input) / 100.0;
1810 0 : flags = readU8(input);
1811 0 : patternWidth = (double)tmpWidth / (m_version < 600 ? 1000.0 :254000.0);
1812 0 : patternHeight = (double)tmpHeight / (m_version < 600 ? 1000.0 :254000.0);
1813 0 : isRelative = false;
1814 0 : if ((flags & 0x04) && (m_version < 900))
1815 : {
1816 0 : isRelative = true;
1817 0 : patternWidth = (double)tmpWidth / 100.0;
1818 0 : patternHeight = (double)tmpHeight / 100.0;
1819 : }
1820 0 : if (m_version >= 1300)
1821 0 : input->seek(17, WPX_SEEK_CUR);
1822 : else
1823 0 : input->seek(21, WPX_SEEK_CUR);
1824 0 : if (m_version >= 600)
1825 0 : patternId = readUnsigned(input);
1826 : }
1827 0 : imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1828 : }
1829 0 : break;
1830 : default:
1831 0 : break;
1832 : }
1833 0 : m_collector->collectFild(fillId, fillType, color1, color2, gradient, imageFill);
1834 0 : }
1835 :
1836 0 : void libcdr::CDRParser::readOutl(WPXInputStream *input, unsigned length)
1837 : {
1838 0 : if (!_redirectX6Chunk(&input, length))
1839 0 : throw GenericException();
1840 0 : unsigned lineId = readU32(input);
1841 0 : if (m_version >= 1300)
1842 : {
1843 0 : unsigned id = 0;
1844 0 : unsigned lngth = 0;
1845 0 : while (id != 1)
1846 : {
1847 0 : input->seek(lngth, WPX_SEEK_CUR);
1848 0 : id = readU32(input);
1849 0 : lngth = readU32(input);
1850 : }
1851 : }
1852 0 : unsigned short lineType = readU16(input);
1853 0 : unsigned short capsType = readU16(input);
1854 0 : unsigned short joinType = readU16(input);
1855 0 : if (m_version < 1300 && m_version >= 600)
1856 0 : input->seek(2, WPX_SEEK_CUR);
1857 0 : double lineWidth = (double)readCoordinate(input);
1858 0 : double stretch = (double)readU16(input) / 100.0;
1859 0 : if (m_version >= 600)
1860 0 : input->seek(2, WPX_SEEK_CUR);
1861 0 : double angle = readAngle(input);
1862 0 : if (m_version >= 1300)
1863 0 : input->seek(46, WPX_SEEK_CUR);
1864 0 : else if (m_version >= 600)
1865 0 : input->seek(52, WPX_SEEK_CUR);
1866 0 : libcdr::CDRColor color = readColor(input);
1867 0 : if (m_version < 600)
1868 0 : input->seek(10, WPX_SEEK_CUR);
1869 : else
1870 0 : input->seek(16, WPX_SEEK_CUR);
1871 0 : unsigned short numDash = readU16(input);
1872 0 : int fixPosition = input->tell();
1873 0 : std::vector<unsigned> dashArray;
1874 0 : for (unsigned short i = 0; i < numDash; ++i)
1875 0 : dashArray.push_back(readU16(input));
1876 0 : if (m_version < 600)
1877 0 : input->seek(fixPosition + 20, WPX_SEEK_SET);
1878 : else
1879 0 : input->seek(fixPosition + 22, WPX_SEEK_SET);
1880 0 : unsigned startMarkerId = readU32(input);
1881 0 : unsigned endMarkerId = readU32(input);
1882 0 : m_collector->collectOutl(lineId, lineType, capsType, joinType, lineWidth, stretch, angle, color, dashArray, startMarkerId, endMarkerId);
1883 0 : }
1884 :
1885 0 : void libcdr::CDRParser::readLoda(WPXInputStream *input, unsigned length)
1886 : {
1887 0 : if (!_redirectX6Chunk(&input, length))
1888 0 : throw GenericException();
1889 0 : long startPosition = input->tell();
1890 0 : unsigned chunkLength = readUnsigned(input);
1891 0 : unsigned numOfArgs = readUnsigned(input);
1892 0 : unsigned startOfArgs = readUnsigned(input);
1893 0 : unsigned startOfArgTypes = readUnsigned(input);
1894 0 : unsigned chunkType = readUnsigned(input);
1895 0 : if (chunkType == 0x26)
1896 0 : m_collector->collectSpline();
1897 0 : std::vector<unsigned> argOffsets(numOfArgs, 0);
1898 0 : std::vector<unsigned> argTypes(numOfArgs, 0);
1899 0 : unsigned i = 0;
1900 0 : input->seek(startPosition+startOfArgs, WPX_SEEK_SET);
1901 0 : while (i<numOfArgs)
1902 0 : argOffsets[i++] = readUnsigned(input);
1903 0 : input->seek(startPosition+startOfArgTypes, WPX_SEEK_SET);
1904 0 : while (i>0)
1905 0 : argTypes[--i] = readUnsigned(input);
1906 :
1907 0 : for (i=0; i < argTypes.size(); i++)
1908 : {
1909 0 : input->seek(startPosition+argOffsets[i], WPX_SEEK_SET);
1910 0 : if (argTypes[i] == 0x1e) // loda coords
1911 : {
1912 0 : if ((m_version >= 400 && chunkType == 0x01) || (m_version < 400 && chunkType == 0x00)) // Rectangle
1913 0 : readRectangle(input);
1914 0 : else if ((m_version >= 400 && chunkType == 0x02) || (m_version < 400 && chunkType == 0x01)) // Ellipse
1915 0 : readEllipse(input);
1916 0 : else if ((m_version >= 400 && chunkType == 0x03) || (m_version < 400 && chunkType == 0x02)) // Line and curve
1917 0 : readLineAndCurve(input);
1918 0 : else if (chunkType == 0x25) // Path
1919 0 : readPath(input);
1920 0 : else if ((m_version >= 400 && chunkType == 0x04) || (m_version < 400 && chunkType == 0x03)) // Artistic text
1921 0 : m_collector->collectArtisticText();
1922 0 : else if ((m_version >= 400 && chunkType == 0x05) || (m_version < 400 && chunkType == 0x04)) // Bitmap
1923 0 : readBitmap(input);
1924 0 : else if ((m_version >= 400 && chunkType == 0x06) || (m_version < 400 && chunkType == 0x05)) // Paragraph text
1925 0 : m_collector->collectParagraphText();
1926 0 : else if (chunkType == 0x14) // Polygon
1927 0 : readPolygonCoords(input);
1928 : }
1929 0 : else if (argTypes[i] == 0x14)
1930 : {
1931 0 : if (m_version < 400)
1932 0 : readWaldoFill(input);
1933 : else
1934 0 : m_collector->collectFildId(readU32(input));
1935 : }
1936 0 : else if (argTypes[i] == 0x0a)
1937 : {
1938 0 : if (m_version < 400)
1939 0 : readWaldoOutl(input);
1940 : else
1941 0 : m_collector->collectOutlId(readU32(input));
1942 : }
1943 0 : else if (argTypes[i] == 0x2af8)
1944 0 : readPolygonTransform(input);
1945 0 : else if (argTypes[i] == 0x1f40)
1946 0 : readOpacity(input, length);
1947 0 : else if (argTypes[i] == 0x64)
1948 : {
1949 0 : if (m_version < 400)
1950 0 : readWaldoTrfd(input);
1951 : }
1952 0 : else if (argTypes[i] == 0x4aba)
1953 0 : readPageSize(input);
1954 : }
1955 0 : input->seek(startPosition+chunkLength, WPX_SEEK_SET);
1956 0 : }
1957 :
1958 0 : void libcdr::CDRParser::readFlags(WPXInputStream *input, unsigned length)
1959 : {
1960 0 : if (!_redirectX6Chunk(&input, length))
1961 0 : throw GenericException();
1962 0 : unsigned flags = readU32(input);
1963 0 : m_collector->collectFlags(flags, m_version >= 400);
1964 0 : }
1965 :
1966 0 : void libcdr::CDRParser::readMcfg(WPXInputStream *input, unsigned length)
1967 : {
1968 0 : if (!_redirectX6Chunk(&input, length))
1969 0 : throw GenericException();
1970 0 : if (m_version >= 1300)
1971 0 : input->seek(12, WPX_SEEK_CUR);
1972 0 : else if (m_version >= 900)
1973 0 : input->seek(4, WPX_SEEK_CUR);
1974 0 : else if (m_version < 700 && m_version >= 600)
1975 0 : input->seek(0x1c, WPX_SEEK_CUR);
1976 0 : double width = 0.0;
1977 0 : double height = 0.0;
1978 0 : if (m_version < 400)
1979 : {
1980 0 : input->seek(2, WPX_SEEK_CUR);
1981 0 : double x0 = readCoordinate(input);
1982 0 : double y0 = readCoordinate(input);
1983 0 : double x1 = readCoordinate(input);
1984 0 : double y1 = readCoordinate(input);
1985 0 : width = fabs(x1-x0);
1986 0 : height = fabs(y1-y0);
1987 : }
1988 : else
1989 : {
1990 0 : width = readCoordinate(input);
1991 0 : height = readCoordinate(input);
1992 : }
1993 0 : m_collector->collectPageSize(width, height, -width/2.0, -height/2.0);
1994 0 : }
1995 :
1996 0 : void libcdr::CDRParser::readPolygonCoords(WPXInputStream *input)
1997 : {
1998 : CDR_DEBUG_MSG(("CDRParser::readPolygonCoords\n"));
1999 :
2000 0 : unsigned short pointNum = readU16(input);
2001 0 : input->seek(2, WPX_SEEK_CUR);
2002 0 : std::vector<std::pair<double, double> > points;
2003 0 : std::vector<unsigned char> pointTypes;
2004 0 : for (unsigned j=0; j<pointNum; j++)
2005 : {
2006 0 : std::pair<double, double> point;
2007 0 : point.first = (double)readCoordinate(input);
2008 0 : point.second = (double)readCoordinate(input);
2009 0 : points.push_back(point);
2010 : }
2011 0 : for (unsigned k=0; k<pointNum; k++)
2012 0 : pointTypes.push_back(readU8(input));
2013 0 : outputPath(points, pointTypes);
2014 0 : m_collector->collectPolygon();
2015 0 : }
2016 :
2017 0 : void libcdr::CDRParser::readPolygonTransform(WPXInputStream *input)
2018 : {
2019 0 : if (m_version < 1300)
2020 0 : input->seek(4, WPX_SEEK_CUR);
2021 0 : unsigned numAngles = readU32(input);
2022 0 : unsigned nextPoint = readU32(input);
2023 0 : if (nextPoint <= 1)
2024 0 : nextPoint = readU32(input);
2025 : else
2026 0 : input->seek(4, WPX_SEEK_CUR);
2027 0 : if (m_version >= 1300)
2028 0 : input->seek(4, WPX_SEEK_CUR);
2029 0 : double rx = readDouble(input);
2030 0 : double ry = readDouble(input);
2031 0 : double cx = readCoordinate(input);
2032 0 : double cy = readCoordinate(input);
2033 0 : m_collector->collectPolygonTransform(numAngles, nextPoint, rx, ry, cx, cy);
2034 0 : }
2035 :
2036 0 : void libcdr::CDRParser::readPageSize(WPXInputStream *input)
2037 : {
2038 0 : double width = readCoordinate(input);
2039 0 : double height = readCoordinate(input);
2040 0 : m_collector->collectPageSize(width, height, -width/2.0, -height/2.0);
2041 0 : }
2042 :
2043 0 : void libcdr::CDRParser::readWaldoBmp(WPXInputStream *input, unsigned length, unsigned id)
2044 : {
2045 0 : if (m_version >= 400)
2046 : return;
2047 0 : if (readU8(input) != 0x42)
2048 : return;
2049 0 : if (readU8(input) != 0x4d)
2050 : return;
2051 0 : input->seek(-2, WPX_SEEK_CUR);
2052 0 : unsigned long tmpNumBytesRead = 0;
2053 0 : const unsigned char *tmpBuffer = input->read(length, tmpNumBytesRead);
2054 0 : if (!tmpNumBytesRead || length != tmpNumBytesRead)
2055 : return;
2056 0 : std::vector<unsigned char> bitmap(tmpNumBytesRead);
2057 0 : memcpy(&bitmap[0], tmpBuffer, tmpNumBytesRead);
2058 0 : m_collector->collectBmp(id, bitmap);
2059 0 : return;
2060 : }
2061 :
2062 0 : void libcdr::CDRParser::readBmp(WPXInputStream *input, unsigned length)
2063 : {
2064 0 : if (!_redirectX6Chunk(&input, length))
2065 0 : throw GenericException();
2066 0 : unsigned imageId = readUnsigned(input);
2067 0 : if (m_version < 500)
2068 : {
2069 0 : if (readU8(input) != 0x42)
2070 : return;
2071 0 : if (readU8(input) != 0x4d)
2072 : return;
2073 0 : unsigned lngth = readU32(input);
2074 0 : input->seek(-6, WPX_SEEK_CUR);
2075 0 : unsigned long tmpNumBytesRead = 0;
2076 0 : const unsigned char *tmpBuffer = input->read(lngth, tmpNumBytesRead);
2077 0 : if (!tmpNumBytesRead || lngth != tmpNumBytesRead)
2078 : return;
2079 0 : std::vector<unsigned char> bitmap(tmpNumBytesRead);
2080 0 : memcpy(&bitmap[0], tmpBuffer, tmpNumBytesRead);
2081 0 : m_collector->collectBmp(imageId, bitmap);
2082 0 : return;
2083 : }
2084 0 : if (m_version < 600)
2085 0 : input->seek(14, WPX_SEEK_CUR);
2086 0 : else if (m_version < 700)
2087 0 : input->seek(46, WPX_SEEK_CUR);
2088 : else
2089 0 : input->seek(50, WPX_SEEK_CUR);
2090 0 : unsigned colorModel = readU32(input);
2091 0 : input->seek(4, WPX_SEEK_CUR);
2092 0 : unsigned width = readU32(input);
2093 0 : unsigned height = readU32(input);
2094 0 : input->seek(4, WPX_SEEK_CUR);
2095 0 : unsigned bpp = readU32(input);
2096 0 : input->seek(4, WPX_SEEK_CUR);
2097 0 : unsigned bmpsize = readU32(input);
2098 0 : input->seek(32, WPX_SEEK_CUR);
2099 0 : std::vector<unsigned> palette;
2100 0 : if (bpp < 24 && colorModel != 5 && colorModel != 6)
2101 : {
2102 0 : input->seek(2, WPX_SEEK_CUR);
2103 0 : unsigned short palettesize = readU16(input);
2104 0 : for (unsigned short i = 0; i <palettesize; ++i)
2105 : {
2106 0 : unsigned b = readU8(input);
2107 0 : unsigned g = readU8(input);
2108 0 : unsigned r = readU8(input);
2109 0 : palette.push_back(b | (g << 8) | (r << 16));
2110 : }
2111 : }
2112 0 : std::vector<unsigned char> bitmap(bmpsize);
2113 0 : unsigned long tmpNumBytesRead = 0;
2114 0 : const unsigned char *tmpBuffer = input->read(bmpsize, tmpNumBytesRead);
2115 0 : if (bmpsize != tmpNumBytesRead)
2116 : return;
2117 0 : memcpy(&bitmap[0], tmpBuffer, bmpsize);
2118 0 : m_collector->collectBmp(imageId, colorModel, width, height, bpp, palette, bitmap);
2119 : }
2120 :
2121 0 : void libcdr::CDRParser::readOpacity(WPXInputStream *input, unsigned /* length */)
2122 : {
2123 0 : if (m_version < 1300)
2124 0 : input->seek(10, WPX_SEEK_CUR);
2125 : else
2126 0 : input->seek(14, WPX_SEEK_CUR);
2127 0 : double opacity = (double)readU16(input) / 1000.0;
2128 0 : m_collector->collectFillOpacity(opacity);
2129 0 : }
2130 :
2131 0 : void libcdr::CDRParser::readBmpf(WPXInputStream *input, unsigned length)
2132 : {
2133 0 : if (!_redirectX6Chunk(&input, length))
2134 0 : throw GenericException();
2135 0 : unsigned patternId = readU32(input);
2136 0 : unsigned headerLength = readU32(input);
2137 0 : if (headerLength != 40)
2138 : return;
2139 0 : unsigned width = readU32(input);
2140 0 : unsigned height = readU32(input);
2141 0 : input->seek(2, WPX_SEEK_CUR);
2142 0 : unsigned bpp = readU16(input);
2143 0 : if (bpp != 1)
2144 : return;
2145 0 : input->seek(4, WPX_SEEK_CUR);
2146 0 : unsigned dataSize = readU32(input);
2147 0 : input->seek(length - dataSize - 28, WPX_SEEK_CUR);
2148 0 : std::vector<unsigned char> pattern(dataSize);
2149 0 : unsigned long tmpNumBytesRead = 0;
2150 0 : const unsigned char *tmpBuffer = input->read(dataSize, tmpNumBytesRead);
2151 0 : if (dataSize != tmpNumBytesRead)
2152 : return;
2153 0 : memcpy(&pattern[0], tmpBuffer, dataSize);
2154 0 : m_collector->collectBmpf(patternId, width, height, pattern);
2155 : }
2156 :
2157 0 : void libcdr::CDRParser::readWaldoBmpf(WPXInputStream *input, unsigned id)
2158 : {
2159 0 : unsigned headerLength = readU32(input);
2160 0 : if (headerLength != 40)
2161 : return;
2162 0 : unsigned width = readU32(input);
2163 0 : unsigned height = readU32(input);
2164 0 : input->seek(2, WPX_SEEK_CUR);
2165 0 : unsigned bpp = readU16(input);
2166 0 : if (bpp != 1)
2167 : return;
2168 0 : input->seek(4, WPX_SEEK_CUR);
2169 0 : unsigned dataSize = readU32(input);
2170 0 : std::vector<unsigned char> pattern(dataSize);
2171 0 : unsigned long tmpNumBytesRead = 0;
2172 0 : input->seek(24, WPX_SEEK_CUR); // TODO: is this empirical experience universal???
2173 0 : const unsigned char *tmpBuffer = input->read(dataSize, tmpNumBytesRead);
2174 0 : if (dataSize != tmpNumBytesRead)
2175 : return;
2176 0 : memcpy(&pattern[0], tmpBuffer, dataSize);
2177 0 : m_collector->collectBmpf(id, width, height, pattern);
2178 : }
2179 :
2180 0 : void libcdr::CDRParser::readPpdt(WPXInputStream *input, unsigned length)
2181 : {
2182 0 : if (!_redirectX6Chunk(&input, length))
2183 0 : throw GenericException();
2184 0 : unsigned short pointNum = readU16(input);
2185 0 : input->seek(4, WPX_SEEK_CUR);
2186 0 : std::vector<std::pair<double, double> > points;
2187 0 : std::vector<unsigned> knotVector;
2188 0 : for (unsigned j=0; j<pointNum; j++)
2189 : {
2190 0 : std::pair<double, double> point;
2191 0 : point.first = (double)readCoordinate(input);
2192 0 : point.second = (double)readCoordinate(input);
2193 0 : points.push_back(point);
2194 : }
2195 0 : for (unsigned k=0; k<pointNum; k++)
2196 0 : knotVector.push_back(readU32(input));
2197 0 : m_collector->collectPpdt(points, knotVector);
2198 0 : }
2199 :
2200 0 : void libcdr::CDRParser::readFtil(WPXInputStream *input, unsigned length)
2201 : {
2202 0 : if (!_redirectX6Chunk(&input, length))
2203 0 : throw GenericException();
2204 0 : double v0 = readDouble(input);
2205 0 : double v1 = readDouble(input);
2206 0 : double x0 = readDouble(input) / 254000.0;
2207 0 : double v3 = readDouble(input);
2208 0 : double v4 = readDouble(input);
2209 0 : double y0 = readDouble(input) / 254000.0;
2210 0 : CDRTransforms fillTrafos;
2211 0 : fillTrafos.append(v0, v1, x0, v3, v4, y0);
2212 0 : m_collector->collectFillTransform(fillTrafos);
2213 0 : }
2214 :
2215 0 : void libcdr::CDRParser::readVersion(WPXInputStream *input, unsigned length)
2216 : {
2217 0 : if (!_redirectX6Chunk(&input, length))
2218 0 : throw GenericException();
2219 0 : m_version = readU16(input);
2220 0 : if (m_version < 600)
2221 0 : m_precision = libcdr::PRECISION_16BIT;
2222 : else
2223 0 : m_precision = libcdr::PRECISION_32BIT;
2224 0 : }
2225 :
2226 0 : bool libcdr::CDRParser::_redirectX6Chunk(WPXInputStream **input, unsigned &length)
2227 : {
2228 0 : if (m_version >= 1600 && length == 0x10)
2229 : {
2230 0 : unsigned streamNumber = readU32(*input);
2231 0 : length = readU32(*input);
2232 0 : if (streamNumber < m_externalStreams.size())
2233 : {
2234 0 : unsigned streamOffset = readU32(*input);
2235 0 : *input = m_externalStreams[streamNumber];
2236 0 : (*input)->seek(streamOffset, WPX_SEEK_SET);
2237 0 : return true;
2238 : }
2239 0 : else if (streamNumber == 0xffffffff)
2240 0 : return true;
2241 0 : return false;
2242 : }
2243 0 : return true;
2244 : }
2245 :
2246 0 : void libcdr::CDRParser::readIccd(WPXInputStream *input, unsigned length)
2247 : {
2248 0 : if (!_redirectX6Chunk(&input, length))
2249 0 : throw GenericException();
2250 0 : unsigned long numBytesRead = 0;
2251 0 : const unsigned char *tmpProfile = input->read(length, numBytesRead);
2252 0 : if (length != numBytesRead)
2253 0 : throw EndOfStreamException();
2254 0 : if (!numBytesRead)
2255 0 : return;
2256 0 : std::vector<unsigned char> profile(numBytesRead);
2257 0 : memcpy(&profile[0], tmpProfile, numBytesRead);
2258 0 : m_collector->collectColorProfile(profile);
2259 : }
2260 :
2261 0 : void libcdr::CDRParser::readBBox(WPXInputStream *input, unsigned length)
2262 : {
2263 0 : if (!_redirectX6Chunk(&input, length))
2264 0 : throw GenericException();
2265 0 : double x0 = readCoordinate(input);
2266 0 : double y0 = readCoordinate(input);
2267 0 : double x1 = readCoordinate(input);
2268 0 : double y1 = readCoordinate(input);
2269 0 : m_collector->collectBBox(x0, y0, x1, y1);
2270 0 : }
2271 :
2272 0 : void libcdr::CDRParser::readSpnd(WPXInputStream *input, unsigned length)
2273 : {
2274 0 : if (!_redirectX6Chunk(&input, length))
2275 0 : throw GenericException();
2276 0 : unsigned spnd = readUnsigned(input);
2277 0 : m_collector->collectSpnd(spnd);
2278 0 : }
2279 :
2280 0 : void libcdr::CDRParser::readVpat(WPXInputStream *input, unsigned length)
2281 : {
2282 0 : if (!_redirectX6Chunk(&input, length))
2283 0 : throw GenericException();
2284 0 : unsigned fillId = readUnsigned(input);
2285 0 : unsigned long numBytesRead = 0;
2286 0 : const unsigned char *buffer = input->read(length-4, numBytesRead);
2287 0 : if (numBytesRead)
2288 : {
2289 0 : WPXBinaryData data(buffer, numBytesRead);
2290 0 : m_collector->collectVectorPattern(fillId, data);
2291 : }
2292 0 : }
2293 :
2294 0 : void libcdr::CDRParser::readUidr(WPXInputStream *input, unsigned length)
2295 : {
2296 0 : if (!_redirectX6Chunk(&input, length))
2297 0 : throw GenericException();
2298 0 : unsigned colorId = readU32(input);
2299 0 : unsigned userId = readU32(input);
2300 0 : input->seek(36, WPX_SEEK_CUR);
2301 0 : CDRColor color = readColor(input);
2302 0 : m_collector->collectPaletteEntry(colorId, userId, color);
2303 0 : }
2304 :
2305 0 : void libcdr::CDRParser::readFont(WPXInputStream *input, unsigned length)
2306 : {
2307 0 : if (!_redirectX6Chunk(&input, length))
2308 0 : throw GenericException();
2309 0 : unsigned fontId = readU32(input);
2310 0 : unsigned short fontEncoding = fontId >> 16;
2311 0 : input->seek(14, WPX_SEEK_CUR);
2312 0 : WPXString name;
2313 0 : if (m_version >= 1200)
2314 : {
2315 0 : unsigned short character = 0;
2316 0 : while (true)
2317 : {
2318 0 : character = readU16(input);
2319 0 : if (character)
2320 0 : name.append((char)(character & 0xff));
2321 : else
2322 0 : break;
2323 : }
2324 : }
2325 : else
2326 : {
2327 0 : unsigned char character = 0;
2328 0 : while(true)
2329 : {
2330 0 : character = readU8(input);
2331 0 : if (character)
2332 0 : name.append((char)character);
2333 : else
2334 0 : break;
2335 : }
2336 : }
2337 0 : m_collector->collectFont(fontId, fontEncoding, name);
2338 0 : }
2339 :
2340 0 : void libcdr::CDRParser::readStlt(WPXInputStream *input, unsigned length)
2341 : {
2342 : #ifndef DEBUG
2343 0 : unsigned version = m_version;
2344 : try
2345 : {
2346 : #endif
2347 0 : if (m_version < 700)
2348 : return;
2349 0 : if (!_redirectX6Chunk(&input, length))
2350 0 : throw GenericException();
2351 0 : long startPosition = input->tell();
2352 0 : unsigned numRecords = readU32(input);
2353 : CDR_DEBUG_MSG(("CDRParser::readStlt numRecords 0x%x\n", numRecords));
2354 0 : if (!numRecords)
2355 : return;
2356 0 : unsigned numFills = readU32(input);
2357 : CDR_DEBUG_MSG(("CDRParser::readStlt numFills 0x%x\n", numFills));
2358 0 : unsigned i = 0;
2359 0 : for (i=0; i<numFills; ++i)
2360 : {
2361 0 : input->seek(12, WPX_SEEK_CUR);
2362 0 : if (m_version >= 1300)
2363 0 : input->seek(48, WPX_SEEK_CUR);
2364 : }
2365 0 : unsigned numOutls = readU32(input);
2366 : CDR_DEBUG_MSG(("CDRParser::readStlt numOutls 0x%x\n", numOutls));
2367 0 : for (i=0; i<numOutls; ++i)
2368 : {
2369 0 : input->seek(12, WPX_SEEK_CUR);
2370 : }
2371 0 : unsigned numFonts = readU32(input);
2372 : CDR_DEBUG_MSG(("CDRParser::readStlt numFonts 0x%x\n", numFonts));
2373 0 : std::map<unsigned,unsigned> fontIds;
2374 0 : std::map<unsigned,double> fontSizes;
2375 0 : for (i=0; i<numFonts; ++i)
2376 : {
2377 0 : unsigned fontStyleId = readU32(input);
2378 0 : if (m_version < 1000)
2379 0 : input->seek(12, WPX_SEEK_CUR);
2380 : else
2381 0 : input->seek(20, WPX_SEEK_CUR);
2382 0 : fontIds[fontStyleId] = readU32(input);
2383 0 : input->seek(8, WPX_SEEK_CUR);
2384 0 : fontSizes[fontStyleId] = readCoordinate(input);
2385 0 : if (m_version < 1000)
2386 0 : input->seek(12, WPX_SEEK_CUR);
2387 : else
2388 0 : input->seek(20, WPX_SEEK_CUR);
2389 : }
2390 0 : unsigned numAligns = readU32(input);
2391 : CDR_DEBUG_MSG(("CDRParser::readStlt numAligns 0x%x\n", numAligns));
2392 0 : for (i=0; i<numAligns; ++i)
2393 : {
2394 0 : input->seek(12, WPX_SEEK_CUR);
2395 : }
2396 0 : unsigned numIntervals = readU32(input);
2397 : CDR_DEBUG_MSG(("CDRParser::readStlt numIntervals 0x%x\n", numIntervals));
2398 0 : for (i=0; i<numIntervals; ++i)
2399 : {
2400 0 : input->seek(52, WPX_SEEK_CUR);
2401 : }
2402 0 : unsigned numSet5s = readU32(input);
2403 : CDR_DEBUG_MSG(("CDRParser::readStlt numSet5s 0x%x\n", numSet5s));
2404 0 : for (i=0; i<numSet5s; ++i)
2405 : {
2406 0 : input->seek(152, WPX_SEEK_CUR);
2407 : }
2408 0 : unsigned numTabs = readU32(input);
2409 : CDR_DEBUG_MSG(("CDRParser::readStlt numTabs 0x%x\n", numTabs));
2410 0 : for (i=0; i<numTabs; ++i)
2411 : {
2412 0 : input->seek(784, WPX_SEEK_CUR);
2413 : }
2414 0 : unsigned numBullets = readU32(input);
2415 : CDR_DEBUG_MSG(("CDRParser::readStlt numBullets 0x%x\n", numBullets));
2416 0 : for (i=0; i<numBullets; ++i)
2417 : {
2418 0 : input->seek(40, WPX_SEEK_CUR);
2419 0 : if (m_version > 1300)
2420 0 : input->seek(4, WPX_SEEK_CUR);
2421 0 : if (m_version >= 1300)
2422 : {
2423 0 : if (readU32(input))
2424 0 : input->seek(68, WPX_SEEK_CUR);
2425 : else
2426 0 : input->seek(12, WPX_SEEK_CUR);
2427 : }
2428 : else
2429 : {
2430 0 : input->seek(20, WPX_SEEK_CUR);
2431 0 : if (m_version >= 1000)
2432 0 : input->seek(8, WPX_SEEK_CUR);
2433 0 : if (readU32(input))
2434 0 : input->seek(8, WPX_SEEK_CUR);
2435 0 : input->seek(8, WPX_SEEK_CUR);
2436 : }
2437 : }
2438 0 : unsigned numIndents = readU32(input);
2439 : CDR_DEBUG_MSG(("CDRParser::readStlt numIndents 0x%x\n", numIndents));
2440 0 : for (i=0; i<numIndents; ++i)
2441 : {
2442 0 : input->seek(28, WPX_SEEK_CUR);
2443 : }
2444 0 : unsigned numHypens = readU32(input);
2445 : CDR_DEBUG_MSG(("CDRParser::readStlt numHypens 0x%x\n", numHypens));
2446 0 : for (i=0; i<numHypens; ++i)
2447 : {
2448 0 : input->seek(32, WPX_SEEK_CUR);
2449 0 : if (m_version >= 1300)
2450 0 : input->seek(4, WPX_SEEK_CUR);
2451 : }
2452 0 : unsigned numDropcaps = readU32(input);
2453 : CDR_DEBUG_MSG(("CDRParser::readStlt numDropcaps 0x%x\n", numDropcaps));
2454 0 : for (i=0; i<numDropcaps; ++i)
2455 : {
2456 0 : input->seek(28, WPX_SEEK_CUR);
2457 : }
2458 0 : std::map<unsigned, CDRCharacterStyle> charStyles;
2459 : try
2460 : {
2461 0 : bool set11Flag(false);
2462 0 : if (m_version > 800)
2463 : {
2464 0 : set11Flag = true;
2465 0 : unsigned numSet11s = readU32(input);
2466 : CDR_DEBUG_MSG(("CDRParser::readStlt numSet11s 0x%x\n", numSet11s));
2467 0 : for (i=0; i<numSet11s; ++i)
2468 : {
2469 0 : input->seek(12, WPX_SEEK_CUR);
2470 : }
2471 : }
2472 0 : std::map<unsigned, CDRStltRecord> styles;
2473 0 : for (i=0; i<numRecords; ++i)
2474 : {
2475 : CDR_DEBUG_MSG(("CDRParser::readStlt parsing styles\n"));
2476 0 : unsigned num = readU32(input);
2477 : CDR_DEBUG_MSG(("CDRParser::readStlt parsing styles num 0x%x\n", num));
2478 0 : unsigned styleId = readU32(input);
2479 0 : CDRStltRecord style;
2480 0 : style.parentId = readU32(input);
2481 0 : input->seek(8, WPX_SEEK_CUR);
2482 0 : unsigned namelen = readU32(input);
2483 : CDR_DEBUG_MSG(("CDRParser::readStlt parsing styles namelen 0x%x\n", namelen));
2484 0 : if (m_version >= 1200)
2485 0 : namelen *= 2;
2486 0 : input->seek(namelen, WPX_SEEK_CUR);
2487 0 : style.fillId = readU32(input);
2488 0 : style.outlId = readU32(input);
2489 0 : if (num > 1)
2490 : {
2491 0 : style.fontRecId = readU32(input);
2492 0 : style.alignId = readU32(input);
2493 0 : style.intervalId = readU32(input);
2494 0 : style.set5Id = readU32(input);
2495 0 : if (set11Flag)
2496 0 : style.set11Id = readU32(input);
2497 : }
2498 0 : if (num > 2)
2499 : {
2500 0 : style.tabId = readU32(input);
2501 0 : style.bulletId = readU32(input);
2502 0 : style.identId = readU32(input);
2503 0 : style.hyphenId = readU32(input);
2504 0 : style.dropCapId = readU32(input);
2505 : }
2506 0 : styles[styleId] = style;
2507 : }
2508 0 : CDRCharacterStyle tmpCharStyle;
2509 0 : for (std::map<unsigned, CDRStltRecord>::const_iterator iter = styles.begin();
2510 0 : iter != styles.end(); ++iter)
2511 : {
2512 0 : unsigned fontRecordId = 0;
2513 0 : if (iter->second.fontRecId)
2514 0 : fontRecordId = iter->second.fontRecId;
2515 0 : else if (iter->second.parentId)
2516 : {
2517 0 : unsigned parentId = iter->second.parentId;
2518 0 : while (true)
2519 : {
2520 0 : std::map<unsigned, CDRStltRecord>::const_iterator iter2 = styles.find(parentId);
2521 0 : if (iter2 == styles.end())
2522 : break;
2523 0 : if (iter2->second.fontRecId)
2524 : {
2525 0 : fontRecordId = iter2->second.fontRecId;
2526 : break;
2527 : }
2528 0 : if (iter2->second.parentId)
2529 0 : parentId = iter2->second.parentId;
2530 : else
2531 : break;
2532 : }
2533 : }
2534 0 : if (!fontRecordId)
2535 0 : continue;
2536 0 : std::map<unsigned, unsigned>::const_iterator iterFontId = fontIds.find(fontRecordId);
2537 0 : if (iterFontId != fontIds.end())
2538 0 : tmpCharStyle.m_fontId = iterFontId->second;
2539 0 : std::map<unsigned, double>::const_iterator iterFontSize = fontSizes.find(fontRecordId);
2540 0 : if (iterFontSize != fontSizes.end())
2541 0 : tmpCharStyle.m_fontSize = iterFontSize->second;
2542 0 : charStyles[iter->first] = tmpCharStyle;
2543 0 : }
2544 : }
2545 0 : catch (libcdr::EndOfStreamException &)
2546 : {
2547 0 : if (m_version == 800)
2548 : {
2549 : CDR_DEBUG_MSG(("Catching EndOfStreamException and trying to parse as version 801\n"));
2550 0 : m_version = 801;
2551 0 : input->seek(startPosition, WPX_SEEK_SET);
2552 0 : readStlt(input, length);
2553 : return;
2554 : }
2555 : else
2556 : {
2557 : CDR_DEBUG_MSG(("Rethrowing EndOfStreamException\n"));
2558 0 : throw libcdr::EndOfStreamException();
2559 : }
2560 : }
2561 0 : m_collector->collectStlt(charStyles);
2562 : #ifndef DEBUG
2563 : }
2564 0 : catch (...)
2565 : {
2566 0 : m_version = version;
2567 : }
2568 : #endif
2569 : }
2570 :
2571 0 : void libcdr::CDRParser::readTxsm(WPXInputStream *input, unsigned length)
2572 : {
2573 : #ifndef DEBUG
2574 : try
2575 : {
2576 : #endif
2577 0 : if (m_version < 500)
2578 : return;
2579 0 : if (!_redirectX6Chunk(&input, length))
2580 0 : throw GenericException();
2581 0 : if (m_version < 600)
2582 0 : return readTxsm5(input);
2583 0 : if (m_version < 700)
2584 0 : return readTxsm6(input);
2585 0 : if (m_version >= 1600)
2586 0 : return readTxsm16(input);
2587 0 : if (m_version >= 1500)
2588 0 : input->seek(0x25, WPX_SEEK_CUR);
2589 : else
2590 0 : input->seek(0x24, WPX_SEEK_CUR);
2591 0 : if (readU32(input))
2592 : {
2593 0 : if (m_version < 800)
2594 0 : input->seek(32, WPX_SEEK_CUR);
2595 : }
2596 0 : if (m_version < 800)
2597 0 : input->seek(4, WPX_SEEK_CUR);
2598 0 : unsigned textId = readU32(input);
2599 0 : input->seek(48, WPX_SEEK_CUR);
2600 0 : if (m_version >= 800)
2601 : {
2602 0 : if (readU32(input))
2603 0 : input->seek(32, WPX_SEEK_CUR);
2604 : }
2605 0 : if (m_version >= 1500)
2606 0 : input->seek(12, WPX_SEEK_CUR);
2607 0 : unsigned num = readU32(input);
2608 0 : if (!num)
2609 : {
2610 0 : if (m_version >= 800)
2611 0 : input->seek(4, WPX_SEEK_CUR);
2612 0 : if (m_version > 800)
2613 0 : input->seek(2, WPX_SEEK_CUR);
2614 0 : if (m_version >= 1400)
2615 0 : input->seek(2, WPX_SEEK_CUR);
2616 0 : input->seek(24, WPX_SEEK_CUR);
2617 0 : if (m_version < 800)
2618 0 : input->seek(8, WPX_SEEK_CUR);
2619 0 : input->seek(4, WPX_SEEK_CUR);
2620 : }
2621 :
2622 0 : unsigned stlId = readU32(input);
2623 0 : if (m_version >= 1300 && num)
2624 0 : input->seek(1, WPX_SEEK_CUR);
2625 0 : input->seek(1, WPX_SEEK_CUR);
2626 0 : unsigned numRecords = readU32(input);
2627 0 : std::map<unsigned, CDRCharacterStyle> charStyles;
2628 0 : unsigned i = 0;
2629 0 : for (i=0; i<numRecords; ++i)
2630 : {
2631 0 : readU8(input);
2632 0 : readU8(input);
2633 0 : unsigned char fl2 = readU8(input);
2634 0 : unsigned char fl3 = 0;
2635 0 : if (m_version >= 800)
2636 0 : fl3 = readU8(input);
2637 :
2638 0 : CDRCharacterStyle charStyle;
2639 : // Read more information depending on the flags
2640 0 : if (fl2&1) // Font
2641 : {
2642 0 : unsigned flag = readU32(input);
2643 0 : charStyle.m_charSet = (flag >> 16);
2644 0 : charStyle.m_fontId = flag & 0xff;
2645 : }
2646 0 : if (fl2&2) // Bold/Italic, etc.
2647 0 : input->seek(4, WPX_SEEK_CUR);
2648 0 : if (fl2&4) // Font Size
2649 0 : charStyle.m_fontSize = readCoordinate(input);
2650 0 : if (fl2&8) // assumption
2651 0 : input->seek(4, WPX_SEEK_CUR);
2652 0 : if (fl2&0x10) // Offset X
2653 0 : input->seek(4, WPX_SEEK_CUR);
2654 0 : if (fl2&0x20) // Offset Y
2655 0 : input->seek(4, WPX_SEEK_CUR);
2656 0 : if (fl2&0x40) // Font Colour
2657 : {
2658 0 : input->seek(4, WPX_SEEK_CUR);
2659 0 : if (m_version >= 1500)
2660 0 : input->seek(48, WPX_SEEK_CUR);
2661 : }
2662 0 : if (fl2&0x80) // Font Outl Colour
2663 0 : input->seek(4, WPX_SEEK_CUR);
2664 :
2665 0 : if (fl3&8) // Encoding
2666 : {
2667 0 : if (m_version >= 1300)
2668 : {
2669 0 : unsigned tlen = readU32(input);
2670 0 : input->seek(tlen*2, WPX_SEEK_CUR);
2671 : }
2672 : else
2673 0 : input->seek(4, WPX_SEEK_CUR);
2674 : }
2675 0 : if (fl3&0x20) // Something
2676 : {
2677 0 : unsigned flag = readU8(input);
2678 0 : if (flag)
2679 0 : input->seek(52, WPX_SEEK_CUR);
2680 : }
2681 :
2682 0 : charStyles[2*i] = charStyle;
2683 : }
2684 0 : unsigned numChars = readU32(input);
2685 0 : std::vector<uint64_t> charDescriptions(numChars);
2686 0 : for (i=0; i<numChars; ++i)
2687 : {
2688 0 : if (m_version >= 1200)
2689 0 : charDescriptions[i] = readU64(input);
2690 : else
2691 0 : charDescriptions[i] = readU32(input);
2692 : }
2693 0 : unsigned numBytes = numChars;
2694 0 : if (m_version >= 1200)
2695 0 : numBytes = readU32(input);
2696 0 : unsigned long numBytesRead = 0;
2697 0 : const unsigned char *buffer = input->read(numBytes, numBytesRead);
2698 0 : if (numBytesRead != numBytes)
2699 0 : throw GenericException();
2700 0 : std::vector<unsigned char> textData(numBytesRead);
2701 0 : if (numBytesRead)
2702 0 : memcpy(&textData[0], buffer, numBytesRead);
2703 :
2704 0 : m_collector->collectText(textId, stlId, textData, charDescriptions, charStyles);
2705 : #ifndef DEBUG
2706 : }
2707 0 : catch (...)
2708 : {
2709 : }
2710 : #endif
2711 : }
2712 :
2713 0 : void libcdr::CDRParser::_readX6StyleString(WPXInputStream *input, unsigned length, WPXString &styleString)
2714 : {
2715 0 : std::vector<unsigned char> styleBuffer(length);
2716 0 : unsigned long numBytesRead = 0;
2717 0 : const unsigned char *tmpBuffer = input->read(length, numBytesRead);
2718 0 : if (numBytesRead)
2719 0 : memcpy(&styleBuffer[0], tmpBuffer, numBytesRead);
2720 0 : appendCharacters(styleString, styleBuffer);
2721 0 : CDR_DEBUG_MSG(("CDRParser::_readX6StyleString - styleString = \"%s\"\n", styleString.cstr()));
2722 0 : }
2723 :
2724 :
2725 0 : void libcdr::CDRParser::readTxsm16(WPXInputStream *input)
2726 : {
2727 : #ifndef DEBUG
2728 : try
2729 : {
2730 : #endif
2731 0 : unsigned frameFlag = readU32(input);
2732 0 : input->seek(41, WPX_SEEK_CUR);
2733 :
2734 0 : unsigned textId = readU32(input);
2735 :
2736 0 : input->seek(48, WPX_SEEK_CUR);
2737 0 : if (!frameFlag)
2738 : {
2739 0 : input->seek(28, WPX_SEEK_CUR);
2740 0 : unsigned tlen = readU32(input);
2741 0 : input->seek(2*tlen + 4, WPX_SEEK_CUR);
2742 : }
2743 : else
2744 : {
2745 0 : unsigned textOnPath = readU32(input);
2746 0 : if (textOnPath == 1)
2747 : {
2748 0 : input->seek(4, WPX_SEEK_CUR); // var1
2749 0 : input->seek(4, WPX_SEEK_CUR); // Orientation
2750 0 : input->seek(4, WPX_SEEK_CUR); // var2
2751 0 : input->seek(4, WPX_SEEK_CUR); // var3
2752 0 : input->seek(4, WPX_SEEK_CUR); // Offset
2753 0 : input->seek(4, WPX_SEEK_CUR); // var4
2754 0 : input->seek(4, WPX_SEEK_CUR); // Distance
2755 0 : input->seek(4, WPX_SEEK_CUR); // var5
2756 0 : input->seek(4, WPX_SEEK_CUR); // Mirror Vert
2757 0 : input->seek(4, WPX_SEEK_CUR); // Mirror Hor
2758 0 : input->seek(4, WPX_SEEK_CUR); // var6
2759 0 : input->seek(4, WPX_SEEK_CUR); // var7
2760 : }
2761 : else
2762 0 : input->seek(8, WPX_SEEK_CUR);
2763 0 : input->seek(4, WPX_SEEK_CUR);
2764 : }
2765 :
2766 0 : unsigned stlId = readU32(input);
2767 :
2768 0 : if (frameFlag)
2769 0 : input->seek(1, WPX_SEEK_CUR);
2770 0 : input->seek(1, WPX_SEEK_CUR);
2771 :
2772 0 : unsigned len2 = readU32(input);
2773 0 : WPXString styleString;
2774 0 : _readX6StyleString(input, 2*len2, styleString);
2775 :
2776 0 : unsigned numRecords = readU32(input);
2777 :
2778 0 : unsigned i = 0;
2779 0 : for (i=0; i<numRecords; ++i)
2780 : {
2781 0 : input->seek(4, WPX_SEEK_CUR);
2782 0 : unsigned flag = readU8(input);
2783 0 : input->seek(1, WPX_SEEK_CUR);
2784 0 : unsigned lenN = 0;
2785 0 : if (flag & 0x04)
2786 : {
2787 0 : lenN = readU32(input);
2788 0 : styleString.clear();
2789 0 : _readX6StyleString(input, 2*lenN, styleString);
2790 : }
2791 0 : lenN = readU32(input);
2792 0 : styleString.clear();
2793 0 : _readX6StyleString(input, 2*lenN, styleString);
2794 : }
2795 :
2796 0 : std::map<unsigned, CDRCharacterStyle> charStyles;
2797 0 : unsigned numChars = readU32(input);
2798 0 : std::vector<uint64_t> charDescriptions(numChars);
2799 0 : for (i=0; i<numChars; ++i)
2800 : {
2801 0 : charDescriptions[i] = readU64(input);
2802 : }
2803 0 : unsigned numBytes = numChars;
2804 0 : numBytes = readU32(input);
2805 0 : unsigned long numBytesRead = 0;
2806 0 : const unsigned char *buffer = input->read(numBytes, numBytesRead);
2807 0 : if (numBytesRead != numBytes)
2808 0 : throw GenericException();
2809 0 : std::vector<unsigned char> textData(numBytesRead);
2810 0 : if (numBytesRead)
2811 0 : memcpy(&textData[0], buffer, numBytesRead);
2812 :
2813 0 : m_collector->collectText(textId, stlId, textData, charDescriptions, charStyles);
2814 : #ifndef DEBUG
2815 : }
2816 0 : catch (...)
2817 : {
2818 : }
2819 : #endif
2820 0 : }
2821 :
2822 0 : void libcdr::CDRParser::readTxsm6(WPXInputStream *input)
2823 : {
2824 :
2825 0 : input->seek(0x28, WPX_SEEK_CUR);
2826 0 : input->seek(48, WPX_SEEK_CUR);
2827 0 : input->seek(4, WPX_SEEK_CUR);
2828 : /* unsigned stlId = */
2829 0 : readU32(input);
2830 0 : unsigned numSt = readU32(input);
2831 0 : unsigned i = 0;
2832 0 : for (; i<numSt; ++i)
2833 : {
2834 0 : input->seek(60, WPX_SEEK_CUR);
2835 : }
2836 0 : unsigned numChars = readU32(input);
2837 0 : for (i=0; i<numChars; ++i)
2838 : {
2839 0 : input->seek(12, WPX_SEEK_CUR);
2840 : }
2841 0 : }
2842 :
2843 0 : void libcdr::CDRParser::readTxsm5(WPXInputStream *input)
2844 : {
2845 0 : input->seek(10, WPX_SEEK_CUR);
2846 : /* unsigned stlId = */
2847 0 : readU16(input);
2848 0 : unsigned numSt = readU16(input);
2849 0 : unsigned i = 0;
2850 0 : for (; i<numSt; ++i)
2851 : {
2852 0 : input->seek(36, WPX_SEEK_CUR);
2853 : }
2854 0 : unsigned numChars = readU16(input);
2855 0 : for (i=0; i<numChars; ++i)
2856 : {
2857 0 : input->seek(8, WPX_SEEK_CUR);
2858 : }
2859 0 : }
2860 :
2861 0 : void libcdr::CDRParser::readStyd(WPXInputStream *input)
2862 : {
2863 : CDR_DEBUG_MSG(("libcdr::CDRParser::readStyd\n"));
2864 0 : if (m_version >= 700)
2865 : {
2866 : CDR_DEBUG_MSG(("Styd should not be present in this file version\n"));
2867 0 : return;
2868 : }
2869 0 : /* unsigned styleId = */ readU16(input);
2870 0 : long startPosition = input->tell();
2871 0 : unsigned chunkLength = readUnsigned(input);
2872 0 : unsigned numOfArgs = readUnsigned(input);
2873 0 : unsigned startOfArgs = readUnsigned(input);
2874 0 : unsigned startOfArgTypes = readUnsigned(input);
2875 : /* unsigned parentId = */
2876 0 : readUnsigned(input);
2877 0 : std::vector<unsigned> argOffsets(numOfArgs, 0);
2878 0 : std::vector<unsigned> argTypes(numOfArgs, 0);
2879 0 : unsigned i = 0;
2880 0 : input->seek(startPosition+startOfArgs, WPX_SEEK_SET);
2881 0 : while (i<numOfArgs)
2882 0 : argOffsets[i++] = readUnsigned(input);
2883 0 : input->seek(startPosition+startOfArgTypes, WPX_SEEK_SET);
2884 0 : while (i>0)
2885 0 : argTypes[--i] = readUnsigned(input);
2886 :
2887 0 : for (i=0; i < argTypes.size(); i++)
2888 : {
2889 0 : input->seek(startPosition+argOffsets[i], WPX_SEEK_SET);
2890 : CDR_DEBUG_MSG(("Styd: argument type: 0x%x\n", argTypes[i]));
2891 0 : switch(argTypes[i])
2892 : {
2893 : case STYD_NAME:
2894 0 : break;
2895 : case STYD_FILL_ID:
2896 0 : break;
2897 : case STYD_OUTL_ID:
2898 0 : break;
2899 : case STYD_FONTS:
2900 0 : break;
2901 : case STYD_ALIGN:
2902 0 : break;
2903 : case STYD_BULLETS:
2904 0 : break;
2905 : case STYD_INTERVALS:
2906 0 : break;
2907 : case STYD_TABS:
2908 0 : break;
2909 : case STYD_IDENTS:
2910 0 : break;
2911 : case STYD_HYPHENS:
2912 0 : break;
2913 : case STYD_SET5S:
2914 0 : break;
2915 : case STYD_DROPCAPS:
2916 0 : break;
2917 : default:
2918 0 : break;
2919 : }
2920 : }
2921 0 : input->seek(startPosition+chunkLength, WPX_SEEK_SET);
2922 0 : }
2923 :
2924 : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|