/src/libwps/src/lib/WPS8Table.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 <iomanip> |
27 | | #include <iostream> |
28 | | |
29 | | #include <librevenge/librevenge.h> |
30 | | |
31 | | #include "WPSCell.h" |
32 | | #include "WPSContentListener.h" |
33 | | #include "WPSEntry.h" |
34 | | #include "WPSPosition.h" |
35 | | #include "WPSTable.h" |
36 | | |
37 | | #include "WPS8.h" |
38 | | #include "WPS8Struct.h" |
39 | | |
40 | | #include "WPS8Table.h" |
41 | | |
42 | | |
43 | | /** Internal: the structures of a WPS8Table */ |
44 | | namespace WPS8TableInternal |
45 | | { |
46 | | /** Internal: class to store a basic cell with borders */ |
47 | | struct Cell final : public WPSCell |
48 | | { |
49 | | //! constructor |
50 | | explicit Cell(WPS8Table &parser) |
51 | 214k | : WPSCell() |
52 | 214k | , m_tableParser(parser) |
53 | 214k | , m_id(-1) |
54 | 214k | , m_strsId(-1) |
55 | 214k | , m_size() |
56 | 214k | { |
57 | 214k | WPSBorder emptyBorder; |
58 | 214k | emptyBorder.m_style = WPSBorder::None; |
59 | 214k | m_bordersList.resize(4, emptyBorder); |
60 | 857k | for (float &i : m_bordersSep) i = 0.0; |
61 | 214k | } |
62 | | //! virtual destructor |
63 | | ~Cell() final; |
64 | | |
65 | | //! operator<< |
66 | | friend std::ostream &operator<<(std::ostream &o, Cell const &cell); |
67 | | //! call when a cell must be send |
68 | | bool send(WPSListenerPtr &listener) final |
69 | 481 | { |
70 | 481 | if (!listener) return true; |
71 | 481 | auto *listen=dynamic_cast<WPSContentListener *>(listener.get()); |
72 | 481 | if (!listen) |
73 | 0 | { |
74 | 0 | WPS_DEBUG_MSG(("WPS8TableInternal::Cell::send: unexpected listener\n")); |
75 | 0 | return true; |
76 | 0 | } |
77 | 481 | listen->openTableCell(*this); |
78 | 481 | sendContent(listener); |
79 | 481 | listen->closeTableCell(); |
80 | 481 | return true; |
81 | 481 | } |
82 | | |
83 | | //! call when the content of a cell must be send |
84 | | bool sendContent(WPSListenerPtr &) final |
85 | 1.06k | { |
86 | 1.06k | m_tableParser.sendTextInCell(m_strsId, m_id); |
87 | 1.06k | return true; |
88 | 1.06k | } |
89 | | |
90 | | //! the actual parser |
91 | | WPS8Table &m_tableParser; |
92 | | //! the cell id |
93 | | int m_id; |
94 | | //! the strsId |
95 | | mutable int m_strsId; |
96 | | //! frame size in inches |
97 | | Vec2f m_size; |
98 | | //! border text separator T,L,R,B ( checkme, not sure ) |
99 | | float m_bordersSep[4]; |
100 | | }; |
101 | | Cell::~Cell() |
102 | 214k | { |
103 | 214k | } |
104 | | //! operator<< for a Cell |
105 | | std::ostream &operator<<(std::ostream &o, Cell const &cell) |
106 | 0 | { |
107 | 0 | o << reinterpret_cast<WPSCell const &>(cell); |
108 | 0 | if (cell.m_size.x() > 0 || cell.m_size.y() > 0) o << "size=" << cell.m_size << ","; |
109 | 0 | bool hasBSize = false; |
110 | 0 | for (float i : cell.m_bordersSep) |
111 | 0 | { |
112 | 0 | if (i <= 0) |
113 | 0 | continue; |
114 | 0 | hasBSize = true; |
115 | 0 | break; |
116 | 0 | } |
117 | 0 | if (hasBSize) |
118 | 0 | { |
119 | 0 | o << "borderSep?=["; |
120 | 0 | for (float i : cell.m_bordersSep) |
121 | 0 | if (i > 0) o << i << ","; |
122 | 0 | else o << "_,"; |
123 | 0 | o << "],"; |
124 | 0 | } |
125 | 0 | return o; |
126 | 0 | } |
127 | | |
128 | | /** Internal: class to store a table: list of cells */ |
129 | | struct Table final : public WPSTable |
130 | | { |
131 | | //! constructor |
132 | | Table() |
133 | 339k | : m_id(-1) |
134 | 339k | , m_parsed(false) {} |
135 | 44.6k | Table &operator=(Table const &)=default; |
136 | | //! destructor |
137 | | ~Table() final; |
138 | | //! operator<< |
139 | | friend std::ostream &operator<<(std::ostream &o, Table const &table); |
140 | | //! the table id |
141 | | int m_id; |
142 | | |
143 | | //! a bool to know if the table has been parsed |
144 | | mutable bool m_parsed; |
145 | | }; |
146 | | |
147 | | Table::~Table() |
148 | 339k | { |
149 | 339k | } |
150 | | |
151 | | //! operator<< for a Table |
152 | | std::ostream &operator<<(std::ostream &o, Table const &table) |
153 | 0 | { |
154 | 0 | o << "id=" << table.m_id << ","; |
155 | 0 | for (int i = 0; i < table.numCells(); i++) |
156 | 0 | { |
157 | 0 | WPSCellPtr cell = const_cast<Table &>(table).getCell(i); |
158 | 0 | if (!cell) continue; |
159 | 0 | o << "cell" << i << "=[" << *reinterpret_cast<Cell const *>(cell.get()) << "],"; |
160 | 0 | } |
161 | 0 | return o; |
162 | 0 | } |
163 | | |
164 | | /** Internal: the state of a WPS8Table */ |
165 | | struct State |
166 | | { |
167 | | //! constructor |
168 | | State() |
169 | 9.45k | : m_version(-1) |
170 | 9.45k | , m_numPages(0) |
171 | 9.45k | , m_tableMap() |
172 | 9.45k | , m_MCLDTypes() |
173 | 9.45k | { |
174 | 9.45k | initTypeMaps(); |
175 | 9.45k | } |
176 | | |
177 | | //! initialize the type map |
178 | | void initTypeMaps(); |
179 | | //! the version |
180 | | int m_version; |
181 | | //! the number page |
182 | | int m_numPages; |
183 | | //! a map id -> table |
184 | | std::map<int, Table> m_tableMap; |
185 | | //! the MCLD type |
186 | | std::map<int,int> m_MCLDTypes; |
187 | | }; |
188 | | |
189 | | void State::initTypeMaps() |
190 | 9.45k | { |
191 | 9.45k | static int const MCLDTypes[] = |
192 | 9.45k | { |
193 | 9.45k | 0, 0x22, 1, 0x22, 2, 0x22, 3, 0x22, 4, 0x22, 5, 0x22, 6, 0x22, 7, 0x22, |
194 | 9.45k | 8, 0x22, 9, 0x22, 0xa, 0x22, 0xb, 0x1a, 0xc, 0x2, 0xd, 0x22, 0xe, 0x22, |
195 | 9.45k | 0x11, 0x22, 0x12, 0x22, 0x13, 0x12, 0x14, 0x2, 0x15, 0x22, 0x16, 0x22, 0x17, 0x22, |
196 | 9.45k | 0x18, 0x22, 0x19, 0x2, 0x1a, 0x2, 0x1d, 0x22, 0x1e, 0x22, 0x1f, 0x12, |
197 | 9.45k | 0x20, 0x22, 0x21, 0x12, 0x22, 0x22, 0x23, 0x22, 0x24, 0x12, 0x25, 0x22, 0x26, 0x22, 0x27, 0x12, |
198 | 9.45k | 0x28, 0x22, 0x29, 0x22, 0x2a, 0x12, 0x2b, 0x22, 0x2c, 0x12, |
199 | 9.45k | 0x31, 0x18 |
200 | 9.45k | }; |
201 | 406k | for (int i = 0; i+1 < int(WPS_N_ELEMENTS(MCLDTypes)); i+=2) |
202 | 397k | m_MCLDTypes[MCLDTypes[i]] = MCLDTypes[i+1]; |
203 | | |
204 | 9.45k | } |
205 | | } |
206 | | |
207 | | //////////////////////////////////////////////////////////// |
208 | | // constructor/destructor |
209 | | //////////////////////////////////////////////////////////// |
210 | | WPS8Table::WPS8Table(WPS8Parser &parser) |
211 | 9.45k | : m_listener() |
212 | 9.45k | , m_mainParser(parser) |
213 | 9.45k | , m_state(new WPS8TableInternal::State) |
214 | 9.45k | , m_asciiFile(parser.ascii()) |
215 | 9.45k | { |
216 | 9.45k | } |
217 | | |
218 | | WPS8Table::~WPS8Table() |
219 | 9.45k | { |
220 | 9.45k | } |
221 | | |
222 | | //////////////////////////////////////////////////////////// |
223 | | // update the positions and send data to the listener |
224 | | //////////////////////////////////////////////////////////// |
225 | | int WPS8Table::version() const |
226 | 0 | { |
227 | 0 | if (m_state->m_version <= 0) |
228 | 0 | m_state->m_version = m_mainParser.version(); |
229 | 0 | return m_state->m_version; |
230 | 0 | } |
231 | | |
232 | | int WPS8Table::numPages() const |
233 | 8.15k | { |
234 | 8.15k | return m_state->m_numPages; |
235 | 8.15k | } |
236 | | |
237 | | void WPS8Table::sendTextInCell(int strsId, int cellId) |
238 | 1.06k | { |
239 | 1.06k | m_mainParser.sendTextInCell(strsId, cellId); |
240 | 1.06k | } |
241 | | |
242 | | //////////////////////////////////////////////////////////// |
243 | | // update the positions and send data to the listener |
244 | | //////////////////////////////////////////////////////////// |
245 | | void WPS8Table::computePositions() const |
246 | 0 | { |
247 | 0 | m_state->m_numPages = 0; |
248 | 0 | } |
249 | | |
250 | | void WPS8Table::flushExtra() |
251 | 0 | { |
252 | 0 | if (m_listener.get() == nullptr) return; |
253 | | |
254 | 0 | for (auto const &table : m_state->m_tableMap) |
255 | 0 | { |
256 | 0 | if (table.second.m_parsed) continue; |
257 | 0 | int strsid = m_mainParser.getTableSTRSId(table.second.m_id); |
258 | 0 | if (strsid < 0) continue; |
259 | 0 | sendTable(Vec2f(100.,100.), table.second.m_id, strsid); |
260 | 0 | } |
261 | 0 | } |
262 | | |
263 | | //////////////////////////////////////////////////////////// |
264 | | // send a table id |
265 | | //////////////////////////////////////////////////////////// |
266 | | bool WPS8Table::sendTable(Vec2f const &siz, int tableId, int strsid, bool inTextBox) |
267 | 426 | { |
268 | 426 | if (!m_listener) |
269 | 0 | { |
270 | 0 | WPS_DEBUG_MSG(("WPS8Table::sendTable: listener is not set\n")); |
271 | 0 | return true; |
272 | 0 | } |
273 | 426 | if (strsid <= 0) |
274 | 0 | { |
275 | 0 | WPS_DEBUG_MSG(("WPS8Table::sendTable: strsid is not set\n")); |
276 | 0 | return false; |
277 | 0 | } |
278 | | |
279 | 426 | auto pos = m_state->m_tableMap.find(tableId); |
280 | 426 | if (pos == m_state->m_tableMap.end()) |
281 | 35 | { |
282 | 35 | WPS_DEBUG_MSG(("WPS8Table::sendTable: can not find table with id=%d\n", tableId)); |
283 | 35 | if (inTextBox) |
284 | 0 | m_mainParser.send(strsid); |
285 | 35 | else |
286 | 35 | { |
287 | | // OK, we revert to a textbox inserted as a character |
288 | 35 | WPSPosition tablePos(Vec2f(), siz); |
289 | 35 | tablePos.m_anchorTo = WPSPosition::CharBaseLine; |
290 | 35 | tablePos.m_wrapping = WPSPosition::WDynamic; |
291 | | |
292 | 35 | m_mainParser.sendTextBox(tablePos, strsid); |
293 | 35 | } |
294 | 35 | return true; |
295 | 35 | } |
296 | | |
297 | 391 | auto &table = pos->second; |
298 | 391 | if (table.m_parsed) |
299 | 120 | WPS_DEBUG_MSG(("WPS8Table::sendTable: table with id=%d is already parsed\n", tableId)); |
300 | 271 | else |
301 | 271 | table.m_parsed = true; |
302 | | // first we need to update the strsid |
303 | 1.57k | for (int c = 0; c < table.numCells(); c++) |
304 | 1.18k | { |
305 | 1.18k | WPSCellPtr cell = table.getCell(c); |
306 | 1.18k | if (!cell) continue; |
307 | 1.18k | reinterpret_cast<WPS8TableInternal::Cell *>(cell.get())->m_strsId = strsid; |
308 | 1.18k | } |
309 | 391 | if (!table.sendTable(m_listener)) |
310 | 181 | table.sendAsText(m_listener); |
311 | 391 | return true; |
312 | 426 | } |
313 | | |
314 | | //////////////////////////////////////////////////////////// |
315 | | // find all structures which correspond to the table |
316 | | //////////////////////////////////////////////////////////// |
317 | | bool WPS8Table::readStructures(RVNGInputStreamPtr const &input) |
318 | 8.15k | { |
319 | 8.15k | m_state->m_tableMap.clear(); |
320 | | |
321 | 8.15k | auto const &nameTable = m_mainParser.getNameEntryMap(); |
322 | 8.15k | auto pos = nameTable.lower_bound("MCLD"); |
323 | 884k | while (pos != nameTable.end()) |
324 | 884k | { |
325 | 884k | WPSEntry const &entry = pos++->second; |
326 | 884k | if (!entry.hasName("MCLD")) break; |
327 | 876k | if (!entry.hasType("MCLD")) continue; |
328 | | |
329 | 689k | readMCLD(input, entry); |
330 | 689k | } |
331 | | |
332 | 8.15k | return true; |
333 | 8.15k | } |
334 | | |
335 | | //////////////////////////////////////////////////////////// |
336 | | // low level |
337 | | //////////////////////////////////////////////////////////// |
338 | | bool WPS8Table::readMCLD(RVNGInputStreamPtr input, WPSEntry const &entry) |
339 | 689k | { |
340 | 689k | if (!entry.hasType(entry.name())) |
341 | 0 | { |
342 | 0 | WPS_DEBUG_MSG(("WPS8Table::readMCLD: warning: MCLD name=%s, type=%s\n", |
343 | 0 | entry.name().c_str(), entry.type().c_str())); |
344 | 0 | return false; |
345 | 0 | } |
346 | | |
347 | 689k | long page_offset = entry.begin(); |
348 | 689k | long length = entry.length(); |
349 | 689k | long endPage = entry.end(); |
350 | | |
351 | 689k | if (length < 24) |
352 | 47.8k | { |
353 | 47.8k | WPS_DEBUG_MSG(("WPS8Table::readMCLD: warning: MCLD length=0x%lx\n", static_cast<unsigned long>(length))); |
354 | | |
355 | 47.8k | return false; |
356 | 47.8k | } |
357 | | |
358 | 641k | entry.setParsed(); |
359 | 641k | input->seek(page_offset, librevenge::RVNG_SEEK_SET); |
360 | | |
361 | 641k | libwps::DebugStream f; |
362 | 641k | auto mZone = int(libwps::read32(input)); |
363 | 641k | auto nTables = int(libwps::read32(input)); |
364 | | |
365 | 641k | f << "maxUnknown=" << mZone << ", nTables= " << nTables; |
366 | 641k | if ((6+long(nTables)) * 4 > length) return false; |
367 | | |
368 | 556k | f << ", ids=("; |
369 | 556k | std::vector<int> listIds; |
370 | 1.27M | for (int i = 0; i < nTables; i++) |
371 | 718k | { |
372 | 718k | auto val = int(libwps::read32(input)); |
373 | 718k | listIds.push_back(val); |
374 | 718k | f << val << ","; |
375 | 718k | } |
376 | 556k | f << ")"; |
377 | | |
378 | 556k | ascii().addPos(page_offset); |
379 | 556k | ascii().addNote(f.str().c_str()); |
380 | | |
381 | 556k | int mCounter = -1; |
382 | 556k | bool ok = true; |
383 | | |
384 | 556k | static char const *borderNames[] = { "T", "L", "R", "B" }; |
385 | 556k | static int const borderPos[] = |
386 | 556k | { WPSBorder::Top, WPSBorder::Left, WPSBorder::Right, WPSBorder::Bottom}; |
387 | 556k | static int const borderBit[] = |
388 | 556k | { |
389 | 556k | WPSBorder::TopBit, WPSBorder::LeftBit, |
390 | 556k | WPSBorder::RightBit, WPSBorder::BottomBit |
391 | 556k | }; |
392 | 556k | long lastPosOk = input->tell(); |
393 | 705k | while (input->tell() != endPage) |
394 | 683k | { |
395 | 683k | if (input->tell()+16 > endPage) |
396 | 45.0k | { |
397 | 45.0k | ok = false; |
398 | 45.0k | break; |
399 | 45.0k | } |
400 | | |
401 | 638k | mCounter++; |
402 | 638k | lastPosOk = input->tell(); |
403 | | |
404 | 638k | WPS8Struct::FileData tableData; |
405 | 638k | auto sz = int(libwps::read16(input)); |
406 | 638k | if (sz < 2 || lastPosOk+sz > endPage) |
407 | 197k | { |
408 | 197k | ok = false; |
409 | 197k | break; |
410 | 197k | } |
411 | | |
412 | 441k | std::string error; |
413 | 441k | if (!readBlockData(input, lastPosOk+sz,tableData, error)) |
414 | 414k | { |
415 | 414k | f.str(""); |
416 | 414k | f << tableData; |
417 | 414k | error = f.str(); |
418 | 414k | } |
419 | | |
420 | 441k | f.str(""); |
421 | 441k | int tableId = (mCounter < int(listIds.size())) ? listIds[size_t(mCounter)] : -1; |
422 | 441k | if (tableId < 0) f << "MCLD/Table[###unknownId]:"; |
423 | 87.9k | else f << "MCLD/Table" << listIds[size_t(mCounter)]<<":"; |
424 | | |
425 | 441k | auto N = int(libwps::readU32(input)); |
426 | 441k | f << " nCells=" << N; |
427 | 441k | if (N < 0 || N > 100) |
428 | 103k | { |
429 | 103k | ok = false; |
430 | 103k | break; |
431 | 103k | } |
432 | | |
433 | 337k | WPS8TableInternal::Table table; |
434 | 337k | table.m_id = tableId; |
435 | | |
436 | | // point dim seems odd, we will need to update them |
437 | 337k | Vec2f totalRealDim(0,0), totalDataDim(0,0); |
438 | | |
439 | 337k | if (!tableData.m_recursData.empty()) |
440 | 97.7k | { |
441 | 97.7k | f << ",("; |
442 | 97.7k | for (auto const &dt : tableData.m_recursData) |
443 | 126k | { |
444 | 126k | if (dt.isBad()) continue; |
445 | 126k | int const expectedTypes[] = { 2, 0x22 }; |
446 | 126k | if (dt.id() < 0 || dt.id() > 1) |
447 | 120k | { |
448 | 120k | f << "##" << dt << ","; |
449 | 120k | continue; |
450 | 120k | } |
451 | 5.50k | if (expectedTypes[dt.id()]!=dt.type()) |
452 | 3.74k | { |
453 | 3.74k | WPS_DEBUG_MSG(("WPS8Table::readMCLD: unexpected type for %d=%d\n", dt.id(), dt.type())); |
454 | 3.74k | f << "###" << dt << ","; |
455 | 3.74k | continue; |
456 | 3.74k | } |
457 | 1.76k | bool done = true; |
458 | 1.76k | switch (dt.id()) |
459 | 1.76k | { |
460 | 917 | case 0: // always set |
461 | 917 | f << "f" << dt.id() << ", "; |
462 | 917 | break; |
463 | 848 | case 1: // always 0 |
464 | 848 | f << "f" << dt.id() << "=" << dt.m_value << ", "; |
465 | 848 | break; |
466 | 0 | default: |
467 | 0 | done = false; |
468 | 0 | break; |
469 | 1.76k | } |
470 | | |
471 | 1.76k | if (!done) f << "###" << dt << ","; |
472 | 1.76k | } |
473 | 97.7k | f << ")"; |
474 | 97.7k | } |
475 | 337k | if (!error.empty()) f << ", ###err=" << error; |
476 | | |
477 | 337k | ascii().addPos(lastPosOk); |
478 | 337k | ascii().addNote(f.str().c_str()); |
479 | | |
480 | 551k | for (size_t actualCell = 0; actualCell < size_t(N); actualCell++) |
481 | 403k | { |
482 | 403k | lastPosOk = input->tell(); |
483 | 403k | sz = int(libwps::read16(input)); |
484 | 403k | if (sz < 2 || lastPosOk+sz > endPage) |
485 | 189k | { |
486 | 189k | ok = false; |
487 | 189k | break; |
488 | 189k | } |
489 | | |
490 | 214k | WPS8Struct::FileData mainData; |
491 | 214k | error = ""; |
492 | | |
493 | 214k | if (!readBlockData(input, lastPosOk+sz,mainData, error)) |
494 | 169k | { |
495 | 169k | f.str(""); |
496 | 169k | f << mainData; |
497 | 169k | error = f.str(); |
498 | 169k | } |
499 | | |
500 | | // original position in point ( checkme) |
501 | 214k | float dim[4] = { 0, 0, 0, 0 }; |
502 | | |
503 | 214k | f.str(""); |
504 | 214k | f << "MCLD/Table"; |
505 | 214k | if (tableId >= 0) f << tableId; |
506 | 214k | f << "(Cell" << actualCell <<"):"; |
507 | | |
508 | 214k | auto cell = std::make_shared<WPS8TableInternal::Cell>(*this); |
509 | 214k | WPSCellPtr cellPtr(cell); |
510 | 214k | cell->m_id = int(actualCell); |
511 | | |
512 | 214k | libwps::DebugStream f2; |
513 | 214k | WPSColor cellColor[] = { WPSColor::black(), WPSColor::white() }; |
514 | | |
515 | 214k | for (auto &dt : mainData.m_recursData) |
516 | 319k | { |
517 | 319k | if (dt.isBad()) continue; |
518 | 319k | if (m_state->m_MCLDTypes.find(dt.id())==m_state->m_MCLDTypes.end()) |
519 | 60.7k | { |
520 | 60.7k | f << "##" << dt << ","; |
521 | 60.7k | continue; |
522 | 60.7k | } |
523 | 259k | if (m_state->m_MCLDTypes.find(dt.id())->second != dt.type()) |
524 | 164k | { |
525 | 164k | WPS_DEBUG_MSG(("WPS8Table::readMCLD: unexpected type for %d=%d\n", dt.id(), dt.type())); |
526 | 164k | f << "###" << dt << ","; |
527 | 164k | continue; |
528 | 164k | } |
529 | | |
530 | 94.5k | bool done = true; |
531 | 94.5k | switch (dt.id()) |
532 | 94.5k | { |
533 | 2.25k | case 0: |
534 | 4.36k | case 1: |
535 | 6.55k | case 2: |
536 | 8.62k | case 3: // min/max pos in point (96 dpi ?) |
537 | 8.62k | dim[dt.id()] = float(dt.m_value); |
538 | 8.62k | break; |
539 | 2.04k | case 4: |
540 | 4.09k | case 5: // look coherent with EOBJ info |
541 | 4.09k | if (dt.id() == 4) cell->m_size.setX(float(dt.m_value)/914400.f); |
542 | 2.05k | else cell->m_size.setY(float(dt.m_value)/914400.f); |
543 | 4.09k | break; |
544 | | // border size : unknown dim |
545 | | // [ 1, 3, 1, 3, ] |
546 | | // [ 0.666667, 1.33333, 0.666667, 1.33333, ]/30 |
547 | 2.03k | case 6: |
548 | 4.06k | case 7: |
549 | 6.08k | case 8: |
550 | 8.09k | case 9: |
551 | 8.09k | cell->m_bordersSep[dt.id()-6] = float(dt.m_value)/914400.f; |
552 | 8.09k | break; |
553 | 1.86k | case 0xe: // always 0x20000000 |
554 | 1.86k | if (dt.m_value != 0x20000000) |
555 | 47 | f2 << "f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ","; |
556 | 1.86k | break; |
557 | 1.81k | case 0x12: // 0x0 or 0x997aa0 or 0x3fffe238 ? |
558 | 1.81k | f2 << "f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ","; |
559 | 1.81k | break; |
560 | 1.80k | case 0x13: //find -1|6 here |
561 | 1.80k | f2 << "f" << dt.id() << "=" << int(int8_t(dt.m_value)) << ","; |
562 | 1.80k | break; |
563 | 1.77k | case 0x1d: // first color |
564 | 3.55k | case 0x1e: // second color |
565 | 3.55k | cellColor[dt.id()-0x1d] = dt.getRGBColor(); |
566 | 3.55k | break; |
567 | 1.68k | case 0x1f: |
568 | 1.68k | { |
569 | 1.68k | float percent=0.5; |
570 | 1.68k | if (dt.m_value == 0) // no motif |
571 | 1.60k | break; |
572 | 81 | if (dt.m_value >= 3 && dt.m_value <= 9) |
573 | 32 | percent = float(dt.m_value)*0.1f; // gray motif |
574 | 49 | else |
575 | 49 | f2 << "backMotif=" << dt.m_value << ","; |
576 | 81 | cell->setBackgroundColor(WPSColor::barycenter(percent,cellColor[0],1.f-percent,cellColor[1])); |
577 | 81 | break; |
578 | 1.68k | } |
579 | | // the border color |
580 | 1.84k | case 0x20: |
581 | 3.51k | case 0x23: |
582 | 5.09k | case 0x26: |
583 | 6.63k | case 0x29: |
584 | 6.63k | { |
585 | 6.63k | int wh = (dt.id()-0x20)/3; |
586 | 6.63k | WPSBorder border = cell->borders()[size_t(borderPos[wh])]; |
587 | 6.63k | border.m_color = dt.getRGBColor(); |
588 | 6.63k | cell->setBorders(borderBit[wh], border); |
589 | 6.63k | break; |
590 | 5.09k | } |
591 | 1.60k | case 0x21: |
592 | 3.10k | case 0x24: |
593 | 4.58k | case 0x27: |
594 | 6.06k | case 0x2a: |
595 | 6.06k | { |
596 | 6.06k | std::string mess(""); |
597 | 6.06k | int wh = (dt.id()-0x21)/3; |
598 | 6.06k | WPSBorder border = cell->borders()[size_t(borderPos[wh])]; |
599 | 6.06k | dt.getBorderStyles(border.m_style, border.m_type, mess); |
600 | 6.06k | cell->setBorders(borderBit[wh], border); |
601 | 6.06k | if (mess.length()) |
602 | 0 | f2 << "bordStyle" << borderNames[wh] << "=[" << mess << "],"; |
603 | 6.06k | break; |
604 | 4.58k | } |
605 | 1.53k | case 0x22: |
606 | 3.03k | case 0x25: |
607 | 4.51k | case 0x28: |
608 | 5.98k | case 0x2b: // often 20 |
609 | 5.98k | f2 << "unknBord" << borderNames[(dt.id()-0x22)/3] << "=" << dt.m_value << ","; |
610 | 5.98k | break; |
611 | 1.46k | case 0x2c: // 1, 0, -1 |
612 | 1.46k | switch (dt.m_value) |
613 | 1.46k | { |
614 | 327 | case 0: |
615 | 327 | break; // normal |
616 | 1.13k | case 0xFF: // also unset, diff with value = 1 ? |
617 | 1.13k | f2 << "#f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ","; |
618 | 1.13k | WPS_FALLTHROUGH; |
619 | 1.13k | case 1: |
620 | 1.13k | cell->setVerticalSet(false); |
621 | 1.13k | break; |
622 | 2 | default: |
623 | 2 | f2 << "f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ","; |
624 | 2 | break; |
625 | 1.46k | } |
626 | 1.46k | break; |
627 | | // always 0,excepted 0x15 hich can be 0 or 1 ? |
628 | 1.92k | case 0xa: |
629 | 3.81k | case 0xb: |
630 | 5.67k | case 0xd: |
631 | 7.51k | case 0x11: |
632 | 9.29k | case 0x15: |
633 | 11.0k | case 0x16: |
634 | 12.8k | case 0x17: |
635 | 12.8k | if (dt.m_value == 0); |
636 | 1.81k | else if (dt.m_value > -10 && dt.m_value < 10) |
637 | 1.77k | f2 << "f" << dt.id() << "=" << dt.m_value << ","; |
638 | 41 | else done = false; |
639 | 12.8k | break; |
640 | 1.83k | case 0x18: |
641 | 1.83k | switch (dt.m_value) |
642 | 1.83k | { |
643 | 1.61k | case 0: |
644 | 1.61k | cell->setVAlignment(WPSCellFormat::VALIGN_TOP); |
645 | 1.61k | break; |
646 | 87 | case 1: |
647 | 87 | cell->setVAlignment(WPSCellFormat::VALIGN_CENTER); |
648 | 87 | break; |
649 | 39 | case 2: |
650 | 39 | cell->setVAlignment(WPSCellFormat::VALIGN_BOTTOM); |
651 | 39 | break; |
652 | 87 | default: |
653 | 87 | if (dt.m_value > -10 && dt.m_value < 10) |
654 | 0 | f2 << "f" << dt.id() << "=" << dt.m_value << ","; |
655 | 87 | else |
656 | 87 | done = false; |
657 | 87 | break; |
658 | 1.83k | } |
659 | 1.83k | break; |
660 | 22.9k | case 0xc: |
661 | 24.6k | case 0x14: |
662 | 26.4k | case 0x19: |
663 | 28.1k | case 0x1a: // flag ? |
664 | 28.1k | if (dt.isTrue()) |
665 | 22.8k | f2 << "f" << dt.id() << ", "; |
666 | 5.36k | else |
667 | 5.36k | f2 << "f" << dt.id() << "=false, "; |
668 | 28.1k | break; |
669 | 0 | default: |
670 | 0 | done = false; |
671 | 0 | break; |
672 | 94.5k | } |
673 | | |
674 | 94.5k | if (!done) |
675 | 128 | f2 << dt << ","; |
676 | 94.5k | } |
677 | | |
678 | 214k | cell->setBox(WPSBox2f(Vec2f(dim[1],dim[0]),Vec2f(dim[3],dim[2]))); |
679 | 214k | totalRealDim += cell->m_size; |
680 | 214k | totalDataDim += cell->box().size(); |
681 | 214k | table.add(cellPtr); |
682 | | |
683 | 214k | f << *cell; |
684 | 214k | if (!f2.str().empty()) |
685 | 0 | f << ", unk=(" << f2.str() << ")"; |
686 | | |
687 | 214k | if (!error.empty()) f << ",###err=" << error; |
688 | 214k | input->seek(lastPosOk+sz, librevenge::RVNG_SEEK_SET); |
689 | | |
690 | 214k | ascii().addPos(lastPosOk); |
691 | 214k | ascii().addNote(f.str().c_str()); |
692 | 214k | } |
693 | 337k | if (!ok) break; |
694 | | |
695 | 148k | float factor[2] = { 1, 1}; |
696 | 148k | if (totalDataDim[0] > 0) factor[0] = 72.f*totalRealDim[0]/totalDataDim[0]; |
697 | 148k | if (totalDataDim[1] > 0) factor[1] = 72.f*totalRealDim[1]/totalDataDim[1]; |
698 | 183k | for (int c = 0; c < table.numCells(); c++) |
699 | 35.1k | { |
700 | 35.1k | auto cell = table.getCell(c); |
701 | 35.1k | if (!cell) continue; |
702 | 35.1k | WPSBox2f box=cell->box(); |
703 | 35.1k | cell->setBox(WPSBox2f(Vec2f(box[0][0]*factor[0], box[0][1]*factor[1]), |
704 | 35.1k | Vec2f(box[1][0]*factor[0], box[1][1]*factor[1]))); |
705 | 35.1k | } |
706 | | |
707 | 148k | if (tableId >=0) m_state->m_tableMap[tableId] = table; |
708 | 103k | else |
709 | 103k | { |
710 | 103k | WPS_DEBUG_MSG(("WPS8Table::readMCLD: find a table with negative id\n")); |
711 | 103k | } |
712 | 148k | } |
713 | | |
714 | 556k | if (!ok) |
715 | 534k | { |
716 | 534k | WPS_DEBUG_MSG(("WPS8Table::readMCLD: stopped prematively")); |
717 | 534k | ascii().addPos(lastPosOk); |
718 | 534k | ascii().addNote("###MCLD"); |
719 | 534k | } |
720 | 556k | return ok; |
721 | 556k | } |
722 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |