Coverage Report

Created: 2026-04-29 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcdr/src/lib/CMXParser.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/*
3
 * This file is part of the libcdr project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#include "CMXParser.h"
11
12
#include <librevenge-stream/librevenge-stream.h>
13
14
#include <math.h>
15
#include <stdlib.h>
16
#include <utility>
17
#include <cinttypes>
18
19
#include "libcdr_utils.h"
20
#include "CDRPath.h"
21
#include "CDRCollector.h"
22
#include "CDRDocumentStructure.h"
23
#include "CMXDocumentStructure.h"
24
25
#ifndef DUMP_PREVIEW_IMAGE
26
#define DUMP_PREVIEW_IMAGE 0
27
#endif
28
29
#ifndef DUMP_IMAGE
30
#define DUMP_IMAGE 0
31
#endif
32
33
static const int MAX_RECORD_DEPTH = 1 << 10;
34
35
namespace
36
{
37
38
uint16_t readTagLength(librevenge::RVNGInputStream *const input, const bool bigEndian)
39
87.1M
{
40
87.1M
  uint16_t tagLength = libcdr::readU16(input, bigEndian);
41
87.1M
  if (tagLength < 3)
42
81.7M
  {
43
81.7M
    CDR_DEBUG_MSG(("invalid tag length %" PRIu16 "\n", tagLength));
44
81.7M
    tagLength = 3;
45
81.7M
  }
46
87.1M
  return tagLength;
47
87.1M
}
48
49
void sanitizeNumRecords(
50
  unsigned long &numRecords,
51
  const libcdr::CoordinatePrecision precision, const unsigned size16, const unsigned size32,
52
  const unsigned long remainingLength)
53
39.5k
{
54
39.5k
  unsigned recordSize = 1;
55
39.5k
  if (precision == libcdr::PRECISION_16BIT)
56
19.2k
    recordSize = size16;
57
20.3k
  else if (precision == libcdr::PRECISION_32BIT)
58
9.35k
    recordSize = size32;
59
39.5k
  if (numRecords > remainingLength / recordSize)
60
7.09k
    numRecords = remainingLength / recordSize;
61
39.5k
}
62
63
void sanitizeNumRecords(
64
  unsigned long &numRecords,
65
  const libcdr::CoordinatePrecision precision, const unsigned size16, const unsigned size32, const unsigned tags,
66
  const unsigned long remainingLength)
67
12.0k
{
68
12.0k
  sanitizeNumRecords(numRecords, precision, size16, size32 + 3 * tags + 1, remainingLength);
69
12.0k
}
70
71
}
72
73
libcdr::CMXParser::CMXParser(libcdr::CDRCollector *collector, CMXParserState &parserState)
74
10.1k
  : CommonParser(collector),
75
10.1k
    m_bigEndian(false), m_unit(0),
76
10.1k
    m_scale(0.0), m_xmin(0.0), m_xmax(0.0), m_ymin(0.0), m_ymax(0.0),
77
10.1k
    m_fillIndex(0), m_nextInstructionOffset(0), m_parserState(parserState),
78
10.1k
    m_currentImageInfo(), m_currentPattern(), m_currentBitmap() {}
79
80
libcdr::CMXParser::~CMXParser()
81
10.1k
{
82
10.1k
}
83
84
bool libcdr::CMXParser::parseRecords(librevenge::RVNGInputStream *input, long size, unsigned level)
85
31.4k
{
86
31.4k
  if (!input || level > MAX_RECORD_DEPTH)
87
1
  {
88
1
    return false;
89
1
  }
90
31.4k
  m_collector->collectLevel(level);
91
31.4k
  long endPosition = -1;
92
31.4k
  if (size > 0)
93
20.8k
    endPosition = input->tell() + size;
94
178k
  while (!input->isEnd() && (endPosition < 0 || input->tell() < endPosition))
95
157k
  {
96
157k
    if (!parseRecord(input, level))
97
10.2k
      return false;
98
157k
  }
99
21.1k
  return true;
100
31.4k
}
101
102
bool libcdr::CMXParser::parseRecord(librevenge::RVNGInputStream *input, unsigned level)
103
157k
{
104
157k
  if (!input)
105
0
  {
106
0
    return false;
107
0
  }
108
157k
  try
109
157k
  {
110
157k
    m_collector->collectLevel(level);
111
10.4M
    while (!input->isEnd() && readU8(input, m_bigEndian) == 0)
112
10.2M
    {
113
10.2M
    }
114
157k
    if (!input->isEnd())
115
157k
      input->seek(-1, librevenge::RVNG_SEEK_CUR);
116
406
    else
117
406
      return true;
118
157k
    unsigned fourCC = readU32(input, m_bigEndian);
119
157k
    unsigned long length = readU32(input, m_bigEndian);
120
157k
    const unsigned long maxLength = getRemainingLength(input);
121
157k
    if (length > maxLength)
122
26.3k
      length = maxLength;
123
157k
    long endPosition = input->tell() + length;
124
125
157k
    CDR_DEBUG_MSG(("Record: level %u %s, length: 0x%.8lx (%lu)\n", level, toFourCC(fourCC), length, length));
126
127
157k
    if (fourCC == CDR_FOURCC_RIFF || fourCC == CDR_FOURCC_RIFX || fourCC == CDR_FOURCC_LIST)
128
21.2k
    {
129
21.2k
      if (length < 4)
130
26
        return false;
131
#ifdef DEBUG
132
      unsigned listType = readU32(input, m_bigEndian);
133
#else
134
21.2k
      input->seek(4, librevenge::RVNG_SEEK_CUR);
135
21.2k
#endif
136
21.2k
      CDR_DEBUG_MSG(("CMX listType: %s\n", toFourCC(listType)));
137
21.2k
      unsigned long dataSize = length-4;
138
21.2k
      if (!parseRecords(input, dataSize, level+1))
139
5.92k
        return false;
140
21.2k
    }
141
135k
    else
142
135k
      readRecord(fourCC, length, input);
143
144
151k
    if (input->tell() < endPosition)
145
20.3k
      input->seek(endPosition, librevenge::RVNG_SEEK_SET);
146
151k
    return true;
147
157k
  }
148
157k
  catch (...)
149
157k
  {
150
4.25k
    return false;
151
4.25k
  }
152
157k
}
153
154
void libcdr::CMXParser::parseImage(librevenge::RVNGInputStream *input)
155
6.21M
{
156
6.21M
  if (!input)
157
0
  {
158
0
    return;
159
0
  }
160
6.21M
  try
161
6.21M
  {
162
32.2M
    while (!input->isEnd() && readU8(input, m_bigEndian) == 0)
163
26.0M
    {
164
26.0M
    }
165
6.21M
    if (!input->isEnd())
166
4.57M
      input->seek(-1, librevenge::RVNG_SEEK_CUR);
167
1.63M
    else
168
1.63M
      return;
169
4.57M
    unsigned fourCC = readU32(input, m_bigEndian);
170
4.57M
    unsigned long length = readU32(input, m_bigEndian);
171
4.57M
    const unsigned long maxLength = getRemainingLength(input);
172
4.57M
    if (length > maxLength)
173
175k
      length = maxLength;
174
4.57M
    long endPosition = input->tell() + length;
175
176
4.57M
    if (fourCC != CDR_FOURCC_LIST)
177
4.57M
      return;
178
1.41k
    unsigned listType = readU32(input, m_bigEndian);
179
1.41k
    CDR_DEBUG_MSG(("CMX listType: %s\n", toFourCC(listType)));
180
1.41k
    if (listType != CDR_FOURCC_imag)
181
534
      return;
182
876
    unsigned long dataSize = length-4;
183
876
    if (!parseRecords(input, dataSize, (unsigned)-1))
184
0
      return;
185
186
876
    if (input->tell() < endPosition)
187
0
      input->seek(endPosition, librevenge::RVNG_SEEK_SET);
188
876
  }
189
6.21M
  catch (...)
190
6.21M
  {
191
876
  }
192
6.21M
}
193
194
void libcdr::CMXParser::readRecord(unsigned fourCC, unsigned long length, librevenge::RVNGInputStream *input)
195
135k
{
196
135k
  long recordEnd = input->tell() + length;
197
135k
  switch (fourCC)
198
135k
  {
199
36.9k
  case CDR_FOURCC_cont:
200
36.9k
    readCMXHeader(input);
201
36.9k
    return;
202
2.76k
  case CDR_FOURCC_info:
203
2.76k
    readInfo(input);
204
2.76k
    break;
205
12.4k
  case CDR_FOURCC_data:
206
12.4k
    readData(input);
207
12.4k
    break;
208
83.4k
  default:
209
83.4k
    break;
210
135k
  }
211
98.4k
  if (input->tell() < recordEnd)
212
12.4k
    input->seek(recordEnd, librevenge::RVNG_SEEK_SET);
213
98.4k
}
214
215
void libcdr::CMXParser::readCMXHeader(librevenge::RVNGInputStream *input)
216
36.9k
{
217
36.9k
  librevenge::RVNGString tmpString;
218
36.9k
  unsigned i = 0;
219
1.21M
  for (i = 0; i < 32; i++)
220
1.18M
    tmpString.append((char)readU8(input, m_bigEndian));
221
36.9k
  CDR_DEBUG_MSG(("CMX File ID: %s\n", tmpString.cstr()));
222
36.9k
  tmpString.clear();
223
627k
  for (i = 0; i < 16; i++)
224
590k
    tmpString.append((char)readU8(input, m_bigEndian));
225
36.9k
  CDR_DEBUG_MSG(("CMX Platform: %s\n", tmpString.cstr()));
226
36.9k
  tmpString.clear();
227
184k
  for (i = 0; i < 4; i++)
228
147k
    tmpString.append((char)readU8(input, m_bigEndian));
229
36.9k
  CDR_DEBUG_MSG(("CMX Byte Order: %s\n", tmpString.cstr()));
230
36.9k
  if (4 == atoi(tmpString.cstr()))
231
118
    m_bigEndian = true;
232
36.9k
  tmpString.clear();
233
110k
  for (i = 0; i < 2; i++)
234
73.7k
    tmpString.append((char)readU8(input, m_bigEndian));
235
36.9k
  CDR_DEBUG_MSG(("CMX Coordinate Size: %s\n", tmpString.cstr()));
236
36.9k
  auto coordSize = (unsigned short)atoi(tmpString.cstr());
237
36.9k
  switch (coordSize)
238
36.9k
  {
239
17.9k
  case 2:
240
17.9k
    m_precision = libcdr::PRECISION_16BIT;
241
17.9k
    break;
242
5.79k
  case 4:
243
5.79k
    m_precision = libcdr::PRECISION_32BIT;
244
5.79k
    break;
245
13.1k
  default:
246
13.1k
    m_precision = libcdr::PRECISION_UNKNOWN;
247
13.1k
    break;
248
36.9k
  }
249
36.8k
  tmpString.clear();
250
184k
  for (i = 0; i < 4; i++)
251
147k
    tmpString.append((char)readU8(input, m_bigEndian));
252
36.8k
  CDR_DEBUG_MSG(("CMX Version Major: %s\n", tmpString.cstr()));
253
36.8k
  tmpString.clear();
254
184k
  for (i = 0; i < 4; i++)
255
147k
    tmpString.append((char)readU8(input, m_bigEndian));
256
36.8k
  CDR_DEBUG_MSG(("CMX Version Minor: %s\n", tmpString.cstr()));
257
36.8k
  m_unit = readU16(input, m_bigEndian);
258
36.8k
  CDR_DEBUG_MSG(("CMX Base Units: %u\n", m_unit));
259
36.8k
  m_scale = readDouble(input, m_bigEndian);
260
36.8k
  CDR_DEBUG_MSG(("CMX Units Scale: %.9f\n", m_scale));
261
36.8k
  input->seek(12, librevenge::RVNG_SEEK_CUR);
262
36.8k
  unsigned indexSectionOffset = readU32(input, m_bigEndian);
263
#ifdef DEBUG
264
  unsigned infoSectionOffset = readU32(input, m_bigEndian);
265
#else
266
36.8k
  input->seek(4, librevenge::RVNG_SEEK_CUR);
267
36.8k
#endif
268
36.8k
  unsigned thumbnailOffset = readU32(input, m_bigEndian);
269
#ifdef DEBUG
270
  CDRBox box = readBBox(input);
271
#endif
272
36.8k
  CDR_DEBUG_MSG(("CMX Offsets: index section 0x%.8x, info section: 0x%.8x, thumbnail: 0x%.8x\n",
273
36.8k
                 indexSectionOffset, infoSectionOffset, thumbnailOffset));
274
36.8k
  CDR_DEBUG_MSG(("CMX Bounding Box: x: %f, y: %f, w: %f, h: %f\n", box.m_x, box.m_y, box.m_w, box.m_h));
275
36.8k
  if (thumbnailOffset != (unsigned)-1)
276
36.2k
  {
277
36.2k
    long oldOffset = input->tell();
278
36.2k
    input->seek(thumbnailOffset, librevenge::RVNG_SEEK_SET);
279
36.2k
    readDisp(input);
280
36.2k
    input->seek(oldOffset, librevenge::RVNG_SEEK_SET);
281
36.2k
  }
282
36.8k
  if (indexSectionOffset != (unsigned)-1)
283
36.2k
  {
284
36.2k
    long oldOffset = input->tell();
285
36.2k
    input->seek(indexSectionOffset, librevenge::RVNG_SEEK_SET);
286
36.2k
    readIxmr(input);
287
36.2k
    input->seek(oldOffset, librevenge::RVNG_SEEK_SET);
288
36.2k
  }
289
36.8k
}
290
291
void libcdr::CMXParser::readDisp(librevenge::RVNGInputStream *input)
292
36.2k
{
293
36.2k
  unsigned fourCC = readU32(input, m_bigEndian);
294
36.2k
  if (CDR_FOURCC_DISP != fourCC)
295
34.4k
    return;
296
1.73k
  unsigned long length = readU32(input, m_bigEndian);
297
1.73k
  const unsigned long maxLength = getRemainingLength(input);
298
1.73k
  if (length > maxLength)
299
156
    length = maxLength;
300
301
1.73k
  librevenge::RVNGBinaryData previewImage;
302
1.73k
  previewImage.append((unsigned char)0x42);
303
1.73k
  previewImage.append((unsigned char)0x4d);
304
305
1.73k
  previewImage.append((unsigned char)((length+8) & 0x000000ff));
306
1.73k
  previewImage.append((unsigned char)(((length+8) & 0x0000ff00) >> 8));
307
1.73k
  previewImage.append((unsigned char)(((length+8) & 0x00ff0000) >> 16));
308
1.73k
  previewImage.append((unsigned char)(((length+8) & 0xff000000) >> 24));
309
310
1.73k
  previewImage.append((unsigned char)0x00);
311
1.73k
  previewImage.append((unsigned char)0x00);
312
1.73k
  previewImage.append((unsigned char)0x00);
313
1.73k
  previewImage.append((unsigned char)0x00);
314
315
1.73k
  long startPosition = input->tell();
316
1.73k
  input->seek(0x18, librevenge::RVNG_SEEK_CUR);
317
1.73k
  unsigned long lengthX = length + 10 - readU32(input, m_bigEndian);
318
1.73k
  input->seek(startPosition, librevenge::RVNG_SEEK_SET);
319
320
1.73k
  previewImage.append((unsigned char)((lengthX) & 0x000000ff));
321
1.73k
  previewImage.append((unsigned char)(((lengthX) & 0x0000ff00) >> 8));
322
1.73k
  previewImage.append((unsigned char)(((lengthX) & 0x00ff0000) >> 16));
323
1.73k
  previewImage.append((unsigned char)(((lengthX) & 0xff000000) >> 24));
324
325
1.73k
  input->seek(4, librevenge::RVNG_SEEK_CUR);
326
10.5M
  for (unsigned long i = 4; i<length; i++)
327
10.5M
    previewImage.append(readU8(input, m_bigEndian));
328
#if DUMP_PREVIEW_IMAGE
329
  FILE *f = fopen("previewImage.bmp", "wb");
330
  if (f)
331
  {
332
    const unsigned char *tmpBuffer = previewImage.getDataBuffer();
333
    for (unsigned long k = 0; k < previewImage.size(); k++)
334
      fprintf(f, "%c",tmpBuffer[k]);
335
    fclose(f);
336
  }
337
#endif
338
1.73k
}
339
340
const unsigned *libcdr::CMXParser::_getOffsetByType(unsigned short type, const std::map<unsigned short, unsigned> &offsets)
341
300k
{
342
300k
  auto iter = offsets.find(type);
343
300k
  if (iter != offsets.end())
344
75.1k
    return &(iter->second);
345
225k
  return nullptr;
346
300k
}
347
348
void libcdr::CMXParser::readIxmr(librevenge::RVNGInputStream *input)
349
36.2k
{
350
36.2k
  unsigned fourCC = readU32(input, m_bigEndian);
351
36.2k
  if (CDR_FOURCC_ixmr != fourCC)
352
2.17k
    return;
353
34.1k
  readU32(input, m_bigEndian); // Length
354
355
34.1k
  readU16(input, m_bigEndian); // Master ID
356
34.1k
  readU16(input, m_bigEndian); // Size
357
34.1k
  unsigned long recordCount = readU16(input, m_bigEndian);
358
34.1k
  if (recordCount > getRemainingLength(input) / 6)
359
9.57k
    recordCount = getRemainingLength(input) / 6;
360
34.1k
  std::map<unsigned short, unsigned> offsets;
361
39.3M
  for (unsigned long i = 1; i <= recordCount; ++i)
362
39.3M
  {
363
39.3M
    unsigned short indexRecordId = readU16(input, m_bigEndian);
364
39.3M
    unsigned offset = readU32(input, m_bigEndian);
365
39.3M
    offsets[indexRecordId] = offset;
366
39.3M
  }
367
34.1k
  long oldOffset = input->tell();
368
34.1k
  const unsigned *address = nullptr;
369
34.1k
  if ((address = _getOffsetByType(CMX_COLOR_DESCRIPTION_SECTION, offsets)))
370
9.53k
  {
371
9.53k
    input->seek(*address, librevenge::RVNG_SEEK_SET);
372
9.53k
    readRclr(input);
373
9.53k
  }
374
34.1k
  if ((address = _getOffsetByType(CMX_DOT_DASH_DESCRIPTION_SECTION, offsets)))
375
5.27k
  {
376
5.27k
    input->seek(*address, librevenge::RVNG_SEEK_SET);
377
5.27k
    readRdot(input);
378
5.27k
  }
379
34.1k
  if ((address = _getOffsetByType(CMX_PEN_DESCRIPTION_SECTION, offsets)))
380
2.75k
  {
381
2.75k
    input->seek(*address, librevenge::RVNG_SEEK_SET);
382
2.75k
    readRpen(input);
383
2.75k
  }
384
34.1k
  if ((address = _getOffsetByType(CMX_LINE_STYLE_DESCRIPTION_SECTION, offsets)))
385
5.57k
  {
386
5.57k
    input->seek(*address, librevenge::RVNG_SEEK_SET);
387
5.57k
    readRott(input);
388
5.57k
  }
389
34.1k
  if ((address = _getOffsetByType(CMX_OUTLINE_DESCRIPTION_SECTION, offsets)))
390
3.57k
  {
391
3.57k
    input->seek(*address, librevenge::RVNG_SEEK_SET);
392
3.57k
    readRotl(input);
393
3.57k
  }
394
34.1k
  if ((address = _getOffsetByType(CMX_BITMAP_INDEX_TABLE, offsets)))
395
6.91k
  {
396
6.91k
    input->seek(*address, librevenge::RVNG_SEEK_SET);
397
6.91k
    readIxtl(input);
398
6.91k
  }
399
34.1k
  if ((address = _getOffsetByType(CMX_EMBEDDED_FILE_INDEX_TABLE, offsets)))
400
11.8k
  {
401
11.8k
    input->seek(*address, librevenge::RVNG_SEEK_SET);
402
11.8k
    readIxef(input);
403
11.8k
  }
404
34.1k
  if ((address = _getOffsetByType(CMX_PROCEDURE_INDEX_TABLE, offsets)))
405
4.48k
  {
406
4.48k
    input->seek(*address, librevenge::RVNG_SEEK_SET);
407
4.48k
    readIxpc(input);
408
4.48k
  }
409
34.1k
  if ((address = _getOffsetByType(CMX_PAGE_INDEX_TABLE, offsets)))
410
25.2k
  {
411
25.2k
    input->seek(*address, librevenge::RVNG_SEEK_SET);
412
25.2k
    readIxpg(input);
413
25.2k
  }
414
34.1k
  input->seek(oldOffset, librevenge::RVNG_SEEK_SET);
415
34.1k
}
416
417
void libcdr::CMXParser::readCommands(librevenge::RVNGInputStream *input, unsigned length)
418
26.0k
{
419
26.0k
  long endPosition = length + input->tell();
420
4.24M
  while (!input->isEnd() && endPosition > input->tell())
421
4.22M
  {
422
4.22M
    long startPosition = input->tell();
423
4.22M
    int instructionSize = readS16(input, m_bigEndian);
424
4.22M
    int minInstructionSize = 4;
425
4.22M
    if (instructionSize < 0)
426
88.5k
    {
427
88.5k
      instructionSize = readS32(input, m_bigEndian);
428
88.5k
      minInstructionSize += 4;
429
88.5k
    }
430
4.22M
    if (instructionSize < minInstructionSize)
431
3.99M
    {
432
3.99M
      CDR_DEBUG_MSG(("CMXParser::readCommands - invalid instructionSize %i\n", instructionSize));
433
3.99M
      instructionSize = minInstructionSize;
434
3.99M
    }
435
4.22M
    m_nextInstructionOffset = startPosition+instructionSize;
436
4.22M
    short instructionCode = abs(readS16(input, m_bigEndian));
437
4.22M
    CDR_DEBUG_MSG(("CMXParser::readCommands - instructionSize %i, instructionCode %i\n", instructionSize, instructionCode));
438
4.22M
    switch (instructionCode)
439
4.22M
    {
440
281k
    case CMX_Command_BeginPage:
441
281k
      readBeginPage(input);
442
281k
      break;
443
1.14k
    case CMX_Command_BeginLayer:
444
1.14k
      readBeginLayer(input);
445
1.14k
      break;
446
25.6k
    case CMX_Command_BeginGroup:
447
25.6k
      readBeginGroup(input);
448
25.6k
      break;
449
93.4k
    case CMX_Command_PolyCurve:
450
93.4k
      readPolyCurve(input);
451
93.4k
      break;
452
591k
    case CMX_Command_Ellipse:
453
591k
      readEllipse(input);
454
591k
      break;
455
8.39k
    case CMX_Command_Rectangle:
456
8.39k
      readRectangle(input);
457
8.39k
      break;
458
955
    case CMX_Command_JumpAbsolute:
459
955
      readJumpAbsolute(input);
460
955
      break;
461
7.53k
    case CMX_Command_DrawImage:
462
7.53k
      readDrawImage(input);
463
7.53k
      break;
464
3.21M
    default:
465
3.21M
      break;
466
4.22M
    }
467
4.22M
    input->seek(m_nextInstructionOffset, librevenge::RVNG_SEEK_SET);
468
4.22M
  }
469
26.0k
}
470
471
void libcdr::CMXParser::readPage(librevenge::RVNGInputStream *input)
472
34.4k
{
473
34.4k
  unsigned fourCC = readU32(input, m_bigEndian);
474
34.4k
  if (CDR_FOURCC_page != fourCC)
475
8.07k
    return;
476
26.3k
  unsigned length = readU32(input, m_bigEndian);
477
26.3k
  CDR_DEBUG_MSG(("CMXParser::readPage\n"));
478
26.3k
  readCommands(input, length);
479
26.3k
}
480
481
void libcdr::CMXParser::readProc(librevenge::RVNGInputStream *input)
482
0
{
483
0
  unsigned fourCC = readU32(input, m_bigEndian);
484
0
  if (CDR_FOURCC_proc != fourCC)
485
0
    return;
486
0
  unsigned length = readU32(input, m_bigEndian);
487
0
  CDR_DEBUG_MSG(("CMXParser::readProc\n"));
488
0
  readCommands(input, length);
489
0
}
490
491
void libcdr::CMXParser::readBeginPage(librevenge::RVNGInputStream *input)
492
281k
{
493
281k
  CDRBox box;
494
281k
  CDRTransform matrix;
495
281k
  unsigned flags = 0;
496
281k
  if (m_precision == libcdr::PRECISION_32BIT)
497
1.72k
  {
498
1.72k
    unsigned char tagId = 0;
499
1.72k
    unsigned short tagLength = 0;
500
1.72k
    do
501
2.13M
    {
502
2.13M
      long startOffset = input->tell();
503
2.13M
      tagId = readU8(input, m_bigEndian);
504
2.13M
      if (tagId == CMX_Tag_EndTag)
505
1.66k
      {
506
1.66k
        CDR_DEBUG_MSG(("  CMXParser::readBeginPage - tagId %i\n", tagId));
507
1.66k
        break;
508
1.66k
      }
509
2.12M
      tagLength = readTagLength(input, m_bigEndian);
510
2.12M
      CDR_DEBUG_MSG(("  CMXParser::readBeginPage - tagId %i, tagLength %u\n", tagId, tagLength));
511
2.12M
      switch (tagId)
512
2.12M
      {
513
43.0k
      case CMX_Tag_BeginPage_PageSpecification:
514
43.0k
        input->seek(2, librevenge::RVNG_SEEK_CUR);
515
43.0k
        flags = readU32(input, m_bigEndian);
516
43.0k
        box = readBBox(input);
517
43.0k
        break;
518
441k
      case CMX_Tag_BeginPage_Matrix:
519
441k
        matrix = readMatrix(input);
520
441k
        break;
521
1.64M
      default:
522
1.64M
        break;
523
2.12M
      }
524
2.12M
      input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
525
2.12M
    }
526
2.12M
    while (tagId != CMX_Tag_EndTag);
527
1.72k
  }
528
279k
  else if (m_precision == libcdr::PRECISION_16BIT)
529
257k
  {
530
257k
    input->seek(2, librevenge::RVNG_SEEK_CUR);
531
257k
    flags = readU32(input, m_bigEndian);
532
257k
    box = readBBox(input);
533
257k
  }
534
22.7k
  else
535
22.7k
    return;
536
258k
  m_collector->collectPage(0);
537
258k
  m_collector->collectFlags(flags, true);
538
258k
  m_collector->collectPageSize(box.getWidth(), box.getHeight(), box.getMinX(), box.getMinY());
539
258k
}
540
void libcdr::CMXParser::readBeginLayer(librevenge::RVNGInputStream * /* input */)
541
1.14k
{
542
1.14k
}
543
void libcdr::CMXParser::readBeginGroup(librevenge::RVNGInputStream *input)
544
25.6k
{
545
25.6k
  CDRBox box;
546
25.6k
  if (m_precision == libcdr::PRECISION_32BIT)
547
20.5k
  {
548
20.5k
    unsigned char tagId = 0;
549
20.5k
    unsigned short tagLength = 0;
550
20.5k
    do
551
94.9k
    {
552
94.9k
      long startOffset = input->tell();
553
94.9k
      tagId = readU8(input, m_bigEndian);
554
94.9k
      if (tagId == CMX_Tag_EndTag)
555
20.5k
      {
556
20.5k
        CDR_DEBUG_MSG(("  CMXParser::readBeginGroup - tagId %i\n", tagId));
557
20.5k
        break;
558
20.5k
      }
559
74.4k
      tagLength = readTagLength(input, m_bigEndian);
560
74.4k
      CDR_DEBUG_MSG(("  CMXParser::readBeginGroup - tagId %i, tagLength %u\n", tagId, tagLength));
561
74.4k
      switch (tagId)
562
74.4k
      {
563
25.1k
      case CMX_Tag_BeginGroup_GroupSpecification:
564
25.1k
      {
565
25.1k
        box = readBBox(input);
566
25.1k
        /* unsigned short groupCount = */ readU16(input, m_bigEndian);
567
25.1k
        /* unsigned commandCount = */ readU32(input, m_bigEndian);
568
25.1k
        /* unsigned endAddress = */ readU32(input, m_bigEndian);
569
25.1k
        break;
570
0
      }
571
49.2k
      default:
572
49.2k
        break;
573
74.4k
      }
574
74.3k
      input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
575
74.3k
    }
576
74.3k
    while (tagId != CMX_Tag_EndTag);
577
20.5k
  }
578
5.04k
  else if (m_precision == libcdr::PRECISION_16BIT)
579
3.97k
  {
580
3.97k
    box = readBBox(input);
581
3.97k
    /* unsigned short groupCount = */ readU16(input, m_bigEndian);
582
3.97k
    /* unsigned commandCount = */ readU32(input, m_bigEndian);
583
3.97k
    /* unsigned endAddress = */ readU32(input, m_bigEndian);
584
3.97k
  }
585
1.07k
  else
586
1.07k
    return;
587
24.5k
  m_collector->collectBBox(box.getMinX(), box.getMinX() + box.getWidth(), box.getMinY(), box.getMinY() + box.getHeight());
588
24.5k
}
589
590
void libcdr::CMXParser::readPolyCurve(librevenge::RVNGInputStream *input)
591
93.4k
{
592
93.4k
  m_collector->collectObject(1);
593
93.4k
  unsigned long pointNum = 0;
594
93.4k
  std::vector<std::pair<double, double> > points;
595
93.4k
  std::vector<unsigned char> pointTypes;
596
93.4k
  if (m_precision == libcdr::PRECISION_32BIT)
597
52.5k
  {
598
52.5k
    unsigned char tagId = 0;
599
52.5k
    unsigned short tagLength = 0;
600
52.5k
    do
601
1.17M
    {
602
1.17M
      long startOffset = input->tell();
603
1.17M
      tagId = readU8(input, m_bigEndian);
604
1.17M
      if (tagId == CMX_Tag_EndTag)
605
52.0k
      {
606
52.0k
        CDR_DEBUG_MSG(("  CMXParser::readPolyCurve - tagId %i\n", tagId));
607
52.0k
        break;
608
52.0k
      }
609
1.12M
      tagLength = readTagLength(input, m_bigEndian);
610
1.12M
      CDR_DEBUG_MSG(("  CMXParser::readPolyCurve - tagId %i, tagLength %u\n", tagId, tagLength));
611
1.12M
      switch (tagId)
612
1.12M
      {
613
100k
      case CMX_Tag_PolyCurve_RenderingAttr:
614
100k
        readRenderingAttributes(input);
615
100k
        break;
616
202k
      case CMX_Tag_PolyCurve_PointList:
617
202k
        pointNum = readU16(input, m_bigEndian);
618
202k
        if (pointNum > getRemainingLength(input) / (2 * 4 + 1))
619
20.1k
          pointNum = getRemainingLength(input) / (2 * 4 + 1);
620
202k
        points.reserve(pointNum);
621
202k
        pointTypes.reserve(pointNum);
622
38.4M
        for (unsigned long i = 0; i < pointNum; ++i)
623
38.2M
        {
624
38.2M
          std::pair<double, double> point;
625
38.2M
          point.first = readCoordinate(input, m_bigEndian);
626
38.2M
          point.second = readCoordinate(input, m_bigEndian);
627
38.2M
          points.push_back(point);
628
38.2M
        }
629
38.4M
        for (unsigned long j = 0; j < pointNum; ++j)
630
38.2M
          pointTypes.push_back(readU8(input, m_bigEndian));
631
202k
        break;
632
824k
      default:
633
824k
        break;
634
1.12M
      }
635
1.12M
      input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
636
1.12M
    }
637
1.12M
    while (tagId != CMX_Tag_EndTag);
638
52.5k
  }
639
40.9k
  else if (m_precision == libcdr::PRECISION_16BIT)
640
37.0k
  {
641
37.0k
    CDR_DEBUG_MSG(("  CMXParser::readPolyCurve\n"));
642
37.0k
    if (!readRenderingAttributes(input))
643
10.0k
      return;
644
26.9k
    pointNum = readU16(input, m_bigEndian);
645
26.9k
    const unsigned long maxPoints = getRemainingLength(input) / (2 * 2 + 1);
646
26.9k
    if (pointNum > maxPoints)
647
22.6k
      pointNum = maxPoints;
648
11.4M
    for (unsigned long i = 0; i < pointNum; ++i)
649
11.3M
    {
650
11.3M
      std::pair<double, double> point;
651
11.3M
      point.first = readCoordinate(input, m_bigEndian);
652
11.3M
      point.second = readCoordinate(input, m_bigEndian);
653
11.3M
      points.push_back(point);
654
11.3M
    }
655
11.4M
    for (unsigned long j = 0; j < pointNum; ++j)
656
11.3M
      pointTypes.push_back(readU8(input, m_bigEndian));
657
26.9k
  }
658
3.88k
  else
659
3.88k
    return;
660
661
79.0k
  outputPath(points, pointTypes);
662
79.0k
  m_collector->collectLevel(1);
663
79.0k
}
664
665
void libcdr::CMXParser::readEllipse(librevenge::RVNGInputStream *input)
666
591k
{
667
591k
  m_collector->collectObject(1);
668
591k
  double angle1 = 0.0;
669
591k
  double angle2 = 0.0;
670
591k
  double rotation = 0.0;
671
591k
  bool pie = false;
672
673
591k
  double cx = 0.0;
674
591k
  double cy = 0.0;
675
591k
  double rx = 0.0;
676
591k
  double ry = 0.0;
677
678
591k
  if (m_precision == libcdr::PRECISION_32BIT)
679
1.60k
  {
680
1.60k
    unsigned char tagId = 0;
681
1.60k
    unsigned short tagLength = 0;
682
1.60k
    do
683
2.72M
    {
684
2.72M
      long startOffset = input->tell();
685
2.72M
      tagId = readU8(input, m_bigEndian);
686
2.72M
      if (tagId == CMX_Tag_EndTag)
687
1.39k
      {
688
1.39k
        CDR_DEBUG_MSG(("  CMXParser::readEllipse - tagId %i\n", tagId));
689
1.39k
        break;
690
1.39k
      }
691
2.72M
      tagLength = readTagLength(input, m_bigEndian);
692
2.72M
      CDR_DEBUG_MSG(("  CMXParser::readEllipse - tagId %i, tagLength %u\n", tagId, tagLength));
693
2.72M
      switch (tagId)
694
2.72M
      {
695
98.7k
      case CMX_Tag_Ellips_RenderingAttr:
696
98.7k
        readRenderingAttributes(input);
697
98.7k
        break;
698
282k
      case CMX_Tag_Ellips_EllipsSpecification:
699
282k
        cx = readCoordinate(input, m_bigEndian);
700
282k
        cy = readCoordinate(input, m_bigEndian);
701
282k
        rx = readCoordinate(input, m_bigEndian) / 2.0;
702
282k
        ry = readCoordinate(input, m_bigEndian) / 2.0;
703
282k
        angle1 = readAngle(input, m_bigEndian);
704
282k
        angle2 = readAngle(input, m_bigEndian);
705
282k
        rotation = readAngle(input, m_bigEndian);
706
282k
        pie = (0 != readU8(input, m_bigEndian));
707
2.62M
      default:
708
2.62M
        break;
709
2.72M
      }
710
2.72M
      input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
711
2.72M
    }
712
2.72M
    while (tagId != CMX_Tag_EndTag);
713
1.60k
  }
714
589k
  else if (m_precision == libcdr::PRECISION_16BIT)
715
514k
  {
716
514k
    CDR_DEBUG_MSG(("  CMXParser::readEllipse\n"));
717
514k
    if (!readRenderingAttributes(input))
718
6.56k
      return;
719
508k
    cx = readCoordinate(input, m_bigEndian);
720
508k
    cy = readCoordinate(input, m_bigEndian);
721
508k
    rx = readCoordinate(input, m_bigEndian) / 2.0;
722
508k
    ry = readCoordinate(input, m_bigEndian) / 2.0;
723
508k
    angle1 = readAngle(input, m_bigEndian);
724
508k
    angle2 = readAngle(input, m_bigEndian);
725
508k
    rotation = readAngle(input, m_bigEndian);
726
508k
    pie = (0 != readU8(input, m_bigEndian));
727
508k
  }
728
74.9k
  else
729
74.9k
    return;
730
731
509k
  CDRPath path;
732
509k
  if (!CDR_ALMOST_EQUAL(angle1,angle2))
733
494k
  {
734
494k
    if (angle2 < angle1)
735
471k
      angle2 += 2*M_PI;
736
494k
    double x0 = cx + rx*cos(angle1);
737
494k
    double y0 = cy - ry*sin(angle1);
738
739
494k
    double x1 = cx + rx*cos(angle2);
740
494k
    double y1 = cy - ry*sin(angle2);
741
742
494k
    bool largeArc = (angle2 - angle1 > M_PI || angle2 - angle1 < -M_PI);
743
744
494k
    path.appendMoveTo(x0, y0);
745
494k
    path.appendArcTo(rx, ry, 0.0, largeArc, true, x1, y1);
746
494k
    if (pie)
747
30.7k
    {
748
30.7k
      path.appendLineTo(cx, cy);
749
30.7k
      path.appendLineTo(x0, y0);
750
30.7k
      path.appendClosePath();
751
30.7k
    }
752
494k
  }
753
15.6k
  else
754
15.6k
  {
755
15.6k
    double x0 = cx + rx;
756
15.6k
    double y0 = cy;
757
758
15.6k
    double x1 = cx;
759
15.6k
    double y1 = cy - ry;
760
761
15.6k
    path.appendMoveTo(x0, y0);
762
15.6k
    path.appendArcTo(rx, ry, 0.0, false, true, x1, y1);
763
15.6k
    path.appendArcTo(rx, ry, 0.0, true, true, x0, y0);
764
15.6k
  }
765
509k
  m_collector->collectPath(path);
766
509k
  m_collector->collectRotate(rotation, cx, cy);
767
509k
  m_collector->collectLevel(1);
768
509k
}
769
770
void libcdr::CMXParser::readDrawImage(librevenge::RVNGInputStream *input)
771
7.53k
{
772
7.53k
  m_collector->collectObject(1);
773
7.53k
  CDRBox bBox;
774
7.53k
  CDRTransforms trafos;
775
7.53k
  unsigned short imageRef = 0;
776
7.53k
  if (m_precision == libcdr::PRECISION_32BIT)
777
1.24k
  {
778
1.24k
    unsigned char tagId = 0;
779
1.24k
    unsigned short tagLength = 0;
780
1.24k
    do
781
2.99M
    {
782
2.99M
      long startOffset = input->tell();
783
2.99M
      tagId = readU8(input, m_bigEndian);
784
2.99M
      if (tagId == CMX_Tag_EndTag)
785
1.00k
      {
786
1.00k
        CDR_DEBUG_MSG(("  CMXParser::readDrawImage - tagId %i\n", tagId));
787
1.00k
        break;
788
1.00k
      }
789
2.99M
      tagLength = readTagLength(input, m_bigEndian);
790
2.99M
      CDR_DEBUG_MSG(("  CMXParser::readDrawImage - tagId %i, tagLength %u\n", tagId, tagLength));
791
2.99M
      switch (tagId)
792
2.99M
      {
793
118k
      case CMX_Tag_DrawImage_RenderingAttr:
794
118k
        readRenderingAttributes(input);
795
118k
        break;
796
797k
      case CMX_Tag_DrawImage_DrawImageSpecification:
797
797k
      {
798
797k
        bBox = readBBox(input);
799
797k
        readBBox(input);
800
797k
        trafos.append(readMatrix(input));
801
797k
        /* unsigned short imageType = */ readU16(input, m_bigEndian);
802
797k
        imageRef = readU16(input, m_bigEndian);
803
797k
        break;
804
0
      }
805
2.07M
      default:
806
2.07M
        break;
807
2.99M
      }
808
2.99M
      input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
809
2.99M
    }
810
2.99M
    while (tagId != CMX_Tag_EndTag);
811
1.24k
  }
812
6.28k
  else if (m_precision == libcdr::PRECISION_16BIT)
813
5.56k
  {
814
5.56k
    CDR_DEBUG_MSG(("  CMXParser::readDrawImage\n"));
815
5.56k
    if (!readRenderingAttributes(input))
816
1.05k
      return;
817
4.51k
    bBox = readBBox(input);
818
4.51k
    readBBox(input);
819
4.51k
    trafos.append(readMatrix(input));
820
4.51k
    /* unsigned short imageType = */ readU16(input, m_bigEndian);
821
4.51k
    imageRef = readU16(input, m_bigEndian);
822
4.51k
  }
823
716
  else
824
716
    return;
825
826
5.51k
  m_collector->collectTransform(trafos, false);
827
5.51k
  m_collector->collectBitmap(imageRef, bBox.m_x, bBox.m_x + bBox.m_w, bBox.m_y, bBox.m_y + bBox.m_h);
828
5.51k
  m_collector->collectLevel(1);
829
5.51k
}
830
831
void libcdr::CMXParser::readRectangle(librevenge::RVNGInputStream *input)
832
8.39k
{
833
8.39k
  m_collector->collectObject(1);
834
8.39k
  double cx = 0.0;
835
8.39k
  double cy = 0.0;
836
8.39k
  double width = 0.0;
837
8.39k
  double height = 0.0;
838
8.39k
  double radius = 0.0;
839
8.39k
  double angle = 0.0;
840
8.39k
  if (m_precision == libcdr::PRECISION_32BIT)
841
630
  {
842
630
    unsigned char tagId = 0;
843
630
    unsigned short tagLength = 0;
844
630
    do
845
277k
    {
846
277k
      long startOffset = input->tell();
847
277k
      tagId = readU8(input, m_bigEndian);
848
277k
      if (tagId == CMX_Tag_EndTag)
849
423
      {
850
423
        CDR_DEBUG_MSG(("  CMXParser::readRectangle - tagId %i\n", tagId));
851
423
        break;
852
423
      }
853
277k
      tagLength = readTagLength(input, m_bigEndian);
854
277k
      CDR_DEBUG_MSG(("  CMXParser::readRectangle - tagId %i, tagLength %u\n", tagId, tagLength));
855
277k
      switch (tagId)
856
277k
      {
857
5.36k
      case CMX_Tag_Rectangle_RenderingAttr:
858
5.36k
        readRenderingAttributes(input);
859
5.36k
        break;
860
25.1k
      case CMX_Tag_Rectangle_RectangleSpecification:
861
25.1k
        cx = readCoordinate(input, m_bigEndian);
862
25.1k
        cy = readCoordinate(input, m_bigEndian);
863
25.1k
        width = readCoordinate(input, m_bigEndian);
864
25.1k
        height = readCoordinate(input, m_bigEndian);
865
25.1k
        radius = readCoordinate(input, m_bigEndian);
866
25.1k
        angle = readAngle(input, m_bigEndian);
867
25.1k
        break;
868
246k
      default:
869
246k
        break;
870
277k
      }
871
277k
      input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
872
277k
    }
873
277k
    while (tagId != CMX_Tag_EndTag);
874
630
  }
875
7.76k
  else if (m_precision == libcdr::PRECISION_16BIT)
876
7.45k
  {
877
7.45k
    CDR_DEBUG_MSG(("  CMXParser::readRectangle\n"));
878
7.45k
    if (!readRenderingAttributes(input))
879
401
      return;
880
7.04k
    cx = readCoordinate(input, m_bigEndian);
881
7.04k
    cy = readCoordinate(input, m_bigEndian);
882
7.04k
    width = readCoordinate(input, m_bigEndian);
883
7.04k
    height = readCoordinate(input, m_bigEndian);
884
7.04k
    radius = readCoordinate(input, m_bigEndian);
885
7.04k
    angle = readAngle(input, m_bigEndian);
886
7.04k
  }
887
310
  else
888
310
    return;
889
890
7.47k
  double x0 = cx - width / 2.0;
891
7.47k
  double y0 = cy - height / 2.0;
892
7.47k
  double x1 = cx + width / 2.0;
893
7.47k
  double y1 = cy + height / 2.0;
894
7.47k
  CDRPath path;
895
7.47k
  if (radius > 0.0)
896
5.78k
  {
897
5.78k
    path.appendMoveTo(x0, y0-radius);
898
5.78k
    path.appendLineTo(x0, y1+radius);
899
5.78k
    path.appendQuadraticBezierTo(x0, y1, x0+radius, y1);
900
5.78k
    path.appendLineTo(x1-radius, y1);
901
5.78k
    path.appendQuadraticBezierTo(x1, y1, x1, y1+radius);
902
5.78k
    path.appendLineTo(x1, y0-radius);
903
5.78k
    path.appendQuadraticBezierTo(x1, y0, x1-radius, y0);
904
5.78k
    path.appendLineTo(x0+radius, y0);
905
5.78k
    path.appendQuadraticBezierTo(x0, y0, x0, y0-radius);
906
5.78k
  }
907
1.68k
  else
908
1.68k
  {
909
1.68k
    path.appendMoveTo(x0, y0);
910
1.68k
    path.appendLineTo(x0, y1);
911
1.68k
    path.appendLineTo(x1, y1);
912
1.68k
    path.appendLineTo(x1, y0);
913
1.68k
    path.appendLineTo(x0, y0);
914
1.68k
  }
915
7.47k
  m_collector->collectPath(path);
916
7.47k
  m_collector->collectRotate(angle, cx, cy);
917
7.47k
  m_collector->collectLevel(1);
918
7.47k
}
919
920
void libcdr::CMXParser::readBeginProcedure(librevenge::RVNGInputStream *input)
921
0
{
922
0
  if (m_precision == libcdr::PRECISION_32BIT)
923
0
  {
924
0
    unsigned char tagId = 0;
925
0
    unsigned short tagLength = 0;
926
0
    do
927
0
    {
928
0
      long startOffset = input->tell();
929
0
      tagId = readU8(input, m_bigEndian);
930
0
      if (tagId == CMX_Tag_EndTag)
931
0
      {
932
0
        CDR_DEBUG_MSG(("  CMXParser::readBeginProcedure - tagId %i\n", tagId));
933
0
        break;
934
0
      }
935
0
      tagLength = readTagLength(input, m_bigEndian);
936
0
      CDR_DEBUG_MSG(("  CMXParser::readBeginProcedure - tagId %i, tagLength %u\n", tagId, tagLength));
937
0
      switch (tagId)
938
0
      {
939
0
      case CMX_Tag_BeginProcedure_ProcedureSpecification:
940
        /* unsigned flags = */
941
0
        readU32(input, m_bigEndian);
942
0
        /* CDRBox bBox = */ readBBox(input);
943
0
        /* unsigned endOffset = */ readU32(input, m_bigEndian);
944
0
        /* unsigned short groupCount = */ readU16(input, m_bigEndian);
945
0
        /* unsigned tally = */ readU32(input, m_bigEndian);
946
0
        break;
947
0
      default:
948
0
        break;
949
0
      }
950
0
      input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
951
0
    }
952
0
    while (tagId != CMX_Tag_EndTag);
953
0
  }
954
0
  else if (m_precision == libcdr::PRECISION_16BIT)
955
0
  {
956
0
    CDR_DEBUG_MSG(("  CMXParser::readBeginProcedure\n"));
957
0
    /* unsigned flags = */ readU32(input, m_bigEndian);
958
0
    /* CDRBox bBox = */ readBBox(input);
959
0
    /* unsigned endOffset = */ readU32(input, m_bigEndian);
960
0
    /* unsigned short groupCount = */ readU16(input, m_bigEndian);
961
0
    /* unsigned tally = */ readU32(input, m_bigEndian);
962
0
  }
963
0
  else
964
0
    return;
965
0
}
966
967
libcdr::CDRTransform libcdr::CMXParser::readMatrix(librevenge::RVNGInputStream *input)
968
1.39M
{
969
1.39M
  CDRTransform matrix;
970
1.39M
  unsigned short type = readU16(input, m_bigEndian);
971
1.39M
  if (type > 1)
972
1.12M
  {
973
1.12M
    double v0 = readDouble(input, m_bigEndian);
974
1.12M
    double v3 = readDouble(input, m_bigEndian);
975
1.12M
    double v1 = readDouble(input, m_bigEndian);
976
1.12M
    double v4 = readDouble(input, m_bigEndian);
977
1.12M
    double x0 = readDouble(input, m_bigEndian) ;
978
1.12M
    double y0 = readDouble(input, m_bigEndian);
979
1.12M
    if (m_precision == PRECISION_32BIT)
980
1.12M
    {
981
1.12M
      x0 /= 254000.0;
982
1.12M
      y0 /= 254000.0;
983
1.12M
    }
984
4.66k
    else if (m_precision == PRECISION_16BIT)
985
4.61k
    {
986
4.61k
      x0 /= 1000.0;
987
4.61k
      y0 /= 1000.0;
988
4.61k
    }
989
46
    else
990
46
      return CDRTransform();
991
1.12M
    return libcdr::CDRTransform(v0, v1, x0, v3, v4, y0);
992
1.12M
  }
993
263k
  else
994
263k
    return matrix;
995
1.39M
}
996
997
libcdr::CDRBox libcdr::CMXParser::readBBox(librevenge::RVNGInputStream *input)
998
2.93M
{
999
2.93M
  double x0 = readCoordinate(input, m_bigEndian);
1000
2.93M
  double y0 = readCoordinate(input, m_bigEndian);
1001
2.93M
  double x1 = readCoordinate(input, m_bigEndian);
1002
2.93M
  double y1 = readCoordinate(input, m_bigEndian);
1003
2.93M
  CDRBox box(x0, y0, x1, y1);
1004
2.93M
  return box;
1005
2.93M
}
1006
1007
librevenge::RVNGString libcdr::CMXParser::readString(librevenge::RVNGInputStream *input)
1008
13.0k
{
1009
13.0k
  unsigned long count = readU16(input, m_bigEndian);
1010
13.0k
  if (count > getRemainingLength(input))
1011
302
    count = getRemainingLength(input);
1012
13.0k
  librevenge::RVNGString tmpString;
1013
4.79M
  for (unsigned long i = 0; i < count; ++i)
1014
4.78M
    tmpString.append((char)readU8(input, m_bigEndian));
1015
13.0k
  return tmpString;
1016
13.0k
}
1017
1018
bool libcdr::CMXParser::readLens(librevenge::RVNGInputStream *input)
1019
561k
{
1020
561k
  unsigned char lensType = readU8(input, m_bigEndian);
1021
561k
  switch (lensType)
1022
561k
  {
1023
10.8k
  case 1: // Glass
1024
10.8k
  {
1025
10.8k
    unsigned char tintMethod = readU8(input, m_bigEndian);
1026
10.8k
    unsigned short uniformRate = readU16(input, m_bigEndian);
1027
10.8k
    /* unsigned short colorRef = */ readU16(input, m_bigEndian);
1028
10.8k
    /* unsigned short rangeProcRef = */ readU16(input, m_bigEndian);
1029
10.8k
    if (tintMethod == 0)
1030
6.32k
      m_collector->collectFillOpacity((double)uniformRate / 1000.0);
1031
10.8k
    break;
1032
0
  }
1033
579
  case 2: // Magnifying
1034
579
  {
1035
579
    /* unsigned short uniformRate = */ readU16(input, m_bigEndian);
1036
579
    /* unsigned short rangeProcRef = */ readU16(input, m_bigEndian);
1037
579
    break;
1038
0
  }
1039
1.26k
  case 3: // Fisheye
1040
1.26k
  {
1041
1.26k
    /* unsigned short uniformRate = */ readU16(input, m_bigEndian);
1042
1.26k
    /* unsigned short rangeProcRef = */ readU16(input, m_bigEndian);
1043
1.26k
    break;
1044
0
  }
1045
6.26k
  case 4: // Wireframe
1046
6.26k
  {
1047
6.26k
    /* unsigned char outlineMethod = */ readU8(input, m_bigEndian);
1048
6.26k
    /* unsigned short outlineColorRef = */ readU16(input, m_bigEndian);
1049
6.26k
    /* unsigned char fillMethod = */ readU8(input, m_bigEndian);
1050
6.26k
    /* unsigned short fillColorRef = */ readU16(input, m_bigEndian);
1051
6.26k
    /* unsigned short rangeProcRef = */ readU16(input, m_bigEndian);
1052
6.26k
    break;
1053
0
  }
1054
542k
  default:
1055
542k
    if (m_precision == libcdr::PRECISION_16BIT)
1056
8.75k
      return false;
1057
534k
    break;
1058
561k
  }
1059
552k
  return true;
1060
561k
}
1061
1062
bool libcdr::CMXParser::readFill(librevenge::RVNGInputStream *input)
1063
893k
{
1064
893k
  libcdr::CDRColor color1;
1065
893k
  libcdr::CDRColor color2;
1066
893k
  libcdr::CDRImageFill imageFill;
1067
893k
  libcdr::CDRGradient gradient;
1068
893k
  auto fillId = (unsigned)input->tell();
1069
893k
  unsigned fillType = readU16(input, m_bigEndian);
1070
893k
  switch (fillType)
1071
893k
  {
1072
91.7k
  case 1: // Uniform
1073
91.7k
    if (m_precision == libcdr::PRECISION_32BIT)
1074
90.8k
    {
1075
90.8k
      unsigned char tagId = 0;
1076
90.8k
      unsigned short tagLength = 0;
1077
90.8k
      do
1078
29.8M
      {
1079
29.8M
        long startOffset = input->tell();
1080
29.8M
        tagId = readU8(input, m_bigEndian);
1081
29.8M
        if (tagId == CMX_Tag_EndTag)
1082
90.7k
        {
1083
90.7k
          CDR_DEBUG_MSG(("    Solid fill - tagId %i\n", tagId));
1084
90.7k
          break;
1085
90.7k
        }
1086
29.7M
        tagLength = readTagLength(input, m_bigEndian);
1087
29.7M
        CDR_DEBUG_MSG(("    Solid fill - tagId %i, tagLength %u\n", tagId, tagLength));
1088
29.7M
        switch (tagId)
1089
29.7M
        {
1090
5.82M
        case CMX_Tag_RenderAttr_FillSpec_Uniform:
1091
5.82M
        {
1092
5.82M
          unsigned colorRef = readU16(input, m_bigEndian);
1093
5.82M
          color1 = getPaletteColor(colorRef);
1094
5.82M
          readU16(input, m_bigEndian);
1095
5.82M
          break;
1096
0
        }
1097
23.9M
        default:
1098
23.9M
          break;
1099
29.7M
        }
1100
29.7M
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1101
29.7M
      }
1102
29.7M
      while (tagId != CMX_Tag_EndTag);
1103
90.8k
    }
1104
931
    else if (m_precision == libcdr::PRECISION_16BIT)
1105
931
    {
1106
931
      CDR_DEBUG_MSG(("    Solid fill\n"));
1107
931
      unsigned colorRef = readU16(input, m_bigEndian);
1108
931
      color1 = getPaletteColor(colorRef);
1109
931
      readU16(input, m_bigEndian);
1110
931
    }
1111
91.6k
    break;
1112
91.6k
  case 2:  // Fountain
1113
14.3k
    if (m_precision == libcdr::PRECISION_32BIT)
1114
4.13k
    {
1115
4.13k
      unsigned char tagId = 0;
1116
4.13k
      unsigned short tagLength = 0;
1117
4.13k
      do
1118
11.0M
      {
1119
11.0M
        long startOffset = input->tell();
1120
11.0M
        tagId = readU8(input, m_bigEndian);
1121
11.0M
        if (tagId == CMX_Tag_EndTag)
1122
4.03k
        {
1123
4.03k
          CDR_DEBUG_MSG(("    Fountain fill - tagId %i\n", tagId));
1124
4.03k
          break;
1125
4.03k
        }
1126
11.0M
        tagLength = readTagLength(input, m_bigEndian);
1127
11.0M
        CDR_DEBUG_MSG(("    Fountain fill - tagId %i, tagLength %u\n", tagId, tagLength));
1128
11.0M
        switch (tagId)
1129
11.0M
        {
1130
719k
        case CMX_Tag_RenderAttr_FillSpec_Fountain_Base:
1131
719k
        {
1132
719k
          gradient.m_type = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1133
719k
          /* unsigned short screen = */ readU16(input, m_bigEndian);
1134
719k
          gradient.m_edgeOffset = readU16(input, m_bigEndian);
1135
719k
          gradient.m_angle = readAngle(input, m_bigEndian);
1136
719k
          gradient.m_centerXOffset = readS32(input, m_bigEndian);
1137
719k
          gradient.m_centerYOffset = readS32(input, m_bigEndian);
1138
719k
          /* unsigned short steps = */ readU16(input, m_bigEndian);
1139
719k
          gradient.m_mode = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1140
719k
          /* unsigned short rateMethod = */ readU16(input, m_bigEndian);
1141
719k
          /* unsigned short rateValue = */ readU16(input, m_bigEndian);
1142
719k
          break;
1143
0
        }
1144
1.46M
        case CMX_Tag_RenderAttr_FillSpec_Fountain_Color:
1145
1.46M
        {
1146
1.46M
          unsigned long colorCount = readU16(input, m_bigEndian);
1147
1.46M
          if (colorCount > getRemainingLength(input) / 4)
1148
26.9k
            colorCount = getRemainingLength(input) / 4;
1149
153M
          for (unsigned long i = 0; i < colorCount; ++i)
1150
152M
          {
1151
152M
            unsigned short colorRef = readU16(input, m_bigEndian);
1152
152M
            unsigned short offset = readU16(input, m_bigEndian);
1153
152M
            libcdr::CDRGradientStop stop;
1154
152M
            stop.m_color = getPaletteColor(colorRef);
1155
152M
            stop.m_offset = (double)offset / 100.0;
1156
152M
            gradient.m_stops.push_back(stop);
1157
152M
          }
1158
1.46M
          break;
1159
0
        }
1160
8.82M
        default:
1161
8.82M
          break;
1162
11.0M
        }
1163
11.0M
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1164
11.0M
      }
1165
11.0M
      while (tagId != CMX_Tag_EndTag);
1166
4.13k
    }
1167
10.2k
    else if (m_precision == libcdr::PRECISION_16BIT)
1168
10.2k
    {
1169
10.2k
      CDR_DEBUG_MSG(("    Fountain fill\n"));
1170
10.2k
      gradient.m_type = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1171
10.2k
      /* unsigned short screen = */ readU16(input, m_bigEndian);
1172
10.2k
      gradient.m_edgeOffset = readU16(input, m_bigEndian);
1173
10.2k
      gradient.m_angle = readAngle(input, m_bigEndian);
1174
10.2k
      input->seek(2, librevenge::RVNG_SEEK_CUR);
1175
10.2k
      gradient.m_centerXOffset = readS16(input, m_bigEndian);
1176
10.2k
      gradient.m_centerYOffset = readS16(input, m_bigEndian);
1177
10.2k
      /* unsigned short steps = */ readU16(input, m_bigEndian);
1178
10.2k
      gradient.m_mode = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1179
10.2k
      unsigned long colorCount = readU16(input, m_bigEndian);
1180
10.2k
      if (colorCount > getRemainingLength(input) / 4)
1181
2.05k
        colorCount = getRemainingLength(input) / 4;
1182
4.72M
      for (unsigned long i = 0; i < colorCount; ++i)
1183
4.71M
      {
1184
4.71M
        unsigned short colorRef = readU16(input, m_bigEndian);
1185
4.71M
        unsigned short offset = readU16(input, m_bigEndian);
1186
4.71M
        libcdr::CDRGradientStop stop;
1187
4.71M
        stop.m_color = getPaletteColor(colorRef);
1188
4.71M
        stop.m_offset = (double)offset / 100.0;
1189
4.71M
        gradient.m_stops.push_back(stop);
1190
4.71M
      }
1191
10.2k
    }
1192
14.2k
    break;
1193
14.2k
  case 6: // Postscript
1194
2.32k
    CDR_DEBUG_MSG(("    Postscript fill\n"));
1195
2.32k
    if (m_precision == libcdr::PRECISION_32BIT)
1196
1.22k
    {
1197
1.22k
    }
1198
1.10k
    else if (m_precision == libcdr::PRECISION_16BIT)
1199
1.10k
    {
1200
1.10k
      /* unsigned atom = */ readU32(input, m_bigEndian);
1201
1.10k
      unsigned long count = readU16(input, m_bigEndian);
1202
1.10k
      if (count > getRemainingLength(input) / 2)
1203
24
        count = getRemainingLength(input) / 2;
1204
90.5k
      for (unsigned long i = 0; i < count; ++i)
1205
89.4k
        readU16(input, m_bigEndian);
1206
1.10k
      readString(input);
1207
1.10k
    }
1208
2.32k
    break;
1209
968
  case 7: // Two-Color Pattern
1210
3.03k
  case 8: // Monochrome with transparent bitmap
1211
3.03k
    if (m_precision == libcdr::PRECISION_32BIT)
1212
1.37k
    {
1213
1.37k
      unsigned char tagId = 0;
1214
1.37k
      unsigned short tagLength = 0;
1215
1.37k
      do
1216
308k
      {
1217
308k
        long startOffset = input->tell();
1218
308k
        tagId = readU8(input, m_bigEndian);
1219
308k
        if (tagId == CMX_Tag_EndTag)
1220
1.30k
        {
1221
1.30k
          CDR_DEBUG_MSG(("    %s fill - tagId %i\n", fillType == 7 ? "Two-Color Pattern" : "Monochrome with transparent bitmap", tagId));
1222
1.30k
          break;
1223
1.30k
        }
1224
307k
        tagLength = readTagLength(input, m_bigEndian);
1225
307k
        CDR_DEBUG_MSG(("    %s fill - tagId %i, tagLength %u\n", fillType == 7 ? "Two-Color Pattern" : "Monochrome with transparent bitmap", tagId, tagLength));
1226
307k
        switch (tagId)
1227
307k
        {
1228
51.6k
        case CMX_Tag_RenderAttr_FillSpec_MonoBM:
1229
51.6k
        {
1230
51.6k
          unsigned short patternId = readU16(input, m_bigEndian);
1231
51.6k
          input->seek(3, librevenge::RVNG_SEEK_CUR); // CMX_Tag_Tiling
1232
51.6k
          int tmpWidth = readS32(input, m_bigEndian);
1233
51.6k
          int tmpHeight = readS32(input, m_bigEndian);
1234
51.6k
          double tileOffsetX = (double)readU16(input, m_bigEndian) / 100.0;
1235
51.6k
          double tileOffsetY = (double)readU16(input, m_bigEndian) / 100.0;
1236
51.6k
          double rcpOffset = (double)readU16(input, m_bigEndian) / 100.0;
1237
51.6k
          unsigned char flags = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1238
51.6k
          input->seek(1, librevenge::RVNG_SEEK_CUR); // CMX_Tag_EndTag
1239
51.6k
          double patternWidth = (double)tmpWidth / 254000.0;
1240
51.6k
          double patternHeight = (double)tmpHeight / 254000.0;
1241
51.6k
          bool isRelative = false;
1242
51.6k
          if (flags & 0x04)
1243
536
          {
1244
536
            isRelative = true;
1245
536
            patternWidth = (double)tmpWidth / 100.0;
1246
536
            patternHeight = (double)tmpHeight / 100.0;
1247
536
          }
1248
51.6k
          color1 = getPaletteColor(readU16(input, m_bigEndian));
1249
51.6k
          color2 = getPaletteColor(readU16(input, m_bigEndian));
1250
51.6k
          /* unsigned short screen = */ readU16(input, m_bigEndian);
1251
51.6k
          imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1252
51.6k
          break;
1253
0
        }
1254
255k
        default:
1255
255k
          break;
1256
307k
        }
1257
307k
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1258
307k
      }
1259
307k
      while (tagId != CMX_Tag_EndTag);
1260
1.37k
    }
1261
1.66k
    else if (m_precision == libcdr::PRECISION_16BIT)
1262
1.66k
    {
1263
1.66k
      CDR_DEBUG_MSG(("    %s fill\n", fillType == 7 ? "Two-Color Pattern" : "Monochrome with transparent bitmap"));
1264
1.66k
      unsigned short patternId = readU16(input, m_bigEndian);
1265
1.66k
      int tmpWidth = readU16(input, m_bigEndian);
1266
1.66k
      int tmpHeight = readU16(input, m_bigEndian);
1267
1.66k
      double tileOffsetX = (double)readU16(input, m_bigEndian) / 100.0;
1268
1.66k
      double tileOffsetY = (double)readU16(input, m_bigEndian) / 100.0;
1269
1.66k
      double rcpOffset = (double)readU16(input, m_bigEndian) / 100.0;
1270
1.66k
      unsigned char flags = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1271
1.66k
      double patternWidth = (double)tmpWidth / 1000.0;
1272
1.66k
      double patternHeight = (double)tmpHeight / 1000.0;
1273
1.66k
      bool isRelative = false;
1274
1.66k
      if (flags & 0x04)
1275
671
      {
1276
671
        isRelative = true;
1277
671
        patternWidth = (double)tmpWidth / 100.0;
1278
671
        patternHeight = (double)tmpHeight / 100.0;
1279
671
      }
1280
1.66k
      color1 = getPaletteColor(readU16(input, m_bigEndian));
1281
1.66k
      color2 = getPaletteColor(readU16(input, m_bigEndian));
1282
1.66k
      /* unsigned short screen = */ readU16(input, m_bigEndian);
1283
1.66k
      imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1284
1.66k
    }
1285
2.96k
    break;
1286
6.94k
  case 9: // Imported Bitmap
1287
11.6k
  case 10: // Full Color Pattern
1288
11.6k
    if (m_precision == libcdr::PRECISION_32BIT)
1289
9.16k
    {
1290
9.16k
      unsigned char tagId = 0;
1291
9.16k
      unsigned short tagLength = 0;
1292
9.16k
      do
1293
2.11M
      {
1294
2.11M
        long startOffset = input->tell();
1295
2.11M
        tagId = readU8(input, m_bigEndian);
1296
2.11M
        if (tagId == CMX_Tag_EndTag)
1297
9.11k
        {
1298
9.11k
          CDR_DEBUG_MSG(("    %s fill - tagId %i\n", fillType == 9 ? "Imported Bitmap" : "Full Color Pattern", tagId));
1299
9.11k
          break;
1300
9.11k
        }
1301
2.10M
        tagLength = readTagLength(input, m_bigEndian);
1302
2.10M
        CDR_DEBUG_MSG(("    %s fill - tagId %i, tagLength %u\n", fillType == 9 ? "Imported Bitmap" : "Full Color Pattern", tagId, tagLength));
1303
2.10M
        switch (tagId)
1304
2.10M
        {
1305
952k
        case CMX_Tag_RenderAttr_FillSpec_ColorBM:
1306
952k
        {
1307
952k
          unsigned short patternId = readU16(input, m_bigEndian);
1308
952k
          input->seek(3, librevenge::RVNG_SEEK_CUR); // CMX_Tag_Tiling
1309
952k
          int tmpWidth = readS32(input, m_bigEndian);
1310
952k
          int tmpHeight = readS32(input, m_bigEndian);
1311
952k
          double tileOffsetX = (double)readU16(input, m_bigEndian) / 100.0;
1312
952k
          double tileOffsetY = (double)readU16(input, m_bigEndian) / 100.0;
1313
952k
          double rcpOffset = (double)readU16(input, m_bigEndian) / 100.0;
1314
952k
          unsigned char flags = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1315
952k
          input->seek(1, librevenge::RVNG_SEEK_CUR); // CMX_Tag_EndTag
1316
952k
          double patternWidth = (double)tmpWidth / 254000.0;
1317
952k
          double patternHeight = (double)tmpHeight / 254000.0;
1318
952k
          bool isRelative = false;
1319
952k
          if (flags & 0x04)
1320
934
          {
1321
934
            isRelative = true;
1322
934
            patternWidth = (double)tmpWidth / 100.0;
1323
934
            patternHeight = (double)tmpHeight / 100.0;
1324
934
          }
1325
952k
          /* libcdr::CDRBox box = */ readBBox(input);
1326
952k
          imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1327
952k
          break;
1328
0
        }
1329
1.15M
        default:
1330
1.15M
          break;
1331
2.10M
        }
1332
2.10M
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1333
2.10M
      }
1334
2.10M
      while (tagId != CMX_Tag_EndTag);
1335
9.16k
    }
1336
2.51k
    else if (m_precision == libcdr::PRECISION_16BIT)
1337
2.51k
    {
1338
2.51k
      CDR_DEBUG_MSG(("    %s fill\n", fillType == 9 ? "Imported Bitmap" : "Full Color Pattern"));
1339
2.51k
      unsigned short patternId = readU16(input, m_bigEndian);
1340
2.51k
      int tmpWidth = readU16(input, m_bigEndian);
1341
2.51k
      int tmpHeight = readU16(input, m_bigEndian);
1342
2.51k
      double tileOffsetX = (double)readU16(input, m_bigEndian) / 100.0;
1343
2.51k
      double tileOffsetY = (double)readU16(input, m_bigEndian) / 100.0;
1344
2.51k
      double rcpOffset = (double)readU16(input, m_bigEndian) / 100.0;
1345
2.51k
      unsigned char flags = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1346
2.51k
      double patternWidth = (double)tmpWidth / 1000.0;
1347
2.51k
      double patternHeight = (double)tmpHeight / 1000.0;
1348
2.51k
      bool isRelative = false;
1349
2.51k
      if (flags & 0x04)
1350
348
      {
1351
348
        isRelative = true;
1352
348
        patternWidth = (double)tmpWidth / 100.0;
1353
348
        patternHeight = (double)tmpHeight / 100.0;
1354
348
      }
1355
2.51k
      /* libcdr::CDRBox box = */ readBBox(input);
1356
2.51k
      imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1357
2.51k
    }
1358
11.6k
    break;
1359
11.6k
  case 11:
1360
4.72k
    if (m_precision == libcdr::PRECISION_32BIT)
1361
710
    {
1362
710
      unsigned char tagId = 0;
1363
710
      unsigned short tagLength = 0;
1364
710
      do
1365
17.1k
      {
1366
17.1k
        long startOffset = input->tell();
1367
17.1k
        tagId = readU8(input, m_bigEndian);
1368
17.1k
        if (tagId == CMX_Tag_EndTag)
1369
630
        {
1370
630
          CDR_DEBUG_MSG(("    Texture fill - tagId %i\n", tagId));
1371
630
          break;
1372
630
        }
1373
16.5k
        tagLength = readTagLength(input, m_bigEndian);
1374
16.5k
        CDR_DEBUG_MSG(("    Texture fill - tagId %i, tagLength %u\n", tagId, tagLength));
1375
16.5k
        switch (tagId)
1376
16.5k
        {
1377
3.67k
        case CMX_Tag_RenderAttr_FillSpec_Texture:
1378
3.67k
        {
1379
3.67k
          unsigned char subTagId = 0;
1380
3.67k
          unsigned short subTagLength = 0;
1381
3.67k
          do
1382
78.5k
          {
1383
78.5k
            long subStartOffset = input->tell();
1384
78.5k
            subTagId = readU8(input, m_bigEndian);
1385
78.5k
            if (subTagId == CMX_Tag_EndTag)
1386
3.61k
              break;
1387
74.9k
            subTagLength = readTagLength(input, m_bigEndian);
1388
74.9k
            switch (subTagId)
1389
74.9k
            {
1390
47.2k
            case CMX_Tag_RenderAttr_FillSpec_ColorBM:
1391
47.2k
            {
1392
47.2k
              unsigned short patternId = readU16(input, m_bigEndian);
1393
47.2k
              input->seek(3, librevenge::RVNG_SEEK_CUR); // CMX_Tag_Tiling
1394
47.2k
              int tmpWidth = readS32(input, m_bigEndian);
1395
47.2k
              int tmpHeight = readS32(input, m_bigEndian);
1396
47.2k
              double tileOffsetX = (double)readU16(input, m_bigEndian) / 100.0;
1397
47.2k
              double tileOffsetY = (double)readU16(input, m_bigEndian) / 100.0;
1398
47.2k
              double rcpOffset = (double)readU16(input, m_bigEndian) / 100.0;
1399
47.2k
              unsigned char flags = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1400
47.2k
              input->seek(1, librevenge::RVNG_SEEK_CUR); // CMX_Tag_EndTag
1401
47.2k
              double patternWidth = (double)tmpWidth / 254000.0;
1402
47.2k
              double patternHeight = (double)tmpHeight / 254000.0;
1403
47.2k
              bool isRelative = false;
1404
47.2k
              if (flags & 0x04)
1405
621
              {
1406
621
                isRelative = true;
1407
621
                patternWidth = (double)tmpWidth / 100.0;
1408
621
                patternHeight = (double)tmpHeight / 100.0;
1409
621
              }
1410
47.2k
              /* libcdr::CDRBox box = */ readBBox(input);
1411
47.2k
              imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1412
47.2k
              break;
1413
0
            }
1414
27.6k
            default:
1415
27.6k
              break;
1416
74.9k
            }
1417
74.8k
            input->seek(subStartOffset + subTagLength, librevenge::RVNG_SEEK_SET);
1418
74.8k
          }
1419
74.8k
          while (subTagId != CMX_Tag_EndTag);
1420
3.67k
        }
1421
16.4k
        default:
1422
16.4k
          break;
1423
16.5k
        }
1424
16.4k
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1425
16.4k
      }
1426
16.4k
      while (tagId != CMX_Tag_EndTag);
1427
710
    }
1428
4.01k
    else if (m_precision == libcdr::PRECISION_16BIT)
1429
4.01k
    {
1430
4.01k
      CDR_DEBUG_MSG(("    Texture fill\n"));
1431
4.01k
      unsigned short patternId = readU16(input, m_bigEndian);
1432
4.01k
      int tmpWidth = readU16(input, m_bigEndian);
1433
4.01k
      int tmpHeight = readU16(input, m_bigEndian);
1434
4.01k
      double tileOffsetX = (double)readU16(input, m_bigEndian) / 100.0;
1435
4.01k
      double tileOffsetY = (double)readU16(input, m_bigEndian) / 100.0;
1436
4.01k
      double rcpOffset = (double)readU16(input, m_bigEndian) / 100.0;
1437
4.01k
      unsigned char flags = (unsigned char)(readU16(input, m_bigEndian) & 0xff);
1438
4.01k
      double patternWidth = (double)tmpWidth / 1000.0;
1439
4.01k
      double patternHeight = (double)tmpHeight / 1000.0;
1440
4.01k
      bool isRelative = false;
1441
4.01k
      if (flags & 0x04)
1442
1.48k
      {
1443
1.48k
        isRelative = true;
1444
1.48k
        patternWidth = (double)tmpWidth / 100.0;
1445
1.48k
        patternHeight = (double)tmpHeight / 100.0;
1446
1.48k
      }
1447
4.01k
      /* libcdr::CDRBox box = */ readBBox(input);
1448
4.01k
      /* unsigned char reserved = */ readU8(input, m_bigEndian);
1449
4.01k
      /* unsigned res = */ readU32(input, m_bigEndian);
1450
4.01k
      /* unsigned short maxEdge = */ readU16(input, m_bigEndian);
1451
4.01k
      /* librevenge::RVNGString lib = */ readString(input);
1452
4.01k
      /* librevenge::RVNGString name = */ readString(input);
1453
4.01k
      /* librevenge::RVNGString stl = */ readString(input);
1454
4.01k
      unsigned long count = readU16(input, m_bigEndian);
1455
4.01k
      if (count > getRemainingLength(input) / 8)
1456
2.08k
        count = getRemainingLength(input) / 8;
1457
6.49M
      for (unsigned long i = 0; i < count; ++i)
1458
6.49M
      {
1459
6.49M
        readU16(input, m_bigEndian);
1460
6.49M
        readU16(input, m_bigEndian);
1461
6.49M
        readU16(input, m_bigEndian);
1462
6.49M
        readU16(input, m_bigEndian);
1463
6.49M
      }
1464
4.01k
      imageFill = libcdr::CDRImageFill(patternId, patternWidth, patternHeight, isRelative, tileOffsetX, tileOffsetY, rcpOffset, flags);
1465
4.01k
    }
1466
4.64k
    break;
1467
765k
  default:
1468
765k
    if (m_precision == libcdr::PRECISION_16BIT)
1469
2.31k
      return false;
1470
763k
    break;
1471
893k
  }
1472
890k
  m_collector->collectFillStyle(fillId, CDRFillStyle((unsigned short)fillType, color1, color2, gradient, imageFill));
1473
890k
  m_collector->collectFillStyleId(fillId);
1474
890k
  return true;
1475
893k
}
1476
1477
bool libcdr::CMXParser::readRenderingAttributes(librevenge::RVNGInputStream *input)
1478
887k
{
1479
887k
  unsigned char tagId = 0;
1480
887k
  unsigned short tagLength = 0;
1481
887k
  unsigned char bitMask = readU8(input, m_bigEndian);
1482
887k
  if (bitMask & 0x01) // fill
1483
60.3k
  {
1484
60.3k
    if (m_precision == libcdr::PRECISION_32BIT)
1485
37.5k
    {
1486
37.5k
      do
1487
15.6M
      {
1488
15.6M
        long startOffset = input->tell();
1489
15.6M
        tagId = readU8(input, m_bigEndian);
1490
15.6M
        if (tagId == CMX_Tag_EndTag)
1491
36.9k
        {
1492
36.9k
          CDR_DEBUG_MSG(("  Fill specification - tagId %i\n", tagId));
1493
36.9k
          break;
1494
36.9k
        }
1495
15.6M
        tagLength = readTagLength(input, m_bigEndian);
1496
15.6M
        CDR_DEBUG_MSG(("  Fill specification - tagId %i, tagLength %u\n", tagId, tagLength));
1497
15.6M
        switch (tagId)
1498
15.6M
        {
1499
870k
        case CMX_Tag_RenderAttr_FillSpec:
1500
870k
          readFill(input);
1501
870k
          break;
1502
14.7M
        default:
1503
14.7M
          break;
1504
15.6M
        }
1505
15.6M
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1506
15.6M
      }
1507
15.6M
      while (tagId != CMX_Tag_EndTag);
1508
37.5k
    }
1509
22.8k
    else if (m_precision == libcdr::PRECISION_16BIT)
1510
22.8k
    {
1511
22.8k
      CDR_DEBUG_MSG(("  Fill specification\n"));
1512
22.8k
      if (!readFill(input))
1513
2.31k
        return false;
1514
22.8k
    }
1515
60.3k
  }
1516
884k
  if (bitMask & 0x02) // outline
1517
61.0k
  {
1518
61.0k
    CDRLineStyle lineStyle;
1519
61.0k
    auto lineStyleId = (unsigned)input->tell();
1520
61.0k
    if (m_precision == libcdr::PRECISION_32BIT)
1521
22.5k
    {
1522
22.5k
      do
1523
6.57M
      {
1524
6.57M
        long startOffset = input->tell();
1525
6.57M
        tagId = readU8(input, m_bigEndian);
1526
6.57M
        if (tagId == CMX_Tag_EndTag)
1527
22.5k
        {
1528
22.5k
          CDR_DEBUG_MSG(("  Outline specification - tagId %i\n", tagId));
1529
22.5k
          break;
1530
22.5k
        }
1531
6.55M
        tagLength = readTagLength(input, m_bigEndian);
1532
6.55M
        CDR_DEBUG_MSG(("  Outline specification - tagId %i, tagLength %u\n", tagId, tagLength));
1533
6.55M
        switch (tagId)
1534
6.55M
        {
1535
306k
        case CMX_Tag_RenderAttr_OutlineSpec:
1536
306k
          lineStyle = getLineStyle(readU16(input, m_bigEndian));
1537
306k
          break;
1538
6.24M
        default:
1539
6.24M
          break;
1540
6.55M
        }
1541
6.55M
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1542
6.55M
      }
1543
6.55M
      while (tagId != CMX_Tag_EndTag);
1544
22.5k
    }
1545
38.4k
    else if (m_precision == libcdr::PRECISION_16BIT)
1546
38.4k
    {
1547
38.4k
      CDR_DEBUG_MSG(("  Outline specification\n"));
1548
38.4k
      lineStyle = getLineStyle(readU16(input, m_bigEndian));
1549
38.4k
    }
1550
60.9k
    m_collector->collectLineStyle(lineStyleId, lineStyle);
1551
60.9k
    m_collector->collectLineStyleId(lineStyleId);
1552
60.9k
  }
1553
884k
  if (bitMask & 0x04) // lens
1554
21.8k
  {
1555
21.8k
    if (m_precision == libcdr::PRECISION_32BIT)
1556
3.46k
    {
1557
3.46k
      do
1558
7.09M
      {
1559
7.09M
        long startOffset = input->tell();
1560
7.09M
        tagId = readU8(input, m_bigEndian);
1561
7.09M
        if (tagId == CMX_Tag_EndTag)
1562
3.37k
        {
1563
3.37k
          CDR_DEBUG_MSG(("  Lens specification - tagId %i\n", tagId));
1564
3.37k
          break;
1565
3.37k
        }
1566
7.09M
        tagLength = readTagLength(input, m_bigEndian);
1567
7.09M
        CDR_DEBUG_MSG(("  Lens specification - tagId %i, tagLength %u\n", tagId, tagLength));
1568
7.09M
        switch (tagId)
1569
7.09M
        {
1570
543k
        case CMX_Tag_RenderAttr_LensSpec_Base:
1571
543k
          readLens(input);
1572
543k
          break;
1573
6.54M
        default:
1574
6.54M
          break;
1575
7.09M
        }
1576
7.09M
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1577
7.09M
      }
1578
7.09M
      while (tagId != CMX_Tag_EndTag);
1579
3.46k
    }
1580
18.3k
    else if (m_precision == libcdr::PRECISION_16BIT)
1581
18.3k
    {
1582
18.3k
      CDR_DEBUG_MSG(("  Lens specification\n"));
1583
18.3k
      if (!readLens(input))
1584
8.75k
        return false;
1585
18.3k
    }
1586
21.8k
  }
1587
875k
  if (bitMask & 0x08) // canvas
1588
5.55k
  {
1589
5.55k
    if (m_precision == libcdr::PRECISION_32BIT)
1590
3.71k
    {
1591
3.71k
      do
1592
783k
      {
1593
783k
        long startOffset = input->tell();
1594
783k
        tagId = readU8(input, m_bigEndian);
1595
783k
        if (tagId == CMX_Tag_EndTag)
1596
3.68k
        {
1597
3.68k
          CDR_DEBUG_MSG(("  Canvas specification - tagId %i\n", tagId));
1598
3.68k
          break;
1599
3.68k
        }
1600
780k
        tagLength = readTagLength(input, m_bigEndian);
1601
780k
        CDR_DEBUG_MSG(("  Canvas specification - tagId %i, tagLength %u\n", tagId, tagLength));
1602
780k
        switch (tagId)
1603
780k
        {
1604
780k
        default:
1605
780k
          break;
1606
780k
        }
1607
780k
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1608
780k
      }
1609
780k
      while (tagId != CMX_Tag_EndTag);
1610
3.71k
    }
1611
1.83k
    else if (m_precision == libcdr::PRECISION_16BIT)
1612
1.83k
    {
1613
1.83k
      CDR_DEBUG_MSG(("  Canvas specification\n"));
1614
1.83k
      return false;
1615
1.83k
    }
1616
5.55k
  }
1617
873k
  if (bitMask & 0x10) // container
1618
8.61k
  {
1619
8.61k
    if (m_precision == libcdr::PRECISION_32BIT)
1620
3.44k
    {
1621
3.44k
      do
1622
274k
      {
1623
274k
        long startOffset = input->tell();
1624
274k
        tagId = readU8(input, m_bigEndian);
1625
274k
        if (tagId == CMX_Tag_EndTag)
1626
3.39k
        {
1627
3.39k
          CDR_DEBUG_MSG(("  Container specification - tagId %i\n", tagId));
1628
3.39k
          break;
1629
3.39k
        }
1630
271k
        tagLength = readTagLength(input, m_bigEndian);
1631
271k
        CDR_DEBUG_MSG(("  Container specification - tagId %i, tagLength %u\n", tagId, tagLength));
1632
271k
        switch (tagId)
1633
271k
        {
1634
271k
        default:
1635
271k
          break;
1636
271k
        }
1637
271k
        input->seek(startOffset + tagLength, librevenge::RVNG_SEEK_SET);
1638
271k
      }
1639
271k
      while (tagId != CMX_Tag_EndTag);
1640
3.44k
    }
1641
5.17k
    else if (m_precision == libcdr::PRECISION_16BIT)
1642
5.17k
    {
1643
5.17k
      CDR_DEBUG_MSG(("  Container specification\n"));
1644
5.17k
      return false;
1645
5.17k
    }
1646
8.61k
  }
1647
868k
  return true;
1648
873k
}
1649
1650
void libcdr::CMXParser::readJumpAbsolute(librevenge::RVNGInputStream *input)
1651
955
{
1652
955
  if (m_precision == libcdr::PRECISION_32BIT)
1653
75
  {
1654
75
    unsigned char tagId = 0;
1655
75
    unsigned short tagLength = 0;
1656
75
    do
1657
1.44k
    {
1658
1.44k
      long offset = input->tell();
1659
1.44k
      tagId = readU8(input, m_bigEndian);
1660
1.44k
      if (tagId == CMX_Tag_EndTag)
1661
40
      {
1662
40
        CDR_DEBUG_MSG(("  CMXParser::readJumpAbsolute - tagId %i\n", tagId));
1663
40
        break;
1664
40
      }
1665
1.40k
      tagLength = readTagLength(input, m_bigEndian);
1666
1.40k
      CDR_DEBUG_MSG(("  CMXParser::readJumpAbsolute - tagId %i, tagLength %u\n", tagId, tagLength));
1667
1.40k
      switch (tagId)
1668
1.40k
      {
1669
276
      case CMX_Tag_JumpAbsolute_Offset:
1670
276
        m_nextInstructionOffset = readU32(input, m_bigEndian);
1671
1.37k
      default:
1672
1.37k
        break;
1673
1.40k
      }
1674
1.37k
      input->seek(offset + tagLength, librevenge::RVNG_SEEK_SET);
1675
1.37k
    }
1676
1.37k
    while (tagId != CMX_Tag_EndTag);
1677
75
  }
1678
880
  else if (m_precision == libcdr::PRECISION_16BIT)
1679
352
    m_nextInstructionOffset = readU32(input, m_bigEndian);
1680
528
  else
1681
528
    return;
1682
955
}
1683
1684
void libcdr::CMXParser::readRclr(librevenge::RVNGInputStream *input)
1685
9.53k
{
1686
9.53k
  unsigned fourCC = readU32(input, m_bigEndian);
1687
9.53k
  if (CDR_FOURCC_rclr != fourCC)
1688
6.54k
    return;
1689
2.99k
  /* unsigned length = */ readU32(input, m_bigEndian);
1690
1691
2.99k
  unsigned long numRecords = readU16(input, m_bigEndian);
1692
2.99k
  CDR_DEBUG_MSG(("CMXParser::readRclr - numRecords %li\n", numRecords));
1693
2.99k
  sanitizeNumRecords(numRecords, m_precision, 2, 2 + 0, 2, getRemainingLength(input));
1694
312k
  for (unsigned j = 1; j <= numRecords; ++j)
1695
309k
  {
1696
309k
    CDR_DEBUG_MSG(("Color index %i\n", j));
1697
309k
    unsigned char colorModel = 0;
1698
309k
    if (m_precision == libcdr::PRECISION_32BIT)
1699
26.8k
    {
1700
26.8k
      unsigned char tagId = 0;
1701
26.8k
      do
1702
1.31M
      {
1703
1.31M
        long offset = input->tell();
1704
1.31M
        tagId = readU8(input, m_bigEndian);
1705
1.31M
        if (tagId == CMX_Tag_EndTag)
1706
26.8k
          break;
1707
1.28M
        unsigned short tagLength = readTagLength(input, m_bigEndian);
1708
1.28M
        switch (tagId)
1709
1.28M
        {
1710
18.8k
        case CMX_Tag_DescrSection_Color_Base:
1711
18.8k
          colorModel = readU8(input, m_bigEndian);
1712
18.8k
          readU8(input, m_bigEndian);
1713
18.8k
          break;
1714
18.1k
        case CMX_Tag_DescrSection_Color_ColorDescr:
1715
18.1k
          m_parserState.m_colorPalette[j] = readColor(input, colorModel);
1716
18.1k
          break;
1717
1.24M
        default:
1718
1.24M
          break;
1719
1.28M
        }
1720
1.28M
        input->seek(offset+tagLength, librevenge::RVNG_SEEK_SET);
1721
1.28M
      }
1722
1.28M
      while (tagId != CMX_Tag_EndTag);
1723
26.8k
    }
1724
282k
    else if (m_precision == libcdr::PRECISION_16BIT)
1725
282k
    {
1726
282k
      colorModel = readU8(input, m_bigEndian);
1727
282k
      readU8(input, m_bigEndian);
1728
282k
      m_parserState.m_colorPalette[j] = readColor(input, colorModel);
1729
282k
    }
1730
279
    else
1731
279
      return;
1732
309k
  }
1733
2.99k
}
1734
1735
void libcdr::CMXParser::readRdot(librevenge::RVNGInputStream *input)
1736
5.27k
{
1737
5.27k
  unsigned fourCC = readU32(input, m_bigEndian);
1738
5.27k
  if (CDR_FOURCC_rdot != fourCC)
1739
2.24k
    return;
1740
3.02k
  /* unsigned length = */ readU32(input, m_bigEndian);
1741
1742
3.02k
  unsigned long numRecords = readU16(input, m_bigEndian);
1743
3.02k
  CDR_DEBUG_MSG(("CMXParser::readRdot - numRecords %li\n", numRecords));
1744
3.02k
  sanitizeNumRecords(numRecords, m_precision, 2, 2, 1, getRemainingLength(input));
1745
124k
  for (unsigned j = 1; j <= numRecords; ++j)
1746
122k
  {
1747
122k
    std::vector<unsigned> dots;
1748
122k
    if (m_precision == libcdr::PRECISION_32BIT)
1749
6.39k
    {
1750
6.39k
      unsigned char tagId = 0;
1751
6.39k
      do
1752
2.12M
      {
1753
2.12M
        long offset = input->tell();
1754
2.12M
        tagId = readU8(input, m_bigEndian);
1755
2.12M
        if (tagId == CMX_Tag_EndTag)
1756
6.25k
          break;
1757
2.11M
        unsigned short tagLength = readTagLength(input, m_bigEndian);
1758
2.11M
        switch (tagId)
1759
2.11M
        {
1760
103k
        case CMX_Tag_DescrSection_Dash:
1761
103k
        {
1762
103k
          unsigned long dotCount = readU16(input, m_bigEndian);
1763
103k
          if (dotCount > getRemainingLength(input) / 2)
1764
3.38k
            dotCount = getRemainingLength(input) / 2;
1765
95.2M
          for (unsigned long i = 0; i < dotCount; ++i)
1766
95.1M
            dots.push_back(readU16(input, m_bigEndian));
1767
103k
          break;
1768
0
        }
1769
2.01M
        default:
1770
2.01M
          break;
1771
2.11M
        }
1772
2.11M
        input->seek(offset+tagLength, librevenge::RVNG_SEEK_SET);
1773
2.11M
      }
1774
2.11M
      while (tagId != CMX_Tag_EndTag);
1775
6.39k
    }
1776
116k
    else if (m_precision == libcdr::PRECISION_16BIT)
1777
115k
    {
1778
115k
      unsigned long dotCount = readU16(input, m_bigEndian);
1779
115k
      if (dotCount > getRemainingLength(input) / 2)
1780
466
        dotCount = getRemainingLength(input) / 2;
1781
4.60M
      for (unsigned long i = 0; i < dotCount; ++i)
1782
4.48M
        dots.push_back(readU16(input, m_bigEndian));
1783
115k
    }
1784
636
    else
1785
636
      return;
1786
121k
    m_parserState.m_dashArrays[j] = dots;
1787
121k
  }
1788
3.02k
}
1789
1790
void libcdr::CMXParser::readRott(librevenge::RVNGInputStream *input)
1791
5.57k
{
1792
5.57k
  unsigned fourCC = readU32(input, m_bigEndian);
1793
5.57k
  if (CDR_FOURCC_rott != fourCC)
1794
3.29k
    return;
1795
2.27k
  /* unsigned length = */ readU32(input, m_bigEndian);
1796
1797
2.27k
  unsigned long numRecords = readU16(input, m_bigEndian);
1798
2.27k
  CDR_DEBUG_MSG(("CMXParser::readRott - numRecords %li\n", numRecords));
1799
2.27k
  sanitizeNumRecords(numRecords, m_precision, 2, 2, 1, getRemainingLength(input));
1800
708k
  for (unsigned j = 1; j <= numRecords; ++j)
1801
707k
  {
1802
707k
    CMXLineStyle lineStyle;
1803
707k
    if (m_precision == libcdr::PRECISION_32BIT)
1804
3.93k
    {
1805
3.93k
      unsigned char tagId = 0;
1806
3.93k
      do
1807
865k
      {
1808
865k
        long offset = input->tell();
1809
865k
        tagId = readU8(input, m_bigEndian);
1810
865k
        if (tagId == CMX_Tag_EndTag)
1811
3.89k
          break;
1812
861k
        unsigned short tagLength = readTagLength(input, m_bigEndian);
1813
861k
        switch (tagId)
1814
861k
        {
1815
4.56k
        case CMX_Tag_DescrSection_LineStyle:
1816
4.56k
        {
1817
4.56k
          lineStyle.m_spec = readU8(input, m_bigEndian);
1818
4.56k
          lineStyle.m_capAndJoin = readU8(input, m_bigEndian);
1819
4.56k
          break;
1820
0
        }
1821
857k
        default:
1822
857k
          break;
1823
861k
        }
1824
861k
        input->seek(offset+tagLength, librevenge::RVNG_SEEK_SET);
1825
861k
      }
1826
861k
      while (tagId != CMX_Tag_EndTag);
1827
3.93k
    }
1828
703k
    else if (m_precision == libcdr::PRECISION_16BIT)
1829
702k
    {
1830
702k
      lineStyle.m_spec = readU8(input, m_bigEndian);
1831
702k
      lineStyle.m_capAndJoin = readU8(input, m_bigEndian);
1832
702k
    }
1833
581
    else
1834
581
      return;
1835
706k
    m_parserState.m_lineStyles[j] = lineStyle;
1836
706k
  }
1837
2.27k
}
1838
1839
void libcdr::CMXParser::readRotl(librevenge::RVNGInputStream *input)
1840
3.57k
{
1841
3.57k
  unsigned fourCC = readU32(input, m_bigEndian);
1842
3.57k
  if (CDR_FOURCC_rotl != fourCC)
1843
1.14k
    return;
1844
2.42k
  /* unsigned length = */ readU32(input, m_bigEndian);
1845
1846
2.42k
  unsigned long numRecords = readU16(input, m_bigEndian);
1847
2.42k
  CDR_DEBUG_MSG(("CMXParser::readRotl - numRecords %li\n", numRecords));
1848
2.42k
  sanitizeNumRecords(numRecords, m_precision, 12, 12, 1, getRemainingLength(input));
1849
169k
  for (unsigned j = 1; j <= numRecords; ++j)
1850
167k
  {
1851
167k
    CMXOutline outline;
1852
167k
    if (m_precision == libcdr::PRECISION_32BIT)
1853
20.4k
    {
1854
20.4k
      unsigned char tagId = 0;
1855
20.4k
      do
1856
57.1k
      {
1857
57.1k
        long offset = input->tell();
1858
57.1k
        tagId = readU8(input, m_bigEndian);
1859
57.1k
        if (tagId == CMX_Tag_EndTag)
1860
20.4k
          break;
1861
36.7k
        unsigned short tagLength = readTagLength(input, m_bigEndian);
1862
36.7k
        switch (tagId)
1863
36.7k
        {
1864
20.4k
        case CMX_Tag_DescrSection_Outline:
1865
20.4k
        {
1866
20.4k
          outline.m_lineStyle = readU16(input, m_bigEndian);
1867
20.4k
          outline.m_screen = readU16(input, m_bigEndian);
1868
20.4k
          outline.m_color = readU16(input, m_bigEndian);
1869
20.4k
          outline.m_arrowHeads = readU16(input, m_bigEndian);
1870
20.4k
          outline.m_pen = readU16(input, m_bigEndian);
1871
20.4k
          outline.m_dashArray = readU16(input, m_bigEndian);
1872
20.4k
          break;
1873
0
        }
1874
16.2k
        default:
1875
16.2k
          break;
1876
36.7k
        }
1877
36.7k
        input->seek(offset+tagLength, librevenge::RVNG_SEEK_SET);
1878
36.7k
      }
1879
36.7k
      while (tagId != CMX_Tag_EndTag);
1880
20.4k
    }
1881
147k
    else if (m_precision == libcdr::PRECISION_16BIT)
1882
146k
    {
1883
146k
      outline.m_lineStyle = readU16(input, m_bigEndian);
1884
146k
      outline.m_screen = readU16(input, m_bigEndian);
1885
146k
      outline.m_color = readU16(input, m_bigEndian);
1886
146k
      outline.m_arrowHeads = readU16(input, m_bigEndian);
1887
146k
      outline.m_pen = readU16(input, m_bigEndian);
1888
146k
      outline.m_dashArray = readU16(input, m_bigEndian);
1889
146k
    }
1890
501
    else
1891
501
      return;
1892
167k
    m_parserState.m_outlines[j] = outline;
1893
167k
  }
1894
2.42k
}
1895
1896
void libcdr::CMXParser::readRpen(librevenge::RVNGInputStream *input)
1897
2.75k
{
1898
2.75k
  unsigned fourCC = readU32(input, m_bigEndian);
1899
2.75k
  if (CDR_FOURCC_rpen != fourCC)
1900
1.45k
    return;
1901
1.29k
  /* unsigned length = */ readU32(input, m_bigEndian);
1902
1903
1.29k
  unsigned long numRecords = readU16(input, m_bigEndian);
1904
1.29k
  CDR_DEBUG_MSG(("CMXParser::readRpen - numRecords %li\n", numRecords));
1905
1.29k
  sanitizeNumRecords(numRecords, m_precision, 10, 12, 1, getRemainingLength(input));
1906
149k
  for (unsigned j = 1; j <= numRecords; ++j)
1907
148k
  {
1908
148k
    CMXPen pen;
1909
148k
    if (m_precision == libcdr::PRECISION_32BIT)
1910
5.25k
    {
1911
5.25k
      unsigned char tagId = 0;
1912
5.25k
      do
1913
11.7k
      {
1914
11.7k
        long offset = input->tell();
1915
11.7k
        tagId = readU8(input, m_bigEndian);
1916
11.7k
        if (tagId == CMX_Tag_EndTag)
1917
5.22k
          break;
1918
6.57k
        unsigned short tagLength = readTagLength(input, m_bigEndian);
1919
6.57k
        switch (tagId)
1920
6.57k
        {
1921
4.87k
        case CMX_Tag_DescrSection_Pen:
1922
4.87k
        {
1923
4.87k
          pen.m_width = readCoordinate(input);
1924
4.87k
          pen.m_aspect = (double)readU16(input, m_bigEndian) / 100.0;
1925
4.87k
          pen.m_angle = readAngle(input);
1926
4.87k
          pen.m_matrix = readMatrix(input);
1927
4.87k
          break;
1928
0
        }
1929
1.66k
        default:
1930
1.66k
          break;
1931
6.57k
        }
1932
6.53k
        input->seek(offset+tagLength, librevenge::RVNG_SEEK_SET);
1933
6.53k
      }
1934
6.53k
      while (tagId != CMX_Tag_EndTag);
1935
5.25k
    }
1936
143k
    else if (m_precision == libcdr::PRECISION_16BIT)
1937
142k
    {
1938
142k
      pen.m_width = readCoordinate(input);
1939
142k
      pen.m_aspect = (double)readU16(input, m_bigEndian) / 100.0;
1940
142k
      pen.m_angle = readAngle(input);
1941
142k
      input->seek(2, librevenge::RVNG_SEEK_CUR);
1942
142k
      pen.m_matrix = readMatrix(input);
1943
142k
    }
1944
393
    else
1945
393
      return;
1946
147k
    m_parserState.m_pens[j] = pen;
1947
147k
  }
1948
1.29k
}
1949
1950
void libcdr::CMXParser::readIxtl(librevenge::RVNGInputStream *input)
1951
6.91k
{
1952
6.91k
  unsigned fourCC = readU32(input, m_bigEndian);
1953
6.91k
  if (CDR_FOURCC_ixtl != fourCC)
1954
4.38k
    return;
1955
2.52k
  /* unsigned length = */ readU32(input, m_bigEndian);
1956
1957
2.52k
  unsigned long numRecords = readU16(input, m_bigEndian);
1958
2.52k
  CDR_DEBUG_MSG(("CMXParser::readIxtl - numRecords %li\n", numRecords));
1959
2.52k
  int sizeInFile(0);
1960
2.52k
  if (m_precision == libcdr::PRECISION_32BIT)
1961
394
  {
1962
394
    sizeInFile = readU16(input, m_bigEndian);
1963
394
    if (sizeInFile < 4)
1964
86
      return;
1965
394
  }
1966
2.43k
  unsigned type = readU16(input, m_bigEndian);
1967
2.43k
  sanitizeNumRecords(numRecords, m_precision, 4, 4, getRemainingLength(input));
1968
8.86M
  for (unsigned j = 1; j <= numRecords; ++j)
1969
8.86M
  {
1970
8.86M
    switch (type)
1971
8.86M
    {
1972
6.20M
    case 5: // BMP
1973
6.20M
    {
1974
6.20M
      unsigned offset = readU32(input, m_bigEndian);
1975
6.20M
      long oldOffset = input->tell();
1976
6.20M
      input->seek(offset, librevenge::RVNG_SEEK_SET);
1977
6.20M
      parseImage(input);
1978
6.20M
      input->seek(oldOffset, librevenge::RVNG_SEEK_SET);
1979
6.20M
      if (m_currentPattern && !m_currentPattern->pattern.empty())
1980
472
        m_collector->collectBmpf(j, m_currentPattern->width, m_currentPattern->height, m_currentPattern->pattern);
1981
6.20M
      m_currentPattern = nullptr;
1982
6.20M
      break;
1983
0
    }
1984
189k
    case 6:
1985
189k
      m_parserState.m_arrowOffsets[j] = readU32(input, m_bigEndian);
1986
189k
      break;
1987
2.47M
    default:
1988
2.47M
      break;
1989
8.86M
    }
1990
8.86M
    if (sizeInFile)
1991
139k
      input->seek(sizeInFile-4, librevenge::RVNG_SEEK_CUR);
1992
8.86M
  }
1993
2.43k
}
1994
1995
void libcdr::CMXParser::readIxef(librevenge::RVNGInputStream *input)
1996
11.8k
{
1997
11.8k
  unsigned fourCC = readU32(input, m_bigEndian);
1998
11.8k
  if (CDR_FOURCC_ixef != fourCC)
1999
5.98k
    return;
2000
5.85k
  /* unsigned length = */ readU32(input, m_bigEndian);
2001
2002
5.85k
  unsigned long numRecords = readU16(input, m_bigEndian);
2003
5.85k
  CDR_DEBUG_MSG(("CMXParser::readIxef - numRecords %li\n", numRecords));
2004
5.85k
  sanitizeNumRecords(numRecords, m_precision, 6, 8, getRemainingLength(input));
2005
20.7M
  for (unsigned j = 1; j <= numRecords; ++j)
2006
20.7M
  {
2007
20.7M
    int sizeInFile(0);
2008
20.7M
    if (m_precision == libcdr::PRECISION_32BIT)
2009
395
    {
2010
395
      sizeInFile = readU16(input, m_bigEndian);
2011
395
      if (sizeInFile < 6)
2012
110
        return;
2013
395
    }
2014
20.7M
    unsigned offset = readU32(input, m_bigEndian);
2015
20.7M
    unsigned type = readU16(input, m_bigEndian);
2016
20.7M
    long oldOffset = input->tell();
2017
20.7M
    if (type == 0x11)
2018
7.40k
    {
2019
7.40k
      input->seek(offset, librevenge::RVNG_SEEK_SET);
2020
7.40k
      parseImage(input);
2021
7.40k
      input->seek(oldOffset, librevenge::RVNG_SEEK_SET);
2022
7.40k
      if (m_currentBitmap && !(m_currentBitmap->bitmap.empty()))
2023
4.30k
        m_collector->collectBmp(j, m_currentBitmap->colorModel, m_currentBitmap->width, m_currentBitmap->height,
2024
4.30k
                                m_currentBitmap->bpp, m_currentBitmap->palette, m_currentBitmap->bitmap);
2025
7.40k
      m_currentBitmap = nullptr;
2026
7.40k
    }
2027
20.7M
    if (sizeInFile)
2028
283
      input->seek(sizeInFile-6, librevenge::RVNG_SEEK_CUR);
2029
20.7M
  }
2030
5.85k
}
2031
2032
void libcdr::CMXParser::readIxpg(librevenge::RVNGInputStream *input)
2033
25.2k
{
2034
25.2k
  unsigned fourCC = readU32(input, m_bigEndian);
2035
25.2k
  if (CDR_FOURCC_ixpg != fourCC)
2036
5.90k
    return;
2037
19.3k
  /* unsigned length = */ readU32(input, m_bigEndian);
2038
2039
19.3k
  unsigned long numRecords = readU16(input, m_bigEndian);
2040
19.3k
  CDR_DEBUG_MSG(("CMXParser::readIxpg - numRecords %li\n", numRecords));
2041
19.3k
  sanitizeNumRecords(numRecords, m_precision, 16, 18, getRemainingLength(input));
2042
55.7k
  for (unsigned j = 1; j <= numRecords; ++j)
2043
37.2k
  {
2044
37.2k
    int sizeInFile(0);
2045
37.2k
    if (m_precision == libcdr::PRECISION_32BIT)
2046
4.61k
    {
2047
4.61k
      sizeInFile = readU16(input, m_bigEndian);
2048
4.61k
      if (sizeInFile < 16)
2049
870
        return;
2050
4.61k
    }
2051
36.3k
    unsigned pageOffset = readU32(input, m_bigEndian);
2052
36.3k
    /* unsigned layerTableOffset = */ readU32(input, m_bigEndian);
2053
36.3k
    /* unsigned thumbnailOffset = */ readU32(input, m_bigEndian);
2054
36.3k
    /* unsigned refListOffset = */ readU32(input, m_bigEndian);
2055
36.3k
    if (pageOffset && pageOffset != (unsigned)-1)
2056
34.4k
    {
2057
34.4k
      long oldOffset = input->tell();
2058
34.4k
      input->seek(pageOffset, librevenge::RVNG_SEEK_SET);
2059
34.4k
      readPage(input);
2060
34.4k
      input->seek(oldOffset, librevenge::RVNG_SEEK_SET);
2061
34.4k
    }
2062
36.3k
    if (sizeInFile)
2063
2.34k
      input->seek(sizeInFile-16, librevenge::RVNG_SEEK_CUR);
2064
36.3k
  }
2065
19.3k
}
2066
2067
void libcdr::CMXParser::readIxpc(librevenge::RVNGInputStream *input)
2068
4.48k
{
2069
4.48k
  unsigned fourCC = readU32(input, m_bigEndian);
2070
4.48k
  if (CDR_FOURCC_ixpc != fourCC)
2071
4.25k
    return;
2072
224
  /* unsigned length = */ readU32(input, m_bigEndian);
2073
2074
224
  unsigned numRecords = readU16(input, m_bigEndian);
2075
224
  CDR_DEBUG_MSG(("CMXParser::readIxpc - numRecords %i\n", numRecords));
2076
2077
  /* Don't really parse it for the while */
2078
224
  return;
2079
0
  for (unsigned j = 1; j <= numRecords; ++j)
2080
0
  {
2081
0
    int sizeInFile(0);
2082
0
    if (m_precision == libcdr::PRECISION_32BIT)
2083
0
    {
2084
0
      sizeInFile = readU16(input, m_bigEndian);
2085
0
      if (sizeInFile < 8)
2086
0
        return;
2087
0
    }
2088
0
    /* unsigned refListOffset = */ readU32(input, m_bigEndian);
2089
0
    unsigned procOffset = readU32(input, m_bigEndian);
2090
0
    if (procOffset && procOffset != (unsigned)-1)
2091
0
    {
2092
0
      long oldOffset = input->tell();
2093
0
      input->seek(procOffset, librevenge::RVNG_SEEK_SET);
2094
0
      m_collector->collectVect(0);
2095
0
      m_collector->collectSpnd(j);
2096
0
      readProc(input);
2097
0
      input->seek(oldOffset, librevenge::RVNG_SEEK_SET);
2098
0
    }
2099
0
    if (sizeInFile)
2100
0
      input->seek(sizeInFile-8, librevenge::RVNG_SEEK_CUR);
2101
0
  }
2102
0
}
2103
2104
void libcdr::CMXParser::readInfo(librevenge::RVNGInputStream *input)
2105
2.76k
{
2106
2.76k
  m_currentImageInfo = libcdr::CMXImageInfo();
2107
2.76k
  CDR_DEBUG_MSG(("CMXParser::readInfo\n"));
2108
2.76k
  if (m_precision == libcdr::PRECISION_32BIT)
2109
365
  {
2110
365
    unsigned char tagId = 0;
2111
365
    do
2112
4.75k
    {
2113
4.75k
      long offset = input->tell();
2114
4.75k
      tagId = readU8(input, m_bigEndian);
2115
4.75k
      if (tagId == CMX_Tag_EndTag)
2116
327
        break;
2117
4.42k
      unsigned short tagLength = readTagLength(input, m_bigEndian);
2118
4.42k
      switch (tagId)
2119
4.42k
      {
2120
276
      case CMX_Tag_DescrSection_Image_ImageInfo:
2121
276
      {
2122
276
        m_currentImageInfo.m_type = readU16(input, m_bigEndian);
2123
276
        m_currentImageInfo.m_compression = readU16(input, m_bigEndian);
2124
276
        m_currentImageInfo.m_size = readU32(input, m_bigEndian);
2125
276
        m_currentImageInfo.m_compressedSize = readU32(input, m_bigEndian);
2126
276
      }
2127
4.39k
      default:
2128
4.39k
        break;
2129
4.42k
      }
2130
4.38k
      input->seek(offset+tagLength, librevenge::RVNG_SEEK_SET);
2131
4.38k
    }
2132
4.38k
    while (tagId != CMX_Tag_EndTag);
2133
365
  }
2134
2.40k
  else if (m_precision == libcdr::PRECISION_16BIT)
2135
325
  {
2136
325
    m_currentImageInfo.m_type = readU16(input, m_bigEndian);
2137
325
    m_currentImageInfo.m_compression = readU16(input, m_bigEndian);
2138
325
    m_currentImageInfo.m_size = readU32(input, m_bigEndian);
2139
325
    m_currentImageInfo.m_compressedSize = readU32(input, m_bigEndian);
2140
325
  }
2141
2.07k
  else
2142
2.07k
    return;
2143
2.76k
}
2144
2145
void libcdr::CMXParser::readData(librevenge::RVNGInputStream *input)
2146
12.4k
{
2147
12.4k
  CDR_DEBUG_MSG(("CMXParser::readData\n"));
2148
12.4k
  if (m_precision == libcdr::PRECISION_32BIT && m_currentImageInfo.m_type == 0x10)
2149
107
  {
2150
107
    unsigned char tagId = 0;
2151
107
    do
2152
217
    {
2153
217
      long offset = input->tell();
2154
217
      tagId = readU8(input, m_bigEndian);
2155
217
      if (tagId == CMX_Tag_EndTag)
2156
74
        break;
2157
143
      unsigned tagLength = readU32(input, m_bigEndian);
2158
143
      switch (tagId)
2159
143
      {
2160
21
      case CMX_Tag_DescrSection_Image_ImageData:
2161
21
      {
2162
21
        unsigned char first = readU8(input, m_bigEndian);
2163
21
        unsigned char second = readU8(input, m_bigEndian);
2164
21
        if (0x42 == first && 0x4d == second) // BM
2165
2
        {
2166
2
          unsigned fileSize = readU32(input, m_bigEndian);
2167
2
          input->seek(8, librevenge::RVNG_SEEK_CUR);
2168
2
          m_currentPattern.reset(new libcdr::CDRPattern());
2169
2
          readBmpPattern(m_currentPattern->width, m_currentPattern->height, m_currentPattern->pattern,
2170
2
                         fileSize - 14, input, m_bigEndian);
2171
2
        }
2172
19
        else if (0x52 == first && 0x49 == second) // RI
2173
2
        {
2174
2
          input->seek(12, librevenge::RVNG_SEEK_CUR);
2175
2
          m_currentBitmap.reset(new libcdr::CDRBitmap());
2176
2
          readRImage(m_currentBitmap->colorModel, m_currentBitmap->width, m_currentBitmap->height,
2177
2
                     m_currentBitmap->bpp, m_currentBitmap->palette, m_currentBitmap->bitmap,
2178
2
                     input, m_bigEndian);
2179
2
        }
2180
21
        break;
2181
0
      }
2182
92
      default:
2183
92
        break;
2184
143
      }
2185
110
      input->seek(offset+tagLength, librevenge::RVNG_SEEK_SET);
2186
110
    }
2187
110
    while (tagId != CMX_Tag_EndTag);
2188
107
  }
2189
12.3k
  else if (m_precision == libcdr::PRECISION_16BIT || m_currentImageInfo.m_type != 0x10)
2190
12.2k
  {
2191
12.2k
    unsigned char first = readU8(input, m_bigEndian);
2192
12.2k
    unsigned char second = readU8(input, m_bigEndian);
2193
12.2k
    if (0x42 == first && 0x4d == second) // RI
2194
2.20k
    {
2195
2.20k
      unsigned fileSize = readU32(input, m_bigEndian);
2196
2.20k
      input->seek(8, librevenge::RVNG_SEEK_CUR);
2197
2.20k
      m_currentPattern.reset(new libcdr::CDRPattern());
2198
2.20k
      readBmpPattern(m_currentPattern->width, m_currentPattern->height, m_currentPattern->pattern, fileSize - 14, input);
2199
2.20k
    }
2200
10.0k
    else if (0x52 == first && 0x49 == second)
2201
8.04k
    {
2202
8.04k
      input->seek(12, librevenge::RVNG_SEEK_CUR); // RI
2203
8.04k
      m_currentBitmap.reset(new libcdr::CDRBitmap());
2204
8.04k
      readRImage(m_currentBitmap->colorModel, m_currentBitmap->width, m_currentBitmap->height,
2205
8.04k
                 m_currentBitmap->bpp, m_currentBitmap->palette, m_currentBitmap->bitmap,
2206
8.04k
                 input, m_bigEndian);
2207
8.04k
    }
2208
12.2k
  }
2209
81
  else
2210
81
    return;
2211
12.4k
}
2212
2213
libcdr::CDRColor libcdr::CMXParser::getPaletteColor(unsigned id)
2214
162M
{
2215
162M
  const std::map<unsigned, libcdr::CDRColor>::const_iterator iter = m_parserState.m_colorPalette.find(id);
2216
162M
  if (iter != m_parserState.m_colorPalette.end())
2217
110k
    return iter->second;
2218
162M
  return libcdr::CDRColor();
2219
162M
}
2220
2221
libcdr::CDRColor libcdr::CMXParser::readColor(librevenge::RVNGInputStream *input, unsigned char colorModel)
2222
300k
{
2223
300k
  libcdr::CDRColor color;
2224
300k
  switch (colorModel)
2225
300k
  {
2226
203k
  case 0: // Invalid
2227
203k
    CDR_DEBUG_MSG(("Invalid color model\n"));
2228
203k
    break;
2229
2.54k
  case 1: // Pantone
2230
2.54k
  {
2231
2.54k
    unsigned short pantoneId = readU16(input, m_bigEndian);
2232
2.54k
    unsigned short pantoneDensity = readU16(input, m_bigEndian);
2233
2.54k
    CDR_DEBUG_MSG(("Pantone color: id 0x%x, density 0x%x\n", pantoneId, pantoneDensity));
2234
2.54k
    color.m_colorValue = ((unsigned)pantoneId & 0xff) | ((unsigned)pantoneId & 0xff00) | ((unsigned)pantoneDensity & 0xff) << 16 | ((unsigned)pantoneDensity & 0xff00) << 16;
2235
2.54k
    color.m_colorModel = 0;
2236
2.54k
    break;
2237
0
  }
2238
13.6k
  case 2: // CMYK
2239
13.6k
  {
2240
13.6k
    unsigned char c = readU8(input, m_bigEndian);
2241
13.6k
    unsigned char m = readU8(input, m_bigEndian);
2242
13.6k
    unsigned char y = readU8(input, m_bigEndian);
2243
13.6k
    unsigned char k = readU8(input, m_bigEndian);
2244
13.6k
    CDR_DEBUG_MSG(("CMYK color: c 0x%x, m 0x%x, y 0x%x, k 0x%x\n", c, m, y, k));
2245
13.6k
    color.m_colorValue = c | (unsigned)m << 8 | (unsigned)y << 16 | (unsigned)k << 24;
2246
13.6k
    color.m_colorModel = colorModel;
2247
13.6k
    break;
2248
0
  }
2249
1.82k
  case 3: // CMYK255
2250
1.82k
  {
2251
1.82k
    unsigned char c = readU8(input, m_bigEndian);
2252
1.82k
    unsigned char m = readU8(input, m_bigEndian);
2253
1.82k
    unsigned char y = readU8(input, m_bigEndian);
2254
1.82k
    unsigned char k = readU8(input, m_bigEndian);
2255
1.82k
    CDR_DEBUG_MSG(("CMYK255 color: c 0x%x, m 0x%x, y 0x%x, k 0x%x\n", c, m, y, k));
2256
1.82k
    color.m_colorValue = c | (unsigned)m << 8 | (unsigned)y << 16 | (unsigned)k << 24;
2257
1.82k
    color.m_colorModel = colorModel;
2258
1.82k
    break;
2259
0
  }
2260
672
  case 4: // CMY
2261
672
  {
2262
672
    unsigned char c = readU8(input, m_bigEndian);
2263
672
    unsigned char m = readU8(input, m_bigEndian);
2264
672
    unsigned char y = readU8(input, m_bigEndian);
2265
672
    CDR_DEBUG_MSG(("CMY color: c 0x%x, m 0x%x, y 0x%x\n", c, m, y));
2266
672
    color.m_colorValue = c | (unsigned)m << 8 | (unsigned)y << 16;
2267
672
    color.m_colorModel = colorModel;
2268
672
    break;
2269
0
  }
2270
1.04k
  case 5: // RGB
2271
1.04k
  {
2272
1.04k
    unsigned char r = readU8(input, m_bigEndian);
2273
1.04k
    unsigned char g = readU8(input, m_bigEndian);
2274
1.04k
    unsigned char b = readU8(input, m_bigEndian);
2275
1.04k
    CDR_DEBUG_MSG(("RGB color: r 0x%x, g 0x%x, b 0x%x\n", r, g, b));
2276
1.04k
    color.m_colorValue = b | (unsigned)g << 8 | (unsigned)r << 16;
2277
1.04k
    color.m_colorModel = colorModel;
2278
1.04k
    break;
2279
0
  }
2280
955
  case 6: // HSB
2281
955
  {
2282
955
    unsigned short h = readU16(input, m_bigEndian);
2283
955
    unsigned char s = readU8(input, m_bigEndian);
2284
955
    unsigned char b = readU8(input, m_bigEndian);
2285
955
    CDR_DEBUG_MSG(("HSB color: h 0x%x, s 0x%x, b 0x%x\n", h, s, b));
2286
955
    color.m_colorValue = (h & 0xff) | ((unsigned)(h & 0xff00) >> 8) << 8 | (unsigned)s << 16 | (unsigned)b << 24;
2287
955
    color.m_colorModel = colorModel;
2288
955
    break;
2289
0
  }
2290
588
  case 7: // HLS
2291
588
  {
2292
588
    unsigned short h = readU16(input, m_bigEndian);
2293
588
    unsigned char l = readU8(input, m_bigEndian);
2294
588
    unsigned char s = readU8(input, m_bigEndian);
2295
588
    CDR_DEBUG_MSG(("HLS color: h 0x%x, l 0x%x, s 0x%x\n", h, l, s));
2296
588
    color.m_colorValue = (h & 0xff) | ((unsigned)(h & 0xff00) >> 8) << 8 | (unsigned)l << 16 | (unsigned)s << 24;
2297
588
    color.m_colorModel = colorModel;
2298
588
    break;
2299
0
  }
2300
843
  case 8: // BW
2301
1.62k
  case 9: // Gray
2302
1.62k
  {
2303
1.62k
    unsigned value = readU8(input, m_bigEndian);
2304
1.62k
    CDR_DEBUG_MSG(("%s color: %s 0x%x\n", colorModel == 8 ? "BW" : "Gray", colorModel == 8 ? "black" : "gray", value));
2305
1.62k
    color.m_colorValue = value;
2306
1.62k
    color.m_colorModel = colorModel;
2307
1.62k
    break;
2308
843
  }
2309
367
  case 10: // YIQ255
2310
367
  {
2311
367
    unsigned char y = readU8(input, m_bigEndian);
2312
367
    unsigned char i = readU8(input, m_bigEndian);
2313
367
    unsigned char q = readU8(input, m_bigEndian);
2314
367
    CDR_DEBUG_MSG(("YIQ255 color: y 0x%x, i 0x%x, q 0x%x\n", y, i, q));
2315
367
    color.m_colorValue = (unsigned)y << 8 | (unsigned)i << 16 | (unsigned)q << 24 ;
2316
367
    color.m_colorModel = 11;
2317
367
    break;
2318
843
  }
2319
612
  case 11: // LAB
2320
957
  case 12: // LAB ???
2321
957
  {
2322
957
    unsigned char l = readU8(input, m_bigEndian);
2323
957
    unsigned char a = readU8(input, m_bigEndian);
2324
957
    unsigned char b = readU8(input, m_bigEndian);
2325
957
    CDR_DEBUG_MSG(("LAB color: L 0x%x, green2magenta 0x%x, blue2yellow 0x%x\n", l, a, b));
2326
957
    color.m_colorValue =l | (unsigned)a << 8 | (unsigned)b << 16;
2327
957
    color.m_colorModel = 12;
2328
957
    break;
2329
612
  }
2330
12.5k
  case 0xff: // something funny here
2331
12.5k
    input->seek(4, librevenge::RVNG_SEEK_CUR);
2332
12.5k
    CDR_FALLTHROUGH;
2333
72.8k
  default:
2334
72.8k
    CDR_DEBUG_MSG(("Unknown color model %i\n", colorModel));
2335
72.8k
    break;
2336
300k
  }
2337
300k
  return color;
2338
300k
}
2339
2340
libcdr::CDRLineStyle libcdr::CMXParser::getLineStyle(unsigned id)
2341
344k
{
2342
344k
  libcdr::CDRLineStyle tmpLineStyle;
2343
344k
  std::map<unsigned, CMXOutline>::const_iterator iterOutline = m_parserState.m_outlines.find(id);
2344
344k
  if (iterOutline == m_parserState.m_outlines.end())
2345
317k
    return tmpLineStyle;
2346
27.2k
  unsigned lineStyleId = iterOutline->second.m_lineStyle;
2347
27.2k
  unsigned colorId = iterOutline->second.m_color;
2348
27.2k
  unsigned penId = iterOutline->second.m_pen;
2349
27.2k
  unsigned dashArrayId = iterOutline->second.m_dashArray;
2350
27.2k
  tmpLineStyle.color = getPaletteColor(colorId);
2351
27.2k
  std::map<unsigned, CMXLineStyle>::const_iterator iterLineStyle = m_parserState.m_lineStyles.find(lineStyleId);
2352
27.2k
  if (iterLineStyle != m_parserState.m_lineStyles.end())
2353
21.8k
  {
2354
21.8k
    tmpLineStyle.lineType = iterLineStyle->second.m_spec;
2355
21.8k
    tmpLineStyle.capsType = (unsigned short)((iterLineStyle->second.m_capAndJoin) & 0xf);
2356
21.8k
    tmpLineStyle.joinType = (unsigned short)(((iterLineStyle->second.m_capAndJoin) & 0xf0) >> 4);
2357
21.8k
  }
2358
27.2k
  std::map<unsigned, CMXPen>::const_iterator iterPen = m_parserState.m_pens.find(penId);
2359
27.2k
  if (iterPen != m_parserState.m_pens.end())
2360
7.63k
  {
2361
7.63k
    tmpLineStyle.lineWidth = iterPen->second.m_width * (iterPen->second.m_matrix.getScaleX()+iterPen->second.m_matrix.getScaleY())/ 2.0;
2362
7.63k
    if (!CDR_ALMOST_ZERO(iterPen->second.m_matrix.getScaleY()))
2363
7.35k
      tmpLineStyle.stretch = iterPen->second.m_matrix.getScaleX()/iterPen->second.m_matrix.getScaleY();
2364
283
    else
2365
283
      tmpLineStyle.stretch = 1.0;
2366
7.63k
    tmpLineStyle.stretch *= iterPen->second.m_aspect;
2367
7.63k
    tmpLineStyle.angle = iterPen->second.m_angle;
2368
7.63k
  }
2369
27.2k
  std::map<unsigned, std::vector<unsigned> >::const_iterator iterDash = m_parserState.m_dashArrays.find(dashArrayId);
2370
27.2k
  if (iterDash != m_parserState.m_dashArrays.end())
2371
21.4k
  {
2372
21.4k
    tmpLineStyle.dashArray = iterDash->second;
2373
21.4k
  }
2374
27.2k
  return tmpLineStyle;
2375
344k
}
2376
2377
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */