/src/libwps/src/lib/QuattroGraph.cpp
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ |
2 | | /* libwps |
3 | | * Version: MPL 2.0 / LGPLv2.1+ |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * Major Contributor(s): |
10 | | * Copyright (C) 2006, 2007 Andrew Ziem |
11 | | * Copyright (C) 2004 Marc Maurer (uwog@uwog.net) |
12 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
13 | | * |
14 | | * For minor contributions see the git repository. |
15 | | * |
16 | | * Alternatively, the contents of this file may be used under the terms |
17 | | * of the GNU Lesser General Public License Version 2.1 or later |
18 | | * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are |
19 | | * applicable instead of those above. |
20 | | */ |
21 | | |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | |
25 | | #include <cmath> |
26 | | #include <sstream> |
27 | | #include <limits> |
28 | | #include <map> |
29 | | #include <stack> |
30 | | |
31 | | #include <librevenge-stream/librevenge-stream.h> |
32 | | |
33 | | #include "libwps_internal.h" |
34 | | #include "libwps_tools_win.h" |
35 | | |
36 | | #include "WKSContentListener.h" |
37 | | #include "WKSSubDocument.h" |
38 | | |
39 | | #include "WPSEntry.h" |
40 | | #include "WPSFont.h" |
41 | | #include "WPSGraphicShape.h" |
42 | | #include "WPSGraphicStyle.h" |
43 | | #include "WPSOLEObject.h" |
44 | | #include "WPSParagraph.h" |
45 | | #include "WPSPosition.h" |
46 | | #include "WPSStream.h" |
47 | | |
48 | | #include "Quattro.h" |
49 | | |
50 | | #include "QuattroGraph.h" |
51 | | |
52 | | namespace QuattroGraphInternal |
53 | | { |
54 | | //! a dialog header |
55 | | struct Dialog |
56 | | { |
57 | | //! constructor |
58 | | explicit Dialog() |
59 | 12.7k | : m_cellBox() |
60 | 12.7k | { |
61 | 63.6k | for (auto &f : m_flags1) f=0; |
62 | 114k | for (auto &f : m_flags2) f=0; |
63 | 12.7k | } |
64 | | //! operator<< |
65 | | friend std::ostream &operator<<(std::ostream &o, Dialog const &gr); |
66 | | //! the cell's position |
67 | | WPSBox2i m_cellBox; |
68 | | //! some flags |
69 | | int m_flags1[5]; |
70 | | //! final flag |
71 | | int m_flags2[9]; |
72 | | }; |
73 | | |
74 | | std::ostream &operator<<(std::ostream &o, Dialog const &dlg) |
75 | 0 | { |
76 | 0 | if (dlg.m_cellBox!=WPSBox2i()) o << "cellBox=" << dlg.m_cellBox << ","; |
77 | 0 | o << "fl1=["; |
78 | 0 | for (auto f : dlg.m_flags1) |
79 | 0 | { |
80 | 0 | if (f) |
81 | 0 | o << std::hex << f << std::dec << ","; |
82 | 0 | else |
83 | 0 | o << "_,"; |
84 | 0 | } |
85 | 0 | o << "],"; |
86 | 0 | o << "fl2=["; |
87 | 0 | for (auto f : dlg.m_flags2) |
88 | 0 | { |
89 | 0 | if (f) |
90 | 0 | o << std::hex << f << std::dec << ","; |
91 | 0 | else |
92 | 0 | o << "_,"; |
93 | 0 | } |
94 | 0 | o << "],"; |
95 | 0 | return o; |
96 | 0 | } |
97 | | |
98 | | //! a shape header of a QuattroGraph |
99 | | struct ShapeHeader |
100 | | { |
101 | | //! constructor |
102 | | ShapeHeader() |
103 | 204k | : m_type(0) |
104 | 204k | , m_box() |
105 | 204k | , m_id(0) |
106 | 204k | , m_style() |
107 | 204k | , m_extra() |
108 | 204k | { |
109 | 2.86M | for (auto &f : m_flags) f=0; |
110 | 1.02M | for (auto &v : m_values) v=0; |
111 | 819k | for (auto &v : m_values2) v=0; |
112 | 204k | } |
113 | | //! destructor |
114 | | virtual ~ShapeHeader(); |
115 | | //! returns true if the shape is a textbox |
116 | | virtual bool isTextbox() const |
117 | 94.6k | { |
118 | 94.6k | return false; |
119 | 94.6k | } |
120 | | //! operator<< |
121 | | friend std::ostream &operator<<(std::ostream &o, ShapeHeader const &sh); |
122 | | //! the type |
123 | | int m_type; |
124 | | //! the bdbox |
125 | | WPSBox2i m_box; |
126 | | //! an id? |
127 | | int m_id; |
128 | | //! the graphic style |
129 | | WPSGraphicStyle m_style; |
130 | | //! optional values |
131 | | int m_values[5]; |
132 | | //! some flags |
133 | | int m_flags[14]; |
134 | | |
135 | | // |
136 | | // style |
137 | | // |
138 | | |
139 | | //! style values |
140 | | int m_values2[4]; |
141 | | //! error message |
142 | | std::string m_extra; |
143 | | }; |
144 | | |
145 | | ShapeHeader::~ShapeHeader() |
146 | 204k | { |
147 | 204k | } |
148 | | |
149 | | std::ostream &operator<<(std::ostream &o, ShapeHeader const &sh) |
150 | 0 | { |
151 | 0 | o << "type=" << sh.m_type << ","; |
152 | 0 | o << "box=" << sh.m_box << ","; |
153 | 0 | if (sh.m_id) o << "id=" << sh.m_id << ","; |
154 | 0 | o << sh.m_style << ","; |
155 | 0 | int wh=0; |
156 | 0 | for (auto v : sh.m_values) |
157 | 0 | { |
158 | 0 | if (v) o << "f" << wh << "=" << v << ","; |
159 | 0 | ++wh; |
160 | 0 | } |
161 | 0 | o << "unkn["; |
162 | 0 | for (auto f : sh.m_flags) |
163 | 0 | { |
164 | 0 | if (f) |
165 | 0 | o << std::hex << f << std::dec << ","; |
166 | 0 | else |
167 | 0 | o << ","; |
168 | 0 | } |
169 | 0 | o << "],"; |
170 | 0 | wh=0; |
171 | 0 | for (auto v : sh.m_values2) |
172 | 0 | { |
173 | 0 | if (v) o << "g" << wh << "=" << v << ","; |
174 | 0 | ++wh; |
175 | 0 | } |
176 | 0 | o << sh.m_extra << ","; |
177 | 0 | return o; |
178 | 0 | } |
179 | | |
180 | | //! Internal: a shape of a QuattroGraph |
181 | | struct Shape final : public ShapeHeader |
182 | | { |
183 | | //! constructor |
184 | | Shape() |
185 | 186k | : ShapeHeader() |
186 | 186k | , m_shape() |
187 | 186k | { |
188 | 186k | } |
189 | | //! destructor |
190 | | ~Shape() final; |
191 | | //! the graphic shape |
192 | | WPSGraphicShape m_shape; |
193 | | }; |
194 | | |
195 | | Shape::~Shape() |
196 | 186k | { |
197 | 186k | } |
198 | | |
199 | | //! Internal: a shape of a QuattroGraph |
200 | | struct Textbox final : public ShapeHeader |
201 | | { |
202 | | //! constructor |
203 | | Textbox() |
204 | 18.1k | : ShapeHeader() |
205 | 18.1k | , m_entry() |
206 | 18.1k | , m_font() |
207 | 18.1k | , m_paragraph() |
208 | 18.1k | { |
209 | 18.1k | } |
210 | | //! destructor |
211 | | ~Textbox() final; |
212 | | //! returns true |
213 | | bool isTextbox() const final |
214 | 15.0k | { |
215 | 15.0k | return true; |
216 | 15.0k | } |
217 | | //! the text entry |
218 | | WPSEntry m_entry; |
219 | | //! the font |
220 | | WPSFont m_font; |
221 | | //! the paragraph style |
222 | | WPSParagraph m_paragraph; |
223 | | }; |
224 | | |
225 | | Textbox::~Textbox() |
226 | 18.1k | { |
227 | 18.1k | } |
228 | | |
229 | | //! Internal: a graph of a QuattroGraph |
230 | | struct Graph |
231 | | { |
232 | | //! the posible type |
233 | | enum Type { Button, Chart, Frame, OLE/* or bitmap */, Image, Shape, Textbox, Unknown }; |
234 | | //! constructor |
235 | | explicit Graph(std::shared_ptr<WPSStream> const &stream, Type type=Unknown) |
236 | 184k | : m_type(type) |
237 | 184k | , m_size() |
238 | 184k | , m_cellBox() |
239 | 184k | , m_cellBoxDecal() |
240 | 184k | , m_label() |
241 | 184k | , m_ole() |
242 | 184k | , m_linkName() |
243 | 184k | , m_shape() |
244 | 184k | , m_textbox() |
245 | 184k | , m_stream(stream) |
246 | 184k | { |
247 | 739k | for (auto &f : m_flags1) f=0; |
248 | 1.29M | for (auto &f : m_flags2) f=0; |
249 | 924k | for (auto &v : m_values) v=0; |
250 | 184k | } |
251 | | //! operator<< |
252 | | friend std::ostream &operator<<(std::ostream &o, Graph const &gr); |
253 | | //! the type |
254 | | Type m_type; |
255 | | //! the size |
256 | | Vec2f m_size; |
257 | | //! the cell's position |
258 | | WPSBox2i m_cellBox; |
259 | | //! the decal position(LT, RB) |
260 | | WPSBox2f m_cellBoxDecal; |
261 | | //! some flags |
262 | | int m_flags1[4]; |
263 | | //! final flag |
264 | | int m_flags2[7]; |
265 | | //! some values |
266 | | int m_values[5]; |
267 | | |
268 | | //! the label(button) |
269 | | librevenge::RVNGString m_label; |
270 | | |
271 | | //! the OLE's data |
272 | | WPSEmbeddedObject m_ole; |
273 | | //! the OLE's link name |
274 | | librevenge::RVNGString m_linkName; |
275 | | |
276 | | //! the graphic shape |
277 | | std::shared_ptr<QuattroGraphInternal::Shape> m_shape; |
278 | | //! the textbox |
279 | | std::shared_ptr<QuattroGraphInternal::Textbox> m_textbox; |
280 | | |
281 | | //! the main stream |
282 | | std::shared_ptr<WPSStream> m_stream; |
283 | | }; |
284 | | |
285 | | std::ostream &operator<<(std::ostream &o, Graph const &gr) |
286 | 0 | { |
287 | 0 | if (gr.m_size!=Vec2f()) o << "size=" << gr.m_size << ","; |
288 | 0 | if (gr.m_cellBox!=WPSBox2i()) o << "cellBox=" << gr.m_cellBox << ","; |
289 | 0 | if (gr.m_cellBoxDecal!=WPSBox2f()) o << "cellBox[decal]=" << gr.m_cellBoxDecal << ","; |
290 | 0 | o << "fl1=["; |
291 | 0 | for (auto f : gr.m_flags1) |
292 | 0 | { |
293 | 0 | if (f) |
294 | 0 | o << std::hex << f << std::dec << ","; |
295 | 0 | else |
296 | 0 | o << "_,"; |
297 | 0 | } |
298 | 0 | o << "],"; |
299 | 0 | o << "fl2=["; |
300 | 0 | for (auto f : gr.m_flags2) |
301 | 0 | { |
302 | 0 | if (f) |
303 | 0 | o << std::hex << f << std::dec << ","; |
304 | 0 | else |
305 | 0 | o << "_,"; |
306 | 0 | } |
307 | 0 | o << "],"; |
308 | 0 | for (int i=0; i<5; ++i) |
309 | 0 | { |
310 | 0 | if (gr.m_values[i]) |
311 | 0 | o << "f" << i << "=" << gr.m_values[i] << ","; |
312 | 0 | } |
313 | 0 | return o; |
314 | 0 | } |
315 | | |
316 | | //! the state of QuattroGraph |
317 | | struct State |
318 | | { |
319 | | //! constructor |
320 | | State() |
321 | 47.8k | : m_version(-1) |
322 | 47.8k | , m_actualSheet(-1) |
323 | 47.8k | , m_sheetIdToGraphMap() |
324 | 47.8k | , m_actualGraph() |
325 | 47.8k | , m_linkNameToObjectMap() |
326 | 47.8k | { |
327 | 47.8k | } |
328 | | //! store a graph |
329 | | void storeGraph(std::shared_ptr<Graph> graph) |
330 | 75.6k | { |
331 | 75.6k | if (!graph) |
332 | 0 | { |
333 | 0 | WPS_DEBUG_MSG(("QuattroGraphInternal::storeGraph: no graph\n")); |
334 | 0 | return; |
335 | 0 | } |
336 | 75.6k | m_actualGraph=graph; |
337 | 75.6k | if (m_actualSheet<0) |
338 | 22.7k | { |
339 | 22.7k | WPS_DEBUG_MSG(("QuattroGraphInternal::storeGraph: can not find the current sheet\n")); |
340 | 22.7k | return; |
341 | 22.7k | } |
342 | 52.8k | m_sheetIdToGraphMap.insert(std::multimap<int, std::shared_ptr<Graph> >::value_type(m_actualSheet, graph)); |
343 | 52.8k | } |
344 | | //! returns the pattern corresponding to a pattern id between 0 and 24 |
345 | | static bool getPattern(int id, WPSGraphicStyle::Pattern &pattern); |
346 | | //! the file version |
347 | | int m_version; |
348 | | //! the actual sheet id |
349 | | int m_actualSheet; |
350 | | //! a multimap sheetId to graph |
351 | | std::multimap<int, std::shared_ptr<Graph> > m_sheetIdToGraphMap; |
352 | | //! the actual graph |
353 | | std::shared_ptr<Graph> m_actualGraph; |
354 | | //! a map link name to object |
355 | | std::map<librevenge::RVNGString,WPSEmbeddedObject> m_linkNameToObjectMap; |
356 | | }; |
357 | | |
358 | | bool State::getPattern(int id, WPSGraphicStyle::Pattern &pat) |
359 | 19.2k | { |
360 | 19.2k | if (id<0 || id>24) |
361 | 16.1k | { |
362 | 16.1k | WPS_DEBUG_MSG(("QuattroInternal::State::getPattern(): unknown pattern id: %d\n",id)); |
363 | 16.1k | return false; |
364 | 16.1k | } |
365 | 3.08k | static const uint16_t patterns[]= |
366 | 3.08k | { |
367 | 3.08k | 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0x0000, 0x00ff, 0x0000, 0x0101, 0x0101, 0x0101, 0x0101, // 0-3 |
368 | 3.08k | 0x8844, 0x2211, 0x8844, 0x2211, 0x8811, 0x2244, 0x8811, 0x2244, 0xff01, 0x0101, 0x0101, 0x0101, 0x040a, 0x11a0, 0x40a0, 0x110a, // 4-7 |
369 | 3.08k | 0x44aa, 0x1100, 0x44aa, 0x1100, 0xffff, 0x0000, 0xffff, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, 0x060c, 0x1830, 0x60c0, 0x8103, // 8-9 |
370 | 3.08k | 0xc060, 0x3018, 0x0c06, 0x0381, 0xc864, 0x3219, 0x8c46, 0x2391, 0xff11, 0xff11, 0xff11, 0xff11, 0xcccc, 0x3333, 0xcccc, 0x3333, |
371 | 3.08k | 0xcc33, 0xcc33, 0xcc33, 0xcc33, 0x0110, 0x0110, 0x0110, 0x0110, 0x1144, 0x1144, 0x1144, 0x1144, 0x070e, 0x9ee9, 0xe070, 0xb99b, |
372 | 3.08k | 0x0101, 0x01ff, 0x1010, 0x10ff, 0x4080, 0x0103, 0x8448, 0x3020, 0x2011, 0x0204, 0x0811, 0x8040, 0x00aa, 0x00aa, 0x00aa, 0x00aa, |
373 | 3.08k | 0xaa55, 0xaa55, 0xaa55, 0xaa55 |
374 | 3.08k | }; |
375 | 3.08k | pat.m_dim=Vec2i(8,8); |
376 | 3.08k | uint16_t const *ptr=&patterns[4*id]; |
377 | 3.08k | pat.m_data.resize(8); |
378 | 15.4k | for (size_t i=0; i < 8; i+=2) |
379 | 12.3k | { |
380 | 12.3k | uint16_t val=*(ptr++); |
381 | 12.3k | pat.m_data[i]=static_cast<unsigned char>((val>>8) & 0xFF); |
382 | 12.3k | pat.m_data[i+1]=static_cast<unsigned char>(val & 0xFF); |
383 | 12.3k | } |
384 | 3.08k | return true; |
385 | 19.2k | } |
386 | | |
387 | | //! Internal: the subdocument of a QuattroGraphInternal |
388 | | class SubDocument final : public WKSSubDocument |
389 | | { |
390 | | public: |
391 | | //! constructor for a textbox document |
392 | | SubDocument(QuattroGraph &graphParser, std::shared_ptr<Textbox> const &textbox, std::shared_ptr<WPSStream> const &stream) |
393 | 415 | : WKSSubDocument(RVNGInputStreamPtr(), &graphParser.m_mainParser) |
394 | 415 | , m_graphParser(graphParser) |
395 | 415 | , m_textbox(textbox) |
396 | 415 | , m_stream(stream) |
397 | 415 | , m_text() {} |
398 | | //! constructor for a text entry |
399 | | SubDocument(QuattroGraph &graphParser, librevenge::RVNGString const &text) |
400 | 877 | : WKSSubDocument(RVNGInputStreamPtr(), &graphParser.m_mainParser) |
401 | 877 | , m_graphParser(graphParser) |
402 | 877 | , m_textbox() |
403 | 877 | , m_stream() |
404 | 877 | , m_text(text) {} |
405 | | //! destructor |
406 | 1.29k | ~SubDocument() final {} |
407 | | |
408 | | //! operator== |
409 | | bool operator==(std::shared_ptr<WPSSubDocument> const &doc) const final |
410 | 0 | { |
411 | 0 | if (!doc || !WKSSubDocument::operator==(doc)) |
412 | 0 | return false; |
413 | 0 | auto const *sDoc = dynamic_cast<SubDocument const *>(doc.get()); |
414 | 0 | if (!sDoc) return false; |
415 | 0 | if (&m_graphParser != &sDoc->m_graphParser) return false; |
416 | 0 | if (m_textbox.get() != sDoc->m_textbox.get()) return false; |
417 | 0 | if (m_stream.get() != sDoc->m_stream.get()) return false; |
418 | 0 | return m_text == sDoc->m_text; |
419 | 0 | } |
420 | | |
421 | | //! the parser function |
422 | | void parse(std::shared_ptr<WKSContentListener> &listener, libwps::SubDocumentType subDocumentType) final; |
423 | | //! the graph parser |
424 | | QuattroGraph &m_graphParser; |
425 | | //! the textbox data |
426 | | std::shared_ptr<Textbox> m_textbox; |
427 | | //! the file stream |
428 | | std::shared_ptr<WPSStream> m_stream; |
429 | | //! the main text |
430 | | librevenge::RVNGString m_text; |
431 | | }; |
432 | | |
433 | | void SubDocument::parse(std::shared_ptr<WKSContentListener> &listener, libwps::SubDocumentType) |
434 | 1.29k | { |
435 | 1.29k | if (!listener.get()) |
436 | 0 | { |
437 | 0 | WPS_DEBUG_MSG(("QuattroGraphInternal::SubDocument::parse: no listener\n")); |
438 | 0 | return; |
439 | 0 | } |
440 | 1.29k | if (!dynamic_cast<WKSContentListener *>(listener.get())) |
441 | 0 | { |
442 | 0 | WPS_DEBUG_MSG(("QuattroGraphInternal::SubDocument::parse: bad listener\n")); |
443 | 0 | return; |
444 | 0 | } |
445 | 1.29k | if (m_textbox && m_stream) |
446 | 415 | { |
447 | 415 | auto input=m_stream->m_input; |
448 | 415 | long actPos=input->tell(); |
449 | 415 | m_graphParser.send(*m_textbox, m_stream); |
450 | 415 | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
451 | 415 | return; |
452 | 415 | } |
453 | 877 | WPSParagraph para; |
454 | 877 | para.m_justify=libwps::JustificationCenter; |
455 | 877 | listener->setParagraph(para); |
456 | 877 | if (!m_text.empty()) |
457 | 877 | listener->insertUnicodeString(m_text); |
458 | 877 | } |
459 | | |
460 | | } |
461 | | |
462 | | // constructor, destructor |
463 | | QuattroGraph::QuattroGraph(QuattroParser &parser) |
464 | 23.9k | : m_listener() |
465 | 23.9k | , m_mainParser(parser) |
466 | 23.9k | , m_state(new QuattroGraphInternal::State()) |
467 | 23.9k | { |
468 | 23.9k | } |
469 | | |
470 | | QuattroGraph::~QuattroGraph() |
471 | 23.9k | { |
472 | 23.9k | } |
473 | | |
474 | | void QuattroGraph::cleanState() |
475 | 23.9k | { |
476 | 23.9k | m_state.reset(new QuattroGraphInternal::State()); |
477 | 23.9k | } |
478 | | |
479 | | void QuattroGraph::updateState() |
480 | 23.8k | { |
481 | 23.8k | } |
482 | | |
483 | | int QuattroGraph::version() const |
484 | 146k | { |
485 | 146k | if (m_state->m_version<0) |
486 | 2.47k | m_state->m_version=m_mainParser.version(); |
487 | 146k | return m_state->m_version; |
488 | 146k | } |
489 | | |
490 | | void QuattroGraph::storeObjects(std::map<librevenge::RVNGString,WPSEmbeddedObject> const &nameToObjectMap) |
491 | 168 | { |
492 | 168 | m_state->m_linkNameToObjectMap=nameToObjectMap; |
493 | 168 | } |
494 | | |
495 | | std::vector<Vec2i> QuattroGraph::getGraphicCellsInSheet(int sheetId) const |
496 | 641k | { |
497 | 641k | std::vector<Vec2i> list; |
498 | 641k | auto it=m_state->m_sheetIdToGraphMap.find(sheetId); |
499 | 693k | while (it!=m_state->m_sheetIdToGraphMap.end() && it->first==sheetId) |
500 | 51.7k | { |
501 | 51.7k | auto const &graph=it++->second; |
502 | 51.7k | if (graph && graph->m_type!=graph->Shape && graph->m_type!=graph->Textbox) |
503 | 40.0k | list.push_back(graph->m_cellBox[0]); |
504 | 51.7k | } |
505 | 641k | return list; |
506 | 641k | } |
507 | | |
508 | | //////////////////////////////////////////////////////////// |
509 | | // low level |
510 | | |
511 | | //////////////////////////////////////////////////////////// |
512 | | // zones |
513 | | //////////////////////////////////////////////////////////// |
514 | | bool QuattroGraph::readHeader(QuattroGraphInternal::Graph &header, std::shared_ptr<WPSStream> stream, long endPos) |
515 | 101k | { |
516 | 101k | auto input=stream->m_input; |
517 | 101k | long pos = input->tell(); |
518 | 101k | if (endPos-pos<49) |
519 | 0 | { |
520 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readHeader: the zone is too short\n")); |
521 | 0 | return false; |
522 | 0 | } |
523 | 405k | for (auto &fl : header.m_flags1) fl=int(libwps::readU16(input)); |
524 | 101k | int dim[4]; |
525 | 405k | for (auto &d: dim) d=libwps::readU16(input); |
526 | 101k | header.m_cellBox=WPSBox2i(Vec2i(dim[0],dim[1]),Vec2i(dim[2],dim[3])); |
527 | 101k | float fDim[4]; |
528 | 405k | for (auto &d: fDim) d=float(libwps::read16(input))/20.f; |
529 | 101k | header.m_cellBoxDecal=WPSBox2f(Vec2f(fDim[0],fDim[1]),Vec2f(fDim[2],fDim[3])); |
530 | 303k | for (int i=0; i<2; ++i) fDim[i]=float(libwps::read32(input))/20.f; |
531 | 101k | header.m_size=Vec2f(fDim[0],fDim[1]); |
532 | 708k | for (auto &fl : header.m_flags2) fl=int(libwps::readU8(input)); |
533 | 506k | for (auto &v : header.m_values) v=int(libwps::read16(input)); |
534 | 101k | return true; |
535 | 101k | } |
536 | | |
537 | | bool QuattroGraph::readShapeHeader(QuattroGraphInternal::ShapeHeader &shape, std::shared_ptr<WPSStream> stream, long endPos) |
538 | 146k | { |
539 | 146k | int const vers=version(); |
540 | 146k | auto input=stream->m_input; |
541 | 146k | long pos = input->tell(); |
542 | 146k | int const endSize=15+(vers==1003 ? 3 : 0); |
543 | 146k | if (endPos-pos<42+(vers==1003 ? 4 : 0)) |
544 | 0 | { |
545 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readShapeHeader: the zone is too short\n")); |
546 | 0 | return false; |
547 | 0 | } |
548 | 146k | libwps::DebugStream f; |
549 | 146k | shape.m_type=int(libwps::readU16(input)); // v1: 6f, v2: 73, v3: 9e |
550 | 146k | int wFl=0; |
551 | 734k | for (int i=0; i<4; ++i) |
552 | 587k | shape.m_flags[wFl++]=int(libwps::readU16(input)); |
553 | 146k | int dim[4]; |
554 | 587k | for (auto &d: dim) d=int(libwps::read16(input)); |
555 | 146k | shape.m_box=WPSBox2i(Vec2i(dim[0],dim[1]),Vec2i(dim[2],dim[3])); |
556 | 881k | for (int i=0; i<(vers>=1003 ? 7 : 5); ++i) |
557 | 734k | shape.m_flags[wFl++]=int(libwps::readU16(input)); |
558 | 146k | shape.m_id=int(libwps::readU16(input)); |
559 | 146k | auto &style=shape.m_style; |
560 | 146k | WPSColor surfaceColor[2]; |
561 | 146k | unsigned char col[4]; |
562 | 587k | for (auto &c : col) c=libwps::readU8(input); |
563 | 146k | surfaceColor[0]=WPSColor(col[0],col[1],col[2]); |
564 | 587k | for (auto &c : col) c=libwps::readU8(input); |
565 | 146k | style.m_lineColor=WPSColor(col[0],col[1],col[2]); |
566 | 146k | shape.m_flags[wFl++]=int(libwps::readU16(input)); |
567 | 146k | int hasData[2]; |
568 | 293k | for (auto &d : hasData) d=int(libwps::readU8(input)); |
569 | 146k | if (hasData[0]==1 && endPos-input->tell()>=3+endSize) |
570 | 1.67k | { |
571 | 1.67k | shape.m_values[0]=int(libwps::read8(input)); |
572 | 1.67k | shape.m_values[1]=int(libwps::read16(input)); |
573 | 1.67k | } |
574 | 145k | else if (hasData[0]) |
575 | 28.6k | { |
576 | 28.6k | WPS_DEBUG_MSG(("QuattroGraph::readShapeHeader: find unexpected data0 %d\n", hasData[0])); |
577 | 28.6k | return false; |
578 | 28.6k | } |
579 | 118k | if (hasData[1]==1 && endPos-input->tell()>=6+endSize) |
580 | 1.37k | { |
581 | 5.48k | for (int i=0; i<3; ++i) |
582 | 4.11k | shape.m_values[i+2]=int(libwps::read16(input)); |
583 | 1.37k | } |
584 | 116k | else if (hasData[1]) |
585 | 8.65k | { |
586 | 8.65k | WPS_DEBUG_MSG(("QuattroGraph::readShapeHeader: find unexpected data1 %d\n", hasData[1])); |
587 | 8.65k | return false; |
588 | 8.65k | } |
589 | | |
590 | | // end data |
591 | 109k | shape.m_values2[0]=int(libwps::readU8(input)); |
592 | 109k | if (vers>=1003) |
593 | 60 | { |
594 | 180 | for (int i=0; i<2; ++i) |
595 | 120 | { |
596 | 120 | int val=i==1 ? int(libwps::read8(input)) : int(libwps::read16(input)); |
597 | 120 | shape.m_values2[1+i]=val; |
598 | 120 | } |
599 | 60 | } |
600 | 109k | int patternId=int(libwps::readU16(input)); // 154: solid |
601 | 109k | int lineStyle=int(libwps::readU16(input)); |
602 | 109k | switch (lineStyle) |
603 | 109k | { |
604 | 409 | case 1: // solid |
605 | 409 | break; |
606 | 1.12k | case 2: // dash |
607 | 1.12k | style.m_lineDashWidth.push_back(float(4)); |
608 | 1.12k | style.m_lineDashWidth.push_back(float(1)); |
609 | 1.12k | break; |
610 | 231 | case 3: // dots |
611 | 231 | style.m_lineDashWidth.resize(2,float(1)); |
612 | 231 | break; |
613 | 3.41k | case 4: // dash/dots |
614 | 3.41k | style.m_lineDashWidth.resize(4,float(1)); |
615 | 3.41k | style.m_lineDashWidth[0]=float(4); |
616 | 3.41k | break; |
617 | 57 | case 5: // |
618 | 57 | style.m_lineDashWidth.resize(6,float(1)); |
619 | 57 | style.m_lineDashWidth[0]=float(4); |
620 | 57 | break; |
621 | 162 | case 6: // empty |
622 | 162 | style.m_lineWidth=0; |
623 | 162 | break; |
624 | 104k | default: |
625 | 104k | WPS_DEBUG_MSG(("QuattroGraph::readShapeHeader: find unknown line style\n")); |
626 | 104k | f << "line[style]=##" << lineStyle << ","; |
627 | 104k | break; |
628 | 109k | } |
629 | 438k | for (auto &c : col) c=libwps::readU8(input); |
630 | 109k | surfaceColor[1]=WPSColor(col[0],col[1],col[2]); |
631 | 109k | int lineWidth=int(libwps::readU16(input)); |
632 | 109k | if (style.m_lineWidth>0) style.m_lineWidth=float(lineWidth); |
633 | | // 0: none, 1: pattern, 5: gradient(wb3), 1001: bitmap |
634 | 109k | int fillType=int(libwps::readU16(input)); |
635 | 109k | shape.m_values2[3]=int(libwps::readU16(input)); |
636 | 109k | bool isTextbox=shape.isTextbox(); |
637 | 109k | if (fillType==0) |
638 | 85.5k | { |
639 | 85.5k | WPSGraphicStyle::Pattern pattern; |
640 | 85.5k | if (patternId==0) // none |
641 | 65.8k | ; |
642 | 19.6k | else if (patternId==1) |
643 | 242 | { |
644 | 242 | if (isTextbox) |
645 | 78 | style.setBackgroundColor(surfaceColor[1]); |
646 | 164 | else |
647 | 164 | style.setSurfaceColor(surfaceColor[1]); |
648 | 242 | } |
649 | 19.4k | else if (patternId==154) |
650 | 158 | { |
651 | 158 | if (isTextbox) |
652 | 23 | style.setBackgroundColor(surfaceColor[0]); |
653 | 135 | else |
654 | 135 | style.setSurfaceColor(surfaceColor[0]); |
655 | 158 | } |
656 | 19.2k | else if (m_state->getPattern(patternId, pattern)) |
657 | 3.08k | { |
658 | 9.24k | for (int i=0; i<2; ++i) |
659 | 6.16k | pattern.m_colors[i]=surfaceColor[i]; |
660 | 3.08k | if (isTextbox) |
661 | 295 | { |
662 | 295 | WPSColor finalColor; |
663 | 295 | if (pattern.getAverageColor(finalColor)) |
664 | 295 | style.setBackgroundColor(finalColor); |
665 | 295 | } |
666 | 2.78k | else |
667 | 2.78k | style.setPattern(pattern); |
668 | 3.08k | } |
669 | 16.1k | else |
670 | 16.1k | f << "###pat[id]=" << patternId << ","; |
671 | 85.5k | } |
672 | 24.1k | else |
673 | 24.1k | { |
674 | 24.1k | if (!readFillData(shape.m_style, fillType, stream, endPos)) |
675 | 23.9k | return false; |
676 | 135 | if (fillType>=1 && fillType<=6) |
677 | 5 | { |
678 | 5 | f << "gradient=" << fillType << ","; |
679 | 5 | if (isTextbox) |
680 | 1 | style.setBackgroundColor(WPSColor::barycenter(0.5f, surfaceColor[0], 0.5f, surfaceColor[1])); |
681 | 4 | else |
682 | 4 | { |
683 | 4 | style.m_gradientType=fillType<=4 ? WPSGraphicStyle::G_Linear : WPSGraphicStyle::G_Axial; |
684 | 4 | style.m_gradientStopList.clear(); |
685 | 4 | style.m_gradientStopList.push_back(WPSGraphicStyle::GradientStop(0.0, surfaceColor[1])); |
686 | 4 | style.m_gradientStopList.push_back(WPSGraphicStyle::GradientStop(1.0, surfaceColor[0])); |
687 | 4 | int const rot[]= {0, 90, -90, 0, 180, 90, 0}; |
688 | 4 | style.m_gradientAngle=float(rot[fillType]); |
689 | 4 | } |
690 | 5 | } |
691 | 130 | else |
692 | 130 | { |
693 | 130 | if (!surfaceColor[0].isBlack()) f << "surf[col0]=" << surfaceColor[0] << ","; |
694 | 130 | if (!surfaceColor[1].isWhite()) f << "surf[col1]=" << surfaceColor[1] << ","; |
695 | 130 | f << "fill[type]=" << fillType << ","; |
696 | 130 | f << "pat[id]=" << patternId << ","; |
697 | 130 | if ((fillType&0xfff)==1) |
698 | 6 | { |
699 | 6 | f << "###bitmap[" << std::hex << fillType << std::dec << "],"; |
700 | 6 | f << "crop[type]=" << (fillType>>12) << ","; |
701 | 6 | stream->m_ascii.addDelimiter(input->tell(),'|'); |
702 | 6 | shape.m_extra=f.str(); |
703 | 6 | WPS_DEBUG_MSG(("QuattroGraph::readShapeHeader: find a bitmap, unimplemented!!!\n")); |
704 | 6 | return false; |
705 | 6 | } |
706 | 124 | f << "###fill[type]=" << std::hex << fillType << std::dec << ","; |
707 | 124 | WPS_DEBUG_MSG(("QuattroGraph::readShapeHeader: unexpected fill type %d\n", fillType)); |
708 | 124 | } |
709 | 135 | } |
710 | 85.6k | shape.m_extra=f.str(); |
711 | 85.6k | return true; |
712 | 109k | } |
713 | | |
714 | | bool QuattroGraph::readFillData(WPSGraphicStyle &/*style*/, int fillType, std::shared_ptr<WPSStream> stream, long endPos) |
715 | 27.6k | { |
716 | 27.6k | if (fillType==0) return true; |
717 | 27.6k | RVNGInputStreamPtr input = stream->m_input; |
718 | 27.6k | libwps::DebugFile &ascFile=stream->m_ascii; |
719 | 27.6k | libwps::DebugStream f; |
720 | 27.6k | long pos = input->tell(); |
721 | 27.6k | if (fillType<0) |
722 | 0 | { |
723 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readFillData: unexpected fillType\n")); |
724 | 0 | return false; |
725 | 0 | } |
726 | 27.6k | if (pos+4>endPos || libwps::readU16(input)!=0x2e4) |
727 | 27.4k | { |
728 | 27.4k | WPS_DEBUG_MSG(("QuattroGraph::readFillData: the zone length seems bad\n")); |
729 | 27.4k | return false; |
730 | 27.4k | } |
731 | 189 | f << "Entries(FillData)[" << std::hex << fillType << std::dec << ":"; |
732 | 189 | int dSz=int(libwps::readU16(input)); |
733 | 189 | if (pos+4+dSz>endPos) |
734 | 44 | { |
735 | 44 | WPS_DEBUG_MSG(("QuattroGraph::readFillData: can not read the data size\n")); |
736 | 44 | return false; |
737 | 44 | } |
738 | 145 | if (dSz) |
739 | 27 | { |
740 | 27 | ascFile.addDelimiter(input->tell(),'|'); |
741 | 27 | input->seek(pos+4+dSz, librevenge::RVNG_SEEK_SET); |
742 | 27 | } |
743 | 145 | ascFile.addPos(pos); |
744 | 145 | ascFile.addNote(f.str().c_str()); |
745 | 145 | if ((fillType&0xf000)==0 || (fillType&0xfff)!=1) |
746 | 134 | return true; |
747 | 11 | pos=input->tell(); |
748 | 11 | if (pos+68>endPos) |
749 | 3 | { |
750 | 3 | WPS_DEBUG_MSG(("QuattroGraph::readFillData: can not read the bitmap name\n")); |
751 | 3 | return false; |
752 | 3 | } |
753 | 8 | f.str(""); |
754 | 8 | f << "FillData[bitmap]:"; |
755 | 8 | int val=int(libwps::readU16(input)); |
756 | 8 | if (val!=10) f << "f0=" << val << ","; |
757 | 8 | val=int(libwps::readU16(input)); |
758 | 8 | if (val) f << "crop[type]=" << val << ","; |
759 | 8 | librevenge::RVNGString name; |
760 | 8 | if (!m_mainParser.readCString(stream,name,64)) |
761 | 0 | f << "###name,"; |
762 | 8 | else |
763 | 8 | f << name.cstr() << ","; |
764 | 8 | input->seek(pos+68, librevenge::RVNG_SEEK_SET); |
765 | 8 | ascFile.addPos(pos); |
766 | 8 | ascFile.addNote(f.str().c_str()); |
767 | | |
768 | 8 | pos=input->tell(); |
769 | 8 | if (pos+10>endPos) |
770 | 2 | { |
771 | 2 | WPS_DEBUG_MSG(("QuattroGraph::readFillData: can not read the bitmap data\n")); |
772 | 2 | return false; |
773 | 2 | } |
774 | 6 | f.str(""); |
775 | 6 | f << "FillData[extra]:"; |
776 | 6 | val=int(libwps::readU16(input)); |
777 | 6 | if (val!=0x4000) f << "f0=" << val << ","; |
778 | 6 | val=int(libwps::readU16(input)); |
779 | 6 | if (val!=0x1c93) f << "f1=" << std::hex << val << std::dec << ","; |
780 | 6 | int dim[2]; |
781 | 12 | for (auto &d:dim) d=int(libwps::readU16(input)); |
782 | 6 | f << "dim=" << Vec2i(dim[0],dim[1]) << ","; |
783 | 6 | ascFile.addPos(pos); |
784 | 6 | ascFile.addNote(f.str().c_str()); |
785 | | |
786 | 6 | return true; |
787 | 8 | } |
788 | | |
789 | | bool QuattroGraph::readBeginEnd(std::shared_ptr<WPSStream> stream, int sheetId) |
790 | 29.8k | { |
791 | 29.8k | RVNGInputStreamPtr input = stream->m_input; |
792 | 29.8k | libwps::DebugFile &ascFile=stream->m_ascii; |
793 | 29.8k | libwps::DebugStream f; |
794 | 29.8k | long pos = input->tell(); |
795 | 29.8k | auto type = int(libwps::readU16(input)&0x7fff); |
796 | | |
797 | 29.8k | if (type != 0x321 && type != 0x322) |
798 | 0 | { |
799 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readBeginEnd: not a begin/end zone\n")); |
800 | 0 | return false; |
801 | 0 | } |
802 | 29.8k | auto sz = long(libwps::readU16(input)); |
803 | 29.8k | int const expectedSize=(type==0x321 ? 0 : 2); |
804 | 29.8k | m_state->m_actualGraph.reset(); |
805 | 29.8k | m_state->m_actualSheet=type==0x321 ? sheetId : -1; |
806 | 29.8k | if (sz!=expectedSize) |
807 | 450 | { |
808 | 450 | WPS_DEBUG_MSG(("QuattroGraph::readBeginEnd: size seems very bad\n")); |
809 | 450 | f << "###"; |
810 | 450 | ascFile.addPos(pos); |
811 | 450 | ascFile.addNote(f.str().c_str()); |
812 | 450 | return true; |
813 | 450 | } |
814 | 29.4k | if (type==0x322) // always 0 |
815 | 5.69k | { |
816 | 5.69k | auto val=int(libwps::read16(input)); |
817 | 5.69k | if (val) f << "f0=" << val << ","; |
818 | 5.69k | } |
819 | 29.4k | ascFile.addPos(pos); |
820 | 29.4k | ascFile.addNote(f.str().c_str()); |
821 | 29.4k | return true; |
822 | 29.8k | } |
823 | | |
824 | | bool QuattroGraph::readFrame(std::shared_ptr<WPSStream> stream) |
825 | 15.9k | { |
826 | 15.9k | RVNGInputStreamPtr input = stream->m_input; |
827 | 15.9k | libwps::DebugFile &ascFile=stream->m_ascii; |
828 | 15.9k | libwps::DebugStream f; |
829 | 15.9k | long pos = input->tell(); |
830 | 15.9k | auto type = int(libwps::readU16(input)&0x7fff); |
831 | | |
832 | 15.9k | if (type != 0x385) |
833 | 0 | { |
834 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readFrame: not a frame zone\n")); |
835 | 0 | return false; |
836 | 0 | } |
837 | 15.9k | auto sz = long(libwps::readU16(input)); |
838 | 15.9k | long endPos=pos+4+sz; |
839 | 15.9k | auto frame=std::make_shared<QuattroGraphInternal::Graph>(stream,QuattroGraphInternal::Graph::Frame); |
840 | 15.9k | m_state->m_actualGraph.reset(); |
841 | 15.9k | if (sz<57 || !readHeader(*frame,stream,endPos)) |
842 | 2.76k | { |
843 | 2.76k | if (sz) |
844 | 71 | { |
845 | 71 | WPS_DEBUG_MSG(("QuattroGraph::readFrame: size seems very bad\n")); |
846 | 71 | f << "###"; |
847 | 71 | } |
848 | 2.76k | ascFile.addPos(pos); |
849 | 2.76k | ascFile.addNote(f.str().c_str()); |
850 | 2.76k | return true; |
851 | 2.76k | } |
852 | 13.1k | f << *frame; |
853 | 13.1k | m_state->storeGraph(frame); |
854 | 13.1k | auto sSz=int(libwps::readU16(input)); |
855 | 13.1k | librevenge::RVNGString text; |
856 | 13.1k | if (input->tell()+sSz+6>endPos || !m_mainParser.readCString(stream,text,sSz)) |
857 | 8.28k | { |
858 | 8.28k | WPS_DEBUG_MSG(("QuattroGraph::readFrame: can not read string1\n")); |
859 | 8.28k | f << "##sSz,"; |
860 | 8.28k | ascFile.addPos(pos); |
861 | 8.28k | ascFile.addNote(f.str().c_str()); |
862 | 8.28k | return true; |
863 | 8.28k | } |
864 | 4.90k | f << "name=" << text.cstr() << ","; |
865 | 19.6k | for (int i=0; i<3; ++i) // g0=1, g2=2001 |
866 | 14.7k | { |
867 | 14.7k | auto val=int(libwps::readU16(input)); |
868 | 14.7k | if (val) |
869 | 8.00k | f << "g" << i << "=" << std::hex << val << std::dec << ","; |
870 | 14.7k | } |
871 | 4.90k | if (input->tell()!=endPos) |
872 | 4.80k | { |
873 | 4.80k | ascFile.addDelimiter(input->tell(),'|'); |
874 | 4.80k | WPS_DEBUG_MSG(("QuattroGraph::readFrame: find extra data\n")); |
875 | 4.80k | f << "##extra,"; |
876 | 4.80k | } |
877 | 4.90k | ascFile.addPos(pos); |
878 | 4.90k | ascFile.addNote(f.str().c_str()); |
879 | 4.90k | return true; |
880 | 13.1k | } |
881 | | |
882 | | bool QuattroGraph::readFrameOLE(std::shared_ptr<WPSStream> stream) |
883 | 85.8k | { |
884 | 85.8k | RVNGInputStreamPtr input = stream->m_input; |
885 | 85.8k | libwps::DebugFile &ascFile=stream->m_ascii; |
886 | 85.8k | libwps::DebugStream f; |
887 | 85.8k | long pos = input->tell(); |
888 | 85.8k | auto type = int(libwps::readU16(input)&0x7fff); |
889 | | |
890 | 85.8k | if (type != 0x381) |
891 | 0 | { |
892 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readFrameOLE: not a frame zone\n")); |
893 | 0 | return false; |
894 | 0 | } |
895 | 85.8k | auto sz = long(libwps::readU16(input)); |
896 | 85.8k | long endPos=pos+4+sz; |
897 | 85.8k | auto frame=std::make_shared<QuattroGraphInternal::Graph>(stream,QuattroGraphInternal::Graph::OLE); |
898 | 85.8k | m_state->m_actualGraph.reset(); |
899 | 85.8k | if (sz<59 || !readHeader(*frame,stream,endPos)) |
900 | 43.6k | { |
901 | 43.6k | if (sz) |
902 | 41.0k | { |
903 | 41.0k | WPS_DEBUG_MSG(("QuattroGraph::readFrameOLE: size seems very bad\n")); |
904 | 41.0k | f << "###"; |
905 | 41.0k | } |
906 | 43.6k | ascFile.addPos(pos); |
907 | 43.6k | ascFile.addNote(f.str().c_str()); |
908 | 43.6k | return true; |
909 | 43.6k | } |
910 | 42.1k | f << *frame; |
911 | 42.1k | m_state->storeGraph(frame); |
912 | 42.1k | auto sSz=int(libwps::readU16(input)); |
913 | 42.1k | librevenge::RVNGString text; |
914 | 42.1k | if (input->tell()+sSz+4>endPos || !m_mainParser.readCString(stream,text,sSz)) |
915 | 24.3k | { |
916 | 24.3k | WPS_DEBUG_MSG(("QuattroGraph::readFrameOLE: can not read string1\n")); |
917 | 24.3k | f << "##sSz,"; |
918 | 24.3k | ascFile.addPos(pos); |
919 | 24.3k | ascFile.addNote(f.str().c_str()); |
920 | 24.3k | return true; |
921 | 24.3k | } |
922 | 17.8k | frame->m_linkName=text; |
923 | 17.8k | f << "name=" << text.cstr() << ","; |
924 | 89.2k | for (int i=0; i<4; ++i) // g0=11, g2=d00, g4=7500 |
925 | 71.3k | { |
926 | 71.3k | auto val=int(libwps::readU16(input)); |
927 | 71.3k | if (val) |
928 | 47.8k | f << "g" << i << "=" << std::hex << val << std::dec << ","; |
929 | 71.3k | } |
930 | 17.8k | if (input->tell()!=endPos) |
931 | 13.8k | { |
932 | 13.8k | ascFile.addDelimiter(input->tell(),'|'); |
933 | 13.8k | WPS_DEBUG_MSG(("QuattroGraph::readFrameOLE: find extra data\n")); |
934 | 13.8k | f << "##extra,"; |
935 | 13.8k | } |
936 | 17.8k | ascFile.addPos(pos); |
937 | 17.8k | ascFile.addNote(f.str().c_str()); |
938 | 17.8k | return true; |
939 | 42.1k | } |
940 | | |
941 | | bool QuattroGraph::readOLEData(std::shared_ptr<WPSStream> stream) |
942 | 12.0k | { |
943 | 12.0k | RVNGInputStreamPtr input = stream->m_input; |
944 | 12.0k | libwps::DebugFile &ascFile=stream->m_ascii; |
945 | 12.0k | libwps::DebugStream f; |
946 | 12.0k | long pos = input->tell(); |
947 | 12.0k | auto type = int(libwps::readU16(input)&0x7fff); |
948 | | |
949 | 12.0k | if (type != 0x38b) |
950 | 0 | { |
951 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readOLEData: not a OLE zone\n")); |
952 | 0 | return false; |
953 | 0 | } |
954 | 12.0k | auto sz = long(libwps::readU16(input)); |
955 | 12.0k | long endPos=sz<0xFF00 ? pos+4+sz : stream->m_eof; |
956 | 12.0k | if (sz<38) |
957 | 2.45k | { |
958 | 2.45k | if (sz) |
959 | 24 | { |
960 | 24 | WPS_DEBUG_MSG(("QuattroGraph::readOLEData: size seems very bad\n")); |
961 | 24 | f << "###"; |
962 | 24 | } |
963 | 2.45k | ascFile.addPos(pos); |
964 | 2.45k | ascFile.addNote(f.str().c_str()); |
965 | 2.45k | return true; |
966 | 2.45k | } |
967 | 9.62k | auto frame=m_state->m_actualGraph; |
968 | 9.62k | if (frame && frame->m_type!=frame->Frame) |
969 | 424 | frame.reset(); |
970 | 9.62k | if (frame) |
971 | 919 | frame->m_type=frame->OLE; |
972 | 8.70k | else |
973 | 8.70k | { |
974 | 8.70k | WPS_DEBUG_MSG(("QuattroGraph::readOLEData: can not find current frame\n")); |
975 | 8.70k | } |
976 | 57.7k | for (int i=0; i<5; ++i) |
977 | 48.1k | { |
978 | 48.1k | int val=int(libwps::readU16(input)); |
979 | 48.1k | int const expected[]= {0x1a,0x8068,0x2001,0,0}; |
980 | 48.1k | if (val!=expected[i]) |
981 | 45.2k | f << "f" << i << "=" << std::hex << val << std::dec << ","; |
982 | 48.1k | } |
983 | 9.62k | long actPos=input->tell(); |
984 | 9.62k | auto sSz=int(libwps::readU16(input)); |
985 | 9.62k | librevenge::RVNGString text; |
986 | 9.62k | if (actPos+2+sSz+12+1+12>endPos || !m_mainParser.readCString(stream,text,sSz)) |
987 | 1.00k | { |
988 | 1.00k | WPS_DEBUG_MSG(("QuattroGraph::readOLEData: can not read the name\n")); |
989 | 1.00k | f << "##sSz,"; |
990 | 1.00k | ascFile.addPos(pos); |
991 | 1.00k | ascFile.addNote(f.str().c_str()); |
992 | 1.00k | return true; |
993 | 1.00k | } |
994 | 8.62k | f << "name=" << text.cstr() << ","; |
995 | 8.62k | input->seek(actPos+2+sSz, librevenge::RVNG_SEEK_SET); |
996 | 8.62k | ascFile.addPos(pos); |
997 | 8.62k | ascFile.addNote(f.str().c_str()); |
998 | | |
999 | 8.62k | pos=input->tell(); |
1000 | 8.62k | WPSEmbeddedObject dummyObject; |
1001 | 8.62k | if (!WPSOLEObject::readOLE(stream, frame ? frame->m_ole : dummyObject,endPos)) |
1002 | 1.87k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1003 | 8.62k | if (input->tell()!=endPos) |
1004 | 8.55k | { |
1005 | 8.55k | WPS_DEBUG_MSG(("QuattroGraph::readOLEData: find extra data\n")); |
1006 | 8.55k | ascFile.addPos(input->tell()); |
1007 | 8.55k | ascFile.addNote("Object:###extra"); |
1008 | 8.55k | } |
1009 | 8.62k | return true; |
1010 | 9.62k | } |
1011 | | |
1012 | | bool QuattroGraph::readButton(std::shared_ptr<WPSStream> stream) |
1013 | 15.7k | { |
1014 | 15.7k | RVNGInputStreamPtr input = stream->m_input; |
1015 | 15.7k | libwps::DebugFile &ascFile=stream->m_ascii; |
1016 | 15.7k | libwps::DebugStream f; |
1017 | 15.7k | long pos = input->tell(); |
1018 | 15.7k | auto type = int(libwps::readU16(input)&0x7fff); |
1019 | | |
1020 | 15.7k | if (type != 0x386) |
1021 | 0 | { |
1022 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readButton: not a button zone\n")); |
1023 | 0 | return false; |
1024 | 0 | } |
1025 | 15.7k | auto sz = long(libwps::readU16(input)); |
1026 | 15.7k | long endPos=pos+4+sz; |
1027 | 15.7k | m_state->m_actualGraph.reset(); |
1028 | 15.7k | auto button=std::make_shared<QuattroGraphInternal::Graph>(stream,QuattroGraphInternal::Graph::Button); |
1029 | 15.7k | if (sz<67 || !readHeader(*button,stream,endPos)) |
1030 | 11.8k | { |
1031 | 11.8k | if (sz) |
1032 | 99 | { |
1033 | 99 | WPS_DEBUG_MSG(("QuattroGraph::readButton: size seems very bad\n")); |
1034 | 99 | f << "###"; |
1035 | 99 | } |
1036 | 11.8k | ascFile.addPos(pos); |
1037 | 11.8k | ascFile.addNote(f.str().c_str()); |
1038 | 11.8k | return true; |
1039 | 11.8k | } |
1040 | 3.94k | f << *button; // fl1=[7f|81,0x8063,0x2000,0]; |
1041 | 3.94k | ascFile.addPos(pos); |
1042 | 3.94k | ascFile.addNote(f.str().c_str()); |
1043 | | |
1044 | 3.94k | pos=input->tell(); |
1045 | 3.94k | f.str(""); |
1046 | 3.94k | f << "Object-A:"; |
1047 | 3.94k | auto sSz=int(libwps::readU16(input)); |
1048 | 3.94k | librevenge::RVNGString text; |
1049 | 3.94k | if (pos+2+sSz>endPos || !m_mainParser.readCString(stream,text,sSz)) |
1050 | 977 | { |
1051 | 977 | WPS_DEBUG_MSG(("QuattroGraph::readButton: can not read string1 bad\n")); |
1052 | 977 | f << "##sSz,"; |
1053 | 977 | ascFile.addPos(pos); |
1054 | 977 | ascFile.addNote(f.str().c_str()); |
1055 | 977 | return true; |
1056 | 977 | } |
1057 | 2.97k | input->seek(pos+2+sSz, librevenge::RVNG_SEEK_SET); |
1058 | 2.97k | f << "name=" << text.cstr() << ","; |
1059 | 17.8k | for (int i=0; i<5; ++i) |
1060 | 14.8k | { |
1061 | 14.8k | auto val=int(libwps::readU16(input)); |
1062 | 14.8k | if (val) f << "f" << i << "=" << val << ","; |
1063 | 14.8k | } |
1064 | 2.97k | auto val=int(libwps::readU8(input)); |
1065 | 2.97k | if (val) f << "f5=" << val << ","; |
1066 | 2.97k | ascFile.addPos(pos); |
1067 | 2.97k | ascFile.addNote(f.str().c_str()); |
1068 | 2.97k | pos=input->tell(); |
1069 | 2.97k | f.str(""); |
1070 | 2.97k | f << "Object-B:"; |
1071 | 2.97k | auto dType=int(libwps::readU8(input)); |
1072 | 2.97k | if (dType==1) f << "complex,"; |
1073 | 2.91k | else if (dType) |
1074 | 376 | { |
1075 | 376 | WPS_DEBUG_MSG(("QuattroGraph::readButton: find unknown type\n")); |
1076 | 376 | f << "##dType=" << dType << ","; |
1077 | 376 | } |
1078 | 7.41k | for (int st=0; st<2; ++st) |
1079 | 5.29k | { |
1080 | 5.29k | sSz=int(libwps::readU16(input)); |
1081 | 5.29k | if (pos+2+sSz>endPos || !m_mainParser.readCString(stream,text,sSz)) |
1082 | 854 | { |
1083 | 854 | WPS_DEBUG_MSG(("QuattroGraph::readButton: can not read string2 bad\n")); |
1084 | 854 | f << "##sSz,"; |
1085 | 854 | ascFile.addPos(pos); |
1086 | 854 | ascFile.addNote(f.str().c_str()); |
1087 | 854 | return true; |
1088 | 854 | } |
1089 | 4.44k | if (text.empty()) continue; |
1090 | 1.04k | f << (st==0 ? "macros" : "label") << "=" << text.cstr() << ","; |
1091 | 1.04k | if (st==1) |
1092 | 1.02k | button->m_label=text; |
1093 | 1.04k | } |
1094 | 2.11k | if (dType==0) |
1095 | 1.89k | { |
1096 | 1.89k | if (input->tell()!=endPos) |
1097 | 1.35k | { |
1098 | 1.35k | WPS_DEBUG_MSG(("QuattroGraph::readButton: find extra data\n")); |
1099 | 1.35k | f << "##extra,"; |
1100 | 1.35k | ascFile.addDelimiter(input->tell(),'|'); |
1101 | 1.35k | } |
1102 | 1.89k | m_state->storeGraph(button); |
1103 | 1.89k | } |
1104 | 2.11k | ascFile.addPos(pos); |
1105 | 2.11k | ascFile.addNote(f.str().c_str()); |
1106 | | |
1107 | 2.11k | if (dType && input->tell()!=endPos) |
1108 | 148 | { |
1109 | 148 | ascFile.addPos(input->tell()); |
1110 | 148 | ascFile.addNote("Object-C:"); |
1111 | 148 | } |
1112 | 2.11k | return true; |
1113 | 2.97k | } |
1114 | | |
1115 | | bool QuattroGraph::readImage(std::shared_ptr<WPSStream> stream) |
1116 | 4.70k | { |
1117 | 4.70k | RVNGInputStreamPtr input = stream->m_input; |
1118 | 4.70k | libwps::DebugFile &ascFile=stream->m_ascii; |
1119 | 4.70k | libwps::DebugStream f; |
1120 | 4.70k | long pos = input->tell(); |
1121 | 4.70k | auto type = int(libwps::readU16(input)&0x7fff); |
1122 | | |
1123 | 4.70k | if (type != 0x382) |
1124 | 0 | { |
1125 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readImage: unknown id\n")); |
1126 | 0 | return false; |
1127 | 0 | } |
1128 | 4.70k | auto sz = long(libwps::readU16(input)); |
1129 | 4.70k | long endPos=pos+4+sz; |
1130 | 4.70k | auto zone382=std::make_shared<QuattroGraphInternal::Graph>(stream,QuattroGraphInternal::Graph::Image); |
1131 | 4.70k | m_state->m_actualGraph.reset(); |
1132 | 4.70k | if (sz<53 || !readHeader(*zone382,stream,endPos)) |
1133 | 4.32k | { |
1134 | 4.32k | if (sz) |
1135 | 2.50k | { |
1136 | 2.50k | WPS_DEBUG_MSG(("QuattroGraph::readImage: size seems very bad\n")); |
1137 | 2.50k | f << "###"; |
1138 | 2.50k | } |
1139 | 4.32k | ascFile.addPos(pos); |
1140 | 4.32k | ascFile.addNote(f.str().c_str()); |
1141 | 4.32k | return true; |
1142 | 4.32k | } |
1143 | 374 | f << *zone382; |
1144 | 374 | auto sSz=int(libwps::readU16(input)); |
1145 | 374 | librevenge::RVNGString text; |
1146 | 374 | if (input->tell()+sSz+2>endPos || !m_mainParser.readCString(stream,text,sSz)) |
1147 | 152 | { |
1148 | 152 | WPS_DEBUG_MSG(("QuattroGraph::readImage: can not read string1\n")); |
1149 | 152 | f << "##sSz,"; |
1150 | 152 | ascFile.addPos(pos); |
1151 | 152 | ascFile.addNote(f.str().c_str()); |
1152 | 152 | return true; |
1153 | 152 | } |
1154 | 222 | f << text.cstr() << ","; // find Bitmap5, followed by |
1155 | | // 20000000070001000080000000ffffff0000000100000000070064e96729a1e87328af2b0700628597334100 |
1156 | | // c767040064e96729b7e87328af2b04008bce67354800 |
1157 | | // c7670500673575ce0400 |
1158 | | // 2d002d00: a picture dimension ? |
1159 | | // eb010000: the gif's size |
1160 | | // the gif |
1161 | 222 | if (input->tell()!=endPos) |
1162 | 222 | { |
1163 | 222 | ascFile.addDelimiter(input->tell(),'|'); |
1164 | 222 | } |
1165 | 222 | static bool first=true; |
1166 | 222 | if (first) |
1167 | 4 | { |
1168 | 4 | first=false; |
1169 | 4 | WPS_DEBUG_MSG(("QuattroGraph::readImage: this file contains a zone 382, there will not be recovered\n")); |
1170 | 4 | } |
1171 | 222 | ascFile.addPos(pos); |
1172 | 222 | ascFile.addNote(f.str().c_str()); |
1173 | 222 | return true; |
1174 | 374 | } |
1175 | | |
1176 | | bool QuattroGraph::readBitmap(std::shared_ptr<WPSStream> stream) |
1177 | 8.45k | { |
1178 | 8.45k | RVNGInputStreamPtr input = stream->m_input; |
1179 | 8.45k | libwps::DebugFile &ascFile=stream->m_ascii; |
1180 | 8.45k | libwps::DebugStream f; |
1181 | 8.45k | long pos = input->tell(); |
1182 | 8.45k | auto type = int(libwps::readU16(input)&0x7fff); |
1183 | | |
1184 | 8.45k | if (type != 0x383) |
1185 | 0 | { |
1186 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readBitmap: unknown id\n")); |
1187 | 0 | return false; |
1188 | 0 | } |
1189 | 8.45k | auto sz = long(libwps::readU16(input)); |
1190 | 8.45k | long endPos=pos+4+sz; |
1191 | 8.45k | auto bitmap=std::make_shared<QuattroGraphInternal::Graph>(stream,QuattroGraphInternal::Graph::OLE); |
1192 | 8.45k | m_state->m_actualGraph.reset(); |
1193 | 8.45k | if (sz<67 || !readHeader(*bitmap,stream,endPos)) |
1194 | 3.63k | { |
1195 | 3.63k | if (sz) |
1196 | 87 | { |
1197 | 87 | WPS_DEBUG_MSG(("QuattroGraph::readBitmap: size seems very bad\n")); |
1198 | 87 | f << "###"; |
1199 | 87 | } |
1200 | 3.63k | ascFile.addPos(pos); |
1201 | 3.63k | ascFile.addNote(f.str().c_str()); |
1202 | 3.63k | return true; |
1203 | 3.63k | } |
1204 | 4.82k | f << *bitmap; |
1205 | 4.82k | auto sSz=int(libwps::readU16(input)); |
1206 | 4.82k | librevenge::RVNGString text; |
1207 | 4.82k | if (input->tell()+sSz+16>endPos || !m_mainParser.readCString(stream,text,sSz)) |
1208 | 1.04k | { |
1209 | 1.04k | WPS_DEBUG_MSG(("QuattroGraph::readBitmap: can not read string1\n")); |
1210 | 1.04k | f << "##sSz,"; |
1211 | 1.04k | ascFile.addPos(pos); |
1212 | 1.04k | ascFile.addNote(f.str().c_str()); |
1213 | 1.04k | return true; |
1214 | 1.04k | } |
1215 | 3.78k | f << text.cstr() << ","; |
1216 | 3.78k | f << "unkn=["; |
1217 | 34.0k | for (int i=0; i<8; ++i) |
1218 | 30.2k | { |
1219 | 30.2k | auto val=int(libwps::readU16(input)); |
1220 | 30.2k | if (val) |
1221 | 13.6k | f << std::hex << val << std::dec << ","; |
1222 | 16.6k | else |
1223 | 16.6k | f << "_,"; |
1224 | 30.2k | } |
1225 | 3.78k | f << "],"; |
1226 | 3.78k | ascFile.addPos(pos); |
1227 | 3.78k | ascFile.addNote(f.str().c_str()); |
1228 | | |
1229 | 3.78k | WPSEmbeddedObject object; |
1230 | 3.78k | pos=input->tell(); |
1231 | 3.78k | if (!WPSOLEObject::readWMF(stream, bitmap->m_ole, endPos)) |
1232 | 3.33k | { |
1233 | 3.33k | WPS_DEBUG_MSG(("QuattroGraph::readBitmap: can not find the wmf file\n")); |
1234 | 3.33k | ascFile.addPos(pos); |
1235 | 3.33k | ascFile.addNote("Object:###"); |
1236 | 3.33k | } |
1237 | 443 | else |
1238 | 443 | m_state->storeGraph(bitmap); |
1239 | | |
1240 | 3.78k | return true; |
1241 | 4.82k | } |
1242 | | |
1243 | | bool QuattroGraph::readChart(std::shared_ptr<WPSStream> stream) |
1244 | 23.0k | { |
1245 | 23.0k | RVNGInputStreamPtr input = stream->m_input; |
1246 | 23.0k | libwps::DebugFile &ascFile=stream->m_ascii; |
1247 | 23.0k | libwps::DebugStream f; |
1248 | 23.0k | long pos = input->tell(); |
1249 | 23.0k | auto type = int(libwps::readU16(input)&0x7fff); |
1250 | | |
1251 | 23.0k | if (type != 0x384) |
1252 | 0 | { |
1253 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readChart: unknown id\n")); |
1254 | 0 | return false; |
1255 | 0 | } |
1256 | 23.0k | auto sz = long(libwps::readU16(input)); |
1257 | 23.0k | long endPos=pos+4+sz; |
1258 | 23.0k | auto chart=std::make_shared<QuattroGraphInternal::Graph>(stream,QuattroGraphInternal::Graph::Chart); |
1259 | 23.0k | m_state->m_actualGraph.reset(); |
1260 | 23.0k | if (sz<57 || !readHeader(*chart,stream,endPos)) |
1261 | 17.0k | { |
1262 | 17.0k | if (sz) |
1263 | 24 | { |
1264 | 24 | WPS_DEBUG_MSG(("QuattroGraph::readChart: size seems very bad\n")); |
1265 | 24 | f << "###"; |
1266 | 24 | } |
1267 | 17.0k | ascFile.addPos(pos); |
1268 | 17.0k | ascFile.addNote(f.str().c_str()); |
1269 | 17.0k | return true; |
1270 | 17.0k | } |
1271 | 5.99k | f << *chart; |
1272 | 5.99k | auto sSz=int(libwps::readU16(input)); |
1273 | 5.99k | librevenge::RVNGString text; |
1274 | 5.99k | if (input->tell()+sSz+6>endPos || !m_mainParser.readCString(stream,text,sSz)) |
1275 | 3.21k | { |
1276 | 3.21k | WPS_DEBUG_MSG(("QuattroGraph::readChart: can not read string1\n")); |
1277 | 3.21k | f << "##sSz,"; |
1278 | 3.21k | ascFile.addPos(pos); |
1279 | 3.21k | ascFile.addNote(f.str().c_str()); |
1280 | 3.21k | return true; |
1281 | 3.21k | } |
1282 | 2.77k | f << text.cstr() << ","; // find Inserted1-21 |
1283 | 8.32k | for (int i=0; i<2; ++i) // f0=1|30 |
1284 | 5.55k | { |
1285 | 5.55k | auto val=int(libwps::read16(input)); |
1286 | 5.55k | if (val) f << "f" << i << "=" << val << ","; |
1287 | 5.55k | } |
1288 | 2.77k | sSz=int(libwps::readU16(input)); |
1289 | 2.77k | if (input->tell()+sSz>endPos || !m_mainParser.readCString(stream,text,sSz)) |
1290 | 1.42k | { |
1291 | 1.42k | WPS_DEBUG_MSG(("QuattroGraph::readChart: can not read string1\n")); |
1292 | 1.42k | f << "##sSz2,"; |
1293 | 1.42k | ascFile.addPos(pos); |
1294 | 1.42k | ascFile.addNote(f.str().c_str()); |
1295 | 1.42k | return true; |
1296 | 1.42k | } |
1297 | 1.34k | f << "name=" << text.cstr() << ","; |
1298 | 1.34k | if (input->tell()!=endPos) |
1299 | 1.30k | { |
1300 | 1.30k | WPS_DEBUG_MSG(("QuattroGraph::readChart: find extra data\n")); |
1301 | 1.30k | f << "##extra,"; |
1302 | 1.30k | ascFile.addDelimiter(input->tell(),'|'); |
1303 | 1.30k | } |
1304 | 1.34k | static bool first=true; |
1305 | 1.34k | if (first) |
1306 | 5 | { |
1307 | 5 | first=false; |
1308 | 5 | WPS_DEBUG_MSG(("QuattroGraph::readChart: this file contains some charts, there will not be recovered\n")); |
1309 | 5 | } |
1310 | 1.34k | ascFile.addPos(pos); |
1311 | 1.34k | ascFile.addNote(f.str().c_str()); |
1312 | 1.34k | return true; |
1313 | 2.77k | } |
1314 | | |
1315 | | //////////////////////////////////////////////////////////// |
1316 | | // shape, line, ... |
1317 | | //////////////////////////////////////////////////////////// |
1318 | | bool QuattroGraph::readShape(std::shared_ptr<WPSStream> stream) |
1319 | 31.0k | { |
1320 | 31.0k | RVNGInputStreamPtr input = stream->m_input; |
1321 | 31.0k | libwps::DebugFile &ascFile=stream->m_ascii; |
1322 | 31.0k | libwps::DebugStream f; |
1323 | 31.0k | long pos = input->tell(); |
1324 | 31.0k | auto type = int(libwps::readU16(input)&0x7fff); |
1325 | | |
1326 | 31.0k | if (type != 0x4d3) |
1327 | 0 | { |
1328 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readShape: not a shape zone\n")); |
1329 | 0 | return false; |
1330 | 0 | } |
1331 | 31.0k | auto sz = long(libwps::readU16(input)); |
1332 | 31.0k | long endPos=pos+4+sz; |
1333 | 31.0k | auto shape=std::make_shared<QuattroGraphInternal::Graph>(stream,QuattroGraphInternal::Graph::Shape); |
1334 | 31.0k | m_state->m_actualGraph.reset(); |
1335 | 31.0k | if (sz<59 || !readHeader(*shape,stream,endPos)) |
1336 | 318 | { |
1337 | 318 | if (sz) |
1338 | 258 | { |
1339 | 258 | WPS_DEBUG_MSG(("QuattroGraph::readShape: size seems very bad\n")); |
1340 | 258 | f << "###"; |
1341 | 258 | } |
1342 | 318 | ascFile.addPos(pos); |
1343 | 318 | ascFile.addNote(f.str().c_str()); |
1344 | 318 | return true; |
1345 | 318 | } |
1346 | 30.7k | f << *shape; |
1347 | 30.7k | auto sSz=int(libwps::readU16(input)); |
1348 | 30.7k | librevenge::RVNGString text; |
1349 | 30.7k | if (input->tell()+sSz+8>endPos || !m_mainParser.readCString(stream,text,sSz)) |
1350 | 12.8k | { |
1351 | 12.8k | WPS_DEBUG_MSG(("QuattroGraph::readShape: can not read string1\n")); |
1352 | 12.8k | f << "##sSz,"; |
1353 | 12.8k | ascFile.addPos(pos); |
1354 | 12.8k | ascFile.addNote(f.str().c_str()); |
1355 | 12.8k | return true; |
1356 | 12.8k | } |
1357 | 17.9k | shape->m_linkName=text; |
1358 | 17.9k | f << "name=" << text.cstr() << ","; |
1359 | 89.5k | for (int i=0; i<4; ++i) // f2=1b(oval) 37(line),41(rect), 56(rect oval), 58(arrow) |
1360 | 71.6k | { |
1361 | 71.6k | int val=int(libwps::read16(input)); |
1362 | 71.6k | int const expected[]= {0x20,0,0,0x2001}; |
1363 | 71.6k | if (val!=expected[i]) |
1364 | 54.5k | f << "f" << i << "=" << val << ","; |
1365 | 71.6k | } |
1366 | 17.9k | m_state->storeGraph(shape); |
1367 | 17.9k | if (input->tell()!=endPos) |
1368 | 17.3k | { |
1369 | 17.3k | ascFile.addDelimiter(input->tell(),'|'); |
1370 | 17.3k | f << "##extra,"; |
1371 | 17.3k | WPS_DEBUG_MSG(("QuattroGraph::readShape: find extra data\n")); |
1372 | 17.3k | } |
1373 | 17.9k | ascFile.addPos(pos); |
1374 | 17.9k | ascFile.addNote(f.str().c_str()); |
1375 | 17.9k | return true; |
1376 | 30.7k | } |
1377 | | |
1378 | | bool QuattroGraph::readLine(std::shared_ptr<WPSStream> stream) |
1379 | 167k | { |
1380 | 167k | RVNGInputStreamPtr input = stream->m_input; |
1381 | 167k | libwps::DebugFile &ascFile=stream->m_ascii; |
1382 | 167k | libwps::DebugStream f; |
1383 | 167k | long pos = input->tell(); |
1384 | 167k | auto type = int(libwps::readU16(input)&0x7fff); |
1385 | 167k | if (type!=0x35a && type!=0x37b) |
1386 | 0 | { |
1387 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readLine: not a line zone\n")); |
1388 | 0 | return false; |
1389 | 0 | } |
1390 | 167k | auto parent=m_state->m_actualGraph; |
1391 | 167k | m_state->m_actualGraph.reset(); |
1392 | 167k | auto sz = long(libwps::readU16(input)); |
1393 | 167k | long endPos=pos+4+sz; |
1394 | 167k | auto shape=std::make_shared<QuattroGraphInternal::Shape>(); |
1395 | 167k | if (sz<58 || !readShapeHeader(*shape, stream, endPos-1) || input->tell()+1>endPos) |
1396 | 102k | { |
1397 | 102k | if (sz) |
1398 | 101k | { |
1399 | 101k | WPS_DEBUG_MSG(("QuattroGraph::readLine: the size seems very bad\n")); |
1400 | 101k | f << shape << ","; |
1401 | 101k | f << "###"; |
1402 | 101k | } |
1403 | 102k | ascFile.addPos(pos); |
1404 | 102k | ascFile.addNote(f.str().c_str()); |
1405 | 102k | return true; |
1406 | 102k | } |
1407 | 65.4k | f << *shape << ","; |
1408 | 65.4k | ascFile.addPos(pos); |
1409 | 65.4k | ascFile.addNote(f.str().c_str()); |
1410 | | |
1411 | 65.4k | pos=input->tell(); |
1412 | 65.4k | f.str(""); |
1413 | 65.4k | f << "GrLine:"; |
1414 | 65.4k | int val=int(libwps::readU8(input)); |
1415 | 65.4k | f << "type=" << val << ","; |
1416 | 65.4k | if (input->tell()!=endPos) |
1417 | 1.72k | { |
1418 | 1.72k | ascFile.addDelimiter(input->tell(),'|'); |
1419 | 1.72k | f << "##extra,"; |
1420 | 1.72k | WPS_DEBUG_MSG(("QuattroGraph::readLine: find extra data\n")); |
1421 | 1.72k | } |
1422 | 65.4k | shape->m_style.m_arrows[1]=type==0x37b; |
1423 | 65.4k | switch (val&3) |
1424 | 65.4k | { |
1425 | 87 | case 1: |
1426 | 87 | shape->m_shape=WPSGraphicShape::line(Vec2f(float(shape->m_box[1][0]),float(shape->m_box[0][1])), |
1427 | 87 | Vec2f(float(shape->m_box[0][0]),float(shape->m_box[1][1]))); |
1428 | 87 | break; |
1429 | 6.10k | case 2: |
1430 | 6.10k | shape->m_shape=WPSGraphicShape::line(Vec2f(shape->m_box[1]),Vec2f(shape->m_box[0])); |
1431 | 6.10k | break; |
1432 | 10.0k | case 3: |
1433 | 10.0k | shape->m_shape=WPSGraphicShape::line(Vec2f(float(shape->m_box[0][0]),float(shape->m_box[1][1])), |
1434 | 10.0k | Vec2f(float(shape->m_box[1][0]),float(shape->m_box[0][1]))); |
1435 | 10.0k | break; |
1436 | 49.2k | case 0: |
1437 | 49.2k | default: |
1438 | 49.2k | shape->m_shape=WPSGraphicShape::line(Vec2f(shape->m_box[0]),Vec2f(shape->m_box[1])); |
1439 | 49.2k | break; |
1440 | 65.4k | } |
1441 | 65.4k | if (parent && parent->m_type==parent->Shape) |
1442 | 296 | parent->m_shape=shape; |
1443 | | |
1444 | 65.4k | ascFile.addPos(pos); |
1445 | 65.4k | ascFile.addNote(f.str().c_str()); |
1446 | 65.4k | return true; |
1447 | 65.4k | } |
1448 | | |
1449 | | bool QuattroGraph::readRect(std::shared_ptr<WPSStream> stream) |
1450 | 7.42k | { |
1451 | 7.42k | RVNGInputStreamPtr input = stream->m_input; |
1452 | 7.42k | libwps::DebugFile &ascFile=stream->m_ascii; |
1453 | 7.42k | libwps::DebugStream f; |
1454 | 7.42k | long pos = input->tell(); |
1455 | 7.42k | auto type = int(libwps::readU16(input)&0x7fff); |
1456 | | |
1457 | 7.42k | auto parent=m_state->m_actualGraph; |
1458 | 7.42k | m_state->m_actualGraph.reset(); |
1459 | 7.42k | if (type!=0x33e && type!=0x364 && type!=0x379) |
1460 | 0 | { |
1461 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readRect: not a rect zone\n")); |
1462 | 0 | return false; |
1463 | 0 | } |
1464 | 7.42k | auto sz = long(libwps::readU16(input)); |
1465 | 7.42k | long endPos=pos+4+sz; |
1466 | 7.42k | auto shape=std::make_shared<QuattroGraphInternal::Shape>(); |
1467 | 7.42k | if (sz<57 || !readShapeHeader(*shape, stream, endPos)) |
1468 | 4.16k | { |
1469 | 4.16k | if (sz) |
1470 | 3.11k | { |
1471 | 3.11k | WPS_DEBUG_MSG(("QuattroGraph::readRect: the size seems very bad\n")); |
1472 | 3.11k | f << *shape << ","; |
1473 | 3.11k | f << "###"; |
1474 | 3.11k | } |
1475 | 4.16k | ascFile.addPos(pos); |
1476 | 4.16k | ascFile.addNote(f.str().c_str()); |
1477 | 4.16k | return true; |
1478 | 4.16k | } |
1479 | 3.25k | f << *shape << ","; |
1480 | 3.25k | switch (type) |
1481 | 3.25k | { |
1482 | 2.56k | case 0x33e: |
1483 | 2.56k | shape->m_shape=WPSGraphicShape::circle(WPSBox2f(shape->m_box)); |
1484 | 2.56k | break; |
1485 | 599 | case 0x364: |
1486 | 599 | shape->m_shape=WPSGraphicShape::rectangle(WPSBox2f(shape->m_box)); |
1487 | 599 | break; |
1488 | 0 | default: |
1489 | 95 | case 0x379: |
1490 | 95 | shape->m_shape=WPSGraphicShape::rectangle(WPSBox2f(shape->m_box), Vec2f(20,20)); |
1491 | 95 | break; |
1492 | 3.25k | } |
1493 | 3.25k | if (parent && parent->m_type==parent->Shape) |
1494 | 111 | parent->m_shape=shape; |
1495 | 3.25k | if (input->tell()!=endPos) |
1496 | 3.25k | { |
1497 | 3.25k | ascFile.addDelimiter(input->tell(),'|'); |
1498 | 3.25k | f << "##extra,"; |
1499 | 3.25k | WPS_DEBUG_MSG(("QuattroGraph::readRect: find extra data\n")); |
1500 | 3.25k | } |
1501 | 3.25k | ascFile.addPos(pos); |
1502 | 3.25k | ascFile.addNote(f.str().c_str()); |
1503 | 3.25k | return true; |
1504 | 3.25k | } |
1505 | | |
1506 | | bool QuattroGraph::readPolygon(std::shared_ptr<WPSStream> stream) |
1507 | 11.7k | { |
1508 | 11.7k | RVNGInputStreamPtr input = stream->m_input; |
1509 | 11.7k | libwps::DebugFile &ascFile=stream->m_ascii; |
1510 | 11.7k | libwps::DebugStream f; |
1511 | 11.7k | long pos = input->tell(); |
1512 | 11.7k | auto type = int(libwps::readU16(input)&0x7fff); |
1513 | 11.7k | if (type!=0x35b && type!=0x35c && type!=0x37c && type!=0x388) |
1514 | 0 | { |
1515 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readPolygon: not a polygon zone\n")); |
1516 | 0 | return false; |
1517 | 0 | } |
1518 | 11.7k | auto parent=m_state->m_actualGraph; |
1519 | 11.7k | m_state->m_actualGraph.reset(); |
1520 | 11.7k | auto sz = long(libwps::readU16(input)); |
1521 | 11.7k | long endPos=pos+4+sz; |
1522 | 11.7k | auto shape=std::make_shared<QuattroGraphInternal::Shape>(); |
1523 | 11.7k | if (sz<57 || !readShapeHeader(*shape, stream, endPos-6) || input->tell()+6>endPos) |
1524 | 7.84k | { |
1525 | 7.84k | if (sz) |
1526 | 2.68k | { |
1527 | 2.68k | WPS_DEBUG_MSG(("QuattroGraph::readPolygon: the size seems very bad\n")); |
1528 | 2.68k | f << *shape << ","; |
1529 | 2.68k | f << "###"; |
1530 | 2.68k | } |
1531 | 7.84k | ascFile.addPos(pos); |
1532 | 7.84k | ascFile.addNote(f.str().c_str()); |
1533 | 7.84k | return true; |
1534 | 7.84k | } |
1535 | 3.91k | f << *shape << ","; |
1536 | 3.91k | ascFile.addPos(pos); |
1537 | 3.91k | ascFile.addNote(f.str().c_str()); |
1538 | | |
1539 | 3.91k | pos=input->tell(); |
1540 | 3.91k | f.str(""); |
1541 | 3.91k | f << "GrPolygon:"; |
1542 | 3.91k | int N=int(libwps::readU16(input)); |
1543 | 3.91k | if ((endPos-pos-2)/4!=N+1) |
1544 | 1.87k | { |
1545 | 1.87k | WPS_DEBUG_MSG(("QuattroGraph::readPolygon: the number of points seems very bad\n")); |
1546 | 1.87k | f << "###N=" << N << ","; |
1547 | 1.87k | ascFile.addPos(pos); |
1548 | 1.87k | ascFile.addNote(f.str().c_str()); |
1549 | 1.87k | return true; |
1550 | 1.87k | } |
1551 | 2.04k | if (type==0x35c || type==0x37c) // FIXME |
1552 | 2.04k | shape->m_shape=WPSGraphicShape::polyline(WPSBox2f(shape->m_box)); |
1553 | 8 | else |
1554 | 8 | shape->m_shape=WPSGraphicShape::polygon(WPSBox2f(shape->m_box)); |
1555 | 2.04k | f << "pts=["; |
1556 | 10.2k | for (int i=0; i<=N; ++i) |
1557 | 8.24k | { |
1558 | 8.24k | int pt[2]; |
1559 | 16.4k | for (auto &p : pt) p=int(libwps::read16(input)); |
1560 | 8.24k | shape->m_shape.m_vertices.push_back(Vec2f(float(pt[0]),float(pt[1]))); |
1561 | 8.24k | f << shape->m_shape.m_vertices.back() << ","; |
1562 | 8.24k | } |
1563 | 2.04k | f << "],"; |
1564 | 2.04k | if (parent && parent->m_type==parent->Shape) |
1565 | 5 | parent->m_shape=shape; |
1566 | 2.04k | ascFile.addPos(pos); |
1567 | 2.04k | ascFile.addNote(f.str().c_str()); |
1568 | 2.04k | return true; |
1569 | 3.91k | } |
1570 | | |
1571 | | bool QuattroGraph::readTextBox(std::shared_ptr<WPSStream> stream) |
1572 | 18.1k | { |
1573 | 18.1k | RVNGInputStreamPtr input = stream->m_input; |
1574 | 18.1k | libwps::DebugFile &ascFile=stream->m_ascii; |
1575 | 18.1k | libwps::DebugStream f; |
1576 | 18.1k | long pos = input->tell(); |
1577 | 18.1k | auto type = int(libwps::readU16(input)&0x7fff); |
1578 | | |
1579 | 18.1k | if (type!=0x36f) |
1580 | 0 | { |
1581 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readTextBox: not a text box zone\n")); |
1582 | 0 | return false; |
1583 | 0 | } |
1584 | 18.1k | auto parent=m_state->m_actualGraph; |
1585 | 18.1k | m_state->m_actualGraph.reset(); |
1586 | 18.1k | auto sz = long(libwps::readU16(input)); |
1587 | 18.1k | long endPos=pos+4+sz; |
1588 | 18.1k | auto textbox=std::make_shared<QuattroGraphInternal::Textbox>(); |
1589 | 18.1k | if (sz<57 || !readShapeHeader(*textbox, stream, endPos-3) || input->tell()+3>endPos) |
1590 | 5.29k | { |
1591 | 5.29k | if (sz) |
1592 | 4.91k | { |
1593 | 4.91k | WPS_DEBUG_MSG(("QuattroGraph::readTextBox: the size seems very bad\n")); |
1594 | 4.91k | f << *textbox << ","; |
1595 | 4.91k | f << "###"; |
1596 | 4.91k | } |
1597 | 5.29k | ascFile.addPos(pos); |
1598 | 5.29k | ascFile.addNote(f.str().c_str()); |
1599 | 5.29k | return true; |
1600 | 5.29k | } |
1601 | 12.8k | f << *textbox << ","; |
1602 | 12.8k | ascFile.addPos(pos); |
1603 | 12.8k | ascFile.addNote(f.str().c_str()); |
1604 | | |
1605 | 12.8k | pos=input->tell(); |
1606 | 12.8k | f.str(""); |
1607 | 12.8k | f << "GrTextBox[text]:"; |
1608 | 12.8k | int val=int(libwps::readU8(input)); |
1609 | 12.8k | if (val) f << "f0=" << std::hex << val << std::dec << ","; |
1610 | 12.8k | int N=int(libwps::readU16(input)); |
1611 | 12.8k | if (pos+3+N+10>endPos) |
1612 | 1.07k | { |
1613 | 1.07k | WPS_DEBUG_MSG(("QuattroGraph::readTextBox: can not read the text zone\n")); |
1614 | 1.07k | f << "###"; |
1615 | 1.07k | ascFile.addPos(pos); |
1616 | 1.07k | ascFile.addNote(f.str().c_str()); |
1617 | 1.07k | return true; |
1618 | 1.07k | } |
1619 | 11.7k | textbox->m_entry.setBegin(pos+3); |
1620 | 11.7k | textbox->m_entry.setLength(N); |
1621 | 11.7k | std::string text; |
1622 | 76.5k | for (int i=0; i<N; ++i) text+=char(libwps::readU8(input)); |
1623 | 11.7k | f << text; |
1624 | 11.7k | ascFile.addPos(pos); |
1625 | 11.7k | ascFile.addNote(f.str().c_str()); |
1626 | | |
1627 | 11.7k | pos=input->tell(); |
1628 | 11.7k | f.str(""); |
1629 | 11.7k | f << "GrTextBox[format]:"; |
1630 | 11.7k | if (pos+80>endPos) |
1631 | 1.09k | { |
1632 | 1.09k | WPS_DEBUG_MSG(("QuattroGraph::readTextBox: can not read the format zone\n")); |
1633 | 1.09k | f << "###"; |
1634 | 1.09k | ascFile.addPos(pos); |
1635 | 1.09k | ascFile.addNote(f.str().c_str()); |
1636 | 1.09k | return true; |
1637 | 1.09k | } |
1638 | 10.6k | auto &font = textbox->m_font;; |
1639 | 10.6k | font.m_size=double(libwps::readU16(input)); |
1640 | 10.6k | int flags=int(libwps::readU16(input)); |
1641 | 10.6k | uint32_t attributes = 0; |
1642 | 10.6k | if (flags & 1) attributes |= WPS_BOLD_BIT; |
1643 | 10.6k | if (flags & 2) attributes |= WPS_ITALICS_BIT; |
1644 | 10.6k | if (flags & 4) attributes |= WPS_UNDERLINE_BIT; |
1645 | 10.6k | if (flags & 0x20) attributes |= WPS_STRIKEOUT_BIT; |
1646 | 10.6k | font.m_attributes=attributes; |
1647 | 10.6k | flags&=0xffd8; |
1648 | 10.6k | if (flags) |
1649 | 3.78k | f << "#font[flag]=" << std::hex << flags << std::dec << ","; |
1650 | 10.6k | librevenge::RVNGString name; |
1651 | 10.6k | if (!m_mainParser.readCString(stream, name, 32)) |
1652 | 0 | f << "###name,"; |
1653 | 10.6k | else |
1654 | 10.6k | font.m_name=name; |
1655 | 10.6k | input->seek(pos+35, librevenge::RVNG_SEEK_SET); |
1656 | 10.6k | val=int(libwps::readU8(input)); // 0|5|8|58|ff |
1657 | 10.6k | if (val) f << "f0=" << std::hex << val << std::dec << ","; |
1658 | 10.6k | unsigned char col[4]; |
1659 | 10.6k | WPSColor colors[2]; |
1660 | 10.6k | for (auto &color : colors) |
1661 | 21.3k | { |
1662 | 85.3k | for (auto &c : col) c=libwps::readU8(input); |
1663 | 21.3k | color=WPSColor(col[0],col[1],col[2]); |
1664 | 21.3k | } |
1665 | 10.6k | int fillType=int(libwps::readU16(input)); |
1666 | 10.6k | if (fillType==0) |
1667 | 5.91k | { |
1668 | 5.91k | font.m_color=colors[0]; |
1669 | 5.91k | } |
1670 | 4.75k | else if (fillType>=1 && fillType<=6) |
1671 | 1.39k | font.m_color=WPSColor::barycenter(0.5f, colors[0], 0.5f, colors[1]); |
1672 | 3.36k | else if ((fillType&0x8060)==0x8060) |
1673 | 306 | { |
1674 | 306 | font.m_color=colors[0]; |
1675 | 306 | f << "#3d[effect]=" << (fillType&0x7f9f) << ","; |
1676 | 306 | WPS_DEBUG_MSG(("QuattroGraph::readTextBox: find unimplemented 3d color\n")); |
1677 | 306 | } |
1678 | 3.05k | else |
1679 | 3.05k | { |
1680 | 3.05k | WPS_DEBUG_MSG(("QuattroGraph::readTextBox: find unimplemented fillType color\n")); |
1681 | 3.05k | f << "###fill[type]=" << std::hex << fillType << std::dec << ","; |
1682 | 3.05k | } |
1683 | 10.6k | f << font; |
1684 | 10.6k | val=int(libwps::read16(input)); |
1685 | 10.6k | if (val) f << "f1=" << val << ","; |
1686 | 10.6k | val=int(libwps::read16(input)); |
1687 | 10.6k | if (val) f << "box[width]=" << val << ","; // maybe type |
1688 | 10.6k | val=int(libwps::read16(input)); |
1689 | 10.6k | switch (val) |
1690 | 10.6k | { |
1691 | 6.60k | case 0: // left |
1692 | 6.60k | break; |
1693 | 840 | case 1: |
1694 | 840 | textbox->m_paragraph.m_justify=libwps::JustificationCenter; |
1695 | 840 | f << "center,"; |
1696 | 840 | break; |
1697 | 38 | case 2: |
1698 | 38 | textbox->m_paragraph.m_justify=libwps::JustificationRight; |
1699 | 38 | f << "right,"; |
1700 | 38 | break; |
1701 | 3.18k | default: |
1702 | 3.18k | WPS_DEBUG_MSG(("QuattroGraph::readTextBox: unknown alignment\n")); |
1703 | 3.18k | f << "###align=" << val << ","; |
1704 | 3.18k | break; |
1705 | 10.6k | } |
1706 | 53.3k | for (int i=0; i<4; ++i) // f3=1, f2=small number, f3=-1,f4=-1 |
1707 | 42.6k | { |
1708 | 42.6k | val=int(libwps::read16(input)); |
1709 | 42.6k | if (!val) continue; |
1710 | 22.8k | f << "f" << i+2 << "=" << val << ","; |
1711 | 22.8k | } |
1712 | 10.6k | val=int(libwps::read16(input)); |
1713 | 10.6k | if (val!=300) f << "tab[width]=" << float(val)/10.f << ","; // unsure about the unit 300=1inch, 390=1,3125 inch |
1714 | 10.6k | val=int(libwps::read16(input)); |
1715 | 10.6k | if (val) f << "g1=" << val << ","; |
1716 | 10.6k | int sSz=int(libwps::readU16(input)); |
1717 | 10.6k | if (input->tell()+sSz+14>endPos) |
1718 | 2.54k | { |
1719 | 2.54k | WPS_DEBUG_MSG(("QuattroGraph::readTextBox: can not read the last string\n")); |
1720 | 2.54k | f << "###"; |
1721 | 2.54k | ascFile.addPos(pos); |
1722 | 2.54k | ascFile.addNote(f.str().c_str()); |
1723 | 2.54k | return true; |
1724 | 2.54k | } |
1725 | 8.12k | text=""; |
1726 | 36.5k | for (int i=0; i<sSz; ++i) text+=char(libwps::readU8(input)); |
1727 | 8.12k | if (!text.empty()) f << text << ","; |
1728 | 64.9k | for (int i=0; i<7; ++i) // h0=0|2|1d,h3=0|2, h5=0|16a, h6=0|922c |
1729 | 56.8k | { |
1730 | 56.8k | val=int(libwps::read16(input)); |
1731 | 56.8k | if (val) f << "h" << i << "=" << val << ","; |
1732 | 56.8k | } |
1733 | 8.12k | long actPos=input->tell(); |
1734 | 8.12k | if (fillType && !readFillData(textbox->m_style, fillType, stream, endPos)) |
1735 | 3.49k | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
1736 | 8.12k | if (input->tell()!=endPos) |
1737 | 8.06k | { |
1738 | 8.06k | ascFile.addDelimiter(input->tell(),'|'); |
1739 | 8.06k | f << "##extra,"; |
1740 | 8.06k | WPS_DEBUG_MSG(("QuattroGraph::readTextBox: find extra data\n")); |
1741 | 8.06k | } |
1742 | 8.12k | if (parent && parent->m_type==parent->Shape) |
1743 | 470 | { |
1744 | 470 | parent->m_type=parent->Textbox; |
1745 | 470 | parent->m_textbox=textbox; |
1746 | 470 | } |
1747 | 8.12k | ascFile.addPos(pos); |
1748 | 8.12k | ascFile.addNote(f.str().c_str()); |
1749 | 8.12k | return true; |
1750 | 10.6k | } |
1751 | | //////////////////////////////////////////////////////////// |
1752 | | // dialog |
1753 | | //////////////////////////////////////////////////////////// |
1754 | | bool QuattroGraph::readHeader(QuattroGraphInternal::Dialog &header, std::shared_ptr<WPSStream> stream, long endPos) |
1755 | 4.68k | { |
1756 | 4.68k | auto input=stream->m_input; |
1757 | 4.68k | long pos = input->tell(); |
1758 | 4.68k | if (endPos-pos<22) |
1759 | 0 | { |
1760 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readHeader: the zone is too short\n")); |
1761 | 0 | return false; |
1762 | 0 | } |
1763 | 23.4k | for (auto &fl : header.m_flags1) fl=int(libwps::readU16(input)); |
1764 | 4.68k | int dim[4]; |
1765 | 18.7k | for (auto &d: dim) d=libwps::readU16(input); |
1766 | 4.68k | header.m_cellBox=WPSBox2i(Vec2i(dim[0],dim[1]),Vec2i(dim[2],dim[3])); |
1767 | 42.1k | for (auto &fl : header.m_flags2) fl=int(libwps::readU8(input)); |
1768 | 4.68k | return true; |
1769 | 4.68k | } |
1770 | | |
1771 | | bool QuattroGraph::readDialog(std::shared_ptr<WPSStream> stream) |
1772 | 4.27k | { |
1773 | 4.27k | RVNGInputStreamPtr input = stream->m_input; |
1774 | 4.27k | libwps::DebugFile &ascFile=stream->m_ascii; |
1775 | 4.27k | libwps::DebugStream f; |
1776 | 4.27k | long pos = input->tell(); |
1777 | 4.27k | auto type = int(libwps::readU16(input)&0x7fff); |
1778 | | |
1779 | 4.27k | if (type != 0x35e) |
1780 | 0 | { |
1781 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readDialog: unknown id\n")); |
1782 | 0 | return false; |
1783 | 0 | } |
1784 | 4.27k | auto sz = long(libwps::readU16(input)); |
1785 | 4.27k | long endPos=pos+4+sz; |
1786 | 4.27k | QuattroGraphInternal::Dialog dialog; |
1787 | 4.27k | if (sz<65 || !readHeader(dialog,stream,endPos)) |
1788 | 265 | { |
1789 | 265 | if (sz) |
1790 | 134 | { |
1791 | 134 | WPS_DEBUG_MSG(("QuattroGraph::readDialog: size seems very bad\n")); |
1792 | 134 | f << "###"; |
1793 | 134 | } |
1794 | 265 | ascFile.addPos(pos); |
1795 | 265 | ascFile.addNote(f.str().c_str()); |
1796 | 265 | return true; |
1797 | 265 | } |
1798 | 4.00k | f << dialog << ","; |
1799 | 4.00k | int val; |
1800 | 16.0k | for (int i=0; i<3; ++i) // f1=0|-256, f2=-1 |
1801 | 12.0k | { |
1802 | 12.0k | val=int(libwps::read16(input)); |
1803 | 12.0k | if (val) |
1804 | 7.08k | f << "f" << i << "=" << val <<","; |
1805 | 12.0k | } |
1806 | 16.0k | for (int i=0; i<3; ++i) // 0 |
1807 | 12.0k | { |
1808 | 12.0k | val=int(libwps::read16(input)); |
1809 | 12.0k | if (val) |
1810 | 5.25k | f << "f" << i+4 << "=" << val <<","; |
1811 | 12.0k | } |
1812 | 4.00k | val=int(libwps::readU16(input)); |
1813 | 4.00k | if (val!=0x100) |
1814 | 3.59k | f << "f7=" << std::hex << val << std::dec << ","; |
1815 | 4.00k | auto sSz=int(libwps::readU16(input)); |
1816 | 4.00k | librevenge::RVNGString text; |
1817 | 4.00k | if (input->tell()+sSz+7+15>endPos || !m_mainParser.readCString(stream,text,sSz)) |
1818 | 1.19k | { |
1819 | 1.19k | WPS_DEBUG_MSG(("QuattroGraph::readDialog: can not read string1\n")); |
1820 | 1.19k | f << "##sSz,"; |
1821 | 1.19k | ascFile.addPos(pos); |
1822 | 1.19k | ascFile.addNote(f.str().c_str()); |
1823 | 1.19k | return true; |
1824 | 1.19k | } |
1825 | 2.80k | f << text.cstr() << ","; // find Dialog1... |
1826 | 2.80k | val=int(libwps::readU8(input)); |
1827 | 2.80k | if (val!=0x1) |
1828 | 1.93k | f << "f9=" << val << ","; |
1829 | 2.80k | sSz=int(libwps::readU16(input)); |
1830 | 2.80k | if (sSz<4 || input->tell()+sSz+15>endPos || (sz>4 && !m_mainParser.readCString(stream,text,sSz-4))) |
1831 | 2.28k | { |
1832 | 2.28k | WPS_DEBUG_MSG(("QuattroGraph::readDialog: can not read string1\n")); |
1833 | 2.28k | f << "##sSz2,"; |
1834 | 2.28k | ascFile.addPos(pos); |
1835 | 2.28k | ascFile.addNote(f.str().c_str()); |
1836 | 2.28k | return true; |
1837 | 2.28k | } |
1838 | 525 | if (!text.empty()) // find Enter ... |
1839 | 52 | f << text.cstr() << ","; |
1840 | 1.57k | for (int i=0; i<2; ++i) // 0 |
1841 | 1.05k | { |
1842 | 1.05k | val=int(libwps::read16(input)); |
1843 | 1.05k | if (!val) continue; |
1844 | 495 | f << "g" << i << "=" << val << ","; |
1845 | 495 | } |
1846 | 525 | if (input->tell()!=endPos) // then some flags |
1847 | 525 | ascFile.addDelimiter(input->tell(),'|'); |
1848 | 525 | static bool first=true; |
1849 | 525 | if (first) |
1850 | 4 | { |
1851 | 4 | first=false; |
1852 | 4 | WPS_DEBUG_MSG(("QuattroGraph::readDialog: this file contains some dialogs, there will not be recovered\n")); |
1853 | 4 | } |
1854 | 525 | ascFile.addPos(pos); |
1855 | 525 | ascFile.addNote(f.str().c_str()); |
1856 | 525 | return true; |
1857 | 2.80k | } |
1858 | | |
1859 | | bool QuattroGraph::readDialogUnknown(std::shared_ptr<WPSStream> stream) |
1860 | 8.45k | { |
1861 | 8.45k | RVNGInputStreamPtr input = stream->m_input; |
1862 | 8.45k | libwps::DebugFile &ascFile=stream->m_ascii; |
1863 | 8.45k | libwps::DebugStream f; |
1864 | 8.45k | long pos = input->tell(); |
1865 | 8.45k | auto type = int(libwps::readU16(input)&0x7fff); |
1866 | | |
1867 | 8.45k | if (type<0x330 || type>0x380) |
1868 | 0 | { |
1869 | 0 | WPS_DEBUG_MSG(("QuattroGraph::readDialogUnknown: unknown id\n")); |
1870 | 0 | return false; |
1871 | 0 | } |
1872 | 8.45k | auto sz = long(libwps::readU16(input)); |
1873 | 8.45k | long endPos=pos+4+sz; |
1874 | 8.45k | QuattroGraphInternal::Dialog dialog; |
1875 | 8.45k | if (sz<38 || !readHeader(dialog,stream,endPos)) |
1876 | 7.78k | { |
1877 | 7.78k | if (sz) |
1878 | 1.08k | { |
1879 | 1.08k | WPS_DEBUG_MSG(("QuattroGraph::readDialogUnknown: size seems very bad\n")); |
1880 | 1.08k | f << "###"; |
1881 | 1.08k | } |
1882 | 7.78k | ascFile.addPos(pos); |
1883 | 7.78k | ascFile.addNote(f.str().c_str()); |
1884 | 7.78k | return true; |
1885 | 7.78k | } |
1886 | 673 | if (dialog.m_flags2[8]&0x80) |
1887 | 261 | { |
1888 | 261 | f << "select,"; |
1889 | 261 | dialog.m_flags2[8]&=0x7f; |
1890 | 261 | } |
1891 | 673 | f << dialog << ","; |
1892 | 673 | auto fl=int(libwps::readU8(input)); // [0128][08ac] |
1893 | 673 | if (fl&1) f << "has[frame],"; |
1894 | 673 | fl &= 0xfe; |
1895 | 673 | if (fl) f << "flag=" << std::hex << fl << std::dec << ","; |
1896 | 673 | auto id=int(libwps::readU16(input)); |
1897 | 673 | f << "id=" << id << ","; |
1898 | 673 | unsigned char col[3]; |
1899 | 2.01k | for (auto &c : col) c=libwps::readU8(input); |
1900 | 673 | f << "col=" << WPSColor(col[0],col[1],col[2]) << ","; |
1901 | 673 | f << "fl3=["; |
1902 | 4.03k | for (int i=0; i<5; ++i) // 0 |
1903 | 3.36k | { |
1904 | 3.36k | auto val=int(libwps::readU8(input)); |
1905 | 3.36k | if (val) |
1906 | 2.10k | f << std::hex << val << std::dec << ","; |
1907 | 1.26k | else |
1908 | 1.26k | f << "_,"; |
1909 | 3.36k | } |
1910 | 673 | f << "],"; |
1911 | 673 | if (input->tell()!=endPos) // then some flags |
1912 | 505 | ascFile.addDelimiter(input->tell(),'|'); |
1913 | 673 | ascFile.addPos(pos); |
1914 | 673 | ascFile.addNote(f.str().c_str()); |
1915 | 673 | return true; |
1916 | 8.45k | } |
1917 | | |
1918 | | //////////////////////////////////////////////////////////// |
1919 | | // send data |
1920 | | //////////////////////////////////////////////////////////// |
1921 | | bool QuattroGraph::sendGraphics(int sheetId, Vec2i const &cell) const |
1922 | 7.07k | { |
1923 | 7.07k | if (!m_listener) |
1924 | 0 | { |
1925 | 0 | WPS_DEBUG_MSG(("QuattroGraph::sendGraphics: can not find the listener\n")); |
1926 | 0 | return false; |
1927 | 0 | } |
1928 | 7.07k | auto it=m_state->m_sheetIdToGraphMap.find(sheetId); |
1929 | 7.07k | bool find=false; |
1930 | 404k | while (it!=m_state->m_sheetIdToGraphMap.end() && it->first==sheetId) |
1931 | 397k | { |
1932 | 397k | auto const &graph=it++->second; |
1933 | 397k | if (!graph || graph->m_cellBox[0]!=cell) continue; |
1934 | 28.5k | sendGraphic(*graph); |
1935 | 28.5k | find=true; |
1936 | 28.5k | } |
1937 | 7.07k | if (!find) |
1938 | 0 | { |
1939 | 0 | WPS_DEBUG_MSG(("QuattroGraph::sendGraphics: sorry, can not find any graph\n")); |
1940 | 0 | } |
1941 | 7.07k | return find; |
1942 | 7.07k | } |
1943 | | |
1944 | | bool QuattroGraph::sendPageGraphics(int sheetId) const |
1945 | 641k | { |
1946 | 693k | for (auto it=m_state->m_sheetIdToGraphMap.lower_bound(sheetId); it!=m_state->m_sheetIdToGraphMap.upper_bound(sheetId); ++it) |
1947 | 51.7k | { |
1948 | 51.7k | auto const &graph=it->second; |
1949 | 51.7k | if (!graph) continue; |
1950 | 51.7k | if (graph->m_type==graph->Shape) |
1951 | 11.3k | sendShape(*graph, sheetId); |
1952 | 51.7k | if (graph->m_type==graph->Textbox) |
1953 | 415 | sendTextbox(*graph, sheetId); |
1954 | 51.7k | } |
1955 | 641k | return true; |
1956 | 641k | } |
1957 | | |
1958 | | bool QuattroGraph::sendGraphic(QuattroGraphInternal::Graph const &graph) const |
1959 | 28.5k | { |
1960 | 28.5k | if (!m_listener) |
1961 | 0 | { |
1962 | 0 | WPS_DEBUG_MSG(("QuattroGraph::sendGraphic: can not find the listener\n")); |
1963 | 0 | return false; |
1964 | 0 | } |
1965 | 28.5k | WPSPosition pos(graph.m_cellBoxDecal[0], graph.m_size, librevenge::RVNG_POINT); |
1966 | 28.5k | pos.m_anchorTo = WPSPosition::Cell; |
1967 | 28.5k | pos.m_anchorCellName = libwps::getCellName(graph.m_cellBox[1]+Vec2i(1,1)).c_str(); |
1968 | 28.5k | if (graph.m_type==graph.OLE) |
1969 | 21.8k | { |
1970 | 21.8k | if (!graph.m_linkName.empty()) |
1971 | 1.93k | { |
1972 | 1.93k | auto it=m_state->m_linkNameToObjectMap.find(graph.m_linkName); |
1973 | 1.93k | if (it==m_state->m_linkNameToObjectMap.end() || it->second.isEmpty()) |
1974 | 1.84k | { |
1975 | 1.84k | WPS_DEBUG_MSG(("QuattroGraph::sendGraphic: can not find ole %s\n", graph.m_linkName.cstr())); |
1976 | 1.84k | } |
1977 | 87 | else |
1978 | 87 | m_listener->insertObject(pos, it->second); |
1979 | 1.93k | } |
1980 | 19.8k | else if (graph.m_ole.isEmpty()) |
1981 | 19.7k | { |
1982 | 19.7k | WPS_DEBUG_MSG(("QuattroGraph::sendGraphic: find an empty ole\n")); |
1983 | 19.7k | } |
1984 | 85 | else |
1985 | 85 | m_listener->insertObject(pos, graph.m_ole); |
1986 | 21.8k | return true; |
1987 | 21.8k | } |
1988 | 6.75k | if (graph.m_type==graph.Button) |
1989 | 959 | { |
1990 | 959 | if (graph.m_label.empty()) |
1991 | 82 | { |
1992 | 82 | WPS_DEBUG_MSG(("QuattroGraph::sendGraphic: find an empty label\n")); |
1993 | 82 | } |
1994 | 877 | else |
1995 | 877 | { |
1996 | 877 | WPSGraphicStyle style; |
1997 | 877 | style.setBackgroundColor(WPSColor(128,128,128)); |
1998 | 877 | auto doc=std::make_shared<QuattroGraphInternal::SubDocument>(const_cast<QuattroGraph &>(*this),graph.m_label); |
1999 | 877 | m_listener->insertTextBox(pos, doc, style); |
2000 | 877 | } |
2001 | 959 | return true; |
2002 | 959 | } |
2003 | 5.79k | static bool first=true; |
2004 | 5.79k | if (first) |
2005 | 5 | { |
2006 | 5 | first=false; |
2007 | 5 | WPS_DEBUG_MSG(("QuattroGraph::sendGraphic: sorry, unexpected graph type\n")); |
2008 | 5 | } |
2009 | 5.79k | return true; |
2010 | 6.75k | } |
2011 | | |
2012 | | bool QuattroGraph::sendShape(QuattroGraphInternal::Graph const &graph, int sheetId) const |
2013 | 11.3k | { |
2014 | 11.3k | if (!m_listener) |
2015 | 0 | { |
2016 | 0 | WPS_DEBUG_MSG(("QuattroGraph::sendShape: can not find the listener\n")); |
2017 | 0 | return false; |
2018 | 0 | } |
2019 | 11.3k | if (graph.m_type!=graph.Shape || !graph.m_shape) |
2020 | 11.0k | { |
2021 | 11.0k | WPS_DEBUG_MSG(("QuattroGraph::sendShape: can not find the shape\n")); |
2022 | 11.0k | return false; |
2023 | 11.0k | } |
2024 | 287 | auto const &shape=*graph.m_shape; |
2025 | 287 | WPSPosition pos(graph.m_cellBoxDecal[0]+m_mainParser.getCellPosition(sheetId, graph.m_cellBox[0]), graph.m_size, librevenge::RVNG_POINT); |
2026 | 287 | pos.m_anchorTo = WPSPosition::Page; |
2027 | 287 | auto gShape=shape.m_shape; |
2028 | 287 | auto bdBoxSize=gShape.getBdBox().size(); |
2029 | 287 | gShape.scale(Vec2f(bdBoxSize[0]>0 ? float(graph.m_size[0])/bdBoxSize[0] : 1.f, bdBoxSize[1]>0 ? float(graph.m_size[1])/bdBoxSize[1] : 1.f)); |
2030 | 287 | m_listener->insertPicture(pos, gShape, shape.m_style); |
2031 | 287 | return true; |
2032 | 11.3k | } |
2033 | | |
2034 | | bool QuattroGraph::sendTextbox(QuattroGraphInternal::Graph const &graph, int sheetId) const |
2035 | 415 | { |
2036 | 415 | if (!m_listener) |
2037 | 0 | { |
2038 | 0 | WPS_DEBUG_MSG(("QuattroGraph::sendTextbox: can not find the listener\n")); |
2039 | 0 | return false; |
2040 | 0 | } |
2041 | 415 | if (graph.m_type!=graph.Textbox || !graph.m_textbox) |
2042 | 0 | { |
2043 | 0 | WPS_DEBUG_MSG(("QuattroGraph::sendTextbox: can not find the textbox\n")); |
2044 | 0 | return false; |
2045 | 0 | } |
2046 | 415 | auto const &textbox=*graph.m_textbox; |
2047 | 415 | WPSPosition pos(graph.m_cellBoxDecal[0]+m_mainParser.getCellPosition(sheetId, graph.m_cellBox[0]), graph.m_size, librevenge::RVNG_POINT); |
2048 | 415 | pos.m_anchorTo = WPSPosition::Page; |
2049 | 415 | auto doc=std::make_shared<QuattroGraphInternal::SubDocument>(const_cast<QuattroGraph &>(*this),graph.m_textbox, graph.m_stream); |
2050 | 415 | m_listener->insertTextBox(pos, doc, textbox.m_style); |
2051 | 415 | return true; |
2052 | 415 | } |
2053 | | |
2054 | | bool QuattroGraph::send(QuattroGraphInternal::Textbox const &textbox, std::shared_ptr<WPSStream> stream) const |
2055 | 415 | { |
2056 | 415 | if (!m_listener) |
2057 | 0 | { |
2058 | 0 | WPS_DEBUG_MSG(("QuattroGraph::send: can not find the listener\n")); |
2059 | 0 | return false; |
2060 | 0 | } |
2061 | 415 | if (!stream || !textbox.m_entry.valid()) |
2062 | 51 | { |
2063 | 51 | WPS_DEBUG_MSG(("QuattroGraph::send: can not find the file stream\n")); |
2064 | 51 | return false; |
2065 | 51 | } |
2066 | 364 | m_listener->setFont(textbox.m_font); |
2067 | 364 | m_listener->setParagraph(textbox.m_paragraph); |
2068 | 364 | auto input=stream->m_input; |
2069 | 364 | input->seek(textbox.m_entry.begin(), librevenge::RVNG_SEEK_SET); |
2070 | 364 | auto fontType = m_mainParser.getDefaultFontType(); |
2071 | 364 | std::string text; |
2072 | 16.2k | for (long l=0; l<=textbox.m_entry.length(); ++l) |
2073 | 16.2k | { |
2074 | 16.2k | auto c=l==textbox.m_entry.length() ? '\0' : char(libwps::readU8(input)); |
2075 | 16.2k | if ((c==0 || c==0x9 || c==0xd) && !text.empty()) |
2076 | 1.92k | { |
2077 | 1.92k | m_listener->insertUnicodeString(libwps_tools_win::Font::unicodeString(text, fontType)); |
2078 | 1.92k | text.clear(); |
2079 | 1.92k | } |
2080 | 16.2k | if (l==textbox.m_entry.length()) break; |
2081 | 15.9k | if (c==0xd) |
2082 | 171 | m_listener->insertEOL(); |
2083 | 15.7k | else if (c==0x9) |
2084 | 972 | m_listener->insertTab(); |
2085 | 14.7k | else if (c) |
2086 | 8.53k | text.push_back(c); |
2087 | 15.9k | } |
2088 | 364 | return true; |
2089 | 415 | } |
2090 | | |
2091 | | /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */ |