/src/libmwaw/src/lib/MsWksGraph.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 <set> |
40 | | #include <sstream> |
41 | | |
42 | | #include <librevenge/librevenge.h> |
43 | | |
44 | | #include "MWAWListener.hxx" |
45 | | #include "MWAWFont.hxx" |
46 | | #include "MWAWFontConverter.hxx" |
47 | | #include "MWAWGraphicEncoder.hxx" |
48 | | #include "MWAWGraphicListener.hxx" |
49 | | #include "MWAWGraphicShape.hxx" |
50 | | #include "MWAWGraphicStyle.hxx" |
51 | | #include "MWAWParagraph.hxx" |
52 | | #include "MWAWPictBitmap.hxx" |
53 | | #include "MWAWPictMac.hxx" |
54 | | #include "MWAWPosition.hxx" |
55 | | #include "MWAWSubDocument.hxx" |
56 | | |
57 | | #include "MsWksTable.hxx" |
58 | | #include "MsWksDocument.hxx" |
59 | | |
60 | | #include "MsWksGraph.hxx" |
61 | | |
62 | | /** Internal: the structures of a MsWksGraph */ |
63 | | namespace MsWksGraphInternal |
64 | | { |
65 | | //////////////////////////////////////// |
66 | | //! Internal: a list of zones ( for v4) |
67 | | struct RBZone { |
68 | | RBZone() |
69 | 53.4k | : m_isMain(true) |
70 | 53.4k | , m_id(-2) |
71 | 53.4k | , m_idList() |
72 | 53.4k | , m_frame("") |
73 | 53.4k | { |
74 | 53.4k | } |
75 | | //! returns a unique id |
76 | | int getId() const |
77 | 30.8k | { |
78 | 30.8k | return m_isMain ? -1 : m_id; |
79 | 30.8k | } |
80 | | //! the zone type: rbdr(true) or rbil |
81 | | bool m_isMain; |
82 | | //! the zone id |
83 | | int m_id; |
84 | | //! the list of rb |
85 | | std::vector<int> m_idList; |
86 | | //! the frame name ( if it exist ) |
87 | | std::string m_frame; |
88 | | }; |
89 | | |
90 | | //////////////////////////////////////// |
91 | | //! Internal: the generic pict |
92 | | struct Zone { |
93 | | enum Type { Unknown, Shape, ChartZone, Group, Pict, Text, Textv4, Bitmap, TableZone, OLE}; |
94 | | //! constructor |
95 | | Zone() |
96 | 102M | : m_subType(-1) |
97 | 102M | , m_zoneId(-1) |
98 | 102M | , m_pos() |
99 | 102M | , m_dataPos(-1) |
100 | 102M | , m_fileId(-1) |
101 | 102M | , m_page(-1) |
102 | 102M | , m_decal() |
103 | 102M | , m_finalDecal() |
104 | 102M | , m_box() |
105 | 102M | , m_line(-1) |
106 | 102M | , m_style() |
107 | 102M | , m_order(0) |
108 | 102M | , m_extra("") |
109 | 102M | , m_doNotSend(false) |
110 | 102M | , m_isSent(false) |
111 | 102M | { |
112 | 306M | for (auto &id : m_ids) id = 0; |
113 | 102M | } |
114 | 25.6M | Zone(Zone const &)=default; |
115 | | Zone &operator=(Zone const &)=default; |
116 | 43.4M | Zone &operator=(Zone &&)=default; |
117 | | //! destructor |
118 | 127M | virtual ~Zone() {} |
119 | | |
120 | | //! operator<< |
121 | | friend std::ostream &operator<<(std::ostream &o, Zone const &pict) |
122 | 0 | { |
123 | 0 | pict.print(o); |
124 | 0 | return o; |
125 | 0 | } |
126 | | //! return the type |
127 | | virtual Type type() const |
128 | 0 | { |
129 | 0 | return Unknown; |
130 | 0 | } |
131 | | |
132 | | //! return a binary data (if known) |
133 | | virtual bool getBinaryData(MWAWInputStreamPtr, MWAWEmbeddedObject &picture) const |
134 | 0 | { |
135 | 0 | picture=MWAWEmbeddedObject(); |
136 | 0 | return false; |
137 | 0 | } |
138 | | |
139 | | //! return the extra border space ( if needed) |
140 | | virtual float needExtraBorderWidth() const |
141 | 666k | { |
142 | 666k | return 0.0; |
143 | 666k | } |
144 | | |
145 | | //! add frame parameters to propList (if needed ) |
146 | 0 | virtual void fillFrame(MWAWGraphicStyle &) const { } |
147 | | |
148 | | //! return the box |
149 | | MWAWBox2f getLocalBox(bool extendWithBord=true) const |
150 | 3.61M | { |
151 | 3.61M | float x = m_box.size().x(), y=m_box.size().y(); |
152 | 3.61M | MWAWVec2f min = m_box.min(); |
153 | 3.61M | if (x < 0) { |
154 | 1.17M | min+=MWAWVec2f(x,0); |
155 | 1.17M | x *= -1.0f; |
156 | 1.17M | } |
157 | 3.61M | if (y < 0) { |
158 | 1.12M | min+=MWAWVec2f(0,y); |
159 | 1.12M | y *= -1.0f; |
160 | 1.12M | } |
161 | 3.61M | MWAWBox2f res(min, min+MWAWVec2f(x,y)); |
162 | 3.61M | if (!extendWithBord) return res; |
163 | 3.45M | float bExtra = needExtraBorderWidth(); |
164 | 3.45M | if (bExtra > 0) res.extend(2.0f*bExtra); |
165 | 3.45M | return res; |
166 | 3.61M | } |
167 | | |
168 | | MWAWPosition getPosition(MWAWPosition::AnchorTo rel) const |
169 | 3.27M | { |
170 | 3.27M | MWAWPosition res; |
171 | 3.27M | MWAWBox2f box = getLocalBox(); |
172 | 3.27M | if (rel==MWAWPosition::Paragraph || rel==MWAWPosition::Frame) { |
173 | 1.87M | res = MWAWPosition(box.min()+m_finalDecal, box.size(), librevenge::RVNG_POINT); |
174 | 1.87M | res.setRelativePosition(rel); |
175 | 1.87M | if (rel==MWAWPosition::Paragraph) |
176 | 1.86M | res.m_wrapping = MWAWPosition::WBackground; |
177 | 1.87M | } |
178 | 1.39M | else if (rel!=MWAWPosition::Page) { |
179 | 8.89k | res = MWAWPosition(MWAWVec2f(0,0), box.size(), librevenge::RVNG_POINT); |
180 | 8.89k | res.setRelativePosition(MWAWPosition::Char, |
181 | 8.89k | MWAWPosition::XLeft, MWAWPosition::YTop); |
182 | 8.89k | } |
183 | 1.38M | else { |
184 | 1.38M | res = MWAWPosition(box.min()+m_finalDecal, box.size(), librevenge::RVNG_POINT); |
185 | 1.38M | res.setRelativePosition(MWAWPosition::Page); |
186 | 1.38M | if (m_page >=0) |
187 | 381k | res.setPage(m_page+1); |
188 | 1.38M | res.m_wrapping = MWAWPosition::WBackground; |
189 | 1.38M | } |
190 | 3.27M | if (m_order > 0) res.setOrder(m_order); |
191 | 3.27M | return res; |
192 | 3.27M | } |
193 | | |
194 | | //! the virtual print function |
195 | | virtual void print(std::ostream &o) const; |
196 | | |
197 | | //! the type |
198 | | int m_subType; |
199 | | //! the zone id |
200 | | int m_zoneId; |
201 | | //! the file position |
202 | | MWAWEntry m_pos; |
203 | | //! the data begin position |
204 | | long m_dataPos; |
205 | | //! the file id |
206 | | int m_fileId; |
207 | | //! the zones id (main, previous, next) |
208 | | long m_ids[3]; |
209 | | //! the page |
210 | | int m_page; |
211 | | //! the local position |
212 | | MWAWBox2f m_decal; |
213 | | //! the final local position |
214 | | MWAWVec2f m_finalDecal; |
215 | | //! local bdbox |
216 | | MWAWBox2f m_box; |
217 | | //! the line position(v1) |
218 | | int m_line; |
219 | | //! the style |
220 | | MsWksGraph::Style m_style; |
221 | | //! the picture order |
222 | | int m_order; |
223 | | //! extra data |
224 | | std::string m_extra; |
225 | | //! a flag used to know if we need to send the data ( or if this is the part of a sub group) |
226 | | bool m_doNotSend; |
227 | | //! true if the zone is send |
228 | | bool m_isSent; |
229 | | }; |
230 | | |
231 | | void Zone::print(std::ostream &o) const |
232 | 0 | { |
233 | 0 | if (m_fileId >= 0) { |
234 | 0 | o << "P" << m_fileId; |
235 | 0 | if (m_zoneId >= 0) o << "[" << m_zoneId << "],"; |
236 | 0 | else o << ","; |
237 | 0 | } |
238 | 0 | for (int i = 0; i < 3; i++) { |
239 | 0 | if (m_ids[i] <= 0) continue; |
240 | 0 | switch (i) { |
241 | 0 | case 0: |
242 | 0 | o << "id="; |
243 | 0 | break; |
244 | 0 | case 1: |
245 | 0 | o << "pId="; |
246 | 0 | break; |
247 | 0 | default: |
248 | 0 | o << "nId="; |
249 | 0 | break; |
250 | 0 | } |
251 | 0 | o << std::hex << m_ids[i] << std::dec << ","; |
252 | 0 | } |
253 | 0 | switch (m_subType) { |
254 | 0 | case 0: |
255 | 0 | o << "line,"; |
256 | 0 | break; |
257 | 0 | case 1: |
258 | 0 | o << "rect,"; |
259 | 0 | break; |
260 | 0 | case 2: |
261 | 0 | o << "rectOval,"; |
262 | 0 | break; |
263 | 0 | case 3: |
264 | 0 | o << "circle,"; |
265 | 0 | break; |
266 | 0 | case 4: |
267 | 0 | o << "arc,"; |
268 | 0 | break; |
269 | 0 | case 5: |
270 | 0 | o << "poly,"; |
271 | 0 | break; |
272 | 0 | case 7: |
273 | 0 | o << "pict,"; |
274 | 0 | break; |
275 | 0 | case 8: |
276 | 0 | o << "group,"; |
277 | 0 | break; |
278 | 0 | case 9: |
279 | 0 | o << "textbox,"; |
280 | 0 | break; |
281 | 0 | case 0xa: |
282 | 0 | o << "chart,"; |
283 | 0 | break; |
284 | 0 | case 0xc: |
285 | 0 | o << "equation/graph,"; |
286 | 0 | break; |
287 | 0 | case 0xd: |
288 | 0 | o << "bitmap,"; |
289 | 0 | break; |
290 | 0 | case 0xe: |
291 | 0 | o << "ssheet,"; |
292 | 0 | break; |
293 | 0 | case 0xf: |
294 | 0 | o << "textbox2,"; |
295 | 0 | break; |
296 | 0 | case 0x10: |
297 | 0 | o << "table,"; |
298 | 0 | break; |
299 | 0 | case 0x100: |
300 | 0 | o << "pict,"; |
301 | 0 | break; // V1 pict |
302 | 0 | default: |
303 | 0 | o << "#type=" << m_subType << ","; |
304 | 0 | } |
305 | 0 | if (m_page>=0) o << "page=" << m_page << ","; |
306 | 0 | if (m_decal!=MWAWBox2f()) |
307 | 0 | o << "pos=" << m_decal << ","; |
308 | 0 | o << "bdbox=" << m_box << ","; |
309 | 0 | o << "style=[" << m_style << "],"; |
310 | 0 | if (m_line >= 0) o << "line=" << m_line << ","; |
311 | 0 | if (m_extra.length()) o << m_extra; |
312 | 0 | } |
313 | | //////////////////////////////////////// |
314 | | //! Internal: the group of a MsWksGraph |
315 | | struct GroupZone final : public Zone { |
316 | | //! constructor |
317 | | explicit GroupZone(Zone const &z) |
318 | 459k | : Zone(z) |
319 | 459k | , m_childs() |
320 | 459k | { |
321 | 459k | } |
322 | | //! destructor |
323 | | ~GroupZone() final; |
324 | | //! return the type |
325 | | Type type() const final |
326 | 1.02M | { |
327 | 1.02M | return Group; |
328 | 1.02M | } |
329 | | //! operator<< |
330 | | void print(std::ostream &o) const final |
331 | 0 | { |
332 | 0 | Zone::print(o); |
333 | 0 | o << "childs=["; |
334 | 0 | for (auto id : m_childs) |
335 | 0 | o << "P" << id << ","; |
336 | 0 | o << "],"; |
337 | 0 | } |
338 | | //! list of child id |
339 | | std::vector<int> m_childs; |
340 | | }; |
341 | | |
342 | | GroupZone::~GroupZone() |
343 | 459k | { |
344 | 459k | } |
345 | | |
346 | | //////////////////////////////////////// |
347 | | //! Internal: the simple form of a MsWksGraph ( line, rect, ...) |
348 | | struct BasicShape final : public Zone { |
349 | | //! constructor |
350 | | explicit BasicShape(Zone const &z) |
351 | 10.0M | : Zone(z) |
352 | 10.0M | , m_shape() |
353 | 10.0M | { |
354 | 10.0M | } |
355 | | //! destructor |
356 | | ~BasicShape() final; |
357 | | //! return the type |
358 | | Type type() const final |
359 | 6.23M | { |
360 | 6.23M | return Shape; |
361 | 6.23M | } |
362 | | //! operator<< |
363 | | void print(std::ostream &o) const final |
364 | 0 | { |
365 | 0 | Zone::print(o); |
366 | 0 | o << m_shape << ","; |
367 | 0 | } |
368 | | //! return the extra border size |
369 | | float needExtraBorderWidth() const final |
370 | 2.78M | { |
371 | 2.78M | float res=m_style.m_lineWidth; |
372 | 2.78M | if (m_shape.m_type==MWAWGraphicShape::Line) { |
373 | 5.01M | for (const auto &arrow : m_style.m_arrows) { |
374 | 5.01M | if (!arrow.isEmpty()) res+=4; |
375 | 5.01M | } |
376 | 2.50M | } |
377 | 2.78M | return 0.5f*res; |
378 | 2.78M | } |
379 | | //! return the shape type |
380 | | MWAWGraphicStyle getStyle() const |
381 | 3.56M | { |
382 | 3.56M | MWAWGraphicStyle style(m_style); |
383 | 3.56M | if (m_subType!=0) |
384 | 307k | style.m_arrows[0] = style.m_arrows[1]=MWAWGraphicStyle::Arrow(); |
385 | 3.56M | return style; |
386 | 3.56M | } |
387 | | |
388 | | //! the basic shape |
389 | | MWAWGraphicShape m_shape; |
390 | | private: |
391 | | BasicShape(BasicShape const &) = delete; |
392 | | BasicShape &operator=(BasicShape const &) = delete; |
393 | | }; |
394 | | |
395 | | BasicShape::~BasicShape() |
396 | 10.0M | { |
397 | 10.0M | } |
398 | | |
399 | | //////////////////////////////////////// |
400 | | //! Internal: the table of a MsWksGraph |
401 | | struct Chart final : public Zone { |
402 | | //! constructor |
403 | | explicit Chart(Zone const &z) |
404 | 6.49M | : Zone(z) |
405 | 6.49M | , m_chartId(0) |
406 | 6.49M | { |
407 | 6.49M | } |
408 | | //! empty constructor |
409 | | Chart() |
410 | | : Zone() |
411 | | , m_chartId(0) |
412 | 0 | { |
413 | 0 | } |
414 | | //! destructor |
415 | | ~Chart() final; |
416 | | |
417 | | //! return the type |
418 | | Type type() const final |
419 | 367 | { |
420 | 367 | return ChartZone; |
421 | 367 | } |
422 | | //! the chart id |
423 | | int m_chartId; |
424 | | }; |
425 | | |
426 | | Chart::~Chart() |
427 | 6.49M | { |
428 | 6.49M | } |
429 | | |
430 | | //////////////////////////////////////// |
431 | | //! Internal: the picture of a MsWksGraph |
432 | | struct DataPict final : public Zone { |
433 | | //! constructor |
434 | | explicit DataPict(Zone const &z) |
435 | 340k | : Zone(z) |
436 | 340k | , m_dataEndPos(-1) |
437 | 340k | , m_naturalBox() |
438 | 340k | { |
439 | 340k | } |
440 | | //! empty constructor |
441 | | DataPict() |
442 | 5.31M | : Zone(), |
443 | 5.31M | m_dataEndPos(-1) |
444 | 5.31M | , m_naturalBox() |
445 | 5.31M | { |
446 | 5.31M | } |
447 | | |
448 | | //! return the type |
449 | | Type type() const final |
450 | 383k | { |
451 | 383k | return Pict; |
452 | 383k | } |
453 | | //! return a binary data (if known) |
454 | | bool getBinaryData(MWAWInputStreamPtr ip, MWAWEmbeddedObject &picture) const final; |
455 | | |
456 | | //! operator<< |
457 | | void print(std::ostream &o) const final |
458 | 0 | { |
459 | 0 | Zone::print(o); |
460 | 0 | } |
461 | | //! the end of data (only defined when different to m_pos.end()) |
462 | | long m_dataEndPos; |
463 | | //! the pict box (if known ) |
464 | | mutable MWAWBox2f m_naturalBox; |
465 | | }; |
466 | | |
467 | | bool DataPict::getBinaryData(MWAWInputStreamPtr ip, MWAWEmbeddedObject &picture) const |
468 | 106k | { |
469 | 106k | picture=MWAWEmbeddedObject(); |
470 | 106k | long endPos = m_dataEndPos<=0 ? m_pos.end() : m_dataEndPos; |
471 | 106k | long pictSize = endPos-m_dataPos; |
472 | 106k | if (pictSize < 0) { |
473 | 0 | MWAW_DEBUG_MSG(("MsWksGraphInternal::DataPict::getBinaryData: picture size is bad\n")); |
474 | 0 | return false; |
475 | 0 | } |
476 | | |
477 | | #ifdef DEBUG_WITH_FILES |
478 | | if (1) { |
479 | | librevenge::RVNGBinaryData file; |
480 | | ip->seek(m_dataPos, librevenge::RVNG_SEEK_SET); |
481 | | ip->readDataBlock(pictSize, file); |
482 | | static int volatile pictName = 0; |
483 | | libmwaw::DebugStream f; |
484 | | f << "Pict-" << ++pictName << ".pct"; |
485 | | libmwaw::Debug::dumpFile(file, f.str().c_str()); |
486 | | } |
487 | | #endif |
488 | | |
489 | 106k | ip->seek(m_dataPos, librevenge::RVNG_SEEK_SET); |
490 | 106k | auto res = MWAWPictData::check(ip, static_cast<int>(pictSize), m_naturalBox); |
491 | 106k | if (res == MWAWPict::MWAW_R_BAD) { |
492 | 66.0k | MWAW_DEBUG_MSG(("MsWksGraphInternal::DataPict::getBinaryData: can not find the picture\n")); |
493 | 66.0k | return false; |
494 | 66.0k | } |
495 | | |
496 | 40.8k | ip->seek(m_dataPos, librevenge::RVNG_SEEK_SET); |
497 | 40.8k | std::shared_ptr<MWAWPict> pict(MWAWPictData::get(ip, static_cast<int>(pictSize))); |
498 | | |
499 | 40.8k | return pict && pict->getBinary(picture); |
500 | 106k | } |
501 | | |
502 | | //////////////////////////////////////// |
503 | | //! Internal: the bitmap of a MsWksGraph |
504 | | struct DataBitmap final : public Zone { |
505 | | //! constructor |
506 | | explicit DataBitmap(Zone const &z) |
507 | 12 | : Zone(z) |
508 | 12 | , m_numRows(0) |
509 | 12 | , m_numCols(0) |
510 | 12 | , m_dataSize(0) |
511 | 12 | , m_naturalBox() |
512 | 12 | { |
513 | 12 | } |
514 | | //! empty constructor |
515 | | DataBitmap() |
516 | | : Zone() |
517 | | , m_numRows(0) |
518 | | , m_numCols(0) |
519 | | , m_dataSize(0) |
520 | | , m_naturalBox() |
521 | 0 | { |
522 | 0 | } |
523 | | //! destructor |
524 | | ~DataBitmap() final; |
525 | | |
526 | | //! return the type |
527 | | Type type() const final |
528 | 0 | { |
529 | 0 | return Bitmap; |
530 | 0 | } |
531 | | //! return a binary data (if known) |
532 | | bool getPictureData(MWAWInputStreamPtr ip, MWAWEmbeddedObject &picture, std::vector<MWAWColor> const &palette) const; |
533 | | |
534 | | //! operator<< |
535 | | void print(std::ostream &o) const final |
536 | 0 | { |
537 | 0 | o << "nRows=" << m_numRows << ","; |
538 | 0 | o << "nCols=" << m_numCols << ","; |
539 | 0 | if (m_dataSize > 0) |
540 | 0 | o << "dSize=" << std::hex << m_dataSize << std::dec << ","; |
541 | 0 | Zone::print(o); |
542 | 0 | } |
543 | | |
544 | | int m_numRows /** the number of rows*/, m_numCols/** the number of columns*/; |
545 | | long m_dataSize /** the bitmap data size */; |
546 | | //! the pict box (if known ) |
547 | | mutable MWAWBox2f m_naturalBox; |
548 | | }; |
549 | | |
550 | | bool DataBitmap::getPictureData(MWAWInputStreamPtr ip, MWAWEmbeddedObject &picture, std::vector<MWAWColor> const &palette) const |
551 | 0 | { |
552 | 0 | picture=MWAWEmbeddedObject(); |
553 | 0 | if (m_dataSize <= 0 || m_dataSize < m_numRows*m_numCols) { |
554 | 0 | MWAW_DEBUG_MSG(("MsWksGraphInternal::DataBitmap::getPictureData: dataSize size is bad\n")); |
555 | 0 | return false; |
556 | 0 | } |
557 | 0 | auto szCol = int(m_dataSize/m_numRows); |
558 | 0 | long pos = m_dataPos; |
559 | |
|
560 | 0 | MWAWPictBitmapIndexed *btmap = new MWAWPictBitmapIndexed(MWAWVec2i(m_numCols, m_numRows)); |
561 | 0 | if (!btmap) return false; |
562 | 0 | btmap->setColors(palette); |
563 | 0 | std::shared_ptr<MWAWPict> pict(btmap); |
564 | 0 | for (int i = 0; i < m_numRows; i++) { |
565 | 0 | ip->seek(pos, librevenge::RVNG_SEEK_SET); |
566 | |
|
567 | 0 | unsigned long numRead; |
568 | 0 | uint8_t const *value = ip->read(size_t(m_numCols), numRead); |
569 | 0 | if (!value || int(numRead) != m_numCols) return false; |
570 | 0 | btmap->setRow(i, value); |
571 | |
|
572 | 0 | pos += szCol; |
573 | 0 | } |
574 | | |
575 | 0 | return pict->getBinary(picture); |
576 | 0 | } |
577 | | |
578 | | DataBitmap::~DataBitmap() |
579 | 12 | { |
580 | 12 | } |
581 | | |
582 | | //////////////////////////////////////// |
583 | | //! Internal: the table of a MsWksGraph |
584 | | struct Table final : public Zone { |
585 | | //! constructor |
586 | | explicit Table(Zone const &z) |
587 | 174k | : Zone(z) |
588 | 174k | , m_tableId(0) |
589 | 174k | { |
590 | 174k | } |
591 | | //! empty constructor |
592 | | Table() |
593 | | : Zone() |
594 | | , m_tableId(0) |
595 | 0 | { |
596 | 0 | } |
597 | | //! destructor |
598 | | ~Table() final; |
599 | | |
600 | | //! return the type |
601 | | Type type() const final |
602 | 50.3k | { |
603 | 50.3k | return TableZone; |
604 | 50.3k | } |
605 | | //! the table id |
606 | | int m_tableId; |
607 | | }; |
608 | | |
609 | | Table::~Table() |
610 | 174k | { |
611 | 174k | } |
612 | | |
613 | | //////////////////////////////////////// |
614 | | //! Internal: the textbox of a MsWksGraph ( v2-v3) |
615 | | struct TextBox final : public Zone { |
616 | | //! constructor |
617 | | explicit TextBox(Zone const &z) |
618 | 7.93M | : Zone(z) |
619 | 7.93M | , m_numPositions(-1) |
620 | 7.93M | , m_fontsList() |
621 | 7.93M | , m_positions() |
622 | 7.93M | , m_formats() |
623 | 7.93M | , m_text("") |
624 | 7.93M | , m_justify(MWAWParagraph::JustificationLeft) |
625 | 7.93M | { } |
626 | | //! destructor |
627 | | ~TextBox() final; |
628 | | //! return the type |
629 | | Type type() const final |
630 | 35.0k | { |
631 | 35.0k | return Text; |
632 | 35.0k | } |
633 | | //! operator<< |
634 | | void print(std::ostream &o) const final |
635 | 0 | { |
636 | 0 | Zone::print(o); |
637 | 0 | switch (m_justify) { |
638 | 0 | case MWAWParagraph::JustificationLeft: |
639 | 0 | break; |
640 | 0 | case MWAWParagraph::JustificationCenter: |
641 | 0 | o << ",centered"; |
642 | 0 | break; |
643 | 0 | case MWAWParagraph::JustificationRight: |
644 | 0 | o << ",right"; |
645 | 0 | break; |
646 | 0 | case MWAWParagraph::JustificationFull: |
647 | 0 | o << ",full"; |
648 | 0 | break; |
649 | 0 | case MWAWParagraph::JustificationFullAllLines: |
650 | 0 | o << ",fullAllLines"; |
651 | 0 | break; |
652 | | #if !defined(__clang__) |
653 | | default: |
654 | | o << ",#just=" << m_justify; |
655 | | break; |
656 | | #endif |
657 | 0 | } |
658 | 0 | } |
659 | | |
660 | | //! add frame parameters to propList (if needed ) |
661 | | void fillFrame(MWAWGraphicStyle &style) const final |
662 | 0 | { |
663 | 0 | if (!m_style.m_baseSurfaceColor.isWhite()) |
664 | 0 | style.setBackgroundColor(m_style.m_baseSurfaceColor); |
665 | 0 | } |
666 | | |
667 | | //! the number of positions |
668 | | int m_numPositions; |
669 | | //! the list of fonts |
670 | | std::vector<MWAWFont> m_fontsList; |
671 | | //! the list of positions |
672 | | std::vector<int> m_positions; |
673 | | //! the list of format |
674 | | std::vector<int> m_formats; |
675 | | //! the text |
676 | | std::string m_text; |
677 | | //! the paragraph alignment |
678 | | MWAWParagraph::Justification m_justify; |
679 | | private: |
680 | | TextBox(TextBox const &) = delete; |
681 | | TextBox &operator=(TextBox const &) = delete; |
682 | | }; |
683 | | |
684 | | TextBox::~TextBox() |
685 | 7.93M | { |
686 | 7.93M | } |
687 | | |
688 | | //////////////////////////////////////// |
689 | | //! Internal: the ole zone of a MsWksGraph ( v4) |
690 | | struct OLEZone final : public Zone { |
691 | | //! constructor |
692 | | explicit OLEZone(Zone const &z) |
693 | 134k | : Zone(z) |
694 | 134k | , m_oleId(-1) |
695 | 134k | , m_dim() |
696 | 134k | { } |
697 | | //! destructor |
698 | | ~OLEZone() final; |
699 | | //! return the type |
700 | | Type type() const final |
701 | 102k | { |
702 | 102k | return OLE; |
703 | 102k | } |
704 | | //! operator<< |
705 | | void print(std::ostream &o) const final |
706 | 0 | { |
707 | 0 | if (m_oleId >= 0) o << "ole" << m_oleId << ","; |
708 | 0 | if (m_dim[0] > 0 && m_dim[1] > 0) o << "dim=" << m_dim << ","; |
709 | 0 | Zone::print(o); |
710 | 0 | } |
711 | | |
712 | | //! the ole id |
713 | | int m_oleId; |
714 | | //! the dimension |
715 | | MWAWVec2i m_dim; |
716 | | }; |
717 | | |
718 | | OLEZone::~OLEZone() |
719 | 134k | { |
720 | 134k | } |
721 | | |
722 | | //////////////////////////////////////// |
723 | | //! Internal: the textbox of a MsWksGraph ( v4) |
724 | | struct TextBoxv4 final : public Zone { |
725 | | //! constructor |
726 | | explicit TextBoxv4(Zone const &z) |
727 | 56.5k | : Zone(z) |
728 | 56.5k | , m_text() |
729 | 56.5k | , m_frame("") |
730 | 56.5k | { } |
731 | | //! destructor |
732 | | ~TextBoxv4() final; |
733 | | //! return the type |
734 | | Type type() const final |
735 | 182k | { |
736 | 182k | return Textv4; |
737 | 182k | } |
738 | | //! operator<< |
739 | | void print(std::ostream &o) const final |
740 | 0 | { |
741 | 0 | Zone::print(o); |
742 | 0 | if (m_text.valid()) o << ", textPos=[" << m_text.begin() << "-" << m_text.end() << "]"; |
743 | 0 | } |
744 | | |
745 | | //! add frame parameters to propList (if needed ) |
746 | | void fillFrame(MWAWGraphicStyle &style) const final |
747 | 174k | { |
748 | 174k | if (!m_style.m_baseSurfaceColor.isWhite()) |
749 | 20.0k | style.setBackgroundColor(m_style.m_baseSurfaceColor); |
750 | 174k | } |
751 | | |
752 | | //! the text of positions (0-0: means no text) |
753 | | MWAWEntry m_text; |
754 | | //! the frame name |
755 | | std::string m_frame; |
756 | | }; |
757 | | |
758 | | |
759 | | TextBoxv4::~TextBoxv4() |
760 | 56.5k | { |
761 | 56.5k | } |
762 | | |
763 | | //! Internal the pattern ressource of a MsWksGraph |
764 | | struct Pattern { |
765 | | //! constructor ( 4 int by patterns ) |
766 | | Pattern(int num, uint16_t const *data) |
767 | 209k | : m_num(num) |
768 | 209k | , m_valuesList() |
769 | 209k | , m_percentList() |
770 | 209k | { |
771 | 209k | if (m_num<=0) return; |
772 | 209k | m_valuesList.resize(size_t(m_num)*8); |
773 | 21.9M | for (size_t i=0; i < size_t(m_num)*4; ++i) { |
774 | 21.7M | uint16_t val=data[i]; |
775 | 21.7M | m_valuesList[2*i]=static_cast<unsigned char>(val>>8); |
776 | 21.7M | m_valuesList[2*i+1]=static_cast<unsigned char>(val&0xFF); |
777 | 21.7M | } |
778 | 209k | size_t pat=0; |
779 | 5.63M | for (size_t i=0; i < size_t(num); ++i) { |
780 | 5.42M | int numOnes=0; |
781 | 48.8M | for (int j=0; j < 8; ++j) { |
782 | 43.4M | uint8_t val=m_valuesList[pat++]; |
783 | 390M | for (int b=0; b < 8; b++) { |
784 | 347M | if (val&1) ++numOnes; |
785 | 347M | val = uint8_t(val>>1); |
786 | 347M | } |
787 | 43.4M | } |
788 | 5.42M | m_percentList.push_back(float(numOnes)/64.f); |
789 | 5.42M | } |
790 | 209k | } |
791 | | //! return the pattern corresponding to an id |
792 | | bool get(int id, MWAWGraphicStyle::Pattern &pat) const |
793 | 1.72M | { |
794 | 1.72M | if (id < 0 || id >= m_num) { |
795 | 303k | MWAW_DEBUG_MSG(("MsWksGraphInternal::Pattern::get: can not find pattern %d\n", id)); |
796 | 303k | return false; |
797 | 303k | } |
798 | 1.41M | pat.m_dim=MWAWVec2i(8,8); |
799 | 1.41M | unsigned char const *ptr=&m_valuesList[8*size_t(id)]; |
800 | 1.41M | pat.m_data.resize(8); |
801 | 1.41M | for (auto &data : pat.m_data) |
802 | 11.3M | data=*(ptr++); |
803 | 1.41M | return true; |
804 | 1.72M | } |
805 | | //! return the percentage corresponding to a pattern |
806 | | float getPercent(int id) const |
807 | 2.47M | { |
808 | 2.47M | if (id < 0 || id >= m_num) { |
809 | 235k | MWAW_DEBUG_MSG(("MsWksGraphInternal::Pattern::getPatternPercent: can not find pattern %d\n", id)); |
810 | 235k | return 1.0; |
811 | 235k | } |
812 | 2.23M | return m_percentList[size_t(id)]; |
813 | 2.47M | } |
814 | | |
815 | | //! the number of patterns |
816 | | int m_num; |
817 | | //! the pattern values (8 data by pattern) |
818 | | std::vector<unsigned char> m_valuesList; |
819 | | //! the pattern percent values |
820 | | std::vector<float> m_percentList; |
821 | | }; |
822 | | |
823 | | //////////////////////////////////////// |
824 | | //! Internal: the state of a MsWksGraph |
825 | | struct State { |
826 | | //! constructor |
827 | | State() |
828 | 287k | : m_version(-1) |
829 | 287k | , m_leftTopPos(0,0) |
830 | 287k | , m_zonesList() |
831 | 287k | , m_RBsMap() |
832 | 287k | , m_font(20,12) |
833 | 287k | , m_chartId(0) |
834 | 287k | , m_tableId(0) |
835 | 287k | , m_numPages(0) |
836 | 287k | , m_rsrcPatternMap() |
837 | 287k | { |
838 | 287k | } |
839 | | //! return the pattern corresponding to an id |
840 | | bool getPattern(MWAWGraphicStyle::Pattern &pat, int id, long rsid=-1); |
841 | | //! return the percentage corresponding to a pattern |
842 | | float getPatternPercent(int id, long rsid=-1); |
843 | | //! init the pattern value |
844 | | void initPattern(int vers); |
845 | | //! the version |
846 | | int m_version; |
847 | | //! the page left top position in points |
848 | | MWAWVec2f m_leftTopPos; |
849 | | //! the list of zone |
850 | | std::vector<std::shared_ptr<Zone> > m_zonesList; |
851 | | //! the RBIL zone id->list id |
852 | | std::map<int, RBZone> m_RBsMap; |
853 | | //! the actual font |
854 | | MWAWFont m_font; |
855 | | //! an index used to store chart |
856 | | int m_chartId; |
857 | | //! an index used to store table |
858 | | int m_tableId; |
859 | | //! the number of pages |
860 | | int m_numPages; |
861 | | //! a map ressource id -> patterns |
862 | | std::map<long, Pattern> m_rsrcPatternMap; |
863 | | }; |
864 | | |
865 | | void State::initPattern(int vers) |
866 | 36.8k | { |
867 | 36.8k | if (!m_rsrcPatternMap.empty()) return; |
868 | 36.8k | if (vers <= 2) { |
869 | 24.8k | static uint16_t const valuesV2[] = { |
870 | 24.8k | 0xffff, 0xffff, 0xffff, 0xffff, 0xddff, 0x77ff, 0xddff, 0x77ff, 0xdd77, 0xdd77, 0xdd77, 0xdd77, 0xaa55, 0xaa55, 0xaa55, 0xaa55, |
871 | 24.8k | 0x55ff, 0x55ff, 0x55ff, 0x55ff, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, 0xeedd, 0xbb77, 0xeedd, 0xbb77, 0x8888, 0x8888, 0x8888, 0x8888, |
872 | 24.8k | 0xb130, 0x031b, 0xd8c0, 0x0c8d, 0x8010, 0x0220, 0x0108, 0x4004, 0xff88, 0x8888, 0xff88, 0x8888, 0xff80, 0x8080, 0xff08, 0x0808, |
873 | 24.8k | 0x0000, 0x0002, 0x0000, 0x0002, 0x8040, 0x2000, 0x0204, 0x0800, 0x8244, 0x3944, 0x8201, 0x0101, 0xf874, 0x2247, 0x8f17, 0x2271, |
874 | 24.8k | 0x55a0, 0x4040, 0x550a, 0x0404, 0x2050, 0x8888, 0x8888, 0x0502, 0xbf00, 0xbfbf, 0xb0b0, 0xb0b0, 0x0000, 0x0000, 0x0000, 0x0000, |
875 | 24.8k | 0x8000, 0x0800, 0x8000, 0x0800, 0x8800, 0x2200, 0x8800, 0x2200, 0x8822, 0x8822, 0x8822, 0x8822, 0xaa00, 0xaa00, 0xaa00, 0xaa00, |
876 | 24.8k | 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x1122, 0x4488, 0x1122, 0x4488, 0x8040, 0x2000, 0x0204, 0x0800, 0x0102, 0x0408, 0x1020, 0x4080, |
877 | 24.8k | 0xaa00, 0x8000, 0x8800, 0x8000, 0xff80, 0x8080, 0x8080, 0x8080, 0x0814, 0x2241, 0x8001, 0x0204, 0x8814, 0x2241, 0x8800, 0xaa00, |
878 | 24.8k | 0x40a0, 0x0000, 0x040a, 0x0000, 0x0384, 0x4830, 0x0c02, 0x0101, 0x8080, 0x413e, 0x0808, 0x14e3, 0x1020, 0x54aa, 0xff02, 0x0408, |
879 | 24.8k | 0x7789, 0x8f8f, 0x7798, 0xf8f8, 0x0008, 0x142a, 0x552a, 0x1408, 0x0000, 0x0000, 0x0000, 0x0000, |
880 | 24.8k | }; |
881 | 24.8k | m_rsrcPatternMap.insert(std::map<long, Pattern>::value_type(-1,Pattern(39, valuesV2))); |
882 | 24.8k | } |
883 | 36.8k | static uint16_t const values4002[] = { |
884 | 36.8k | 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff, 0xffff, 0xf7ff, 0xffff, 0x7fff, 0xf7ff, 0x7fff, 0xf7ff, 0x77ff, 0xddff, 0x77ff, 0xddff, |
885 | 36.8k | 0x55ff, 0xddff, 0x55ff, 0xddff, 0x55ff, 0xeeff, 0x55ff, 0xbbff, 0x55ff, 0x55ff, 0x55ff, 0x55ff, 0x77dd, 0x77dd, 0x77dd, 0x77dd, |
886 | 36.8k | 0x55bf, 0x55ff, 0x55fb, 0x55ff, 0x55bb, 0x55ff, 0x55bb, 0x55ff, 0x55bf, 0x55ee, 0x55fb, 0x55ee, 0x55bb, 0x55ee, 0x55bb, 0x55ee, |
887 | 36.8k | 0x55bb, 0x55ea, 0x55bb, 0x55ae, 0x55ba, 0x55ab, 0x55ba, 0x55ab, 0x55ea, 0x55aa, 0x55ae, 0x55aa, 0xaa55, 0xaa55, 0xaa55, 0xaa55, |
888 | 36.8k | 0xaa15, 0xaa55, 0xaa51, 0xaa55, 0xaa45, 0xaa54, 0xaa45, 0xaa54, 0xaa44, 0xaa15, 0xaa44, 0xaa51, 0xaa44, 0xaa11, 0xaa44, 0xaa11, |
889 | 36.8k | 0xaa40, 0xaa11, 0xaa04, 0xaa11, 0xaa44, 0xaa00, 0xaa44, 0xaa00, 0xaa40, 0xaa00, 0xaa04, 0xaa00, 0x8822, 0x8822, 0x8822, 0x8822, |
890 | 36.8k | 0xaa00, 0xaa00, 0xaa00, 0xaa00, 0xaa00, 0x1100, 0xaa00, 0x4400, 0xaa00, 0x2200, 0xaa00, 0x2200, 0x8800, 0x2200, 0x8800, 0x2200, |
891 | 36.8k | 0x8800, 0x2000, 0x8800, 0x0200, 0x8000, 0x0800, 0x8000, 0x0800, 0x8000, 0x0000, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 |
892 | 36.8k | }; |
893 | 36.8k | m_rsrcPatternMap.insert(std::map<long, Pattern>::value_type(4002,Pattern(32, values4002))); |
894 | 36.8k | static uint16_t const values4003[] = { |
895 | 36.8k | 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x0000, 0x0800, 0x0000, 0x8000, 0x0800, 0x8000, 0x0800, 0x8800, 0x2000, 0x8800, 0x0200, |
896 | 36.8k | 0x8800, 0x2200, 0x8800, 0x2200, 0xaa00, 0x2200, 0xaa00, 0x2200, 0xaa00, 0x1100, 0xaa00, 0x4400, 0xaa00, 0xaa00, 0xaa00, 0xaa00, |
897 | 36.8k | 0x8822, 0x8822, 0x8822, 0x8822, 0xaa44, 0xaa11, 0xaa44, 0xaa11, 0xaa45, 0xaa54, 0xaa45, 0xaa54, 0xaa55, 0xaa55, 0xaa55, 0xaa55, |
898 | 36.8k | 0x55ea, 0x55aa, 0x55ae, 0x55aa, 0x55ba, 0x55ab, 0x55ba, 0x55ab, 0x55bb, 0x55ee, 0x55bb, 0x55ee, 0x77dd, 0x77dd, 0x77dd, 0x77dd, |
899 | 36.8k | 0x55ff, 0x55ff, 0x55ff, 0x55ff, 0x55ff, 0xeeff, 0x55ff, 0xbbff, 0x77ff, 0xddff, 0x77ff, 0xddff, 0x7fff, 0xf7ff, 0x7fff, 0xf7ff, |
900 | 36.8k | 0x7fff, 0xffff, 0xf7ff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff |
901 | 36.8k | }; |
902 | 36.8k | m_rsrcPatternMap.insert(std::map<long, Pattern>::value_type(4003,Pattern(22, values4003))); |
903 | 36.8k | static uint16_t const values4004[] = { |
904 | 36.8k | 0xf0f0, 0xf0f0, 0x0f0f, 0x0f0f, 0xcccc, 0x3333, 0xcccc, 0x3333, 0x3333, 0xcccc, 0x3333, 0xcccc |
905 | 36.8k | }; |
906 | 36.8k | m_rsrcPatternMap.insert(std::map<long, Pattern>::value_type(4004,Pattern(3, values4004))); |
907 | 36.8k | static uint16_t const values7000[] = { |
908 | 36.8k | 0x0101, 0x1010, 0x0101, 0x1010, 0xcc00, 0x0000, 0x3300, 0x0000, 0x1122, 0x4400, 0x1122, 0x4400, 0x4422, 0x0088, 0x4422, 0x0088, |
909 | 36.8k | 0xf0f0, 0xf0f0, 0x0f0f, 0x0f0f, 0x9966, 0x6699, 0x9966, 0x6699, 0x0008, 0x1c3e, 0x7f3e, 0x1c08, 0x0008, 0x142a, 0x552a, 0x1408, |
910 | 36.8k | 0xb130, 0x031b, 0xd8c0, 0x0c8d, 0x8010, 0x0220, 0x0108, 0x4004, 0x0814, 0x2241, 0x8001, 0x0204, 0x80c0, 0x2112, 0x0c04, 0x0201, |
911 | 36.8k | 0xff80, 0x8080, 0xff08, 0x0808, 0x007f, 0x7f7f, 0x00f7, 0xf7f7, 0x8040, 0x2000, 0x0204, 0x0800, 0x8244, 0x3944, 0x8201, 0x0101, |
912 | 36.8k | 0xf078, 0x2442, 0x870f, 0x1221, 0x1020, 0x54aa, 0xff02, 0x0408, 0xf874, 0x2247, 0x8f17, 0x2271, 0xbfa0, 0xbfbd, 0xbdfd, 0x05fd, |
913 | 36.8k | 0x2050, 0x8888, 0x8888, 0x0502, 0x55a0, 0x4040, 0x550a, 0x0404, 0x8844, 0x2211, 0x1122, 0x4488, 0x8142, 0x2418, 0x8142, 0x2418, |
914 | 36.8k | 0xaa00, 0x8000, 0x8800, 0x8000, 0x0384, 0x4830, 0x0c02, 0x0101, 0x8080, 0x413e, 0x0808, 0x14e3, 0xaf5f, 0xaf5f, 0x0d0b, 0x0d0b, |
915 | 36.8k | 0x7789, 0x8f8f, 0x7798, 0xf8f8, 0x8814, 0x2241, 0x8800, 0xaa00, 0x40a0, 0x0000, 0x040a, 0x0000, 0xbf00, 0xbfbf, 0xb0b0, 0xb0b0 |
916 | 36.8k | }; |
917 | 36.8k | m_rsrcPatternMap.insert(std::map<long, Pattern>::value_type(7000,Pattern(32, values7000))); |
918 | 36.8k | static uint16_t const values14001[] = { |
919 | 36.8k | 0x8844, 0x2211, 0x8844, 0x2211, 0x77bb, 0xddee, 0x77bb, 0xddee, 0x1122, 0x4488, 0x1122, 0x4488, 0xeedd, 0xbb77, 0xeedd, 0xbb77, |
920 | 36.8k | 0x8040, 0x2010, 0x0804, 0x0201, 0x7fbf, 0xdfef, 0xf7fb, 0xfdfe, 0x0102, 0x0408, 0x1020, 0x4080, 0xfefd, 0xfbf7, 0xefdf, 0xbf7f, |
921 | 36.8k | 0xe070, 0x381c, 0x0e07, 0x83c1, 0x99cc, 0x6633, 0x99cc, 0x6633, 0x8307, 0x0e1c, 0x3870, 0xe0c1, 0x3366, 0xcc99, 0x3366, 0xcc99, |
922 | 36.8k | 0x8142, 0x2418, 0x1824, 0x4281, 0x7ebd, 0xdbe7, 0xe7db, 0xbd7e, 0x8244, 0x2810, 0x2844, 0x8201, 0x7dbb, 0xd7ef, 0xd7bb, 0x7dfe, |
923 | 36.8k | 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x8888, 0x8888, 0x8888, 0x8888, 0x7777, 0x7777, 0x7777, 0x7777, |
924 | 36.8k | 0xff00, 0x0000, 0xff00, 0x0000, 0x00ff, 0xffff, 0x00ff, 0xffff, 0x8080, 0x8080, 0x8080, 0x8080, 0x7f7f, 0x7f7f, 0x7f7f, 0x7f7f, |
925 | 36.8k | 0xff00, 0x0000, 0x0000, 0x0000, 0x00ff, 0xffff, 0xffff, 0xffff, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xffff, 0x0000, 0xffff, 0x0000, |
926 | 36.8k | 0xff88, 0x8888, 0xff88, 0x8888, 0x0077, 0x7777, 0x0077, 0x7777, 0xff80, 0x8080, 0x8080, 0x8080, 0x007f, 0x7f7f, 0x7f7f, 0x7f7f |
927 | 36.8k | }; |
928 | 36.8k | m_rsrcPatternMap.insert(std::map<long, Pattern>::value_type(14001,Pattern(32, values14001))); |
929 | 36.8k | } |
930 | | |
931 | | float State::getPatternPercent(int id, long rsid) |
932 | 2.47M | { |
933 | 2.47M | if (m_rsrcPatternMap.empty()) |
934 | 24.8k | initPattern(m_version); |
935 | 2.47M | if (m_rsrcPatternMap.find(rsid)==m_rsrcPatternMap.end()) { |
936 | 0 | MWAW_DEBUG_MSG(("MsWksGraphInternal::State::getPatternPercent unknown map for rsdid=%ld\n",rsid)); |
937 | 0 | return 1.0; |
938 | 0 | } |
939 | 2.47M | return m_rsrcPatternMap.find(rsid)->second.getPercent(id); |
940 | 2.47M | } |
941 | | |
942 | | bool State::getPattern(MWAWGraphicStyle::Pattern &pat, int id, long rsid) |
943 | 12.3M | { |
944 | 12.3M | if (m_rsrcPatternMap.empty()) |
945 | 11.9k | initPattern(m_version); |
946 | 12.3M | if (m_rsrcPatternMap.find(rsid)==m_rsrcPatternMap.end()) { |
947 | 10.6M | MWAW_DEBUG_MSG(("MsWksGraphInternal::State::getPattern unknown map for rsdid=%ld\n",rsid)); |
948 | 10.6M | return false; |
949 | 10.6M | } |
950 | 1.72M | return m_rsrcPatternMap.find(rsid)->second.get(id, pat); |
951 | 12.3M | } |
952 | | |
953 | | //////////////////////////////////////// |
954 | | //! Internal: the subdocument of a MsWksGraph |
955 | | class SubDocument final : public MWAWSubDocument |
956 | | { |
957 | | public: |
958 | | enum Type { RBILZone, Chart, Empty, Group, Table, TextBox, TextBoxv4 }; |
959 | | SubDocument(MsWksGraph &pars, MWAWInputStreamPtr const &input, Type type, int zoneId) |
960 | 25.8k | : MWAWSubDocument(pars.m_mainParser, input, MWAWEntry()) |
961 | 25.8k | , m_graphParser(&pars) |
962 | 25.8k | , m_type(type) |
963 | 25.8k | , m_id(zoneId) |
964 | 25.8k | , m_frame("") |
965 | 25.8k | { |
966 | 25.8k | } |
967 | | SubDocument(MsWksGraph &pars, MWAWInputStreamPtr const &input, Type type, |
968 | | MWAWEntry const &entry, std::string const &frame=std::string("")) |
969 | 174k | : MWAWSubDocument(pars.m_mainParser, input, entry) |
970 | 174k | , m_graphParser(&pars) |
971 | 174k | , m_type(type) |
972 | 174k | , m_id(-1) |
973 | 174k | , m_frame(frame) |
974 | 174k | { |
975 | 174k | } |
976 | | |
977 | | //! destructor |
978 | 200k | ~SubDocument() final {} |
979 | | |
980 | | //! operator!= |
981 | | bool operator!=(MWAWSubDocument const &doc) const final; |
982 | | |
983 | | //! the parser function |
984 | | void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final; |
985 | | private: |
986 | | SubDocument(SubDocument const &orig) = delete; |
987 | | SubDocument &operator=(SubDocument const &orig) = delete; |
988 | | |
989 | | protected: |
990 | | /** the graph parser */ |
991 | | MsWksGraph *m_graphParser; |
992 | | /** the type */ |
993 | | Type m_type; |
994 | | /** the subdocument id*/ |
995 | | int m_id; |
996 | | /** the frame name: for textv4 */ |
997 | | std::string m_frame; |
998 | | }; |
999 | | |
1000 | | void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/) |
1001 | 200k | { |
1002 | 200k | if (!listener.get()) { |
1003 | 0 | MWAW_DEBUG_MSG(("MsWksGraphInternal::SubDocument::parse: no listener\n")); |
1004 | 0 | return; |
1005 | 0 | } |
1006 | 200k | if (!m_graphParser) { |
1007 | 0 | MWAW_DEBUG_MSG(("MsWksGraphInternal::SubDocument::parse: no parser\n")); |
1008 | 0 | return; |
1009 | 0 | } |
1010 | | |
1011 | 200k | long pos = m_input->tell(); |
1012 | 200k | switch (m_type) { |
1013 | 0 | case Empty: |
1014 | 0 | break; |
1015 | 364 | case Chart: |
1016 | 364 | m_graphParser->sendChart(m_id); |
1017 | 364 | break; |
1018 | 737 | case Group: { |
1019 | 737 | MWAWPosition gPos; |
1020 | 737 | gPos.setRelativePosition(MWAWPosition::Frame, |
1021 | 737 | MWAWPosition::XLeft, MWAWPosition::YTop); |
1022 | 737 | m_graphParser->sendGroupChild(m_id, gPos); |
1023 | 737 | break; |
1024 | 0 | } |
1025 | 0 | case Table: |
1026 | 0 | m_graphParser->sendTable(m_id); |
1027 | 0 | break; |
1028 | 24.7k | case TextBox: |
1029 | 24.7k | m_graphParser->sendTextBox(m_id, listener); |
1030 | 24.7k | break; |
1031 | 174k | case TextBoxv4: |
1032 | 174k | m_graphParser->sendFrameText(m_zone, m_frame); |
1033 | 174k | break; |
1034 | 0 | case RBILZone: { |
1035 | 0 | MsWksGraph::SendData sendData; |
1036 | 0 | sendData.m_type = MsWksGraph::SendData::RBIL; |
1037 | 0 | sendData.m_id = m_id; |
1038 | 0 | sendData.m_anchor = MWAWPosition::Frame; |
1039 | 0 | m_graphParser->sendObjects(sendData); |
1040 | 0 | break; |
1041 | 0 | } |
1042 | | #if !defined(__clang__) |
1043 | | default: |
1044 | | MWAW_DEBUG_MSG(("MsWksGraph::SubDocument::parse: unexpected zone type\n")); |
1045 | | break; |
1046 | | #endif |
1047 | 200k | } |
1048 | 200k | m_input->seek(pos, librevenge::RVNG_SEEK_SET); |
1049 | 200k | } |
1050 | | |
1051 | | bool SubDocument::operator!=(MWAWSubDocument const &doc) const |
1052 | 139k | { |
1053 | 139k | if (MWAWSubDocument::operator!=(doc)) return true; |
1054 | 18.5k | auto const *sDoc = dynamic_cast<SubDocument const *>(&doc); |
1055 | 18.5k | if (!sDoc) return true; |
1056 | 0 | if (m_graphParser != sDoc->m_graphParser) return true; |
1057 | 0 | if (m_id != sDoc->m_id) return true; |
1058 | 0 | if (m_type != sDoc->m_type) return true; |
1059 | 0 | if (m_frame != sDoc->m_frame) return true; |
1060 | 0 | return false; |
1061 | 0 | } |
1062 | | |
1063 | | } |
1064 | | |
1065 | | //////////////////////////////////////////////////////////// |
1066 | | // constructor/destructor, ... |
1067 | | //////////////////////////////////////////////////////////// |
1068 | | MsWksGraph::MsWksGraph(MsWksDocument &document) |
1069 | 287k | : m_parserState() |
1070 | 287k | , m_state(new MsWksGraphInternal::State) |
1071 | 287k | , m_mainParser(&document.getMainParser()) |
1072 | 287k | , m_document(document) |
1073 | 287k | , m_tableParser() |
1074 | 287k | { |
1075 | 287k | m_parserState=m_mainParser->getParserState(); |
1076 | 287k | m_tableParser.reset(new MsWksTable(*m_mainParser, m_document, *this)); |
1077 | 287k | } |
1078 | | |
1079 | | MsWksGraph::~MsWksGraph() |
1080 | 287k | { |
1081 | 287k | } |
1082 | | |
1083 | | void MsWksGraph::setPageLeftTop(MWAWVec2f const &leftTop) |
1084 | 74.0k | { |
1085 | 74.0k | m_state->m_leftTopPos=leftTop; |
1086 | 74.0k | } |
1087 | | |
1088 | | int MsWksGraph::version() const |
1089 | 109M | { |
1090 | 109M | if (m_state->m_version < 0) |
1091 | 77.4k | m_state->m_version = m_parserState->m_version; |
1092 | 109M | return m_state->m_version; |
1093 | 109M | } |
1094 | | |
1095 | | int MsWksGraph::numPages(int zoneId) const |
1096 | 77.5k | { |
1097 | 77.5k | if (m_state->m_numPages > 0) |
1098 | 3.48k | return m_state->m_numPages; |
1099 | | |
1100 | 74.0k | int maxPage = 0; |
1101 | 1.24M | for (auto const &zone : m_state->m_zonesList) { |
1102 | 1.24M | if (zoneId >= 0 && zone->m_zoneId!=zoneId) continue; |
1103 | 1.12M | if (zone->m_page > maxPage) |
1104 | 8.37k | maxPage = zone->m_page; |
1105 | 1.12M | } |
1106 | 74.0k | m_state->m_numPages = maxPage+1; |
1107 | 74.0k | return m_state->m_numPages; |
1108 | 77.5k | } |
1109 | | |
1110 | | void MsWksGraph::sendFrameText(MWAWEntry const &entry, std::string const &frame) |
1111 | 174k | { |
1112 | 174k | m_document.sendTextbox(entry, frame); |
1113 | 174k | } |
1114 | | |
1115 | | void MsWksGraph::sendChart(int zoneId) |
1116 | 364 | { |
1117 | 364 | m_tableParser->sendChart(zoneId); |
1118 | 364 | } |
1119 | | |
1120 | | void MsWksGraph::sendTable(int zoneId) |
1121 | 0 | { |
1122 | 0 | m_tableParser->sendTable(zoneId); |
1123 | 0 | } |
1124 | | |
1125 | | //////////////////////////////////////////////////////////// |
1126 | | // |
1127 | | // Intermediate level |
1128 | | // |
1129 | | //////////////////////////////////////////////////////////// |
1130 | | bool MsWksGraph::getZoneGraphicStyle(int id, MWAWGraphicStyle &style) const |
1131 | 0 | { |
1132 | 0 | if (id<0 || id>=int(m_state->m_zonesList.size()) || !m_state->m_zonesList[size_t(id)]) { |
1133 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::getZoneGraphicStyle: unknown zone %d\n", id)); |
1134 | 0 | return false; |
1135 | 0 | } |
1136 | 0 | style = m_state->m_zonesList[size_t(id)]->m_style; |
1137 | 0 | return true; |
1138 | 0 | } |
1139 | | |
1140 | | bool MsWksGraph::getZonePosition(int id, MWAWPosition::AnchorTo anchor, MWAWPosition &pos) const |
1141 | 1.45k | { |
1142 | 1.45k | if (id<0 || id>=int(m_state->m_zonesList.size()) || !m_state->m_zonesList[size_t(id)]) { |
1143 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::getZoneGraphicStyle: unknown zone %d\n", id)); |
1144 | 0 | return false; |
1145 | 0 | } |
1146 | 1.45k | pos = m_state->m_zonesList[size_t(id)]->getPosition(anchor); |
1147 | 1.45k | return true; |
1148 | 1.45k | } |
1149 | | |
1150 | | bool MsWksGraph::readPictHeader(MsWksGraphInternal::Zone &pict) |
1151 | 53.4M | { |
1152 | 53.4M | MWAWInputStreamPtr input=m_document.getInput(); |
1153 | 53.4M | long pos=input->tell(); |
1154 | 53.4M | int vers = version(); |
1155 | 53.4M | if (!input->checkPosition(pos+(vers>=3 ? 54 : 38)) || input->readULong(1) != 0) return false; |
1156 | 43.4M | pict = MsWksGraphInternal::Zone(); |
1157 | 43.4M | pict.m_subType = static_cast<int>(input->readULong(1)); |
1158 | 43.4M | if (pict.m_subType > 0x10 || pict.m_subType == 6 || pict.m_subType == 0xb) |
1159 | 1.78M | return false; |
1160 | 41.6M | if (pict.m_subType>9) { |
1161 | 16.2M | if (vers<=2) |
1162 | 3.30k | return false; |
1163 | | // we can find chart in v3 spreadsheet file |
1164 | 16.2M | else if (vers==3 && pict.m_subType != 0xa && m_parserState->m_type!=MWAWParserState::Spreadsheet) |
1165 | 512k | return false; |
1166 | 16.2M | } |
1167 | 41.1M | libmwaw::DebugStream f; |
1168 | 41.1M | int val; |
1169 | 41.1M | if (vers >= 3) { |
1170 | 40.2M | val = static_cast<int>(input->readLong(2)); |
1171 | 40.2M | if (vers == 4 || m_parserState->m_type==MWAWParserState::Graphic) |
1172 | 29.0M | pict.m_page = val==0 ? -2 : val-1; |
1173 | 11.1M | else if (val) |
1174 | 7.37M | f << "f0=" << val << ","; |
1175 | 40.2M | } |
1176 | | // color |
1177 | 41.1M | Style &style=pict.m_style; |
1178 | 123M | for (int i = 0; i < 2; i++) { |
1179 | 82.2M | auto rId = static_cast<int>(input->readLong(2)); |
1180 | 82.2M | int cId = (vers <= 2) ? rId+1 : rId; |
1181 | 82.2M | MWAWColor col; |
1182 | 82.2M | if (m_document.getColor(cId,col,vers <= 3 ? vers : 3)) { |
1183 | 24.2M | if (i) style.m_baseSurfaceColor = col; |
1184 | 9.85M | else style.m_baseLineColor = col; |
1185 | 24.2M | } |
1186 | 58.0M | else |
1187 | 58.0M | f << "#col" << i << "=" << rId << ","; |
1188 | 82.2M | } |
1189 | 41.1M | bool hasSurfPatFunction=false; |
1190 | 41.1M | if (vers <= 2) { |
1191 | 2.72M | for (int i = 0; i < 2; i++) { |
1192 | 1.81M | auto pId = static_cast<int>(input->readLong(2)); |
1193 | 1.81M | if (pId==38) { // empty |
1194 | 6.17k | if (i==0) |
1195 | 4.91k | style.m_lineWidth=0; |
1196 | 6.17k | continue; |
1197 | 6.17k | } |
1198 | 1.80M | float percent = m_state->getPatternPercent(pId); |
1199 | 1.80M | MWAWGraphicStyle::Pattern pattern; |
1200 | 1.80M | if (i==0) |
1201 | 902k | style.m_lineColor=MWAWColor::barycenter(percent, style.m_baseLineColor, 1.f-percent, style.m_baseSurfaceColor); |
1202 | 905k | else if (m_state->getPattern(pattern, pId)) { |
1203 | 755k | pattern.m_colors[0] = style.m_baseSurfaceColor; |
1204 | 755k | pattern.m_colors[1] = style.m_baseLineColor; |
1205 | 755k | style.setPattern(pattern); |
1206 | 755k | } |
1207 | 150k | else |
1208 | 150k | style.setSurfaceColor(MWAWColor::barycenter(percent, style.m_baseLineColor, 1.f-percent, style.m_baseSurfaceColor)); |
1209 | 1.80M | } |
1210 | 907k | auto lineType=static_cast<int>(input->readLong(2)); |
1211 | 907k | if (style.m_lineWidth>0) { |
1212 | 902k | switch (lineType) { |
1213 | 701k | case 0: |
1214 | 701k | style.m_lineWidth=0.; |
1215 | 701k | break; |
1216 | 14.1k | case 1: |
1217 | 14.1k | style.m_lineWidth=0.5; |
1218 | 14.1k | break; |
1219 | 12.2k | case 2: // lineW=1 |
1220 | 12.2k | break; |
1221 | 26.5k | case 3: |
1222 | 26.5k | style.m_lineWidth=2; |
1223 | 26.5k | break; |
1224 | 4.95k | case 4: |
1225 | 4.95k | style.m_lineWidth=4; |
1226 | 4.95k | break; |
1227 | 143k | default: |
1228 | 143k | f << "#lineType=" << lineType << ","; |
1229 | 143k | break; |
1230 | 902k | } |
1231 | 902k | } |
1232 | 907k | } |
1233 | 40.2M | else { |
1234 | 40.2M | style.m_lineColor=style.m_baseLineColor; |
1235 | 40.2M | style.m_surfaceColor=style.m_baseSurfaceColor; |
1236 | 120M | for (int i = 0; i < 2; i++) { |
1237 | 80.4M | if (i) f << "surface"; |
1238 | 40.2M | else f << "line"; |
1239 | 80.4M | f << "Pattern=["; |
1240 | 80.4M | long rsid= input->readLong(2); |
1241 | 80.4M | if (rsid==0) f << "noColor,"; |
1242 | 56.4M | else if (rsid==-1) f << "grad,"; |
1243 | 45.9M | else f << "rsid=" << rsid << ","; |
1244 | 80.4M | auto patId = static_cast<int>(input->readULong(2)); |
1245 | 80.4M | if (patId) f << "pat=" << patId << ","; |
1246 | 25.1M | else f << "_"; |
1247 | 80.4M | if (vers==4 && rsid==-1 && patId==0xFFFF) |
1248 | 5.78M | hasSurfPatFunction=true; |
1249 | 80.4M | val = static_cast<int>(input->readLong(1)); |
1250 | 80.4M | if (val) f << "unkn=" << val << ","; |
1251 | 80.4M | auto per = static_cast<int>(input->readULong(1)); |
1252 | 80.4M | f << per << "%,"; |
1253 | 80.4M | if (rsid<=0) { |
1254 | 42.9M | if (i==0 && rsid==0) |
1255 | 13.4M | style.m_lineWidth=0.; |
1256 | 42.9M | } |
1257 | 37.4M | else { |
1258 | 37.4M | float percent=1.0; |
1259 | 37.4M | bool done=false; |
1260 | 37.4M | MWAWGraphicStyle::Pattern pattern; |
1261 | 37.4M | if (per >= 0 && per < 100) |
1262 | 26.0M | percent = float(per)/100.f; |
1263 | 11.4M | else if (m_state->getPattern(pattern, patId, rsid)) { |
1264 | 663k | percent = m_state->getPatternPercent(patId, rsid); |
1265 | 663k | if (i) { |
1266 | 294k | pattern.m_colors[0] = style.m_baseSurfaceColor; |
1267 | 294k | pattern.m_colors[1] = style.m_baseLineColor; |
1268 | 294k | style.setPattern(pattern); |
1269 | 294k | done = true; |
1270 | 294k | } |
1271 | 663k | } |
1272 | 10.8M | else { |
1273 | 10.8M | MWAW_DEBUG_MSG(("MsWksGraph::readPictHeader:find odd pattern\n")); |
1274 | 10.8M | f << "##"; |
1275 | 10.8M | } |
1276 | 37.4M | if (done) { |
1277 | 294k | } |
1278 | 37.2M | else if (i==0) |
1279 | 17.9M | style.m_lineColor=MWAWColor::barycenter(percent, style.m_baseLineColor, 1.f-percent, style.m_baseSurfaceColor); |
1280 | 19.3M | else |
1281 | 19.3M | style.setSurfaceColor(MWAWColor::barycenter(percent, style.m_baseLineColor, 1.f-percent, style.m_baseSurfaceColor)); |
1282 | 37.4M | } |
1283 | 80.4M | f << "],"; |
1284 | 80.4M | } |
1285 | 40.2M | int penSize[2]; |
1286 | 80.4M | for (auto &pSize : penSize) pSize = static_cast<int>(input->readLong(2)); |
1287 | 40.2M | if (style.m_lineWidth<=0) |
1288 | 13.4M | f << "pen=" << penSize[0] << "x" << penSize[1] << ","; |
1289 | 26.7M | else if (penSize[0]==penSize[1]) |
1290 | 7.62M | style.m_lineWidth=float(penSize[0]); |
1291 | 19.1M | else { |
1292 | 19.1M | f << "pen=" << penSize[0] << "x" << penSize[1] << ","; |
1293 | 19.1M | style.m_lineWidth=0.5f*float(penSize[0]+penSize[1]); |
1294 | 19.1M | } |
1295 | 40.2M | if (style.m_lineWidth < 0 || style.m_lineWidth > 10) { |
1296 | 21.6M | f << "##penSize=" << style.m_lineWidth << ","; |
1297 | 21.6M | style.m_lineWidth = 1; |
1298 | 21.6M | } |
1299 | 40.2M | val = static_cast<int>(input->readLong(2)); |
1300 | 40.2M | if (val) |
1301 | 23.9M | f << "f1=" << val << ","; |
1302 | 40.2M | } |
1303 | | |
1304 | 41.1M | float offset[4]; |
1305 | 164M | for (auto &off : offset) off = float(input->readLong(2)); |
1306 | 41.1M | pict.m_decal = MWAWBox2f(MWAWVec2f(offset[0],offset[1]), MWAWVec2f(offset[3],offset[2])); |
1307 | 41.1M | pict.m_finalDecal = MWAWVec2f(float(offset[0]+offset[3]), float(offset[1]+offset[2])); |
1308 | | |
1309 | | // the two point which allows to create the form ( in general the bdbox) |
1310 | 41.1M | float dim[4]; |
1311 | 164M | for (auto &d : dim) d = float(input->readLong(4))/65536.f; |
1312 | 41.1M | pict.m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]),MWAWVec2f(dim[2],dim[3])); |
1313 | | |
1314 | 41.1M | auto flags = static_cast<int>(input->readLong(1)); |
1315 | | // 2: rotations, 1:lock ?, 0: nothing, other ? |
1316 | 41.1M | if (vers >= 4 && (flags&1)) { |
1317 | 8.51M | f << "locked,"; |
1318 | 8.51M | flags &= 0xFE; |
1319 | 8.51M | } |
1320 | 41.1M | if (vers >= 4 && (flags&2)) { |
1321 | 5.99M | f << "Rot=["; |
1322 | 197M | for (int i = 0; i < 32; i++) |
1323 | 191M | f << input->readLong(2) << ","; |
1324 | 5.99M | f << "],"; |
1325 | 5.99M | flags &= 0xFC; |
1326 | 5.99M | } |
1327 | 41.1M | if (flags) f << "fl0=" << flags << ","; |
1328 | 41.1M | auto lineFlags = static_cast<int>(input->readULong(1)); |
1329 | 41.1M | switch (lineFlags&3) { |
1330 | 4.48M | case 2: |
1331 | 4.48M | style.m_arrows[0]=MWAWGraphicStyle::Arrow::plain(); |
1332 | 4.48M | MWAW_FALLTHROUGH; |
1333 | 10.4M | case 1: |
1334 | 10.4M | style.m_arrows[1]=MWAWGraphicStyle::Arrow::plain(); |
1335 | 10.4M | break; |
1336 | 4.49M | default: |
1337 | 4.49M | f << "#arrow=3,"; |
1338 | 4.49M | break; |
1339 | 26.1M | case 0: |
1340 | 26.1M | break; |
1341 | 41.1M | } |
1342 | 41.1M | if (lineFlags&0xFC) f << "#lineFlags=" << std::hex << (lineFlags&0xFC) << std::dec << ","; |
1343 | 41.1M | if (vers >= 3) pict.m_ids[0] = long(input->readULong(4)); |
1344 | 41.1M | if (vers >= 4 && hasSurfPatFunction) { |
1345 | 4.08M | pos = input->tell(); |
1346 | 4.08M | if (!readGradient(style)) { |
1347 | 851k | f << "##gradient,"; |
1348 | 851k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1349 | 851k | } |
1350 | 4.08M | } |
1351 | 41.1M | pict.m_extra = f.str(); |
1352 | 41.1M | pict.m_dataPos = input->tell(); |
1353 | 41.1M | return true; |
1354 | 41.1M | } |
1355 | | |
1356 | | bool MsWksGraph::readGradient(MsWksGraph::Style &style) |
1357 | 4.08M | { |
1358 | 4.08M | MWAWInputStreamPtr input=m_document.getInput(); |
1359 | 4.08M | long pos = input->tell(); |
1360 | | |
1361 | 4.08M | if (!input->checkPosition(pos+22)) |
1362 | 851k | return false; |
1363 | | |
1364 | 3.23M | libmwaw::DebugStream f; |
1365 | 3.23M | f << "gradient[unknown]=["; |
1366 | 3.23M | auto type=static_cast<int>(input->readLong(2)); |
1367 | 3.23M | auto val=static_cast<int>(input->readLong(2)); // always 0? |
1368 | 3.23M | if (val) f << "f0=" << val << ","; |
1369 | 3.23M | val=static_cast<int>(input->readLong(1)); // always 8? |
1370 | 3.23M | if (val!=8) f << "f1=" << val << ","; |
1371 | 3.23M | val=static_cast<int>(input->readLong(2)); // find 1 in square |
1372 | 3.23M | if (val) f << "f2=" << val << ","; |
1373 | 3.23M | val=static_cast<int>(input->readULong(2)); // always 0 ? |
1374 | 3.23M | if (val) f << "f3=" << std::hex << val << std::dec << ","; |
1375 | 3.23M | auto angle =static_cast<int>(input->readLong(2)); |
1376 | 3.23M | val=static_cast<int>(input->readLong(2)); // 89[square]|156[square:linearbi]|255 |
1377 | 3.23M | if (val!=0xff) f << "f4=" << val << ","; |
1378 | 3.23M | val=static_cast<int>(input->readLong(2)); // 54[square]|0 |
1379 | 3.23M | if (val) f << "f5=" << val << ","; |
1380 | 3.23M | val=static_cast<int>(input->readLong(2)); // 18 |
1381 | 3.23M | if (val!=0x18) f << "f6=" << val << ","; |
1382 | 3.23M | val=static_cast<int>(input->readULong(2)); |
1383 | 3.23M | int subType = (val&0xf); |
1384 | 3.23M | val = (val>>4); |
1385 | 3.23M | if (val!=0xFF) |
1386 | 3.23M | f << "sType[high]=" << std::hex << val << std::dec << ","; |
1387 | 3.23M | val=static_cast<int>(input->readLong(2)); // 0 |
1388 | 3.23M | if (val) f << "f7=" << val << ","; |
1389 | 3.23M | val=static_cast<int>(input->readLong(1)); // 0 |
1390 | 3.23M | if (val) f << "f8=" << val << ","; |
1391 | 3.23M | f << "],"; |
1392 | 3.23M | auto &finalGrad=style.m_gradient; |
1393 | 3.23M | switch (type) { |
1394 | 289k | case 1: |
1395 | 289k | finalGrad.m_stopList.resize(2); |
1396 | 289k | finalGrad.m_stopList[0]=MWAWGraphicStyle::Gradient::Stop(0.0, style.m_baseSurfaceColor); |
1397 | 289k | finalGrad.m_stopList[1]=MWAWGraphicStyle::Gradient::Stop(1.0, style.m_baseLineColor); |
1398 | 289k | finalGrad.m_angle = float(90+angle); |
1399 | 289k | finalGrad.m_type = MWAWGraphicStyle::Gradient::G_Linear; |
1400 | 289k | angle=type=0; |
1401 | 289k | break; |
1402 | 394k | case 2: |
1403 | 394k | finalGrad.m_stopList.resize(2); |
1404 | 394k | finalGrad.m_stopList[0]=MWAWGraphicStyle::Gradient::Stop(0.0, style.m_baseSurfaceColor); |
1405 | 394k | finalGrad.m_stopList[1]=MWAWGraphicStyle::Gradient::Stop(1.0, style.m_baseLineColor); |
1406 | 394k | finalGrad.m_angle = float(90+angle); |
1407 | 394k | finalGrad.m_type = MWAWGraphicStyle::Gradient::G_Axial; |
1408 | 394k | angle=type=0; |
1409 | 394k | break; |
1410 | 254k | case 3: |
1411 | 254k | finalGrad.m_stopList.resize(2); |
1412 | 254k | finalGrad.m_stopList[0]=MWAWGraphicStyle::Gradient::Stop(0.0, style.m_baseSurfaceColor); |
1413 | 254k | finalGrad.m_stopList[1]=MWAWGraphicStyle::Gradient::Stop(1.0, style.m_baseLineColor); |
1414 | 254k | switch (subType) { |
1415 | 48.4k | case 9: |
1416 | 48.4k | finalGrad.m_percentCenter=MWAWVec2f(0.25f,0.25f); |
1417 | 48.4k | break; |
1418 | 4.90k | case 10: |
1419 | 4.90k | finalGrad.m_percentCenter=MWAWVec2f(0.25f,0.75f); |
1420 | 4.90k | break; |
1421 | 42.5k | case 11: |
1422 | 42.5k | finalGrad.m_percentCenter=MWAWVec2f(0.75f,0.75f); |
1423 | 42.5k | break; |
1424 | 3.69k | case 12: |
1425 | 3.69k | finalGrad.m_percentCenter=MWAWVec2f(1.f,1.f); |
1426 | 3.69k | break; |
1427 | 63.3k | case 13: |
1428 | 63.3k | finalGrad.m_percentCenter=MWAWVec2f(0.f,0.f); |
1429 | 63.3k | break; |
1430 | 91.1k | default: |
1431 | 91.1k | f << "#subType=" << subType << ","; |
1432 | 91.1k | break; |
1433 | 127 | case 8: // centered |
1434 | 127 | break; |
1435 | 254k | } |
1436 | 254k | finalGrad.m_type = MWAWGraphicStyle::Gradient::G_Rectangular; |
1437 | 254k | angle=type=0; |
1438 | 254k | break; |
1439 | 332k | case 7: |
1440 | 332k | finalGrad.m_stopList.resize(2); |
1441 | 332k | finalGrad.m_stopList[0]=MWAWGraphicStyle::Gradient::Stop(0.0, style.m_baseSurfaceColor); |
1442 | 332k | finalGrad.m_stopList[1]=MWAWGraphicStyle::Gradient::Stop(1.0, style.m_baseLineColor); |
1443 | 332k | finalGrad.m_type = MWAWGraphicStyle::Gradient::G_Radial; |
1444 | 332k | type = 0; |
1445 | 332k | break; |
1446 | 1.96M | default: |
1447 | 1.96M | break; |
1448 | 3.23M | } |
1449 | 3.23M | if (type) f << "#type=" << type << ","; |
1450 | 3.23M | if (angle) f << "#angle=" << angle << ","; |
1451 | 3.23M | f << "subType=" << subType << ","; |
1452 | 3.23M | f << "],"; |
1453 | 3.23M | style.m_extra = f.str(); |
1454 | 3.23M | return true; |
1455 | 3.23M | } |
1456 | | |
1457 | | int MsWksGraph::getEntryPicture(int zoneId, MWAWEntry &zone, bool autoSend, int order) |
1458 | 53.4M | { |
1459 | 53.4M | MsWksGraphInternal::Zone pict; |
1460 | 53.4M | MWAWInputStreamPtr input=m_document.getInput(); |
1461 | 53.4M | long pos = input->tell(); |
1462 | | |
1463 | 53.4M | if (!readPictHeader(pict)) |
1464 | 12.2M | return -1; |
1465 | 41.1M | pict.m_zoneId = zoneId; |
1466 | 41.1M | pict.m_pos.setBegin(pos); |
1467 | 41.1M | libmwaw::DebugFile &ascFile = m_document.ascii(); |
1468 | 41.1M | libmwaw::DebugStream f; |
1469 | 41.1M | int vers = version(); |
1470 | 41.1M | long debData = input->tell(); |
1471 | 41.1M | long dataSize = 0; |
1472 | 41.1M | int versSize = 0; |
1473 | 41.1M | switch (pict.m_subType) { |
1474 | 9.18M | case 0: |
1475 | 10.5M | case 1: |
1476 | 11.8M | case 2: |
1477 | 12.2M | case 3: |
1478 | 12.2M | dataSize = 1; |
1479 | 12.2M | break; |
1480 | 726k | case 4: // arc |
1481 | 726k | dataSize = 0xd; |
1482 | 726k | break; |
1483 | 937k | case 5: { // poly |
1484 | 937k | input->seek(3, librevenge::RVNG_SEEK_CUR); |
1485 | 937k | auto N = static_cast<int>(input->readULong(2)); |
1486 | 937k | dataSize = 9+N*8; |
1487 | 937k | break; |
1488 | 11.8M | } |
1489 | 560k | case 7: { // picture |
1490 | 560k | if (vers >= 3) versSize = 0x14; |
1491 | 560k | dataSize = 5; |
1492 | 560k | input->seek(debData+5+versSize-2, librevenge::RVNG_SEEK_SET); |
1493 | 560k | dataSize += static_cast<int>(input->readULong(2)); |
1494 | 560k | break; |
1495 | 11.8M | } |
1496 | 1.36M | case 8: // group |
1497 | 1.36M | if (vers >= 3) versSize = 4; |
1498 | 1.36M | dataSize = 0x1b; |
1499 | 1.36M | break; |
1500 | 9.60M | case 9: // textbox v<=3 |
1501 | 9.60M | dataSize = 0x21; |
1502 | 9.60M | if (vers >= 3) dataSize += 0x10; |
1503 | 9.60M | break; |
1504 | 7.35M | case 0xa: // chart v4 |
1505 | 7.35M | dataSize = 50; |
1506 | 7.35M | break; |
1507 | 464k | case 0xc: // equation v4 |
1508 | 464k | dataSize = 0x11; |
1509 | 464k | break; |
1510 | 2.66M | case 0xd: { // bitmap v4 |
1511 | 2.66M | input->seek(debData+0x29, librevenge::RVNG_SEEK_SET); |
1512 | 2.66M | auto sz = long(input->readULong(4)); |
1513 | 2.66M | dataSize = 0x29+4+sz; |
1514 | 2.66M | break; |
1515 | 11.8M | } |
1516 | 3.12M | case 0xe: { // spreadsheet v4 |
1517 | 3.12M | input->seek(debData+0xa7, librevenge::RVNG_SEEK_SET); |
1518 | 3.12M | auto pSize = static_cast<int>(input->readULong(2)); |
1519 | 3.12M | if (pSize == 0) return -1; |
1520 | 2.01M | dataSize = 0xa9+pSize; |
1521 | 2.01M | if (!input->checkPosition(debData+dataSize)) |
1522 | 871k | return -1; |
1523 | | |
1524 | 1.13M | input->seek(debData+dataSize, librevenge::RVNG_SEEK_SET); |
1525 | 2.51M | for (int i = 0; i < 2; i++) { |
1526 | 1.92M | auto sz = long(input->readULong(4)); |
1527 | 1.92M | if (sz<0 || (sz>>28)) return -1; |
1528 | 1.37M | dataSize += 4 + sz; |
1529 | 1.37M | input->seek(sz, librevenge::RVNG_SEEK_CUR); |
1530 | 1.37M | } |
1531 | 592k | break; |
1532 | 1.13M | } |
1533 | 592k | case 0xf: { // textbox v4 |
1534 | 164k | input->seek(debData+0x39, librevenge::RVNG_SEEK_SET); |
1535 | 164k | dataSize = 0x3b+ long(input->readULong(2)); |
1536 | 164k | break; |
1537 | 1.13M | } |
1538 | 1.92M | case 0x10: { // table v4 |
1539 | 1.92M | input->seek(debData+0x57, librevenge::RVNG_SEEK_SET); |
1540 | 1.92M | dataSize = 0x59+ long(input->readULong(2)); |
1541 | 1.92M | input->seek(debData+dataSize, librevenge::RVNG_SEEK_SET); |
1542 | | |
1543 | 6.63M | for (int i = 0; i < 3; i++) { |
1544 | 5.14M | auto sz = long(input->readULong(4)); |
1545 | 5.14M | if (sz<0 || ((sz>>28))) return -1; |
1546 | 4.70M | dataSize += 4 + sz; |
1547 | 4.70M | input->seek(sz, librevenge::RVNG_SEEK_CUR); |
1548 | 4.70M | } |
1549 | | |
1550 | 1.48M | break; |
1551 | 1.92M | } |
1552 | 1.48M | default: |
1553 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::getEntryPicture: type %d is not umplemented\n", pict.m_subType)); |
1554 | 0 | return -1; |
1555 | 41.1M | } |
1556 | | |
1557 | 38.1M | pict.m_pos.setEnd(debData+dataSize+versSize); |
1558 | 38.1M | if (!input->checkPosition(pict.m_pos.end())) |
1559 | 9.95M | return -1; |
1560 | | |
1561 | 28.1M | input->seek(debData, librevenge::RVNG_SEEK_SET); |
1562 | 28.1M | if (versSize) { |
1563 | 546k | switch (pict.m_subType) { |
1564 | 144k | case 7: { |
1565 | 144k | auto ptr = long(input->readULong(4)); |
1566 | 144k | f << std::hex << "ptr2=" << ptr << std::dec << ","; |
1567 | 144k | f << "depth?=" << input->readLong(1) << ","; |
1568 | 144k | float dim[4]; |
1569 | 577k | for (auto &d : dim) d = float(input->readLong(4))/65536.f; |
1570 | 144k | MWAWBox2f box(MWAWVec2f(dim[1], dim[0]), MWAWVec2f(dim[3], dim[2])); |
1571 | 144k | f << "bdbox2=" << box << ","; |
1572 | 144k | break; |
1573 | 0 | } |
1574 | 401k | default: |
1575 | 401k | break; |
1576 | 546k | } |
1577 | 546k | } |
1578 | 28.1M | auto val = static_cast<int>(input->readLong(1)); // 0 and sometimes -1 |
1579 | 28.1M | if (val) f << "g0=" << val << ","; |
1580 | 28.1M | pict.m_dataPos++; |
1581 | | |
1582 | 28.1M | if (pict.m_subType > 0xd) { |
1583 | 970k | f << ", " << std::hex << input->readULong(4) << std::dec << ", BdMWAWBox2=("; |
1584 | 4.85M | for (int i = 0; i < 4; i++) |
1585 | 3.88M | f << float(input->readLong(4))/65536.f << ", "; |
1586 | 970k | f << ")"; |
1587 | 970k | } |
1588 | | |
1589 | 28.1M | std::shared_ptr<MsWksGraphInternal::Zone> res; |
1590 | 28.1M | switch (pict.m_subType) { |
1591 | 7.43M | case 0: { // line |
1592 | 7.43M | auto form = std::make_shared<MsWksGraphInternal::BasicShape>(pict); |
1593 | 7.43M | res = form; |
1594 | 7.43M | form->m_shape = MWAWGraphicShape::line(pict.m_box.min(), pict.m_box.max()); |
1595 | 7.43M | break; |
1596 | 0 | } |
1597 | 417k | case 1: // rect |
1598 | 1.40M | case 2: // rectoval |
1599 | 1.72M | case 3: { // circle |
1600 | 1.72M | MWAWBox2f bdbox = pict.m_box; |
1601 | 1.72M | auto form = std::make_shared<MsWksGraphInternal::BasicShape>(pict); |
1602 | 1.72M | res = form; |
1603 | 1.72M | form->m_shape.m_bdBox = form->m_shape.m_formBox = bdbox; |
1604 | 1.72M | form->m_shape.m_type = (pict.m_subType==3) ? MWAWGraphicShape::Circle : |
1605 | 1.72M | MWAWGraphicShape::Rectangle; |
1606 | 1.72M | if (pict.m_subType==2) { |
1607 | 984k | float sz=10; |
1608 | 984k | if (bdbox.size().x() > 0 && bdbox.size().x() < 2*sz) |
1609 | 247k | sz = bdbox.size().x()/2.f; |
1610 | 984k | if (bdbox.size().y() > 0 && bdbox.size().y() < 2*sz) |
1611 | 192k | sz = bdbox.size().y()/2.f; |
1612 | 984k | form->m_shape.m_cornerWidth=MWAWVec2f(sz,sz); |
1613 | 984k | } |
1614 | 1.72M | break; |
1615 | 1.40M | } |
1616 | 404k | case 4: { |
1617 | 404k | auto form = std::make_shared<MsWksGraphInternal::BasicShape>(pict); |
1618 | 404k | res = form; |
1619 | 404k | auto angle = float(input->readLong(2)); |
1620 | 404k | auto deltaAngle = float(input->readLong(2)); |
1621 | 404k | float angl2 = angle+((deltaAngle>0) ? deltaAngle : -deltaAngle); |
1622 | 404k | float dim[4]; // real Bdbox |
1623 | 1.61M | for (auto &d : dim) d = float(input->readLong(2)); |
1624 | 404k | MWAWBox2f realBox(MWAWVec2f(dim[1],dim[0]), MWAWVec2f(dim[3],dim[2])); |
1625 | 404k | form->m_shape=MWAWGraphicShape::arc(realBox,pict.m_box,MWAWVec2f(450.f-angl2,450.f-angle)); |
1626 | 404k | form->m_box = realBox; |
1627 | 404k | break; |
1628 | 1.40M | } |
1629 | 434k | case 5: { |
1630 | 434k | auto form = std::make_shared<MsWksGraphInternal::BasicShape>(pict); |
1631 | 434k | res = form; |
1632 | 434k | val = static_cast<int>(input->readULong(2)); |
1633 | 434k | bool smooth=false; |
1634 | 434k | if (val==1) |
1635 | 21.3k | smooth=true; |
1636 | 413k | else if (val) f << "#smooth=" << val << ","; |
1637 | 434k | auto numPt = static_cast<int>(input->readLong(2)); |
1638 | 434k | auto ptr = long(input->readULong(4)); |
1639 | 434k | if (!input->checkPosition(input->tell()+8*numPt)) |
1640 | 1 | return -1; |
1641 | 434k | f << std::hex << "ptr2=" << ptr << std::dec << ","; |
1642 | 434k | std::vector<MWAWVec2f> vertices; |
1643 | 3.21M | for (int i = 0; i < numPt; i++) { |
1644 | 2.77M | float x = float(input->readLong(4))/65336.f; |
1645 | 2.77M | float y = float(input->readLong(4))/65336.f; |
1646 | 2.77M | vertices.push_back(MWAWVec2f(x,y)); |
1647 | 2.77M | } |
1648 | 434k | if (!smooth || numPt <= 2) { |
1649 | 430k | form->m_shape=MWAWGraphicShape::polygon(pict.m_box); |
1650 | 430k | form->m_shape.m_vertices = vertices; |
1651 | 430k | break; |
1652 | 430k | } |
1653 | 4.05k | form->m_shape=MWAWGraphicShape::path(pict.m_box); |
1654 | 4.05k | form->m_shape.m_path.push_back(MWAWGraphicShape::PathData('M', vertices[0])); |
1655 | | |
1656 | 4.05k | MWAWVec2f middle=0.5f*(vertices[1]+vertices[0]); |
1657 | 4.05k | form->m_shape.m_path.push_back(MWAWGraphicShape::PathData('L', middle)); |
1658 | 1.35M | for (size_t pt=1; pt+1 < size_t(numPt); ++pt) { |
1659 | 1.34M | middle=0.5f*(vertices[pt+1]+vertices[pt]); |
1660 | 1.34M | form->m_shape.m_path.push_back(MWAWGraphicShape::PathData('Q', middle, vertices[pt])); |
1661 | 1.34M | } |
1662 | 4.05k | form->m_shape.m_path.push_back(MWAWGraphicShape::PathData('L',vertices[size_t(numPt-1)])); |
1663 | 4.05k | if (vertices[0]==vertices[size_t(numPt)-1]) |
1664 | 219 | form->m_shape.m_path.push_back(MWAWGraphicShape::PathData('Z')); |
1665 | 4.05k | break; |
1666 | 434k | } |
1667 | 152k | case 7: { |
1668 | 152k | val = static_cast<int>(input->readULong(vers >= 3 ? 1 : 2)); |
1669 | 152k | if (val) f << "g1=" << val << ","; |
1670 | | // skip size (already read) |
1671 | 152k | pict.m_dataPos = input->tell()+2; |
1672 | 152k | auto pct = std::make_shared<MsWksGraphInternal::DataPict>(pict); |
1673 | 152k | res = pct; |
1674 | 152k | ascFile.skipZone(pct->m_dataPos, pct->m_pos.end()-1); |
1675 | 152k | break; |
1676 | 434k | } |
1677 | 459k | case 8: |
1678 | 459k | res = readGroup(pict); |
1679 | 459k | if (!res) |
1680 | 0 | return -1; |
1681 | 459k | break; |
1682 | 8.33M | case 9: { // textbox normal |
1683 | 8.33M | auto justify = MWAWParagraph::JustificationLeft; |
1684 | 8.33M | val = static_cast<int>(input->readLong(2)); |
1685 | 8.33M | switch (val) { |
1686 | 2.43M | case 0: |
1687 | 2.43M | break; |
1688 | 115k | case 1: |
1689 | 115k | justify = MWAWParagraph::JustificationCenter; |
1690 | 115k | break; |
1691 | 14.1k | case 2: |
1692 | 14.1k | justify = MWAWParagraph::JustificationFull; |
1693 | 14.1k | break; |
1694 | 366k | case -1: |
1695 | 366k | justify = MWAWParagraph::JustificationRight; |
1696 | 366k | break; |
1697 | 5.40M | default: |
1698 | 5.40M | f << "##align=" << val << ","; |
1699 | 5.40M | break; |
1700 | 8.33M | } |
1701 | 8.33M | if (vers >= 3) { |
1702 | 8.32M | f << "h=" << input->readLong(4) << ","; |
1703 | 58.2M | for (int i = 0; i < 6; i++) { |
1704 | 49.9M | val = static_cast<int>(input->readLong(2)); |
1705 | 49.9M | if (val) f << "g" << i+2 << "=" << val << ","; |
1706 | 49.9M | } |
1707 | 8.32M | pict.m_dataPos += 0x10; |
1708 | 8.32M | } |
1709 | 8.33M | f << "Fl=["; |
1710 | 41.6M | for (int i = 0; i < 4; i++) { |
1711 | 33.3M | val = static_cast<int>(input->readLong(2)); |
1712 | 33.3M | if (val) f << std::hex << val << std::dec << ","; |
1713 | 17.1M | else f << ","; |
1714 | 33.3M | } |
1715 | 8.33M | f << "],"; |
1716 | 8.33M | auto numPos = static_cast<int>(input->readLong(2)); |
1717 | 8.33M | if (numPos < 0) return -1; |
1718 | 7.93M | f << "numFonts=" << input->readLong(2); |
1719 | | |
1720 | 7.93M | long off[4]; |
1721 | 31.7M | for (auto &d : off) d = long(input->readULong(4)); |
1722 | 7.93M | f << ", Ptrs=[" << std::hex << std::setw(8) << off[2] << ", " << std::setw(8) << off[0] |
1723 | 7.93M | << ", " << std::dec << long(off[1]-off[0]) |
1724 | 7.93M | << ", " << std::dec << long(off[3]-off[0]) << "]"; |
1725 | | |
1726 | 7.93M | auto text = std::make_shared<MsWksGraphInternal::TextBox>(pict); |
1727 | 7.93M | text->m_justify = justify; |
1728 | 7.93M | text->m_numPositions = numPos; |
1729 | 7.93M | res = text; |
1730 | 7.93M | if (!readText(*text)) return -1; |
1731 | 6.45k | res->m_pos.setEnd(input->tell()); |
1732 | 6.45k | break; |
1733 | 7.93M | } |
1734 | 6.49M | case 0xa: { // chart |
1735 | 6.49M | auto chart = std::make_shared<MsWksGraphInternal::Chart>(pict); |
1736 | 6.49M | int chartId = m_state->m_chartId++; |
1737 | 6.49M | if (!m_tableParser->readChart(chartId, chart->m_style)) { |
1738 | 6.49M | return -1; |
1739 | 6.49M | } |
1740 | 836 | m_tableParser->setChartZoneId(chartId, int(m_state->m_zonesList.size())); |
1741 | 836 | chart->m_chartId = chartId; |
1742 | 836 | res = chart; |
1743 | 836 | res->m_pos.setEnd(input->tell()); |
1744 | 836 | break; |
1745 | 6.49M | } |
1746 | 134k | case 0xc: { // equation |
1747 | 134k | auto ole = std::make_shared<MsWksGraphInternal::OLEZone>(pict); |
1748 | 134k | res = ole; |
1749 | 134k | int dim[2]; |
1750 | 268k | for (auto &d : dim) d = static_cast<int>(input->readLong(4)); |
1751 | 134k | ole->m_dim = MWAWVec2i(dim[0], dim[1]); |
1752 | 134k | val = static_cast<int>(input->readULong(2)); // always 0x4f4d ? |
1753 | 134k | f << "g0=" << std::hex << val << std::dec << ","; |
1754 | 134k | ole->m_oleId=static_cast<int>(input->readULong(4)); |
1755 | 134k | val = static_cast<int>(input->readLong(2)); // always 0? |
1756 | 134k | if (val) f << "g1=" << val << ","; |
1757 | 134k | break; |
1758 | 6.49M | } |
1759 | 1.63M | case 0xd: { // bitmap |
1760 | 1.63M | libmwaw::DebugStream f2; |
1761 | 1.63M | f2 << "Graphd(II): fl("; |
1762 | | |
1763 | 1.63M | long actPos = input->tell(); |
1764 | 4.89M | for (int i = 0; i < 2; i++) |
1765 | 3.26M | f2 << input->readLong(2) << ", "; |
1766 | 1.63M | f2 << "), "; |
1767 | 1.63M | auto nCol = static_cast<int>(input->readLong(2)); |
1768 | 1.63M | auto nRow = static_cast<int>(input->readLong(2)); |
1769 | 1.63M | if (nRow <= 0 || nCol <= 0) return -1; |
1770 | | |
1771 | 942k | f2 << "nRow=" << nRow << ", " << "nCol=" << nCol << ", "; |
1772 | | |
1773 | 942k | f2 << std::hex << input->readULong(4) << std::dec << ", "; |
1774 | | |
1775 | 3.76M | for (int i = 0; i < 3; i++) { |
1776 | 2.82M | f2 << "bdbox" << i << "=("; |
1777 | 14.1M | for (int d= 0; d < 4; d++) f2 << input->readLong(2) << ", "; |
1778 | 2.82M | f2 << "), "; |
1779 | 2.82M | if (i == 1) f2 << "unk=" << input->readLong(2) << ", "; |
1780 | 2.82M | } |
1781 | 942k | auto sizeLine = static_cast<int>(input->readLong(2)); |
1782 | 942k | f2 << "lineSize(?)=" << sizeLine << ", "; |
1783 | 942k | long bitmapSize = input->readLong(4); |
1784 | 942k | f2 << "bitmapSize=" << std::hex << bitmapSize << ", "; |
1785 | | |
1786 | 942k | if (bitmapSize <= 0 || (bitmapSize%nRow) != 0) { |
1787 | | // sometimes, another row is added: only for big picture? |
1788 | 748k | if (bitmapSize>0 && (bitmapSize%(nRow+1)) == 0) nRow++; |
1789 | 704k | else if (bitmapSize < nCol*nRow || bitmapSize > 2*nCol*nRow) |
1790 | 704k | return -1; |
1791 | 7 | else { // maybe a not implemented case |
1792 | 7 | MWAW_DEBUG_MSG(("MsWksGraph::getEntryPicture: bitmap size is a little odd\n")); |
1793 | 7 | f2 << "###"; |
1794 | 7 | ascFile.addPos(actPos); |
1795 | 7 | ascFile.addNote(f2.str().c_str()); |
1796 | 7 | ascFile.addDelimiter(input->tell(),'|'); |
1797 | 7 | break; |
1798 | 7 | } |
1799 | 748k | } |
1800 | | |
1801 | 237k | auto szCol = int(bitmapSize/nRow); |
1802 | 237k | if (szCol < nCol) return -1; |
1803 | | |
1804 | 12 | ascFile.addPos(actPos); |
1805 | 12 | ascFile.addNote(f2.str().c_str()); |
1806 | | |
1807 | 12 | pict.m_dataPos = input->tell(); |
1808 | 12 | auto pct = std::make_shared<MsWksGraphInternal::DataBitmap>(pict); |
1809 | 12 | pct->m_numRows = nRow; |
1810 | 12 | pct->m_numCols = nCol; |
1811 | 12 | pct->m_dataSize = bitmapSize; |
1812 | 12 | res = pct; |
1813 | 12 | break; |
1814 | 237k | } |
1815 | 145k | case 0xe: { |
1816 | 145k | long actPos = input->tell(); |
1817 | 145k | ascFile.addPos(actPos); |
1818 | 145k | ascFile.addNote("Graphe(I)"); |
1819 | | |
1820 | | // first: the picture ( fixme: kept while we do not parse the spreadsheet ) |
1821 | 145k | input->seek(144, librevenge::RVNG_SEEK_CUR); |
1822 | 145k | actPos = input->tell(); |
1823 | 145k | ascFile.addPos(actPos); |
1824 | 145k | ascFile.addNote("Graphe(pict)"); |
1825 | 145k | auto dSize = long(input->readLong(4)); |
1826 | 145k | if (dSize < 0) return -1; |
1827 | 13.5k | pict.m_dataPos = actPos+4; |
1828 | | |
1829 | 13.5k | auto pct = std::make_shared<MsWksGraphInternal::DataPict>(pict); |
1830 | 13.5k | pct->m_dataEndPos = actPos+4+dSize; |
1831 | 13.5k | res = pct; |
1832 | 13.5k | ascFile.skipZone(pct->m_dataPos, pct->m_dataEndPos-1); |
1833 | 13.5k | input->seek(actPos+4+dSize, librevenge::RVNG_SEEK_SET); |
1834 | | |
1835 | | // now the spreadsheet ( a classic WKS file ) |
1836 | 13.5k | actPos = input->tell(); |
1837 | 13.5k | dSize = long(input->readULong(4)); |
1838 | 13.5k | if (dSize < 0) return -1; |
1839 | 13.5k | ascFile.addPos(actPos); |
1840 | 13.5k | ascFile.addNote("Graphe(sheet)"); |
1841 | 13.5k | ascFile.skipZone(actPos+4, actPos+3+dSize); |
1842 | | #ifdef DEBUG_WITH_FILES |
1843 | | if (dSize > 0) { |
1844 | | librevenge::RVNGBinaryData file; |
1845 | | input->seek(actPos+4, librevenge::RVNG_SEEK_SET); |
1846 | | input->readDataBlock(dSize, file); |
1847 | | static int volatile sheetName = 0; |
1848 | | libmwaw::DebugStream f2; |
1849 | | f2 << "Sheet-" << ++sheetName << ".wks"; |
1850 | | libmwaw::Debug::dumpFile(file, f2.str().c_str()); |
1851 | | } |
1852 | | #endif |
1853 | 13.5k | input->seek(actPos+4+dSize, librevenge::RVNG_SEEK_SET); |
1854 | | |
1855 | 13.5k | actPos = input->tell(); |
1856 | 13.5k | ascFile.addPos(actPos); |
1857 | 13.5k | ascFile.addNote("Graphe(colWidth?)"); // blocksize, unknown+list of 100 w |
1858 | 13.5k | break; |
1859 | 13.5k | } |
1860 | 60.6k | case 0xf: { // new text box v4 (a picture is stored) |
1861 | 60.6k | if (vers < 4) return -1; |
1862 | 56.5k | auto textbox = std::make_shared<MsWksGraphInternal::TextBoxv4>(pict); |
1863 | 56.5k | res = textbox; |
1864 | 56.5k | textbox->m_ids[1] = long(input->readULong(4)); |
1865 | 56.5k | textbox->m_ids[2] = long(input->readULong(4)); |
1866 | 56.5k | f << "," << std::hex << input->readULong(4)<< std::dec << ","; |
1867 | | // always 0 ? |
1868 | 395k | for (int i = 0; i < 6; i++) { |
1869 | 339k | val = static_cast<int>(input->readLong(2)); |
1870 | 339k | if (val) f << "f" << i << "=" << val << ","; |
1871 | 339k | } |
1872 | 56.5k | textbox->m_text.setBegin(input->readLong(4)); |
1873 | 56.5k | textbox->m_text.setEnd(input->readLong(4)); |
1874 | | |
1875 | | // always 0 ? |
1876 | 56.5k | val = static_cast<int>(input->readLong(2)); |
1877 | 56.5k | if (val) f << "f10=" << val << ","; |
1878 | 56.5k | auto sz = long(input->readULong(4)); |
1879 | 56.5k | if (sz+0x3b != dataSize) |
1880 | 44.2k | f << "###sz=" << sz << ","; |
1881 | | |
1882 | 56.5k | pict.m_dataPos = input->tell(); |
1883 | 56.5k | if (pict.m_dataPos != pict.m_pos.end()) { |
1884 | | #ifdef DEBUG_WITH_FILES |
1885 | | librevenge::RVNGBinaryData file; |
1886 | | input->readDataBlock(pict.m_pos.end()-pict.m_dataPos, file); |
1887 | | static int volatile textboxName = 0; |
1888 | | libmwaw::DebugStream f2; |
1889 | | f2 << "TextBox-" << ++textboxName << ".pct"; |
1890 | | libmwaw::Debug::dumpFile(file, f2.str().c_str()); |
1891 | | #endif |
1892 | 44.9k | ascFile.skipZone(pict.m_dataPos, pict.m_pos.end()-1); |
1893 | 44.9k | } |
1894 | 56.5k | break; |
1895 | 60.6k | } |
1896 | 765k | case 0x10: { // basic table |
1897 | 765k | libmwaw::DebugStream f2; |
1898 | 765k | f2 << "Graph10(II): fl=("; |
1899 | 765k | long actPos = input->tell(); |
1900 | 3.06M | for (int i = 0; i < 3; i++) |
1901 | 2.29M | f2 << input->readLong(2) << ", "; |
1902 | 765k | f2 << "), "; |
1903 | 765k | auto nRow = static_cast<int>(input->readLong(2)); |
1904 | 765k | auto nCol = static_cast<int>(input->readLong(2)); |
1905 | 765k | f2 << "nRow=" << nRow << ", " << "nCol=" << nCol << ", "; |
1906 | | |
1907 | | // basic name font |
1908 | 765k | auto nbChar = static_cast<int>(input->readULong(1)); |
1909 | 765k | if (nbChar > 31) return -1; |
1910 | 542k | std::string fName; |
1911 | 3.80M | for (int c = 0; c < nbChar; c++) |
1912 | 3.26M | fName+=char(input->readLong(1)); |
1913 | 542k | f2 << fName << ","; |
1914 | 542k | input->seek(actPos+10+32, librevenge::RVNG_SEEK_SET); |
1915 | 542k | auto fSz = static_cast<int>(input->readLong(2)); |
1916 | 542k | if (fSz) f << "fSz=" << fSz << ","; |
1917 | | |
1918 | 542k | ascFile.addDelimiter(input->tell(),'|'); |
1919 | 542k | ascFile.addPos(actPos); |
1920 | 542k | ascFile.addNote(f2.str().c_str()); |
1921 | 542k | input->seek(actPos+0x40, librevenge::RVNG_SEEK_SET); |
1922 | | |
1923 | | // a pict |
1924 | 542k | actPos = input->tell(); |
1925 | 542k | ascFile.addPos(actPos); |
1926 | 542k | ascFile.addNote("Graph10(pict)"); |
1927 | 542k | auto dSize = long(input->readLong(4)); |
1928 | 542k | if (dSize < 0) return -1; |
1929 | 174k | pict.m_dataPos = actPos+4; |
1930 | | |
1931 | 174k | auto pct = std::make_shared<MsWksGraphInternal::DataPict>(pict); |
1932 | 174k | pct->m_dataEndPos = actPos+4+dSize; |
1933 | 174k | res = pct; |
1934 | 174k | ascFile.skipZone(pct->m_dataPos, pct->m_dataEndPos-1); |
1935 | 174k | input->seek(actPos+4+dSize, librevenge::RVNG_SEEK_SET); |
1936 | | |
1937 | | // the table |
1938 | 174k | f << "numRows=" << nRow << ",nCols=" << nCol << ","; |
1939 | 174k | std::shared_ptr<MsWksGraphInternal::Table> table(new MsWksGraphInternal::Table(pict)); |
1940 | 174k | int tableId = m_state->m_tableId++; |
1941 | 174k | if (m_tableParser->readTable(nCol, nRow, tableId, table->m_style)) { |
1942 | 118k | table->m_tableId = tableId; |
1943 | 118k | res=table; |
1944 | 118k | } |
1945 | 174k | break; |
1946 | 542k | } |
1947 | 0 | default: |
1948 | 0 | ascFile.addDelimiter(debData, '|'); |
1949 | 0 | break; |
1950 | 28.1M | } |
1951 | | |
1952 | 10.9M | if (!res) |
1953 | 7 | res.reset(new MsWksGraphInternal::Zone(pict)); |
1954 | 10.9M | res->m_extra += f.str(); |
1955 | | |
1956 | 10.9M | if (order > -1000) |
1957 | 9.42M | res->m_order = order; |
1958 | 10.9M | if (!autoSend) |
1959 | 10.1M | res->m_doNotSend = true; |
1960 | 10.9M | res->m_fileId = int(m_state->m_zonesList.size()); |
1961 | 10.9M | m_state->m_zonesList.push_back(res); |
1962 | | |
1963 | 10.9M | f.str(""); |
1964 | 10.9M | f << "Entries(Graph" << std::hex << res->m_subType << std::dec << "):" << *res; |
1965 | 10.9M | ascFile.addPos(pos); |
1966 | 10.9M | ascFile.addNote(f.str().c_str()); |
1967 | | |
1968 | 10.9M | zone = res->m_pos; |
1969 | 10.9M | zone.setType("Graphic"); |
1970 | 10.9M | input->seek(res->m_pos.end(), librevenge::RVNG_SEEK_SET); |
1971 | | |
1972 | 10.9M | return res->m_fileId; |
1973 | 28.1M | } |
1974 | | |
1975 | | void MsWksGraph::computePositions(int zoneId, std::vector<int> const &linesH, std::vector<int> const &pagesH) |
1976 | 41.5k | { |
1977 | 41.5k | auto numLines = int(linesH.size()); |
1978 | 41.5k | auto nPages = int(pagesH.size()); |
1979 | 41.5k | bool isSpreadsheet=m_parserState->m_type==MWAWParserState::Spreadsheet; |
1980 | 1.12M | for (auto const &zone : m_state->m_zonesList) { |
1981 | 1.12M | if (zone->m_zoneId != -1 && zoneId != zone->m_zoneId) continue; |
1982 | 732k | if (zone->m_line >= 0) { |
1983 | 14.5k | int h = 0; |
1984 | 14.5k | if (zone->m_line >= numLines) { |
1985 | 11.9k | MWAW_DEBUG_MSG(("MsWksGraph::computePositions: linepos is too big\n")); |
1986 | 11.9k | if (numLines) |
1987 | 5.91k | h = linesH[size_t(numLines)-1]; |
1988 | 11.9k | } |
1989 | 2.62k | else |
1990 | 2.62k | h = linesH[size_t(zone->m_line)]; |
1991 | 14.5k | zone->m_finalDecal = MWAWVec2f(0, float(h)); |
1992 | 14.5k | } |
1993 | 732k | if (zone->m_page < 0 && (isSpreadsheet || zone->m_page != -2)) { |
1994 | 683k | float h = zone->m_finalDecal.y(); |
1995 | 683k | float middleH=zone->m_box.center().y(); |
1996 | 683k | h+=middleH; |
1997 | 683k | int p = 0; |
1998 | 920k | while (p < nPages) { |
1999 | 331k | if (h < float(pagesH[size_t(p)])) break; |
2000 | 236k | h -= float(pagesH[size_t(p++)]); |
2001 | 236k | } |
2002 | 683k | zone->m_page = p; |
2003 | 683k | zone->m_finalDecal.setY(h-middleH); |
2004 | 683k | } |
2005 | 732k | } |
2006 | 41.5k | } |
2007 | | |
2008 | | int MsWksGraph::getEntryPictureV1(int zoneId, MWAWEntry &zone, bool autoSend) |
2009 | 9.12M | { |
2010 | 9.12M | MWAWInputStreamPtr input=m_document.getInput(); |
2011 | 9.12M | if (input->isEnd()) return -1; |
2012 | | |
2013 | 9.12M | long pos = input->tell(); |
2014 | 9.12M | if (input->readULong(1) != 1) return -1; |
2015 | | |
2016 | 9.12M | libmwaw::DebugFile &ascFile = m_document.ascii(); |
2017 | 9.12M | libmwaw::DebugStream f; |
2018 | 9.12M | auto ptr = long(input->readULong(2)); |
2019 | 9.12M | auto flag = static_cast<int>(input->readULong(1)); |
2020 | 9.12M | long size = long(input->readULong(2))+6; |
2021 | 9.12M | if (size < 22) return -1; |
2022 | | |
2023 | | // check if we can go to the next zone |
2024 | 7.43M | if (!input->checkPosition(pos+size)) return -1; |
2025 | 5.31M | std::shared_ptr<MsWksGraphInternal::DataPict> pict(new MsWksGraphInternal::DataPict()); |
2026 | 5.31M | pict->m_zoneId = zoneId; |
2027 | 5.31M | pict->m_subType = 0x100; |
2028 | 5.31M | pict->m_pos.setBegin(pos); |
2029 | 5.31M | pict->m_pos.setLength(size); |
2030 | | |
2031 | 5.31M | if (ptr) f << std::hex << "ptr0=" << ptr << ","; |
2032 | 5.31M | if (flag) f << std::hex << "fl=" << flag << ","; |
2033 | | |
2034 | 5.31M | ptr = input->readLong(4); |
2035 | 5.31M | if (ptr) |
2036 | 4.99M | f << "ptr1=" << std::hex << ptr << std::dec << ";"; |
2037 | 5.31M | pict->m_line = static_cast<int>(input->readLong(2)); |
2038 | 5.31M | auto val = static_cast<int>(input->readLong(2)); // almost always equal to m_linePOs |
2039 | 5.31M | if (val != pict->m_line) |
2040 | 3.70M | f << "linePos2=" << std::hex << val << std::dec << ","; |
2041 | 5.31M | int dim[4]; // pictbox |
2042 | 21.2M | for (auto &d : dim) d = static_cast<int>(input->readLong(2)); |
2043 | 5.31M | pict->m_box = MWAWBox2f(MWAWVec2f(float(dim[1]), float(dim[0])), MWAWVec2f(float(dim[3]),float(dim[2]))); |
2044 | | |
2045 | 5.31M | MWAWVec2i pictMin(pict->m_box.min()), pictSize(pict->m_box.size()); |
2046 | 5.31M | if (pictSize.x() < 0 || pictSize.y() < 0) return -1; |
2047 | | |
2048 | 3.20M | if (pictSize.x() > 3000 || pictSize.y() > 3000 || |
2049 | 3.17M | pictMin.x() < -200 || pictMin.y() < -200) return -1; |
2050 | 32.2k | pict->m_dataPos = input->tell(); |
2051 | | |
2052 | 32.2k | zone = pict->m_pos; |
2053 | 32.2k | zone.setType("GraphEntry"); |
2054 | | |
2055 | 32.2k | pict->m_extra = f.str(); |
2056 | 32.2k | if (!autoSend) |
2057 | 0 | pict->m_doNotSend=true; |
2058 | 32.2k | pict->m_fileId = int(m_state->m_zonesList.size()); |
2059 | 32.2k | m_state->m_zonesList.push_back(pict); |
2060 | 32.2k | f.str(""); |
2061 | 32.2k | f << "Entries(GraphEntry):" << *pict; |
2062 | | |
2063 | 32.2k | ascFile.skipZone(pict->m_dataPos, pict->m_pos.end()-1); |
2064 | 32.2k | ascFile.addPos(pos); |
2065 | 32.2k | ascFile.addNote(f.str().c_str()); |
2066 | | |
2067 | 32.2k | input->seek(pict->m_pos.end(), librevenge::RVNG_SEEK_SET); |
2068 | 32.2k | return pict->m_fileId; |
2069 | 3.20M | } |
2070 | | |
2071 | | // a list of picture |
2072 | | bool MsWksGraph::readRB(MWAWInputStreamPtr input, MWAWEntry const &entry, int kind) |
2073 | 2.52M | { |
2074 | 2.52M | libmwaw::DebugFile &ascFile = m_document.ascii(); |
2075 | 2.52M | libmwaw::DebugStream f; |
2076 | | |
2077 | 2.52M | long beginRB, endRB; |
2078 | 2.52M | long pos=input->tell(); |
2079 | 2.52M | f << "Entries(" << entry.name() << "):"; |
2080 | 2.52M | const int vers=version(); |
2081 | 2.52M | switch (kind) { |
2082 | 3.89k | case 0: |
2083 | 3.89k | pos=beginRB=entry.begin(); |
2084 | 3.89k | endRB=entry.end(); |
2085 | 3.89k | break; |
2086 | 2.30M | case 2: |
2087 | 2.30M | if (input->readLong(1)!=3) return false; |
2088 | 2.30M | f << "id=" << input->readLong(1) << ","; |
2089 | 2.30M | MWAW_FALLTHROUGH; |
2090 | 2.52M | case 1: { |
2091 | 2.52M | unsigned long dSz=input->readULong(4); |
2092 | 2.52M | beginRB=input->tell(); |
2093 | 2.52M | if (dSz&0x80000000) { |
2094 | 893k | f << "flags[high],"; |
2095 | 893k | dSz &= 0x7FFFFFFF; |
2096 | 893k | } |
2097 | 2.52M | endRB=beginRB+long(dSz); |
2098 | 2.52M | break; |
2099 | 2.30M | } |
2100 | 0 | default: |
2101 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::readRB: unknown kind\n")); |
2102 | 0 | return false; |
2103 | 2.52M | } |
2104 | | |
2105 | 2.52M | long const headerSize=vers<3 ? 0x150 : 0x164; |
2106 | 2.52M | if (endRB-beginRB+2 < headerSize || !input->checkPosition(endRB)) return false; |
2107 | | |
2108 | 40.3k | MsWksGraphInternal::RBZone zone; |
2109 | 40.3k | if (vers==4) |
2110 | 9.45k | zone.m_isMain = entry.name()=="RBDR"; |
2111 | 40.3k | zone.m_id = entry.id(); |
2112 | | |
2113 | 40.3k | input->seek(beginRB, librevenge::RVNG_SEEK_SET); |
2114 | 40.3k | f << input->readLong(4) << ", "; |
2115 | 201k | for (int i = 0; i < 4; i++) { |
2116 | 161k | long val = input->readLong(4); |
2117 | 161k | if (val) f << "#t" << i << "=" << val << ", "; |
2118 | 161k | } |
2119 | 40.3k | f << "type?=" << std::hex << input->readLong(2) << std::dec << ", "; |
2120 | 40.3k | f << "numPage=" << input->readLong(2) << ", "; |
2121 | 484k | for (int i = 0; i < 11; i++) { |
2122 | 444k | long val = input->readLong(2); |
2123 | 444k | if (!val) continue; |
2124 | 224k | if (i >= 8 && (val < -100 || val > 100)) f << "###"; |
2125 | 224k | f << "f" << i << "=" << val << ", "; |
2126 | 224k | } |
2127 | 40.3k | f << ", unk=("; |
2128 | 121k | for (int i = 0; i < 2; i++) |
2129 | 80.7k | f << input->readLong(4) << ","; |
2130 | 40.3k | f << "), "; |
2131 | 403k | for (int i = 0; i < 9; i++) { |
2132 | 363k | long val = input->readLong(2); |
2133 | 363k | if (val) f << "#u" << i << "=" << val << ", "; |
2134 | 363k | } |
2135 | 40.3k | f << std::hex << "sz?=" << input->readLong(4) << std::dec << ", "; |
2136 | 121k | for (int i = 0; i < 2; i++) { |
2137 | 80.7k | long val = input->readLong(2); |
2138 | 80.7k | if (val) f << "#v" << i << "=" << val << ", "; |
2139 | 80.7k | } |
2140 | | |
2141 | 40.3k | f << "unk1=("; |
2142 | 403k | for (int i = 0; i < 9; i++) { |
2143 | 363k | long val = input->readLong(2); |
2144 | 363k | if (val) f << val << ","; |
2145 | 183k | else f << "_,"; |
2146 | 363k | } |
2147 | 40.3k | f << "), "; |
2148 | 40.3k | if (vers>=3) { |
2149 | 18.9k | long aPos=input->tell(); |
2150 | 18.9k | std::string oleName; |
2151 | 81.4k | while (input->tell() < beginRB+headerSize-2) { |
2152 | 81.4k | auto val = char(input->readLong(1)); |
2153 | 81.4k | if (val == 0) break; |
2154 | 67.1k | oleName+= val; |
2155 | 67.1k | if (oleName.length() >= 10) break; |
2156 | 67.1k | } |
2157 | 18.9k | if (!oleName.empty()) { |
2158 | 11.3k | zone.m_frame = oleName; |
2159 | 11.3k | f << "ole='" << oleName << "', "; |
2160 | 11.3k | } |
2161 | 18.9k | ascFile.addDelimiter(input->tell(),'|'); |
2162 | 18.9k | input->seek(aPos+20, librevenge::RVNG_SEEK_SET); |
2163 | 18.9k | } |
2164 | 40.3k | ascFile.addPos(pos); |
2165 | 40.3k | ascFile.addNote(f.str().c_str()); |
2166 | | |
2167 | 40.3k | pos=input->tell(); |
2168 | 40.3k | f.str(""); |
2169 | 40.3k | f << entry.name() << "-II:"; |
2170 | 4.80M | for (int i=0; i<118; ++i) { |
2171 | 4.76M | auto val = static_cast<int>(input->readLong(2)); |
2172 | 4.76M | if (val) f << "g" << i << "=" << std::hex << val << std::dec << ","; |
2173 | 4.76M | } |
2174 | | // can happens at least with vers=2 and this means that the size is not set |
2175 | 40.3k | if (endRB-beginRB+2 == headerSize) |
2176 | 19.5k | endRB=-1; |
2177 | 40.3k | auto N = static_cast<int>(input->readLong(2)); |
2178 | 40.3k | f << "N=" << N << ","; |
2179 | 40.3k | ascFile.addPos(pos); |
2180 | 40.3k | ascFile.addNote(f.str().c_str()); |
2181 | | |
2182 | 40.3k | if (N == 0) return true; |
2183 | | |
2184 | 30.8k | if (endRB>0) |
2185 | 13.6k | input->pushLimit(endRB); |
2186 | 30.8k | size_t actId = m_state->m_zonesList.size(); |
2187 | 128k | for (int i = 0; i < N; i++) { |
2188 | 115k | pos = input->tell(); |
2189 | 115k | MWAWEntry pictZone; |
2190 | 115k | if (getEntryPicture(vers==4 ? 0 : entry.id(), pictZone)>=0) |
2191 | 97.4k | continue; |
2192 | 18.1k | MWAW_DEBUG_MSG(("MsWksDocument::readGroup: can not find the end of group\n")); |
2193 | 18.1k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2194 | 18.1k | break; |
2195 | 115k | } |
2196 | 30.8k | if (endRB>0) |
2197 | 13.6k | input->popLimit(); |
2198 | 160k | for (size_t z = actId; z < m_state->m_zonesList.size(); z++) { |
2199 | 129k | auto pictZone = m_state->m_zonesList[z]; |
2200 | 129k | if (!pictZone) continue; |
2201 | 129k | zone.m_idList.push_back(int(z)); |
2202 | 129k | if (!zone.m_isMain) |
2203 | 3.51k | pictZone->m_page = -2; |
2204 | 129k | } |
2205 | 30.8k | if (endRB>0 && input->tell() < endRB) { |
2206 | 10.3k | f.str(""); |
2207 | 10.3k | f << entry.name() << "-end:###"; |
2208 | 10.3k | MWAW_DEBUG_MSG(("MsWksGraph::readRB: find some extra data\n")); |
2209 | 10.3k | ascFile.addPos(input->tell()); |
2210 | 10.3k | ascFile.addNote(f.str().c_str()); |
2211 | 10.3k | } |
2212 | 30.8k | if (endRB>0) |
2213 | 13.6k | input->seek(endRB, librevenge::RVNG_SEEK_SET); |
2214 | 30.8k | checkTextBoxLinks(zone); |
2215 | 30.8k | int zId = zone.getId(); |
2216 | 30.8k | if (m_state->m_RBsMap.find(zId) != m_state->m_RBsMap.end()) { |
2217 | 17.8k | MWAW_DEBUG_MSG(("MsWksGraph::readRB: zone %d is already filled\n", zId)); |
2218 | | // ok, let's merge the two zone |
2219 | 17.8k | auto &orig=m_state->m_RBsMap.find(zId)->second; |
2220 | 17.8k | orig.m_idList.insert(orig.m_idList.end(), zone.m_idList.begin(), zone.m_idList.end()); |
2221 | 17.8k | if (orig.m_frame.empty()) orig.m_frame=zone.m_frame; |
2222 | 17.8k | } |
2223 | 13.0k | else |
2224 | 13.0k | m_state->m_RBsMap[zId]=zone; |
2225 | 30.8k | return true; |
2226 | 40.3k | } |
2227 | | |
2228 | | void MsWksGraph::checkTextBoxLinks(MsWksGraphInternal::RBZone &rbZone) |
2229 | 30.8k | { |
2230 | 30.8k | auto const &listIds = rbZone.m_idList; |
2231 | 30.8k | std::string const &fName = rbZone.m_frame; |
2232 | 30.8k | auto numZones = int(m_state->m_zonesList.size()); |
2233 | 30.8k | std::set<long> textIds; |
2234 | 30.8k | std::map<long, long> prevLinks, nextLinks; |
2235 | 30.8k | bool ok = true; |
2236 | 129k | for (auto id : listIds) { |
2237 | 129k | if (id < 0 || id >= numZones) continue; |
2238 | 129k | auto zone = m_state->m_zonesList[size_t(id)]; |
2239 | 129k | if (zone->type() != MsWksGraphInternal::Zone::Textv4) |
2240 | 126k | continue; |
2241 | 2.40k | static_cast<MsWksGraphInternal::TextBoxv4 &>(*zone).m_frame = fName; |
2242 | 2.40k | if (textIds.find(zone->m_ids[0]) != textIds.end()) { |
2243 | 11 | MWAW_DEBUG_MSG(("MsWksGraph::checkTextBoxLinks: id %lX already exists\n", static_cast<long unsigned int>(zone->m_ids[0]))); |
2244 | 11 | ok = false; |
2245 | 11 | break; |
2246 | 11 | } |
2247 | 2.39k | textIds.insert(zone->m_ids[0]); |
2248 | 2.39k | if (zone->m_ids[1]>0) |
2249 | 1.10k | prevLinks.insert(std::map<long, long>::value_type(zone->m_ids[0],zone->m_ids[1])); |
2250 | 2.39k | if (zone->m_ids[2]>0) |
2251 | 1.12k | nextLinks.insert(std::map<long, long>::value_type(zone->m_ids[0],zone->m_ids[2])); |
2252 | 2.39k | } |
2253 | 30.8k | size_t numLinks = nextLinks.size(); |
2254 | 30.8k | for (auto const &link : nextLinks) { |
2255 | 653 | if (prevLinks.find(link.second)==prevLinks.end() || |
2256 | 639 | prevLinks.find(link.second)->second!=link.first) { |
2257 | 639 | MWAW_DEBUG_MSG(("MsWksGraph::checkTextBoxLinks: can not find prevLinks: %lX<->%lX already exists\n", static_cast<long unsigned int>(link.first), static_cast<long unsigned int>(link.second))); |
2258 | 639 | ok = false; |
2259 | 639 | break; |
2260 | 639 | } |
2261 | | // check loops |
2262 | 14 | size_t w = 0; |
2263 | 14 | long actText = link.second; |
2264 | 46 | while (1) { |
2265 | 46 | if (nextLinks.find(actText)==nextLinks.end()) |
2266 | 0 | break; |
2267 | 46 | actText = nextLinks.find(actText)->second; |
2268 | 46 | if (w++ > numLinks) { |
2269 | 14 | MWAW_DEBUG_MSG(("MsWksGraph::checkTextBoxLinks:find a loop for id %lX\n", static_cast<long unsigned int>(link.first))); |
2270 | 14 | ok = false; |
2271 | 14 | break; |
2272 | 14 | } |
2273 | 46 | } |
2274 | 14 | } |
2275 | 30.8k | if (!ok) { |
2276 | 654 | MWAW_DEBUG_MSG(("MsWksGraph::checkTextBoxLinks: problem find with text links\n")); |
2277 | 4.16k | for (auto const &zone : m_state->m_zonesList) { |
2278 | 4.16k | if (zone->type() != MsWksGraphInternal::Zone::Textv4) |
2279 | 2.77k | continue; |
2280 | 1.39k | zone->m_ids[1] = zone->m_ids[2] = 0; |
2281 | 1.39k | } |
2282 | 654 | } |
2283 | 30.8k | } |
2284 | | |
2285 | | bool MsWksGraph::readPictureV4(MWAWInputStreamPtr /*input*/, MWAWEntry const &entry) |
2286 | 0 | { |
2287 | 0 | if (!entry.hasType("PICT")) { |
2288 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::readPictureV4: unknown type='%s'\n", entry.type().c_str())); |
2289 | 0 | return false; |
2290 | 0 | } |
2291 | 0 | entry.setParsed(true); |
2292 | |
|
2293 | 0 | MsWksGraphInternal::Zone pict; |
2294 | 0 | pict.m_pos = entry; |
2295 | 0 | pict.m_dataPos = entry.begin(); |
2296 | 0 | pict.m_page = -2; |
2297 | 0 | pict.m_zoneId = -1; |
2298 | |
|
2299 | 0 | auto pct = std::make_shared<MsWksGraphInternal::DataPict>(pict); |
2300 | 0 | std::shared_ptr<MsWksGraphInternal::Zone>res(pct); |
2301 | 0 | m_document.ascii().skipZone(entry.begin(), entry.end()-1); |
2302 | |
|
2303 | 0 | auto zId = int(m_state->m_zonesList.size()); |
2304 | 0 | res->m_fileId = zId; |
2305 | 0 | m_state->m_zonesList.push_back(res); |
2306 | |
|
2307 | 0 | return true; |
2308 | 0 | } |
2309 | | |
2310 | | //////////////////////////////////////////////////////////// |
2311 | | // |
2312 | | // Low level |
2313 | | // |
2314 | | //////////////////////////////////////////////////////////// |
2315 | | |
2316 | | // read/send a group |
2317 | | void MsWksGraph::sendGroup(int id, MWAWPosition const &pos) |
2318 | 252k | { |
2319 | 252k | if (id<0 || id>=int(m_state->m_zonesList.size()) || !m_state->m_zonesList[size_t(id)] || |
2320 | 252k | m_state->m_zonesList[size_t(id)]->type()!=MsWksGraphInternal::Zone::Group) { |
2321 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::sendGroup: can not find group %d\n", id)); |
2322 | 0 | return; |
2323 | 0 | } |
2324 | 252k | MWAWListenerPtr listener=m_parserState->getMainListener(); |
2325 | 252k | if (!listener) return; |
2326 | 252k | auto &group=static_cast<MsWksGraphInternal::GroupZone &>(*m_state->m_zonesList[size_t(id)]); |
2327 | 252k | group.m_isSent = true; |
2328 | 252k | if (listener->getType()==MWAWListener::Graphic) { |
2329 | 220k | sendGroup(group, m_parserState->m_graphicListener); |
2330 | 220k | return; |
2331 | 220k | } |
2332 | 31.8k | if (!canCreateGraphic(group)) { |
2333 | 23.2k | if (pos.m_anchorTo == MWAWPosition::Char || pos.m_anchorTo == MWAWPosition::CharBaseLine) { |
2334 | 737 | std::shared_ptr<MsWksGraphInternal::SubDocument> subdoc |
2335 | 737 | (new MsWksGraphInternal::SubDocument(*this, m_document.getInput(), MsWksGraphInternal::SubDocument::Group, id)); |
2336 | 737 | listener->insertTextBox(pos, subdoc); |
2337 | 737 | return; |
2338 | 737 | } |
2339 | 22.5k | MWAWPosition childPos(pos); |
2340 | 22.5k | childPos.setSize(MWAWVec2f(0,0)); |
2341 | 22.5k | sendGroupChild(id, childPos); |
2342 | 22.5k | return; |
2343 | 23.2k | } |
2344 | 8.57k | MWAWGraphicEncoder graphicEncoder; |
2345 | 8.57k | MWAWGraphicListenerPtr graphicListener(new MWAWGraphicListener(*m_parserState, group.m_box, &graphicEncoder)); |
2346 | 8.57k | graphicListener->startDocument(); |
2347 | 8.57k | sendGroup(group, graphicListener); |
2348 | 8.57k | graphicListener->endDocument(); |
2349 | 8.57k | MWAWEmbeddedObject picture; |
2350 | 8.57k | if (graphicEncoder.getBinaryResult(picture)) |
2351 | 8.57k | listener->insertPicture(pos, picture); |
2352 | 8.57k | } |
2353 | | |
2354 | | void MsWksGraph::sendGroupChild(int id, MWAWPosition const &pos) |
2355 | 23.2k | { |
2356 | 23.2k | if (id<0 || id>=int(m_state->m_zonesList.size()) || !m_state->m_zonesList[size_t(id)] || |
2357 | 23.2k | m_state->m_zonesList[size_t(id)]->type()!=MsWksGraphInternal::Zone::Group) { |
2358 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::sendGroupChild: can not find group %d\n", id)); |
2359 | 0 | return; |
2360 | 0 | } |
2361 | 23.2k | MWAWListenerPtr listener=m_parserState->getMainListener(); |
2362 | 23.2k | if (!listener) return; |
2363 | 23.2k | auto &group=static_cast<MsWksGraphInternal::GroupZone &>(*m_state->m_zonesList[size_t(id)]); |
2364 | 23.2k | group.m_isSent = true; |
2365 | | |
2366 | 23.2k | MWAWInputStreamPtr input=m_document.getInput(); |
2367 | 23.2k | size_t numZones=m_state->m_zonesList.size(); |
2368 | 23.2k | size_t numChild=group.m_childs.size(), childNotSent=0; |
2369 | 23.2k | int numDataToMerge=0; |
2370 | 23.2k | MWAWBox2f partialBdBox; |
2371 | 23.2k | MWAWPosition partialPos(pos); |
2372 | 23.2k | bool isDraw=listener->getType()==MWAWListener::Graphic; |
2373 | 219k | for (size_t c=0; c < numChild; ++c) { |
2374 | 201k | int cId = group.m_childs[c]; |
2375 | 201k | if (cId < 0 || cId >= int(numZones) || !m_state->m_zonesList[size_t(cId)]) |
2376 | 0 | continue; |
2377 | 201k | auto const &child=*(m_state->m_zonesList[size_t(cId)]); |
2378 | 201k | bool isLast=false; |
2379 | 201k | bool canMerge=false; |
2380 | 201k | if (isDraw) |
2381 | 0 | canMerge=false; |
2382 | 201k | else if (child.type()==MsWksGraphInternal::Zone::Shape || child.type()==MsWksGraphInternal::Zone::Text) { |
2383 | 164k | MWAWBox2f origBdBox=child.getLocalBox(); |
2384 | 164k | MWAWVec2f decal = child.m_decal[0] + child.m_decal[1]; |
2385 | 164k | MWAWBox2f localBdBox(origBdBox[0]+decal, origBdBox[1]+decal); |
2386 | 164k | if (numDataToMerge == 0) |
2387 | 17.3k | partialBdBox=localBdBox; |
2388 | 146k | else |
2389 | 146k | partialBdBox=partialBdBox.getUnion(localBdBox); |
2390 | 164k | canMerge=true; |
2391 | 164k | } |
2392 | 37.2k | else if (child.type()==MsWksGraphInternal::Zone::Group && |
2393 | 30.4k | canCreateGraphic(static_cast<MsWksGraphInternal::GroupZone const &>(child))) { |
2394 | 11.6k | if (numDataToMerge == 0) |
2395 | 4.42k | partialBdBox=child.getLocalBox(); |
2396 | 7.24k | else |
2397 | 7.24k | partialBdBox=partialBdBox.getUnion(child.getLocalBox()); |
2398 | 11.6k | canMerge=true; |
2399 | 11.6k | } |
2400 | 201k | if (canMerge) { |
2401 | 175k | ++numDataToMerge; |
2402 | 175k | if (c+1 < numChild) |
2403 | 169k | continue; |
2404 | 6.15k | isLast=true; |
2405 | 6.15k | } |
2406 | | |
2407 | 31.7k | if (numDataToMerge>1) { |
2408 | 12.3k | MWAWGraphicEncoder graphicEncoder; |
2409 | 12.3k | MWAWGraphicListenerPtr graphicListener(new MWAWGraphicListener(*m_parserState, partialBdBox, &graphicEncoder)); |
2410 | 12.3k | graphicListener->startDocument(); |
2411 | 12.3k | size_t lastChild = isLast ? c : c-1; |
2412 | 178k | for (size_t ch=childNotSent; ch <= lastChild; ++ch) { |
2413 | 166k | int localCId = group.m_childs[ch]; |
2414 | 166k | if (localCId < 0 || localCId >= int(numZones) || !m_state->m_zonesList[size_t(localCId)]) |
2415 | 0 | continue; |
2416 | 166k | auto const &localChild=*(m_state->m_zonesList[size_t(localCId)]); |
2417 | 166k | MWAWBox2f origBdBox=localChild.getLocalBox(false); |
2418 | 166k | MWAWVec2f decal=localChild.m_decal[0]+localChild.m_decal[1]; |
2419 | 166k | MWAWPosition pictPos(origBdBox[0]+decal, origBdBox.size(), librevenge::RVNG_POINT); |
2420 | 166k | pictPos.m_anchorTo=MWAWPosition::Page; |
2421 | 166k | pictPos.m_wrapping = MWAWPosition::WBackground; |
2422 | 166k | if (localChild.type()==MsWksGraphInternal::Zone::Group) |
2423 | 11.1k | sendGroup(static_cast<MsWksGraphInternal::GroupZone const &>(localChild), graphicListener); |
2424 | 155k | else if (localChild.type()==MsWksGraphInternal::Zone::Shape) { |
2425 | 154k | auto const &shape=static_cast<MsWksGraphInternal::BasicShape const &>(localChild); |
2426 | 154k | graphicListener->insertShape(pictPos, shape.m_shape, shape.getStyle()); |
2427 | 154k | } |
2428 | 669 | else if (localChild.type()==MsWksGraphInternal::Zone::Text) { |
2429 | 669 | std::shared_ptr<MsWksGraphInternal::SubDocument> subdoc |
2430 | 669 | (new MsWksGraphInternal::SubDocument(const_cast<MsWksGraph &>(*this), input, MsWksGraphInternal::SubDocument::TextBox, localCId)); |
2431 | | // a textbox can not have border |
2432 | 669 | MWAWGraphicStyle style(localChild.m_style); |
2433 | 669 | style.m_lineWidth=0; |
2434 | 669 | graphicListener->insertTextBox(pictPos, subdoc, style); |
2435 | 669 | } |
2436 | 166k | } |
2437 | 12.3k | graphicListener->endDocument(); |
2438 | 12.3k | MWAWEmbeddedObject picture; |
2439 | 12.3k | if (graphicEncoder.getBinaryResult(picture)) { |
2440 | 12.3k | partialPos.setOrigin(pos.origin()+partialBdBox[0]-group.m_box[0]); |
2441 | 12.3k | partialPos.setSize(partialBdBox.size()); |
2442 | 12.3k | listener->insertPicture(partialPos, picture); |
2443 | 12.3k | if (isLast) |
2444 | 5.26k | break; |
2445 | 7.09k | childNotSent=c; |
2446 | 7.09k | } |
2447 | 12.3k | } |
2448 | | // time to send back the data |
2449 | 61.5k | for (; childNotSent <= c; ++childNotSent) |
2450 | 35.0k | send(group.m_childs[childNotSent],pos); |
2451 | 26.5k | numDataToMerge=0; |
2452 | 26.5k | } |
2453 | 23.2k | } |
2454 | | |
2455 | | bool MsWksGraph::canCreateGraphic(MsWksGraphInternal::GroupZone const &group) const |
2456 | 409k | { |
2457 | 409k | if (m_parserState->getMainListener()->getType()==MWAWListener::Graphic) return false; |
2458 | 409k | auto numZones = int(m_state->m_zonesList.size()); |
2459 | 1.72M | for (auto cId : group.m_childs) { |
2460 | 1.72M | if (cId < 0 || cId >= numZones || !m_state->m_zonesList[size_t(cId)]) |
2461 | 0 | continue; |
2462 | 1.72M | auto const &child=*(m_state->m_zonesList[size_t(cId)]); |
2463 | 1.72M | if (child.m_page!=group.m_page) |
2464 | 27.2k | return false; |
2465 | 1.70M | switch (child.type()) { |
2466 | 1.33M | case MsWksGraphInternal::Zone::Shape: |
2467 | 1.33M | case MsWksGraphInternal::Zone::Text: |
2468 | 1.33M | break; |
2469 | 347k | case MsWksGraphInternal::Zone::Group: |
2470 | 347k | if (!canCreateGraphic(static_cast<MsWksGraphInternal::GroupZone const &>(child))) |
2471 | 184k | return false; |
2472 | 163k | break; |
2473 | 163k | case MsWksGraphInternal::Zone::Bitmap: |
2474 | 0 | case MsWksGraphInternal::Zone::ChartZone: |
2475 | 0 | case MsWksGraphInternal::Zone::OLE: |
2476 | 14.7k | case MsWksGraphInternal::Zone::Pict: |
2477 | 14.7k | case MsWksGraphInternal::Zone::TableZone: |
2478 | 14.7k | case MsWksGraphInternal::Zone::Textv4: |
2479 | 14.7k | case MsWksGraphInternal::Zone::Unknown: |
2480 | | #if !defined(__clang__) |
2481 | | default: |
2482 | | #endif |
2483 | 14.7k | return false; |
2484 | 1.70M | } |
2485 | 1.70M | } |
2486 | 183k | return true; |
2487 | 409k | } |
2488 | | |
2489 | | void MsWksGraph::sendGroup(MsWksGraphInternal::GroupZone const &group, MWAWGraphicListenerPtr &listener) const |
2490 | 285k | { |
2491 | 285k | if (!listener || !listener->isDocumentStarted()) { |
2492 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::sendGroup: the listener is bad\n")); |
2493 | 0 | return; |
2494 | 0 | } |
2495 | 285k | auto numZones = int(m_state->m_zonesList.size()); |
2496 | 285k | MWAWInputStreamPtr input=m_document.getInput(); |
2497 | 1.03M | for (auto cId : group.m_childs) { |
2498 | 1.03M | if (cId < 0 || cId >= numZones || !m_state->m_zonesList[size_t(cId)]) |
2499 | 0 | continue; |
2500 | 1.03M | auto const &child=*(m_state->m_zonesList[size_t(cId)]); |
2501 | 1.03M | MWAWVec2f decal=child.m_decal[0]+child.m_decal[1]; |
2502 | 1.03M | MWAWPosition pictPos(child.m_box[0]+decal, child.m_box.size(), librevenge::RVNG_POINT); |
2503 | 1.03M | pictPos.m_anchorTo=MWAWPosition::Page; |
2504 | 1.03M | pictPos.m_wrapping = MWAWPosition::WBackground; |
2505 | | |
2506 | 1.03M | if (child.type()==MsWksGraphInternal::Zone::Group) |
2507 | 44.9k | sendGroup(static_cast<MsWksGraphInternal::GroupZone const &>(child), listener); |
2508 | 992k | else if (child.type()==MsWksGraphInternal::Zone::Shape) { |
2509 | 887k | auto const &shape=static_cast<MsWksGraphInternal::BasicShape const &>(child); |
2510 | 887k | listener->insertShape(pictPos, shape.m_shape, shape.getStyle()); |
2511 | 887k | } |
2512 | 104k | else if (child.type()==MsWksGraphInternal::Zone::Text) { |
2513 | 2.12k | std::shared_ptr<MsWksGraphInternal::SubDocument> subdoc |
2514 | 2.12k | (new MsWksGraphInternal::SubDocument(const_cast<MsWksGraph &>(*this), input, MsWksGraphInternal::SubDocument::TextBox, cId)); |
2515 | | // a textbox can not have border |
2516 | 2.12k | MWAWGraphicStyle style(child.m_style); |
2517 | 2.12k | style.m_lineWidth=0; |
2518 | 2.12k | listener->insertTextBox(pictPos, subdoc, style); |
2519 | 2.12k | } |
2520 | 102k | else { |
2521 | 102k | MWAW_DEBUG_MSG(("MsWksGraph::sendGroup: find some unexpected child\n")); |
2522 | 102k | } |
2523 | 1.03M | } |
2524 | 285k | } |
2525 | | |
2526 | | std::shared_ptr<MsWksGraphInternal::GroupZone> MsWksGraph::readGroup(MsWksGraphInternal::Zone &header) |
2527 | 459k | { |
2528 | 459k | std::shared_ptr<MsWksGraphInternal::GroupZone> group(new MsWksGraphInternal::GroupZone(header)); |
2529 | 459k | libmwaw::DebugStream f; |
2530 | 459k | MWAWInputStreamPtr input=m_document.getInput(); |
2531 | 459k | input->seek(header.m_dataPos, librevenge::RVNG_SEEK_SET); |
2532 | 459k | float dim[4]; |
2533 | 1.83M | for (auto &d : dim) d = float(input->readLong(4)); |
2534 | 459k | group->m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]), MWAWVec2f(dim[2],dim[3])); |
2535 | 459k | group->m_finalDecal=MWAWVec2f(0,0); |
2536 | 459k | long ptr[2]; |
2537 | 919k | for (auto &p : ptr) p = long(input->readULong(4)); |
2538 | 459k | f << "ptr0=" << std::hex << ptr[0] << std::dec << ","; |
2539 | 459k | if (ptr[0] != ptr[1]) |
2540 | 396k | f << "ptr1=" << std::hex << ptr[1] << std::dec << ","; |
2541 | 459k | if (version() >= 3) { |
2542 | 401k | auto val = static_cast<int>(input->readULong(4)); |
2543 | 401k | if (val) f << "g1=" << val << ","; |
2544 | 401k | } |
2545 | | |
2546 | 459k | input->seek(header.m_pos.end()-2, librevenge::RVNG_SEEK_SET); |
2547 | 459k | auto N = static_cast<int>(input->readULong(2)); |
2548 | 1.20M | for (int i = 0; i < N; i++) { |
2549 | 965k | long pos = input->tell(); |
2550 | 965k | MWAWEntry childZone; |
2551 | 965k | int childId = getEntryPicture(header.m_zoneId, childZone, false); |
2552 | 965k | if (childId < 0) { |
2553 | 216k | MWAW_DEBUG_MSG(("MsWksGraph::readGroup: can not find child\n")); |
2554 | 216k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2555 | 216k | f << "#child,"; |
2556 | 216k | break; |
2557 | 216k | } |
2558 | 749k | group->m_childs.push_back(childId); |
2559 | 749k | } |
2560 | 459k | group->m_extra += f.str(); |
2561 | 459k | group->m_pos.setEnd(input->tell()); |
2562 | 459k | return group; |
2563 | 459k | } |
2564 | | |
2565 | | // read/send a textbox zone |
2566 | | bool MsWksGraph::readText(MsWksGraphInternal::TextBox &textBox) |
2567 | 7.93M | { |
2568 | 7.93M | if (textBox.m_numPositions < 0) return false; // can an empty text exist |
2569 | | |
2570 | 7.93M | libmwaw::DebugFile &ascFile = m_document.ascii(); |
2571 | 7.93M | libmwaw::DebugStream f; |
2572 | 7.93M | f << "Entries(SmallText):"; |
2573 | 7.93M | MWAWInputStreamPtr input=m_document.getInput(); |
2574 | 7.93M | long pos = input->tell(); |
2575 | 7.93M | if (!input->checkPosition(pos+4*(textBox.m_numPositions+1))) return false; |
2576 | | |
2577 | | // first read the set of (positions, font) |
2578 | 6.68M | f << "pos=["; |
2579 | 6.68M | int nbFonts = 0; |
2580 | 19.2M | for (int i = 0; i <= textBox.m_numPositions; i++) { |
2581 | 13.9M | auto fPos = static_cast<int>(input->readLong(2)); |
2582 | 13.9M | auto form = static_cast<int>(input->readLong(2)); |
2583 | 13.9M | f << fPos << ":" << form << ", "; |
2584 | | |
2585 | 13.9M | if (fPos < 0 || form < -1) return false; |
2586 | 12.5M | if ((form == -1 && i != textBox.m_numPositions) || |
2587 | 12.3M | (!textBox.m_positions.empty() && fPos < textBox.m_positions.back())) { |
2588 | 2.98M | MWAW_DEBUG_MSG(("MsWksGraph::readText: find odd positions\n")); |
2589 | 2.98M | f << "#"; |
2590 | 2.98M | continue; |
2591 | 2.98M | } |
2592 | | |
2593 | 9.61M | textBox.m_positions.push_back(fPos); |
2594 | 9.61M | textBox.m_formats.push_back(form); |
2595 | 9.61M | if (form >= nbFonts) nbFonts = form+1; |
2596 | 9.61M | } |
2597 | 5.34M | f << "] "; |
2598 | 5.34M | ascFile.addPos(pos); |
2599 | 5.34M | ascFile.addNote(f.str().c_str()); |
2600 | | |
2601 | 5.34M | pos = input->tell(); |
2602 | 5.34M | f.str(""); |
2603 | 5.34M | f << "SmallText:Fonts "; |
2604 | | |
2605 | | // actualPos, -1, only exists if actualPos!= 0 ? We ignored it. |
2606 | 5.34M | input->readLong(2); |
2607 | 5.34M | if (input->readLong(2) != -1) |
2608 | 4.09M | input->seek(pos,librevenge::RVNG_SEEK_SET); |
2609 | 1.25M | else { |
2610 | 1.25M | ascFile.addPos(pos); |
2611 | 1.25M | ascFile.addNote("SmallText:char Pos"); |
2612 | 1.25M | pos = input->tell(); |
2613 | 1.25M | } |
2614 | 5.34M | f.str(""); |
2615 | | |
2616 | 5.34M | long endFontPos = input->tell(); |
2617 | 5.34M | auto sizeOfData = long(input->readULong(4)); |
2618 | 5.34M | int numFonts = (sizeOfData%0x12 == 0) ? int(sizeOfData/0x12) : 0; |
2619 | | |
2620 | 5.34M | if (numFonts >= nbFonts) { |
2621 | 2.88M | endFontPos = input->tell()+4+sizeOfData; |
2622 | | |
2623 | 2.88M | ascFile.addPos(pos); |
2624 | 2.88M | ascFile.addNote("SmallText: Fonts"); |
2625 | | |
2626 | 12.4M | for (int i = 0; i < numFonts; i++) { |
2627 | 11.7M | pos = input->tell(); |
2628 | 11.7M | MWAWFont font; |
2629 | 11.7M | if (!readFont(font)) { |
2630 | 2.25M | input->seek(endFontPos, librevenge::RVNG_SEEK_SET); |
2631 | 2.25M | break; |
2632 | 2.25M | } |
2633 | 9.53M | textBox.m_fontsList.push_back(font); |
2634 | | |
2635 | 9.53M | f.str(""); |
2636 | 9.53M | f << "SmallText:Font"<< i |
2637 | 9.53M | << "(" << font.getDebugString(m_parserState->m_fontConverter) << "),"; |
2638 | | |
2639 | 9.53M | ascFile.addPos(pos); |
2640 | 9.53M | ascFile.addNote(f.str().c_str()); |
2641 | 9.53M | pos = input->tell(); |
2642 | 9.53M | } |
2643 | 2.88M | } |
2644 | 5.34M | int nChar = textBox.m_positions.back()-1; |
2645 | 5.34M | if (nbFonts > int(textBox.m_fontsList.size())) { |
2646 | 3.93M | MWAW_DEBUG_MSG(("MsWksGraph::readText: can not read the fonts\n")); |
2647 | 3.93M | ascFile.addPos(pos); |
2648 | 3.93M | ascFile.addNote("SmallText:###"); |
2649 | 3.93M | input->seek(endFontPos,librevenge::RVNG_SEEK_SET); |
2650 | 3.93M | textBox.m_fontsList.resize(0); |
2651 | 3.93M | textBox.m_positions.resize(0); |
2652 | 3.93M | textBox.m_numPositions = 0; |
2653 | 3.93M | } |
2654 | | |
2655 | | // now, syntax is : long(size) + size char |
2656 | | // - 0x16 - 0 - 0 - Fonts (default fonts) |
2657 | | // - 0x08 followed by two long, maybe interesting to look |
2658 | | // - 0x0c (or 0x18) seems followed by small int |
2659 | | // - nbChar : the strings (final) |
2660 | | |
2661 | 5.34M | f.str(""); |
2662 | 5.34M | f << "SmallText:"; |
2663 | 8.34M | while (1) { |
2664 | 8.34M | if (input->isEnd()) return false; |
2665 | | |
2666 | 5.34M | pos = input->tell(); |
2667 | 5.34M | sizeOfData = long(input->readULong(4)); |
2668 | 5.34M | if (sizeOfData == nChar) { |
2669 | 137k | bool ok = true; |
2670 | | // ok we try to read the string |
2671 | 137k | std::string chaine(""); |
2672 | 857k | for (long i = 0; i < sizeOfData; i++) { |
2673 | 851k | auto c = static_cast<unsigned char>(input->readULong(1)); |
2674 | 851k | if (c == 0) { |
2675 | 130k | ok = false; |
2676 | 130k | break; |
2677 | 130k | } |
2678 | 720k | chaine += char(c); |
2679 | 720k | } |
2680 | | |
2681 | 137k | if (!ok) |
2682 | 130k | input->seek(pos+4,librevenge::RVNG_SEEK_SET); |
2683 | 6.45k | else { |
2684 | 6.45k | textBox.m_text = chaine; |
2685 | 6.45k | f << "=" << chaine; |
2686 | 6.45k | ascFile.addPos(pos); |
2687 | 6.45k | ascFile.addNote(f.str().c_str()); |
2688 | 6.45k | return true; |
2689 | 6.45k | } |
2690 | 137k | } |
2691 | | |
2692 | 5.33M | if (sizeOfData <= 100+nChar && (sizeOfData%2==0)) { |
2693 | 2.99M | if (input->seek(sizeOfData, librevenge::RVNG_SEEK_CUR) != 0) return false; |
2694 | 2.99M | f << "#"; |
2695 | 2.99M | ascFile.addPos(pos); |
2696 | 2.99M | ascFile.addNote(f.str().c_str()); |
2697 | 2.99M | f.str(""); |
2698 | 2.99M | f << "SmallText:Text"; |
2699 | 2.99M | continue; |
2700 | 2.99M | } |
2701 | | |
2702 | | // fixme: we can try to find the next string |
2703 | 2.34M | MWAW_DEBUG_MSG(("MsWksGraph::readText: problem reading text\n")); |
2704 | 2.34M | f << "#"; |
2705 | 2.34M | ascFile.addPos(pos); |
2706 | 2.34M | ascFile.addNote(f.str().c_str()); |
2707 | | |
2708 | 2.34M | break; |
2709 | 5.33M | } |
2710 | 2.34M | return false; |
2711 | 5.34M | } |
2712 | | |
2713 | | bool MsWksGraph::readFont(MWAWFont &font) |
2714 | 11.7M | { |
2715 | 11.7M | int vers = version(); |
2716 | 11.7M | MWAWInputStreamPtr input=m_document.getInput(); |
2717 | 11.7M | long pos = input->tell(); |
2718 | 11.7M | libmwaw::DebugStream f; |
2719 | 11.7M | if (!input->checkPosition(pos+18)) |
2720 | 2.25M | return false; |
2721 | 9.53M | font = MWAWFont(); |
2722 | 38.1M | for (int i = 0; i < 3; i++) { |
2723 | 28.6M | auto val = static_cast<int>(input->readLong(2)); |
2724 | 28.6M | if (val) |
2725 | 17.6M | f << "f" << i << "=" << val << ","; |
2726 | 28.6M | } |
2727 | 9.53M | font.setFont(static_cast<int>(input->readULong(2))); |
2728 | 9.53M | auto flags = static_cast<int>(input->readULong(1)); |
2729 | 9.53M | uint32_t flag = 0; |
2730 | 9.53M | if (flags & 0x1) flag |= MWAWFont::boldBit; |
2731 | 9.53M | if (flags & 0x2) flag |= MWAWFont::italicBit; |
2732 | 9.53M | if (flags & 0x4) font.setUnderlineStyle(MWAWFont::Line::Simple); |
2733 | 9.53M | if (flags & 0x8) flag |= MWAWFont::embossBit; |
2734 | 9.53M | if (flags & 0x10) flag |= MWAWFont::shadowBit; |
2735 | 9.53M | if (flags & 0x20) { |
2736 | 2.56M | if (vers==1) |
2737 | 221k | font.set(MWAWFont::Script(20,librevenge::RVNG_PERCENT,80)); |
2738 | 2.34M | else |
2739 | 2.34M | font.set(MWAWFont::Script::super100()); |
2740 | 2.56M | } |
2741 | 9.53M | if (flags & 0x40) { |
2742 | 2.17M | if (vers==1) |
2743 | 19.6k | font.set(MWAWFont::Script(-20,librevenge::RVNG_PERCENT,80)); |
2744 | 2.15M | else |
2745 | 2.15M | font.set(MWAWFont::Script::sub100()); |
2746 | 2.17M | } |
2747 | 9.53M | if (flags & 0x80) f << "#smaller,"; |
2748 | 9.53M | font.setFlags(flag); |
2749 | | |
2750 | 9.53M | auto val = static_cast<int>(input->readULong(1)); |
2751 | 9.53M | if (val) f << "#flags2=" << val << ","; |
2752 | 9.53M | font.setSize(float(input->readULong(2))); |
2753 | | |
2754 | 9.53M | unsigned char color[3]; |
2755 | 28.6M | for (auto &c : color) c = static_cast<unsigned char>(input->readULong(2)>>8); |
2756 | 9.53M | font.setColor(MWAWColor(color[0],color[1],color[2])); |
2757 | 9.53M | font.m_extra = f.str(); |
2758 | 9.53M | return true; |
2759 | 11.7M | } |
2760 | | |
2761 | | void MsWksGraph::sendTextBox(int zoneId, MWAWListenerPtr listener) |
2762 | 24.7k | { |
2763 | 24.7k | if (!listener || !listener->canWriteText()) { |
2764 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::sendTextBox: can not find get access to the listener\n")); |
2765 | 0 | return; |
2766 | 0 | } |
2767 | 24.7k | if (zoneId < 0 || zoneId >= int(m_state->m_zonesList.size())) { |
2768 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::sendTextBox: can not find textbox %d\n", zoneId)); |
2769 | 0 | return; |
2770 | 0 | } |
2771 | 24.7k | auto zone = m_state->m_zonesList[size_t(zoneId)]; |
2772 | 24.7k | if (!zone) return; |
2773 | 24.7k | auto &textBox = static_cast<MsWksGraphInternal::TextBox &>(*zone); |
2774 | 24.7k | listener->setFont(MWAWFont(20,12)); |
2775 | 24.7k | MWAWParagraph para; |
2776 | 24.7k | para.m_justify=textBox.m_justify; |
2777 | 24.7k | listener->setParagraph(para); |
2778 | 24.7k | auto numFonts = int(textBox.m_fontsList.size()); |
2779 | 24.7k | int actFormatPos = 0; |
2780 | 24.7k | auto numFormats = int(textBox.m_formats.size()); |
2781 | 24.7k | if (numFormats != int(textBox.m_positions.size())) { |
2782 | 22.4k | MWAW_DEBUG_MSG(("MsWksGraph::sendTextBox: positions and formats have different length\n")); |
2783 | 22.4k | if (numFormats > int(textBox.m_positions.size())) |
2784 | 22.4k | numFormats = int(textBox.m_positions.size()); |
2785 | 22.4k | } |
2786 | 151k | for (size_t i = 0; i < textBox.m_text.length(); i++) { |
2787 | 126k | if (actFormatPos < numFormats && textBox.m_positions[size_t(actFormatPos)]==int(i)) { |
2788 | 57 | int id = textBox.m_formats[size_t(actFormatPos++)]; |
2789 | 57 | if (id < 0 || id >= numFonts) { |
2790 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::sendTextBox: can not find a font\n")); |
2791 | 0 | } |
2792 | 57 | else |
2793 | 57 | listener->setFont(textBox.m_fontsList[size_t(id)]); |
2794 | 57 | } |
2795 | 126k | auto c = static_cast<unsigned char>(textBox.m_text[i]); |
2796 | 126k | switch (c) { |
2797 | 9.42k | case 0x9: |
2798 | 9.42k | MWAW_DEBUG_MSG(("MsWksGraph::sendTextBox: find some tab\n")); |
2799 | 9.42k | listener->insertChar(' '); |
2800 | 9.42k | break; |
2801 | 44.0k | case 0xd: |
2802 | 44.0k | if (i+1 != textBox.m_text.length()) |
2803 | 43.7k | listener->insertEOL(); |
2804 | 44.0k | break; |
2805 | 3.71k | case 0x19: |
2806 | 3.71k | listener->insertField(MWAWField(MWAWField::Title)); |
2807 | 3.71k | break; |
2808 | 7.76k | case 0x18: |
2809 | 7.76k | listener->insertField(MWAWField(MWAWField::PageNumber)); |
2810 | 7.76k | break; |
2811 | 2.47k | case 0x16: |
2812 | 2.47k | MWAW_DEBUG_MSG(("MsWksGraph::sendTextBox: find some time\n")); |
2813 | 2.47k | listener->insertField(MWAWField(MWAWField::Time)); |
2814 | 2.47k | break; |
2815 | 4.28k | case 0x17: |
2816 | 4.28k | MWAW_DEBUG_MSG(("MsWksGraph::sendTextBox: find some date\n")); |
2817 | 4.28k | listener->insertField(MWAWField(MWAWField::Date)); |
2818 | 4.28k | break; |
2819 | 2.69k | case 0x14: // fixme |
2820 | 2.69k | MWAW_DEBUG_MSG(("MsWksGraph::sendTextBox: footnote are not implemented\n")); |
2821 | 2.69k | break; |
2822 | 52.3k | default: |
2823 | 52.3k | listener->insertCharacter(c); |
2824 | 52.3k | break; |
2825 | 126k | } |
2826 | 126k | } |
2827 | 24.7k | } |
2828 | | |
2829 | | void MsWksGraph::send(int id, MWAWPosition const &pos) |
2830 | 3.17M | { |
2831 | 3.17M | if (id < 0 || id >= int(m_state->m_zonesList.size())) { |
2832 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::send: can not find zone %d\n", id)); |
2833 | 0 | return; |
2834 | 0 | } |
2835 | 3.17M | MWAWListenerPtr listener=m_parserState->getMainListener(); |
2836 | 3.17M | if (!listener) return; |
2837 | 3.17M | auto zone = m_state->m_zonesList[size_t(id)]; |
2838 | 3.17M | zone->m_isSent = true; |
2839 | | |
2840 | 3.17M | MWAWPosition pictPos(pos); |
2841 | 3.17M | if (pos.size()[0]<=0 || pos.size()[1]<=0) |
2842 | 2.69M | pictPos = zone->getPosition(pos.m_anchorTo); |
2843 | 3.17M | if (pictPos.m_anchorTo == MWAWPosition::Page) |
2844 | 1.28M | pictPos.setOrigin(pictPos.origin()+m_state->m_leftTopPos); |
2845 | | |
2846 | 3.17M | MWAWInputStreamPtr input=m_document.getInput(); |
2847 | 3.17M | bool isDraw=listener->getType()==MWAWListener::Graphic; |
2848 | 3.17M | switch (zone->type()) { |
2849 | 21.9k | case MsWksGraphInternal::Zone::Text: { |
2850 | 21.9k | auto &textbox = static_cast<MsWksGraphInternal::TextBox &>(*zone); |
2851 | 21.9k | MWAWBox2f box(MWAWVec2f(0,0),textbox.m_box.size()); |
2852 | 21.9k | std::shared_ptr<MsWksGraphInternal::SubDocument> subdoc |
2853 | 21.9k | (new MsWksGraphInternal::SubDocument(*this, input, MsWksGraphInternal::SubDocument::TextBox, id)); |
2854 | | // a textbox can not have border |
2855 | 21.9k | MWAWGraphicStyle style(textbox.m_style); |
2856 | 21.9k | style.m_lineWidth=0; |
2857 | 21.9k | if (isDraw) { |
2858 | 18.2k | listener->insertTextBox(pictPos, subdoc, style); |
2859 | 18.2k | return; |
2860 | 18.2k | } |
2861 | 3.65k | MWAWPosition textPos(box[0], box.size(), librevenge::RVNG_POINT); |
2862 | 3.65k | MWAWGraphicEncoder graphicEncoder; |
2863 | 3.65k | MWAWGraphicListener graphicListener(*m_parserState, box, &graphicEncoder); |
2864 | 3.65k | graphicListener.startDocument(); |
2865 | 3.65k | textPos.m_anchorTo=MWAWPosition::Page; |
2866 | 3.65k | textPos.m_wrapping=pos.m_wrapping; |
2867 | 3.65k | graphicListener.insertTextBox(textPos, subdoc, style); |
2868 | 3.65k | graphicListener.endDocument(); |
2869 | 3.65k | MWAWEmbeddedObject picture; |
2870 | 3.65k | if (graphicEncoder.getBinaryResult(picture)) |
2871 | 3.65k | listener->insertPicture(pictPos, picture); |
2872 | 3.65k | return; |
2873 | 21.9k | } |
2874 | 13.2k | case MsWksGraphInternal::Zone::TableZone: { |
2875 | 13.2k | auto &table = static_cast<MsWksGraphInternal::Table &>(*zone); |
2876 | 13.2k | if (isDraw) { |
2877 | 13.2k | listener->openFrame(pictPos, zone->m_style); |
2878 | 13.2k | m_tableParser->sendTable(table.m_tableId); |
2879 | 13.2k | listener->closeFrame(); |
2880 | 13.2k | return; |
2881 | 13.2k | } |
2882 | 0 | std::shared_ptr<MsWksGraphInternal::SubDocument> subdoc |
2883 | 0 | (new MsWksGraphInternal::SubDocument(*this, input, MsWksGraphInternal::SubDocument::Table, table.m_tableId)); |
2884 | 0 | listener->insertTextBox(pictPos, subdoc, zone->m_style); |
2885 | 0 | return; |
2886 | 13.2k | } |
2887 | 364 | case MsWksGraphInternal::Zone::ChartZone: { |
2888 | 364 | auto &chart = static_cast<MsWksGraphInternal::Chart &>(*zone); |
2889 | 364 | std::shared_ptr<MsWksGraphInternal::SubDocument> subdoc |
2890 | 364 | (new MsWksGraphInternal::SubDocument(*this, input, MsWksGraphInternal::SubDocument::Chart, chart.m_chartId)); |
2891 | 364 | listener->insertTextBox(pictPos, subdoc, zone->m_style); |
2892 | 364 | return; |
2893 | 13.2k | } |
2894 | 252k | case MsWksGraphInternal::Zone::Group: |
2895 | 252k | sendGroup(id, pictPos); |
2896 | 252k | return; |
2897 | 0 | case MsWksGraphInternal::Zone::Bitmap: { |
2898 | 0 | auto &bmap = static_cast<MsWksGraphInternal::DataBitmap &>(*zone); |
2899 | 0 | MWAWEmbeddedObject picture; |
2900 | 0 | if (!bmap.getPictureData(input, picture,m_document.getPalette(4))) |
2901 | 0 | break; |
2902 | 0 | m_document.ascii().skipZone(bmap.m_dataPos, bmap.m_pos.end()-1); |
2903 | 0 | listener->insertPicture(pictPos, picture, zone->m_style); |
2904 | 0 | return; |
2905 | 0 | } |
2906 | 2.52M | case MsWksGraphInternal::Zone::Shape: { |
2907 | 2.52M | auto &shape = static_cast<MsWksGraphInternal::BasicShape &>(*zone); |
2908 | 2.52M | listener->insertShape(pictPos, shape.m_shape, shape.getStyle()); |
2909 | 2.52M | return; |
2910 | 0 | } |
2911 | 106k | case MsWksGraphInternal::Zone::Pict: { |
2912 | 106k | MWAWEmbeddedObject picture; |
2913 | 106k | if (!zone->getBinaryData(input, picture)) |
2914 | 66.0k | break; |
2915 | 40.8k | listener->insertPicture(pictPos, picture, zone->m_style); |
2916 | 40.8k | return; |
2917 | 106k | } |
2918 | 174k | case MsWksGraphInternal::Zone::Textv4: { |
2919 | 174k | auto &textbox = static_cast<MsWksGraphInternal::TextBoxv4 &>(*zone); |
2920 | 174k | std::shared_ptr<MsWksGraphInternal::SubDocument> subdoc |
2921 | 174k | (new MsWksGraphInternal::SubDocument(*this, input, MsWksGraphInternal::SubDocument::TextBoxv4, textbox.m_text, textbox.m_frame)); |
2922 | 174k | MWAWGraphicStyle style; |
2923 | 174k | zone->fillFrame(style); |
2924 | | // a textbox can not have a border |
2925 | 174k | style.m_lineWidth=0; |
2926 | 174k | if (zone->m_ids[1] > 0) { |
2927 | 15.0k | librevenge::RVNGString fName; |
2928 | 15.0k | fName.sprintf("Frame%ld", zone->m_ids[0]); |
2929 | 15.0k | style.m_frameName=fName.cstr(); |
2930 | 15.0k | } |
2931 | 174k | if (zone->m_ids[2] > 0) { |
2932 | 0 | librevenge::RVNGString fName; |
2933 | 0 | fName.sprintf("Frame%ld", zone->m_ids[2]); |
2934 | 0 | style.m_frameNextName=fName.cstr(); |
2935 | 0 | } |
2936 | 174k | listener->insertTextBox(pictPos, subdoc, style); |
2937 | 174k | return; |
2938 | 106k | } |
2939 | 77.5k | case MsWksGraphInternal::Zone::OLE: { |
2940 | 77.5k | auto &ole = static_cast<MsWksGraphInternal::OLEZone &>(*zone); |
2941 | 77.5k | m_document.sendOLE(ole.m_oleId, pictPos, zone->m_style); |
2942 | 77.5k | return; |
2943 | 106k | } |
2944 | 0 | case MsWksGraphInternal::Zone::Unknown: |
2945 | | #if !defined(__clang__) |
2946 | | default: |
2947 | | #endif |
2948 | 0 | break; |
2949 | 3.17M | } |
2950 | | |
2951 | 66.0k | MWAW_DEBUG_MSG(("MsWksGraph::send: can not send zone %d\n", id)); |
2952 | 66.0k | } |
2953 | | |
2954 | | void MsWksGraph::sendAll(int zoneId, bool mainZone) |
2955 | 1.65M | { |
2956 | 1.65M | MWAWPosition undefPos; |
2957 | 7.83M | for (size_t i = 0; i < m_state->m_zonesList.size(); i++) { |
2958 | 6.18M | auto zone = m_state->m_zonesList[i]; |
2959 | 6.18M | if (zoneId >= 0 && zoneId!=zone->m_zoneId) |
2960 | 2.45M | continue; |
2961 | 3.72M | if (zone->m_doNotSend || (zone->m_isSent && mainZone)) |
2962 | 1.18M | continue; |
2963 | 2.54M | undefPos.m_anchorTo = mainZone ? MWAWPosition::Page : MWAWPosition::Paragraph; |
2964 | 2.54M | send(int(i), undefPos); |
2965 | 2.54M | } |
2966 | 1.65M | } |
2967 | | |
2968 | | void MsWksGraph::sendObjects(MsWksGraph::SendData const &what) |
2969 | 4.70M | { |
2970 | 4.70M | MWAWListenerPtr listener=m_parserState->getMainListener(); |
2971 | 4.70M | if (!listener) { |
2972 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::sendObjects: listener is not set\n")); |
2973 | 0 | return; |
2974 | 0 | } |
2975 | | |
2976 | 4.70M | bool first = true; |
2977 | 4.70M | auto numZones = int(m_state->m_zonesList.size()); |
2978 | 4.70M | std::vector<int> listIds; |
2979 | 4.70M | MsWksGraphInternal::RBZone *rbZone=nullptr; |
2980 | 4.70M | switch (what.m_type) { |
2981 | 0 | case MsWksGraph::SendData::ALL: |
2982 | 0 | listIds.resize(size_t(numZones)); |
2983 | 0 | for (int i = 0; i < numZones; i++) listIds[size_t(i)]=i; |
2984 | 0 | break; |
2985 | 3.65M | case MsWksGraph::SendData::RBDR: |
2986 | 4.70M | case MsWksGraph::SendData::RBIL: { |
2987 | 4.70M | int zId = what.m_type==MsWksGraph::SendData::RBDR ? -1 : what.m_id; |
2988 | 4.70M | if (m_state->m_RBsMap.find(zId)!=m_state->m_RBsMap.end()) |
2989 | 3.89M | rbZone = &m_state->m_RBsMap.find(zId)->second; |
2990 | 4.70M | break; |
2991 | 3.65M | } |
2992 | | #if !defined(__clang__) |
2993 | | default: |
2994 | | break; |
2995 | | #endif |
2996 | 4.70M | } |
2997 | 4.70M | if (rbZone) |
2998 | 3.89M | listIds=rbZone->m_idList; |
2999 | 4.70M | bool isText=m_parserState->m_type==MWAWParserState::Text; |
3000 | 4.70M | if (isText && what.m_type==MsWksGraph::SendData::RBIL) { |
3001 | 0 | if (!rbZone) { |
3002 | 0 | MWAW_DEBUG_MSG(("MsWksGraph::sendObjects: can find RBIL zone %d\n", what.m_id)); |
3003 | 0 | return; |
3004 | 0 | } |
3005 | 0 | if (listIds.size() != 1) { |
3006 | 0 | if (what.m_anchor == MWAWPosition::Char || |
3007 | 0 | what.m_anchor == MWAWPosition::CharBaseLine) { |
3008 | 0 | std::shared_ptr<MsWksGraphInternal::SubDocument> subdoc |
3009 | 0 | (new MsWksGraphInternal::SubDocument(*this, m_document.getInput(), MsWksGraphInternal::SubDocument::RBILZone, what.m_id)); |
3010 | 0 | MWAWPosition pictPos(MWAWVec2f(0,0), MWAWVec2f(what.m_size), librevenge::RVNG_POINT); |
3011 | 0 | pictPos.setRelativePosition(MWAWPosition::Char, |
3012 | 0 | MWAWPosition::XLeft, MWAWPosition::YTop); |
3013 | 0 | pictPos.m_wrapping = MWAWPosition::WBackground; |
3014 | 0 | listener->insertTextBox(pictPos, subdoc); |
3015 | 0 | return; |
3016 | 0 | } |
3017 | 0 | } |
3018 | 0 | } |
3019 | 4.70M | MWAWPosition undefPos; |
3020 | 4.70M | undefPos.m_anchorTo = what.m_anchor; |
3021 | 19.8M | for (auto id : listIds) { |
3022 | 19.8M | if (id < 0 || id >= numZones) continue; |
3023 | 19.8M | auto zone = m_state->m_zonesList[size_t(id)]; |
3024 | 19.8M | if (!zone || zone->m_doNotSend) continue; |
3025 | 18.7M | if (zone->m_isSent) { |
3026 | 7.69M | if (what.m_type == MsWksGraph::SendData::ALL || |
3027 | 7.69M | (isText && what.m_anchor == MWAWPosition::Page)) continue; |
3028 | 7.69M | } |
3029 | 18.7M | if (what.m_anchor == MWAWPosition::Page) { |
3030 | 18.7M | if (what.m_page > 0 && zone->m_page+1 != what.m_page) continue; |
3031 | 580k | else if (what.m_page==0 && zone->m_page < 0) continue; |
3032 | 580k | else if (what.m_page==-2 && zone->m_page >=0) continue; |
3033 | 580k | undefPos=zone->getPosition(MWAWPosition::Page); |
3034 | 580k | } |
3035 | | |
3036 | 580k | if (isText && first) { |
3037 | 0 | first = false; |
3038 | 0 | if (what.m_anchor == MWAWPosition::Page && !listener->isSectionOpened() && !listener->isParagraphOpened()) |
3039 | 0 | listener->insertChar(' '); |
3040 | 0 | } |
3041 | 580k | send(int(id), undefPos); |
3042 | 580k | } |
3043 | 4.70M | } |
3044 | | |
3045 | | void MsWksGraph::flushExtra() |
3046 | 57.4k | { |
3047 | 57.4k | MWAWPosition undefPos; |
3048 | 57.4k | undefPos.m_anchorTo=MWAWPosition::Char; |
3049 | 1.18M | for (size_t i = 0; i < m_state->m_zonesList.size(); i++) { |
3050 | 1.12M | auto zone = m_state->m_zonesList[i]; |
3051 | 1.12M | if (!zone || zone->m_isSent || zone->m_doNotSend) continue; |
3052 | 8.89k | send(int(i), undefPos); |
3053 | 8.89k | } |
3054 | 57.4k | } |
3055 | | |
3056 | | //////////////////////////////////////////////////////////// |
3057 | | // style |
3058 | | //////////////////////////////////////////////////////////// |
3059 | | MsWksGraph::Style::~Style() |
3060 | 127M | { |
3061 | 127M | } |
3062 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |