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