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) 2012 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 <string>
31 : #include <string.h>
32 : #include "CDRDocument.h"
33 : #include "CDRParser.h"
34 : #include "CDRSVGGenerator.h"
35 : #include "CDRContentCollector.h"
36 : #include "CDRStylesCollector.h"
37 : #include "CDRZipStream.h"
38 : #include "libcdr_utils.h"
39 : #include "CDRDocumentStructure.h"
40 :
41 : using namespace libcdr;
42 :
43 : namespace
44 : {
45 :
46 0 : static unsigned getCDRVersion(WPXInputStream *input)
47 : {
48 0 : unsigned riff = readU32(input);
49 0 : if ((riff & 0xffff) == 0x4c57) // "WL<micro>\0"
50 0 : return 200;
51 0 : if (riff != FOURCC_RIFF)
52 0 : return 0;
53 0 : input->seek(4, WPX_SEEK_CUR);
54 0 : char signature_c = (char)readU8(input);
55 0 : if (signature_c != 'C' && signature_c != 'c')
56 0 : return 0;
57 0 : char signature_d = (char)readU8(input);
58 0 : if (signature_d != 'D' && signature_d != 'd')
59 0 : return 0;
60 0 : char signature_r = (char)readU8(input);
61 0 : if (signature_r != 'R' && signature_r != 'r')
62 0 : return 0;
63 0 : unsigned char c = readU8(input);
64 0 : if (c == 0x20)
65 0 : return 300;
66 0 : else if (c < 0x31)
67 0 : return 0;
68 0 : else if (c < 0x3a)
69 0 : return 100 * (c - 0x30);
70 0 : else if (c < 0x41)
71 0 : return 0;
72 0 : return 100 * (c - 0x37);
73 : }
74 :
75 : } // anonymous namespace
76 :
77 : /**
78 : Analyzes the content of an input stream to see if it can be parsed
79 : \param input The input stream
80 : \return A value that indicates whether the content from the input
81 : stream is a Corel Draw Document that libcdr is able to parse
82 : */
83 0 : bool libcdr::CDRDocument::isSupported(WPXInputStream *input)
84 : {
85 0 : WPXInputStream *tmpInput = input;
86 : try
87 : {
88 0 : input->seek(0, WPX_SEEK_SET);
89 0 : unsigned version = getCDRVersion(input);
90 0 : if (version)
91 0 : return true;
92 0 : CDRZipStream zinput(input);
93 : // Yes, we are kidnapping here the OLE document API and extending
94 : // it to support also zip files.
95 0 : if (zinput.isOLEStream())
96 : {
97 0 : input = zinput.getDocumentOLEStream("content/riffData.cdr");
98 0 : if (!input)
99 0 : input = zinput.getDocumentOLEStream("content/root.dat");
100 : }
101 0 : if (!input)
102 0 : return false;
103 0 : input->seek(0, WPX_SEEK_SET);
104 0 : version = getCDRVersion(input);
105 0 : if (input != tmpInput)
106 0 : delete input;
107 0 : input = tmpInput;
108 0 : if (!version)
109 0 : return false;
110 0 : return true;
111 : }
112 0 : catch (...)
113 : {
114 0 : if (input != tmpInput)
115 0 : delete input;
116 0 : return false;
117 : }
118 : }
119 :
120 : /**
121 : Parses the input stream content. It will make callbacks to the functions provided by a
122 : CDRPaintInterface class implementation when needed. This is often commonly called the
123 : 'main parsing routine'.
124 : \param input The input stream
125 : \param painter A CDRPainterInterface implementation
126 : \return A value that indicates whether the parsing was successful
127 : */
128 0 : bool libcdr::CDRDocument::parse(::WPXInputStream *input, libwpg::WPGPaintInterface *painter)
129 : {
130 0 : input->seek(0, WPX_SEEK_SET);
131 0 : bool retVal = false;
132 0 : unsigned version = getCDRVersion(input);
133 0 : if (version)
134 : {
135 0 : input->seek(0, WPX_SEEK_SET);
136 0 : CDRParserState ps;
137 0 : CDRStylesCollector stylesCollector(ps);
138 0 : CDRParser stylesParser(std::vector<WPXInputStream *>(), &stylesCollector);
139 0 : if (version >= 300)
140 0 : retVal = stylesParser.parseRecords(input);
141 : else
142 0 : retVal = stylesParser.parseWaldo(input);
143 0 : if (ps.m_pages.empty())
144 0 : retVal = false;
145 0 : if (retVal)
146 : {
147 0 : input->seek(0, WPX_SEEK_SET);
148 0 : CDRContentCollector contentCollector(ps, painter);
149 0 : CDRParser contentParser(std::vector<WPXInputStream *>(), &contentCollector);
150 0 : if (version >= 300)
151 0 : retVal = contentParser.parseRecords(input);
152 : else
153 0 : retVal = contentParser.parseWaldo(input);
154 : }
155 0 : return retVal;
156 : }
157 :
158 0 : WPXInputStream *tmpInput = input;
159 0 : CDRZipStream zinput(input);
160 0 : bool isZipDocument = zinput.isOLEStream();
161 0 : std::vector<std::string> dataFiles;
162 0 : if (isZipDocument)
163 : {
164 0 : input = zinput.getDocumentOLEStream("content/riffData.cdr");
165 0 : if (!input)
166 : {
167 0 : input = zinput.getDocumentOLEStream("content/root.dat");
168 0 : if (input)
169 : {
170 0 : WPXInputStream *tmpStream = zinput.getDocumentOLEStream("content/dataFileList.dat");
171 0 : if (tmpStream)
172 : {
173 0 : std::string dataFileName;
174 0 : while (!tmpStream->atEOS())
175 : {
176 0 : unsigned char character = readU8(tmpStream);
177 0 : if (character == 0x0a)
178 : {
179 0 : dataFiles.push_back(dataFileName);
180 0 : dataFileName.clear();
181 : }
182 : else
183 0 : dataFileName += (char)character;
184 : }
185 0 : if (!dataFileName.empty())
186 0 : dataFiles.push_back(dataFileName);
187 : }
188 : }
189 : }
190 : }
191 0 : std::vector<WPXInputStream *> dataStreams(dataFiles.size());
192 0 : for (unsigned i=0; i<dataFiles.size(); i++)
193 : {
194 0 : std::string streamName("content/data/");
195 0 : streamName += dataFiles[i];
196 : CDR_DEBUG_MSG(("Extracting stream: %s\n", streamName.c_str()));
197 0 : dataStreams[i] = zinput.getDocumentOLEStream(streamName.c_str());
198 0 : }
199 0 : if (!input)
200 0 : input = tmpInput;
201 0 : input->seek(0, WPX_SEEK_SET);
202 0 : CDRParserState ps;
203 : // libcdr extension to the getDocumentOLEStream. Will extract the first stream in the
204 : // given directory
205 0 : WPXInputStream *cmykProfile = zinput.getDocumentOLEStream("color/profiles/cmyk/");
206 0 : if (cmykProfile)
207 : {
208 0 : ps.setColorTransform(cmykProfile);
209 0 : delete cmykProfile;
210 : }
211 0 : WPXInputStream *rgbProfile = zinput.getDocumentOLEStream("color/profiles/rgb/");
212 0 : if (rgbProfile)
213 : {
214 0 : ps.setColorTransform(rgbProfile);
215 0 : delete rgbProfile;
216 : }
217 0 : CDRStylesCollector stylesCollector(ps);
218 0 : CDRParser stylesParser(dataStreams, &stylesCollector);
219 0 : retVal = stylesParser.parseRecords(input);
220 0 : if (ps.m_pages.empty())
221 0 : retVal = false;
222 0 : if (retVal)
223 : {
224 0 : input->seek(0, WPX_SEEK_SET);
225 0 : CDRContentCollector contentCollector(ps, painter);
226 0 : CDRParser contentParser(dataStreams, &contentCollector);
227 0 : retVal = contentParser.parseRecords(input);
228 : }
229 0 : if (input != tmpInput)
230 0 : delete input;
231 0 : input = tmpInput;
232 0 : for (std::vector<WPXInputStream *>::iterator iter = dataStreams.begin(); iter != dataStreams.end(); ++iter)
233 0 : delete *iter;
234 0 : return retVal;
235 : }
236 :
237 : /**
238 : Parses the input stream content and generates a valid Scalable Vector Graphics
239 : Provided as a convenience function for applications that support SVG internally.
240 : \param input The input stream
241 : \param output The output string whose content is the resulting SVG
242 : \return A value that indicates whether the SVG generation was successful.
243 : */
244 0 : bool libcdr::CDRDocument::generateSVG(::WPXInputStream *input, libcdr::CDRStringVector &output)
245 : {
246 0 : libcdr::CDRSVGGenerator generator(output);
247 0 : bool result = libcdr::CDRDocument::parse(input, &generator);
248 0 : return result;
249 0 : }
250 :
251 : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|