LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/cdr/src/lib - CDRParser.cpp (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 1868 0.0 %
Date: 2012-12-17 Functions: 0 57 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10