/src/libmwaw/src/lib/FreeHandParser.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 <algorithm> |
35 | | #include <cmath> |
36 | | #include <iomanip> |
37 | | #include <iostream> |
38 | | #include <limits> |
39 | | #include <map> |
40 | | #include <set> |
41 | | #include <sstream> |
42 | | #include <utility> |
43 | | |
44 | | #include <librevenge/librevenge.h> |
45 | | |
46 | | #include "MWAWFont.hxx" |
47 | | #include "MWAWFontConverter.hxx" |
48 | | #include "MWAWGraphicListener.hxx" |
49 | | #include "MWAWGraphicShape.hxx" |
50 | | #include "MWAWGraphicStyle.hxx" |
51 | | #include "MWAWHeader.hxx" |
52 | | #include "MWAWParagraph.hxx" |
53 | | #include "MWAWPictBitmap.hxx" |
54 | | #include "MWAWPictData.hxx" |
55 | | #include "MWAWPrinter.hxx" |
56 | | #include "MWAWPosition.hxx" |
57 | | #include "MWAWSubDocument.hxx" |
58 | | |
59 | | #include "FreeHandParser.hxx" |
60 | | |
61 | | /** Internal: the structures of a FreeHandParser */ |
62 | | namespace FreeHandParserInternal |
63 | | { |
64 | | //! the different zone type |
65 | | enum ZoneType { Z_Unknown, Z_Color, Z_ColorGroup, Z_Dash, Z_DashGroup, Z_Data, Z_Fill, Z_FillGroup, Z_Group, |
66 | | Z_LineStyle, Z_LineStyleGroup, Z_Note, Z_Picture, Z_PictureName, Z_String, Z_Shape, Z_StyleGroup |
67 | | }; |
68 | | |
69 | | /** struct which defines the screen parameters in FreeHandParserInternal */ |
70 | | struct ScreenMode { |
71 | | //! constructor |
72 | | ScreenMode() |
73 | 943k | : m_function(0) |
74 | 943k | , m_angle(0) |
75 | 943k | , m_lineByInch(0) |
76 | 943k | , m_value(0) |
77 | 943k | { |
78 | 943k | } |
79 | | //! operator<< |
80 | | friend std::ostream &operator<<(std::ostream &o, ScreenMode const &screen) |
81 | 0 | { |
82 | 0 | switch (screen.m_function) { |
83 | 0 | case 0: // unset |
84 | 0 | case -1: // default |
85 | 0 | break; |
86 | 0 | case 1: |
87 | 0 | o << "function=round,"; |
88 | 0 | break; |
89 | 0 | case 2: |
90 | 0 | o << "function=line,"; |
91 | 0 | break; |
92 | 0 | default: |
93 | 0 | MWAW_DEBUG_MSG(("FreeHandParserInternal::operator<<(ScreenMode): find unexpected screen function\n")); |
94 | 0 | o << "function=###" << screen.m_function << ","; |
95 | 0 | break; |
96 | 0 | } |
97 | 0 | if (screen.m_angle < 0 || screen.m_angle>0) |
98 | 0 | o << "angle=" << screen.m_angle << ","; |
99 | 0 | if (screen.m_lineByInch==0xFFFF) |
100 | 0 | o << "lineByInch*,"; |
101 | 0 | else |
102 | 0 | o << "lineByInch=" << screen.m_lineByInch << ","; |
103 | 0 | if (screen.m_value) |
104 | 0 | o << "unkn0=" << screen.m_value << ","; |
105 | 0 | return o; |
106 | 0 | } |
107 | | |
108 | | //! the function |
109 | | int m_function; |
110 | | //! the angle |
111 | | float m_angle; |
112 | | //! the line/inch |
113 | | int m_lineByInch; |
114 | | //! unknow value |
115 | | int m_value; |
116 | | }; |
117 | | |
118 | | /** small structure of FreeHandParserInternal used to stored |
119 | | a shape header |
120 | | */ |
121 | | struct ShapeHeader { |
122 | | //! constructor |
123 | | ShapeHeader() |
124 | 532k | : m_size(0) |
125 | 532k | , m_type(0) |
126 | 532k | , m_note("") |
127 | 532k | , m_dataId(0) |
128 | 532k | , m_layerId(-1) |
129 | 532k | , m_screen() |
130 | 532k | , m_extra("") |
131 | 532k | { |
132 | 2.12M | for (auto &value : m_values) value=0; |
133 | 532k | } |
134 | | //! operator<< |
135 | | friend std::ostream &operator<<(std::ostream &o, ShapeHeader const &shape) |
136 | 0 | { |
137 | 0 | if (shape.m_layerId>=0) o << "layer=" << shape.m_layerId << ","; |
138 | 0 | if (shape.m_dataId) o << "data=Z" << shape.m_dataId << ","; |
139 | 0 | if (!shape.m_note.empty()) o << "note=\"" << shape.m_note << "\","; |
140 | 0 | if (shape.m_screen.isSet()) o << "screen=[" << *shape.m_screen << "],"; |
141 | 0 | for (int i=0; i<3; ++i) { |
142 | 0 | if (!shape.m_values[i]) |
143 | 0 | continue; |
144 | 0 | int val=shape.m_values[i]; |
145 | 0 | if (i==1 && (val&1)) { |
146 | 0 | o << "locked,"; |
147 | 0 | val&=0xFFFE; |
148 | 0 | } |
149 | 0 | if (val) |
150 | 0 | o << "unkn" << i << "=" << val << ","; |
151 | 0 | } |
152 | 0 | if (shape.m_values[3]) // always a 1005 zone ? |
153 | 0 | o << "unknZone=Z" << shape.m_values[3] << ","; |
154 | 0 | o << shape.m_extra; |
155 | 0 | return o; |
156 | 0 | } |
157 | | //! a field related to the zone size |
158 | | long m_size; |
159 | | //! the zone type |
160 | | int m_type; |
161 | | //! the note |
162 | | std::string m_note; |
163 | | //! the data id (used to store a note, ...) |
164 | | int m_dataId; |
165 | | //! the layer id |
166 | | int m_layerId; |
167 | | //! the screen mode |
168 | | MWAWVariable<ScreenMode> m_screen; |
169 | | //! the unknown values |
170 | | int m_values[4]; |
171 | | //! extra data |
172 | | std::string m_extra; |
173 | | }; |
174 | | |
175 | | /** small structure of FreeHandParserInternal used to stored |
176 | | a fill style |
177 | | */ |
178 | | struct FillStyle { |
179 | | //! constructor |
180 | | FillStyle() |
181 | 79.3k | : m_type(MWAWGraphicStyle::Gradient::G_None) |
182 | 79.3k | , m_pattern() |
183 | 79.3k | , m_angle(0) |
184 | 79.3k | , m_logarithm(false) |
185 | 79.3k | { |
186 | 158k | for (auto &colorId : m_colorId) colorId=0; |
187 | 79.3k | } |
188 | | //! the gradient type |
189 | | MWAWGraphicStyle::Gradient::Type m_type; |
190 | | //! the color id |
191 | | int m_colorId[2]; |
192 | | //! the pattern |
193 | | MWAWGraphicStyle::Pattern m_pattern; |
194 | | //! the angle |
195 | | float m_angle; |
196 | | //! flag to know if a flag has logarithmic scale |
197 | | bool m_logarithm; |
198 | | }; |
199 | | |
200 | | /** small structure of FreeHandParserInternal used to stored |
201 | | a line style |
202 | | */ |
203 | | struct LineStyle { |
204 | | //! constructor |
205 | | LineStyle() |
206 | 109k | : m_width(1) |
207 | 109k | , m_colorId(0) |
208 | 109k | , m_dashId(0) |
209 | 109k | , m_pattern() |
210 | 109k | , m_miterLimit(0) |
211 | 109k | , m_cap(MWAWGraphicStyle::C_Butt) |
212 | 109k | , m_join(MWAWGraphicStyle::J_Miter) |
213 | 109k | { |
214 | 109k | } |
215 | | //! the line width |
216 | | float m_width; |
217 | | //! the color id |
218 | | int m_colorId; |
219 | | //! the dash id |
220 | | int m_dashId; |
221 | | //! the pattern |
222 | | MWAWGraphicStyle::Pattern m_pattern; |
223 | | //! the miter limit |
224 | | float m_miterLimit; |
225 | | //! the line cap |
226 | | MWAWGraphicStyle::LineCap m_cap; |
227 | | //! the line join |
228 | | MWAWGraphicStyle::LineJoin m_join; |
229 | | }; |
230 | | /** small structure of FreeHandParserInternal used to stored |
231 | | a style header |
232 | | */ |
233 | | struct StyleHeader { |
234 | | //! constructor |
235 | | StyleHeader() |
236 | 411k | : m_size(0) |
237 | 411k | , m_type(0) |
238 | 411k | , m_labelId(0) |
239 | 411k | , m_screen() |
240 | 411k | , m_unknownValue(0) |
241 | 411k | , m_extra("") |
242 | 411k | { |
243 | 411k | } |
244 | | //! operator<< |
245 | | friend std::ostream &operator<<(std::ostream &o, StyleHeader const &style) |
246 | 0 | { |
247 | 0 | if (style.m_labelId) o << "label=Z" << style.m_labelId << ","; |
248 | 0 | if (style.m_screen.isSet()) o << "screen=[" << *style.m_screen << "],"; |
249 | 0 | if (style.m_unknownValue) |
250 | 0 | o << "unkn0=" << style.m_unknownValue << ","; |
251 | 0 | o << style.m_extra; |
252 | 0 | return o; |
253 | 0 | } |
254 | | //! a field related to the zone size |
255 | | long m_size; |
256 | | //! the zone type |
257 | | int m_type; |
258 | | //! the label id |
259 | | int m_labelId; |
260 | | //! the screen mode |
261 | | MWAWVariable<ScreenMode> m_screen; |
262 | | //! the first unknown value |
263 | | int m_unknownValue; |
264 | | //! extra data |
265 | | std::string m_extra; |
266 | | }; |
267 | | |
268 | | /** small structure of FreeHandParserInternal used to stored a shape |
269 | | */ |
270 | | struct Shape { |
271 | | //! the different type |
272 | | enum Type { Line, Rectangle, Ellipse, Path, BackgroundPicture, Picture, Group, JoinGroup, Unknown }; |
273 | | |
274 | | //! constructor |
275 | | Shape() |
276 | 401k | : m_id(0) |
277 | 401k | , m_type(Unknown) |
278 | 401k | , m_layerId(-1) |
279 | 401k | , m_lineId(0) |
280 | 401k | , m_fillId(0) |
281 | 401k | , m_transformation() |
282 | 401k | , m_box() |
283 | 401k | , m_corner() |
284 | 401k | , m_vertices() |
285 | 401k | , m_closed(false) |
286 | 401k | , m_evenOdd(false) |
287 | 401k | , m_joinDistance(0) |
288 | 401k | , m_childs() |
289 | 401k | , m_picture() |
290 | 401k | , m_dataId(0) |
291 | 401k | , m_isSent(false) |
292 | 401k | { |
293 | 401k | } |
294 | | |
295 | | //! try to returns a shape and position |
296 | | bool updateShape(MWAWGraphicShape &shape) const |
297 | 17.9k | { |
298 | 17.9k | if (m_type==Line || m_type==Rectangle || m_type==Ellipse) { |
299 | 16.0k | MWAWBox2f box=m_box; |
300 | 16.0k | if (m_type==Line) |
301 | 3.22k | shape=MWAWGraphicShape::line(box[0],box[1]); |
302 | 12.8k | else if (m_type==Rectangle) |
303 | 8.05k | shape=MWAWGraphicShape::rectangle(box, m_corner); |
304 | 4.74k | else |
305 | 4.74k | shape=MWAWGraphicShape::circle(box); |
306 | 16.0k | return true; |
307 | 16.0k | } |
308 | 1.90k | if (m_type!=Path || m_vertices.empty()) return false; |
309 | 1.83k | if (m_vertices.size()<6) { |
310 | | // probably an aborted spline, transform in a point |
311 | 23 | MWAWVec2f pt=m_vertices[0]; |
312 | 23 | shape=MWAWGraphicShape::line(pt,pt); |
313 | 23 | return true; |
314 | 23 | } |
315 | 1.81k | shape.m_type=MWAWGraphicShape::Polygon; |
316 | 1.81k | MWAWBox2f box; |
317 | 1.81k | bool needSpline=false; |
318 | 37.5k | for (size_t i=0; i+2<m_vertices.size(); i+=3) { |
319 | 35.6k | MWAWVec2f pt=m_vertices[i]; |
320 | 35.6k | if (i==0) |
321 | 1.81k | box=MWAWBox2f(pt,pt); |
322 | 33.8k | else |
323 | 33.8k | box=box.getUnion(MWAWBox2f(pt,pt)); |
324 | 35.6k | if (!needSpline && (m_vertices[i]!=m_vertices[i+1] || m_vertices[i]!=m_vertices[i+2])) |
325 | 1.80k | needSpline=true; |
326 | 35.6k | shape.m_vertices.push_back(pt); |
327 | 35.6k | } |
328 | 1.81k | shape.m_bdBox=box; |
329 | 1.81k | if (m_closed) |
330 | 175 | shape.m_vertices.push_back(shape.m_vertices.front()); |
331 | 1.81k | if (!needSpline) |
332 | 12 | return true; |
333 | | |
334 | 1.80k | MWAWVec2f prevPoint, pt1; |
335 | 1.80k | bool hasPrevPoint = false; |
336 | 1.80k | shape.m_type=MWAWGraphicShape::Path; |
337 | 1.80k | shape.m_vertices.clear(); |
338 | 37.4k | for (size_t i=0; i+2<m_vertices.size()+3; i+=3) { |
339 | 37.4k | bool end=i+2>=m_vertices.size(); |
340 | 37.4k | if (end) { |
341 | 1.80k | if (!m_closed) |
342 | 1.63k | break; |
343 | 172 | if (end && !hasPrevPoint && m_vertices[0]==m_vertices[1]) { |
344 | 17 | shape.m_path.push_back(MWAWGraphicShape::PathData('Z')); |
345 | 17 | break; |
346 | 17 | } |
347 | 155 | i=0; |
348 | 155 | } |
349 | 35.8k | MWAWVec2f pt=m_vertices[i]; |
350 | 35.8k | pt1 = m_vertices[i+1]; |
351 | 35.8k | char type = hasPrevPoint ? 'C' : i==0 ? 'M' : (m_vertices[i]!=m_vertices[i+1]) ? 'S' : 'L'; |
352 | 35.8k | shape.m_path.push_back(MWAWGraphicShape::PathData(type, pt, hasPrevPoint ? prevPoint : pt1, pt1)); |
353 | 35.8k | hasPrevPoint = m_vertices[i]!=m_vertices[i+2]; |
354 | 35.8k | if (hasPrevPoint) |
355 | 26.2k | prevPoint=m_vertices[i+2]; |
356 | 35.8k | if (end) |
357 | 155 | break; |
358 | 35.8k | } |
359 | 1.80k | return true; |
360 | 1.81k | } |
361 | | //! the zone id |
362 | | int m_id; |
363 | | //! the type |
364 | | Type m_type; |
365 | | //! the layer |
366 | | int m_layerId; |
367 | | //! the line id |
368 | | int m_lineId; |
369 | | //! the fill id |
370 | | int m_fillId; |
371 | | |
372 | | //! the transformation |
373 | | MWAWTransformation m_transformation; |
374 | | //! the main box (for line, rectangle, ellipse) |
375 | | MWAWBox2f m_box; |
376 | | //! the corner size |
377 | | MWAWVec2f m_corner; |
378 | | //! the list of point for path: 3 Vec2f defining each point |
379 | | std::vector<MWAWVec2f> m_vertices; |
380 | | //! a flag to know if a path is closed |
381 | | bool m_closed; |
382 | | //! a flag to know how path intersection are defined |
383 | | bool m_evenOdd; |
384 | | //! the join distance |
385 | | float m_joinDistance; |
386 | | //! the list of child (for group and join group ) |
387 | | std::vector<int> m_childs; |
388 | | //! the picture entry |
389 | | MWAWEntry m_picture; |
390 | | //! the id of a the picture date |
391 | | int m_dataId; |
392 | | //! flag to known if a shape is sent |
393 | | mutable bool m_isSent; |
394 | | }; |
395 | | |
396 | | /** structure of FreeHandParserInternal used to stored a font */ |
397 | | struct Font { |
398 | | //! constructor |
399 | | Font() |
400 | 1.52M | : m_font() |
401 | 1.52M | , m_nameId(0) |
402 | 1.52M | , m_colorId(0) |
403 | 1.52M | { |
404 | 1.52M | } |
405 | | //! the font |
406 | | MWAWFont m_font; |
407 | | //! the font name id |
408 | | int m_nameId; |
409 | | //! the font color id |
410 | | int m_colorId; |
411 | | }; |
412 | | |
413 | | /** structure of FreeHandParserInternal used to stored a textbox */ |
414 | | struct Textbox { |
415 | | //! constructor |
416 | | explicit Textbox(int id) |
417 | 134k | : m_id(id) |
418 | 134k | , m_layerId(-1) |
419 | 134k | , m_box() |
420 | 134k | , m_transformation() |
421 | 134k | , m_spacings(0,0) |
422 | 134k | , m_scalings(1,1) |
423 | 134k | , m_baseline(0) |
424 | 134k | , m_justify(MWAWParagraph::JustificationLeft) |
425 | 134k | , m_text() |
426 | 134k | , m_posToFontMap() |
427 | 134k | , m_isSent(false) |
428 | 134k | { |
429 | 134k | } |
430 | | //! the textbox id |
431 | | int m_id; |
432 | | //! the layer id |
433 | | int m_layerId; |
434 | | //! the main box |
435 | | MWAWBox2f m_box; |
436 | | //! the transformation |
437 | | MWAWTransformation m_transformation; |
438 | | //! the letter/word spacing |
439 | | MWAWVec2f m_spacings; |
440 | | //! the horizontal/vertical scalings |
441 | | MWAWVec2f m_scalings; |
442 | | //! the baseline |
443 | | float m_baseline; |
444 | | //! the paragraph justification |
445 | | MWAWParagraph::Justification m_justify; |
446 | | //! the text data |
447 | | MWAWEntry m_text; |
448 | | //! map char pos to font |
449 | | std::map<int, Font> m_posToFontMap; |
450 | | //! flag to known if a shape is sent |
451 | | mutable bool m_isSent; |
452 | | }; |
453 | | |
454 | | //////////////////////////////////////// |
455 | | //! Internal: the state of a FreeHandParser |
456 | | struct State { |
457 | | //! constructor |
458 | | State() |
459 | 147k | : m_mainGroupId(0) |
460 | 147k | , m_transform() |
461 | 147k | , m_zIdToTypeMap() |
462 | 147k | , m_zIdToColorMap() |
463 | 147k | , m_zIdToDashMap() |
464 | 147k | , m_zIdToDataMap() |
465 | 147k | , m_zIdToFillStyleMap() |
466 | 147k | , m_zIdToLineStyleMap() |
467 | 147k | , m_zIdToStringMap() |
468 | 147k | , m_zIdToPostscriptMap() |
469 | 147k | , m_zIdToShapeMap() |
470 | 147k | , m_zIdToTextboxMap() |
471 | 147k | , m_actualLayer(-1) |
472 | 147k | , m_sendIdSet() |
473 | 147k | , m_sendLayerSet() |
474 | 147k | { |
475 | 147k | } |
476 | | //! try to return a zone type |
477 | | ZoneType getZoneType(int id) const |
478 | 71.0k | { |
479 | 71.0k | if (m_zIdToTypeMap.find(id)==m_zIdToTypeMap.end()) |
480 | 7.40k | return Z_Unknown; |
481 | 63.6k | return m_zIdToTypeMap.find(id)->second; |
482 | 71.0k | } |
483 | | //! try to add a id |
484 | | bool addZoneId(int id, ZoneType zoneType) |
485 | 5.33M | { |
486 | 5.33M | if (m_zIdToTypeMap.find(id)!=m_zIdToTypeMap.end()) |
487 | 4.37M | return m_zIdToTypeMap.find(id)->second==zoneType; |
488 | 958k | m_zIdToTypeMap[id]=zoneType; |
489 | 958k | return true; |
490 | 5.33M | } |
491 | | //! try to update the fill style |
492 | | bool updateFillStyle(int zId, MWAWGraphicStyle &style) const; |
493 | | //! try to update the line style |
494 | | bool updateLineStyle(int zId, MWAWGraphicStyle &style) const; |
495 | | //! try to update the group layer id, return 0 or the new layer id |
496 | | int updateGroupLayerId(int zId, std::set<int> &seen); |
497 | | //! the main group id |
498 | | int m_mainGroupId; |
499 | | //! the main transformation |
500 | | MWAWTransformation m_transform; |
501 | | //! the list of id seen |
502 | | std::map<int, ZoneType> m_zIdToTypeMap; |
503 | | //! the list zoneId to color |
504 | | std::map<int, MWAWColor> m_zIdToColorMap; |
505 | | //! the list zoneId to dash |
506 | | std::map<int, std::vector<float> > m_zIdToDashMap; |
507 | | //! the list zoneId to data map |
508 | | std::map<int, MWAWEntry> m_zIdToDataMap; |
509 | | //! the list zoneId to fillStyle |
510 | | std::map<int, FillStyle> m_zIdToFillStyleMap; |
511 | | //! the list zoneId to lineStyle |
512 | | std::map<int, LineStyle> m_zIdToLineStyleMap; |
513 | | //! the list zoneId to string |
514 | | std::map<int, std::string> m_zIdToStringMap; |
515 | | //! the list zoneId to postscrip code |
516 | | std::map<int, std::string> m_zIdToPostscriptMap; |
517 | | //! the list zoneId to shape |
518 | | std::map<int, Shape> m_zIdToShapeMap; |
519 | | //! the list zoneId to textbox |
520 | | std::map<int, Textbox> m_zIdToTextboxMap; |
521 | | //! the actual layer |
522 | | int m_actualLayer; |
523 | | //! a set of send id used to avoid potential loop |
524 | | std::set<int> m_sendIdSet; |
525 | | //! a set of create layer to avoid dupplicating layer |
526 | | std::set<int> m_sendLayerSet; |
527 | | }; |
528 | | |
529 | | bool State::updateFillStyle(int zId, MWAWGraphicStyle &style) const |
530 | 12.9k | { |
531 | 12.9k | if (!zId) return true; |
532 | | // can be a simple color |
533 | 11.4k | if (m_zIdToColorMap.find(zId)!=m_zIdToColorMap.end()) { |
534 | 99 | style.setSurfaceColor(m_zIdToColorMap.find(zId)->second); |
535 | 99 | return true; |
536 | 99 | } |
537 | 11.3k | if (m_zIdToFillStyleMap.find(zId)==m_zIdToFillStyleMap.end()) { |
538 | 7.27k | static bool first=true; |
539 | 7.27k | if (first) { |
540 | 13 | first=false; |
541 | 13 | MWAW_DEBUG_MSG(("FreeHandParserInternal::State::updateFillStyle: can not find style %d\n", zId)); |
542 | 13 | } |
543 | 7.27k | return false; |
544 | 7.27k | } |
545 | 4.06k | FillStyle const &fill=m_zIdToFillStyleMap.find(zId)->second; |
546 | 4.06k | int numColors=fill.m_type==MWAWGraphicStyle::Gradient::G_None ? 1 : 2; |
547 | 4.06k | MWAWColor colors[2]; |
548 | 9.76k | for (int i=0; i<numColors; ++i) { |
549 | 6.11k | if (fill.m_colorId[i]==0) { |
550 | 2.02k | colors[i]=MWAWColor::white(); |
551 | 2.02k | continue; |
552 | 2.02k | } |
553 | 4.09k | if (m_zIdToColorMap.find(fill.m_colorId[i])==m_zIdToColorMap.end()) { |
554 | 415 | MWAW_DEBUG_MSG(("FreeHandParserInternal::State::updateFillStyle: can not find some color %d\n", fill.m_colorId[i])); |
555 | 415 | return false; |
556 | 415 | } |
557 | 3.68k | colors[i]=m_zIdToColorMap.find(fill.m_colorId[i])->second; |
558 | 3.68k | } |
559 | 3.65k | if (!fill.m_pattern.empty()) { |
560 | 689 | auto pat=fill.m_pattern; |
561 | 689 | pat.m_colors[0]=MWAWColor::white(); |
562 | 689 | pat.m_colors[1]=colors[0]; |
563 | 689 | style.setPattern(pat); |
564 | 689 | return true; |
565 | 689 | } |
566 | 2.96k | if (fill.m_type==MWAWGraphicStyle::Gradient::G_None) { |
567 | 969 | style.setSurfaceColor(colors[0]); |
568 | 969 | return true; |
569 | 969 | } |
570 | 1.99k | auto &finalGrad=style.m_gradient; |
571 | 1.99k | finalGrad.m_type = fill.m_type; |
572 | 1.99k | finalGrad.m_angle = 270.f-fill.m_angle; |
573 | 1.99k | finalGrad.m_stopList.resize(2); |
574 | 5.97k | for (size_t i=0; i<2; ++i) |
575 | 3.98k | finalGrad.m_stopList[i]=MWAWGraphicStyle::Gradient::Stop(float(i), colors[i]); |
576 | 1.99k | return true; |
577 | 2.96k | } |
578 | | |
579 | | bool State::updateLineStyle(int zId, MWAWGraphicStyle &style) const |
580 | 17.9k | { |
581 | 17.9k | if (!zId) { |
582 | 131 | style.m_lineWidth=0; |
583 | 131 | return true; |
584 | 131 | } |
585 | 17.8k | if (m_zIdToLineStyleMap.find(zId)==m_zIdToLineStyleMap.end()) { |
586 | 14.4k | MWAW_DEBUG_MSG(("FreeHandParserInternal::State::updateLineStyle: can not find style %d\n", zId)); |
587 | 14.4k | style.m_lineWidth=1; |
588 | 14.4k | return false; |
589 | 14.4k | } |
590 | 3.33k | LineStyle const &line=m_zIdToLineStyleMap.find(zId)->second; |
591 | 3.33k | style.m_lineWidth=line.m_width; |
592 | 3.33k | MWAWColor color=MWAWColor::white(); |
593 | 3.33k | if (line.m_colorId) { |
594 | 3.22k | if (m_zIdToColorMap.find(line.m_colorId)==m_zIdToColorMap.end()) { |
595 | 932 | static bool first=true; |
596 | 932 | if (first) { |
597 | 13 | first=false; |
598 | 13 | MWAW_DEBUG_MSG(("FreeHandParserInternal::State::updateLineStyle: can not find some color %d\n", line.m_colorId)); |
599 | 13 | } |
600 | 932 | } |
601 | 2.29k | else |
602 | 2.29k | color=m_zIdToColorMap.find(line.m_colorId)->second; |
603 | 3.22k | } |
604 | 3.33k | if (!line.m_pattern.empty()) { |
605 | 19 | auto pat=line.m_pattern; |
606 | | // CHECKME |
607 | 19 | pat.m_colors[0]=MWAWColor::white(); |
608 | 19 | pat.m_colors[1]=color; |
609 | 19 | pat.getAverageColor(style.m_lineColor); |
610 | 19 | } |
611 | 3.31k | else |
612 | 3.31k | style.m_lineColor=color; |
613 | 3.33k | if (line.m_dashId) { |
614 | 920 | if (m_zIdToDashMap.find(line.m_dashId)==m_zIdToDashMap.end()) { |
615 | 500 | MWAW_DEBUG_MSG(("FreeHandParserInternal::State::updateLineStyle: can not find dash %d\n", line.m_dashId)); |
616 | 500 | } |
617 | 420 | else if (m_zIdToDashMap.find(line.m_dashId)->second.size()>1) |
618 | 406 | style.m_lineDashWidth=m_zIdToDashMap.find(line.m_dashId)->second; |
619 | 920 | } |
620 | 3.33k | style.m_lineCap=line.m_cap; |
621 | 3.33k | style.m_lineJoin=line.m_join; |
622 | 3.33k | return true; |
623 | 17.8k | } |
624 | | |
625 | | int State::updateGroupLayerId(int zId, std::set<int> &seen) |
626 | 55.2k | { |
627 | 55.2k | if (m_zIdToTextboxMap.find(zId)!=m_zIdToTextboxMap.end()) |
628 | 2.91k | return m_zIdToTextboxMap.find(zId)->second.m_layerId; |
629 | 52.3k | if (m_zIdToShapeMap.find(zId)==m_zIdToShapeMap.end()) |
630 | 29.5k | return -1; |
631 | 22.8k | Shape &shape=m_zIdToShapeMap.find(zId)->second; |
632 | 22.8k | if (seen.find(zId)!=seen.end() || (shape.m_type!=Shape::Group && shape.m_type!=Shape::JoinGroup)) |
633 | 18.3k | return shape.m_layerId; |
634 | 4.49k | int layerId=-1; |
635 | 4.49k | seen.insert(zId); |
636 | 4.49k | bool first=true; |
637 | 52.1k | for (auto const &child : shape.m_childs) { |
638 | 52.1k | int newLayerId=updateGroupLayerId(child, seen); |
639 | 52.1k | if (newLayerId==-1 || (!first && layerId!=newLayerId)) |
640 | 37.2k | layerId=-1; |
641 | 14.9k | else |
642 | 14.9k | layerId=newLayerId; |
643 | 52.1k | first=false; |
644 | 52.1k | } |
645 | 4.49k | shape.m_layerId=layerId; |
646 | 4.49k | seen.erase(zId); |
647 | 4.49k | return layerId; |
648 | 22.8k | } |
649 | | |
650 | | //////////////////////////////////////// |
651 | | //! Internal: the subdocument of a FreeHandParser |
652 | | class SubDocument final : public MWAWSubDocument |
653 | | { |
654 | | public: |
655 | | SubDocument(FreeHandParser &pars, MWAWInputStreamPtr const &input, int zoneId) |
656 | 2.91k | : MWAWSubDocument(&pars, input, MWAWEntry()) |
657 | 2.91k | , m_id(zoneId) {} |
658 | | |
659 | | //! destructor |
660 | 0 | ~SubDocument() final {} |
661 | | |
662 | | //! operator!= |
663 | | bool operator!=(MWAWSubDocument const &doc) const final |
664 | 0 | { |
665 | 0 | if (MWAWSubDocument::operator!=(doc)) return true; |
666 | 0 | auto const *sDoc = dynamic_cast<SubDocument const *>(&doc); |
667 | 0 | if (!sDoc) return true; |
668 | 0 | if (m_id != sDoc->m_id) return true; |
669 | 0 | return false; |
670 | 0 | } |
671 | | |
672 | | //! the parser function |
673 | | void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final; |
674 | | |
675 | | protected: |
676 | | //! the subdocument id |
677 | | int m_id; |
678 | | private: |
679 | | SubDocument(SubDocument const &orig); |
680 | | SubDocument &operator=(SubDocument const &orig); |
681 | | }; |
682 | | |
683 | | void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType) |
684 | 2.91k | { |
685 | 2.91k | if (!listener || !listener->canWriteText()) { |
686 | 0 | MWAW_DEBUG_MSG(("FreeHandParserInternal::SubDocument::parse: no listener\n")); |
687 | 0 | return; |
688 | 0 | } |
689 | 2.91k | auto *parser=dynamic_cast<FreeHandParser *>(m_parser); |
690 | 2.91k | if (!parser) { |
691 | 0 | MWAW_DEBUG_MSG(("FreeHandParserInternal::SubDocument::parse: no parser\n")); |
692 | 0 | return; |
693 | 0 | } |
694 | 2.91k | long pos = m_input->tell(); |
695 | 2.91k | parser->sendText(m_id); |
696 | 2.91k | m_input->seek(pos, librevenge::RVNG_SEEK_SET); |
697 | 2.91k | } |
698 | | |
699 | | } |
700 | | |
701 | | //////////////////////////////////////////////////////////// |
702 | | // constructor/destructor, ... |
703 | | //////////////////////////////////////////////////////////// |
704 | | FreeHandParser::FreeHandParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header) |
705 | 62.7k | : MWAWGraphicParser(input, rsrcParser, header) |
706 | 62.7k | , m_state() |
707 | 62.7k | { |
708 | 62.7k | init(); |
709 | 62.7k | } |
710 | | |
711 | | FreeHandParser::~FreeHandParser() |
712 | 62.7k | { |
713 | 62.7k | } |
714 | | |
715 | | void FreeHandParser::init() |
716 | 62.7k | { |
717 | 62.7k | resetGraphicListener(); |
718 | 62.7k | setAsciiName("main-1"); |
719 | | |
720 | 62.7k | m_state.reset(new FreeHandParserInternal::State); |
721 | | |
722 | 62.7k | getPageSpan().setMargins(0.1); |
723 | 62.7k | } |
724 | | |
725 | | //////////////////////////////////////////////////////////// |
726 | | // the parser |
727 | | //////////////////////////////////////////////////////////// |
728 | | void FreeHandParser::parse(librevenge::RVNGDrawingInterface *docInterface) |
729 | 21.8k | { |
730 | 21.8k | if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException()); |
731 | 21.8k | bool ok = false; |
732 | 21.8k | try { |
733 | | // create the asciiFile |
734 | 21.8k | ascii().setStream(getInput()); |
735 | 21.8k | ascii().open(asciiName()); |
736 | 21.8k | checkHeader(nullptr); |
737 | 21.8k | ok = createZones(); |
738 | 21.8k | if (ok) { |
739 | 6.69k | createDocument(docInterface); |
740 | 6.69k | sendZone(m_state->m_mainGroupId, m_state->m_transform); |
741 | | #ifdef DEBUG |
742 | | flushExtra(); |
743 | | #endif |
744 | 6.69k | } |
745 | 21.8k | ascii().reset(); |
746 | 21.8k | } |
747 | 21.8k | catch (...) { |
748 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::parse: exception catched when parsing\n")); |
749 | 0 | ok = false; |
750 | 0 | } |
751 | | |
752 | 21.8k | resetGraphicListener(); |
753 | 21.8k | if (!ok) throw(libmwaw::ParseException()); |
754 | 21.8k | } |
755 | | |
756 | | //////////////////////////////////////////////////////////// |
757 | | // create the document |
758 | | //////////////////////////////////////////////////////////// |
759 | | void FreeHandParser::createDocument(librevenge::RVNGDrawingInterface *documentInterface) |
760 | 6.69k | { |
761 | 6.69k | if (!documentInterface) return; |
762 | 6.69k | if (getGraphicListener()) { |
763 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::createDocument: listener already exist\n")); |
764 | 0 | return; |
765 | 0 | } |
766 | | |
767 | | // create the page list |
768 | 6.69k | MWAWPageSpan ps(getPageSpan()); |
769 | 6.69k | ps.setPageSpan(1); |
770 | 6.69k | std::vector<MWAWPageSpan> pageList(1,ps); |
771 | 6.69k | MWAWGraphicListenerPtr listen(new MWAWGraphicListener(*getParserState(), pageList, documentInterface)); |
772 | 6.69k | setGraphicListener(listen); |
773 | 6.69k | listen->startDocument(); |
774 | 6.69k | } |
775 | | |
776 | | //////////////////////////////////////////////////////////// |
777 | | // |
778 | | // Intermediate level |
779 | | // |
780 | | //////////////////////////////////////////////////////////// |
781 | | bool FreeHandParser::createZones() |
782 | 21.8k | { |
783 | 21.8k | MWAWInputStreamPtr input = getInput(); |
784 | 21.8k | long pos; |
785 | 21.8k | libmwaw::DebugStream f; |
786 | 21.8k | bool readSome=false; |
787 | 21.8k | int zId=1; |
788 | 21.8k | int const vers=version(); |
789 | 21.8k | if (vers==2) { |
790 | 6.21k | pos=input->tell(); |
791 | 6.21k | libmwaw::PrinterInfo info; |
792 | 6.21k | if (!info.read(input)) { |
793 | 5.93k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
794 | 5.93k | if (input->readULong(4)==0) { // null print info is ok |
795 | 1.86k | ascii().addPos(pos); |
796 | 1.86k | ascii().addNote("_"); |
797 | 1.86k | input->seek(pos+0x78, librevenge::RVNG_SEEK_SET); |
798 | 1.86k | } |
799 | 4.06k | else |
800 | 4.06k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
801 | 5.93k | } |
802 | 287 | else { |
803 | 287 | f.str(""); |
804 | 287 | f << "Entries(PrintInfo):" << info; |
805 | 287 | ascii().addPos(pos); |
806 | 287 | ascii().addNote(f.str().c_str()); |
807 | 287 | } |
808 | 6.21k | } |
809 | 482k | while (!input->isEnd()) { |
810 | 481k | pos=input->tell(); |
811 | 618k | while ((vers==1 && readZoneV1(zId)) || (vers==2 && readZoneV2(zId))) { |
812 | 136k | readSome=true; |
813 | 136k | pos=input->tell(); |
814 | 136k | if (zId) ++zId; |
815 | 136k | } |
816 | 481k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
817 | 481k | if (!input->checkPosition(pos+5)) |
818 | 1.27k | break; |
819 | | // ok try to continue |
820 | 480k | bool ok=true; |
821 | 480k | zId=0; |
822 | 45.7M | while (!input->isEnd()) { |
823 | 45.7M | auto val=static_cast<unsigned long>(input->readULong(4)); |
824 | 45.7M | if (input->isEnd()) { |
825 | 19.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
826 | 19.9k | ok=false; |
827 | 19.9k | break; |
828 | 19.9k | } |
829 | 45.6M | if (!val || (val&0xFF00)) { |
830 | 35.8M | input->seek(-1, librevenge::RVNG_SEEK_CUR); |
831 | 35.8M | continue; |
832 | 35.8M | } |
833 | 9.83M | if (val&0xFF0000) { |
834 | 4.39M | input->seek(-2, librevenge::RVNG_SEEK_CUR); |
835 | 4.39M | continue; |
836 | 4.39M | } |
837 | 5.43M | if (val&0xFF000000) { |
838 | 1.70M | input->seek(-3, librevenge::RVNG_SEEK_CUR); |
839 | 1.70M | continue; |
840 | 1.70M | } |
841 | 3.73M | input->seek(-4, librevenge::RVNG_SEEK_CUR); |
842 | 3.73M | long actPos=input->tell(); |
843 | 3.73M | if ((vers==1 && readZoneV1(zId)) || (vers==2 && readZoneV2(zId))) { |
844 | 460k | if (pos!=actPos) { |
845 | 460k | MWAW_DEBUG_MSG(("FreeHandParser::createZones: find some unexpected data\n")); |
846 | 460k | ascii().addPos(pos); |
847 | 460k | ascii().addNote("Entries(Unknown):###"); |
848 | 460k | } |
849 | 460k | break; |
850 | 460k | } |
851 | 3.27M | input->seek(actPos+4, librevenge::RVNG_SEEK_SET); |
852 | 3.27M | } |
853 | 480k | if (!ok) break; |
854 | 480k | } |
855 | 21.8k | pos=input->tell(); |
856 | 21.8k | f.str(""); |
857 | 21.8k | f << "Entries(End):"; |
858 | 21.8k | if (input->readLong(4)!=-1) { |
859 | 21.1k | MWAW_DEBUG_MSG(("FreeHandParser::createZones: find unexpected end data\n")); |
860 | 21.1k | f << "###"; |
861 | 21.1k | } |
862 | 21.8k | if (readSome && m_state->m_mainGroupId) { |
863 | 3.08k | std::set<int> seen; |
864 | 3.08k | m_state->updateGroupLayerId(m_state->m_mainGroupId, seen); |
865 | 3.08k | } |
866 | 21.8k | ascii().addPos(pos); |
867 | 21.8k | ascii().addNote(f.str().c_str()); |
868 | 21.8k | return readSome; |
869 | 21.8k | } |
870 | | |
871 | | bool FreeHandParser::readZoneV1(int zId) |
872 | 2.58M | { |
873 | 2.58M | MWAWInputStreamPtr input = getInput(); |
874 | 2.58M | long pos=input->tell(); |
875 | 2.58M | if (!input->checkPosition(pos+5)) |
876 | 965 | return false; |
877 | 2.58M | auto val=static_cast<int>(input->readULong(4)); |
878 | 2.58M | if (val < 0 || (static_cast<unsigned long>(val)&0xFF000000)) { |
879 | 167k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
880 | 167k | return false; |
881 | 167k | } |
882 | 2.41M | auto type=static_cast<int>(input->readULong(2)); |
883 | 2.41M | input->seek(pos, librevenge::RVNG_SEEK_SET); |
884 | 2.41M | switch (type) { |
885 | | // does type=1 exist ? |
886 | 53.0k | case 2: |
887 | 53.0k | return readStyleGroup(zId); |
888 | 66.5k | case 3: |
889 | 66.5k | return readStringZone(zId); |
890 | | |
891 | | // 4001-4002 |
892 | 5.00k | case 0xfa1: |
893 | 5.00k | return readRootGroup(zId); |
894 | 67.8k | case 0xfa2: |
895 | 67.8k | return readGroupV1(zId); |
896 | | |
897 | | // 4101-4104 |
898 | 10.7k | case 0x1005: |
899 | 10.7k | return readTransformGroup(zId); |
900 | 95.9k | case 0x1006: |
901 | 95.9k | return readTextboxV1(zId); |
902 | 48.5k | case 0x1007: |
903 | 48.5k | return readBackgroundPicture(zId); |
904 | 12.0k | case 0x1008: |
905 | 12.0k | return readJoinGroup(zId); |
906 | | |
907 | | // 4202-4204 |
908 | | // does type=0x1069 exist ? |
909 | 7.56k | case 0x106a: |
910 | 50.4k | case 0x106b: |
911 | 56.2k | case 0x106c: |
912 | 56.2k | return readColor(zId); |
913 | | |
914 | | // 4301-4305 |
915 | 18.9k | case 0x10cd: |
916 | 18.9k | return readFillStyle(zId); |
917 | 114k | case 0x10ce: |
918 | 114k | return readLineStyle(zId); |
919 | 69.3k | case 0x10cf: |
920 | 69.3k | return readPostscriptStyle(zId); |
921 | 17.5k | case 0x10d0: |
922 | 46.5k | case 0x10d1: |
923 | 46.5k | return readFillStyle(zId); |
924 | | |
925 | | // 4401-4405 |
926 | 20.6k | case 0x1131: // rectangle |
927 | 71.6k | case 0x1132: // ellipse |
928 | | // does type=0x1133 exist ? |
929 | 95.8k | case 0x1134: // spline |
930 | 106k | case 0x1135: // line |
931 | 106k | return readShape(zId); |
932 | | |
933 | | // 4501 |
934 | 44.3k | case 0x1195: |
935 | 44.3k | return readDash(zId); |
936 | 1.60M | default: |
937 | 1.60M | break; |
938 | 2.41M | } |
939 | 1.60M | input->seek(pos, librevenge::RVNG_SEEK_SET); |
940 | 1.60M | return false; |
941 | 2.41M | } |
942 | | |
943 | | bool FreeHandParser::readZoneV2(int zId) |
944 | 1.76M | { |
945 | 1.76M | MWAWInputStreamPtr input = getInput(); |
946 | 1.76M | long pos=input->tell(); |
947 | 1.76M | if (!input->checkPosition(pos+5)) |
948 | 308 | return false; |
949 | 1.76M | auto val=static_cast<int>(input->readULong(4)); |
950 | 1.76M | if (val < 0 || (static_cast<unsigned long>(val)&0xFF000000)) { |
951 | 116k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
952 | 116k | return false; |
953 | 116k | } |
954 | 1.64M | auto type=static_cast<int>(input->readULong(2)); |
955 | 1.64M | input->seek(pos, librevenge::RVNG_SEEK_SET); |
956 | 1.64M | switch (type) { |
957 | 39.6k | case 5: // style group |
958 | 39.6k | return readStyleGroup(zId); |
959 | 16.3k | case 6: |
960 | 16.3k | return readStringZone(zId); |
961 | 2.88k | case 0x1389: |
962 | 2.88k | return readRootGroup(zId); |
963 | 24.9k | case 0x138a: |
964 | 24.9k | return readGroupV2(zId); |
965 | 5.65k | case 0x138b: |
966 | 5.65k | return readDataZone(zId); |
967 | 8.26k | case 0x13ed: |
968 | 8.26k | return readTransformGroup(zId); |
969 | 76.0k | case 0x13ee: |
970 | 76.0k | return readTextboxV2(zId); |
971 | 2.92k | case 0x13f0: |
972 | 2.92k | return readJoinGroup(zId); |
973 | 117k | case 0x13f8: |
974 | 117k | return readPictureZone(zId); |
975 | 4.85k | case 0x1452: // basic |
976 | 7.29k | case 0x1453: // tint |
977 | 17.0k | case 0x1454: // cmyk |
978 | 20.4k | case 0x1455: // pantome ? |
979 | 20.4k | return readColor(zId); |
980 | 4.90k | case 0x14b5: // basic |
981 | 4.90k | return readFillStyle(zId); |
982 | 4.46k | case 0x14b6: // line style |
983 | 4.46k | return readLineStyle(zId); |
984 | 6.19k | case 0x14b7: // gradient linear |
985 | 8.48k | case 0x14b8: // radial |
986 | 8.48k | return readFillStyle(zId); |
987 | 2.58k | case 0x14c9: // line, always follow 14d3 |
988 | 5.12k | case 0x14ca: // surf, always follow 14d4 |
989 | 5.12k | return readPostscriptStyle(zId); |
990 | 4.24k | case 0x14d3: // pattern |
991 | 4.24k | return readFillStyle(zId); |
992 | 1.29k | case 0x14d4: // pattern line style |
993 | 1.29k | return readLineStyle(zId); |
994 | 2.56k | case 0x14dd: // tile style |
995 | 2.56k | return readFillStyle(zId); |
996 | 9.83k | case 0x1519: // rectangle |
997 | 14.6k | case 0x151a: // ellipse |
998 | 14.6k | return readShape(zId); |
999 | 31.5k | case 0x151c: |
1000 | 31.5k | return readShape(zId); |
1001 | 7.86k | case 0x151d: // line |
1002 | 7.86k | return readShape(zId); |
1003 | 10.4k | case 0x157d: |
1004 | 10.4k | return readDash(zId); |
1005 | 1.23M | default: |
1006 | 1.23M | break; |
1007 | 1.64M | } |
1008 | 1.23M | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1009 | 1.23M | return false; |
1010 | 1.64M | } |
1011 | | |
1012 | | //////////////////////////////////////////////////////////// |
1013 | | // read the header |
1014 | | //////////////////////////////////////////////////////////// |
1015 | | bool FreeHandParser::checkHeader(MWAWHeader *header, bool strict) |
1016 | 84.5k | { |
1017 | 84.5k | *m_state = FreeHandParserInternal::State(); |
1018 | 84.5k | MWAWInputStreamPtr input = getInput(); |
1019 | 84.5k | if (!input || !input->hasDataFork() || !input->checkPosition(128)) |
1020 | 250 | return false; |
1021 | | |
1022 | 84.2k | libmwaw::DebugStream f; |
1023 | 84.2k | f << "FileHeader:"; |
1024 | 84.2k | input->seek(0, librevenge::RVNG_SEEK_SET); |
1025 | 84.2k | auto signature=long(input->readULong(4)); |
1026 | 84.2k | int vers=1, val; |
1027 | 84.2k | if (signature==0x61636633) { |
1028 | 59.6k | val=static_cast<int>(input->readULong(2)); // the subversion? |
1029 | 59.6k | if (strict && val>=9) return false; |
1030 | 59.5k | if (val!=5) |
1031 | 53.5k | f << "f0=" << val << ","; |
1032 | 59.5k | } |
1033 | 24.6k | else if (signature==0x46484432) { |
1034 | 24.3k | if (!input->checkPosition(256)) |
1035 | 66 | return false; |
1036 | 24.2k | vers=2; |
1037 | 24.2k | val=static_cast<int>(input->readULong(2)); // the subversion? |
1038 | 24.2k | if (strict && val>20) return false; |
1039 | 24.1k | if (val!=9) |
1040 | 19.4k | f << "f0=" << val << ","; |
1041 | 24.1k | } |
1042 | 316 | else |
1043 | 316 | return false; |
1044 | 83.7k | val=static_cast<int>(input->readULong(2)); |
1045 | 83.7k | if (val!=100) f << "f1=" << val << ","; |
1046 | 83.7k | float dim[8]; |
1047 | 669k | for (auto &d : dim) d=float(input->readLong(2))/10.f; |
1048 | 83.7k | f << "page[sz]=" << MWAWVec2f(dim[0],dim[1]) << ","; |
1049 | 83.7k | f << "paper[sz]=" << MWAWVec2f(dim[2],dim[3]) << ","; |
1050 | 83.7k | if (dim[4]>0 || dim[5]>0) |
1051 | 52.3k | f << "unkn[sz]=" << MWAWVec2f(dim[4],dim[5]) << ","; |
1052 | 83.7k | f << "margins=" << MWAWVec2f(dim[6],dim[7]) << ","; |
1053 | 83.7k | if (vers>1) { |
1054 | 24.1k | ascii().addDelimiter(input->tell(),'|'); |
1055 | 24.1k | input->seek(30, librevenge::RVNG_SEEK_CUR); |
1056 | 96.5k | for (int i=0; i<3; ++i) { |
1057 | 72.4k | val=static_cast<int>(input->readULong(2)); |
1058 | 72.4k | if (!val) continue; |
1059 | | // checkme: odd |
1060 | 44.0k | if (i==0 && (val&0x20) && dim[0]>dim[1]) { |
1061 | 1.90k | f << "landscape,"; |
1062 | 1.90k | getPageSpan().setFormOrientation(MWAWPageSpan::LANDSCAPE); |
1063 | 9.53k | for (int j=0; j<4; ++j) { |
1064 | 7.62k | if (j==1) continue; |
1065 | 5.71k | std::swap(dim[2*j],dim[2*j+1]); |
1066 | 5.71k | } |
1067 | 1.90k | val &= 0xFFDF; |
1068 | 1.90k | } |
1069 | 44.0k | if (val) |
1070 | 44.0k | f << i+2 << "=" << std::hex << val << std::dec << ","; |
1071 | 44.0k | } |
1072 | 24.1k | } |
1073 | 59.5k | else { |
1074 | 178k | for (int i=0; i<2; ++i) { // f2=1|2|a |
1075 | 119k | val=static_cast<int>(input->readULong(2)); |
1076 | 119k | if (!val) continue; |
1077 | 84.4k | if (i==1) { |
1078 | 39.8k | if (val&1) { |
1079 | 19.9k | f << "landscape,"; |
1080 | 19.9k | getPageSpan().setFormOrientation(MWAWPageSpan::LANDSCAPE); |
1081 | 99.8k | for (int j=0; j<4; ++j) |
1082 | 79.9k | std::swap(dim[2*j],dim[2*j+1]); |
1083 | 19.9k | } |
1084 | 39.8k | if (val&2) f << "crop[mark],"; |
1085 | 39.8k | if (val&4) f << "center[mark],"; |
1086 | 39.8k | if (val&8) f << "separation[name],"; |
1087 | 39.8k | if (val&0x10) f << "file[name&date],"; |
1088 | 39.8k | if (val&0x40) f << "include[processColor],"; |
1089 | 39.8k | if (val&0x80) f << "display[quality]=better,"; |
1090 | 39.8k | if (val&0x100) f << "print[quality]=better,"; |
1091 | 39.8k | val &= 0xFE20; |
1092 | 39.8k | } |
1093 | 84.4k | if (val) |
1094 | 80.2k | f << "f" << i+2 << "=" << std::hex << val << std::dec << ","; |
1095 | 84.4k | } |
1096 | 59.5k | } |
1097 | 83.7k | if (dim[2]>0 && dim[3]>0) { |
1098 | 42.9k | getPageSpan().setFormLength(double(dim[2])/72.); |
1099 | 42.9k | getPageSpan().setFormWidth(double(dim[3])/72.); |
1100 | 42.9k | if (dim[0]+dim[6]<=dim[2]) { |
1101 | 29.6k | getPageSpan().setMarginBottom(double(dim[6])/72.0); |
1102 | 29.6k | getPageSpan().setMarginTop(double(dim[2]-dim[0]-dim[6])/72.0); |
1103 | 29.6k | } |
1104 | 13.2k | else { |
1105 | 13.2k | MWAW_DEBUG_MSG(("FreeHandParser::checkHeader: the vertical margins seems bad\n")); |
1106 | 13.2k | if (dim[0]<=dim[2]) { |
1107 | 9.22k | getPageSpan().setMarginBottom(double(dim[2]-dim[0])/2.0/72.0); |
1108 | 9.22k | getPageSpan().setMarginTop(double(dim[2]-dim[0])/2.0/72.0); |
1109 | 9.22k | } |
1110 | 13.2k | } |
1111 | 42.9k | if (dim[1]+dim[7]<=dim[3]) { |
1112 | 29.7k | getPageSpan().setMarginRight(double(dim[7])/72.0); |
1113 | 29.7k | getPageSpan().setMarginLeft(double(dim[3]-dim[1]-dim[7])/72.0); |
1114 | 29.7k | } |
1115 | 13.1k | else { |
1116 | 13.1k | MWAW_DEBUG_MSG(("FreeHandParser::checkHeader: the horizontal margins seems bad\n")); |
1117 | 13.1k | if (dim[1]<=dim[3]) { |
1118 | 8.20k | getPageSpan().setMarginLeft(double(dim[3]-dim[1])/2.0/72.0); |
1119 | 8.20k | getPageSpan().setMarginRight(double(dim[3]-dim[1])/2.0/72.0); |
1120 | 8.20k | } |
1121 | 13.1k | } |
1122 | 42.9k | } |
1123 | 40.7k | else { |
1124 | 40.7k | if (strict) |
1125 | 10.1k | return false; |
1126 | 30.6k | MWAW_DEBUG_MSG(("FreeHandParser::checkHeader: the paper size seems bad\n")); |
1127 | 30.6k | } |
1128 | | // transform orig from page content LeftBot -> origin form page LeftTop |
1129 | 73.5k | m_state->m_transform= |
1130 | 73.5k | MWAWTransformation::translation(72.f *MWAWVec2f(float(getPageSpan().getMarginLeft()),float(getPageSpan().getPageLength()+getPageSpan().getMarginTop()))) * |
1131 | 73.5k | MWAWTransformation::scale(MWAWVec2f(1, -1)); |
1132 | 73.5k | if (vers==1) { |
1133 | 52.7k | val=static_cast<int>(input->readULong(4)); |
1134 | 52.7k | switch ((val>>29)) { |
1135 | 33.4k | case 0: // point |
1136 | 33.4k | break; |
1137 | 5.51k | case 1: |
1138 | 5.51k | f << "unit=picas,"; |
1139 | 5.51k | break; |
1140 | 4.17k | case 2: |
1141 | 4.17k | f << "unit=inches,"; |
1142 | 4.17k | break; |
1143 | 1.67k | case 3: |
1144 | 1.67k | f << "unit=decimal[inches],"; |
1145 | 1.67k | break; |
1146 | 0 | case 4: |
1147 | 0 | f << "unit=millimeters,"; |
1148 | 0 | break; |
1149 | 7.87k | default: |
1150 | 7.87k | MWAW_DEBUG_MSG(("FreeHandParser::checkHeader: find unknown unit\n")); |
1151 | 7.87k | f << "##units=" << ((val>>29)&7) << ","; |
1152 | 52.7k | } |
1153 | 52.7k | val &= 0x1FFF; |
1154 | 52.7k | if (val) f << "grid[size]=" << float(val)/65536.f/10.f << ","; |
1155 | 263k | for (int i=0; i<4; ++i) { // f4=0|200 |
1156 | 210k | val=static_cast<int>(input->readULong(2)); |
1157 | 210k | if (val) |
1158 | 135k | f << "f" << i+4 << "=" << std::hex << val << std::dec << ","; |
1159 | 210k | } |
1160 | 52.7k | } |
1161 | | |
1162 | 215k | for (int i=0; i<2; ++i) { |
1163 | | // checkme no sure what are limit |
1164 | 145k | long actPos=input->tell(); |
1165 | 145k | auto sSz=static_cast<int>(input->readULong(1)); |
1166 | 145k | if (sSz>31) { |
1167 | 39.0k | if (strict) return false; |
1168 | 35.7k | MWAW_DEBUG_MSG(("FreeHandParser::checkHeader: string size %d seems bad\n", i)); |
1169 | 35.7k | f << "##sSz,"; |
1170 | 35.7k | sSz=0; |
1171 | 35.7k | } |
1172 | 141k | std::string name; |
1173 | 562k | for (int s=0; s<sSz; ++s) name+=char(input->readULong(1)); |
1174 | 141k | if (!name.empty()) { |
1175 | 46.3k | char const *wh[]= {"printer", "paper"}; |
1176 | 46.3k | f << wh[i] << "=" << name << ","; |
1177 | 46.3k | } |
1178 | 141k | input->seek(actPos+32, librevenge::RVNG_SEEK_SET); |
1179 | 141k | } |
1180 | 70.2k | if (vers==1) { |
1181 | 300k | for (int i=0; i<5; ++i) { // g0=0|41, g1=0|3-7, g3=0|20, g4=0|b4 |
1182 | 250k | val=static_cast<int>(input->readULong(2)); |
1183 | 250k | if (val) |
1184 | 169k | f << "g" << i << "=" << std::hex << val << std::dec << ","; |
1185 | 250k | } |
1186 | | // big number |
1187 | 50.1k | f << "unkn=" << std::hex << input->readULong(4) << std::dec << ","; |
1188 | 300k | for (int i=0; i<5; ++i) { // always 0 |
1189 | 250k | val=static_cast<int>(input->readULong(2)); |
1190 | 250k | if (val) |
1191 | 158k | f << "h" << i << "=" << val << ","; |
1192 | 250k | } |
1193 | 50.1k | } |
1194 | 20.0k | else { |
1195 | 20.0k | ascii().addDelimiter(input->tell(),'|'); |
1196 | 20.0k | f << "unkn=" << std::hex << input->readULong(4) << std::dec << ","; |
1197 | | // always 0 |
1198 | 1.30M | for (int i=0; i<64; ++i) { |
1199 | 1.28M | val=static_cast<int>(input->readULong(2)); |
1200 | 1.28M | if (val) |
1201 | 712k | f << "h" << i << "=" << val << ","; |
1202 | 1.28M | } |
1203 | | // check for printer info or null printer info |
1204 | 20.0k | if (strict) { |
1205 | 2.84k | libmwaw::PrinterInfo info; |
1206 | 2.84k | if (!info.read(input)) { |
1207 | 2.60k | input->seek(256, librevenge::RVNG_SEEK_SET); |
1208 | 2.60k | if (input->readULong(4)) |
1209 | 550 | return false; |
1210 | 2.60k | } |
1211 | 2.84k | } |
1212 | 20.0k | } |
1213 | 69.6k | ascii().addPos(0); |
1214 | 69.6k | ascii().addNote(f.str().c_str()); |
1215 | 69.6k | setVersion(vers); |
1216 | 69.6k | if (header) |
1217 | 26.0k | header->reset(MWAWDocument::MWAW_T_FREEHAND, vers, MWAWDocument::MWAW_K_DRAW); |
1218 | 69.6k | input->seek(vers==1 ? 128 : 256, librevenge::RVNG_SEEK_SET); |
1219 | | |
1220 | 69.6k | return true; |
1221 | 70.2k | } |
1222 | | |
1223 | | //////////////////////////////////////////////////////////// |
1224 | | // try to read the zone |
1225 | | //////////////////////////////////////////////////////////// |
1226 | | bool FreeHandParser::readRootGroup(int zId) |
1227 | 7.88k | { |
1228 | 7.88k | if ((zId && zId!=1) || !m_state->m_zIdToTypeMap.empty()) |
1229 | 3.26k | return false; |
1230 | 4.62k | MWAWInputStreamPtr input = getInput(); |
1231 | 4.62k | libmwaw::DebugStream f; |
1232 | | |
1233 | 4.62k | long pos=input->tell(); |
1234 | 4.62k | int const vers=version(); |
1235 | 4.62k | if (!input->checkPosition(pos+(vers==1 ? 24 : 34))) |
1236 | 40 | return false; |
1237 | 4.58k | f.str(""); |
1238 | 4.58k | f << "Entries(Root):"; |
1239 | 4.58k | auto dSz=static_cast<int>(input->readULong(4)); // probably related to size |
1240 | 4.58k | auto opCode=static_cast<int>(input->readULong(2)); |
1241 | 4.58k | if ((vers==1 && opCode !=0xfa1) || (vers>1 && opCode != 0x1389)) |
1242 | 0 | return false; |
1243 | 4.58k | if (vers>1) dSz-=4; |
1244 | 4.58k | if (dSz!=0x34) { |
1245 | 1.50k | MWAW_DEBUG_MSG(("FreeHandParser::readRootGroup: find unexpected zone size\n")); |
1246 | 1.50k | f << "#sz?=" << dSz << ","; |
1247 | 1.50k | } |
1248 | 4.58k | if (vers==1) { |
1249 | 9.04k | for (int i=0; i<2; ++i) { // always 0 ? |
1250 | 6.03k | auto val=static_cast<int>(input->readLong(2)); |
1251 | 6.03k | if (!val) continue; |
1252 | 1.24k | MWAW_DEBUG_MSG(("FreeHandParser::readRootGroup: find unknown zone %d\n", i)); |
1253 | 1.24k | f << "#f" << i << "=" << val << ","; |
1254 | 1.24k | } |
1255 | 3.01k | } |
1256 | 4.58k | auto id=static_cast<int>(input->readLong(2)); |
1257 | 4.58k | if (id) { |
1258 | 3.28k | m_state->m_mainGroupId=id; |
1259 | 3.28k | m_state->addZoneId(id, FreeHandParserInternal::Z_Group); |
1260 | 3.28k | f << "main=Z" << id << ","; |
1261 | 3.28k | } |
1262 | 4.58k | if (vers==1) { |
1263 | 21.1k | for (int i=0; i<6; ++i) { |
1264 | 18.0k | id=static_cast<int>(input->readLong(2)); |
1265 | 18.0k | if (!id) continue; |
1266 | | // the first group is a style group, but I never find any child, so... |
1267 | 7.85k | FreeHandParserInternal::ZoneType type[6]= { |
1268 | 7.85k | FreeHandParserInternal::Z_StyleGroup, FreeHandParserInternal::Z_FillGroup, FreeHandParserInternal::Z_LineStyleGroup, |
1269 | 7.85k | FreeHandParserInternal::Z_ColorGroup, FreeHandParserInternal::Z_DashGroup, FreeHandParserInternal::Z_ColorGroup |
1270 | 7.85k | }; |
1271 | 7.85k | if (!m_state->addZoneId(id, type[i])) { |
1272 | 165 | MWAW_DEBUG_MSG(("FreeHandParser::readRootGroup: find dupplicated id\n")); |
1273 | 165 | f << "###"; |
1274 | 165 | } |
1275 | 7.85k | char const *wh[6]= { "groupStyle0", "fillStyle", "lineStyle", "colStyle", "dashStyle", "colStyle2" }; |
1276 | 7.85k | f << wh[i] << "=Z" << id << ","; |
1277 | 7.85k | } |
1278 | 3.01k | } |
1279 | 1.57k | else { |
1280 | | // at least 8, maybe more |
1281 | 14.1k | for (int i=0; i<8; ++i) { |
1282 | 12.5k | id=static_cast<int>(input->readLong(2)); |
1283 | 12.5k | if (!id) continue; |
1284 | 10.3k | FreeHandParserInternal::ZoneType type[8]= { |
1285 | 10.3k | FreeHandParserInternal::Z_ColorGroup, FreeHandParserInternal::Z_FillGroup, FreeHandParserInternal::Z_LineStyleGroup, |
1286 | 10.3k | FreeHandParserInternal::Z_StyleGroup, FreeHandParserInternal::Z_FillGroup, FreeHandParserInternal::Z_LineStyleGroup, |
1287 | 10.3k | FreeHandParserInternal::Z_DashGroup, FreeHandParserInternal::Z_ColorGroup, |
1288 | 10.3k | }; |
1289 | 10.3k | if (!m_state->addZoneId(id, type[i])) { |
1290 | 284 | MWAW_DEBUG_MSG(("FreeHandParser::readRootGroup: find dupplicated id\n")); |
1291 | 284 | f << "###"; |
1292 | 284 | } |
1293 | 10.3k | char const *wh[8]= { "colStyle", "fillStyle", "lineStyle", "groupStyle3", "fillStyle[unamed]", "lineStyle[unamed]", "dashStyle", "colStyle2"}; |
1294 | 10.3k | f << wh[i] << "=Z" << id << ","; |
1295 | 10.3k | } |
1296 | 9.43k | for (int i=0; i<5; ++i) { |
1297 | 7.86k | auto val=static_cast<int>(input->readULong(2)); |
1298 | 7.86k | if (!val) continue; |
1299 | 751 | MWAW_DEBUG_MSG(("FreeHandParser::readRootGroup: find unknown group id\n")); |
1300 | 751 | f << "###Z" << val << ","; |
1301 | 751 | } |
1302 | 1.57k | } |
1303 | 4.58k | ascii().addPos(pos); |
1304 | 4.58k | ascii().addNote(f.str().c_str()); |
1305 | | |
1306 | 4.58k | return true; |
1307 | 4.58k | } |
1308 | | |
1309 | | bool FreeHandParser::readGroupV1(int zId) |
1310 | 67.8k | { |
1311 | 67.8k | MWAWInputStreamPtr input = getInput(); |
1312 | 67.8k | libmwaw::DebugStream f; |
1313 | | |
1314 | 67.8k | long pos=input->tell(); |
1315 | 67.8k | if (!input->checkPosition(pos+20)) |
1316 | 631 | return false; |
1317 | 67.2k | f.str(""); |
1318 | 67.2k | if (zId) |
1319 | 2.11k | f << "Entries(Group)[Z" << zId << "]:"; |
1320 | 65.0k | else |
1321 | 65.0k | f << "Entries(Group):"; |
1322 | 67.2k | if (zId) { |
1323 | 2.11k | auto type=m_state->getZoneType(zId); |
1324 | 2.11k | if (type!=FreeHandParserInternal::Z_Group && type!=FreeHandParserInternal::Z_Shape) { |
1325 | 252 | MWAW_DEBUG_MSG(("FreeHandParser::readGroupV1: find unexpected zone type for zone %d\n", zId)); |
1326 | 252 | } |
1327 | 2.11k | } |
1328 | | |
1329 | 67.2k | auto dSz=static_cast<int>(input->readULong(4)); // probably related to size |
1330 | 67.2k | f << "sz=" << dSz << ","; |
1331 | 67.2k | if (input->readULong(2)!=0xfa2) { |
1332 | 0 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1333 | 0 | return false; |
1334 | 0 | } |
1335 | 67.2k | FreeHandParserInternal::Shape res; |
1336 | 67.2k | res.m_id=zId; |
1337 | 67.2k | res.m_type=FreeHandParserInternal::Shape::Group; |
1338 | 67.2k | ascii().addDelimiter(input->tell(),'|'); |
1339 | 67.2k | input->seek(pos+18, librevenge::RVNG_SEEK_SET); |
1340 | 67.2k | ascii().addDelimiter(input->tell(),'|'); |
1341 | 67.2k | auto N=static_cast<int>(input->readULong(2)); |
1342 | 67.2k | if (!input->checkPosition(pos+20+2*N)) { |
1343 | 23.3k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1344 | 23.3k | return false; |
1345 | 23.3k | } |
1346 | 43.8k | f << "childs=["; |
1347 | 1.32M | for (int i=0; i<N; ++i) { |
1348 | 1.30M | auto id=static_cast<int>(input->readULong(2)); |
1349 | 1.30M | if (!m_state->addZoneId(id, FreeHandParserInternal::Z_Shape)) { |
1350 | 22.6k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1351 | 22.6k | return false; |
1352 | 22.6k | } |
1353 | 1.28M | res.m_childs.push_back(id); |
1354 | 1.28M | f << "Z" << id << ","; |
1355 | 1.28M | } |
1356 | 21.2k | f <<"],"; |
1357 | 21.2k | ascii().addPos(pos); |
1358 | 21.2k | ascii().addNote(f.str().c_str()); |
1359 | 21.2k | if (zId && m_state->m_zIdToShapeMap.find(zId)==m_state->m_zIdToShapeMap.end()) |
1360 | 2.03k | m_state->m_zIdToShapeMap.insert(std::map<int, FreeHandParserInternal::Shape>::value_type(zId,res)); |
1361 | 21.2k | return true; |
1362 | 43.8k | } |
1363 | | |
1364 | | bool FreeHandParser::readGroupV2(int zId) |
1365 | 24.9k | { |
1366 | 24.9k | MWAWInputStreamPtr input = getInput(); |
1367 | 24.9k | libmwaw::DebugStream f; |
1368 | | |
1369 | 24.9k | long pos=input->tell(); |
1370 | 24.9k | if (!input->checkPosition(pos+20)) |
1371 | 121 | return false; |
1372 | 24.8k | f.str(""); |
1373 | 24.8k | if (zId) |
1374 | 1.44k | f << "Entries(Group)[Z" << zId << "]:"; |
1375 | 23.3k | else |
1376 | 23.3k | f << "Entries(Group):"; |
1377 | 24.8k | if (zId) { |
1378 | 1.44k | auto type=m_state->getZoneType(zId); |
1379 | 1.44k | if (type!=FreeHandParserInternal::Z_Group && type!=FreeHandParserInternal::Z_Shape) { |
1380 | 68 | MWAW_DEBUG_MSG(("FreeHandParser::readGroupV2: find unexpected zone type for zone %d\n", zId)); |
1381 | 68 | } |
1382 | 1.44k | } |
1383 | | |
1384 | 24.8k | auto dSz=static_cast<int>(input->readULong(4)); // probably related to size |
1385 | 24.8k | f << "sz=" << dSz << ","; |
1386 | 24.8k | if (input->readULong(2)!=0x138a) { |
1387 | 0 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1388 | 0 | return false; |
1389 | 0 | } |
1390 | 24.8k | FreeHandParserInternal::Shape res; |
1391 | 24.8k | res.m_id=zId; |
1392 | 24.8k | res.m_type=FreeHandParserInternal::Shape::Group; |
1393 | 74.4k | for (int i=0; i<2; ++i) { // always 0 |
1394 | 49.6k | auto val=static_cast<int>(input->readLong(2)); |
1395 | 49.6k | if (val) f << "f" << i << "=" << val << ","; |
1396 | 49.6k | } |
1397 | 24.8k | auto sSz=static_cast<int>(input->readULong(2)); |
1398 | 24.8k | if (!input->checkPosition(input->tell()+sSz+8)) { |
1399 | 1.79k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1400 | 1.79k | return false; |
1401 | 1.79k | } |
1402 | 23.0k | ascii().addDelimiter(input->tell(),'|'); |
1403 | | /* find |
1404 | | 00000000000000000000000000000000 |
1405 | | 000f000a000000000000000000000000a89d800180017fff7fff7fff7fff7fff7fff7fff7fff7fff7fff4ead7fff80017fff52807fff7fff7fff60144ead8fff670a |
1406 | | */ |
1407 | 23.0k | input->seek(sSz, librevenge::RVNG_SEEK_CUR); |
1408 | 23.0k | ascii().addDelimiter(input->tell(),'|'); |
1409 | 23.0k | float dim[2]; |
1410 | 46.0k | for (auto &d : dim) d=float(input->readLong(2))/10.f; |
1411 | 23.0k | if (MWAWVec2f(dim[0],dim[1])!=MWAWVec2f(0,0)) |
1412 | 16.1k | f << "dim?=" << MWAWVec2f(dim[0],dim[1]) << ","; |
1413 | 23.0k | auto val=static_cast<int>(input->readLong(2)); |
1414 | 23.0k | if (val) f << "f2=" << val << ","; |
1415 | | |
1416 | 23.0k | auto N=static_cast<int>(input->readULong(2)); |
1417 | 23.0k | if (!input->checkPosition(input->tell()+2*N)) { |
1418 | 4.32k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1419 | 4.32k | return false; |
1420 | 4.32k | } |
1421 | 18.6k | f << "childs=["; |
1422 | 738k | for (int i=0; i<N; ++i) { |
1423 | 727k | auto id=static_cast<int>(input->readULong(2)); |
1424 | 727k | if (!m_state->addZoneId(id, FreeHandParserInternal::Z_Shape)) { |
1425 | 7.22k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1426 | 7.22k | return false; |
1427 | 7.22k | } |
1428 | 719k | res.m_childs.push_back(id); |
1429 | 719k | f << "Z" << id << ","; |
1430 | 719k | } |
1431 | 11.4k | f <<"],"; |
1432 | 11.4k | ascii().addPos(pos); |
1433 | 11.4k | ascii().addNote(f.str().c_str()); |
1434 | 11.4k | if (zId && m_state->m_zIdToShapeMap.find(zId)==m_state->m_zIdToShapeMap.end()) |
1435 | 1.40k | m_state->m_zIdToShapeMap.insert(std::map<int, FreeHandParserInternal::Shape>::value_type(zId,res)); |
1436 | 11.4k | return true; |
1437 | 18.6k | } |
1438 | | |
1439 | | bool FreeHandParser::readJoinGroup(int zId) |
1440 | 14.9k | { |
1441 | 14.9k | MWAWInputStreamPtr input = getInput(); |
1442 | 14.9k | libmwaw::DebugStream f; |
1443 | | |
1444 | 14.9k | long pos=input->tell(); |
1445 | 14.9k | FreeHandParserInternal::ShapeHeader shape; |
1446 | 14.9k | int const vers=version(); |
1447 | 14.9k | if (!readShapeHeader(shape)) { |
1448 | 3.24k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1449 | 3.24k | return false; |
1450 | 3.24k | } |
1451 | 11.7k | if ((vers==1 && shape.m_type!=0x1008) || (vers>1 && shape.m_type!=0x13f0) |
1452 | 11.7k | || !input->checkPosition(input->tell()+8)) { |
1453 | 155 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1454 | 155 | return false; |
1455 | 155 | } |
1456 | 11.5k | f.str(""); |
1457 | 11.5k | if (zId) |
1458 | 191 | f << "Entries(JoinGrp)[Z" << zId << "]:" << shape; |
1459 | 11.3k | else |
1460 | 11.3k | f << "Entries(JoinGrp):" << shape; |
1461 | 11.5k | if (zId) { |
1462 | 191 | auto type=m_state->getZoneType(zId); |
1463 | 191 | if (type!=FreeHandParserInternal::Z_Shape) { |
1464 | 182 | MWAW_DEBUG_MSG(("FreeHandParser::readJoinGroup: find unexpected zone type for zone %d\n", zId)); |
1465 | 182 | } |
1466 | 191 | } |
1467 | 11.5k | FreeHandParserInternal::Shape res; |
1468 | 11.5k | res.m_id=zId; |
1469 | 11.5k | res.m_layerId=shape.m_layerId; |
1470 | 11.5k | res.m_type=FreeHandParserInternal::Shape::JoinGroup; |
1471 | 11.5k | if (shape.m_size!=0x24) f << "sz?=" << shape.m_size << ","; |
1472 | 11.5k | res.m_joinDistance=float(input->readLong(4))/65536.f; |
1473 | 11.5k | if (res.m_joinDistance<0 || res.m_joinDistance>0) |
1474 | 11.0k | f << "dist=" << res.m_joinDistance << ","; |
1475 | 11.5k | f << "childs=["; |
1476 | 34.7k | for (int i=0; i<2; ++i) { |
1477 | 23.1k | auto id=static_cast<int>(input->readULong(2)); |
1478 | 23.1k | if (!m_state->addZoneId(id, FreeHandParserInternal::Z_Shape)) { |
1479 | 1.32k | MWAW_DEBUG_MSG(("FreeHandParser::readJoinGroup: find unexpected child id\n")); |
1480 | 1.32k | f << "###"; |
1481 | 1.32k | } |
1482 | 23.1k | res.m_childs.push_back(id); |
1483 | 23.1k | f << "Z" << id << ","; |
1484 | 23.1k | } |
1485 | 11.5k | f <<"],"; |
1486 | 11.5k | ascii().addPos(pos); |
1487 | 11.5k | ascii().addNote(f.str().c_str()); |
1488 | 11.5k | if (zId && m_state->m_zIdToShapeMap.find(zId)==m_state->m_zIdToShapeMap.end()) |
1489 | 191 | m_state->m_zIdToShapeMap.insert(std::map<int, FreeHandParserInternal::Shape>::value_type(zId,res)); |
1490 | 11.5k | static bool first=true; |
1491 | 11.5k | if (first) { |
1492 | 13 | MWAW_DEBUG_MSG(("FreeHandParser::readJoinGroup: Ooops, sending text on path is unimplemented\n")); |
1493 | 13 | first=false; |
1494 | 13 | } |
1495 | 11.5k | return true; |
1496 | 11.7k | } |
1497 | | |
1498 | | bool FreeHandParser::readTransformGroup(int zId) |
1499 | 18.9k | { |
1500 | 18.9k | MWAWInputStreamPtr input = getInput(); |
1501 | 18.9k | libmwaw::DebugStream f; |
1502 | | |
1503 | 18.9k | long pos=input->tell(); |
1504 | 18.9k | FreeHandParserInternal::ShapeHeader shape; |
1505 | 18.9k | if (!readShapeHeader(shape)) { |
1506 | 4.96k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1507 | 4.96k | return false; |
1508 | 4.96k | } |
1509 | 14.0k | int const vers=version(); |
1510 | 14.0k | if ((vers==1 && shape.m_type!=0x1005) || (vers>1 && shape.m_type!=0x13ed) || !input->checkPosition(input->tell()+30)) { |
1511 | 201 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1512 | 201 | return false; |
1513 | 201 | } |
1514 | 13.7k | f.str(""); |
1515 | 13.7k | if (zId) |
1516 | 1.18k | f << "Entries(TransformGrp)[Z" << zId << "]:" << shape; |
1517 | 12.6k | else |
1518 | 12.6k | f << "Entries(TransformGrp):" << shape; |
1519 | 13.7k | if (shape.m_size!=0x38) f << "sz?=" << shape.m_size << ","; |
1520 | 13.7k | if (zId) { |
1521 | 1.18k | auto zType=m_state->getZoneType(zId); |
1522 | 1.18k | if (zType!=FreeHandParserInternal::Z_Group && zType!=FreeHandParserInternal::Z_Shape) { |
1523 | 106 | MWAW_DEBUG_MSG(("FreeHandParser::readTransformGroup: find unexpected zone type for zone %d\n", zId)); |
1524 | 106 | } |
1525 | 1.18k | } |
1526 | 13.7k | FreeHandParserInternal::Shape res; |
1527 | 13.7k | res.m_id=zId; |
1528 | 13.7k | res.m_layerId=shape.m_layerId; |
1529 | 13.7k | res.m_type=FreeHandParserInternal::Shape::Group; |
1530 | 13.7k | auto id=static_cast<int>(input->readULong(2)); |
1531 | 13.7k | if (!m_state->addZoneId(id, FreeHandParserInternal::Z_Group)) { |
1532 | 486 | MWAW_DEBUG_MSG(("FreeHandParser::readTransformGroup: find unexpected child id\n")); |
1533 | 486 | f << "###"; |
1534 | 486 | } |
1535 | 13.7k | f << "child=Z" << id << ","; |
1536 | 13.7k | res.m_childs.push_back(id); |
1537 | 13.7k | auto val=static_cast<int>(input->readULong(2)); // always 0 |
1538 | 13.7k | if (val) f << "f0=" << val << ","; |
1539 | 13.7k | f << "flags=" << std::hex << input->readULong(2) << std::dec << ","; |
1540 | 13.7k | f << "rot=["; |
1541 | 13.7k | float dim[6]; |
1542 | 68.9k | for (int i=0; i<4; ++i) { |
1543 | 55.1k | dim[i]=float(input->readLong(4))/65536.f; |
1544 | 55.1k | f << dim[i] << ","; |
1545 | 55.1k | } |
1546 | 13.7k | f << "],"; |
1547 | 13.7k | f << "trans=["; |
1548 | 41.3k | for (int i=0; i<2; ++i) { |
1549 | 27.5k | dim[i+4]=float(input->readLong(4))/65536.f/10.f; |
1550 | 27.5k | f << dim[i+4] << ","; |
1551 | 27.5k | } |
1552 | 13.7k | f << "],"; |
1553 | 13.7k | res.m_transformation=MWAWTransformation(MWAWVec3f(dim[0],dim[2],dim[4]),MWAWVec3f(dim[1],dim[3],dim[5])); |
1554 | | |
1555 | 13.7k | ascii().addPos(pos); |
1556 | 13.7k | ascii().addNote(f.str().c_str()); |
1557 | 13.7k | if (zId && m_state->m_zIdToShapeMap.find(zId)==m_state->m_zIdToShapeMap.end()) |
1558 | 1.18k | m_state->m_zIdToShapeMap.insert(std::map<int, FreeHandParserInternal::Shape>::value_type(zId,res)); |
1559 | 13.7k | return true; |
1560 | 14.0k | } |
1561 | | |
1562 | | bool FreeHandParser::readStyleGroup(int zId) |
1563 | 92.7k | { |
1564 | 92.7k | int const vers=version(); |
1565 | 92.7k | MWAWInputStreamPtr input = getInput(); |
1566 | 92.7k | libmwaw::DebugStream f; |
1567 | | |
1568 | 92.7k | long pos=input->tell(); |
1569 | 92.7k | if (!input->checkPosition(pos+(vers>1 ? 12 : 16))) |
1570 | 265 | return false; |
1571 | 92.4k | f.str(""); |
1572 | 92.4k | if (zId) |
1573 | 14.5k | f << "Entries(StyleGrp)[Z" << zId << "]:"; |
1574 | 77.9k | else |
1575 | 77.9k | f << "Entries(StyleGrp):"; |
1576 | 92.4k | auto cType=FreeHandParserInternal::Z_Unknown; |
1577 | 92.4k | bool checkDSize=true; |
1578 | 92.4k | if (zId) { |
1579 | 14.5k | auto zType=m_state->getZoneType(zId); |
1580 | 14.5k | checkDSize=false; |
1581 | 14.5k | if (zType==FreeHandParserInternal::Z_ColorGroup) |
1582 | 2.74k | cType=FreeHandParserInternal::Z_Color; |
1583 | 11.8k | else if (zType==FreeHandParserInternal::Z_DashGroup) |
1584 | 2.53k | cType=FreeHandParserInternal::Z_Dash; |
1585 | 9.27k | else if (zType==FreeHandParserInternal::Z_FillGroup) |
1586 | 3.83k | cType=FreeHandParserInternal::Z_Fill; |
1587 | 5.44k | else if (zType==FreeHandParserInternal::Z_LineStyleGroup) |
1588 | 3.69k | cType=FreeHandParserInternal::Z_LineStyle; |
1589 | 1.74k | else if (zType!=FreeHandParserInternal::Z_StyleGroup) { |
1590 | 678 | checkDSize=true; |
1591 | 678 | MWAW_DEBUG_MSG(("FreeHandParser::readStyleGroup: find unexpected zone type for zone %d\n", zId)); |
1592 | 678 | } |
1593 | 14.5k | } |
1594 | 92.4k | auto dSz=static_cast<int>(input->readULong(4)); // probably related to size |
1595 | 92.4k | f << "sz?=" << dSz << ","; |
1596 | 92.4k | auto opCode=static_cast<int>(input->readULong(2)); |
1597 | 92.4k | if ((vers==1 && opCode!=2) || (vers>1 && opCode!=5)) |
1598 | 0 | return false; |
1599 | 92.4k | if (vers==1) { |
1600 | 158k | for (int i=0; i<2; ++i) { // always f0=0,f1=16 ? |
1601 | 105k | auto val=static_cast<int>(input->readLong(2)); |
1602 | 105k | if (val) |
1603 | 58.2k | f << "f" << i << "=" << val << ","; |
1604 | 105k | } |
1605 | 52.7k | } |
1606 | 92.4k | auto N=static_cast<int>(input->readULong(2)); |
1607 | 92.4k | if (!input->checkPosition(input->tell()+4+2*N) || |
1608 | 82.0k | (vers==1 && checkDSize && N!=(dSz-16)/2) || |
1609 | 59.4k | (vers>1 && checkDSize && N!=(dSz-12)/2)) |
1610 | 51.9k | return false; |
1611 | 121k | for (int i=0; i<2; ++i) { // always 0? |
1612 | 80.9k | auto val=static_cast<int>(input->readLong(2)); |
1613 | 80.9k | if (val) |
1614 | 29.1k | f << "f" << i+2 << "=" << val << ","; |
1615 | 80.9k | } |
1616 | 40.4k | f << "childs=["; |
1617 | 157k | for (int i=0; i<N; ++i) { |
1618 | 130k | auto id=static_cast<int>(input->readULong(2)); |
1619 | 130k | if (!m_state->addZoneId(id, cType)) { |
1620 | 17.8k | if (checkDSize) return false; |
1621 | 5.00k | MWAW_DEBUG_MSG(("FreeHandParser::readStyleGroup: find unexpected child zone %d\n", id)); |
1622 | 5.00k | f << "###"; |
1623 | 5.00k | } |
1624 | 117k | f << "Z" << id << ","; |
1625 | 117k | } |
1626 | 27.6k | f << "],"; |
1627 | 27.6k | ascii().addPos(pos); |
1628 | 27.6k | ascii().addNote(f.str().c_str()); |
1629 | | |
1630 | 27.6k | return true; |
1631 | 40.4k | } |
1632 | | |
1633 | | bool FreeHandParser::readStringZone(int zId) |
1634 | 82.8k | { |
1635 | 82.8k | MWAWInputStreamPtr input = getInput(); |
1636 | 82.8k | libmwaw::DebugStream f; |
1637 | | |
1638 | 82.8k | long pos=input->tell(); |
1639 | 82.8k | auto dSz=long(input->readULong(4)); |
1640 | 82.8k | auto opCode=static_cast<int>(input->readLong(2)); |
1641 | 82.8k | int const vers=version(); |
1642 | | // v1: opcode=3, v2: opcode=6 |
1643 | 82.8k | if (vers==2) { |
1644 | 16.3k | dSz-=4; |
1645 | 16.3k | opCode-=3; |
1646 | 16.3k | } |
1647 | 82.8k | if (opCode!=3 || dSz<3 || !input->checkPosition(pos+dSz+2)) { |
1648 | 10.2k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1649 | 10.2k | return false; |
1650 | 10.2k | } |
1651 | 72.6k | f.str(""); |
1652 | 72.6k | if (zId) |
1653 | 2.31k | f << "Entries(String)[Z" << zId << "]:"; |
1654 | 70.2k | else |
1655 | 70.2k | f << "Entries(String):"; |
1656 | 72.6k | if (zId && m_state->getZoneType(zId)!=FreeHandParserInternal::Z_String) { |
1657 | 815 | MWAW_DEBUG_MSG(("FreeHandParser::readStringZone: find unexpected zone type for zone %d\n", zId)); |
1658 | 815 | } |
1659 | 72.6k | auto sSz=int(input->readULong(1)); |
1660 | 72.6k | if (sSz+5>dSz || (!zId && sSz+6<dSz)) { |
1661 | 51.1k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1662 | 51.1k | return false; |
1663 | 51.1k | } |
1664 | 21.4k | std::string name; |
1665 | 246k | for (int i=0; i<sSz; ++i) name += char(input->readULong(1)); |
1666 | 21.4k | f << name << ","; |
1667 | 21.4k | if (zId && m_state->m_zIdToStringMap.find(zId)==m_state->m_zIdToStringMap.end()) |
1668 | 2.24k | m_state->m_zIdToStringMap[zId]=name; |
1669 | 21.4k | ascii().addPos(pos); |
1670 | 21.4k | ascii().addNote(f.str().c_str()); |
1671 | 21.4k | input->seek(pos+dSz+2, librevenge::RVNG_SEEK_SET); |
1672 | 21.4k | return true; |
1673 | 72.6k | } |
1674 | | |
1675 | | bool FreeHandParser::readShapeHeader(FreeHandParserInternal::ShapeHeader &shape) |
1676 | 532k | { |
1677 | 532k | MWAWInputStreamPtr input = getInput(); |
1678 | 532k | libmwaw::DebugStream f; |
1679 | 532k | long pos=input->tell(); |
1680 | 532k | int const vers=version(); |
1681 | 532k | if (!input->checkPosition(pos+(vers==1 ? 20 : 18))) return false; |
1682 | 528k | shape.m_size=long(input->readULong(4)); |
1683 | 528k | shape.m_type=static_cast<int>(input->readULong(2)); |
1684 | 528k | if (vers>1) { |
1685 | 257k | shape.m_dataId=static_cast<int>(input->readULong(2)); |
1686 | 257k | if (shape.m_dataId && !m_state->addZoneId(shape.m_dataId, FreeHandParserInternal::Z_Note)) { |
1687 | 8.83k | MWAW_DEBUG_MSG(("FreeHandParser::readShapeHeader: find unexpected data id\n")); |
1688 | 8.83k | f << "###dataId"; |
1689 | 8.83k | } |
1690 | 257k | shape.m_values[0]=static_cast<int>(input->readLong(2)); // always 0 |
1691 | 257k | shape.m_layerId=static_cast<int>(input->readULong(2)); |
1692 | 257k | shape.m_values[1]=static_cast<int>(input->readLong(2)); // always 0 |
1693 | | // now to multiple of 256 ??? |
1694 | 257k | f << "unkn=[" << float(input->readLong(2))/256.f << "," << float(input->readLong(2))/256.f << "],"; |
1695 | 257k | shape.m_extra=f.str(); |
1696 | 257k | return true; |
1697 | 257k | } |
1698 | | // always 0, if not we may have a problem... |
1699 | 271k | shape.m_values[0]=static_cast<int>(input->readLong(2)); |
1700 | 271k | auto dataSz=static_cast<int>(input->readULong(2)); |
1701 | 271k | if (!input->checkPosition(pos+14+dataSz)) { |
1702 | 23.0k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1703 | 23.0k | return false; |
1704 | 23.0k | } |
1705 | 248k | if (dataSz) { |
1706 | 139k | auto sSz=static_cast<int>(input->readULong(1)); |
1707 | 139k | if (sSz==dataSz-1) { |
1708 | 1.37M | for (int i=0; i<sSz; ++i) |
1709 | 1.35M | shape.m_note+=char(input->readULong(1)); |
1710 | 18.1k | } |
1711 | 121k | else { |
1712 | 121k | MWAW_DEBUG_MSG(("FreeHandParser::readShapeHeader: find unexpected special size\n")); |
1713 | 121k | f << "##specialSize=" << dataSz << ","; |
1714 | 121k | input->seek(dataSz-1, librevenge::RVNG_SEEK_CUR); |
1715 | 121k | } |
1716 | 139k | } |
1717 | 248k | shape.m_layerId=static_cast<int>(input->readULong(2)); |
1718 | | /* val1,val2: always 0, if not we may have a problem... |
1719 | | val3: sometimes a 1005 zone |
1720 | | */ |
1721 | 992k | for (int i=0; i<3; ++i) |
1722 | 744k | shape.m_values[i+1]=static_cast<int>(input->readLong(2)); |
1723 | 248k | if (shape.m_values[3]) { |
1724 | 158k | if (!m_state->addZoneId(shape.m_values[3], FreeHandParserInternal::Z_Shape)) { |
1725 | 14.9k | MWAW_DEBUG_MSG(("FreeHandParser::readShapeHeader: find unexpected shape id\n")); |
1726 | 14.9k | f << "###shapeId"; |
1727 | 14.9k | } |
1728 | 158k | } |
1729 | | // the special zone |
1730 | 248k | dataSz=static_cast<int>(input->readULong(2)); |
1731 | 248k | if (!input->checkPosition(input->tell()+dataSz)) { |
1732 | 55.3k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1733 | 55.3k | return false; |
1734 | 55.3k | } |
1735 | 192k | if (dataSz==8) { |
1736 | 2.85k | long actPos=input->tell(); |
1737 | 2.85k | if (!readScreenMode(*shape.m_screen)) { |
1738 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::readShapeHeader: can not read screen mode\n")); |
1739 | 0 | f << "##screenMode,"; |
1740 | 0 | input->seek(actPos+8, librevenge::RVNG_SEEK_SET); |
1741 | 0 | } |
1742 | 2.85k | } |
1743 | 189k | else if (dataSz) { |
1744 | 76.9k | MWAW_DEBUG_MSG(("FreeHandParser::readShapeHeader: find unexpected special size\n")); |
1745 | 76.9k | f << "##specialSize=" << dataSz << ","; |
1746 | 76.9k | input->seek(dataSz, librevenge::RVNG_SEEK_CUR); |
1747 | 76.9k | } |
1748 | 192k | shape.m_extra=f.str(); |
1749 | 192k | return true; |
1750 | 248k | } |
1751 | | |
1752 | | bool FreeHandParser::readScreenMode(FreeHandParserInternal::ScreenMode &screen) |
1753 | 65.4k | { |
1754 | 65.4k | MWAWInputStreamPtr input = getInput(); |
1755 | 65.4k | long pos=input->tell(); |
1756 | 65.4k | if (!input->checkPosition(pos+8)) return false; |
1757 | 65.4k | screen.m_function=static_cast<int>(input->readLong(2)); |
1758 | 65.4k | screen.m_angle=float(input->readLong(2))/10.f; |
1759 | 65.4k | screen.m_lineByInch=static_cast<int>(input->readULong(2)); |
1760 | 65.4k | screen.m_value=static_cast<int>(input->readLong(2)); // always 0? |
1761 | 65.4k | return true; |
1762 | 65.4k | } |
1763 | | |
1764 | | bool FreeHandParser::readStyleHeader(FreeHandParserInternal::StyleHeader &style) |
1765 | 411k | { |
1766 | 411k | MWAWInputStreamPtr input = getInput(); |
1767 | 411k | libmwaw::DebugStream f; |
1768 | 411k | long pos=input->tell(); |
1769 | 411k | if (!input->checkPosition(pos+12)) return false; |
1770 | 411k | style.m_size=long(input->readULong(4)); |
1771 | 411k | style.m_type=static_cast<int>(input->readULong(2)); |
1772 | 411k | if (version()==1) { |
1773 | | // always 0, if not we may have a problem... |
1774 | 349k | style.m_unknownValue=static_cast<int>(input->readLong(2)); |
1775 | 349k | auto dataSz=static_cast<int>(input->readULong(2)); |
1776 | 349k | if (!input->checkPosition(pos+12+dataSz)) { |
1777 | 21.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1778 | 21.9k | return false; |
1779 | 21.9k | } |
1780 | 327k | if (dataSz==8) { |
1781 | 62.5k | long actPos=input->tell(); |
1782 | 62.5k | if (!readScreenMode(*style.m_screen)) { |
1783 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::readStyleHeader: can not read screen mode\n")); |
1784 | 0 | f << "##screenMode,"; |
1785 | 0 | input->seek(actPos+8, librevenge::RVNG_SEEK_SET); |
1786 | 0 | } |
1787 | 62.5k | } |
1788 | 264k | else if (dataSz) { |
1789 | 36.9k | MWAW_DEBUG_MSG(("FreeHandParser::readStyleHeader: find unexpected special size\n")); |
1790 | 36.9k | f << "##specialSize=" << dataSz << ","; |
1791 | 36.9k | input->seek(dataSz, librevenge::RVNG_SEEK_CUR); |
1792 | 36.9k | } |
1793 | 327k | } |
1794 | 389k | auto id=static_cast<int>(input->readULong(2)); |
1795 | 389k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_String)) { |
1796 | 24.5k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1797 | 24.5k | return false; |
1798 | 24.5k | } |
1799 | 364k | else |
1800 | 364k | style.m_labelId=id; |
1801 | 364k | return true; |
1802 | 389k | } |
1803 | | |
1804 | | bool FreeHandParser::readColor(int zId) |
1805 | 76.6k | { |
1806 | 76.6k | MWAWInputStreamPtr input = getInput(); |
1807 | 76.6k | libmwaw::DebugStream f; |
1808 | | |
1809 | 76.6k | long pos=input->tell(); |
1810 | 76.6k | f.str(""); |
1811 | 76.6k | if (zId) |
1812 | 5.49k | f << "Entries(Color)[Z" << zId << "]:"; |
1813 | 71.1k | else |
1814 | 71.1k | f << "Entries(Color):"; |
1815 | 76.6k | if (zId && m_state->getZoneType(zId)!=FreeHandParserInternal::Z_Color) { |
1816 | 1.51k | MWAW_DEBUG_MSG(("FreeHandParser::readColor: find unexpected zone type for zone %d\n", zId)); |
1817 | 1.51k | } |
1818 | 76.6k | FreeHandParserInternal::StyleHeader zone; |
1819 | 76.6k | if (!readStyleHeader(zone)) { |
1820 | 4.25k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1821 | 4.25k | return false; |
1822 | 4.25k | } |
1823 | 72.4k | int expectedSize=0; |
1824 | 72.4k | int const vers=version(); |
1825 | 72.4k | switch (zone.m_type) { |
1826 | 7.13k | case 0x106a: |
1827 | 11.9k | case 0x1452: |
1828 | 11.9k | f << "color,"; |
1829 | 11.9k | expectedSize=12; |
1830 | 11.9k | if ((vers==1 && zone.m_size!=0x1c) || (vers>1 && zone.m_size!=0x1e)) |
1831 | 5.94k | f << "#sz?=" << zone.m_size << ","; |
1832 | 11.9k | break; |
1833 | 39.5k | case 0x106b: |
1834 | 39.5k | f << "tint,"; |
1835 | 39.5k | expectedSize=4; |
1836 | 39.5k | if (zone.m_size!=0x16) |
1837 | 39.0k | f << "#sz?=" << zone.m_size << ","; |
1838 | 39.5k | break; |
1839 | 2.41k | case 0x1453: |
1840 | 2.41k | f << "tint,"; |
1841 | 2.41k | expectedSize=10; |
1842 | 2.41k | if (zone.m_size!=0x1e) |
1843 | 32 | f << "#sz?=" << zone.m_size << ","; |
1844 | 2.41k | break; |
1845 | 5.40k | case 0x106c: |
1846 | 5.40k | f << "cmyk,"; |
1847 | 5.40k | expectedSize=8; |
1848 | 5.40k | if (zone.m_size!=0x18) |
1849 | 5.36k | f << "#sz?=" << zone.m_size << ","; |
1850 | 5.40k | break; |
1851 | 9.75k | case 0x1454: |
1852 | 9.75k | f << "cmyk,"; |
1853 | 9.75k | expectedSize=14; |
1854 | 9.75k | if (zone.m_size!=0x20) |
1855 | 9.75k | f << "#sz?=" << zone.m_size << ","; |
1856 | 9.75k | break; |
1857 | 3.36k | case 0x1455: |
1858 | 3.36k | f << "pantome?,"; |
1859 | 3.36k | expectedSize=22; |
1860 | 3.36k | if (zone.m_size!=0x28) |
1861 | 3.36k | f << "#sz?=" << zone.m_size << ","; |
1862 | 3.36k | break; |
1863 | 0 | default: |
1864 | 0 | break; |
1865 | 72.4k | } |
1866 | 72.4k | long endPos=input->tell()+expectedSize; |
1867 | 72.4k | if (expectedSize==0 || !input->checkPosition(endPos)) { |
1868 | 248 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1869 | 248 | return false; |
1870 | 248 | } |
1871 | 72.1k | f << zone; |
1872 | 72.1k | MWAWColor color; |
1873 | 72.1k | if (zone.m_type==0x106a || zone.m_type==0x1452) { |
1874 | 11.9k | unsigned char col[3]; |
1875 | 35.7k | for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
1876 | 11.9k | color=MWAWColor(col[0],col[1],col[2]); |
1877 | 11.9k | f << color << ","; |
1878 | 11.9k | auto val=static_cast<int>(input->readLong(2)); |
1879 | 11.9k | if (val) f << "id=" << val << ","; |
1880 | 11.9k | val=static_cast<int>(input->readLong(2)); // flag or big number |
1881 | 11.9k | if (val) f << "f0=" << val << ","; |
1882 | 11.9k | val=static_cast<int>(input->readLong(2)); // always 1 |
1883 | 11.9k | if (val!=1) f << "f1=" << val << ","; |
1884 | 11.9k | } |
1885 | 60.2k | else if (zone.m_type==0x106b || zone.m_type==0x1453) { |
1886 | 41.8k | if (zone.m_type==0x1453) { |
1887 | 2.41k | unsigned char col[3]; |
1888 | 7.24k | for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
1889 | 2.41k | color=MWAWColor(col[0],col[1],col[2]); |
1890 | 2.41k | f << color << ","; |
1891 | 2.41k | } |
1892 | 41.8k | auto cId=static_cast<int>(input->readULong(2)); |
1893 | 41.8k | if (cId && !m_state->addZoneId(cId, FreeHandParserInternal::Z_Color)) { |
1894 | 4.98k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1895 | 4.98k | return false; |
1896 | 4.98k | } |
1897 | 36.8k | f << "main[color]=Z" << cId << ","; |
1898 | 36.8k | MWAWColor mainColor(MWAWColor::white()); |
1899 | 36.8k | if (cId && m_state->m_zIdToColorMap.find(cId)!=m_state->m_zIdToColorMap.end()) |
1900 | 6.25k | mainColor=m_state->m_zIdToColorMap.find(cId)->second; |
1901 | 30.5k | else if (cId) { |
1902 | 16.8k | static bool first=true; |
1903 | 16.8k | if (first) { |
1904 | 13 | MWAW_DEBUG_MSG(("FreeHandParser::readColor: can not find some main color\n")); |
1905 | 13 | first=false; |
1906 | 13 | } |
1907 | 16.8k | } |
1908 | 36.8k | float tint=float(input->readULong(2))/65535.f; |
1909 | 36.8k | if (zone.m_type==0x106b) |
1910 | 34.4k | color=MWAWColor::barycenter(tint, mainColor, 1-tint, MWAWColor::white()); |
1911 | 36.8k | f << "percent=" << tint << ","; |
1912 | 36.8k | } |
1913 | 18.4k | else if (zone.m_type==0x1455) { |
1914 | 3.34k | unsigned char col[3]; |
1915 | 10.0k | for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
1916 | 3.34k | color=MWAWColor(col[0],col[1],col[2]); |
1917 | 3.34k | f << color << ","; |
1918 | | // what is that ? |
1919 | 30.1k | for (int i=0; i<8; ++i) { // f0=0|1a5|1f7,f2=0|451e,f4=0|f5c|1c28,f5=147a|2e14|828f,f6=1c2, f7=1 |
1920 | 26.7k | auto val=static_cast<int>(input->readULong(2)); |
1921 | 26.7k | if (val) f << "f" << i << "=" << std::hex << val << std::dec << ","; |
1922 | 26.7k | } |
1923 | 3.34k | } |
1924 | 15.0k | else { |
1925 | 15.0k | if (zone.m_type==0x1454) { |
1926 | 9.69k | unsigned char col[3]; |
1927 | 29.0k | for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
1928 | 9.69k | color=MWAWColor(col[0],col[1],col[2]); |
1929 | 9.69k | f << color << ","; |
1930 | 9.69k | } |
1931 | 15.0k | unsigned char col[4]; |
1932 | 60.3k | for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
1933 | 15.0k | if (zone.m_type==0x106c) { |
1934 | 5.38k | color=MWAWColor::colorFromCMYK(col[1],col[2],col[3],col[0]); |
1935 | 5.38k | f << color << ","; |
1936 | 5.38k | } |
1937 | 15.0k | } |
1938 | 67.2k | if (zId && m_state->m_zIdToColorMap.find(zId)==m_state->m_zIdToColorMap.end()) |
1939 | 5.38k | m_state->m_zIdToColorMap[zId]=color; |
1940 | 67.2k | ascii().addPos(pos); |
1941 | 67.2k | ascii().addNote(f.str().c_str()); |
1942 | 67.2k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1943 | 67.2k | return true; |
1944 | 72.1k | } |
1945 | | |
1946 | | bool FreeHandParser::readDash(int zId) |
1947 | 54.7k | { |
1948 | 54.7k | MWAWInputStreamPtr input = getInput(); |
1949 | 54.7k | libmwaw::DebugStream f; |
1950 | | |
1951 | 54.7k | long pos=input->tell(); |
1952 | 54.7k | f.str(""); |
1953 | 54.7k | if (zId) |
1954 | 4.96k | f << "Entries(Dash)[Z" << zId << "]:"; |
1955 | 49.7k | else |
1956 | 49.7k | f << "Entries(Dash):"; |
1957 | 54.7k | if (zId && m_state->getZoneType(zId)!=FreeHandParserInternal::Z_Dash) { |
1958 | 901 | MWAW_DEBUG_MSG(("FreeHandParser::readDash: find unexpected zone type for zone %d\n", zId)); |
1959 | 901 | } |
1960 | 54.7k | FreeHandParserInternal::StyleHeader zone; |
1961 | 54.7k | if (!readStyleHeader(zone)) { |
1962 | 8.68k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1963 | 8.68k | return false; |
1964 | 8.68k | } |
1965 | 46.0k | int const vers=version(); |
1966 | 46.0k | if (zone.m_size < 12 || (vers==1 && zone.m_type!=0x1195) || (vers>1 && zone.m_type!=0x157d)) { |
1967 | 16.3k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1968 | 16.3k | return false; |
1969 | 16.3k | } |
1970 | 29.6k | long endPos; |
1971 | 29.6k | if (vers==1) |
1972 | 19.3k | endPos=pos+2+zone.m_size; |
1973 | 10.3k | else { |
1974 | 10.3k | endPos=pos-2+zone.m_size; |
1975 | 31.0k | for (int i=0; i<2; ++i) { // 0 |
1976 | 20.7k | auto val=static_cast<int>(input->readULong(2)); |
1977 | 20.7k | if (val) |
1978 | 815 | f << "f" << i << "=" << val << ","; |
1979 | 20.7k | } |
1980 | 10.3k | } |
1981 | 29.6k | f << zone; |
1982 | 29.6k | auto N=static_cast<int>(input->readLong(2)); |
1983 | 29.6k | if (endPos!=input->tell()+2*N || !input->checkPosition(endPos)) { |
1984 | 14.6k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1985 | 14.6k | return false; |
1986 | 14.6k | } |
1987 | 14.9k | f << "dash=["; |
1988 | 14.9k | std::vector<float> dashes; |
1989 | 52.1k | for (int j=0; j<N; ++j) { |
1990 | 37.1k | dashes.push_back(float(input->readLong(2))/10.f); |
1991 | 37.1k | f << dashes.back() << ","; |
1992 | 37.1k | } |
1993 | 14.9k | f << "],"; |
1994 | 14.9k | if (zId && m_state->m_zIdToDashMap.find(zId)==m_state->m_zIdToDashMap.end()) |
1995 | 4.79k | m_state->m_zIdToDashMap[zId]=dashes; |
1996 | 14.9k | ascii().addPos(pos); |
1997 | 14.9k | ascii().addNote(f.str().c_str()); |
1998 | 14.9k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1999 | | |
2000 | 14.9k | return true; |
2001 | 29.6k | } |
2002 | | |
2003 | | bool FreeHandParser::readFillStyle(int zId) |
2004 | 85.6k | { |
2005 | 85.6k | MWAWInputStreamPtr input = getInput(); |
2006 | 85.6k | libmwaw::DebugStream f; |
2007 | | |
2008 | 85.6k | long pos=input->tell(); |
2009 | 85.6k | if (!input->checkPosition(pos+13)) |
2010 | 365 | return false; |
2011 | 85.2k | f.str(""); |
2012 | 85.2k | if (zId) |
2013 | 9.20k | f << "Entries(FillStyle)[Z" << zId << "]:"; |
2014 | 76.0k | else |
2015 | 76.0k | f << "Entries(FillStyle):"; |
2016 | 85.2k | if (zId && m_state->getZoneType(zId)!=FreeHandParserInternal::Z_Fill) { |
2017 | 1.39k | MWAW_DEBUG_MSG(("FreeHandParser::readFillStyle: find unexpected zone type for zone %d\n", zId)); |
2018 | 1.39k | } |
2019 | 85.2k | FreeHandParserInternal::StyleHeader zone; |
2020 | 85.2k | if (!readStyleHeader(zone)) { |
2021 | 14.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2022 | 14.9k | return false; |
2023 | 14.9k | } |
2024 | 70.2k | FreeHandParserInternal::FillStyle style; |
2025 | 70.2k | int expectedSize=0; |
2026 | 70.2k | int const vers=version(); |
2027 | 70.2k | switch (zone.m_type) { |
2028 | 14.3k | case 0x10cd: |
2029 | 14.3k | f << "basic,"; |
2030 | 14.3k | if (zone.m_size!=0x12) f << "sz?=" << zone.m_size << ","; |
2031 | 14.3k | expectedSize=3; |
2032 | 14.3k | break; |
2033 | 14.7k | case 0x10d0: |
2034 | 14.7k | f << "gradient,"; |
2035 | 14.7k | style.m_type=MWAWGraphicStyle::Gradient::G_Linear; |
2036 | 14.7k | if (zone.m_size!=0x18) f << "sz?=" << zone.m_size << ","; |
2037 | 14.7k | expectedSize=8; |
2038 | 14.7k | break; |
2039 | 21.2k | case 0x10d1: |
2040 | 21.2k | f << "radial,"; |
2041 | 21.2k | style.m_type=MWAWGraphicStyle::Gradient::G_Radial; |
2042 | 21.2k | if (zone.m_size!=0x14) f << "sz?=" << zone.m_size << ","; |
2043 | 21.2k | expectedSize=4; |
2044 | 21.2k | break; |
2045 | 4.88k | case 0x14b5: |
2046 | 4.88k | f << "basic,"; |
2047 | 4.88k | if (zone.m_size!=0x16) f << "sz?=" << zone.m_size << ","; |
2048 | 4.88k | expectedSize=8; |
2049 | 4.88k | break; |
2050 | 6.01k | case 0x14b7: |
2051 | 6.01k | f << "gradient,"; |
2052 | 6.01k | style.m_type=MWAWGraphicStyle::Gradient::G_Linear; |
2053 | 6.01k | if (zone.m_size!=0x1c) f << "sz?=" << zone.m_size << ","; |
2054 | 6.01k | expectedSize=12; |
2055 | 6.01k | break; |
2056 | 2.25k | case 0x14b8: |
2057 | 2.25k | f << "radial,"; |
2058 | 2.25k | style.m_type=MWAWGraphicStyle::Gradient::G_Radial; |
2059 | 2.25k | if (zone.m_size!=0x1e) f << "sz?=" << zone.m_size << ","; |
2060 | 2.25k | expectedSize=14; |
2061 | 2.25k | break; |
2062 | 4.23k | case 0x14d3: |
2063 | 4.23k | f << "pattern,"; |
2064 | 4.23k | if (zone.m_size!=0x1c) f << "sz?=" << zone.m_size << ","; |
2065 | 4.23k | expectedSize=14; |
2066 | 4.23k | break; |
2067 | 2.55k | case 0x14dd: |
2068 | 2.55k | f << "tiled,"; |
2069 | 2.55k | if (zone.m_size!=0x44) f << "sz?=" << zone.m_size << ","; |
2070 | 2.55k | expectedSize=54; |
2071 | 2.55k | break; |
2072 | 0 | default: |
2073 | 0 | break; |
2074 | 70.2k | } |
2075 | 70.2k | long endPos=input->tell()+expectedSize; |
2076 | 70.2k | if (expectedSize==0 || !input->checkPosition(endPos)) { |
2077 | 345 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2078 | 345 | return false; |
2079 | 345 | } |
2080 | 69.9k | f << zone; |
2081 | 69.9k | if (vers>1) { |
2082 | 59.3k | for (int i=0; i<2; ++i) { // always 0 |
2083 | 39.5k | auto val=static_cast<int>(input->readLong(2)); |
2084 | 39.5k | if (val) f << "f" << i << "=" << val << ","; |
2085 | 39.5k | } |
2086 | 19.7k | } |
2087 | 69.9k | auto id=static_cast<int>(input->readULong(2)); |
2088 | 69.9k | if (zone.m_type==0x14dd) { |
2089 | 2.40k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Group)) { |
2090 | 100 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2091 | 100 | return false; |
2092 | 100 | } |
2093 | 2.30k | else if (id) { |
2094 | 1.27k | static bool first=true; |
2095 | 1.27k | if (first) { |
2096 | 13 | MWAW_DEBUG_MSG(("FreeHandParser::readFillStyle: retrieving tiled style is not implemented\n")); |
2097 | 13 | first=false; |
2098 | 13 | } |
2099 | 1.27k | f << "group=Z" << id << ","; |
2100 | 1.27k | } |
2101 | 11.5k | for (int i=0; i<4; ++i) { // always 0 |
2102 | 9.22k | auto val=static_cast<int>(input->readLong(2)); |
2103 | 9.22k | if (val) f << "f" << i+2 << "=" << val << ","; |
2104 | 9.22k | } |
2105 | 2.30k | f << "scale=" << float(input->readLong(4))/65536.f << "x" << float(input->readLong(4))/65536.f << ","; |
2106 | 2.30k | f << "decal=" << float(input->readLong(2))/10.f << "x" << float(input->readLong(2))/10.f << ","; |
2107 | 2.30k | f << "angle=" << float(input->readLong(2))/10.f << ","; |
2108 | 2.30k | f << "fl=" << std::hex << input->readULong(2) << std::dec << ","; // 39|49 |
2109 | 2.30k | f << "rot=["; |
2110 | 11.5k | for (int i=0; i<4; ++i) |
2111 | 9.22k | f << float(input->readLong(4))/65536.f << ","; |
2112 | 2.30k | f << "],"; |
2113 | 2.30k | f << "trans=["; |
2114 | 6.91k | for (int i=0; i<2; ++i) |
2115 | 4.61k | f << float(input->readLong(4))/65536.f/10.f << ","; |
2116 | 2.30k | f << "],"; |
2117 | 2.30k | } |
2118 | 67.5k | else if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Color)) { |
2119 | 6.69k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2120 | 6.69k | return false; |
2121 | 6.69k | } |
2122 | 60.8k | else if (id) { |
2123 | 46.3k | style.m_colorId[0]=id; |
2124 | 46.3k | f << "color=Z" << id << ","; |
2125 | 46.3k | } |
2126 | 63.1k | if (zone.m_type==0x10d0 || zone.m_type==0x10d1 || zone.m_type==0x14b7 || zone.m_type==0x14b8) { |
2127 | 39.4k | id=static_cast<int>(input->readULong(2)); |
2128 | 39.4k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Color)) { |
2129 | 6.89k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2130 | 6.89k | return false; |
2131 | 6.89k | } |
2132 | 32.5k | else if (id) { |
2133 | 20.4k | style.m_colorId[1]=id; |
2134 | 20.4k | f << "color2=Z" << id << ","; |
2135 | 20.4k | } |
2136 | 39.4k | } |
2137 | 56.2k | if (zone.m_type==0x10d0 || zone.m_type==0x14b7) { |
2138 | 17.3k | style.m_angle = float(input->readULong(2))/10.f; |
2139 | 17.3k | f << "angle=" << style.m_angle << ","; |
2140 | 17.3k | auto val=static_cast<int>(input->readULong(vers==1 ? 1 : 2)); |
2141 | 17.3k | switch (val) { |
2142 | 3.85k | case 1: |
2143 | 3.85k | f << "linear,"; |
2144 | 3.85k | break; |
2145 | 6.84k | case 2: |
2146 | 6.84k | style.m_logarithm=true; |
2147 | 6.84k | f << "logarithm,"; |
2148 | 6.84k | break; |
2149 | 6.66k | default: |
2150 | 6.66k | MWAW_DEBUG_MSG(("FreeHandParser::readFillStyle: find unexpected gradient type\n")); |
2151 | 6.66k | f << "#gradient[type]=" << val << ","; |
2152 | 17.3k | } |
2153 | 17.3k | } |
2154 | 38.8k | else if (zone.m_type==0x14b8) { |
2155 | 8.52k | for (int i=0; i<3; ++i) { // always 0 |
2156 | 6.39k | auto val=static_cast<int>(input->readLong(2)); |
2157 | 6.39k | if (val) f << "g" << i << "=" << val << ","; |
2158 | 6.39k | } |
2159 | 2.13k | } |
2160 | 36.7k | else if (zone.m_type==0x14d3) { |
2161 | 4.10k | MWAWGraphicStyle::Pattern pattern; |
2162 | 4.10k | pattern.m_colors[0]=MWAWColor::white(); |
2163 | 4.10k | pattern.m_colors[1]=MWAWColor::black(); |
2164 | 4.10k | pattern.m_dim=MWAWVec2i(8,8); |
2165 | 4.10k | pattern.m_data.resize(8); |
2166 | 4.10k | for (auto &data : pattern.m_data) |
2167 | 32.8k | data=static_cast<uint8_t>(input->readULong(1)); |
2168 | 4.10k | style.m_pattern=pattern; |
2169 | 4.10k | f << pattern; |
2170 | 4.10k | } |
2171 | 56.2k | if ((vers==1 && zone.m_type!=0x10d1) || (vers>1 && zone.m_type==0x14b5)) { |
2172 | 28.7k | auto val=static_cast<int>(input->readULong(vers==1 ? 1 : 2)); // always 0 |
2173 | 28.7k | if (val==1) |
2174 | 1.37k | f << "overprint,"; |
2175 | 27.4k | else |
2176 | 27.4k | f << "g0=" << val << ","; |
2177 | 28.7k | } |
2178 | 56.2k | if (zId && m_state->m_zIdToFillStyleMap.find(zId)==m_state->m_zIdToFillStyleMap.end()) |
2179 | 9.10k | m_state->m_zIdToFillStyleMap[zId]=style; |
2180 | 56.2k | ascii().addPos(pos); |
2181 | 56.2k | ascii().addNote(f.str().c_str()); |
2182 | 56.2k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
2183 | | |
2184 | 56.2k | return true; |
2185 | 56.2k | } |
2186 | | |
2187 | | bool FreeHandParser::readLineStyle(int zId) |
2188 | 120k | { |
2189 | 120k | MWAWInputStreamPtr input = getInput(); |
2190 | 120k | libmwaw::DebugStream f; |
2191 | | |
2192 | 120k | long pos=input->tell(); |
2193 | 120k | if (!input->checkPosition(pos+13)) |
2194 | 284 | return false; |
2195 | 120k | f.str(""); |
2196 | 120k | if (zId) |
2197 | 3.43k | f << "Entries(LinStyle)[Z" << zId << "]:"; |
2198 | 116k | else |
2199 | 116k | f << "Entries(LinStyle):"; |
2200 | 120k | if (zId && m_state->getZoneType(zId)!=FreeHandParserInternal::Z_LineStyle) { |
2201 | 1.16k | MWAW_DEBUG_MSG(("FreeHandParser::readLineStyle: find unexpected zone type for zone %d\n", zId)); |
2202 | 1.16k | } |
2203 | 120k | FreeHandParserInternal::StyleHeader zone; |
2204 | 120k | int const vers=version(); |
2205 | 120k | if (!readStyleHeader(zone)) { |
2206 | 13.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2207 | 13.9k | return false; |
2208 | 13.9k | } |
2209 | 106k | f << zone; |
2210 | 106k | long endPos=0; |
2211 | 106k | bool ok=false; |
2212 | 106k | switch (zone.m_type) { |
2213 | 100k | case 0x10ce: |
2214 | 100k | ok=(vers==1); |
2215 | 100k | endPos=input->tell()+12; |
2216 | 100k | if (zone.m_size!=0x1c) f << "sz?=" << zone.m_size << ","; |
2217 | 100k | break; |
2218 | 4.44k | case 0x14b6: |
2219 | 4.44k | ok=(vers>1); |
2220 | 4.44k | endPos=input->tell()+18; |
2221 | 4.44k | if (zone.m_size!=0x22) f << "sz?=" << zone.m_size << ","; |
2222 | 4.44k | break; |
2223 | 1.29k | case 0x14d4: |
2224 | 1.29k | f << "pattern,"; |
2225 | 1.29k | ok=(vers>1); |
2226 | 1.29k | endPos=input->tell()+22; |
2227 | 1.29k | if (zone.m_size!=0x24) f << "sz?=" << zone.m_size << ","; |
2228 | 1.29k | break; |
2229 | 0 | default: |
2230 | 0 | ok=false; |
2231 | 0 | break; |
2232 | 106k | } |
2233 | 106k | if (!ok || !input->checkPosition(endPos)) { |
2234 | 435 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2235 | 435 | return false; |
2236 | 435 | } |
2237 | 105k | if (vers>1) { |
2238 | 17.1k | for (int i=0; i<2; ++i) { // 0 |
2239 | 11.4k | auto val=static_cast<int>(input->readLong(2)); |
2240 | 11.4k | if (val) |
2241 | 845 | f << "f" << i << "=" << val << ","; |
2242 | 11.4k | } |
2243 | 5.71k | } |
2244 | 105k | FreeHandParserInternal::LineStyle style; |
2245 | 105k | auto id=static_cast<int>(input->readULong(2)); |
2246 | 105k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Color)) { |
2247 | 12.4k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2248 | 12.4k | return false; |
2249 | 12.4k | } |
2250 | 93.4k | else if (id) { |
2251 | 77.1k | style.m_colorId=id; |
2252 | 77.1k | f << "color=Z" << id << ","; |
2253 | 77.1k | } |
2254 | 93.4k | if (zone.m_type==0x14d4) { |
2255 | 1.07k | MWAWGraphicStyle::Pattern pattern; |
2256 | 1.07k | pattern.m_colors[0]=MWAWColor::white(); |
2257 | 1.07k | pattern.m_colors[1]=MWAWColor::black(); |
2258 | 1.07k | pattern.m_dim=MWAWVec2i(8,8); |
2259 | 1.07k | pattern.m_data.resize(8); |
2260 | 1.07k | for (auto &data : pattern.m_data) |
2261 | 8.60k | data=static_cast<uint8_t>(input->readULong(1)); |
2262 | 1.07k | style.m_pattern=pattern; |
2263 | 1.07k | f << pattern; |
2264 | 1.07k | } |
2265 | 92.4k | else { |
2266 | 92.4k | id=static_cast<int>(input->readULong(2)); |
2267 | 92.4k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Dash)) { |
2268 | 7.32k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2269 | 7.32k | return false; |
2270 | 7.32k | } |
2271 | 85.0k | else if (id) { |
2272 | 65.6k | style.m_dashId=id; |
2273 | 65.6k | f << "dash=Z" << id << ","; |
2274 | 65.6k | } |
2275 | 92.4k | } |
2276 | | // probably cosecant(miter/2) |
2277 | 86.1k | float value=float(input->readLong(4))/65536.f; |
2278 | 86.1k | if (value<=-1||value>=1) { |
2279 | 66.0k | style.m_miterLimit=float(360./M_PI)*float(std::asin(1/value)); |
2280 | 66.0k | f << "miter[limit]=" << style.m_miterLimit << ","; |
2281 | 66.0k | } |
2282 | 20.0k | else if (value<0||value>0) { |
2283 | 11.3k | f << "##miter[limit]=2*asin(" << 1/value << "),"; |
2284 | 11.3k | } |
2285 | 8.74k | else |
2286 | 8.74k | f << "miter[limit]*,"; |
2287 | 86.1k | style.m_width=vers==1 ? float(input->readLong(2))/10.0f : float(input->readLong(4))/65536.f/10.0f; |
2288 | 86.1k | f << "width=" << style.m_width << ","; |
2289 | 86.1k | if (zone.m_type!=0x14d4) { |
2290 | 85.0k | auto val=static_cast<int>(input->readULong(1)); |
2291 | 85.0k | switch (val) { |
2292 | 18.3k | case 0: // default |
2293 | 18.3k | break; |
2294 | 5.37k | case 1: |
2295 | 5.37k | style.m_join=MWAWGraphicStyle::J_Bevel; |
2296 | 5.37k | f << "join=bevel,"; |
2297 | 5.37k | break; |
2298 | 16.6k | case 2: |
2299 | 16.6k | style.m_join=MWAWGraphicStyle::J_Round; |
2300 | 16.6k | f << "join=round,"; |
2301 | 16.6k | break; |
2302 | 44.7k | default: |
2303 | 44.7k | MWAW_DEBUG_MSG(("FreeHandParser::readLineStyle: find unknown join\n")); |
2304 | 44.7k | f << "#join=" << val << ","; |
2305 | 85.0k | } |
2306 | 85.0k | val=static_cast<int>(input->readULong(1)); |
2307 | 85.0k | switch (val) { |
2308 | 20.7k | case 0: // default |
2309 | 20.7k | break; |
2310 | 16.0k | case 1: |
2311 | 16.0k | style.m_cap=MWAWGraphicStyle::C_Round; |
2312 | 16.0k | f << "cap=round,"; |
2313 | 16.0k | break; |
2314 | 6.27k | case 2: |
2315 | 6.27k | style.m_cap=MWAWGraphicStyle::C_Square; |
2316 | 6.27k | f << "cap=square,"; |
2317 | 6.27k | break; |
2318 | 42.0k | default: |
2319 | 42.0k | MWAW_DEBUG_MSG(("FreeHandParser::readLineStyle: find unknown cap\n")); |
2320 | 42.0k | f << "#cap=" << val << ","; |
2321 | 85.0k | } |
2322 | 85.0k | } |
2323 | 86.1k | if (zId && m_state->m_zIdToLineStyleMap.find(zId)==m_state->m_zIdToLineStyleMap.end()) |
2324 | 3.32k | m_state->m_zIdToLineStyleMap[zId]=style; |
2325 | 86.1k | ascii().addPos(pos); |
2326 | 86.1k | ascii().addNote(f.str().c_str()); |
2327 | 86.1k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
2328 | | |
2329 | 86.1k | return true; |
2330 | 86.1k | } |
2331 | | |
2332 | | bool FreeHandParser::readPostscriptStyle(int zId) |
2333 | 74.5k | { |
2334 | 74.5k | MWAWInputStreamPtr input = getInput(); |
2335 | 74.5k | libmwaw::DebugStream f; |
2336 | | |
2337 | 74.5k | long pos=input->tell(); |
2338 | 74.5k | if (!input->checkPosition(pos+12)) |
2339 | 123 | return false; |
2340 | 74.4k | f.str(""); |
2341 | 74.4k | if (zId) |
2342 | 2.37k | f << "Entries(Postscript)[Z" << zId << "]:"; |
2343 | 72.0k | else |
2344 | 72.0k | f << "Entries(Postscript):"; |
2345 | 74.4k | if (zId) { |
2346 | 2.37k | auto type=m_state->getZoneType(zId); |
2347 | 2.37k | if (type!=FreeHandParserInternal::Z_Fill && type!=FreeHandParserInternal::Z_LineStyle) { |
2348 | 504 | MWAW_DEBUG_MSG(("FreeHandParser::readPostscriptStyle: find unexpected zone type for zone %d\n", zId)); |
2349 | 504 | } |
2350 | 2.37k | } |
2351 | 74.4k | FreeHandParserInternal::StyleHeader zone; |
2352 | 74.4k | if (!readStyleHeader(zone)) { |
2353 | 5.00k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2354 | 5.00k | return false; |
2355 | 5.00k | } |
2356 | 69.3k | f << zone; |
2357 | 69.3k | long endPos; |
2358 | 69.3k | int sSz; |
2359 | 69.3k | if (version()==1) { |
2360 | 64.2k | if (zone.m_type!=0x10cf) { |
2361 | 0 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2362 | 0 | return false; |
2363 | 0 | } |
2364 | 64.2k | if (zone.m_size!=0x12) f << "sz?=" << zone.m_size << ","; |
2365 | 64.2k | sSz=static_cast<int>(input->readULong(1)); |
2366 | 64.2k | endPos=input->tell()+sSz; |
2367 | 64.2k | } |
2368 | 5.11k | else { |
2369 | 5.11k | bool ok=true; |
2370 | 5.11k | if (zone.m_type==0x14c9) |
2371 | 2.57k | f << "surf,"; |
2372 | 2.53k | else if (zone.m_type==0x14ca) |
2373 | 2.53k | f << "line,"; |
2374 | 0 | else |
2375 | 0 | ok=false; |
2376 | 5.11k | if (!ok || zone.m_size<16) { |
2377 | 164 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2378 | 164 | return false; |
2379 | 164 | } |
2380 | 14.8k | for (int i=0; i<2; ++i) { // always 0? |
2381 | 9.89k | auto val=static_cast<int>(input->readLong(2)); |
2382 | 9.89k | if (val) f << "f" << i << "=" << val << ","; |
2383 | 9.89k | } |
2384 | 4.94k | endPos=pos+zone.m_size-4; |
2385 | 4.94k | sSz=int(zone.m_size-16); |
2386 | 4.94k | } |
2387 | 69.2k | if (!input->checkPosition(endPos)) { |
2388 | 414 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2389 | 414 | return false; |
2390 | 414 | } |
2391 | 68.8k | std::string text; |
2392 | 1.01M | for (int i=0; i<sSz; ++i) text+=char(input->readULong(1)); |
2393 | 68.8k | if (!text.empty()) |
2394 | 31.1k | f << "ps=\"" << text << "\","; |
2395 | 68.8k | if (zId && m_state->m_zIdToPostscriptMap.find(zId)==m_state->m_zIdToPostscriptMap.end()) |
2396 | 2.32k | m_state->m_zIdToPostscriptMap[zId]=text; |
2397 | 68.8k | ascii().addPos(pos); |
2398 | 68.8k | ascii().addNote(f.str().c_str()); |
2399 | 68.8k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
2400 | | |
2401 | 68.8k | return true; |
2402 | 69.2k | } |
2403 | | |
2404 | | bool FreeHandParser::readBackgroundPicture(int zId) |
2405 | 48.5k | { |
2406 | 48.5k | MWAWInputStreamPtr input = getInput(); |
2407 | 48.5k | libmwaw::DebugStream f; |
2408 | | |
2409 | 48.5k | long pos=input->tell(); |
2410 | 48.5k | FreeHandParserInternal::ShapeHeader shape; |
2411 | 48.5k | if (!readShapeHeader(shape) || shape.m_type!=0x1007 || !input->checkPosition(input->tell()+32)) { |
2412 | 13.5k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2413 | 13.5k | return false; |
2414 | 13.5k | } |
2415 | 34.9k | FreeHandParserInternal::Shape res; |
2416 | 34.9k | res.m_type=FreeHandParserInternal::Shape::BackgroundPicture; |
2417 | 34.9k | res.m_layerId=shape.m_layerId; |
2418 | 34.9k | if (zId) |
2419 | 94 | f << "Entries(BackgroundPicture)[Z" << zId << "]:" << shape; |
2420 | 34.8k | else |
2421 | 34.8k | f << "Entries(BackgroundPicture):" << shape; |
2422 | 524k | for (int i=0; i<14; ++i) { // f1=29|39, f2=1, f8=1, f10=0|-5, f12=109|113|118 |
2423 | 489k | auto val=static_cast<int>(input->readLong(2)); |
2424 | 489k | if (val) f << "f" << i << "=" << val << ","; |
2425 | 489k | } |
2426 | 34.9k | auto picSize=long(input->readLong(4)); |
2427 | 34.9k | res.m_picture.setBegin(input->tell()); |
2428 | 34.9k | res.m_picture.setLength(picSize); |
2429 | 34.9k | if (picSize<0 || !input->checkPosition(res.m_picture.end())) { |
2430 | 26.3k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2431 | 26.3k | return false; |
2432 | 26.3k | } |
2433 | 8.64k | ascii().skipZone(res.m_picture.begin(), res.m_picture.end()-1); |
2434 | 8.64k | input->seek(picSize, librevenge::RVNG_SEEK_CUR); |
2435 | 8.64k | ascii().addPos(pos); |
2436 | 8.64k | ascii().addNote(f.str().c_str()); |
2437 | | |
2438 | 8.64k | if (zId && m_state->m_zIdToShapeMap.find(zId)==m_state->m_zIdToShapeMap.end()) |
2439 | 29 | m_state->m_zIdToShapeMap.insert(std::map<int, FreeHandParserInternal::Shape>::value_type(zId,res)); |
2440 | 8.64k | return true; |
2441 | 34.9k | } |
2442 | | |
2443 | | bool FreeHandParser::readPictureZone(int zId) |
2444 | 117k | { |
2445 | 117k | MWAWInputStreamPtr input = getInput(); |
2446 | 117k | libmwaw::DebugStream f; |
2447 | | |
2448 | 117k | long pos=input->tell(); |
2449 | 117k | FreeHandParserInternal::ShapeHeader shape; |
2450 | 117k | if (!readShapeHeader(shape) || shape.m_type!=0x13f8 || !input->checkPosition(input->tell()+58)) { |
2451 | 1.56k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2452 | 1.56k | return false; |
2453 | 1.56k | } |
2454 | 115k | long endPos=input->tell()+58; |
2455 | 115k | FreeHandParserInternal::Shape res; |
2456 | 115k | res.m_type=FreeHandParserInternal::Shape::Picture; |
2457 | 115k | res.m_layerId=shape.m_layerId; |
2458 | 115k | if (zId) |
2459 | 248 | f << "Entries(Picture)[Z" << zId << "]:" << shape; |
2460 | 115k | else |
2461 | 115k | f << "Entries(Picture):" << shape; |
2462 | 115k | if (zId && m_state->getZoneType(zId)!=FreeHandParserInternal::Z_Shape) { |
2463 | 245 | MWAW_DEBUG_MSG(("FreeHandParser::readPictureZone: find unexpected zone type for zone %d\n", zId)); |
2464 | 245 | } |
2465 | 290k | for (int i=0; i<2; ++i) { |
2466 | 215k | auto id=static_cast<int>(input->readULong(2)); |
2467 | 215k | if (!id) continue; |
2468 | 187k | if (!m_state->addZoneId(id, i==0 ? FreeHandParserInternal::Z_Picture : FreeHandParserInternal::Z_PictureName)) { |
2469 | 40.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2470 | 40.9k | return false; |
2471 | 40.9k | } |
2472 | 146k | if (i==0) { |
2473 | 84.2k | res.m_dataId=id; |
2474 | 84.2k | f << "data=Z" << id << ","; |
2475 | 84.2k | } |
2476 | 61.9k | else |
2477 | 61.9k | f << "name=Z" << id << ","; |
2478 | 146k | } |
2479 | 74.9k | auto val=static_cast<int>(input->readLong(2)); // 0 |
2480 | 74.9k | if (val) f << "f0=" << val << ","; |
2481 | 74.9k | float dim[6]; |
2482 | 224k | for (int i=0; i<2; ++i) dim[i]=float(input->readLong(2))/10.f; |
2483 | 74.9k | f << "dim=" << MWAWVec2f(dim[1],dim[0]) << ","; |
2484 | | // checkme: why are the coord inverted ? |
2485 | 74.9k | res.m_box=MWAWBox2f(MWAWVec2f(0,0), MWAWVec2f(dim[1],dim[0])); |
2486 | 224k | for (int i=0; i<2; ++i) { // 0? |
2487 | 149k | val=static_cast<int>(input->readLong(2)); // 0 |
2488 | 149k | if (val) f << "f" << i+1 << "=" << val << ","; |
2489 | 149k | } |
2490 | 74.9k | f << "flags=" << std::hex << input->readULong(2) << std::dec << ","; |
2491 | 74.9k | f << "rot=["; |
2492 | 374k | for (int i=0; i<4; ++i) { |
2493 | 299k | dim[i]=float(input->readLong(4))/65536.f; |
2494 | 299k | f << dim[i] << ","; |
2495 | 299k | } |
2496 | 74.9k | f << "],"; |
2497 | 74.9k | f << "trans=["; |
2498 | 224k | for (int i=0; i<2; ++i) { |
2499 | 149k | dim[i+4]=float(input->readLong(4))/65536.f/10.f; |
2500 | 149k | f << dim[i+4] << ","; |
2501 | 149k | } |
2502 | 74.9k | f << "],"; |
2503 | 74.9k | res.m_transformation=MWAWTransformation(MWAWVec3f(dim[0],dim[2],dim[4]),MWAWVec3f(dim[1],dim[3],dim[5])); |
2504 | 74.9k | auto id=static_cast<int>(input->readULong(2)); |
2505 | 74.9k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Color)) { |
2506 | 19.1k | MWAW_DEBUG_MSG(("FreeHandParser::readPictureZone: find unexpected colorId\n")); |
2507 | 19.1k | f << "###colorId,"; |
2508 | 19.1k | } |
2509 | 55.7k | else if (id) |
2510 | 30.4k | f << "color=Z" << id << ","; |
2511 | 224k | for (int i=0; i<2; ++i) { |
2512 | 149k | int iDim[4]; |
2513 | 599k | for (auto &d : iDim) d=static_cast<int>(input->readLong(2)); |
2514 | 149k | f << "box" << i << "=" << MWAWBox2i(MWAWVec2i(iDim[0],iDim[1]),MWAWVec2i(iDim[2],iDim[3])) << ","; |
2515 | 149k | } |
2516 | 74.9k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
2517 | 74.9k | ascii().addPos(pos); |
2518 | 74.9k | ascii().addNote(f.str().c_str()); |
2519 | | |
2520 | 74.9k | if (zId && m_state->m_zIdToShapeMap.find(zId)==m_state->m_zIdToShapeMap.end()) |
2521 | 237 | m_state->m_zIdToShapeMap.insert(std::map<int, FreeHandParserInternal::Shape>::value_type(zId,res)); |
2522 | 74.9k | return true; |
2523 | 115k | } |
2524 | | |
2525 | | bool FreeHandParser::readShape(int zId) |
2526 | 160k | { |
2527 | 160k | MWAWInputStreamPtr input = getInput(); |
2528 | 160k | libmwaw::DebugStream f; |
2529 | | |
2530 | 160k | long pos=input->tell(); |
2531 | 160k | FreeHandParserInternal::ShapeHeader shape; |
2532 | 160k | if (!readShapeHeader(shape)) { |
2533 | 26.3k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2534 | 26.3k | return false; |
2535 | 26.3k | } |
2536 | 133k | bool canHaveMatrix=true, hasDimension=true; |
2537 | 133k | int dataSize=-1; |
2538 | 133k | FreeHandParserInternal::Shape res; |
2539 | 133k | res.m_layerId=shape.m_layerId; |
2540 | 133k | const int vers=version(); |
2541 | 133k | switch (shape.m_type) { |
2542 | 16.3k | case 0x1131: |
2543 | 26.1k | case 0x1519: |
2544 | 26.1k | if (zId) |
2545 | 8.91k | f << "Entries(Rectangle)[Z" << zId << "]:" << shape; |
2546 | 17.2k | else |
2547 | 17.2k | f << "Entries(Rectangle):" << shape; |
2548 | 26.1k | dataSize=4; |
2549 | 26.1k | res.m_type=FreeHandParserInternal::Shape::Rectangle; |
2550 | 26.1k | break; |
2551 | 38.6k | case 0x1132: |
2552 | 43.4k | case 0x151a: |
2553 | 43.4k | if (zId) |
2554 | 4.83k | f << "Entries(Circle)[Z" << zId << "]:" << shape; |
2555 | 38.5k | else |
2556 | 38.5k | f << "Entries(Circle):" << shape; |
2557 | 43.4k | dataSize=0; |
2558 | 43.4k | res.m_type=FreeHandParserInternal::Shape::Ellipse; |
2559 | 43.4k | break; |
2560 | 16.5k | case 0x1134: |
2561 | 48.1k | case 0x151c: |
2562 | 48.1k | if (zId) |
2563 | 1.50k | f << "Entries(Spline)[Z" << zId << "]:" << shape; |
2564 | 46.6k | else |
2565 | 46.6k | f << "Entries(Spline):" << shape; |
2566 | 48.1k | dataSize=4; |
2567 | 48.1k | hasDimension=canHaveMatrix=false; |
2568 | 48.1k | res.m_type=FreeHandParserInternal::Shape::Path; |
2569 | 48.1k | break; |
2570 | 8.23k | case 0x1135: |
2571 | 16.0k | case 0x151d: |
2572 | 16.0k | if (zId) |
2573 | 4.33k | f << "Entries(Line)[Z" << zId << "]:" << shape; |
2574 | 11.7k | else |
2575 | 11.7k | f << "Entries(Line):" << shape; |
2576 | 16.0k | dataSize=0; |
2577 | 16.0k | canHaveMatrix=false; |
2578 | 16.0k | res.m_type=FreeHandParserInternal::Shape::Line; |
2579 | 16.0k | break; |
2580 | 0 | default: |
2581 | 0 | break; |
2582 | 133k | } |
2583 | 133k | if (dataSize<0 || !input->checkPosition(input->tell()+4+(vers>1 ? 6 : 0)+(hasDimension ? 8 : 0)+(canHaveMatrix ? 4 : 0)+dataSize)) { |
2584 | 1.27k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2585 | 1.27k | return false; |
2586 | 1.27k | } |
2587 | 132k | f << "sz?=" << shape.m_size << ","; |
2588 | 132k | if (zId && m_state->getZoneType(zId)!=FreeHandParserInternal::Z_Shape) { |
2589 | 2.67k | MWAW_DEBUG_MSG(("FreeHandParser::readShape: find unexpected zone type for zone %d\n", zId)); |
2590 | 2.67k | } |
2591 | 132k | if (vers>1) { |
2592 | 53.8k | auto id=static_cast<int>(input->readULong(2)); |
2593 | 53.8k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Group)) { |
2594 | 6.55k | MWAW_DEBUG_MSG(("FreeHandParser::readShapeHeader: find unexpected group id\n")); |
2595 | 6.55k | f << "###groupId,"; |
2596 | 6.55k | } |
2597 | 47.3k | else if (id) { |
2598 | 28.7k | f << "group=Z" << id << ","; |
2599 | 28.7k | res.m_childs.push_back(id); |
2600 | 28.7k | } |
2601 | 53.8k | } |
2602 | 132k | auto id=static_cast<int>(input->readLong(2)); // always 0? |
2603 | 132k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Fill)) { |
2604 | 20.1k | MWAW_DEBUG_MSG(("FreeHandParser::readShape: find a bad color\n")); |
2605 | 20.1k | f << "###"; |
2606 | 20.1k | } |
2607 | 132k | if (id) f << "fill=Z" << id << ","; |
2608 | 132k | res.m_fillId=id; |
2609 | 132k | id=static_cast<int>(input->readULong(2)); |
2610 | 132k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_LineStyle)) { |
2611 | 19.8k | MWAW_DEBUG_MSG(("FreeHandParser::readShape: find a bad style\n")); |
2612 | 19.8k | f << "###"; |
2613 | 19.8k | } |
2614 | 132k | if (id) f << "line[style]=Z" << id << ","; |
2615 | 132k | res.m_lineId=id; |
2616 | 132k | if (vers>1) { |
2617 | 161k | for (int i=0; i<2; ++i) { // always 0? |
2618 | 107k | auto val=static_cast<int>(input->readULong(2)); |
2619 | 107k | if (val) f << "f" << i << "=" << val << ","; |
2620 | 107k | } |
2621 | 53.8k | } |
2622 | 132k | if (hasDimension) { |
2623 | 84.6k | float dim[4]; |
2624 | 338k | for (auto &d : dim) d=float(input->readLong(2))/10.f; |
2625 | 84.6k | res.m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]),MWAWVec2f(dim[2],dim[3])); |
2626 | 84.6k | f << "rect=" << res.m_box << ","; |
2627 | 84.6k | } |
2628 | 132k | int dSz=canHaveMatrix ? static_cast<int>(input->readULong(4)) : 0; |
2629 | 132k | if (dSz<0 || !input->checkPosition(input->tell()+dSz+dataSize)) { |
2630 | 42.3k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2631 | 42.3k | return false; |
2632 | 42.3k | } |
2633 | 90.2k | if (dSz==0x1a) { |
2634 | 2.05k | f << "flags=" << std::hex << input->readULong(2) << std::dec << ","; |
2635 | 2.05k | float dim[6]; |
2636 | 2.05k | f << "rot=["; |
2637 | 10.2k | for (int i=0; i<4; ++i) { |
2638 | 8.20k | dim[i]=float(input->readLong(4))/65536.f; |
2639 | 8.20k | f << dim[i] << ","; |
2640 | 8.20k | } |
2641 | 2.05k | f << "],"; |
2642 | 2.05k | f << "trans=["; |
2643 | 6.15k | for (int i=0; i<2; ++i) { |
2644 | 4.10k | dim[i+4]=float(input->readLong(4))/65536.f/10.f; |
2645 | 4.10k | f << dim[i+4] << ","; |
2646 | 4.10k | } |
2647 | 2.05k | f << "],"; |
2648 | 2.05k | res.m_transformation=MWAWTransformation(MWAWVec3f(dim[0],dim[2],dim[4]),MWAWVec3f(dim[1],dim[3],dim[5])); |
2649 | 2.05k | } |
2650 | 88.1k | else if (dSz) { |
2651 | 5.11k | MWAW_DEBUG_MSG(("FreeHandParser::readShape: find unknown matrix size\n")); |
2652 | 5.11k | f << "###matrix,"; |
2653 | 5.11k | input->seek(dSz, librevenge::RVNG_SEEK_CUR); |
2654 | 5.11k | } |
2655 | 90.2k | if (shape.m_type==0x1131 || shape.m_type==0x1519) { |
2656 | 16.5k | float dim[2]; |
2657 | 33.0k | for (auto &d : dim) d=float(input->readLong(2))/10.f; |
2658 | 16.5k | res.m_corner=MWAWVec2f(dim[0],dim[1]); |
2659 | 16.5k | if (res.m_corner!=MWAWVec2f(0,0)) |
2660 | 6.29k | f << "corner=" << res.m_corner << ","; |
2661 | 16.5k | } |
2662 | 90.2k | if (shape.m_type==0x1134 || shape.m_type==0x151c) { |
2663 | 47.8k | auto val=static_cast<int>(input->readULong(2)); |
2664 | 47.8k | if (val&1) { |
2665 | 16.4k | res.m_closed=true; |
2666 | 16.4k | f << "closed,"; |
2667 | 16.4k | } |
2668 | 47.8k | if (val&2) { |
2669 | 21.2k | res.m_evenOdd=true; |
2670 | 21.2k | f << "even/odd,"; |
2671 | 21.2k | } |
2672 | 47.8k | val &= 0xFFFC; |
2673 | | // find also 4 |
2674 | 47.8k | if (val) f << "fl=" << std::hex << val << std::dec << ","; |
2675 | 47.8k | auto nPt=static_cast<int>(input->readULong(2)); |
2676 | 47.8k | f << "N=" << nPt << ","; |
2677 | 47.8k | if (!input->checkPosition(input->tell()+16*nPt)) { |
2678 | 24.1k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2679 | 24.1k | return false; |
2680 | 24.1k | } |
2681 | 23.7k | ascii().addPos(pos); |
2682 | 23.7k | ascii().addNote(f.str().c_str()); |
2683 | 526k | for (int i=0; i<nPt; ++i) { |
2684 | 503k | pos=input->tell(); |
2685 | 503k | f.str(""); |
2686 | 503k | f << "Spline-" << i << ":"; |
2687 | 503k | val=static_cast<int>(input->readULong(2)); |
2688 | 503k | switch (val) { |
2689 | 190k | case 0: // corner |
2690 | 190k | break; |
2691 | 5.42k | case 1: |
2692 | 5.42k | f << "connector,"; |
2693 | 5.42k | break; |
2694 | 11.7k | case 2: |
2695 | 11.7k | f << "curve,"; |
2696 | 11.7k | break; |
2697 | 295k | default: |
2698 | | // find also 0xf0 |
2699 | 295k | MWAW_DEBUG_MSG(("FreeHandParser::readShape: find unknown point type\n")); |
2700 | 295k | f << "#type=" << val << ","; |
2701 | 503k | } |
2702 | 503k | val=static_cast<int>(input->readULong(2)); |
2703 | 503k | if (val&0x100) f << "no[autoCurvature],"; |
2704 | 503k | val &= 0xFEFF; |
2705 | | // find unknow [01][4|9|b] |
2706 | 503k | if (val) f << "fl=" << std::hex << val << std::dec << ","; |
2707 | 503k | MWAWVec2f coord[3]; |
2708 | 1.50M | for (auto &pt : coord) { |
2709 | 1.50M | float dim[2]; |
2710 | 3.01M | for (auto &d : dim) d=float(input->readLong(2))/10.f; |
2711 | 1.50M | pt=MWAWVec2f(dim[0], dim[1]); |
2712 | 1.50M | res.m_vertices.push_back(pt); |
2713 | 1.50M | } |
2714 | 503k | if (coord[0]==coord[1] && coord[0]==coord[2]) |
2715 | 151k | f << coord[0] << ","; |
2716 | 351k | else |
2717 | 351k | f << "pts=[" << coord[0] << "," << coord[1] << "," << coord[2] << "],"; |
2718 | 503k | ascii().addPos(pos); |
2719 | 503k | ascii().addNote(f.str().c_str()); |
2720 | 503k | } |
2721 | 23.7k | } |
2722 | 42.3k | else { |
2723 | 42.3k | ascii().addPos(pos); |
2724 | 42.3k | ascii().addNote(f.str().c_str()); |
2725 | 42.3k | } |
2726 | 66.0k | if (zId && m_state->m_zIdToShapeMap.find(zId)==m_state->m_zIdToShapeMap.end()) |
2727 | 19.2k | m_state->m_zIdToShapeMap.insert(std::map<int, FreeHandParserInternal::Shape>::value_type(zId,res)); |
2728 | 66.0k | return true; |
2729 | 90.2k | } |
2730 | | |
2731 | | bool FreeHandParser::readTextboxV1(int zId) |
2732 | 95.9k | { |
2733 | 95.9k | MWAWInputStreamPtr input = getInput(); |
2734 | 95.9k | libmwaw::DebugStream f; |
2735 | | |
2736 | 95.9k | long pos=input->tell(); |
2737 | 95.9k | FreeHandParserInternal::ShapeHeader shape; |
2738 | 95.9k | if (!readShapeHeader(shape) || shape.m_type!=0x1006 || !input->checkPosition(input->tell()+4+8+54)) { |
2739 | 34.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2740 | 34.9k | return false; |
2741 | 34.9k | } |
2742 | 61.0k | if (zId) |
2743 | 2.71k | f << "Entries(Textbox)[Z" << zId << "]:" << shape; |
2744 | 58.2k | else |
2745 | 58.2k | f << "Entries(Textbox):" << shape; |
2746 | 61.0k | FreeHandParserInternal::Textbox textbox(zId); |
2747 | 61.0k | textbox.m_layerId=shape.m_layerId; |
2748 | 61.0k | f << "sz?=" << shape.m_size << ","; |
2749 | 61.0k | if (zId && m_state->getZoneType(zId)!=FreeHandParserInternal::Z_Shape) { |
2750 | 656 | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV1: find unexpected zone type for zone %d\n", zId)); |
2751 | 656 | } |
2752 | 61.0k | auto val=static_cast<int>(input->readLong(2)); // always 0? |
2753 | 61.0k | if (val) f << "f0=" << val << ","; |
2754 | 61.0k | auto nbPt=static_cast<int>(input->readULong(2)); // nbPt=4*textSz |
2755 | 61.0k | f << "N=" << nbPt << ","; |
2756 | 61.0k | long actPos=input->tell(); |
2757 | 61.0k | if ((nbPt%2) || !input->checkPosition(actPos+3*(nbPt/2)+8+54)) { |
2758 | 25.2k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2759 | 25.2k | return false; |
2760 | 25.2k | } |
2761 | | // probably nbPt/2 float (size of each char)+ nbPt/2 bytes (flag?) |
2762 | 35.7k | ascii().skipZone(actPos, actPos+3*(nbPt/2)-1); |
2763 | | |
2764 | 35.7k | actPos+=3*(nbPt/2); |
2765 | 35.7k | ascii().addPos(pos); |
2766 | 35.7k | ascii().addNote(f.str().c_str()); |
2767 | | |
2768 | 35.7k | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
2769 | 35.7k | f.str(""); |
2770 | 35.7k | f << "Textbox-A:"; |
2771 | 143k | for (int i=0; i<3; ++i) { // f0=0|2|-82|-123|-225, f1=0|-41|-82|-123|-151, f2=0 |
2772 | 107k | val=static_cast<int>(input->readLong(2)); |
2773 | 107k | if (val) f << "f" << i << "=" << val << ","; |
2774 | 107k | } |
2775 | 35.7k | auto sSz=static_cast<int>(input->readULong(2)); |
2776 | 35.7k | if (!input->checkPosition(input->tell()+sSz+54)) { |
2777 | 6.76k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2778 | 6.76k | return false; |
2779 | 6.76k | } |
2780 | 29.0k | f << "text[sz]=" << sSz << ","; |
2781 | 29.0k | ascii().addPos(actPos); |
2782 | 29.0k | ascii().addNote(f.str().c_str()); |
2783 | | |
2784 | 29.0k | textbox.m_text.setBegin(input->tell()); |
2785 | 29.0k | textbox.m_text.setLength(sSz); |
2786 | 29.0k | input->seek(textbox.m_text.end(), librevenge::RVNG_SEEK_SET); |
2787 | | |
2788 | 29.0k | actPos=input->tell(); |
2789 | 29.0k | f.str(""); |
2790 | 29.0k | f << "Textbox-B:"; |
2791 | 29.0k | float dim[6]; |
2792 | 145k | for (int i=0; i<4; ++i) dim[i]=float(input->readLong(2))/10.f; |
2793 | 29.0k | textbox.m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]),MWAWVec2f(dim[2],dim[3])); |
2794 | 29.0k | f << "dim=" << textbox.m_box << ","; |
2795 | 29.0k | f << "flags=" << std::hex << input->readULong(2) << std::dec << ","; |
2796 | 29.0k | f << "rot=["; |
2797 | 145k | for (int i=0; i<4; ++i) { |
2798 | 116k | dim[i]=float(input->readLong(4))/65536.f; |
2799 | 116k | f << dim[i] << ","; |
2800 | 116k | } |
2801 | 29.0k | f << "],"; |
2802 | 29.0k | f << "trans=["; |
2803 | 87.0k | for (int i=0; i<2; ++i) { |
2804 | 58.0k | dim[i+4]=float(input->readLong(4))/65536.f/10.f; |
2805 | 58.0k | f << dim[i+4] << ","; |
2806 | 58.0k | } |
2807 | 29.0k | f << "],"; |
2808 | 29.0k | textbox.m_transformation=MWAWTransformation(MWAWVec3f(dim[0],dim[2],dim[4]),MWAWVec3f(dim[1],dim[3],dim[5])); |
2809 | 29.0k | f << "spacing=["; // letter and word |
2810 | 87.0k | for (int i=0; i<2; ++i) { |
2811 | 58.0k | dim[i]=float(input->readLong(4))/65536.f/10.f; |
2812 | 58.0k | f << dim[i] << ","; |
2813 | 58.0k | } |
2814 | 29.0k | f << "],"; |
2815 | 29.0k | textbox.m_spacings=MWAWVec2f(dim[0],dim[1]); |
2816 | 29.0k | f << "scaling=["; |
2817 | 87.0k | for (int i=0; i<2; ++i) { |
2818 | 58.0k | dim[i]=float(input->readLong(4))/65536.f; |
2819 | 58.0k | f << dim[i] << ","; |
2820 | 58.0k | } |
2821 | 29.0k | f << "],"; |
2822 | 29.0k | textbox.m_scalings=MWAWVec2f(dim[0],dim[1]); |
2823 | 29.0k | val=static_cast<int>(input->readLong(1)); // 0|1|2 |
2824 | 29.0k | if (val) f << "f0=" << val << ","; |
2825 | 29.0k | val=static_cast<int>(input->readLong(1)); |
2826 | 29.0k | switch (val) { |
2827 | 11.2k | case 0: // left |
2828 | 11.2k | break; |
2829 | 1.25k | case 1: |
2830 | 1.25k | f << "right,"; |
2831 | 1.25k | textbox.m_justify=MWAWParagraph::JustificationRight; |
2832 | 1.25k | break; |
2833 | 6.01k | case 2: |
2834 | 6.01k | f << "center,"; |
2835 | 6.01k | textbox.m_justify=MWAWParagraph::JustificationCenter; |
2836 | 6.01k | break; |
2837 | 407 | case 3: |
2838 | 407 | f << "justify=all,"; |
2839 | 407 | textbox.m_justify=MWAWParagraph::JustificationFull; |
2840 | 407 | break; |
2841 | 10.0k | default: |
2842 | 10.0k | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV1: find unexpected align\n")); |
2843 | 10.0k | f << "###align=" << val << ","; |
2844 | 10.0k | break; |
2845 | 29.0k | } |
2846 | 29.0k | auto nPLC=static_cast<int>(input->readULong(2)); |
2847 | 29.0k | f << "NPLC=" << nPLC << ","; |
2848 | 29.0k | if (!input->checkPosition(input->tell()+18*nPLC)) { |
2849 | 16.4k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2850 | 16.4k | return false; |
2851 | 16.4k | } |
2852 | 12.5k | ascii().addPos(actPos); |
2853 | 12.5k | ascii().addNote(f.str().c_str()); |
2854 | 1.14M | for (int plc=0; plc<nPLC; ++plc) { |
2855 | 1.13M | actPos=input->tell(); |
2856 | 1.13M | f.str(""); |
2857 | 1.13M | f << "Textbox-PLC" << plc << ":"; |
2858 | 1.13M | FreeHandParserInternal::Font font; |
2859 | 1.13M | if (plc+1!=nPLC) { |
2860 | 1.12M | auto id=static_cast<int>(input->readULong(2)); |
2861 | 1.12M | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_String)) { |
2862 | 250k | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV1: find bad font name\n")); |
2863 | 250k | f << "###"; |
2864 | 250k | } |
2865 | 1.12M | font.m_nameId=id; |
2866 | 1.12M | if (id) |
2867 | 830k | f << "font[name]=Z" << id << ","; |
2868 | 1.12M | id=static_cast<int>(input->readULong(2)); |
2869 | 1.12M | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Color)) { |
2870 | 344k | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV1: find bad color\n")); |
2871 | 344k | f << "###"; |
2872 | 344k | } |
2873 | 1.12M | if (id) |
2874 | 831k | f << "color=Z" << id << ","; |
2875 | 1.12M | font.m_colorId=id; |
2876 | 1.12M | float sz=float(input->readLong(4))/65536.f; |
2877 | 1.12M | font.m_font.setSize(sz); |
2878 | 1.12M | f << "font[sz]=" << sz << ","; |
2879 | 1.12M | val=static_cast<int>(input->readLong(4)); |
2880 | 1.12M | switch (val) { // useme |
2881 | 3.65k | case -2: // solid |
2882 | 3.65k | break; |
2883 | 20.0k | case -1: |
2884 | 20.0k | f << "leading=auto,"; |
2885 | 20.0k | break; |
2886 | 1.10M | default: |
2887 | 1.10M | f << "leading=" << float(val)/65536.f << ","; |
2888 | 1.12M | } |
2889 | 1.12M | } |
2890 | 8.29k | else |
2891 | 8.29k | input->seek(12, librevenge::RVNG_SEEK_CUR); |
2892 | 1.13M | auto cPos=static_cast<int>(input->readULong(2)); |
2893 | 1.13M | f << "pos=" << cPos << ","; |
2894 | 1.13M | uint32_t flags=0; |
2895 | 1.13M | val=static_cast<int>(input->readULong(2)); |
2896 | 1.13M | if (val & 1) { |
2897 | 367k | flags |= MWAWFont::boldBit; |
2898 | 367k | f << "bold,"; |
2899 | 367k | } |
2900 | 1.13M | if (val & 2) { |
2901 | 305k | flags |= MWAWFont::italicBit; |
2902 | 305k | f << "italic,"; |
2903 | 305k | } |
2904 | 1.13M | val &= 0xFFFC; |
2905 | 1.13M | if (val && plc+1!=nPLC) { |
2906 | 794k | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV1: find unknown font flag1\n")); |
2907 | 794k | f << "##flag1=" << std::hex << val << std::dec << ","; |
2908 | 794k | } |
2909 | 1.13M | val=static_cast<int>(input->readULong(2)); |
2910 | 1.13M | switch (val) { |
2911 | 17.9k | case 1: // solid |
2912 | 17.9k | break; |
2913 | 8.84k | case 2: |
2914 | 8.84k | flags |= MWAWFont::boldBit; |
2915 | 8.84k | f << "heavy,"; |
2916 | 8.84k | break; |
2917 | 9.40k | case 3: |
2918 | 9.40k | flags |= MWAWFont::italicBit; |
2919 | 9.40k | f << "oblique,"; |
2920 | 9.40k | break; |
2921 | 6.65k | case 4: |
2922 | 6.65k | flags |= MWAWFont::outlineBit; |
2923 | 6.65k | f << "outline,"; |
2924 | 6.65k | break; |
2925 | 7.09k | case 5: |
2926 | 7.09k | flags |= MWAWFont::shadowBit; |
2927 | 7.09k | f << "shadow,"; |
2928 | 7.09k | break; |
2929 | 1.08M | default: |
2930 | 1.08M | if (plc+1==nPLC) break; |
2931 | 1.07M | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV1: find unknown font flag2\n")); |
2932 | 1.07M | f << "##flag2=" << val << ","; |
2933 | 1.07M | break; |
2934 | 1.13M | } |
2935 | 1.13M | font.m_font.setFlags(flags); |
2936 | 1.13M | textbox.m_posToFontMap[cPos]=font; |
2937 | 1.13M | ascii().addPos(actPos); |
2938 | 1.13M | ascii().addNote(f.str().c_str()); |
2939 | 1.13M | } |
2940 | 12.5k | if (zId && m_state->m_zIdToTextboxMap.find(zId)==m_state->m_zIdToTextboxMap.end()) |
2941 | 2.49k | m_state->m_zIdToTextboxMap.insert(std::map<int, FreeHandParserInternal::Textbox>::value_type(zId,textbox)); |
2942 | | |
2943 | 12.5k | return true; |
2944 | 12.5k | } |
2945 | | |
2946 | | bool FreeHandParser::readTextboxV2(int zId) |
2947 | 76.0k | { |
2948 | 76.0k | MWAWInputStreamPtr input = getInput(); |
2949 | 76.0k | libmwaw::DebugStream f; |
2950 | | |
2951 | 76.0k | long pos=input->tell(); |
2952 | 76.0k | FreeHandParserInternal::ShapeHeader shape; |
2953 | 76.0k | if (!readShapeHeader(shape) || shape.m_type!=0x13ee || !input->checkPosition(input->tell()+66)) { |
2954 | 2.97k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2955 | 2.97k | return false; |
2956 | 2.97k | } |
2957 | 73.0k | if (zId) |
2958 | 981 | f << "Entries(Textbox)[Z" << zId << "]:" << shape; |
2959 | 72.0k | else |
2960 | 72.0k | f << "Entries(Textbox):" << shape; |
2961 | 73.0k | FreeHandParserInternal::Textbox textbox(zId); |
2962 | 73.0k | textbox.m_layerId=shape.m_layerId; |
2963 | 73.0k | f << "sz?=" << shape.m_size << ","; |
2964 | 73.0k | if (zId && m_state->getZoneType(zId)!=FreeHandParserInternal::Z_Shape) { |
2965 | 205 | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV2: find unexpected zone type for zone %d\n", zId)); |
2966 | 205 | } |
2967 | 511k | for (int i=0; i<6; ++i) { // f3=0|2, f4=0|1 |
2968 | 438k | auto val=static_cast<int>(input->readLong(2)); |
2969 | 438k | if (val) f << "f" << i << "=" << val << ","; |
2970 | 438k | } |
2971 | 73.0k | auto val=static_cast<int>(input->readULong(2)); // 1a|7b|c3|eb|f4|fb|114|1af|7d00|7d02 |
2972 | 73.0k | if (val) f << "f6=" << val << ","; |
2973 | 73.0k | float dim[6]; |
2974 | 365k | for (int i=0; i<4; ++i) dim[i]=float(input->readLong(2))/10.f; |
2975 | 73.0k | textbox.m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]),MWAWVec2f(dim[2],dim[3])); |
2976 | 73.0k | f << "dim=" << textbox.m_box << ","; |
2977 | 73.0k | val=static_cast<int>(input->readULong(2)); // 0 |
2978 | 73.0k | if (val) f << "f7=" << val << ","; |
2979 | 73.0k | f << "flags=" << std::hex << input->readULong(2) << std::dec << ","; |
2980 | 73.0k | f << "rot=["; |
2981 | 365k | for (int i=0; i<4; ++i) { |
2982 | 292k | dim[i]=float(input->readLong(4))/65536.f; |
2983 | 292k | f << dim[i] << ","; |
2984 | 292k | } |
2985 | 73.0k | f << "],"; |
2986 | 73.0k | f << "trans=["; |
2987 | 219k | for (int i=0; i<2; ++i) { |
2988 | 146k | dim[i+4]=float(input->readLong(4))/65536.f/10.f; |
2989 | 146k | f << dim[i+4] << ","; |
2990 | 146k | } |
2991 | 73.0k | f << "],"; |
2992 | 73.0k | textbox.m_transformation=MWAWTransformation(MWAWVec3f(dim[0],dim[2],dim[4]),MWAWVec3f(dim[1],dim[3],dim[5])); |
2993 | 73.0k | val=static_cast<int>(input->readLong(1)); |
2994 | 73.0k | switch (val) { |
2995 | 39.5k | case 0: // left |
2996 | 39.5k | break; |
2997 | 1.29k | case 1: |
2998 | 1.29k | f << "center,"; |
2999 | 1.29k | textbox.m_justify=MWAWParagraph::JustificationCenter; |
3000 | 1.29k | break; |
3001 | 2.11k | case 2: |
3002 | 2.11k | f << "right,"; |
3003 | 2.11k | textbox.m_justify=MWAWParagraph::JustificationRight; |
3004 | 2.11k | break; |
3005 | 6.32k | case 3: |
3006 | 6.32k | f << "justify=all,"; |
3007 | 6.32k | textbox.m_justify=MWAWParagraph::JustificationFull; |
3008 | 6.32k | break; |
3009 | 23.8k | default: |
3010 | 23.8k | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV2: find unexpected align\n")); |
3011 | 23.8k | f << "###align=" << val << ","; |
3012 | 23.8k | break; |
3013 | 73.0k | } |
3014 | 73.0k | ascii().addDelimiter(input->tell(), '|'); |
3015 | 73.0k | ascii().addPos(pos); |
3016 | 73.0k | ascii().addNote(f.str().c_str()); |
3017 | 73.0k | input->seek(11, librevenge::RVNG_SEEK_CUR); |
3018 | | |
3019 | 73.0k | pos=input->tell(); |
3020 | 73.0k | f.str(""); |
3021 | 73.0k | f << "Textbox-A:"; |
3022 | 73.0k | auto dSz=static_cast<int>(input->readULong(2)); |
3023 | 73.0k | auto sSz=static_cast<int>(input->readULong(2)); |
3024 | 73.0k | long endPos=pos+dSz-18-80; |
3025 | 73.0k | if (dSz-18-80<58 || !input->checkPosition(endPos)) { |
3026 | 46.6k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
3027 | 46.6k | return false; |
3028 | 46.6k | } |
3029 | 26.4k | f << "text[sz]=" << sSz << ","; |
3030 | 26.4k | val=static_cast<int>(input->readULong(2)); |
3031 | 26.4k | if (val!=sSz) f << "text[pos]=" << val << ","; |
3032 | 26.4k | val=static_cast<int>(input->readULong(2)); // always 7ffd ? |
3033 | 26.4k | if (val!=0x7ffd) f << "f0=" << val << ","; |
3034 | 79.3k | for (int i=0; i<2; ++i) { |
3035 | 52.8k | val=static_cast<int>(input->readLong(2)); |
3036 | 52.8k | if (val) f << "f" << i+1 << "=" << val << ","; |
3037 | 52.8k | } |
3038 | 26.4k | FreeHandParserInternal::Font font; |
3039 | 26.4k | auto id=static_cast<int>(input->readULong(2)); |
3040 | 26.4k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_String)) { |
3041 | 172 | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV2: find bad font name\n")); |
3042 | 172 | f << "###"; |
3043 | 172 | } |
3044 | 26.4k | font.m_nameId=id; |
3045 | 26.4k | if (id) |
3046 | 23.1k | f << "font[name]=Z" << id << ","; |
3047 | 26.4k | float sz=float(input->readLong(4))/65536.f; |
3048 | 26.4k | font.m_font.setSize(sz); |
3049 | 26.4k | f << "font[sz]=" << sz << ","; |
3050 | 26.4k | val=static_cast<int>(input->readULong(4)); |
3051 | | // use me |
3052 | 26.4k | if (val==static_cast<int>(0xFFFE0000)) |
3053 | 0 | f << "leading=auto,"; |
3054 | 26.4k | else if (val!=static_cast<int>(0xFFFF0000)) // no solid |
3055 | 26.4k | f << "leading=" << float(val)/65536.f << ","; |
3056 | 26.4k | val=static_cast<int>(input->readLong(2)); |
3057 | 26.4k | if (val) f << "f4=" << val << ","; |
3058 | 26.4k | uint32_t flags=0; |
3059 | 26.4k | val=static_cast<int>(input->readULong(2)); |
3060 | 26.4k | if (val & 1) { |
3061 | 16.7k | flags |= MWAWFont::boldBit; |
3062 | 16.7k | f << "bold,"; |
3063 | 16.7k | } |
3064 | 26.4k | if (val & 2) { |
3065 | 18.3k | flags |= MWAWFont::italicBit; |
3066 | 18.3k | f << "italic,"; |
3067 | 18.3k | } |
3068 | 26.4k | val &= 0xFFFC; |
3069 | 26.4k | if (val) { |
3070 | 5.29k | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV2: find unknown font flag1\n")); |
3071 | 5.29k | f << "##flag1=" << std::hex << val << std::dec << ","; |
3072 | 5.29k | } |
3073 | 26.4k | id=static_cast<int>(input->readULong(2)); |
3074 | 26.4k | if (id && !m_state->addZoneId(id, FreeHandParserInternal::Z_Color)) { |
3075 | 1.18k | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV2: find bad color\n")); |
3076 | 1.18k | f << "###"; |
3077 | 1.18k | } |
3078 | 26.4k | if (id) |
3079 | 7.19k | f << "color=Z" << id << ","; |
3080 | 26.4k | font.m_colorId=id; |
3081 | 26.4k | val=static_cast<int>(input->readLong(2)); // 0 |
3082 | 26.4k | if (val) f << "f6=" << val << ","; |
3083 | 26.4k | auto special=static_cast<int>(input->readLong(2)); |
3084 | 26.4k | int specialData[6]; |
3085 | 185k | for (int i=0; i<6; ++i) specialData[i]=static_cast<int>(input->readULong(i>=4 ? 1 : 2)); |
3086 | 26.4k | if (!m_state->addZoneId(specialData[0], FreeHandParserInternal::Z_Color)) { |
3087 | 907 | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV2: find bad text color\n")); |
3088 | 907 | f << "###"; |
3089 | 907 | } |
3090 | 26.4k | if (specialData[0]) |
3091 | 7.15k | f << "col2=Z" << specialData[0] << ","; |
3092 | 26.4k | switch (special) { |
3093 | 22 | case 1: // solid |
3094 | 22 | break; |
3095 | 1.47k | case 2: |
3096 | 1.47k | flags |= MWAWFont::boldBit; |
3097 | 1.47k | f << "heavy,"; |
3098 | 1.47k | break; |
3099 | 356 | case 3: |
3100 | 356 | flags |= MWAWFont::italicBit; |
3101 | 356 | f << "oblique,"; |
3102 | 356 | break; |
3103 | 1.82k | case 4: |
3104 | 1.82k | flags |= MWAWFont::outlineBit; |
3105 | 1.82k | f << "outline,"; |
3106 | 1.82k | break; |
3107 | 280 | case 5: |
3108 | 280 | flags |= MWAWFont::shadowBit; |
3109 | 280 | f << "shadow,"; |
3110 | 280 | break; |
3111 | 15.4k | case 6: |
3112 | 15.4k | f << "fillAndStroke,"; |
3113 | 15.4k | if (specialData[1]||specialData[2]) { |
3114 | 6.50k | f << "stroke[w]=" << float((specialData[1]<<16)+specialData[2])/65536.f << ","; |
3115 | 6.50k | specialData[1]=specialData[2]=0; |
3116 | 6.50k | } |
3117 | 15.4k | if (specialData[3]&0x100) f << "fill[set],"; |
3118 | 15.4k | if (specialData[3]&0x1) f << "fill[overprint],"; |
3119 | 15.4k | specialData[3]&=0xfefe; |
3120 | 46.3k | for (int i=0; i<2; ++i) { |
3121 | 30.9k | if (!specialData[4+i]) continue; |
3122 | | |
3123 | 10.3k | char const *wh[]= {"stroke[set]", "stroke[overprint]"}; |
3124 | 10.3k | f << wh[i] << "=" << specialData[4+i] << ","; |
3125 | 10.3k | specialData[4+i]=0; |
3126 | 10.3k | } |
3127 | 15.4k | break; |
3128 | 158 | case 0x79: |
3129 | 158 | f << "char,"; |
3130 | 790 | for (int i=1; i<5; ++i) { |
3131 | 632 | if (!specialData[i]) continue; |
3132 | 456 | char const *wh[]= {"", "fill[sz]", "line[spacing]", "stroke[width]", "has[stroke]"}; |
3133 | 456 | if (i==3) |
3134 | 156 | f << wh[i] << "=" << float(specialData[i])/10.f << ","; |
3135 | 300 | else |
3136 | 300 | f << wh[i] << "=" << specialData[i] << ","; |
3137 | 456 | specialData[i]=0; |
3138 | 456 | } |
3139 | 158 | break; |
3140 | 886 | case 0x7a: |
3141 | 886 | f << "zoom,"; |
3142 | 3.54k | for (int i=1; i<4; ++i) { |
3143 | 2.65k | if (!specialData[i]) continue; |
3144 | 2.61k | char const *wh[]= {"", "zoom[horOffset]", "zoom[verOffset]", "zoom[%]"}; |
3145 | 2.61k | f << wh[i] << "=" << specialData[i] << ","; |
3146 | 2.61k | specialData[i]=0; |
3147 | 2.61k | } |
3148 | 886 | break; |
3149 | 5.96k | default: |
3150 | 5.96k | MWAW_DEBUG_MSG(("FreeHandParser::readTextboxV2: find unknown font flag2\n")); |
3151 | 5.96k | f << "##flag2=" << special << ","; |
3152 | 5.96k | break; |
3153 | 26.4k | } |
3154 | 158k | for (int i=1; i<6; ++i) { |
3155 | 132k | if (specialData[i]) |
3156 | 37.4k | f << "#special" << i << "=" << specialData[i] << ","; |
3157 | 132k | } |
3158 | 26.4k | font.m_font.setFlags(flags); |
3159 | 26.4k | textbox.m_posToFontMap[0]=font; |
3160 | 26.4k | f << "spacing=["; // letter and word |
3161 | 79.3k | for (int i=0; i<2; ++i) { |
3162 | 52.8k | dim[i]=float(input->readLong(4))/65536.f; |
3163 | 52.8k | f << dim[i] << ","; |
3164 | 52.8k | } |
3165 | 26.4k | f << "],"; |
3166 | 26.4k | textbox.m_spacings=MWAWVec2f(dim[0],dim[1]); |
3167 | 26.4k | textbox.m_scalings[0]=float(input->readLong(4))/65536.f; |
3168 | 26.4k | f << "scalings[hor]=" << textbox.m_scalings[0] << ","; |
3169 | 26.4k | textbox.m_baseline=float(input->readLong(4))/65536.f; |
3170 | 26.4k | if (textbox.m_baseline<0||textbox.m_baseline>0) |
3171 | 23.2k | f << "baseline=" << textbox.m_baseline << ","; |
3172 | 26.4k | ascii().addPos(pos); |
3173 | 26.4k | ascii().addNote(f.str().c_str()); |
3174 | | /* CHECKME: find some blocks here : [12bytes]* followed by [unkn]* and [22bytes]* |
3175 | | for instance |
3176 | | 00290003007a9ce0000ffed1 |
3177 | | 002a00190069046000100000 |
3178 | | 0012000... |
3179 | | 001a0000000000c9f280000ac3de00033c22000f0000 |
3180 | | 00290000000000690460000ac3de00033c22000f0000 |
3181 | | 004d0000000000e2f160000ac3de00033c2200120000 |
3182 | | 006000000000007a6860000ac3de00033c22000f0000 |
3183 | | */ |
3184 | 26.4k | if (endPos!=input->tell()) { |
3185 | 26.0k | pos=input->tell(); |
3186 | 26.0k | f.str(""); |
3187 | 26.0k | f << "Textbox-B:"; |
3188 | 26.0k | ascii().addPos(pos); |
3189 | 26.0k | ascii().addNote(f.str().c_str()); |
3190 | 26.0k | } |
3191 | 26.4k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
3192 | | |
3193 | 26.4k | textbox.m_text.setBegin(input->tell()); |
3194 | 26.4k | textbox.m_text.setLength(sSz); |
3195 | 26.4k | input->seek(textbox.m_text.end(), librevenge::RVNG_SEEK_SET); |
3196 | | |
3197 | 26.4k | if (zId && m_state->m_zIdToTextboxMap.find(zId)==m_state->m_zIdToTextboxMap.end()) |
3198 | 828 | m_state->m_zIdToTextboxMap.insert(std::map<int, FreeHandParserInternal::Textbox>::value_type(zId,textbox)); |
3199 | | |
3200 | 26.4k | return true; |
3201 | 26.4k | } |
3202 | | |
3203 | | bool FreeHandParser::readDataZone(int zId) |
3204 | 5.65k | { |
3205 | 5.65k | MWAWInputStreamPtr input = getInput(); |
3206 | 5.65k | libmwaw::DebugStream f; |
3207 | 5.65k | long pos=input->tell(); |
3208 | 5.65k | if (!input->checkPosition(pos+10)) return false; |
3209 | 5.60k | auto dSz=long(input->readULong(4)); |
3210 | 5.60k | auto opCode=static_cast<int>(input->readULong(2)); |
3211 | 5.60k | auto dataSize=long(input->readULong(4)); |
3212 | 5.60k | long endPos=pos+10+dataSize; |
3213 | 5.60k | if (opCode!=0x138b || dataSize<0 || !input->checkPosition(endPos)) { |
3214 | 2.78k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
3215 | 2.78k | return false; |
3216 | 2.78k | } |
3217 | 2.82k | auto type=zId ? m_state->getZoneType(zId) : FreeHandParserInternal::Z_Unknown; |
3218 | 2.82k | if (type==FreeHandParserInternal::Z_Note) { |
3219 | 234 | f << "Entries(Note)[Z" << zId << "]:"; |
3220 | 234 | if (dataSize) { |
3221 | 229 | auto sSz=static_cast<int>(input->readULong(1)); |
3222 | 229 | if (sSz+1>dataSize) { |
3223 | 9 | MWAW_DEBUG_MSG(("FreeHandParser::readDataZone: can not read the note size\n")); |
3224 | 9 | f << "##sSz"; |
3225 | 9 | } |
3226 | 220 | else { |
3227 | 220 | std::string note; |
3228 | 2.43k | for (int i=0; i<sSz; ++i) note+=char(input->readULong(1)); |
3229 | 220 | f << note; |
3230 | 220 | } |
3231 | 229 | } |
3232 | 234 | } |
3233 | 2.58k | else if (type==FreeHandParserInternal::Z_PictureName) { |
3234 | 0 | f << "Picture[name][Z" << zId << "]:"; |
3235 | 0 | if (dataSize<6) { |
3236 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::readDataZone: can not read the picture name zone\n")); |
3237 | 0 | f << "##sSz"; |
3238 | 0 | } |
3239 | 0 | else { |
3240 | 0 | auto val=static_cast<int>(input->readLong(4)); // disk id? |
3241 | 0 | if (val) f << "f0=" << std::hex << val << std::dec << ","; |
3242 | 0 | for (int i=0; i<2; ++i) { // disk name ?, file name |
3243 | 0 | auto sSz=static_cast<int>(input->readULong(1)); |
3244 | 0 | if (input->tell()+sSz>endPos) { |
3245 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::readDataZone: can not read some string\n")); |
3246 | 0 | f << "##sSz"; |
3247 | 0 | break; |
3248 | 0 | } |
3249 | 0 | std::string name; |
3250 | 0 | for (int c=0; c<sSz; ++c) name+=char(input->readULong(1)); |
3251 | 0 | f << name << ","; |
3252 | 0 | } |
3253 | 0 | } |
3254 | 0 | } |
3255 | 2.58k | else if (type==FreeHandParserInternal::Z_Picture) { |
3256 | 0 | f << "Picture[data][Z" << zId << "]:"; |
3257 | 0 | if (dataSize) { |
3258 | 0 | MWAWEntry entry; |
3259 | 0 | entry.setBegin(input->tell()); |
3260 | 0 | entry.setLength(dataSize); |
3261 | 0 | if (zId && m_state->m_zIdToDataMap.find(zId)==m_state->m_zIdToDataMap.end()) |
3262 | 0 | m_state->m_zIdToDataMap[zId]=entry; |
3263 | 0 | ascii().skipZone(entry.begin(), entry.end()-1); |
3264 | 0 | } |
3265 | 0 | } |
3266 | 2.58k | else { |
3267 | 2.58k | MWAW_DEBUG_MSG(("FreeHandParser::readDataZone: find unknown zone\n")); |
3268 | 2.58k | if (zId) |
3269 | 69 | f << "Entries(DataZone)[Z" << zId << "]:"; |
3270 | 2.51k | else |
3271 | 2.51k | f << "Entries(DataZone):"; |
3272 | 2.58k | if (dSz!=dataSize+5) |
3273 | 161 | f << "sz?=" << dSz << ","; |
3274 | 2.58k | } |
3275 | 2.82k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
3276 | 2.82k | ascii().addPos(pos); |
3277 | 2.82k | ascii().addNote(f.str().c_str()); |
3278 | 2.82k | return true; |
3279 | 5.60k | } |
3280 | | |
3281 | | //////////////////////////////////////////////////////////// |
3282 | | // |
3283 | | // send data |
3284 | | // |
3285 | | //////////////////////////////////////////////////////////// |
3286 | | bool FreeHandParser::openLayer(int zId) |
3287 | 15.0k | { |
3288 | 15.0k | if (zId<0 || m_state->m_actualLayer>=0 || m_state->m_sendLayerSet.find(zId)!=m_state->m_sendLayerSet.end()) |
3289 | 11.6k | return false; |
3290 | 3.32k | if (!getGraphicListener()) { |
3291 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::openLayer: can not find the listener\n")); |
3292 | 0 | return false; |
3293 | 0 | } |
3294 | 3.32k | m_state->m_sendLayerSet.insert(zId); |
3295 | 3.32k | librevenge::RVNGString layer; |
3296 | 3.32k | layer.sprintf("%d", zId); |
3297 | 3.32k | if (!getGraphicListener()->openLayer(layer)) |
3298 | 0 | return false; |
3299 | 3.32k | m_state->m_actualLayer=zId; |
3300 | 3.32k | return true; |
3301 | 3.32k | } |
3302 | | |
3303 | | void FreeHandParser::closeLayer() |
3304 | 3.32k | { |
3305 | 3.32k | if (m_state->m_actualLayer<0) |
3306 | 0 | return; |
3307 | 3.32k | getGraphicListener()->closeLayer(); |
3308 | 3.32k | m_state->m_actualLayer=-1; |
3309 | 3.32k | } |
3310 | | |
3311 | | bool FreeHandParser::sendZone(int zId, MWAWTransformation const &transform) |
3312 | 58.8k | { |
3313 | 58.8k | if (!getGraphicListener()) { |
3314 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendZone: can not find the listener\n")); |
3315 | 0 | return false; |
3316 | 0 | } |
3317 | 58.8k | if (m_state->m_zIdToTextboxMap.find(zId)!=m_state->m_zIdToTextboxMap.end()) |
3318 | 2.91k | return sendTextbox(m_state->m_zIdToTextboxMap.find(zId)->second, transform); |
3319 | 55.9k | if (m_state->m_zIdToShapeMap.find(zId)==m_state->m_zIdToShapeMap.end()) { |
3320 | 33.1k | MWAW_DEBUG_MSG(("FreeHandParser::sendZone: can not find the zone %d\n", zId)); |
3321 | 33.1k | return false; |
3322 | 33.1k | } |
3323 | 22.8k | auto const &shape=m_state->m_zIdToShapeMap.find(zId)->second; |
3324 | 22.8k | shape.m_isSent=true; |
3325 | 22.8k | if (shape.m_type==FreeHandParserInternal::Shape::Group || |
3326 | 17.9k | shape.m_type==FreeHandParserInternal::Shape::JoinGroup) |
3327 | 4.88k | return sendGroup(shape, transform); |
3328 | 17.9k | if (shape.m_type==FreeHandParserInternal::Shape::Picture) |
3329 | 4 | return sendPicture(shape, transform); |
3330 | 17.9k | if (shape.m_type==FreeHandParserInternal::Shape::BackgroundPicture) |
3331 | 13 | return sendBackgroundPicture(shape, transform); |
3332 | 17.9k | if (shape.m_type!=FreeHandParserInternal::Shape::Unknown) |
3333 | 17.9k | return sendShape(shape, transform); |
3334 | 0 | return false; |
3335 | 17.9k | } |
3336 | | |
3337 | | bool FreeHandParser::sendGroup(FreeHandParserInternal::Shape const &group, MWAWTransformation const &transform) |
3338 | 4.88k | { |
3339 | 4.88k | MWAWGraphicListenerPtr listener=getGraphicListener(); |
3340 | 4.88k | if (!listener) { |
3341 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendGroup: can not find the listener\n")); |
3342 | 0 | return false; |
3343 | 0 | } |
3344 | 4.88k | if (group.m_childs.empty()) return true; |
3345 | 4.79k | if (m_state->m_sendIdSet.find(group.m_id)!=m_state->m_sendIdSet.end()) { |
3346 | 389 | MWAW_DEBUG_MSG(("FreeHandParser::sendGroup: sorry the zone %d is already sent\n", group.m_id)); |
3347 | 389 | return false; |
3348 | 389 | } |
3349 | 4.40k | m_state->m_sendIdSet.insert(group.m_id); |
3350 | 4.40k | MWAWTransformation transf=transform*group.m_transformation; |
3351 | 4.40k | bool createGroup=group.m_childs.size()>1 && group.m_id!=m_state->m_mainGroupId; |
3352 | | // TODO check for join group |
3353 | 4.40k | bool newLayer=openLayer(group.m_layerId); |
3354 | 4.40k | if (createGroup) { |
3355 | 475 | MWAWPosition pos(MWAWVec2f(0,0), MWAWVec2f(0,0), librevenge::RVNG_POINT); |
3356 | 475 | pos.m_anchorTo = MWAWPosition::Page; |
3357 | 475 | listener->openGroup(pos); |
3358 | 475 | } |
3359 | 4.40k | bool checkLayer=m_state->m_actualLayer==-1; |
3360 | 4.40k | int actualLayerId=-1; |
3361 | 52.1k | for (int cId : group.m_childs) { |
3362 | 52.1k | if (checkLayer) { |
3363 | 51.1k | int newLayerId=-1; |
3364 | 51.1k | if (m_state->m_zIdToTextboxMap.find(cId)!=m_state->m_zIdToTextboxMap.end()) |
3365 | 2.68k | newLayerId=m_state->m_zIdToTextboxMap.find(cId)->second.m_layerId; |
3366 | 48.4k | else if (m_state->m_zIdToShapeMap.find(cId)!=m_state->m_zIdToShapeMap.end()) |
3367 | 19.1k | newLayerId=m_state->m_zIdToShapeMap.find(cId)->second.m_layerId; |
3368 | 51.1k | if (newLayerId!=actualLayerId) { |
3369 | 10.6k | if (actualLayerId>=0) |
3370 | 2.90k | closeLayer(); |
3371 | 10.6k | if (openLayer(newLayerId)) |
3372 | 3.23k | actualLayerId=newLayerId; |
3373 | 7.37k | else |
3374 | 7.37k | actualLayerId=-1; |
3375 | 10.6k | } |
3376 | 51.1k | } |
3377 | 52.1k | sendZone(cId, transf); |
3378 | 52.1k | } |
3379 | 4.40k | if (actualLayerId>=0) closeLayer(); |
3380 | 4.40k | if (createGroup) |
3381 | 475 | listener->closeGroup(); |
3382 | 4.40k | m_state->m_sendIdSet.erase(group.m_id); |
3383 | 4.40k | if (newLayer) closeLayer(); |
3384 | 4.40k | return true; |
3385 | 4.79k | } |
3386 | | |
3387 | | bool FreeHandParser::sendBackgroundPicture(FreeHandParserInternal::Shape const &picture, MWAWTransformation const &) |
3388 | 13 | { |
3389 | 13 | MWAWGraphicListenerPtr listener=getGraphicListener(); |
3390 | 13 | if (!listener) { |
3391 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendBackgroundPicture: can not find the listener\n")); |
3392 | 0 | return false; |
3393 | 0 | } |
3394 | 13 | if (!picture.m_picture.valid()) { |
3395 | 11 | MWAW_DEBUG_MSG(("FreeHandParser::sendBackgroundPicture: can not find the background picture\n")); |
3396 | 11 | return false; |
3397 | 11 | } |
3398 | 2 | MWAWInputStreamPtr input=getInput(); |
3399 | 2 | input->seek(picture.m_picture.begin(), librevenge::RVNG_SEEK_SET); |
3400 | 2 | librevenge::RVNGBinaryData data; |
3401 | 2 | if (!input->readDataBlock(picture.m_picture.length(), data) || data.empty()) { |
3402 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendBackgroundPicture: oops the picture is empty\n")); |
3403 | 0 | return false; |
3404 | 0 | } |
3405 | | #ifdef DEBUG_WITH_FILES |
3406 | | static int volatile pictName = 0; |
3407 | | libmwaw::DebugStream f; |
3408 | | f << "PICT-" << ++pictName << ".pct"; |
3409 | | libmwaw::Debug::dumpFile(data, f.str().c_str()); |
3410 | | #endif |
3411 | 2 | MWAWPosition pos(MWAWVec2f(float(getPageSpan().getMarginLeft()), float(getPageSpan().getMarginTop())), |
3412 | 2 | MWAWVec2f(float(getPageSpan().getPageWidth()), float(getPageSpan().getPageLength())), librevenge::RVNG_INCH); |
3413 | 2 | pos.m_anchorTo = MWAWPosition::Page; |
3414 | 2 | pos.setOrder(-1); |
3415 | 2 | MWAWEmbeddedObject pict(data); |
3416 | 2 | listener->insertPicture(pos, pict); |
3417 | 2 | return true; |
3418 | 2 | } |
3419 | | |
3420 | | bool FreeHandParser::sendPicture(FreeHandParserInternal::Shape const &picture, MWAWTransformation const &transform) |
3421 | 4 | { |
3422 | 4 | MWAWGraphicListenerPtr listener=getGraphicListener(); |
3423 | 4 | if (!listener) { |
3424 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendPicture: can not find the listener\n")); |
3425 | 0 | return false; |
3426 | 0 | } |
3427 | 4 | if (m_state->m_zIdToDataMap.find(picture.m_dataId)==m_state->m_zIdToDataMap.end() || |
3428 | 4 | !m_state->m_zIdToDataMap.find(picture.m_dataId)->second.valid()) { |
3429 | 4 | MWAW_DEBUG_MSG(("FreeHandParser::sendPicture: can not find the picture\n")); |
3430 | 4 | return false; |
3431 | 4 | } |
3432 | 0 | MWAWInputStreamPtr input=getInput(); |
3433 | 0 | MWAWEntry entry=m_state->m_zIdToDataMap.find(picture.m_dataId)->second; |
3434 | 0 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
3435 | 0 | librevenge::RVNGBinaryData data; |
3436 | 0 | if (!input->readDataBlock(entry.length(), data) || data.empty()) { |
3437 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendPicture: oops the picture is empty\n")); |
3438 | 0 | return false; |
3439 | 0 | } |
3440 | | #ifdef DEBUG_WITH_FILES |
3441 | | static int volatile pictName = 0; |
3442 | | libmwaw::DebugStream f; |
3443 | | f << "PICT-" << ++pictName << ".pct"; |
3444 | | libmwaw::Debug::dumpFile(data, f.str().c_str()); |
3445 | | #endif |
3446 | 0 | MWAWGraphicStyle style=MWAWGraphicStyle::emptyStyle(); |
3447 | 0 | MWAWTransformation finalTransformation=transform*picture.m_transformation; |
3448 | 0 | MWAWTransformation transf; |
3449 | 0 | float rotation=0; |
3450 | 0 | MWAWBox2f box; |
3451 | 0 | if (decomposeMatrix(finalTransformation,rotation,transf,picture.m_box.center())) { |
3452 | 0 | box=transf*picture.m_box; |
3453 | 0 | style.m_rotate=rotation; |
3454 | 0 | } |
3455 | 0 | else |
3456 | 0 | box=finalTransformation*picture.m_box; |
3457 | 0 | for (int c=0; c<2; ++c) { |
3458 | 0 | if (box.min()[c]>box.max()[c]) |
3459 | 0 | std::swap(box.min()[c],box.max()[c]); |
3460 | 0 | } |
3461 | 0 | MWAWPosition pos(box[0], box.size(), librevenge::RVNG_POINT); |
3462 | 0 | pos.m_anchorTo = MWAWPosition::Page; |
3463 | 0 | MWAWEmbeddedObject pict(data); |
3464 | 0 | listener->insertPicture(pos, pict, style); |
3465 | 0 | return true; |
3466 | 0 | } |
3467 | | |
3468 | | bool FreeHandParser::sendShape(FreeHandParserInternal::Shape const &shape, MWAWTransformation const &transform) |
3469 | 17.9k | { |
3470 | 17.9k | MWAWGraphicListenerPtr listener=getGraphicListener(); |
3471 | 17.9k | if (!listener) { |
3472 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendShape: can not find the listener\n")); |
3473 | 0 | return false; |
3474 | 0 | } |
3475 | 17.9k | MWAWGraphicStyle style; |
3476 | 17.9k | m_state->updateLineStyle(shape.m_lineId, style); |
3477 | 17.9k | if (shape.m_type!=FreeHandParserInternal::Shape::Line && |
3478 | 14.7k | (shape.m_type!=FreeHandParserInternal::Shape::Path || shape.m_closed)) |
3479 | 12.9k | m_state->updateFillStyle(shape.m_fillId, style); |
3480 | 17.9k | MWAWTransformation finalTransformation=transform*shape.m_transformation; |
3481 | 17.9k | MWAWGraphicShape res; |
3482 | 17.9k | if (shape.updateShape(res)) { |
3483 | 17.8k | res=res.transform(finalTransformation); |
3484 | 17.8k | MWAWPosition pos(res.m_bdBox[0], res.m_bdBox.size(), librevenge::RVNG_POINT); |
3485 | 17.8k | pos.m_anchorTo = MWAWPosition::Page; |
3486 | 17.8k | listener->insertShape(pos, res, style); |
3487 | 17.8k | return true; |
3488 | 17.8k | } |
3489 | 65 | MWAW_DEBUG_MSG(("FreeHandParser::sendShape: found some unexpected shape\n")); |
3490 | 65 | return false; |
3491 | 17.9k | } |
3492 | | |
3493 | | bool FreeHandParser::sendTextbox(FreeHandParserInternal::Textbox const &textbox, MWAWTransformation const &transform) |
3494 | 2.91k | { |
3495 | 2.91k | textbox.m_isSent=true; |
3496 | 2.91k | MWAWGraphicListenerPtr listener=getGraphicListener(); |
3497 | 2.91k | if (!listener) { |
3498 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendTextbox: can not find the listener\n")); |
3499 | 0 | return false; |
3500 | 0 | } |
3501 | 2.91k | MWAWGraphicStyle style(MWAWGraphicStyle::emptyStyle()); |
3502 | 2.91k | MWAWTransformation finalTransformation=transform*textbox.m_transformation; |
3503 | 2.91k | MWAWTransformation transf; |
3504 | 2.91k | float rotation=0; |
3505 | 2.91k | MWAWBox2f box; |
3506 | 2.91k | if (decomposeMatrix(finalTransformation,rotation,transf,textbox.m_box.center())) { |
3507 | 912 | box=transf*textbox.m_box; |
3508 | 912 | style.m_rotate=rotation; |
3509 | 912 | } |
3510 | 2.00k | else |
3511 | 2.00k | box=finalTransformation*textbox.m_box; |
3512 | 8.74k | for (int c=0; c<2; ++c) { |
3513 | 5.83k | if (box.min()[c]>box.max()[c]) |
3514 | 752 | std::swap(box.min()[c],box.max()[c]); |
3515 | 5.83k | } |
3516 | 2.91k | MWAWPosition pos(box[0], box.size(), librevenge::RVNG_POINT); |
3517 | 2.91k | pos.m_anchorTo = MWAWPosition::Page; |
3518 | 2.91k | std::shared_ptr<MWAWSubDocument> doc(new FreeHandParserInternal::SubDocument(*this, getInput(), textbox.m_id)); |
3519 | 2.91k | listener->insertTextBox(pos, doc, style); |
3520 | 2.91k | return false; |
3521 | 2.91k | } |
3522 | | |
3523 | | bool FreeHandParser::sendText(int zId) |
3524 | 2.91k | { |
3525 | 2.91k | MWAWGraphicListenerPtr listener=getGraphicListener(); |
3526 | 2.91k | if (!listener) { |
3527 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendText: can not find the listener\n")); |
3528 | 0 | return false; |
3529 | 0 | } |
3530 | 2.91k | if (m_state->m_zIdToTextboxMap.find(zId)==m_state->m_zIdToTextboxMap.end()) { |
3531 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::sendText: can not find the text shape\n")); |
3532 | 0 | return false; |
3533 | 0 | } |
3534 | 2.91k | auto &textbox=m_state->m_zIdToTextboxMap.find(zId)->second; |
3535 | 2.91k | MWAWParagraph para; |
3536 | 2.91k | para.m_justify = textbox.m_justify; |
3537 | 2.91k | listener->setParagraph(para); |
3538 | 2.91k | if (!textbox.m_text.valid()) |
3539 | 86 | return true; |
3540 | 2.83k | MWAWInputStreamPtr input=getInput(); |
3541 | 2.83k | input->seek(textbox.m_text.begin(), librevenge::RVNG_SEEK_SET); |
3542 | | |
3543 | 2.83k | libmwaw::DebugStream f; |
3544 | 2.83k | f << "Textbox[text]:"; |
3545 | 2.83k | long endPos=textbox.m_text.end(); |
3546 | 2.83k | int cPos=0; |
3547 | 2.83k | float deltaSpacing=textbox.m_spacings[0]; |
3548 | 292k | while (!input->isEnd()) { |
3549 | 292k | if (input->tell()>=endPos) |
3550 | 2.79k | break; |
3551 | 289k | if (textbox.m_posToFontMap.find(cPos)!=textbox.m_posToFontMap.end()) { |
3552 | 5.26k | auto &font=textbox.m_posToFontMap.find(cPos)->second; |
3553 | 5.26k | if (font.m_nameId && m_state->m_zIdToStringMap.find(font.m_nameId)!= m_state->m_zIdToStringMap.end()) |
3554 | 474 | font.m_font.setId(getParserState()->m_fontConverter->getId(m_state->m_zIdToStringMap.find(font.m_nameId)->second)); |
3555 | | // color |
3556 | 5.26k | if (font.m_colorId && m_state->m_zIdToColorMap.find(font.m_colorId) != m_state->m_zIdToColorMap.end()) |
3557 | 1.53k | font.m_font.setColor(m_state->m_zIdToColorMap.find(font.m_colorId)->second); |
3558 | | // spacing |
3559 | 5.26k | font.m_font.setDeltaLetterSpacing(deltaSpacing, librevenge::RVNG_POINT); |
3560 | | // streching |
3561 | 5.26k | bool needStreching=false; |
3562 | 5.26k | if (textbox.m_scalings[1]<1||textbox.m_scalings[1]>1) { |
3563 | 3.24k | font.m_font.setSize(font.m_font.size()*textbox.m_scalings[1]); |
3564 | 3.24k | needStreching=true; |
3565 | 3.24k | } |
3566 | 5.26k | if ((needStreching || textbox.m_scalings[0]<1 || textbox.m_scalings[0]>1) && textbox.m_scalings[1]>0) |
3567 | 3.14k | font.m_font.setWidthStreching(textbox.m_scalings[0]/textbox.m_scalings[1]); |
3568 | 5.26k | listener->setFont(font.m_font); |
3569 | 5.26k | f << "[F]"; |
3570 | 5.26k | } |
3571 | 289k | ++cPos; |
3572 | 289k | auto c = char(input->readULong(1)); |
3573 | 289k | if (c==0) { |
3574 | 113k | MWAW_DEBUG_MSG(("FreeHandParser::sendText: find char 0\n")); |
3575 | 113k | f << "#[0]"; |
3576 | 113k | continue; |
3577 | 113k | } |
3578 | 176k | f << c; |
3579 | 176k | switch (c) { |
3580 | 4.04k | case 9: |
3581 | 4.04k | listener->insertTab(); |
3582 | 4.04k | break; |
3583 | 7.28k | case 0xd: |
3584 | 7.28k | listener->insertEOL(); |
3585 | 7.28k | break; |
3586 | 165k | default: |
3587 | 165k | listener->insertCharacter(static_cast<unsigned char>(c), input, endPos); |
3588 | 165k | break; |
3589 | 176k | } |
3590 | 176k | } |
3591 | 2.83k | ascii().addPos(textbox.m_text.begin()); |
3592 | 2.83k | ascii().addNote(f.str().c_str()); |
3593 | | |
3594 | 2.83k | return true; |
3595 | 2.83k | } |
3596 | | |
3597 | | void FreeHandParser::flushExtra() |
3598 | 0 | { |
3599 | 0 | bool first=true; |
3600 | 0 | for (auto const &it : m_state->m_zIdToShapeMap) { |
3601 | 0 | if (it.second.m_isSent) continue; |
3602 | 0 | if (first) { |
3603 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::flushExtra: find some unused shape: %d\n", it.first)); |
3604 | 0 | first=false; |
3605 | 0 | } |
3606 | 0 | sendZone(it.first, m_state->m_transform); |
3607 | 0 | } |
3608 | 0 | first=true; |
3609 | 0 | for (auto const &it : m_state->m_zIdToTextboxMap) { |
3610 | 0 | if (it.second.m_isSent) continue; |
3611 | 0 | if (first) { |
3612 | 0 | MWAW_DEBUG_MSG(("FreeHandParser::flushExtra: find some unsed textbox %d\n", it.first)); |
3613 | 0 | first=false; |
3614 | 0 | } |
3615 | 0 | sendZone(it.first, m_state->m_transform); |
3616 | 0 | } |
3617 | 0 | } |
3618 | | |
3619 | | bool FreeHandParser::decomposeMatrix(MWAWTransformation const &matrix, float &rot, MWAWTransformation &transform, MWAWVec2f const &origCenter) |
3620 | 2.91k | { |
3621 | | // FIXME: this assumes that there is no skewing, ... |
3622 | 2.91k | MWAWVec3f const &yRow=matrix[1]; |
3623 | 2.91k | if (matrix.isIdentity() || (yRow[0]>=0 && yRow[0]<=0)) return false; |
3624 | 912 | rot=std::atan2(yRow[0], -yRow[1]); |
3625 | | rot *= float(180/M_PI); |
3626 | 912 | transform=MWAWTransformation::rotation(-rot, matrix *origCenter) * matrix; |
3627 | 912 | return true; |
3628 | 2.91k | } |
3629 | | |
3630 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |