1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2
3 /* libmwaw
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 <cmath>
35 #include <iomanip>
36 #include <iostream>
37 #include <limits>
38 #include <map>
39 #include <sstream>
40
41 #include <librevenge/librevenge.h>
42
43 #include "MWAWTextListener.hxx"
44 #include "MWAWPictData.hxx"
45 #include "MWAWPosition.hxx"
46 #include "MWAWSubDocument.hxx"
47
48 #include "FullWrtParser.hxx"
49 #include "FullWrtStruct.hxx"
50
51 #include "FullWrtGraph.hxx"
52
53 /** Internal: the structures of a FullWrtGraph */
54 namespace FullWrtGraphInternal
55 {
56 ////////////////////////////////////////
57 //! Internal: the sidebar of a FullWrtGraph
58 struct SideBar final : public FullWrtStruct::ZoneHeader {
59 //! constructor
SideBarFullWrtGraphInternal::SideBar60 explicit SideBar(FullWrtStruct::ZoneHeader const &header): FullWrtStruct::ZoneHeader(header), m_box(), m_page(0), m_borderId(0), m_parsed(false)
61 {
62 }
63 //! destructor
64 ~SideBar() final;
65 //! the position (in point)
66 MWAWBox2f m_box;
67 //! the page
68 int m_page;
69 //! the border id
70 int m_borderId;
71 //! a flag to know if the sidebar is send to the listener
72 mutable bool m_parsed;
73 };
74
~SideBar()75 SideBar::~SideBar()
76 {
77 }
78
79 ////////////////////////////////////////
80 //! Internal: the state of a FullWrtGraph
81 struct State {
82 //! constructor
StateFullWrtGraphInternal::State83 State()
84 : m_version(-1)
85 , m_sidebarList()
86 , m_graphicMap()
87 , m_borderList()
88 , m_numPages(-1) { }
89
90 //! the file version
91 mutable int m_version;
92 //! the sidebar list
93 std::vector<std::shared_ptr<SideBar> > m_sidebarList;
94 //! zoneId -> graphic entry
95 std::multimap<int, FullWrtStruct::EntryPtr > m_graphicMap;
96 //! a list of border
97 std::vector<FullWrtStruct::Border> m_borderList;
98 int m_numPages /* the number of pages */;
99 };
100
101 ////////////////////////////////////////
102 //! Internal: the subdocument of a FullWrtGraph
103 class SubDocument final : public MWAWSubDocument
104 {
105 public:
106 //! constructor
SubDocument(FullWrtGraph & pars,int id,MWAWColor fontColor)107 SubDocument(FullWrtGraph &pars, int id, MWAWColor fontColor)
108 : MWAWSubDocument(pars.m_mainParser, MWAWInputStreamPtr(), MWAWEntry())
109 , m_graphParser(&pars)
110 , m_id(id)
111 , m_fontColor(fontColor) {}
112
113 //! destructor
~SubDocument()114 ~SubDocument() final {}
115
116 //! operator!=
117 bool operator!=(MWAWSubDocument const &doc) const final;
118
119 //! the parser function
120 void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final;
121
122 protected:
123 /** the graph parser */
124 FullWrtGraph *m_graphParser;
125 //! the zone file id
126 int m_id;
127 //! the default font color
128 MWAWColor m_fontColor;
129
130 private:
131 SubDocument(SubDocument const &orig) = delete;
132 SubDocument &operator=(SubDocument const &orig) = delete;
133 };
134
parse(MWAWListenerPtr & listener,libmwaw::SubDocumentType)135 void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/)
136 {
137 if (!listener.get()) {
138 MWAW_DEBUG_MSG(("FullWrtGraphInternal::SubDocument::parse: no listener\n"));
139 return;
140 }
141 if (!m_graphParser) {
142 MWAW_DEBUG_MSG(("FullWrtGraphInternal::SubDocument::parse: no graph parser\n"));
143 return;
144 }
145 m_graphParser->send(m_id, m_fontColor);
146 }
147
operator !=(MWAWSubDocument const & doc) const148 bool SubDocument::operator!=(MWAWSubDocument const &doc) const
149 {
150 if (MWAWSubDocument::operator!=(doc)) return true;
151 auto const *sDoc = dynamic_cast<SubDocument const *>(&doc);
152 if (!sDoc) return true;
153 if (m_graphParser != sDoc->m_graphParser) return true;
154 if (m_id != sDoc->m_id) return true;
155 if (m_fontColor != sDoc->m_fontColor) return true;
156 return false;
157 }
158 }
159
160 ////////////////////////////////////////////////////////////
161 // constructor/destructor, ...
162 ////////////////////////////////////////////////////////////
FullWrtGraph(FullWrtParser & parser)163 FullWrtGraph::FullWrtGraph(FullWrtParser &parser)
164 : m_parserState(parser.getParserState())
165 , m_state(new FullWrtGraphInternal::State)
166 , m_mainParser(&parser)
167 {
168 }
169
~FullWrtGraph()170 FullWrtGraph::~FullWrtGraph()
171 {
172 }
173
version() const174 int FullWrtGraph::version() const
175 {
176 if (m_state->m_version < 0)
177 m_state->m_version = m_parserState->m_version;
178 return m_state->m_version;
179 }
180
numPages() const181 int FullWrtGraph::numPages() const
182 {
183 if (m_state->m_numPages > 0)
184 return m_state->m_numPages;
185 int nPage=0;
186 for (auto sidebar : m_state->m_sidebarList) {
187 if (!sidebar)
188 continue;
189 if (sidebar->m_page>nPage)
190 nPage=sidebar->m_page;
191 }
192 return (m_state->m_numPages=nPage);
193 }
194
getBorder(int bId,FullWrtStruct::Border & border) const195 bool FullWrtGraph::getBorder(int bId, FullWrtStruct::Border &border) const
196 {
197 if (bId < 0 || bId>= int(m_state->m_borderList.size())) {
198 MWAW_DEBUG_MSG(("FullWrtGraph::getBorder: can not find border %d\n", bId));
199 border=FullWrtStruct::Border();
200 return false;
201 }
202 border=m_state->m_borderList[size_t(bId)];
203 return true;
204 }
205
send(int fileId,MWAWColor const & fontColor)206 bool FullWrtGraph::send(int fileId, MWAWColor const &fontColor)
207 {
208 return m_mainParser->send(fileId, fontColor);
209 }
210
211 ////////////////////////////////////////////////////////////
212 //
213 // Intermediate level
214 //
215 ////////////////////////////////////////////////////////////
216
217 ////////////////////////////////////////////////////////////
218 // low level
219 ////////////////////////////////////////////////////////////
220
221 ////////////////////////////////////////////////////////////
222 // border
readBorderDocInfo(FullWrtStruct::EntryPtr zone)223 bool FullWrtGraph::readBorderDocInfo(FullWrtStruct::EntryPtr zone)
224 {
225 MWAWInputStreamPtr input = zone->m_input;
226 libmwaw::DebugFile &asciiFile = zone->getAsciiFile();
227 libmwaw::DebugStream f;
228 long pos = input->tell();
229 if (input->readULong(4)!=0x626f7264 || input->readULong(1)) {
230 input->seek(pos, librevenge::RVNG_SEEK_SET);
231 return false;
232 }
233
234 long blckSz = input->readLong(4);
235 long endData = pos+9+blckSz;
236 auto num = static_cast<int>(input->readULong(2));
237 int const fSz = 26;
238 f << "Entries(Border):N=" << num << ",";
239 if (blckSz < 2 || blckSz != 2 + num*fSz || endData > zone->end()) {
240 MWAW_DEBUG_MSG(("FullWrtGraph::readBorderDocInfo: problem reading the data block or the number of data\n"));
241 f << "###";
242 asciiFile.addPos(pos);
243 asciiFile.addNote(f.str().c_str());
244 if (endData <= zone->end()) {
245 input->seek(endData, librevenge::RVNG_SEEK_SET);
246 return true;
247 }
248 input->seek(pos, librevenge::RVNG_SEEK_SET);
249 return false;
250 }
251
252 asciiFile.addPos(pos);
253 asciiFile.addNote(f.str().c_str());
254
255 m_state->m_borderList.push_back(FullWrtStruct::Border());
256 for (int i = 0; i < num; i++) {
257 pos = input->tell();
258 FullWrtStruct::Border mod;
259 f.str("");
260 f << "Border-B" << i << ":";
261 if (!mod.read(zone, fSz))
262 f << "###";
263 else
264 f << mod;
265 m_state->m_borderList.push_back(mod);
266 asciiFile.addPos(pos);
267 asciiFile.addNote(f.str().c_str());
268 input->seek(pos+fSz, librevenge::RVNG_SEEK_SET);
269 }
270 return true;
271 }
272
273 ////////////////////////////////////////////////////////////
274 // side bar
readSideBar(FullWrtStruct::EntryPtr zone,FullWrtStruct::ZoneHeader const & doc)275 std::shared_ptr<FullWrtStruct::ZoneHeader> FullWrtGraph::readSideBar(FullWrtStruct::EntryPtr zone, FullWrtStruct::ZoneHeader const &doc)
276 {
277 std::shared_ptr<FullWrtGraphInternal::SideBar> sidebar;
278 if (doc.m_type != 0x13 && doc.m_type != 0x14) {
279 MWAW_DEBUG_MSG(("FullWrtGraph::readSideBar: find unexpected type\n"));
280 return sidebar;
281 }
282 MWAWInputStreamPtr input = zone->m_input;
283 long pos = input->tell();
284 sidebar.reset(new FullWrtGraphInternal::SideBar(doc));
285 if (!sidebar->read(zone)) {
286 input->seek(pos, librevenge::RVNG_SEEK_SET);
287 sidebar.reset();
288 return sidebar;
289 }
290
291 int val;
292 if (input->tell()+12 > zone->end()) {
293 input->seek(pos, librevenge::RVNG_SEEK_SET);
294 sidebar.reset();
295 return sidebar;
296 }
297
298 libmwaw::DebugFile &asciiFile = zone->getAsciiFile();
299 libmwaw::DebugStream f;
300 f << "Entries(SideBar):" << *sidebar;
301 asciiFile.addPos(pos);
302 asciiFile.addNote(f.str().c_str());
303
304 for (int i=0; i<3; ++i) {
305 pos = input->tell();
306 bool ok=false;
307 switch (i) {
308 case 0:
309 ok=readSideBarPosition(zone, *sidebar);
310 break;
311 case 1:
312 ok=readSideBarFormat(zone, *sidebar);
313 break;
314 case 2:
315 ok=readSideBarUnknown(zone, *sidebar);
316 break;
317 default:
318 break;
319 }
320 if (ok) continue;
321 MWAW_DEBUG_MSG(("FullWrtGraph::readSideBar: pb reading the zone %d\n", i));
322 f.str("");
323 static char const *wh[]= {"position","format","unknown"};
324 f << "SideBar[" << wh[i] << ":###";
325 asciiFile.addPos(pos);
326 asciiFile.addNote(f.str().c_str());
327
328 input->seek(pos, librevenge::RVNG_SEEK_SET);
329 return sidebar;
330 }
331
332 // checkme: can this exist for a sidebar ?
333 val = int(input->readLong(1));
334 if (val==1) {
335 pos = input->tell();
336 auto sz = long(input->readULong(4));
337 if (sz && input->tell()+sz <= zone->end()) {
338 f.str("");
339 f << "SideBar[end]:";
340 asciiFile.addPos(pos);
341 asciiFile.addNote(f.str().c_str());
342 input->seek(sz, librevenge::RVNG_SEEK_CUR);
343 }
344 else {
345 MWAW_DEBUG_MSG(("FullWrtGraph::readSideBar: find bad end data\n"));
346 input->seek(pos, librevenge::RVNG_SEEK_SET);
347 }
348 }
349 else if (val) {
350 MWAW_DEBUG_MSG(("FullWrtGraph::readSideBar: find bad end data(II)\n"));
351 }
352 m_state->m_sidebarList.push_back(sidebar);
353 return sidebar;
354 }
355
readSideBarPosition(FullWrtStruct::EntryPtr zone,FullWrtGraphInternal::SideBar & frame)356 bool FullWrtGraph::readSideBarPosition(FullWrtStruct::EntryPtr zone, FullWrtGraphInternal::SideBar &frame)
357 {
358 MWAWInputStreamPtr input = zone->m_input;
359 long pos = input->tell();
360 libmwaw::DebugFile &asciiFile = zone->getAsciiFile();
361 libmwaw::DebugStream f;
362
363 auto sz = long(input->readULong(4));
364 if (sz < 0 || pos+sz+4 > zone->end())
365 return false;
366 f << "SideBar[pos]:";
367
368 if (sz < 28) {
369 MWAW_DEBUG_MSG(("FullWrtGraph::readSideBarPosition: the size seems bad\n"));
370 f << "###";
371 input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
372 asciiFile.addPos(pos);
373 asciiFile.addNote(f.str().c_str());
374 return true;
375 }
376
377 int dim[4];
378 for (auto &d : dim) d=int(input->readLong(2));
379 frame.m_box=MWAWBox2f(MWAWVec2f(float(dim[1]),float(dim[0])),MWAWVec2f(float(dim[3]),float(dim[2])));
380 f << "pos=" << frame.m_box << ",";
381 auto val=int(input->readLong(2));
382 if (val) f << "w[wrap]=" << val << "pt,";
383 f << "ptr?=[" << std::hex;
384 for (int i = 0; i < 2; i++) // two big number
385 f << input->readULong(4) << ",";
386 f << std::dec << "],";
387 val = int(input->readLong(2)); // seems related to floating point position
388 if (val) f << "unkn=" << std::hex << val << std::dec << ",";// 0|441|442|f91|16ac
389 val = int(input->readLong(2)); // always 0?
390 if (val) f << "f0=" << val << ",";
391 frame.m_page = int(input->readLong(2));
392 if (frame.m_page) f << "page=" << frame.m_page << ",";
393 val = int(input->readLong(2)); // number of point in the left part
394 if (val) f << "N[left]?=" << val << ",";
395 auto N=static_cast<int>(input->readLong(2));
396 if (N*4+28 > sz) {
397 f << "#N=" << N << ",";
398 N=0;
399 }
400 else
401 f << "N=" << N << ",";
402
403 /* probably first the left margin: (x_i,n): meaning to add n times
404 a point at x, then the same thing for the right margins
405 -16000/16000=no point (left/right)
406 */
407 f << "mask=[";
408 for (int i = 0; i < N; i++) {
409 auto x = int(input->readLong(2));
410 auto n = int(input->readLong(2));
411 f << x << ":" << n << ",";
412 }
413 f << "],";
414 if (input->tell() != pos+4+sz) {
415 asciiFile.addDelimiter(input->tell(),'|');
416 input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
417 }
418 asciiFile.addPos(pos);
419 asciiFile.addNote(f.str().c_str());
420 return true;
421 }
422
readSideBarFormat(FullWrtStruct::EntryPtr zone,FullWrtGraphInternal::SideBar & frame)423 bool FullWrtGraph::readSideBarFormat(FullWrtStruct::EntryPtr zone, FullWrtGraphInternal::SideBar &frame)
424 {
425 int const vers=version();
426 MWAWInputStreamPtr input = zone->m_input;
427 long pos = input->tell();
428 libmwaw::DebugFile &asciiFile = zone->getAsciiFile();
429 libmwaw::DebugStream f;
430
431 auto sz = long(input->readULong(4));
432 if (sz < 0 || pos+sz+4 > zone->end())
433 return false;
434 f << "SideBar[format]:";
435 if ((vers==1&&sz!=0x3a)||(vers==2&&sz!=0x38)) {
436 MWAW_DEBUG_MSG(("FullWrtGraph::readSideBarFormat: the size seems bad\n"));
437 f << "###";
438 input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
439 asciiFile.addPos(pos);
440 asciiFile.addNote(f.str().c_str());
441 return true;
442 }
443 f << "PTR=" << std::hex << input->readLong(4) << std::dec << ",";
444 auto N=static_cast<int>(input->readLong(1));
445 int val;
446 if (N) {
447 f << "N=" << N << ",";
448 val=static_cast<int>(input->readLong(1));
449 if (val) f << "#f0=" << val << ",";
450 /* now probably N*[unknData],
451 find for N=1 005f000000b201d2001600f40f94020004100001009700000000000000000000
452 */
453 }
454 input->seek(pos+42, librevenge::RVNG_SEEK_SET);
455 float dim[2];
456 for (auto &d : dim) d=float(input->readLong(4))/65536.f;
457 f << "dim?=" << dim[1] << "x" << dim[0] << ",";
458 val=static_cast<int>(input->readULong(2)); // another dim with a flag?
459 if (val&0x8000) f << "f1[high],";
460 if (val&0x7FFF) f << "f1=" << (val&0x7FFF) << ",";
461 float w=float(input->readLong(4))/65536.f;
462 f << "w[wrap]=" << w << "pt,";
463 frame.m_borderId=static_cast<int>(input->readLong(2));
464 if (frame.m_borderId)
465 f << "B" << frame.m_borderId-1 << ",";
466 if (vers==1) {
467 val=static_cast<int>(input->readLong(2)); // 0|1|4|b|20|..f0
468 if (val) f << "f2=" << val << ",";
469 }
470 val=static_cast<int>(input->readLong(2)); // always 0
471 if (val)
472 f << "f3=" << val << ",";
473
474 if (input->tell() != pos+4+sz) {
475 asciiFile.addDelimiter(input->tell(),'|');
476 input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
477 }
478 asciiFile.addPos(pos);
479 asciiFile.addNote(f.str().c_str());
480 return true;
481 }
482
readSideBarUnknown(FullWrtStruct::EntryPtr zone,FullWrtGraphInternal::SideBar &)483 bool FullWrtGraph::readSideBarUnknown(FullWrtStruct::EntryPtr zone, FullWrtGraphInternal::SideBar &/*frame*/)
484 {
485 MWAWInputStreamPtr input = zone->m_input;
486 long pos = input->tell();
487 libmwaw::DebugFile &asciiFile = zone->getAsciiFile();
488 libmwaw::DebugStream f;
489
490 auto sz = long(input->readULong(4));
491 if (sz < 0 || pos+sz+4 > zone->end())
492 return false;
493 f << "SideBar[unknown]:";
494 if (sz!=0x30) {
495 MWAW_DEBUG_MSG(("FullWrtGraph::readSideBarUnknown: the size seems bad\n"));
496 f << "###";
497 input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
498 asciiFile.addPos(pos);
499 asciiFile.addNote(f.str().c_str());
500 return true;
501 }
502 auto val = static_cast<int>(input->readLong(2));
503 if (val!=-1)
504 f << "f0=" << val << ",";
505 val = static_cast<int>(input->readLong(2));
506 if (val!=1)
507 f << "f1=" << val << ",";
508 val = static_cast<int>(input->readULong(2)); // maybe a color?
509 if (val)
510 f << "f2=" << std::hex << val << std::dec << ",";
511 for (int i=0; i<2; ++i) { // f3=1|2, f4=small numer 0..ff
512 val = static_cast<int>(input->readULong(2));
513 if (val)
514 f << "f" << i+3 << "=" << val << ",";
515 }
516 for (int i=0; i<19; ++i) { // g0,g1,g17,g18: in form xyxy, other 0
517 val = static_cast<int>(input->readULong(2));
518 if (val)
519 f << "g" << i << "=" << std::hex << val << std::dec << ",";
520 }
521 if (input->tell() != pos+4+sz) {
522 asciiFile.addDelimiter(input->tell(),'|');
523 input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
524 }
525 asciiFile.addPos(pos);
526 asciiFile.addNote(f.str().c_str());
527 return true;
528 }
529
sendSideBar(FullWrtGraphInternal::SideBar const & frame)530 bool FullWrtGraph::sendSideBar(FullWrtGraphInternal::SideBar const &frame)
531 {
532 MWAWTextListenerPtr listener=m_parserState->m_textListener;
533 if (!listener) {
534 MWAW_DEBUG_MSG(("FullWrtGraph::sendSideBar can not find the listener\n"));
535 return true;
536 }
537
538 frame.m_parsed=true;
539 MWAWPosition pos(frame.m_box[0]+72.f*m_mainParser->getPageLeftTop(),
540 frame.m_box.size(),librevenge::RVNG_POINT);
541 pos.setPage(frame.m_page>0 ? frame.m_page : 1);
542 pos.setRelativePosition(MWAWPosition::Page);
543 pos.m_wrapping=(frame.m_wrapping==3) ?
544 MWAWPosition::WBackground : MWAWPosition::WDynamic;
545 FullWrtStruct::Border border;
546 MWAWGraphicStyle style;
547 if (frame.m_borderId && getBorder(frame.m_borderId, border))
548 border.addTo(style);
549 MWAWSubDocumentPtr doc(new FullWrtGraphInternal::SubDocument(*this,frame.m_fileId,border.m_frontColor));
550 listener->insertTextBox(pos, doc, style);
551 return true;
552 }
553
554 ////////////////////////////////////////////////////////////
555 // graphic: data +
readGraphicData(FullWrtStruct::EntryPtr zone,FullWrtStruct::ZoneHeader & doc)556 std::shared_ptr<FullWrtStruct::ZoneHeader> FullWrtGraph::readGraphicData(FullWrtStruct::EntryPtr zone, FullWrtStruct::ZoneHeader &doc)
557 {
558 std::shared_ptr<FullWrtStruct::ZoneHeader> graphData;
559 if (doc.m_type != 0x15) {
560 MWAW_DEBUG_MSG(("FullWrtGraph::readGraphicData: find unexpected type\n"));
561 return graphData;
562 }
563 MWAWInputStreamPtr input = zone->m_input;
564 long pos = input->tell();
565 if (!doc.read(zone)) {
566 input->seek(pos, librevenge::RVNG_SEEK_SET);
567 return graphData;
568 }
569
570 int const vers = version();
571 libmwaw::DebugFile &asciiFile = zone->getAsciiFile();
572 libmwaw::DebugStream f;
573
574 if (input->tell()+(vers==2?14:2) > zone->end()) {
575 input->seek(pos, librevenge::RVNG_SEEK_SET);
576 return graphData;
577 }
578
579 graphData.reset(new FullWrtStruct::ZoneHeader(doc));
580 f.str("");
581 f << "Entries(GraphData):" << doc;
582 asciiFile.addPos(pos);
583 asciiFile.addNote(f.str().c_str());
584 if (vers == 2) {
585 pos = input->tell();
586 f.str("");
587 f << "GraphData[1]:";
588 int dim[4];
589 for (auto &d : dim) d=int(input->readLong(2));
590 f << "box=" << dim[1] << "x" << dim[0] << "<->" << dim[3] << "x" << dim[2] << ",";
591 for (int i = 0; i < 2; i++) { // always 0 ?
592 auto val = int(input->readLong(2));
593 if (val)
594 f << "f" << i << "=" << val << "c";
595 }
596 asciiFile.addPos(pos);
597 asciiFile.addNote(f.str().c_str());
598 }
599
600 f.str("");
601 auto nextData = int(input->readULong(1));
602 pos = input->tell();
603 if (nextData==1) {
604 f << "GraphData[2]:";
605 auto sz = long(input->readULong(4));
606 if (sz < 0 || pos+4+sz > zone->end()) {
607 f << "#sz=" << sz << ",";
608 input->seek(pos, librevenge::RVNG_SEEK_SET);
609 }
610 else if (sz) { // a serie of doc id ( normally 1e )
611 f << "docId[type1e?]=[";
612 for (long i = 0; i < sz/2; i++) {
613 auto id = int(input->readLong(2));
614 std::string type=m_mainParser->getDocumentTypeName(id);
615 if (type.empty())
616 f << "#" << id << ",";
617 else
618 f << id << "[" << type << "],";
619 }
620 f << "],";
621 input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
622 }
623 }
624 else if (nextData) f << "GraphData[2]:#" << nextData;
625
626 input->seek(1, librevenge::RVNG_SEEK_CUR);
627 if (f.str().length()) {
628 asciiFile.addPos(pos);
629 asciiFile.addNote(f.str().c_str());
630 }
631
632 return graphData;
633 }
634
readGraphic(FullWrtStruct::EntryPtr zone)635 bool FullWrtGraph::readGraphic(FullWrtStruct::EntryPtr zone)
636 {
637 int vers = version();
638
639 MWAWInputStreamPtr input = zone->m_input;
640 libmwaw::DebugFile &asciiFile = zone->getAsciiFile();
641 libmwaw::DebugStream f;
642
643 long pos = zone->begin();
644 input->seek(pos, librevenge::RVNG_SEEK_SET);
645 auto sz = long(input->readULong(4));
646 int expectedSz = vers==1 ? 0x5c : 0x54;
647 if (sz != expectedSz || pos+sz > zone->end()) return false;
648 input->seek(sz, librevenge::RVNG_SEEK_CUR);
649 f << "Entries(Graphic)";
650 f << "|" << *zone << ":";
651 if (zone->m_fileType >= 0)
652 f << "type=" << std::hex << zone->m_fileType << std::dec << ",";
653 asciiFile.addPos(pos);
654 asciiFile.addNote(f.str().c_str());
655
656 pos = input->tell();
657 sz = long(input->readULong(4));
658 if (!sz || pos+4+sz > zone->end()) {
659 MWAW_DEBUG_MSG(("FullWrtGraph::readGraphic: can not read graphic size\n"));
660 return false;
661 }
662 f.str("");
663 f << "Graphic:sz=" << std::hex << sz << std::dec << ",";
664 asciiFile.addPos(pos);
665 asciiFile.addNote(f.str().c_str());
666 asciiFile.skipZone(pos+4, pos+4+sz-1);
667 input->seek(sz, librevenge::RVNG_SEEK_CUR);
668
669 m_state->m_graphicMap.insert
670 (std::multimap<int, FullWrtStruct::EntryPtr >::value_type(zone->id(), zone));
671
672 pos = input->tell();
673 if (pos == zone->end())
674 return true;
675
676 sz = long(input->readULong(4));
677 if (sz)
678 input->seek(sz, librevenge::RVNG_SEEK_CUR);
679 if (pos+4+sz!=zone->end()) {
680 MWAW_DEBUG_MSG(("FullWrtGraph::readGraphic: end graphic seems odds\n"));
681 }
682 asciiFile.addPos(pos);
683 asciiFile.addNote("Graphic-A");
684
685 asciiFile.addPos(input->tell());
686 asciiFile.addNote("_");
687
688 return true;
689 }
690
691 ////////////////////////////////////////////////////////////
692 // send data
693 ////////////////////////////////////////////////////////////
sendGraphic(int fId)694 bool FullWrtGraph::sendGraphic(int fId)
695 {
696 auto it = m_state->m_graphicMap.find(fId);
697 if (it == m_state->m_graphicMap.end() || !it->second) {
698 MWAW_DEBUG_MSG(("FullWrtGraph::sendGraphic: can not find graphic %d\n", fId));
699 return false;
700 }
701 auto zone = it->second;
702 MWAWInputStreamPtr input = zone->m_input;
703 long pos = input->tell();
704 bool ok=sendGraphic(zone);
705 input->seek(pos, librevenge::RVNG_SEEK_SET);
706 return ok;
707 }
708
sendGraphic(FullWrtStruct::EntryPtr zone)709 bool FullWrtGraph::sendGraphic(FullWrtStruct::EntryPtr zone)
710 {
711 MWAWTextListenerPtr listener=m_parserState->m_textListener;
712 if (!listener) {
713 MWAW_DEBUG_MSG(("FullWrtGraph::sendGraphic can not find the listener\n"));
714 return true;
715 }
716 zone->setParsed(true);
717
718 MWAWInputStreamPtr input = zone->m_input;
719
720 long pos = zone->begin();
721 input->seek(pos, librevenge::RVNG_SEEK_SET);
722 auto sz = static_cast<int>(input->readULong(4));
723 input->seek(sz, librevenge::RVNG_SEEK_CUR);
724
725 // header
726 pos = input->tell();
727 sz = static_cast<int>(input->readULong(4));
728
729 #ifdef DEBUG_WITH_FILES
730 if (1) {
731 librevenge::RVNGBinaryData file;
732 input->seek(pos+4, librevenge::RVNG_SEEK_SET);
733 input->readDataBlock(sz, file);
734 static int volatile pictName = 0;
735 libmwaw::DebugStream f;
736 f << "DATA-" << ++pictName;
737 libmwaw::Debug::dumpFile(file, f.str().c_str());
738 }
739 #endif
740
741 input->seek(pos+4, librevenge::RVNG_SEEK_SET);
742 MWAWBox2f box;
743 auto res = MWAWPictData::check(input, sz, box);
744 if (res == MWAWPict::MWAW_R_BAD) {
745 MWAW_DEBUG_MSG(("FullWrtGraph::sendGraphic: can not find the picture\n"));
746 return false;
747 }
748
749 MWAWVec2f actualSize, naturalSize;
750 if (box.size().x() > 0 && box.size().y() > 0) {
751 actualSize = naturalSize = box.size();
752 }
753 else if (actualSize.x() <= 0 || actualSize.y() <= 0) {
754 MWAW_DEBUG_MSG(("FullWrtGraph::sendGraphic: can not find the picture size\n"));
755 actualSize = naturalSize = MWAWVec2f(100,100);
756 }
757 MWAWPosition pictPos=MWAWPosition(MWAWVec2f(0,0),actualSize, librevenge::RVNG_POINT);
758 pictPos.setRelativePosition(MWAWPosition::Char);
759 pictPos.setNaturalSize(naturalSize);
760
761 input->seek(pos+4, librevenge::RVNG_SEEK_SET);
762 std::shared_ptr<MWAWPict> pict(MWAWPictData::get(input, sz));
763 if (pict) {
764 MWAWEmbeddedObject picture;
765 if (pict->getBinary(picture)) {
766 listener->insertPicture(pictPos, picture);
767 return true;
768 }
769 }
770
771 return true;
772 }
773
sendPageGraphics()774 bool FullWrtGraph::sendPageGraphics()
775 {
776 for (auto const &frame : m_state->m_sidebarList) {
777 if (!frame)
778 continue;
779 if (!frame->m_parsed)
780 sendSideBar(*frame);
781 }
782 return true;
783 }
784
flushExtra()785 void FullWrtGraph::flushExtra()
786 {
787 for (auto it : m_state->m_graphicMap) {
788 FullWrtStruct::EntryPtr &zone = it.second;
789 if (!zone || zone->isParsed())
790 continue;
791 sendGraphic(zone);
792 }
793 }
794 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
795