/src/libstaroffice/src/lib/StarFileManager.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libstaroffice |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #include <cstring> |
35 | | #include <iomanip> |
36 | | #include <iostream> |
37 | | #include <limits> |
38 | | #include <memory> |
39 | | #include <sstream> |
40 | | |
41 | | #include <librevenge/librevenge.h> |
42 | | |
43 | | #include "StarZone.hxx" |
44 | | |
45 | | #include "StarAttribute.hxx" |
46 | | #include "StarBitmap.hxx" |
47 | | #include "StarGraphicStruct.hxx" |
48 | | #include "StarObject.hxx" |
49 | | #include "StarObjectChart.hxx" |
50 | | #include "StarObjectDraw.hxx" |
51 | | #include "StarObjectMath.hxx" |
52 | | #include "StarObjectSpreadsheet.hxx" |
53 | | #include "StarObjectText.hxx" |
54 | | #include "StarItemPool.hxx" |
55 | | #include "STOFFGraphicEncoder.hxx" |
56 | | #include "STOFFGraphicListener.hxx" |
57 | | #include "STOFFPageSpan.hxx" |
58 | | #include "STOFFSpreadsheetEncoder.hxx" |
59 | | #include "STOFFSpreadsheetListener.hxx" |
60 | | |
61 | | #include "StarFileManager.hxx" |
62 | | |
63 | | /** Internal: the structures of a StarFileManager */ |
64 | | namespace StarFileManagerInternal |
65 | | { |
66 | | //////////////////////////////////////// |
67 | | //! Internal: a structure use to read SfxMultiRecord zone of a StarFileManager |
68 | | struct SfxMultiRecord { |
69 | | //! constructor |
70 | | explicit SfxMultiRecord(StarZone &zone) |
71 | | : m_zone(zone) |
72 | | , m_zoneType(0) |
73 | | , m_zoneOpened(false) |
74 | | , m_headerType(0) |
75 | | , m_headerVersion(0) |
76 | | , m_headerTag(0) |
77 | | , m_actualRecord(0) |
78 | | , m_numRecord(0) |
79 | | , m_contentSize(0) |
80 | | , m_startPos(0) |
81 | | , m_endPos(0) |
82 | | , m_offsetList() |
83 | | , m_extra("") |
84 | 0 | { |
85 | 0 | } |
86 | | //! try to open a zone |
87 | | bool open() |
88 | 0 | { |
89 | 0 | if (m_zoneOpened) { |
90 | 0 | STOFF_DEBUG_MSG(("StarFileManagerInternal::SfxMultiRecord: oops a record has been opened\n")); |
91 | 0 | return false; |
92 | 0 | } |
93 | 0 | m_actualRecord=m_numRecord=0; |
94 | 0 | m_headerType=m_headerVersion=0; |
95 | 0 | m_headerTag=0; |
96 | 0 | m_contentSize=0; |
97 | 0 | m_offsetList.clear(); |
98 | 0 |
|
99 | 0 | STOFFInputStreamPtr input=m_zone.input(); |
100 | 0 | long pos=input->tell(); |
101 | 0 | if (!m_zone.openSfxRecord(m_zoneType)) { |
102 | 0 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
103 | 0 | return false; |
104 | 0 | } |
105 | 0 | if (m_zoneType==static_cast<unsigned char>(0xff)) { |
106 | 0 | STOFF_DEBUG_MSG(("StarFileManagerInternal::SfxMultiRecord: oops end header\n")); |
107 | 0 | m_extra="###emptyZone,"; |
108 | 0 | return true; /* empty zone*/ |
109 | 0 | } |
110 | 0 | if (m_zoneType!=0) { |
111 | 0 | STOFF_DEBUG_MSG(("StarFileManagerInternal::SfxMultiRecord: find unknown header\n")); |
112 | 0 | m_extra="###badZoneType,"; |
113 | 0 | return true; |
114 | 0 | } |
115 | 0 |
|
116 | 0 | m_zoneOpened=true; |
117 | 0 | m_endPos=m_zone.getRecordLastPosition(); |
118 | 0 | // filerec.cxx: SfxSingleRecordReader::FindHeader_Impl |
119 | 0 | if (input->tell()+10>m_endPos) { |
120 | 0 | STOFF_DEBUG_MSG(("StarFileManagerInternal::SfxMultiRecord::open: oops the zone seems too short\n")); |
121 | 0 | m_extra="###zoneShort,"; |
122 | 0 | return true; |
123 | 0 | } |
124 | 0 | *input >> m_headerType >> m_headerVersion >> m_headerTag; |
125 | 0 | // filerec.cxx: SfxMultiRecordReader::ReadHeader_Impl |
126 | 0 | *input >> m_numRecord >> m_contentSize; |
127 | 0 | m_startPos=input->tell(); |
128 | 0 | std::stringstream s; |
129 | 0 | if (m_headerType==2) { |
130 | 0 | // fixed size |
131 | 0 | if (m_startPos+long(m_numRecord)*long(m_contentSize) > m_endPos) { |
132 | 0 | STOFF_DEBUG_MSG(("StarFileManagerInternal::SfxMultiRecord::open: oops the number of record seems bad\n")); |
133 | 0 | s << "##numRecord=" << m_numRecord << ","; |
134 | 0 | if (m_contentSize && m_endPos>m_startPos) |
135 | 0 | m_numRecord=uint16_t((m_endPos-m_startPos)/long(m_contentSize)); |
136 | 0 | else |
137 | 0 | m_numRecord=0; |
138 | 0 | } |
139 | 0 | m_extra=s.str(); |
140 | 0 | return true; |
141 | 0 | } |
142 | 0 |
|
143 | 0 | long debOffsetList=((m_headerType==3 || m_headerType==7) ? m_startPos : 0) + long(m_contentSize); |
144 | 0 | if (debOffsetList<m_startPos || debOffsetList+4*m_numRecord > m_endPos) { |
145 | 0 | STOFF_DEBUG_MSG(("StarFileManagerInternal::SfxMultiRecord::open: can not find the version map offset\n")); |
146 | 0 | s << "###contentCount"; |
147 | 0 | m_numRecord=0; |
148 | 0 | m_extra=s.str(); |
149 | 0 | return true; |
150 | 0 | } |
151 | 0 | m_endPos=debOffsetList; |
152 | 0 | input->seek(debOffsetList, librevenge::RVNG_SEEK_SET); |
153 | 0 | for (uint16_t i=0; i<m_numRecord; ++i) { |
154 | 0 | uint32_t offset; |
155 | 0 | *input >> offset; |
156 | 0 | m_offsetList.push_back(offset); |
157 | 0 | } |
158 | 0 | input->seek(m_startPos, librevenge::RVNG_SEEK_SET); |
159 | 0 | return true; |
160 | 0 | } |
161 | | //! try to close a zone |
162 | | void close(std::string const &wh) |
163 | 0 | { |
164 | 0 | if (!m_zoneOpened) { |
165 | 0 | STOFF_DEBUG_MSG(("StarFileManagerInternal::SfxMultiRecord::close: can not find any opened zone\n")); |
166 | 0 | return; |
167 | 0 | } |
168 | 0 | m_zoneOpened=false; |
169 | 0 | STOFFInputStreamPtr input=m_zone.input(); |
170 | 0 | if (input->tell()<m_endPos && input->tell()+4>=m_endPos) { // small diff is possible |
171 | 0 | m_zone.ascii().addDelimiter(input->tell(),'|'); |
172 | 0 | input->seek(m_zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET); |
173 | 0 | } |
174 | 0 | else if (input->tell()==m_endPos) |
175 | 0 | input->seek(m_zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET); |
176 | 0 | m_zone.closeSfxRecord(m_zoneType, wh); |
177 | 0 | } |
178 | | //! returns the header tag or -1 |
179 | | int getHeaderTag() const |
180 | 0 | { |
181 | 0 | return !m_zoneOpened ? -1 : int(m_headerTag); |
182 | 0 | } |
183 | | //! try to go to the new content positon |
184 | | bool getNewContent(std::string const &wh) |
185 | 0 | { |
186 | 0 | // SfxMultiRecordReader::GetContent |
187 | 0 | long newPos=getLastContentPosition(); |
188 | 0 | if (newPos>=m_endPos) return false; |
189 | 0 | STOFFInputStreamPtr input=m_zone.input(); |
190 | 0 | ++m_actualRecord; |
191 | 0 | if (input->tell()<newPos && input->tell()+4>=newPos) { // small diff is possible |
192 | 0 | m_zone.ascii().addDelimiter(input->tell(),'|'); |
193 | 0 | input->seek(newPos, librevenge::RVNG_SEEK_SET); |
194 | 0 | } |
195 | 0 | else if (input->tell()!=newPos) { |
196 | 0 | STOFF_DEBUG_MSG(("StarFileManagerInternal::SfxMultiRecord::getNewContent: find extra data\n")); |
197 | 0 | m_zone.ascii().addPos(input->tell()); |
198 | 0 | libstoff::DebugStream f; |
199 | 0 | f << wh << ":###extra"; |
200 | 0 | m_zone.ascii().addNote(f.str().c_str()); |
201 | 0 | input->seek(newPos, librevenge::RVNG_SEEK_SET); |
202 | 0 | } |
203 | 0 | if (m_headerType==7 || m_headerType==8) { |
204 | 0 | // TODO: readtag |
205 | 0 | input->seek(2, librevenge::RVNG_SEEK_CUR); |
206 | 0 | } |
207 | 0 | return true; |
208 | 0 | } |
209 | | //! returns the last content position |
210 | | long getLastContentPosition() const |
211 | 0 | { |
212 | 0 | if (m_actualRecord >= m_numRecord) return m_endPos; |
213 | 0 | if (m_headerType==2) return m_startPos+m_actualRecord*long(m_contentSize); |
214 | 0 | if (m_actualRecord >= uint16_t(m_offsetList.size())) { |
215 | 0 | STOFF_DEBUG_MSG(("StarFileManagerInternal::SfxMultiRecord::getLastContentPosition: argh, find unexpected index\n")); |
216 | 0 | return m_endPos; |
217 | 0 | } |
218 | 0 | return m_startPos+long(m_offsetList[size_t(m_actualRecord)]>>8)-14; |
219 | 0 | } |
220 | | |
221 | | //! basic operator<< ; print header data |
222 | | friend std::ostream &operator<<(std::ostream &o, SfxMultiRecord const &r) |
223 | 0 | { |
224 | 0 | if (!r.m_zoneOpened) { |
225 | 0 | o << r.m_extra; |
226 | 0 | return o; |
227 | 0 | } |
228 | 0 | if (r.m_headerType) o << "type=" << int(r.m_headerType) << ","; |
229 | 0 | if (r.m_headerVersion) o << "version=" << int(r.m_headerVersion) << ","; |
230 | 0 | if (r.m_headerTag) o << "tag=" << r.m_headerTag << ","; |
231 | 0 | if (r.m_numRecord) o << "num[record]=" << r.m_numRecord << ","; |
232 | 0 | if (r.m_contentSize) o << "content[size/pos]=" << r.m_contentSize << ","; |
233 | 0 | if (!r.m_offsetList.empty()) { |
234 | 0 | o << "offset=["; |
235 | 0 | for (unsigned int off : r.m_offsetList) { |
236 | 0 | if (off&0xff) |
237 | 0 | o << (off>>8) << ":" << (off&0xff) << ","; |
238 | 0 | else |
239 | 0 | o << (off>>8) << ","; |
240 | 0 | } |
241 | 0 | o << "],"; |
242 | 0 | } |
243 | 0 | o << r.m_extra; |
244 | 0 | return o; |
245 | 0 | } |
246 | | protected: |
247 | | //! the main zone |
248 | | StarZone &m_zone; |
249 | | //! the zone type |
250 | | unsigned char m_zoneType; |
251 | | //! true if a SfxRecord has been opened |
252 | | bool m_zoneOpened; |
253 | | //! the record type |
254 | | uint8_t m_headerType; |
255 | | //! the header version |
256 | | uint8_t m_headerVersion; |
257 | | //! the header tag |
258 | | uint16_t m_headerTag; |
259 | | //! the actual record |
260 | | uint16_t m_actualRecord; |
261 | | //! the number of record |
262 | | uint16_t m_numRecord; |
263 | | //! the record/content/pos size |
264 | | uint32_t m_contentSize; |
265 | | //! the start of data position |
266 | | long m_startPos; |
267 | | //! the end of data position |
268 | | long m_endPos; |
269 | | //! the list of (offset + type) |
270 | | std::vector<uint32_t> m_offsetList; |
271 | | //! extra data |
272 | | std::string m_extra; |
273 | | private: |
274 | | SfxMultiRecord(SfxMultiRecord const &orig); |
275 | | SfxMultiRecord &operator=(SfxMultiRecord const &orig); |
276 | | }; |
277 | | |
278 | | //////////////////////////////////////// |
279 | | //! Internal: the state of a StarFileManager |
280 | | struct State { |
281 | | //! constructor |
282 | | State() |
283 | 89.4k | { |
284 | 89.4k | } |
285 | | }; |
286 | | |
287 | | } |
288 | | |
289 | | //////////////////////////////////////////////////////////// |
290 | | // constructor/destructor, ... |
291 | | //////////////////////////////////////////////////////////// |
292 | | StarFileManager::StarFileManager() |
293 | 89.4k | : m_state(new StarFileManagerInternal::State) |
294 | 89.4k | { |
295 | 89.4k | } |
296 | | |
297 | | StarFileManager::~StarFileManager() |
298 | 89.4k | { |
299 | 89.4k | } |
300 | | |
301 | | bool StarFileManager::readOLEDirectory(std::shared_ptr<STOFFOLEParser> oleParser, std::shared_ptr<STOFFOLEParser::OleDirectory> ole, STOFFEmbeddedObject &image, std::shared_ptr<StarObject> &res) |
302 | 7.38k | { |
303 | 7.38k | image=STOFFEmbeddedObject(); |
304 | 7.38k | if (!oleParser || !ole || ole->m_inUse) { |
305 | 641 | STOFF_DEBUG_MSG(("StarFileManager::readOLEDirectory: can not read an ole\n")); |
306 | 641 | return false; |
307 | 641 | } |
308 | 6.74k | ole->m_inUse=true; |
309 | 6.74k | StarObject object(nullptr, oleParser, ole); // do we need password here ? |
310 | 6.74k | if (object.getDocumentKind()==STOFFDocument::STOFF_K_CHART) { |
311 | 3.17k | auto chart=std::make_shared<StarObjectChart>(object, false); |
312 | 3.17k | ole->m_parsed=true; |
313 | 3.17k | if (chart->parse()) |
314 | 3.17k | res=chart; |
315 | 3.17k | } |
316 | 3.57k | else if (object.getDocumentKind()==STOFFDocument::STOFF_K_DRAW) { |
317 | 761 | StarObjectDraw draw(object, false); |
318 | 761 | ole->m_parsed=true; |
319 | 761 | if (draw.parse()) { |
320 | 761 | STOFFGraphicEncoder graphicEncoder; |
321 | 761 | std::vector<STOFFPageSpan> pageList; |
322 | 761 | int numPages; |
323 | 761 | if (!draw.updatePageSpans(pageList, numPages)) { |
324 | 244 | STOFFPageSpan ps; |
325 | 244 | ps.m_pageSpan=1; |
326 | 244 | pageList.push_back(ps); |
327 | 244 | } |
328 | 761 | STOFFGraphicListenerPtr graphicListener(new STOFFGraphicListener(STOFFListManagerPtr(), pageList, &graphicEncoder)); |
329 | 761 | graphicListener->startDocument(); |
330 | 761 | draw.sendPages(graphicListener); |
331 | 761 | graphicListener->endDocument(); |
332 | 761 | graphicEncoder.getBinaryResult(image); |
333 | 761 | } |
334 | 761 | } |
335 | 2.81k | else if (object.getDocumentKind()==STOFFDocument::STOFF_K_MATH) { |
336 | 1.15k | auto math=std::make_shared<StarObjectMath>(object, false); |
337 | 1.15k | ole->m_parsed=true; |
338 | 1.15k | if (math->parse()) |
339 | 1.15k | res=math; |
340 | 1.15k | } |
341 | 1.65k | else if (object.getDocumentKind()==STOFFDocument::STOFF_K_SPREADSHEET) { |
342 | 298 | StarObjectSpreadsheet spreadsheet(object, false); |
343 | 298 | ole->m_parsed=true; |
344 | 298 | if (spreadsheet.parse()) { |
345 | 298 | STOFFSpreadsheetEncoder spreadsheetEncoder; |
346 | 298 | std::vector<STOFFPageSpan> pageList; |
347 | 298 | int numPages; |
348 | 298 | if (!spreadsheet.updatePageSpans(pageList, numPages)) { |
349 | 11 | STOFFPageSpan ps; |
350 | 11 | ps.m_pageSpan=1; |
351 | 11 | pageList.push_back(ps); |
352 | 11 | } |
353 | 298 | STOFFListManagerPtr listManager; |
354 | 298 | STOFFSpreadsheetListenerPtr spreadsheetListener(new STOFFSpreadsheetListener(listManager, pageList, &spreadsheetEncoder)); |
355 | 298 | spreadsheetListener->startDocument(); |
356 | 298 | spreadsheet.send(spreadsheetListener); |
357 | 298 | spreadsheetListener->endDocument(); |
358 | 298 | spreadsheetEncoder.getBinaryResult(image); |
359 | 298 | } |
360 | 298 | } |
361 | 1.35k | else if (object.getDocumentKind()==STOFFDocument::STOFF_K_TEXT) { |
362 | 0 | auto text=std::make_shared<StarObjectText>(object, false); |
363 | 0 | ole->m_parsed=true; |
364 | 0 | if (text->parse()) |
365 | 0 | res=text; |
366 | 0 | } |
367 | 1.35k | else { |
368 | 1.35k | ole->m_parsed=true; |
369 | | // Ole-Object has persist elements, so... |
370 | 1.35k | if (ole->m_hasCompObj) object.parse(); |
371 | 1.35k | STOFFOLEParser::OleDirectory &direct=*ole; |
372 | 1.35k | std::vector<std::string> unparsedOLEs=direct.getUnparsedOles(); |
373 | 1.35k | size_t numUnparsed = unparsedOLEs.size(); |
374 | 4.17k | for (size_t i = 0; i < numUnparsed; i++) { |
375 | 2.82k | std::string const &name = unparsedOLEs[i]; |
376 | 2.82k | STOFFInputStreamPtr stream = ole->m_input->getSubStreamByName(name.c_str()); |
377 | 2.82k | if (!stream.get()) { |
378 | 1.30k | STOFF_DEBUG_MSG(("StarFileManager::readOLEDirectory: error: can not find OLE part: \"%s\"\n", name.c_str())); |
379 | 1.30k | continue; |
380 | 1.30k | } |
381 | | |
382 | 1.52k | std::string::size_type pos = name.find_last_of('/'); |
383 | 1.52k | std::string base; |
384 | 1.52k | if (pos == std::string::npos) base = name; |
385 | 1.52k | else |
386 | 1.52k | base = name.substr(pos+1); |
387 | 1.52k | stream->setReadInverted(true); |
388 | 1.52k | if (base=="SfxStyleSheets") { |
389 | 523 | object.readSfxStyleSheets(stream,name); |
390 | 523 | continue; |
391 | 523 | } |
392 | | |
393 | 997 | if (base=="StarImageDocument" || base=="StarImageDocument 4.0") { |
394 | 0 | librevenge::RVNGBinaryData data; |
395 | 0 | if (readImageDocument(stream,data,name) && !data.empty()) |
396 | 0 | image.add(data); |
397 | 0 | continue; |
398 | 0 | } |
399 | | // other |
400 | 997 | if (base=="Ole-Object") { |
401 | 0 | librevenge::RVNGBinaryData data; |
402 | 0 | if (readOleObject(stream,data,name)) |
403 | 0 | image.add(data,"object/ole"); |
404 | 0 | continue; |
405 | 0 | } |
406 | 997 | libstoff::DebugFile asciiFile(stream); |
407 | 997 | asciiFile.open(name); |
408 | | |
409 | 997 | bool ok=false; |
410 | 997 | if (base=="OutPlace Object") |
411 | 0 | ok=readOutPlaceObject(stream, asciiFile); |
412 | 997 | if (!ok) { |
413 | 997 | libstoff::DebugStream f; |
414 | 997 | if (base=="Standard") // can be Standard or STANDARD |
415 | 2 | f << "Entries(STANDARD):"; |
416 | 995 | else |
417 | 995 | f << "Entries(" << base << "):"; |
418 | 997 | asciiFile.addPos(0); |
419 | 997 | asciiFile.addNote(f.str().c_str()); |
420 | 997 | } |
421 | 997 | asciiFile.reset(); |
422 | 997 | } |
423 | 1.35k | } |
424 | | // finally look if some content have image |
425 | 42.4k | for (auto &content : ole->m_contentList) { |
426 | 42.4k | librevenge::RVNGBinaryData data; |
427 | 42.4k | std::string type; |
428 | 42.4k | if (content.getImageData(data,type)) |
429 | 0 | image.add(data, type); |
430 | 42.4k | } |
431 | 6.74k | ole->m_inUse=false; |
432 | 6.74k | return !image.isEmpty(); |
433 | 7.38k | } |
434 | | |
435 | | void StarFileManager::checkUnparsed(STOFFInputStreamPtr input, std::shared_ptr<STOFFOLEParser> oleParser, char const *password) |
436 | 0 | { |
437 | 0 | if (!input || !oleParser) { |
438 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readOLEDirectory: can not find the input/ole parser\n")); |
439 | 0 | return; |
440 | 0 | } |
441 | 0 | auto listDir=oleParser->getDirectoryList(); |
442 | 0 | for (auto &dir : listDir) { |
443 | 0 | if (!dir || dir->m_parsed) continue; |
444 | 0 | dir->m_parsed=true; |
445 | 0 | StarObject object(password, oleParser, dir); |
446 | 0 | if (object.getDocumentKind()==STOFFDocument::STOFF_K_CHART) { |
447 | 0 | StarObjectChart chart(object, false); |
448 | 0 | chart.parse(); |
449 | 0 | continue; |
450 | 0 | } |
451 | 0 | if (object.getDocumentKind()==STOFFDocument::STOFF_K_DRAW) { |
452 | 0 | StarObjectDraw draw(object, false); |
453 | 0 | draw.parse(); |
454 | 0 | continue; |
455 | 0 | } |
456 | 0 | if (object.getDocumentKind()==STOFFDocument::STOFF_K_MATH) { |
457 | 0 | StarObjectMath math(object, false); |
458 | 0 | math.parse(); |
459 | 0 | continue; |
460 | 0 | } |
461 | 0 | if (object.getDocumentKind()==STOFFDocument::STOFF_K_SPREADSHEET) { |
462 | 0 | StarObjectSpreadsheet spreadsheet(object, false); |
463 | 0 | spreadsheet.parse(); |
464 | 0 | continue; |
465 | 0 | } |
466 | 0 | if (object.getDocumentKind()==STOFFDocument::STOFF_K_TEXT) { |
467 | 0 | StarObjectText text(object, false); |
468 | 0 | text.parse(); |
469 | 0 | continue; |
470 | 0 | } |
471 | | // Ole-Object has persist elements, so... |
472 | 0 | if (dir->m_hasCompObj) object.parse(); |
473 | 0 | auto unparsedOLEs=dir->getUnparsedOles(); |
474 | 0 | for (auto const &name : unparsedOLEs) { |
475 | 0 | auto ole = input->getSubStreamByName(name.c_str()); |
476 | 0 | if (!ole.get()) { |
477 | 0 | STOFF_DEBUG_MSG(("SDWParser::createZones: error: can not find OLE part: \"%s\"\n", name.c_str())); |
478 | 0 | continue; |
479 | 0 | } |
480 | | |
481 | 0 | auto pos = name.find_last_of('/'); |
482 | 0 | std::string base; |
483 | 0 | if (pos == std::string::npos) base = name; |
484 | 0 | else base = name.substr(pos+1); |
485 | 0 | ole->setReadInverted(true); |
486 | 0 | if (base=="SfxStyleSheets") { |
487 | 0 | object.readSfxStyleSheets(ole,name); |
488 | 0 | continue; |
489 | 0 | } |
490 | | |
491 | 0 | if (base=="StarImageDocument" || base=="StarImageDocument 4.0") { |
492 | 0 | librevenge::RVNGBinaryData data; |
493 | 0 | readImageDocument(ole,data,name); |
494 | 0 | continue; |
495 | 0 | } |
496 | 0 | if (base.compare(0,3,"Pic")==0) { |
497 | 0 | librevenge::RVNGBinaryData data; |
498 | 0 | std::string type; |
499 | 0 | readEmbeddedPicture(ole,data,type,name); |
500 | 0 | continue; |
501 | 0 | } |
502 | | // other |
503 | 0 | if (base=="Ole-Object") { |
504 | 0 | librevenge::RVNGBinaryData data; |
505 | 0 | readOleObject(ole,data,name); |
506 | 0 | continue; |
507 | 0 | } |
508 | 0 | libstoff::DebugFile asciiFile(ole); |
509 | 0 | asciiFile.open(name); |
510 | |
|
511 | 0 | bool ok=false; |
512 | 0 | if (base=="OutPlace Object") |
513 | 0 | ok=readOutPlaceObject(ole, asciiFile); |
514 | 0 | if (!ok) { |
515 | 0 | libstoff::DebugStream f; |
516 | 0 | if (base=="Standard") // can be Standard or STANDARD |
517 | 0 | f << "Entries(STANDARD):"; |
518 | 0 | else |
519 | 0 | f << "Entries(" << base << "):"; |
520 | 0 | asciiFile.addPos(0); |
521 | 0 | asciiFile.addNote(f.str().c_str()); |
522 | 0 | } |
523 | 0 | asciiFile.reset(); |
524 | 0 | } |
525 | 0 | } |
526 | 0 | } |
527 | | |
528 | | bool StarFileManager::readImageDocument(STOFFInputStreamPtr input, librevenge::RVNGBinaryData &data, std::string const &fileName) |
529 | 0 | { |
530 | | // see this Ole with classic bitmap format |
531 | 0 | libstoff::DebugFile ascii(input); |
532 | 0 | ascii.open(fileName); |
533 | 0 | ascii.skipZone(0, input->size()); |
534 | |
|
535 | 0 | input->seek(0, librevenge::RVNG_SEEK_SET); |
536 | 0 | data.clear(); |
537 | 0 | if (!input->readEndDataBlock(data)) { |
538 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readImageDocument: can not read image content\n")); |
539 | 0 | return false; |
540 | 0 | } |
541 | | #ifdef DEBUG_WITH_FILES |
542 | | libstoff::Debug::dumpFile(data, (fileName+".ppm").c_str()); |
543 | | #endif |
544 | 0 | return true; |
545 | 0 | } |
546 | | |
547 | | bool StarFileManager::readEmbeddedPicture(std::shared_ptr<STOFFOLEParser> oleParser, std::string const &fileName, STOFFEmbeddedObject &image) |
548 | 35 | { |
549 | 35 | if (!oleParser) { |
550 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readEmbeddedPicture: called without OLE parser\n")); |
551 | 0 | return false; |
552 | 0 | } |
553 | 35 | auto dir=oleParser->getDirectory("EmbeddedPictures"); |
554 | 35 | if (!dir || !dir->m_input || !dir->m_input->isStructured()) { |
555 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readEmbeddedPicture: can not find the embedded picture directory\n")); |
556 | 0 | return false; |
557 | 0 | } |
558 | 35 | std::string name("EmbeddedPictures/"); |
559 | 35 | name+=fileName; |
560 | 35 | auto ole= dir->m_input->getSubStreamByName(name.c_str()); |
561 | 35 | if (!ole) { |
562 | 10 | STOFF_DEBUG_MSG(("StarFileManager::readEmbeddedPicture: can not find the picture %s\n", name.c_str())); |
563 | 10 | return false; |
564 | 10 | } |
565 | 25 | librevenge::RVNGBinaryData data; |
566 | 25 | std::string type; |
567 | 25 | if (!readEmbeddedPicture(ole,data,type,name)) |
568 | 10 | return false; |
569 | 15 | image.add(data, type); |
570 | 15 | return true; |
571 | 25 | } |
572 | | |
573 | | bool StarFileManager::readEmbeddedPicture(STOFFInputStreamPtr input, librevenge::RVNGBinaryData &data, std::string &dataType, std::string const &fileName) |
574 | 25 | try |
575 | 25 | { |
576 | | // see this Ole with classic bitmap format |
577 | 25 | StarZone zone(input, fileName, "EmbeddedPicture", nullptr); |
578 | | |
579 | 25 | libstoff::DebugFile &ascii=zone.ascii(); |
580 | 25 | ascii.open(fileName); |
581 | 25 | data.clear(); |
582 | 25 | dataType=""; |
583 | | // impgraph.cxx: ImpGraphic::ImplReadEmbedded |
584 | | |
585 | 25 | input->seek(0, librevenge::RVNG_SEEK_SET); |
586 | 25 | libstoff::DebugStream f; |
587 | 25 | f << "Entries(EmbeddedPicture):"; |
588 | 25 | uint32_t nId; |
589 | 25 | int32_t nLen; |
590 | | |
591 | 25 | *input>>nId; |
592 | 25 | if (nId==0x35465247 || nId==0x47524635) { |
593 | 13 | if (nId==0x47524635) |
594 | 13 | input->setReadInverted(!input->readInverted()); |
595 | 13 | if (!zone.openVersionCompatHeader()) { |
596 | 0 | f << "###"; |
597 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readEmbeddedPicture: can not open the header\n")); |
598 | 0 | ascii.addPos(0); |
599 | 0 | ascii.addNote(f.str().c_str()); |
600 | 0 | return false; |
601 | 0 | } |
602 | 13 | int32_t nType; |
603 | 13 | int32_t sizeX, sizeY; |
604 | 13 | *input >> nType >> nLen >> sizeX>> sizeY; |
605 | 13 | if (nType) |
606 | 13 | f << "type=" << nType << ","; |
607 | 13 | f << "size=" << sizeX << "x" << sizeY << ","; |
608 | | // mapmod.cxx: operator>>(..., ImplMapMode& ) |
609 | 13 | if (!zone.openVersionCompatHeader()) { |
610 | 0 | f << "###"; |
611 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readEmbeddedPicture: can not open the mapmod header\n")); |
612 | 0 | } |
613 | 13 | else { |
614 | 13 | uint16_t nMapMode; |
615 | 13 | int32_t nOffsX, nOffsY, nScaleNumX, nScaleDenomX, nScaleNumY, nScaleDenomY; |
616 | 13 | bool mbSimple; |
617 | 13 | *input >> nMapMode >> nOffsX>> nOffsY; |
618 | 13 | if (nMapMode) f << "mapMode=" << nMapMode << ","; |
619 | 13 | if (nOffsX || nOffsY) |
620 | 0 | f << "offs=" << nOffsX << "x" << nOffsY << ","; |
621 | 13 | *input >> nScaleNumX >> nScaleDenomX >> nScaleNumY >> nScaleDenomY >> mbSimple; |
622 | 13 | f << "scaleX=" << nScaleNumX << "/" << nScaleDenomX << ","; |
623 | 13 | f << "scaleY=" << nScaleNumY << "/" << nScaleDenomY << ","; |
624 | 13 | if (mbSimple) f << "simple,"; |
625 | 13 | zone.closeVersionCompatHeader("StarFileManager"); |
626 | 13 | } |
627 | 13 | zone.closeVersionCompatHeader("StarFileManager"); |
628 | 13 | } |
629 | 12 | else { |
630 | 12 | if (nId>0x100) { |
631 | 12 | input->seek(0, librevenge::RVNG_SEEK_SET); |
632 | 12 | input->setReadInverted(!input->readInverted()); |
633 | 12 | *input>>nId; |
634 | 12 | } |
635 | 12 | if (nId) |
636 | 12 | f << "type=" << nId << ","; |
637 | 12 | int32_t nWidth, nHeight, nMapMode, nScaleNumX, nScaleDenomX, nScaleNumY, nScaleDenomY, nOffsX, nOffsY; |
638 | 12 | *input >> nLen >> nWidth >> nHeight >> nMapMode; |
639 | 12 | f << "size=" << nWidth << "x" << nHeight << ","; |
640 | 12 | if (nMapMode) f << "mapMode=" << nMapMode << ","; |
641 | 12 | *input >> nScaleNumX >> nScaleDenomX >> nScaleNumY >> nScaleDenomY; |
642 | 12 | f << "scaleX=" << nScaleNumX << "/" << nScaleDenomX << ","; |
643 | 12 | f << "scaleY=" << nScaleNumY << "/" << nScaleDenomY << ","; |
644 | 12 | *input >> nOffsX >> nOffsY; |
645 | 12 | f << "offset=" << nOffsX << "x" << nOffsY << ","; |
646 | 12 | } |
647 | 25 | if (nLen<10 || input->size()!=input->tell()+nLen) { |
648 | 10 | f << "###"; |
649 | 10 | STOFF_DEBUG_MSG(("StarFileManager::readEmbeddedPicture: the length seems bad\n")); |
650 | 10 | ascii.addPos(0); |
651 | 10 | ascii.addNote(f.str().c_str()); |
652 | 10 | return false; |
653 | 10 | } |
654 | 15 | long pictPos=input->tell(); |
655 | 15 | auto header=int(input->readULong(2)); |
656 | 15 | input->seek(pictPos, librevenge::RVNG_SEEK_SET); |
657 | 15 | std::string extension("pict"); |
658 | 15 | if (header==0x4142 || header==0x4d42) { |
659 | 3 | dataType="image/bm"; |
660 | 3 | extension="bm"; |
661 | | #ifdef DEBUG_WITH_FILES |
662 | | StarBitmap bitmap; |
663 | | bitmap.readBitmap(zone, true, input->size(), data, dataType); |
664 | | #endif |
665 | 3 | } |
666 | 12 | else if (header==0x5653) { |
667 | | #ifdef DEBUG_WITH_FILES |
668 | | readSVGDI(zone); |
669 | | #endif |
670 | 0 | dataType="image/svg"; |
671 | 0 | extension="svgdi"; |
672 | 0 | } |
673 | 12 | else if (header==0xcdd7) { |
674 | 0 | dataType="image/wmf"; |
675 | 0 | extension="wmf"; |
676 | 0 | } |
677 | 12 | else if (header==0x414e) { |
678 | 12 | bool nat5=input->readULong(4)==0x3554414e; |
679 | 12 | input->seek(pictPos, librevenge::RVNG_SEEK_SET); |
680 | 12 | StarGraphicStruct::StarGraphic graphic; |
681 | 12 | if (nat5 && graphic.read(zone,input->size())) { |
682 | 11 | ascii.addPos(0); |
683 | 11 | ascii.addNote(f.str().c_str()); |
684 | 11 | dataType=graphic.m_object.m_typeList.empty() ? "image/pict" : graphic.m_object.m_typeList[0]; |
685 | 11 | if (!graphic.m_object.m_dataList.empty()) |
686 | 10 | data=graphic.m_object.m_dataList[0]; |
687 | 11 | return true; |
688 | 11 | } |
689 | 1 | dataType="image/pict"; |
690 | 1 | f << "###unknown"; |
691 | 1 | STOFF_DEBUG_MSG(("StarFileManager::readEmbeddedPicture: find unknown format\n")); |
692 | 1 | } |
693 | 0 | else if (header==0x4356) { // VLCMTF |
694 | 0 | dataType="image/pict"; |
695 | 0 | extension="pict"; |
696 | 0 | } |
697 | 0 | else { |
698 | 0 | dataType="image/pict"; |
699 | 0 | f << "###unknown"; |
700 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readEmbeddedPicture: find unknown format\n")); |
701 | 0 | } |
702 | 4 | f << extension << ","; |
703 | 4 | if (input->tell()==pictPos) ascii.addDelimiter(input->tell(),'|'); |
704 | 4 | ascii.addPos(0); |
705 | 4 | ascii.addNote(f.str().c_str()); |
706 | 4 | ascii.skipZone(pictPos+4, input->size()); |
707 | | |
708 | 4 | input->seek(pictPos, librevenge::RVNG_SEEK_SET); |
709 | 4 | if (!input->readEndDataBlock(data)) { |
710 | 0 | data.clear(); |
711 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readEmbeddedPicture: can not read image content\n")); |
712 | 0 | return true; |
713 | 0 | } |
714 | | #ifdef DEBUG_WITH_FILES |
715 | | libstoff::Debug::dumpFile(data, (fileName+"."+extension).c_str()); |
716 | | #endif |
717 | 4 | return true; |
718 | 4 | } |
719 | 25 | catch (...) |
720 | 25 | { |
721 | 0 | return false; |
722 | 0 | } |
723 | | |
724 | | bool StarFileManager::readOleObject(STOFFInputStreamPtr input, librevenge::RVNGBinaryData &data, std::string const &fileName) |
725 | 0 | { |
726 | | // see this Ole only once with PaintBrush data ? |
727 | 0 | libstoff::DebugFile ascii(input); |
728 | 0 | ascii.open(fileName); |
729 | 0 | ascii.skipZone(0, input->size()); |
730 | |
|
731 | 0 | input->seek(0, librevenge::RVNG_SEEK_SET); |
732 | 0 | if (!input->readEndDataBlock(data)) { |
733 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readOleObject: can not read image content\n")); |
734 | 0 | data.clear(); |
735 | 0 | return false; |
736 | 0 | } |
737 | | #ifdef DEBUG_WITH_FILES |
738 | | libstoff::Debug::dumpFile(data, (fileName+".ole").c_str()); |
739 | | #endif |
740 | 0 | return true; |
741 | 0 | } |
742 | | |
743 | | bool StarFileManager::readOutPlaceObject(STOFFInputStreamPtr input, libstoff::DebugFile &ascii) |
744 | 0 | { |
745 | 0 | input->seek(0, librevenge::RVNG_SEEK_SET); |
746 | 0 | libstoff::DebugStream f; |
747 | 0 | f << "Entries(OutPlaceObject):"; |
748 | | // see outplace.cxx SvOutPlaceObject::SaveCompleted |
749 | 0 | if (input->size()<7) { |
750 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readOutPlaceObject: file is too short\n")); |
751 | 0 | f << "###"; |
752 | 0 | } |
753 | 0 | else { |
754 | 0 | uint16_t len; |
755 | 0 | uint32_t dwAspect; |
756 | 0 | bool setExtent; |
757 | 0 | *input>>len >> dwAspect >> setExtent; |
758 | 0 | if (len!=7) f << "length=" << len << ","; |
759 | 0 | if (dwAspect) f << "dwAspect=" << dwAspect << ","; |
760 | 0 | if (setExtent) f << setExtent << ","; |
761 | 0 | if (!input->isEnd()) { |
762 | 0 | STOFF_DEBUG_MSG(("StarFileManager::readOutPlaceObject: find extra data\n")); |
763 | 0 | f << "###extra"; |
764 | 0 | ascii.addDelimiter(input->tell(),'|'); |
765 | 0 | } |
766 | 0 | } |
767 | 0 | ascii.addPos(0); |
768 | 0 | ascii.addNote(f.str().c_str()); |
769 | 0 | return true; |
770 | 0 | } |
771 | | |
772 | | //////////////////////////////////////////////////////////// |
773 | | // small zone |
774 | | //////////////////////////////////////////////////////////// |
775 | | bool StarFileManager::readFont(StarZone &zone) |
776 | 38.8k | { |
777 | 38.8k | STOFFInputStreamPtr input=zone.input(); |
778 | 38.8k | libstoff::DebugFile &ascFile=zone.ascii(); |
779 | 38.8k | long pos=input->tell(); |
780 | | // font.cxx: operator>>( ..., Impl_Font& ) |
781 | 38.8k | libstoff::DebugStream f; |
782 | 38.8k | f << "Entries(StarFont)[" << zone.getRecordLevel() << "]:"; |
783 | 38.8k | if (!zone.openVersionCompatHeader()) { |
784 | 2.39k | STOFF_DEBUG_MSG(("StarFileManager::readFont: can not read the header\n")); |
785 | 2.39k | f << "###header"; |
786 | 2.39k | ascFile.addPos(pos); |
787 | 2.39k | ascFile.addNote(f.str().c_str()); |
788 | 2.39k | return false; |
789 | 2.39k | } |
790 | 36.4k | long lastPos=zone.getRecordLastPosition(); |
791 | 106k | for (int i=0; i<2; ++i) { |
792 | 71.5k | std::vector<uint32_t> string; |
793 | 71.5k | if (!zone.readString(string)||input->tell()>lastPos) { |
794 | 1.80k | STOFF_DEBUG_MSG(("StarFileManager::readFont: can not read a string\n")); |
795 | 1.80k | f << "###string"; |
796 | 1.80k | ascFile.addPos(pos); |
797 | 1.80k | ascFile.addNote(f.str().c_str()); |
798 | 1.80k | zone.closeVersionCompatHeader("StarFont"); |
799 | 1.80k | return true; |
800 | 1.80k | } |
801 | 69.7k | if (!string.empty()) f << (i==0 ? "name" : "style") << "=" << libstoff::getString(string).cstr() << ","; |
802 | 69.7k | } |
803 | 34.6k | f << "size=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
804 | 34.6k | uint16_t eCharSet, eFamily, ePitch, eWeight, eUnderline, eStrikeOut, eItalic, eLanguage, eWidthType; |
805 | 34.6k | int16_t orientation; |
806 | 34.6k | *input >> eCharSet >> eFamily >> ePitch >> eWeight >> eUnderline >> eStrikeOut |
807 | 34.6k | >> eItalic >> eLanguage >> eWidthType >> orientation; |
808 | 34.6k | if (eCharSet) f << "eCharSet=" << eCharSet << ","; |
809 | 34.6k | if (eFamily) f << "eFamily=" << eFamily << ","; |
810 | 34.6k | if (ePitch) f << "ePitch=" << ePitch << ","; |
811 | 34.6k | if (eWeight) f << "eWeight=" << eWeight << ","; |
812 | 34.6k | if (eUnderline) f << "eUnderline=" << eUnderline << ","; |
813 | 34.6k | if (eStrikeOut) f << "eStrikeOut=" << eStrikeOut << ","; |
814 | 34.6k | if (eItalic) f << "eItalic=" << eItalic << ","; |
815 | 34.6k | if (eLanguage) f << "eLanguage=" << eLanguage << ","; |
816 | 34.6k | if (eWidthType) f << "eWidthType=" << eWidthType << ","; |
817 | 34.6k | if (orientation) f << "orientation=" << orientation << ","; |
818 | 34.6k | bool wordline, outline, shadow; |
819 | 34.6k | uint8_t kerning; |
820 | 34.6k | *input >> wordline >> outline >> shadow >> kerning; |
821 | 34.6k | if (wordline) f << "wordline,"; |
822 | 34.6k | if (outline) f << "outline,"; |
823 | 34.6k | if (shadow) f << "shadow,"; |
824 | 34.6k | if (kerning) f << "kerning=" << int(kerning) << ","; |
825 | 34.6k | if (zone.getHeaderVersion() >= 2) { |
826 | 4.63k | bool vertical; |
827 | 4.63k | int8_t relief; |
828 | 4.63k | uint16_t cjkLanguage, emphasisMark; |
829 | 4.63k | *input >> relief >> cjkLanguage >> vertical >> emphasisMark; |
830 | 4.63k | if (relief) f << "relief=" << int(relief) << ","; |
831 | 4.63k | if (cjkLanguage) f << "cjkLanguage=" << cjkLanguage << ","; |
832 | 4.63k | if (vertical) f << "vertical,"; |
833 | 4.63k | if (emphasisMark) f << "emphasisMark=" << emphasisMark << ","; |
834 | 4.63k | } |
835 | 34.6k | if (zone.getHeaderVersion() >= 3) { |
836 | 4.59k | int16_t overline; |
837 | 4.59k | *input>>overline; |
838 | 4.59k | if (overline) f << "overline=" << overline << ","; |
839 | 4.59k | } |
840 | 34.6k | ascFile.addPos(pos); |
841 | 34.6k | ascFile.addNote(f.str().c_str()); |
842 | | |
843 | 34.6k | zone.closeVersionCompatHeader("StarFont"); |
844 | 34.6k | return true; |
845 | 36.4k | } |
846 | | |
847 | | bool StarFileManager::readJobSetUp(StarZone &zone, bool useJobLen) |
848 | 11.8k | { |
849 | 11.8k | STOFFInputStreamPtr input=zone.input(); |
850 | 11.8k | libstoff::DebugFile &ascFile=zone.ascii(); |
851 | 11.8k | long pos=input->tell(); |
852 | | // sw_sw3misc.cxx: InJobSetup |
853 | 11.8k | libstoff::DebugStream f; |
854 | 11.8k | f << "Entries(JobSetUp)[" << zone.getRecordLevel() << "]:"; |
855 | | // sfx2_printer.cxx: SfxPrinter::Create |
856 | | // jobset.cxx: JobSetup operator>> |
857 | 11.8k | long lastPos=zone.getRecordLastPosition(); |
858 | 11.8k | auto len=int(input->readULong(2)); |
859 | 11.8k | f << "nLen=" << len << ","; |
860 | 11.8k | if (len==0) { |
861 | 1.39k | ascFile.addPos(pos); |
862 | 1.39k | ascFile.addNote(f.str().c_str()); |
863 | 1.39k | return true; |
864 | 1.39k | } |
865 | 10.4k | if (useJobLen) { |
866 | 2.54k | if (pos+len>lastPos) { |
867 | 129 | STOFF_DEBUG_MSG(("StarFileManager::readJobSetUp: the jobs len seems bad\n")); |
868 | 129 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
869 | 129 | return false; |
870 | 129 | } |
871 | 2.41k | else |
872 | 2.41k | lastPos=pos+len; |
873 | 2.54k | } |
874 | 10.3k | bool ok=false; |
875 | 10.3k | int nSystem=0; |
876 | 10.3k | if (input->tell()+2+64+3*32<=lastPos) { |
877 | 9.99k | nSystem=int(input->readULong(2)); |
878 | 9.99k | f << "system=" << nSystem << ","; |
879 | 49.9k | for (int i=0; i<4; ++i) { |
880 | 39.9k | long actPos=input->tell(); |
881 | 39.9k | int const length=(i==0 ? 64 : 32); |
882 | 39.9k | std::string name(""); |
883 | 332k | for (int c=0; c<length; ++c) { |
884 | 331k | auto ch=char(input->readULong(1)); |
885 | 331k | if (ch==0) break; |
886 | 292k | name+=ch; |
887 | 292k | } |
888 | 39.9k | if (!name.empty()) { |
889 | 21.4k | static char const* const wh[]= { "printerName", "deviceName", "portName", "driverName" }; |
890 | 21.4k | f << wh[i] << "=" << name << ","; |
891 | 21.4k | } |
892 | 39.9k | input->seek(actPos+length, librevenge::RVNG_SEEK_SET); |
893 | 39.9k | } |
894 | 9.99k | ok=true; |
895 | 9.99k | } |
896 | 10.3k | if (ok && nSystem<0xfffe) { |
897 | 7.53k | ascFile.addPos(pos); |
898 | 7.53k | ascFile.addNote(f.str().c_str()); |
899 | | |
900 | 7.53k | pos=input->tell(); |
901 | 7.53k | f.str(""); |
902 | 7.53k | f << "JobSetUp:driverData,"; |
903 | 7.53k | input->seek(lastPos, librevenge::RVNG_SEEK_SET); |
904 | 7.53k | } |
905 | 2.81k | else if (ok && input->tell()+22<=lastPos) { |
906 | 2.45k | int driverDataLen=0; |
907 | 2.45k | f << "nSize2=" << input->readULong(2) << ","; |
908 | 2.45k | f << "nSystem2=" << input->readULong(2) << ","; |
909 | 2.45k | driverDataLen=int(input->readULong(4)); |
910 | 2.45k | f << "nOrientation=" << input->readULong(2) << ","; |
911 | 2.45k | f << "nPaperBin=" << input->readULong(2) << ","; |
912 | 2.45k | f << "nPaperFormat=" << input->readULong(2) << ","; |
913 | 2.45k | f << "nPaperWidth=" << input->readULong(4) << ","; |
914 | 2.45k | f << "nPaperHeight=" << input->readULong(4) << ","; |
915 | | |
916 | 2.45k | if (driverDataLen && input->tell()+driverDataLen<=lastPos) { |
917 | 1.69k | ascFile.addPos(input->tell()); |
918 | 1.69k | ascFile.addNote("JobSetUp:driverData"); |
919 | 1.69k | input->seek(driverDataLen, librevenge::RVNG_SEEK_CUR); |
920 | 1.69k | } |
921 | 758 | else if (driverDataLen) |
922 | 118 | ok=false; |
923 | 2.45k | if (ok) { |
924 | 2.33k | ascFile.addPos(pos); |
925 | 2.33k | ascFile.addNote(f.str().c_str()); |
926 | 2.33k | pos=input->tell(); |
927 | 2.33k | f.str(""); |
928 | 2.33k | f << "JobSetUp[values]:"; |
929 | 2.33k | if (nSystem==0xfffe) { |
930 | 1.41k | std::vector<uint32_t> text; |
931 | 3.91k | while (input->tell()<lastPos) { |
932 | 7.68k | for (int i=0; i<2; ++i) { |
933 | 5.18k | if (!zone.readString(text)) { |
934 | 174 | f << "###string,"; |
935 | 174 | ok=false; |
936 | 174 | break; |
937 | 174 | } |
938 | 5.01k | f << libstoff::getString(text).cstr() << (i==0 ? ':' : ','); |
939 | 5.01k | } |
940 | 2.67k | if (!ok) |
941 | 174 | break; |
942 | 2.67k | } |
943 | 1.41k | } |
944 | 921 | else if (input->tell()<lastPos) { |
945 | 59 | ascFile.addPos(input->tell()); |
946 | 59 | ascFile.addNote("JobSetUp:driverData"); |
947 | 59 | input->seek(lastPos, librevenge::RVNG_SEEK_SET); |
948 | 59 | } |
949 | 2.33k | } |
950 | 2.45k | } |
951 | 10.3k | if (pos!=lastPos) { |
952 | 9.45k | ascFile.addPos(pos); |
953 | 9.45k | ascFile.addNote(f.str().c_str()); |
954 | 9.45k | } |
955 | 10.3k | return true; |
956 | 10.4k | } |
957 | | |
958 | | bool StarFileManager::readSVGDI(StarZone &zone) |
959 | 3.74k | { |
960 | 3.74k | STOFFInputStreamPtr input=zone.input(); |
961 | 3.74k | libstoff::DebugFile &ascFile=zone.ascii(); |
962 | 3.74k | long pos=input->tell(); |
963 | 3.74k | long lastPos=zone.getRecordLevel()==0 ? input->size() : zone.getRecordLastPosition(); |
964 | | // cvtsvm.cxx: SVMConverter::ImplConvertFromSVM1 |
965 | 3.74k | libstoff::DebugStream f; |
966 | 3.74k | f << "Entries(ImageSVGDI)[" << zone.getRecordLevel() << "]:"; |
967 | 3.74k | std::string code; |
968 | 22.4k | for (int i=0; i<5; ++i) code+=char(input->readULong(1)); |
969 | 3.74k | if (code!="SVGDI") { |
970 | 170 | input->seek(0, librevenge::RVNG_SEEK_SET); |
971 | 170 | return false; |
972 | 170 | } |
973 | 3.57k | uint16_t sz; |
974 | 3.57k | int16_t version; |
975 | 3.57k | int32_t width, height; |
976 | 3.57k | *input >> sz >> version >> width >> height; |
977 | 3.57k | long endPos=pos+5+sz; |
978 | 3.57k | if (version!=200 || sz<42 || endPos>lastPos) { |
979 | 155 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: find unknown version\n")); |
980 | 155 | f << "###"; |
981 | 155 | ascFile.addPos(pos); |
982 | 155 | ascFile.addNote(f.str().c_str()); |
983 | 155 | return false; |
984 | 155 | } |
985 | 3.41k | f << "size=" << width << "x" << height << ","; |
986 | | // map mode |
987 | 3.41k | int16_t unit; |
988 | 3.41k | int32_t orgX, orgY, nXNum, nXDenom, nYNum, nYDenom; |
989 | 3.41k | *input >> unit >> orgX >> orgY >> nXNum >> nXDenom >> nYNum >> nYDenom; |
990 | 3.41k | if (unit) f << "unit=" << unit << ","; |
991 | 3.41k | f << "orig=" << orgX << "x" << orgY << ","; |
992 | 3.41k | f << "x=" << nXNum << "/" << nXDenom << ","; |
993 | 3.41k | f << "y=" << nYNum << "/" << nYDenom << ","; |
994 | | |
995 | 3.41k | int32_t nActions; |
996 | 3.41k | *input >> nActions; |
997 | 3.41k | f << "actions=" << nActions << ","; |
998 | 3.41k | if (input->tell()!=endPos) |
999 | 3.26k | ascFile.addDelimiter(input->tell(),'|'); |
1000 | 3.41k | ascFile.addPos(pos); |
1001 | 3.41k | ascFile.addNote(f.str().c_str()); |
1002 | 3.41k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1003 | 3.41k | uint32_t nUnicodeCommentActionNumber=0; |
1004 | 9.67k | for (int32_t i=0; i<nActions; ++i) { |
1005 | 9.67k | pos=input->tell(); |
1006 | 9.67k | f.str(""); |
1007 | 9.67k | f << "ImageSVGDI[" << i << "]:"; |
1008 | 9.67k | int16_t type; |
1009 | 9.67k | int32_t nActionSize; |
1010 | 9.67k | *input>>type>>nActionSize; |
1011 | 9.67k | long endDataPos=pos+2+nActionSize; |
1012 | 9.67k | if (nActionSize<4 || (lastPos-pos-2)<nActionSize || endDataPos>lastPos) { |
1013 | 3.41k | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: bad size\n")); |
1014 | 3.41k | f << "###"; |
1015 | 3.41k | ascFile.addPos(pos); |
1016 | 3.41k | ascFile.addNote(f.str().c_str()); |
1017 | 3.41k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1018 | 3.41k | break; |
1019 | 3.41k | } |
1020 | 6.26k | unsigned char col[3]; |
1021 | 6.26k | STOFFColor color; |
1022 | 6.26k | int32_t nTmp, nTmp1; |
1023 | 6.26k | std::vector<uint32_t> text; |
1024 | 6.26k | switch (type) { |
1025 | 28 | case 1: |
1026 | 28 | f << "pixel=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1027 | 84 | for (unsigned char &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
1028 | 28 | f << "col=" << STOFFColor(col[0],col[1],col[2]) << ","; |
1029 | 28 | break; |
1030 | 51 | case 2: |
1031 | 51 | f << "point=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1032 | 51 | break; |
1033 | 29 | case 3: |
1034 | 29 | f << "line=" << input->readLong(4) << "x" << input->readLong(4) << "<->" |
1035 | 29 | << input->readLong(4) << "x" << input->readLong(4) << ","; |
1036 | 29 | break; |
1037 | 19 | case 4: |
1038 | 19 | f << "rect=" << input->readLong(4) << "x" << input->readLong(4) << "<->" |
1039 | 19 | << input->readLong(4) << "x" << input->readLong(4) << ","; |
1040 | 19 | *input >> nTmp >> nTmp1; |
1041 | 19 | if (nTmp || nTmp1) f << "round=" << nTmp << "x" << nTmp1 << ","; |
1042 | 19 | break; |
1043 | 25 | case 5: |
1044 | 25 | f << "ellipse=" << input->readLong(4) << "x" << input->readLong(4) << "<->" |
1045 | 25 | << input->readLong(4) << "x" << input->readLong(4) << ","; |
1046 | 25 | break; |
1047 | 26 | case 6: |
1048 | 47 | case 7: |
1049 | 47 | f << (type==6 ? "arc" : "pie")<< "=" << input->readLong(4) << "x" << input->readLong(4) << "<->" |
1050 | 47 | << input->readLong(4) << "x" << input->readLong(4) << ","; |
1051 | 47 | f << "pt1=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1052 | 47 | f << "pt2=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1053 | 47 | break; |
1054 | 25 | case 8: |
1055 | 47 | case 9: |
1056 | 47 | f << (type==8 ? "rect[invert]" : "rect[highlight") << "=" |
1057 | 47 | << input->readLong(4) << "x" << input->readLong(4) << "<->" |
1058 | 47 | << input->readLong(4) << "x" << input->readLong(4) << ","; |
1059 | 47 | break; |
1060 | 154 | case 10: |
1061 | 185 | case 11: |
1062 | 185 | f << (type==10 ? "polyline" : "polygon") << ","; |
1063 | 185 | *input >> nTmp; |
1064 | 185 | if (nTmp<0 || nTmp>(endDataPos-input->tell())/8) { |
1065 | 119 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: bad number of points\n")); |
1066 | 119 | f << "###nPts=" << nTmp << ","; |
1067 | 119 | break; |
1068 | 119 | } |
1069 | 66 | f << "pts=["; |
1070 | 225 | for (int pt=0; pt<int(nTmp); ++pt) f << input->readLong(4) << "x" << input->readLong(4) << ","; |
1071 | 66 | f << "],"; |
1072 | 66 | break; |
1073 | 295 | case 12: |
1074 | 313 | case 1024: |
1075 | 321 | case 1025: |
1076 | 357 | case 1030: |
1077 | 357 | f << (type==12 ? "polypoly" : type==1024 ? "transparent[comment]" : |
1078 | 62 | type==1025 ? "hatch[comment]" : "gradient[comment]") << ","; |
1079 | 357 | *input >> nTmp; |
1080 | 560 | for (int poly=0; poly<int(nTmp) && !input->isEnd(); ++poly) { |
1081 | 424 | *input >> nTmp1; |
1082 | 424 | if (nTmp1<0 || nTmp1>(endDataPos-input->tell())/8) { |
1083 | 221 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: bad number of points\n")); |
1084 | 221 | f << "###poly[nPts=" << nTmp1 << "],"; |
1085 | 221 | break; |
1086 | 221 | } |
1087 | 203 | f << "poly" << poly << "=["; |
1088 | 460 | for (int pt=0; pt<int(nTmp1); ++pt) f << input->readLong(4) << "x" << input->readLong(4) << ","; |
1089 | 203 | f << "],"; |
1090 | 203 | } |
1091 | 357 | if (type==1024) { |
1092 | 18 | f << "nTrans=" << input->readULong(2) << ","; |
1093 | 18 | f << "nComment=" << input->readULong(4) << ","; |
1094 | 18 | } |
1095 | 357 | if (type==1025) { |
1096 | 8 | f << "style=" << input->readULong(2) << ","; |
1097 | 24 | for (unsigned char &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
1098 | 8 | f << "col=" << STOFFColor(col[0],col[1],col[2]) << ","; |
1099 | 8 | f << "distance=" << input->readLong(4) << ","; |
1100 | 8 | f << "nComment=" << input->readULong(4) << ","; |
1101 | 8 | } |
1102 | 357 | if (type==1030) { |
1103 | 36 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: reading gradient is not implemented\n")); |
1104 | 36 | f << "###gradient+following"; |
1105 | 36 | input->seek(endDataPos, librevenge::RVNG_SEEK_SET); |
1106 | 36 | } |
1107 | 357 | break; |
1108 | 214 | case 13: |
1109 | 304 | case 15: { |
1110 | 304 | f << (type==13 ? "text" : "stretch") << ","; |
1111 | 304 | f << "pos=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1112 | 304 | int32_t nIndex, nLen; |
1113 | 304 | *input>>nIndex>>nLen >> nTmp; |
1114 | 304 | if (nIndex) f << "index=" << nIndex << ","; |
1115 | 304 | if (nLen) f << "len=" << nLen << ","; |
1116 | 304 | if (type==15) f << "nWidth=" << input->readLong(4) << ","; |
1117 | 304 | if (nTmp<0 || input->tell()+nTmp>endDataPos) { |
1118 | 180 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: bad string\n")); |
1119 | 180 | f << "###string"; |
1120 | 180 | break; |
1121 | 180 | } |
1122 | 124 | text.clear(); |
1123 | 6.28k | for (int c=0; c<int(nTmp); ++c) text.push_back(static_cast<uint32_t>(input->readULong(1))); |
1124 | 124 | input->seek(1, librevenge::RVNG_SEEK_CUR); |
1125 | 124 | f << libstoff::getString(text).cstr() << ","; |
1126 | 124 | if (nUnicodeCommentActionNumber!=static_cast<uint32_t>(i)) break; |
1127 | 86 | uint16_t type1; |
1128 | 86 | uint32_t len; |
1129 | 86 | *input >> type1 >> len; |
1130 | 86 | if (long(len)<4 || input->tell()+long(len)>endDataPos) { |
1131 | 76 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: bad string\n")); |
1132 | 76 | f << "###unicode"; |
1133 | 76 | break; |
1134 | 76 | } |
1135 | 10 | if (type1==1032) { |
1136 | 0 | text.clear(); |
1137 | 0 | int nUnicode=int(len-4)/2; |
1138 | 0 | for (int c=0; c<nUnicode; ++c) text.push_back(static_cast<uint32_t>(input->readULong(2))); |
1139 | 0 | f << libstoff::getString(text).cstr() << ","; |
1140 | 0 | } |
1141 | 10 | else { |
1142 | 10 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: unknown data\n")); |
1143 | 10 | f << "###unknown"; |
1144 | 10 | input->seek(long(len)-4, librevenge::RVNG_SEEK_CUR); |
1145 | 10 | } |
1146 | 10 | break; |
1147 | 86 | } |
1148 | 323 | case 14: { |
1149 | 323 | f << "text[array],"; |
1150 | 323 | f << "pos=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1151 | 323 | int32_t nIndex, nLen, nAryLen; |
1152 | 323 | *input>>nIndex>>nLen >> nTmp >> nAryLen; |
1153 | 323 | if (nTmp<0 || nAryLen<0 || nAryLen>(endDataPos-input->tell()-nTmp)/4) { |
1154 | 192 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: bad string\n")); |
1155 | 192 | f << "###string"; |
1156 | 192 | break; |
1157 | 192 | } |
1158 | 131 | text.clear(); |
1159 | 2.54k | for (int c=0; c<int(nTmp); ++c) text.push_back(static_cast<uint32_t>(input->readULong(1))); |
1160 | 131 | input->seek(1, librevenge::RVNG_SEEK_CUR); |
1161 | 131 | f << libstoff::getString(text).cstr() << ","; |
1162 | 131 | f << "ary=["; |
1163 | 980 | for (int ary=0; ary<int(nAryLen); ++ary) f << input->readLong(4) << ","; |
1164 | 131 | f << "],"; |
1165 | 131 | if (nUnicodeCommentActionNumber!=static_cast<uint32_t>(i)) break; |
1166 | 86 | uint16_t type1; |
1167 | 86 | uint32_t len; |
1168 | 86 | *input >> type1 >> len; |
1169 | 86 | if (long(len)<4 || input->tell()+long(len)>endDataPos) { |
1170 | 76 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: bad string\n")); |
1171 | 76 | f << "###unicode"; |
1172 | 76 | break; |
1173 | 76 | } |
1174 | 10 | if (type1==1032) { |
1175 | 0 | text.clear(); |
1176 | 0 | int nUnicode=int(len-4)/2; |
1177 | 0 | for (int c=0; c<nUnicode; ++c) text.push_back(static_cast<uint32_t>(input->readULong(2))); |
1178 | 0 | f << libstoff::getString(text).cstr() << ","; |
1179 | 0 | } |
1180 | 10 | else { |
1181 | 10 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: unknown data\n")); |
1182 | 10 | f << "###unknown"; |
1183 | 10 | input->seek(long(len)-4, librevenge::RVNG_SEEK_CUR); |
1184 | 10 | } |
1185 | | |
1186 | 10 | break; |
1187 | 86 | } |
1188 | 40 | case 16: |
1189 | 40 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: reading icon is not implemented\n")); |
1190 | 40 | f << "###icon"; |
1191 | 40 | break; |
1192 | 2.40k | case 17: |
1193 | 2.48k | case 18: |
1194 | 2.61k | case 32: { |
1195 | 2.61k | f << (type==17 ? "bitmap" : type==18 ? "bitmap[scale]" : "bitmap[scale2]"); |
1196 | 2.61k | f << "pos=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1197 | 2.61k | if (type>=17) f << "scale=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1198 | 2.61k | if (type==32) { |
1199 | 131 | f << "pos2=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1200 | 131 | f << "scale2=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1201 | 131 | } |
1202 | 2.61k | StarBitmap bitmap; |
1203 | 2.61k | librevenge::RVNGBinaryData data; |
1204 | 2.61k | std::string dataType; |
1205 | 2.61k | if (!bitmap.readBitmap(zone, false, endDataPos, data, dataType)) |
1206 | 1.73k | f << "###bitmap,"; |
1207 | 2.61k | break; |
1208 | 2.48k | } |
1209 | 282 | case 19: |
1210 | 282 | f << "pen,"; |
1211 | 846 | for (unsigned char &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
1212 | 282 | color=STOFFColor(col[0],col[1],col[2]); |
1213 | 282 | if (!color.isBlack()) f << "col=" << color << ","; |
1214 | 282 | f << "penWidth=" << input->readULong(4) << ","; |
1215 | 282 | f << "penStyle=" << input->readULong(2) << ","; |
1216 | 282 | break; |
1217 | 193 | case 20: { |
1218 | 193 | f << "font,"; |
1219 | 579 | for (int c=0; c<2; ++c) { |
1220 | 1.15k | for (unsigned char &j : col) j=static_cast<unsigned char>(input->readULong(2)>>8); |
1221 | 386 | color=STOFFColor(col[0],col[1],col[2]); |
1222 | 386 | if ((c==1&&!color.isWhite()) || (c==0&&!color.isBlack())) |
1223 | 224 | f << (c==0 ? "col" : "col[fill]") << "=" << color << ","; |
1224 | 386 | } |
1225 | 193 | long actPos=input->tell(); |
1226 | 193 | if (actPos+62>endDataPos) { |
1227 | 20 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: the zone seems too short\n")); |
1228 | 20 | f << "###short"; |
1229 | 20 | break; |
1230 | 20 | } |
1231 | 173 | std::string name(""); |
1232 | 3.57k | for (int c=0; c<32; ++c) { |
1233 | 3.56k | auto ch=char(input->readULong(1)); |
1234 | 3.56k | if (!ch) break; |
1235 | 3.40k | name+=ch; |
1236 | 3.40k | } |
1237 | 173 | f << name << ","; |
1238 | 173 | input->seek(actPos+32, librevenge::RVNG_SEEK_SET); |
1239 | 173 | f << "size=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1240 | 173 | int16_t nCharSet, nFamily, nPitch, nAlign, nWeight, nUnderline, nStrikeout, nCharOrient, nLineOrient; |
1241 | 173 | bool bItalic, bOutline, bShadow, bTransparent; |
1242 | 173 | *input >> nCharSet >> nFamily >> nPitch >> nAlign >> nWeight >> nUnderline >> nStrikeout >> nCharOrient >> nLineOrient; |
1243 | 173 | if (nCharSet) f << "char[set]=" << nCharSet << ","; |
1244 | 173 | if (nFamily) f << "family=" << nFamily << ","; |
1245 | 173 | if (nPitch) f << "pitch=" << nPitch << ","; |
1246 | 173 | if (nAlign) f << "align=" << nAlign << ","; |
1247 | 173 | if (nWeight) f << "weight=" << nWeight << ","; |
1248 | 173 | if (nUnderline) f << "underline=" << nUnderline << ","; |
1249 | 173 | if (nStrikeout) f << "strikeout=" << nStrikeout << ","; |
1250 | 173 | if (nCharOrient) f << "charOrient=" << nCharOrient << ","; |
1251 | 173 | if (nLineOrient) f << "lineOrient=" << nLineOrient << ","; |
1252 | 173 | *input >> bItalic >> bOutline >> bShadow >> bTransparent; |
1253 | 173 | if (bItalic) f << "italic,"; |
1254 | 173 | if (bOutline) f << "outline,"; |
1255 | 173 | if (bShadow) f << "shadow,"; |
1256 | 173 | if (bTransparent) f << "transparent,"; |
1257 | 173 | break; |
1258 | 193 | } |
1259 | 27 | case 21: // unsure |
1260 | 93 | case 22: |
1261 | 93 | f << (type==21 ? "brush[back]" : "brush[fill]") << ","; |
1262 | 279 | for (unsigned char &j : col) j=static_cast<unsigned char>(input->readULong(2)>>8); |
1263 | 93 | f << STOFFColor(col[0],col[1],col[2]) << ","; |
1264 | 93 | input->seek(6, librevenge::RVNG_SEEK_CUR); // unknown |
1265 | 93 | f << "style=" << input->readLong(2) << ","; |
1266 | 93 | input->seek(2, librevenge::RVNG_SEEK_CUR); // unknown |
1267 | 93 | break; |
1268 | 24 | case 23: |
1269 | 24 | f << "map[mode],"; |
1270 | 24 | *input >> unit >> orgX >> orgY >> nXNum >> nXDenom >> nYNum >> nYDenom; |
1271 | 24 | if (unit) f << "unit=" << unit << ","; |
1272 | 24 | f << "orig=" << orgX << "x" << orgY << ","; |
1273 | 24 | f << "x=" << nXNum << "/" << nXDenom << ","; |
1274 | 24 | f << "y=" << nYNum << "/" << nYDenom << ","; |
1275 | 24 | break; |
1276 | 289 | case 24: { |
1277 | 289 | f << "clip[region],"; |
1278 | 289 | int16_t clipType, bIntersect; |
1279 | 289 | *input >> clipType >> bIntersect; |
1280 | 289 | f << "rect=" << input->readLong(4) << "x" << input->readLong(4) << "<->" |
1281 | 289 | << input->readLong(4) << "x" << input->readLong(4) << ","; |
1282 | 289 | if (bIntersect) f << "intersect,"; |
1283 | 289 | switch (clipType) { |
1284 | 1 | case 0: |
1285 | 1 | break; |
1286 | 11 | case 1: |
1287 | 11 | f << "rect2=" << input->readLong(4) << "x" << input->readLong(4) << "<->" |
1288 | 11 | << input->readLong(4) << "x" << input->readLong(4) << ","; |
1289 | 11 | break; |
1290 | 110 | case 2: |
1291 | 110 | *input >> nTmp; |
1292 | 110 | if (nTmp<0 || nTmp>(endDataPos-input->tell())/8) { |
1293 | 96 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: bad number of points\n")); |
1294 | 96 | f << "###nPts=" << nTmp << ","; |
1295 | 96 | break; |
1296 | 96 | } |
1297 | 14 | f << "poly=["; |
1298 | 17 | for (int pt=0; pt<int(nTmp); ++pt) f << input->readLong(4) << "x" << input->readLong(4) << ","; |
1299 | 14 | f << "],"; |
1300 | 14 | break; |
1301 | 147 | case 3: |
1302 | 147 | *input >> nTmp; |
1303 | 253 | for (int poly=0; poly<int(nTmp) && !input->isEnd(); ++poly) { |
1304 | 212 | *input >> nTmp1; |
1305 | 212 | if (nTmp1<0 || nTmp1>(endDataPos-input->tell())/8) { |
1306 | 106 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: bad number of points\n")); |
1307 | 106 | f << "###poly[nPts=" << nTmp1 << "],"; |
1308 | 106 | break; |
1309 | 106 | } |
1310 | 106 | f << "poly" << poly << "=["; |
1311 | 238 | for (int pt=0; pt<int(nTmp1); ++pt) f << input->readLong(4) << "x" << input->readLong(4) << ","; |
1312 | 106 | f << "],"; |
1313 | 106 | } |
1314 | 147 | break; |
1315 | 20 | default: |
1316 | 20 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: find unknown clip type\n")); |
1317 | 20 | f << "###type=" << clipType << ","; |
1318 | 20 | break; |
1319 | 289 | } |
1320 | 289 | break; |
1321 | 289 | } |
1322 | 289 | case 25: |
1323 | 74 | f << "raster=" << input->readULong(2) << ","; // 1 invert, 4,5: xor other paint |
1324 | 74 | break; |
1325 | 184 | case 26: |
1326 | 184 | f << "push,"; |
1327 | 184 | break; |
1328 | 69 | case 27: |
1329 | 69 | f << "pop,"; |
1330 | 69 | break; |
1331 | 58 | case 28: |
1332 | 58 | f << "clip[move]=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1333 | 58 | break; |
1334 | 204 | case 29: |
1335 | 204 | f << "clip[rect]=" << input->readLong(4) << "x" << input->readLong(4) << "<->" |
1336 | 204 | << input->readLong(4) << "x" << input->readLong(4) << ","; |
1337 | 204 | break; |
1338 | 56 | case 30: // checkme |
1339 | 87 | case 1029: { |
1340 | 87 | f << (type==30 ? "mtf" : "floatComment") << ",";; |
1341 | | // gdimtf.cxx operator>>(... GDIMetaFile ) |
1342 | 87 | std::string name(""); |
1343 | 609 | for (int c=0; c<6; ++c) name+=char(input->readULong(1)); |
1344 | 87 | if (name!="VCLMTF") { |
1345 | 57 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: find unexpected header\n")); |
1346 | 57 | f << "###name=" << name << ","; |
1347 | 57 | break; |
1348 | 57 | } |
1349 | 30 | if (!zone.openVersionCompatHeader()) { |
1350 | 22 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: can not open compat header\n")); |
1351 | 22 | f << "###compat,"; |
1352 | 22 | break; |
1353 | 22 | } |
1354 | 8 | f << "compress=" << input->readULong(4) << ","; |
1355 | | // map mode |
1356 | 8 | *input >> unit >> orgX >> orgY >> nXNum >> nXDenom >> nYNum >> nYDenom; |
1357 | 8 | f << "map=["; |
1358 | 8 | if (unit) f << "unit=" << unit << ","; |
1359 | 8 | f << "orig=" << orgX << "x" << orgY << ","; |
1360 | 8 | f << "x=" << nXNum << "/" << nXDenom << ","; |
1361 | 8 | f << "y=" << nYNum << "/" << nYDenom << ","; |
1362 | 8 | f << "],"; |
1363 | 8 | f << "size=" << input->readULong(4) << ","; |
1364 | 8 | uint32_t nCount; |
1365 | 8 | *input >> nCount; |
1366 | 8 | if (nCount) f << "nCount=" << nCount << ","; |
1367 | 8 | if (input->tell()!=zone.getRecordLastPosition()) { |
1368 | | // for (int act=0; act<nCount; ++act) MetaAction::ReadMetaAction(); |
1369 | 7 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: reading mtf action zones is not implemented\n")); |
1370 | 7 | ascFile.addPos(input->tell()); |
1371 | 7 | ascFile.addNote("ImageSVGDI:###listMeta"); |
1372 | 7 | input->seek(zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET); |
1373 | 7 | } |
1374 | 8 | zone.closeVersionCompatHeader("ImageSVGDI"); |
1375 | 8 | if (type!=30) { |
1376 | 4 | f << "orig=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1377 | 4 | f << "sz=" << input->readULong(4) << ","; |
1378 | 4 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: reading gradient is not implemented\n")); |
1379 | 4 | f << "###gradient+following"; |
1380 | 4 | input->seek(endDataPos, librevenge::RVNG_SEEK_SET); |
1381 | 4 | } |
1382 | 8 | break; |
1383 | 30 | } |
1384 | 24 | case 33: { |
1385 | 24 | f << "gradient,"; |
1386 | 24 | f << "rect=" << input->readLong(4) << "x" << input->readLong(4) << "<->" |
1387 | 24 | << input->readLong(4) << "x" << input->readLong(4) << ","; |
1388 | 24 | f << "style=" << input->readULong(2) << ","; |
1389 | 72 | for (int c=0; c<2; ++c) { |
1390 | 144 | for (unsigned char &j : col) j=static_cast<unsigned char>(input->readULong(2)>>8); |
1391 | 48 | color=STOFFColor(col[0],col[1],col[2]); |
1392 | 48 | f << "col" << c << "=" << color << ","; |
1393 | 48 | } |
1394 | 24 | f << "angle=" << input->readLong(2) << ","; |
1395 | 24 | f << "border=" << input->readLong(2) << ","; |
1396 | 24 | f << "offs=" << input->readLong(2) << "x" << input->readLong(2) << ","; |
1397 | 24 | f << "intensity=" << input->readLong(2) << "<->" << input->readLong(2) << ","; |
1398 | 24 | break; |
1399 | 30 | } |
1400 | 11 | case 1026: |
1401 | 11 | f << "refpoint[comment],"; |
1402 | 11 | f << "pt=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1403 | 11 | f << "set=" << input->readULong(1) << ","; |
1404 | 11 | f << "nComments=" << input->readULong(4) << ","; |
1405 | 11 | break; |
1406 | 23 | case 1027: |
1407 | 23 | f << "textline[color,comment],"; |
1408 | 69 | for (unsigned char &j : col) j=static_cast<unsigned char>(input->readULong(2)>>8); |
1409 | 23 | f << "col=" << STOFFColor(col[0],col[1],col[2]) << ","; |
1410 | 23 | f << "set=" << input->readULong(1) << ","; |
1411 | 23 | f << "nComments=" << input->readULong(4) << ","; |
1412 | 23 | break; |
1413 | 11 | case 1028: |
1414 | 11 | f << "textline[comment],"; |
1415 | 11 | f << "pt=" << input->readLong(4) << "x" << input->readLong(4) << ","; |
1416 | 11 | f << "width=" << input->readLong(4) << ","; |
1417 | 11 | f << "strikeOut=" << input->readULong(4) << ","; |
1418 | 11 | f << "underline=" << input->readULong(4) << ","; |
1419 | 11 | f << "nComments=" << input->readULong(4) << ","; |
1420 | 11 | break; |
1421 | 111 | case 1031: { |
1422 | 111 | f << "comment[comment],"; |
1423 | 111 | if (!zone.readString(text)) { |
1424 | 4 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: can not read the text\n")); |
1425 | 4 | f << "###text,"; |
1426 | 4 | break; |
1427 | 4 | } |
1428 | 107 | f << libstoff::getString(text).cstr() << ","; |
1429 | 107 | f << "value=" << input->readULong(4) << ","; |
1430 | 107 | long size=input->readLong(4); |
1431 | 107 | if (size<0 || input->tell()+size+4>endDataPos) { |
1432 | 99 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: size seems bad\n")); |
1433 | 99 | f << "###size=" << size << ","; |
1434 | 99 | break; |
1435 | 99 | } |
1436 | 8 | if (size) { |
1437 | 4 | f << "###unknown,"; |
1438 | 4 | ascFile.addDelimiter(input->tell(),'|'); |
1439 | 4 | input->seek(size, librevenge::RVNG_SEEK_CUR); |
1440 | 4 | } |
1441 | 8 | f << "nComments=" << input->readULong(4) << ","; |
1442 | 8 | break; |
1443 | 107 | } |
1444 | 20 | case 1032: |
1445 | 20 | f << "unicode[next],"; |
1446 | 20 | nUnicodeCommentActionNumber=uint32_t(i)+1; |
1447 | 20 | break; |
1448 | 437 | default: |
1449 | 437 | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: find unimplement type\n")); |
1450 | 437 | f << "###type=" << type << ","; |
1451 | 437 | input->seek(endDataPos, librevenge::RVNG_SEEK_SET); |
1452 | 437 | break; |
1453 | 6.26k | } |
1454 | 6.26k | if (input->tell()!=endDataPos) { |
1455 | 4.57k | STOFF_DEBUG_MSG(("StarFileManager::readSVGDI: find extra data\n")); |
1456 | 4.57k | f << "###extra,"; |
1457 | 4.57k | ascFile.addDelimiter(input->tell(),'|'); |
1458 | 4.57k | } |
1459 | 6.26k | ascFile.addPos(pos); |
1460 | 6.26k | ascFile.addNote(f.str().c_str()); |
1461 | 6.26k | input->seek(endDataPos, librevenge::RVNG_SEEK_SET); |
1462 | 6.26k | } |
1463 | | |
1464 | 3.41k | return true; |
1465 | 3.41k | } |
1466 | | |
1467 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |