/src/libwps/src/lib/WPS8Graph.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) 2009, 2011 Alonso Laurent (alonso@loria.fr) |
11 | | * Copyright (C) 2006, 2007 Andrew Ziem |
12 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
13 | | * Copyright (C) 2004 Marc Maurer (uwog@uwog.net) |
14 | | * Copyright (C) 2003-2005 William Lachance (william.lachance@sympatico.ca) |
15 | | * |
16 | | * For minor contributions see the git repository. |
17 | | * |
18 | | * Alternatively, the contents of this file may be used under the terms |
19 | | * of the GNU Lesser General Public License Version 2.1 or later |
20 | | * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are |
21 | | * applicable instead of those above. |
22 | | * |
23 | | * For further information visit http://libwps.sourceforge.net |
24 | | */ |
25 | | |
26 | | #include <string.h> |
27 | | |
28 | | #include <iomanip> |
29 | | #include <iostream> |
30 | | |
31 | | #include <librevenge/librevenge.h> |
32 | | |
33 | | #include "WPSContentListener.h" |
34 | | #include "WPSEntry.h" |
35 | | #include "WPSFont.h" |
36 | | #include "WPSOLEObject.h" |
37 | | #include "WPSOLEParser.h" |
38 | | #include "WPSParagraph.h" |
39 | | #include "WPSPosition.h" |
40 | | #include "WPSStream.h" |
41 | | |
42 | | #include "WPS8.h" |
43 | | |
44 | | #include "WPS8Graph.h" |
45 | | |
46 | | |
47 | | /** Internal: the structures of a WPS8Graph */ |
48 | | namespace WPS8GraphInternal |
49 | | { |
50 | | /** Internal: a complex border picture |
51 | | * |
52 | | * It consists in series of at most 8 pictures which forms the border */ |
53 | | struct Border |
54 | | { |
55 | | //! constructor |
56 | | Border() |
57 | 0 | : m_name("") |
58 | 0 | , m_pictList() |
59 | 0 | , m_parsed(false) |
60 | 0 | { |
61 | 0 | for (int &i : m_borderSize) i = -1; |
62 | 0 | for (int &i : m_borderId) i = -1; |
63 | 0 | } |
64 | | |
65 | | //! Internal: the border name |
66 | | std::string m_name; |
67 | | /** three value to stored the border's sizes |
68 | | * |
69 | | * Checkme: corner size, following by horizontal, vertical size in points? |
70 | | */ |
71 | | int m_borderSize[3]; |
72 | | //! the picture uses to draw TopLeft corner, Top border, TopRight corner, Right border... |
73 | | int m_borderId[8]; |
74 | | //! the border's pictures: 1 to 8 pictures.. |
75 | | std::vector<WPSEmbeddedObject> m_pictList; |
76 | | //! flag to know if the border was sent to the listener |
77 | | bool m_parsed; |
78 | | }; |
79 | | |
80 | | //! Internal: the state of a WPS8Graph |
81 | | struct State |
82 | | { |
83 | | State() |
84 | 6.71k | : m_version(-1) |
85 | 6.71k | , m_numPages(0) |
86 | 6.71k | , m_borderMap() |
87 | 6.71k | , m_ibgfMap() |
88 | 6.71k | , m_pictMap() |
89 | 6.71k | , m_oleMap() {} |
90 | | //! the version |
91 | | int m_version; |
92 | | //! the number page |
93 | | int m_numPages; |
94 | | //! a map id -> border |
95 | | std::map<int, Border> m_borderMap; |
96 | | //! a map id -> ibgf entry (background picture entry) |
97 | | std::map<int, WPSEntry> m_ibgfMap; |
98 | | //! a map id -> pictData |
99 | | std::map<int, WPSEmbeddedObject> m_pictMap; |
100 | | //! a map id -> OleData |
101 | | std::map<int, WPSEmbeddedObject> m_oleMap; |
102 | | }; |
103 | | } |
104 | | |
105 | | //////////////////////////////////////////////////////////// |
106 | | // constructor/destructor |
107 | | //////////////////////////////////////////////////////////// |
108 | | WPS8Graph::WPS8Graph(WPS8Parser &parser) |
109 | 6.71k | : m_listener() |
110 | 6.71k | , m_mainParser(parser) |
111 | 6.71k | , m_state() |
112 | 6.71k | , m_asciiFile(parser.ascii()) |
113 | 6.71k | { |
114 | 6.71k | m_state.reset(new WPS8GraphInternal::State); |
115 | 6.71k | } |
116 | | |
117 | | WPS8Graph::~WPS8Graph() |
118 | 6.71k | { } |
119 | | |
120 | | //////////////////////////////////////////////////////////// |
121 | | // update the positions and send data to the listener |
122 | | //////////////////////////////////////////////////////////// |
123 | | int WPS8Graph::version() const |
124 | 0 | { |
125 | 0 | if (m_state->m_version <= 0) |
126 | 0 | m_state->m_version = m_mainParser.version(); |
127 | 0 | return m_state->m_version; |
128 | 0 | } |
129 | | |
130 | | int WPS8Graph::numPages() const |
131 | 5.58k | { |
132 | 5.58k | return m_state->m_numPages; |
133 | 5.58k | } |
134 | | |
135 | | //////////////////////////////////////////////////////////// |
136 | | // update the positions and send data to the listener |
137 | | //////////////////////////////////////////////////////////// |
138 | | void WPS8Graph::computePositions() const |
139 | 5.58k | { |
140 | 5.58k | m_state->m_numPages = (m_state->m_pictMap.size() || m_state->m_oleMap.size()) ? 1 : 0; |
141 | 5.58k | } |
142 | | |
143 | | void WPS8Graph::storeObjects(std::map<int,WPSEmbeddedObject> const &objectsMap) |
144 | 6.71k | { |
145 | 6.71k | m_state->m_oleMap=objectsMap; |
146 | 6.71k | } |
147 | | |
148 | | //////////////////////////////////////////////////////////// |
149 | | // find all structures which correspond to the picture |
150 | | //////////////////////////////////////////////////////////// |
151 | | bool WPS8Graph::readStructures(RVNGInputStreamPtr const &input) |
152 | 5.58k | { |
153 | 5.58k | auto const &nameTable = m_mainParser.getNameEntryMap(); |
154 | | |
155 | | // contains a text and 8 borders cells? |
156 | 5.58k | auto pos = nameTable.lower_bound("BDR "); |
157 | 262k | while (nameTable.end() != pos) |
158 | 262k | { |
159 | 262k | WPSEntry const &entry = pos++->second; |
160 | 262k | if (!entry.hasName("BDR ")) break; |
161 | 256k | if (!entry.hasType("WBDR")) continue; |
162 | 0 | readBDR(input, entry); |
163 | 0 | } |
164 | | |
165 | | // read IBGF zone : picture type (image background f...? ) |
166 | 5.58k | pos = nameTable.lower_bound("IBGF"); |
167 | 172k | while (pos != nameTable.end()) |
168 | 172k | { |
169 | 172k | WPSEntry const &entry = pos++->second; |
170 | 172k | if (!entry.hasName("IBGF")) break; |
171 | 167k | if (!entry.hasType("IBGF")) continue; |
172 | | |
173 | 87.5k | readIBGF(input, entry); |
174 | 87.5k | } |
175 | | |
176 | 5.58k | pos = nameTable.lower_bound("PICT"); |
177 | 135k | while (pos != nameTable.end()) |
178 | 135k | { |
179 | 135k | WPSEntry const &entry = pos++->second; |
180 | 135k | if (!entry.hasName("PICT")) break; |
181 | | |
182 | 129k | readPICT(input, entry); |
183 | 129k | } |
184 | | |
185 | 5.58k | return true; |
186 | 5.58k | } |
187 | | |
188 | | //////////////////////////////////////////////////////////// |
189 | | // different function to send data to a listener |
190 | | //////////////////////////////////////////////////////////// |
191 | | bool WPS8Graph::sendObject(WPSPosition const &posi, int id, bool ole) |
192 | 10.9k | { |
193 | 10.9k | if (m_listener.get() == nullptr) |
194 | 0 | { |
195 | 0 | WPS_DEBUG_MSG(("WPS8Graph::sendObject: listener is not set\n")); |
196 | 0 | return false; |
197 | 0 | } |
198 | 10.9k | auto &map = ole ? m_state->m_oleMap : m_state->m_pictMap; |
199 | | |
200 | 10.9k | auto pos = map.find(id); |
201 | 10.9k | if (pos == map.end()) |
202 | 10.7k | { |
203 | 10.7k | WPS_DEBUG_MSG(("WPS8Graph::sendObject: can not find %dth object\n", id)); |
204 | 10.7k | return false; |
205 | 10.7k | } |
206 | 113 | auto &pict = pos->second; |
207 | 113 | pict.m_sent = true; |
208 | | |
209 | 113 | Vec2f size(posi.size()), naturalSize; |
210 | 113 | if (size.x() <= 0 || size.y()<=0) |
211 | 3 | { |
212 | 3 | size=pict.m_size; |
213 | 3 | if (size.x() <= 0 || size.y()<=0) |
214 | 3 | { |
215 | 3 | WPS_DEBUG_MSG(("WPS8Graph::sendObject: can not find object size\n")); |
216 | 3 | size=Vec2f(0.5,0.5); |
217 | 3 | } |
218 | 3 | } |
219 | 110 | else if (pict.m_size.x() > 0 && pict.m_size.y() > 0) |
220 | 2 | naturalSize = pict.m_size; |
221 | 113 | WPSPosition finalPos(posi); |
222 | 113 | finalPos.setSize(size); |
223 | 113 | finalPos.setNaturalSize(naturalSize); |
224 | 113 | m_listener->insertObject(finalPos, pict); |
225 | 113 | return true; |
226 | 10.9k | } |
227 | | |
228 | | bool WPS8Graph::sendIBGF(WPSPosition const &posi, int ibgfId) |
229 | 0 | { |
230 | 0 | auto pos = m_state->m_ibgfMap.find(ibgfId); |
231 | 0 | if (pos == m_state->m_ibgfMap.end()) |
232 | 0 | { |
233 | 0 | WPS_DEBUG_MSG(("WPS8Graph::sendIBGF: can not find background\n")); |
234 | 0 | return false; |
235 | 0 | } |
236 | | |
237 | 0 | WPSEntry const &ent = pos->second; |
238 | 0 | if (!ent.hasName("PICT")) |
239 | 0 | { |
240 | 0 | WPS_DEBUG_MSG(("WPS8Graph::sendIBGF: unknown ibgf type\n")); |
241 | 0 | return false; |
242 | 0 | } |
243 | 0 | return sendObject(posi, ent.id(), false); |
244 | 0 | } |
245 | | |
246 | | void WPS8Graph::sendObjects(int page, int) |
247 | 16.8k | { |
248 | 16.8k | if (page != -1) return; |
249 | 0 | if (m_listener.get() == nullptr) |
250 | 0 | { |
251 | 0 | WPS_DEBUG_MSG(("WPS8Graph::sendObjects: listener is not set\n")); |
252 | 0 | return; |
253 | 0 | } |
254 | | |
255 | | #ifdef DEBUG |
256 | | bool firstSend = false; |
257 | | #endif |
258 | 0 | for (int st = 0; st < 2; st++) |
259 | 0 | { |
260 | 0 | auto &map = (st == 0) ? m_state->m_pictMap : m_state->m_oleMap; |
261 | 0 | auto pos = map.begin(); |
262 | |
|
263 | 0 | while (pos != map.end()) |
264 | 0 | { |
265 | 0 | auto &pict = pos++->second; |
266 | 0 | if (pict.m_sent) continue; |
267 | | |
268 | | #ifdef DEBUG |
269 | | if (!firstSend) |
270 | | { |
271 | | firstSend = true; |
272 | | WPS_DEBUG_MSG(("WPS8Graph::sendObjects: find some extra pictures\n")); |
273 | | m_listener->setFont(WPSFont::getDefault()); |
274 | | m_listener->setParagraph(WPSParagraph()); |
275 | | m_listener->insertEOL(); |
276 | | librevenge::RVNGString message = "--------- The original document has some extra pictures: -------- "; |
277 | | m_listener->insertUnicodeString(message); |
278 | | m_listener->insertEOL(); |
279 | | } |
280 | | #endif |
281 | | |
282 | 0 | pict.m_sent = true; |
283 | 0 | Vec2f size=pict.m_size; |
284 | | // if we do not have the size of the data, we insert small picture |
285 | 0 | if (size.x() <= 0 || size.y() <= 0) size.set(1.0, 1.0); |
286 | 0 | WPSPosition position(Vec2f(),size); |
287 | 0 | position.setNaturalSize(pict.m_size); |
288 | 0 | position.setRelativePosition(WPSPosition::CharBaseLine); |
289 | 0 | position.m_wrapping = WPSPosition::WDynamic; |
290 | 0 | m_listener->insertObject(position, pict); |
291 | 0 | } |
292 | 0 | } |
293 | |
|
294 | | #ifdef DEBUG |
295 | | // check the border |
296 | | for (auto const &pos : m_state->m_borderMap) |
297 | | { |
298 | | int id = pos.first; |
299 | | bool parsed = pos.second.m_parsed; |
300 | | if (parsed) continue; |
301 | | if (!firstSend) |
302 | | { |
303 | | firstSend = true; |
304 | | m_listener->setFont(WPSFont::getDefault()); |
305 | | m_listener->setParagraph(WPSParagraph()); |
306 | | m_listener->insertEOL(); |
307 | | librevenge::RVNGString message; |
308 | | message = "--------- The original document used some complex border: -------- "; |
309 | | m_listener->insertUnicodeString(message); |
310 | | m_listener->insertEOL(); |
311 | | } |
312 | | sendBorder(id); |
313 | | } |
314 | | #endif |
315 | 0 | } |
316 | | |
317 | | void WPS8Graph::sendBorder(int borderId) |
318 | 0 | { |
319 | 0 | if (!m_listener || m_state->m_borderMap.find(borderId) == m_state->m_borderMap.end()) return; |
320 | | |
321 | 0 | auto &border = m_state->m_borderMap[borderId]; |
322 | 0 | if (border.m_parsed) return; |
323 | | |
324 | 0 | border.m_parsed = true; |
325 | |
|
326 | 0 | m_listener->setFont(WPSFont::getDefault()); |
327 | 0 | m_listener->setParagraph(WPSParagraph()); |
328 | 0 | librevenge::RVNGString message("-------"); |
329 | 0 | message.append(border.m_name.c_str()); |
330 | 0 | message.append("---------"); |
331 | 0 | m_listener->insertUnicodeString(message); |
332 | |
|
333 | 0 | WPSPosition pos(Vec2f(),Vec2f(0.5,0.5)); |
334 | 0 | pos.setRelativePosition(WPSPosition::CharBaseLine); |
335 | 0 | pos.m_wrapping = WPSPosition::WDynamic; |
336 | 0 | for (int i = 0; i < 8; i++) |
337 | 0 | { |
338 | 0 | if (i == 0 || i == 3 || i == 5) m_listener->insertEOL(); |
339 | 0 | static int const wh[8] = {0, 1, 2, 7, 3, 6, 5, 4 }; |
340 | 0 | auto id = size_t(border.m_borderId[wh[i]]); |
341 | 0 | if (border.m_pictList[id].m_size.x() > 0 && |
342 | 0 | border.m_pictList[id].m_size.y() > 0) |
343 | 0 | pos.setSize(border.m_pictList[id].m_size); |
344 | 0 | m_listener->insertObject(pos, border.m_pictList[id]); |
345 | 0 | if (i == 3) |
346 | 0 | { |
347 | 0 | message = librevenge::RVNGString("-----"); |
348 | 0 | m_listener->insertUnicodeString(message); |
349 | 0 | } |
350 | 0 | } |
351 | 0 | } |
352 | | |
353 | | //////////////////////////////////////////////////////////// |
354 | | // |
355 | | // low level |
356 | | // |
357 | | //////////////////////////////////////////////////////////// |
358 | | |
359 | | // Read a PICT/MEF4 entry : read uncompressed picture of sx*sy of rgb |
360 | | bool WPS8Graph::readPICT(RVNGInputStreamPtr const &input, WPSEntry const &entry) |
361 | 129k | { |
362 | 129k | long page_offset = entry.begin(); |
363 | 129k | long length = entry.length(); |
364 | 129k | long endPos = entry.end(); |
365 | | |
366 | 129k | WPSEmbeddedObject pict; |
367 | | |
368 | | // too small, we return 0 |
369 | 129k | if (length < 24) return false; |
370 | | |
371 | 48.0k | if (!entry.hasType("MEF4")) |
372 | 48.0k | { |
373 | 48.0k | WPS_DEBUG_MSG(("WPS8Graph::readPICT: warning: PICT name=%s, type=%s\n", |
374 | 48.0k | entry.name().c_str(), entry.type().c_str())); |
375 | 48.0k | return false; |
376 | 48.0k | } |
377 | | |
378 | 0 | input->seek(page_offset, librevenge::RVNG_SEEK_SET); |
379 | 0 | std::string name; |
380 | 0 | for (int i = 0; i < 4; i++) name += char(libwps::readU8(input)); |
381 | 0 | if (strncmp("MEF4", name.c_str(), 4)) |
382 | 0 | { |
383 | 0 | WPS_DEBUG_MSG(("WPS8Graph::readPICT: warning: PICT unknown header=%s\n", |
384 | 0 | name.c_str())); |
385 | 0 | return false; |
386 | 0 | } |
387 | | |
388 | 0 | libwps::DebugStream f; |
389 | 0 | f << "Header:"; |
390 | | // unkn0, unkn1 : always 0 ? |
391 | 0 | for (int i = 0; i < 2; i++) |
392 | 0 | { |
393 | 0 | auto val = long(libwps::readU32(input)); // is one the number of meta file ? |
394 | 0 | if (val) f << "unknA" << i << "=" << std::hex << val << std::dec << ","; |
395 | 0 | } |
396 | 0 | pict.m_size.setX(float(libwps::readU32(input))/914400.f); |
397 | 0 | pict.m_size.setY(float(libwps::readU32(input))/914400.f); |
398 | 0 | f << "pSz(inches)=" << pict.m_size << ","; |
399 | |
|
400 | 0 | ascii().addPos(page_offset); |
401 | 0 | ascii().addNote(f.str().c_str()); |
402 | 0 | entry.setParsed(); |
403 | |
|
404 | 0 | auto stream=std::make_shared<WPSStream>(input, ascii()); |
405 | 0 | bool ok=WPSOLEObject::readWMF(stream, pict, endPos); // we may also want to check if this is a emf file |
406 | 0 | if (ok) |
407 | 0 | { |
408 | 0 | if (m_state->m_pictMap.find(entry.id()) != m_state->m_pictMap.end()) |
409 | 0 | WPS_DEBUG_MSG(("WPS8Graph::readPICT: Pict entry %d already exists\n", entry.id())); |
410 | 0 | else |
411 | 0 | m_state->m_pictMap[entry.id()] = pict; |
412 | 0 | } |
413 | 0 | else |
414 | 0 | input->seek(page_offset+24, librevenge::RVNG_SEEK_SET); |
415 | |
|
416 | 0 | if (input->tell() != endPos) |
417 | 0 | { |
418 | 0 | ascii().addPos(input->tell()); |
419 | 0 | ascii().addNote("PICT###"); |
420 | 0 | } |
421 | | |
422 | |
|
423 | 0 | return ok; |
424 | 0 | } |
425 | | |
426 | | |
427 | | // reads a IBGF zone |
428 | | // Warning: only seems very simple IBGF, complex may differ |
429 | | bool WPS8Graph::readIBGF(RVNGInputStreamPtr const &input, WPSEntry const &entry) |
430 | 87.5k | { |
431 | 87.5k | libwps::DebugStream f; |
432 | 87.5k | if (!entry.hasType(entry.name())) |
433 | 0 | { |
434 | 0 | WPS_DEBUG_MSG(("WPS8Graph::readIBGF: warning: IBGF name=%s, type=%s\n", |
435 | 0 | entry.name().c_str(), entry.type().c_str())); |
436 | 0 | return false; |
437 | 0 | } |
438 | | |
439 | 87.5k | long page_offset = entry.begin(); |
440 | 87.5k | long length = entry.length(); |
441 | | |
442 | 87.5k | if (length != 26) |
443 | 47.9k | { |
444 | 47.9k | WPS_DEBUG_MSG(("WPS8Graph::readIBGF: IBGF length=0x%lx\n", static_cast<unsigned long>(length))); |
445 | 47.9k | return false; |
446 | 47.9k | } |
447 | | |
448 | 39.5k | entry.setParsed(); |
449 | 39.5k | input->seek(page_offset, librevenge::RVNG_SEEK_SET); |
450 | 39.5k | std::string name; |
451 | 120k | for (int i = 0; i < 4; i++) |
452 | 111k | { |
453 | 111k | auto val = char(libwps::readU8(input)); |
454 | 111k | if (val >= '0' && val <= 'z') |
455 | 81.2k | { |
456 | 81.2k | name+=val; |
457 | 81.2k | continue; |
458 | 81.2k | } |
459 | 30.6k | WPS_DEBUG_MSG(("WPS8Graph::readIBGF: invalid name %s\n", name.c_str())); |
460 | 30.6k | return false; |
461 | 111k | } |
462 | | |
463 | 8.97k | auto id = int(libwps::read16(input)); |
464 | | |
465 | 8.97k | WPSEntry res; |
466 | 8.97k | res.setName(name); |
467 | 8.97k | res.setId(id); |
468 | | |
469 | | // name = PICT ? |
470 | 8.97k | f << "indexEntry='" << name << "':" << id; |
471 | | |
472 | 98.6k | for (int i = 0; i < 10; i++) |
473 | 89.7k | { |
474 | 89.7k | auto val = libwps::read16(input); |
475 | 89.7k | if (val) f << ", f"<<i <<"=" << val; |
476 | 89.7k | } |
477 | | |
478 | 8.97k | ascii().addPos(page_offset); |
479 | 8.97k | ascii().addNote(f.str().c_str()); |
480 | | |
481 | 8.97k | if (m_state->m_ibgfMap.find(entry.id()) != m_state->m_ibgfMap.end()) |
482 | 8.95k | WPS_DEBUG_MSG(("WPS8Graph::readIBGF: warning: IBGF entry %d already exists\n", |
483 | 8.95k | entry.id())); |
484 | 16 | else |
485 | 16 | m_state->m_ibgfMap[entry.id()] = res; |
486 | | |
487 | 8.97k | return true; |
488 | 39.5k | } |
489 | | |
490 | | // BDR/WBDR Code : read a BDR Code |
491 | | bool WPS8Graph::readBDR(RVNGInputStreamPtr const &input, WPSEntry const &entry) |
492 | 0 | { |
493 | 0 | long page_offset = entry.begin(); |
494 | 0 | long length = entry.length(); |
495 | 0 | long endPos = entry.end(); |
496 | | |
497 | | // too small, we return 0 |
498 | 0 | if (length < 20) |
499 | 0 | { |
500 | 0 | WPS_DEBUG_MSG(("WPS8Graph::readBDR: length=%ld is too short\n", length)); |
501 | 0 | return false; |
502 | 0 | } |
503 | | |
504 | 0 | if (!entry.hasType("WBDR")) |
505 | 0 | { |
506 | 0 | WPS_DEBUG_MSG(("WPS8Graph::readBDR: warning: BDR name=%s, type=%s\n", |
507 | 0 | entry.name().c_str(), entry.type().c_str())); |
508 | 0 | return false; |
509 | 0 | } |
510 | | |
511 | 0 | entry.setParsed(); |
512 | 0 | input->seek(page_offset, librevenge::RVNG_SEEK_SET); |
513 | |
|
514 | 0 | WPS8GraphInternal::Border border; |
515 | 0 | border.m_name = entry.extra(); |
516 | 0 | libwps::DebugStream f; |
517 | 0 | if (!border.m_name.empty()) f << "Header:borderName='"<<border.m_name << "',"; |
518 | | |
519 | | // 1, unk? = ~ 1/20*following size ? |
520 | 0 | for (int i = 0; i < 2; i++) f << libwps::read16(input) << ","; |
521 | | // 3*size (corner size, following by x/y steps) in points? |
522 | 0 | f << "sizes=("; |
523 | 0 | for (int &i : border.m_borderSize) |
524 | 0 | { |
525 | 0 | i = libwps::read16(input); |
526 | 0 | f << i << ","; |
527 | 0 | } |
528 | 0 | f << "),"; |
529 | |
|
530 | 0 | bool ok = true; |
531 | | // ids of picture which corresponds to the frame borders: |
532 | | // TL, T, TR, R, BR, B, BL, L ? |
533 | 0 | f << "id=("; |
534 | 0 | for (int &i : border.m_borderId) |
535 | 0 | { |
536 | 0 | auto id = int(libwps::read8(input)); |
537 | 0 | if (id < 0 || id> 8) |
538 | 0 | { |
539 | 0 | ok = false; |
540 | 0 | break; |
541 | 0 | } |
542 | 0 | i = id; |
543 | 0 | f << id << ","; |
544 | 0 | } |
545 | 0 | f << "),"; |
546 | 0 | auto N = int(libwps::read8(input)); |
547 | 0 | f << "Nbdr="<<N << ","; |
548 | 0 | auto unkn = int(libwps::read8(input)); |
549 | 0 | if (unkn) f << "###unkn=" << unkn << ","; |
550 | |
|
551 | 0 | if (!ok || N < 0 || N > 8 || 20+N*4 > length) |
552 | 0 | { |
553 | 0 | WPS_DEBUG_MSG(("WPS8Graph::readBDR: can not read the pictures\n")); |
554 | 0 | f << "###"; |
555 | 0 | ascii().addPos(page_offset); |
556 | 0 | ascii().addNote(f.str().c_str()); |
557 | 0 | return false; |
558 | 0 | } |
559 | | |
560 | 0 | long debPos = page_offset+4*N+20; |
561 | 0 | f << "ptr(" << std::hex; |
562 | |
|
563 | 0 | std::vector<long> listPtrs; |
564 | 0 | listPtrs.push_back(debPos); |
565 | |
|
566 | 0 | for (int i = 0; i < N; i++) |
567 | 0 | { |
568 | 0 | f << debPos << ","; |
569 | 0 | auto sz = long(libwps::readU32(input)); |
570 | 0 | debPos += sz; |
571 | 0 | if (sz < 0 || debPos > endPos) |
572 | 0 | { |
573 | 0 | ok = false; |
574 | 0 | break; |
575 | 0 | } |
576 | 0 | listPtrs.push_back(debPos); |
577 | 0 | } |
578 | 0 | f << debPos << ")," << std::dec; |
579 | |
|
580 | 0 | ascii().addPos(page_offset); |
581 | 0 | ascii().addNote(f.str().c_str()); |
582 | 0 | if (!ok) return false; |
583 | | |
584 | 0 | if (listPtrs[size_t(N)] != endPos) |
585 | 0 | { |
586 | 0 | ascii().addPos(listPtrs[size_t(N)]); |
587 | 0 | ascii().addNote("###BDR"); |
588 | 0 | } |
589 | |
|
590 | 0 | auto stream=std::make_shared<WPSStream>(input, ascii()); |
591 | 0 | for (size_t bd = 0; bd < size_t(N); bd++) |
592 | 0 | { |
593 | 0 | long debP = listPtrs[bd]; |
594 | 0 | long endP = listPtrs[bd+1]; |
595 | |
|
596 | 0 | input->seek(debP, librevenge::RVNG_SEEK_SET); |
597 | 0 | f.str(""); |
598 | 0 | f << "BDR(" << bd << "):"; |
599 | |
|
600 | 0 | if (debP+12 > endP || libwps::readU32(input) != 0x4154454d) // META |
601 | 0 | { |
602 | 0 | WPS_DEBUG_MSG(("WPS8Graph::readBDR: unknown type can not read the picture %d\n", int(bd))); |
603 | 0 | f << "###"; |
604 | 0 | ascii().addPos(debP); |
605 | 0 | ascii().addNote(f.str().c_str()); |
606 | 0 | ok = false; |
607 | 0 | continue; |
608 | 0 | } |
609 | | |
610 | 0 | WPSEmbeddedObject pict; |
611 | 0 | int dim[4]; |
612 | 0 | for (int &i : dim) |
613 | 0 | { |
614 | 0 | i = int(libwps::read16(input)); |
615 | 0 | f << i << ","; |
616 | 0 | } |
617 | | // final picture size |
618 | 0 | pict.m_size.set(float(dim[2]-dim[0])/1440.f, float(dim[3]-dim[1])/1440.f); |
619 | 0 | bool correct=WPSOLEObject::readWMF(stream, pict, endP); |
620 | 0 | if (!correct) f << "###"; |
621 | 0 | ascii().addPos(debP); |
622 | 0 | ascii().addNote(f.str().c_str()); |
623 | |
|
624 | 0 | if (!correct) |
625 | 0 | { |
626 | 0 | ok = false; |
627 | 0 | continue; |
628 | 0 | } |
629 | | |
630 | 0 | if (ok) border.m_pictList.push_back(pict); |
631 | 0 | } |
632 | |
|
633 | 0 | if (!ok) return false; |
634 | 0 | m_state->m_borderMap[entry.id()] = border; |
635 | 0 | return true; |
636 | 0 | } |
637 | | |
638 | | /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */ |