/src/libmwaw/src/lib/Canvas5StyleManager.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libmwaw |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #include <cmath> |
35 | | #include <iomanip> |
36 | | #include <iostream> |
37 | | #include <limits> |
38 | | #include <map> |
39 | | #include <set> |
40 | | #include <sstream> |
41 | | #include <stack> |
42 | | |
43 | | #include <librevenge/librevenge.h> |
44 | | |
45 | | #include "MWAWFont.hxx" |
46 | | #include "MWAWFontConverter.hxx" |
47 | | #include "MWAWGraphicListener.hxx" |
48 | | #include "MWAWGraphicStyle.hxx" |
49 | | #include "MWAWParagraph.hxx" |
50 | | #include "MWAWParser.hxx" |
51 | | |
52 | | #include "Canvas5Image.hxx" |
53 | | #include "Canvas5Parser.hxx" |
54 | | #include "Canvas5Structure.hxx" |
55 | | |
56 | | #include "Canvas5StyleManager.hxx" |
57 | | |
58 | | #include "libmwaw_internal.hxx" |
59 | | |
60 | | /** Internal: the structures of a Canvas5StyleManager */ |
61 | | namespace Canvas5StyleManagerInternal |
62 | | { |
63 | | |
64 | | //////////////////////////////////////// |
65 | | //! Internal: the color style of a Canvas5StyleManager |
66 | | struct ColorStyle { |
67 | | //! constructor |
68 | | ColorStyle() |
69 | 0 | : m_type(1) |
70 | 0 | , m_nameId(0) |
71 | 0 | , m_color() |
72 | 0 | , m_gradient() |
73 | 0 | , m_hatch() |
74 | 0 | , m_textureDim(0,0) |
75 | 0 | , m_texture() |
76 | 0 | { |
77 | 0 | } |
78 | | friend std::ostream &operator<<(std::ostream &o, ColorStyle const &color) |
79 | 0 | { |
80 | 0 | if (color.m_type==0) |
81 | 0 | o << "transparent,"; |
82 | 0 | else if (color.m_type==1 && color.m_color.isSet()) |
83 | 0 | o << *color.m_color << ","; |
84 | 0 | else |
85 | 0 | o << "type=" << Canvas5Structure::getString(color.m_type) << ","; |
86 | 0 | if (color.m_nameId) |
87 | 0 | o << "N" << color.m_nameId << ","; |
88 | 0 | return o; |
89 | 0 | } |
90 | | //! the type |
91 | | unsigned m_type; |
92 | | //! the name id |
93 | | int m_nameId; |
94 | | //! the basic color |
95 | | MWAWVariable<MWAWColor> m_color; |
96 | | //! the gradient |
97 | | MWAWGraphicStyle::Gradient m_gradient; |
98 | | //! the hatch |
99 | | MWAWGraphicStyle::Hatch m_hatch; |
100 | | //! the texture dimension |
101 | | MWAWVec2i m_textureDim; |
102 | | //! the embedded objet (texture) |
103 | | MWAWEmbeddedObject m_texture; |
104 | | }; |
105 | | |
106 | | //////////////////////////////////////// |
107 | | //! Internal: the pen style of a Canvas5StyleManager |
108 | | struct PenStyle { |
109 | | /// a line of a Canvas5StyleManager pen style |
110 | | struct Line { |
111 | | //! constructor |
112 | | Line() |
113 | 0 | : m_size(1,1) |
114 | 0 | , m_offset(0) |
115 | 0 | , m_color(MWAWColor::black()) |
116 | 0 | { |
117 | 0 | } |
118 | | //! the line width |
119 | | MWAWVec2f m_size; |
120 | | //! the offset |
121 | | float m_offset; |
122 | | //! the line color |
123 | | MWAWVariable<MWAWColor> m_color; |
124 | | }; |
125 | | //! constructor |
126 | | PenStyle() |
127 | 0 | : m_type(1) |
128 | 0 | , m_size(1,1) |
129 | 0 | , m_usePenColor(true) |
130 | 0 | , m_lines() |
131 | 0 | { |
132 | 0 | for (auto &c : m_colors) c=MWAWColor::black(); |
133 | 0 | } |
134 | | friend std::ostream &operator<<(std::ostream &o, PenStyle const &pen) |
135 | 0 | { |
136 | 0 | if (pen.m_type!=1) |
137 | 0 | o << "type=" << Canvas5Structure::getString(pen.m_type) << ","; |
138 | 0 | if (pen.m_size!=MWAWVec2f(1,1)) |
139 | 0 | o << "size=" << pen.m_size << ","; |
140 | 0 | return o; |
141 | 0 | } |
142 | | //! the type |
143 | | unsigned m_type; |
144 | | //! the pen size |
145 | | MWAWVec2f m_size; |
146 | | //! the neo color |
147 | | MWAWVariable<MWAWColor> m_colors[2]; |
148 | | //! use pen ink |
149 | | bool m_usePenColor; |
150 | | //! the plin lines |
151 | | std::vector<Line> m_lines; |
152 | | }; |
153 | | |
154 | | //////////////////////////////////////// |
155 | | //! Internal: the stroke style of a Canvas5StyleManager |
156 | | struct Stroke { |
157 | | //! constructor |
158 | | Stroke() |
159 | 0 | : m_type(1) |
160 | 0 | , m_penId(0) |
161 | 0 | , m_dashId(0) |
162 | 0 | { |
163 | 0 | for (auto &id : m_arrowId) id=0; |
164 | 0 | } |
165 | | friend std::ostream &operator<<(std::ostream &o, Stroke const &stroke) |
166 | 0 | { |
167 | 0 | if (stroke.m_type!=1) |
168 | 0 | o << "type=" << Canvas5Structure::getString(stroke.m_type) << ","; |
169 | 0 | if (stroke.m_penId) |
170 | 0 | o << "Pe" << stroke.m_penId << ","; |
171 | 0 | if (stroke.m_dashId) |
172 | 0 | o << "Da" << stroke.m_dashId << ","; |
173 | 0 | for (int i=0; i<2; ++i) { |
174 | 0 | if (!stroke.m_arrowId[i]) continue; |
175 | 0 | o << (i==0 ? "beg" : "end") << "=Ar" << stroke.m_arrowId[i] << ","; |
176 | 0 | } |
177 | 0 | return o; |
178 | 0 | } |
179 | | //! the type |
180 | | unsigned m_type; |
181 | | //! the pen id |
182 | | int m_penId; |
183 | | //! the dash id |
184 | | int m_dashId; |
185 | | //! the arrow id (beg/end) |
186 | | int m_arrowId[2]; |
187 | | }; |
188 | | |
189 | | //////////////////////////////////////// |
190 | | //! Internal: the state of a Canvas5StyleManager |
191 | | struct State { |
192 | | //! constructor |
193 | | State() |
194 | 5.63k | : m_idToArrow() |
195 | 5.63k | , m_idToColor() |
196 | 5.63k | , m_idToPen() |
197 | 5.63k | , m_idToDash() |
198 | 5.63k | , m_idToStroke() |
199 | 5.63k | { |
200 | 5.63k | } |
201 | | |
202 | | //! the id to arrow map |
203 | | std::map<int, MWAWGraphicStyle::Arrow> m_idToArrow; |
204 | | //! the id to color style map |
205 | | std::map<int, std::shared_ptr<ColorStyle> > m_idToColor; |
206 | | //! the id to pen style map |
207 | | std::map<int, std::shared_ptr<PenStyle> > m_idToPen; |
208 | | //! the id to dash map |
209 | | std::map<int, std::vector<float> > m_idToDash; |
210 | | //! the id to stroke style map |
211 | | std::map<int, Stroke> m_idToStroke; |
212 | | }; |
213 | | |
214 | | } |
215 | | |
216 | | //////////////////////////////////////////////////////////// |
217 | | // constructor/destructor, ... |
218 | | //////////////////////////////////////////////////////////// |
219 | | Canvas5StyleManager::Canvas5StyleManager(Canvas5Parser &parser) |
220 | 5.63k | : m_parserState(parser.getParserState()) |
221 | 5.63k | , m_state(new Canvas5StyleManagerInternal::State) |
222 | 5.63k | , m_mainParser(&parser) |
223 | 5.63k | { |
224 | 5.63k | } |
225 | | |
226 | | Canvas5StyleManager::~Canvas5StyleManager() |
227 | 5.63k | { } |
228 | | |
229 | | int Canvas5StyleManager::version() const |
230 | 0 | { |
231 | 0 | return m_parserState->m_version; |
232 | 0 | } |
233 | | |
234 | | std::shared_ptr<Canvas5Image> Canvas5StyleManager::getImageParser() const |
235 | 0 | { |
236 | 0 | return m_mainParser->m_imageParser; |
237 | 0 | } |
238 | | |
239 | | //////////////////////////////////////////////////////////// |
240 | | // |
241 | | // Intermediate level |
242 | | // |
243 | | //////////////////////////////////////////////////////////// |
244 | | |
245 | | bool Canvas5StyleManager::readColor(Canvas5Structure::Stream &stream, MWAWVariable<MWAWColor> &color, std::string &extra) |
246 | 0 | { |
247 | 0 | color.setSet(false); |
248 | |
|
249 | 0 | auto input=stream.input(); |
250 | 0 | long pos=input->tell(); |
251 | 0 | extra=""; |
252 | 0 | if (!input->checkPosition(pos+24)) { |
253 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readColor: file is to short\n")); |
254 | 0 | return false; |
255 | 0 | } |
256 | 0 | libmwaw::DebugStream f; |
257 | 0 | for (int i=0; i<6; ++i) { |
258 | 0 | int val=(i>0 && i<5) ? int(input->readULong(2)) : int(input->readLong(2)); |
259 | 0 | if (val==(i==5 ? -1 : 0)) continue; |
260 | 0 | if (i>0 && i<5) |
261 | 0 | f << "f" << i << "=" << std::hex << val << std::dec << ","; |
262 | 0 | else |
263 | 0 | f << "f" << i << "=" << val << ","; |
264 | 0 | } |
265 | 0 | unsigned char cols[4]; |
266 | 0 | for (auto &c : cols) c=(unsigned char)(input->readULong(2)>>8); |
267 | | // cmyk, gray, rgb , sepp, pton, trum, toyo |
268 | 0 | unsigned name=unsigned(input->readULong(4)); |
269 | 0 | f << Canvas5Structure::getString(name) << ","; |
270 | 0 | if (name==0x67726179) // gray |
271 | 0 | color=MWAWColor(cols[0],cols[0],cols[0]); |
272 | 0 | else if (name==0x72676220) // rgb |
273 | 0 | color=MWAWColor(cols[0],cols[1],cols[2],(unsigned char)(255-cols[3])); |
274 | 0 | else { |
275 | 0 | if (name==0x70746f6e) { // pton |
276 | 0 | f << "##"; |
277 | 0 | static bool first=true; |
278 | 0 | if (first) { |
279 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readColor: this file contains pantom color, there will ne be converted correctly\n")); |
280 | 0 | first=false; |
281 | 0 | } |
282 | 0 | } |
283 | 0 | color=MWAWColor::colorFromCMYK(cols[0],cols[1],cols[2],cols[3]); |
284 | 0 | } |
285 | 0 | f << *color << ","; |
286 | 0 | extra=f.str(); |
287 | 0 | return true; |
288 | 0 | } |
289 | | |
290 | | bool Canvas5StyleManager::readGradient(std::shared_ptr<Canvas5Structure::Stream> stream, long len, |
291 | | MWAWGraphicStyle::Gradient &gradient) |
292 | 0 | { |
293 | 0 | if (!stream || !stream->input()) |
294 | 0 | return false; |
295 | 0 | auto input=stream->input(); |
296 | 0 | long pos=input->tell(); |
297 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
298 | 0 | libmwaw::DebugStream f; |
299 | |
|
300 | 0 | f << "Entries(ObFl):"; |
301 | 0 | int vers=version(); |
302 | 0 | long headerLength=vers==5 ? 56 : vers<9 ? 80+0x300 : 912; |
303 | 0 | unsigned dataSize=vers==5 ? 28 : 60; |
304 | 0 | if (len<headerLength || !input->checkPosition(pos+len)) { |
305 | 0 | if (vers>5 && input->checkPosition(pos+len) && len>=56) { |
306 | | // find some v5 gradient in v6 files converted from v5, so let's us try to revert to v5 |
307 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readGradient: this does not look as a v6 gradient, try to read a v5 gradient\n")); |
308 | 0 | f << "#v5,"; |
309 | 0 | vers=5; |
310 | 0 | headerLength=56; |
311 | 0 | dataSize=28; |
312 | 0 | } |
313 | 0 | else { |
314 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readGradient: unexpected length\n")); |
315 | 0 | f << "###"; |
316 | 0 | ascFile.addPos(pos); |
317 | 0 | ascFile.addNote(f.str().c_str()); |
318 | 0 | return false; |
319 | 0 | } |
320 | 0 | } |
321 | | |
322 | 0 | int type; |
323 | 0 | size_t N; |
324 | 0 | if (vers==5) { |
325 | 0 | N=size_t(input->readULong(4)); |
326 | 0 | f << "N=" << N << ","; |
327 | 0 | type=int(input->readLong(4)); |
328 | 0 | f << "pts=["; |
329 | 0 | MWAWVec2f pts[3]; |
330 | 0 | for (auto &pt : pts) { |
331 | 0 | float fDim[2]; |
332 | 0 | for (auto &d : fDim) d=float(input->readLong(4))/65536; |
333 | 0 | pt=MWAWVec2f(fDim[1],fDim[0]); |
334 | 0 | f << pt << ","; |
335 | 0 | } |
336 | 0 | f << "],"; |
337 | 0 | if (pts[0]!=pts[1]) { |
338 | 0 | MWAWVec2f dir=pts[1]-pts[0]; |
339 | 0 | gradient.m_angle=90-180*std::atan2(dir[1],dir[0])/float(M_PI); |
340 | 0 | } |
341 | 0 | float fDim[4]; |
342 | 0 | for (auto &d : fDim) d=float(input->readLong(4))/65536; |
343 | 0 | MWAWBox2f box=MWAWBox2f(MWAWVec2f(fDim[1],fDim[0]),MWAWVec2f(fDim[3],fDim[2])); |
344 | 0 | gradient.m_percentCenter=box.center(); |
345 | 0 | f << "box=" << box << ","; |
346 | 0 | int val=int(input->readULong(4)); |
347 | 0 | if (val==1) |
348 | 0 | f << "rainbow,"; |
349 | 0 | else if (val) { |
350 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readGradient: find unknown rainbow type\n")); |
351 | 0 | f << "##rainbow=" << val << ","; |
352 | 0 | } |
353 | 0 | val=int(input->readULong(2)); |
354 | 0 | if (val==1) |
355 | 0 | f << "rainbow[inverted],"; |
356 | 0 | else if (val) |
357 | 0 | f << "#rainbow[inverted]=" << val << ","; |
358 | 0 | val=int(input->readULong(1)); |
359 | 0 | if (val) |
360 | 0 | f << "h0=" << val << ","; |
361 | 0 | val=int(input->readULong(1)); |
362 | 0 | if (val!=0x13) |
363 | 0 | f << "h1=" << val << ","; |
364 | 0 | } |
365 | 0 | else { |
366 | 0 | for (int i=0; i<2; ++i) { |
367 | 0 | int val=int(input->readLong(4)); |
368 | 0 | int const expected[]= {vers<9 ? 0xdf : 0xfa, vers<9 ? 0x600 : 0x900}; |
369 | 0 | if (val!=expected[i]) |
370 | 0 | f << "f" << i << "=" << val << ","; |
371 | 0 | } |
372 | 0 | type=int(input->readLong(4)); |
373 | 0 | auto fl=input->readULong(4); |
374 | 0 | if (fl&1) |
375 | 0 | f << "rainbow,"; |
376 | 0 | if ((fl&0x100)==0) |
377 | 0 | f << "rainbow[inverted],"; |
378 | 0 | fl&=0xFFFFFEFE; |
379 | 0 | if (fl!=0x1000) |
380 | 0 | f << "fl=" << std::hex << fl << std::dec << ","; |
381 | 0 | MWAWVec2f pts[2]; |
382 | 0 | for (auto &pt : pts) { |
383 | 0 | float coords[2]; |
384 | 0 | for (auto &c : coords) c=float(m_mainParser->readDouble(*stream,vers<9 ? 4 : 8)); |
385 | 0 | pt=MWAWVec2f(coords[1],coords[0]); |
386 | 0 | } |
387 | 0 | if (type<=2) { |
388 | 0 | MWAWVec2f dir=pts[1]-pts[0]; |
389 | 0 | gradient.m_angle=90-180*std::atan2(dir[1],dir[0])/float(M_PI); |
390 | 0 | if (std::isnan(gradient.m_angle)) { |
391 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readGradient: can not compute the gradient angle\n")); |
392 | 0 | f << "###angle,"; |
393 | 0 | gradient.m_angle=0; |
394 | 0 | } |
395 | 0 | else if (gradient.m_angle<0 || gradient.m_angle>0) |
396 | 0 | f << "angle=" << gradient.m_angle << ","; |
397 | 0 | } |
398 | 0 | else { |
399 | 0 | MWAWBox2f box=MWAWBox2f(pts[0], pts[1]); |
400 | 0 | gradient.m_percentCenter=box.center(); |
401 | 0 | f << "box=" << box << ","; |
402 | 0 | } |
403 | 0 | N=unsigned(input->readULong(4)); |
404 | 0 | f << "N=" << N << ","; |
405 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
406 | 0 | ascFile.addPos(input->tell()+44); |
407 | 0 | ascFile.addNote("ObFl[unkn]:"); |
408 | 0 | } |
409 | 0 | if (long(N)<0 || (len-headerLength)/long(dataSize)<long(N) || headerLength+long(N)*long(dataSize)<headerLength || len<headerLength+long(N*dataSize)) { |
410 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readGradient: can not read N\n")); |
411 | 0 | f << "###"; |
412 | 0 | ascFile.addPos(pos); |
413 | 0 | ascFile.addNote(f.str().c_str()); |
414 | 0 | return false; |
415 | 0 | } |
416 | 0 | if (type>=1 && type<=5) { |
417 | 0 | char const *wh[]= {"radial", "directional", "shape", "rectangular", |
418 | 0 | "elliptical" |
419 | 0 | }; |
420 | 0 | MWAWGraphicStyle::Gradient::Type const types[]= { |
421 | 0 | MWAWGraphicStyle::Gradient::G_Radial, MWAWGraphicStyle::Gradient::G_Linear, |
422 | 0 | MWAWGraphicStyle::Gradient::G_Rectangular, MWAWGraphicStyle::Gradient::G_Rectangular, |
423 | 0 | MWAWGraphicStyle::Gradient::G_Ellipsoid |
424 | 0 | }; |
425 | 0 | gradient.m_type=types[type-1]; |
426 | 0 | f << wh[type-1] << ","; |
427 | 0 | } |
428 | 0 | else { |
429 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readGradient: find unknown type\n")); |
430 | 0 | f << "###type=" << type << ","; |
431 | 0 | } |
432 | 0 | ascFile.addPos(pos); |
433 | 0 | ascFile.addNote(f.str().c_str()); |
434 | |
|
435 | 0 | input->seek(pos+headerLength, librevenge::RVNG_SEEK_SET); |
436 | 0 | gradient.m_stopList.resize(size_t(N)); |
437 | 0 | for (size_t i=0; i<size_t(N); ++i) { |
438 | 0 | long actPos=input->tell(); |
439 | 0 | f.str(""); |
440 | 0 | f << "ObFl[stop" << i << "]:"; |
441 | 0 | MWAWGraphicStyle::Gradient::Stop &stop=gradient.m_stopList[size_t(N)-1-i]; |
442 | 0 | stop.m_offset=1-float(input->readLong(4))/100; |
443 | 0 | f << "pos=" << stop.m_offset << ","; |
444 | 0 | std::string extra; |
445 | 0 | MWAWVariable<MWAWColor> stopColor; |
446 | 0 | if (!readColor(*stream, stopColor, extra)) |
447 | 0 | input->seek(actPos+4+24, librevenge::RVNG_SEEK_SET); |
448 | 0 | else if (stopColor.isSet()) |
449 | 0 | stop.m_color=*stopColor; |
450 | 0 | f << extra; |
451 | 0 | if (vers>5) { |
452 | 0 | std::string name; |
453 | 0 | for (int j=0; j<32; ++j) { |
454 | 0 | char c=char(input->readULong(1)); |
455 | 0 | if (!c) |
456 | 0 | break; |
457 | 0 | name+=c; |
458 | 0 | } |
459 | 0 | f << name << ","; |
460 | 0 | input->seek(actPos+4+24+32, librevenge::RVNG_SEEK_SET); |
461 | 0 | } |
462 | 0 | ascFile.addPos(actPos); |
463 | 0 | ascFile.addNote(f.str().c_str()); |
464 | 0 | } |
465 | 0 | return true; |
466 | 0 | } |
467 | | |
468 | | bool Canvas5StyleManager::readHatch(std::shared_ptr<Canvas5Structure::Stream> stream, long len, |
469 | | MWAWGraphicStyle::Hatch &hatch, MWAWVariable<MWAWColor> &backColor) |
470 | 0 | { |
471 | 0 | hatch=MWAWGraphicStyle::Hatch(); |
472 | 0 | if (!stream || !stream->input()) |
473 | 0 | return false; |
474 | 0 | auto input=stream->input(); |
475 | 0 | long pos=input->tell(); |
476 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
477 | 0 | libmwaw::DebugStream f; |
478 | 0 | int const vers=version(); |
479 | 0 | int headerSz=vers<9 ? 8 : 12; |
480 | 0 | int const dataSz=vers<9 ? 104 : 192; |
481 | 0 | f << "Entries(Hatch):"; |
482 | 0 | if (len<headerSz+dataSz) { |
483 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readHatch: unexpected length\n")); |
484 | 0 | f << "###"; |
485 | 0 | ascFile.addPos(pos); |
486 | 0 | ascFile.addNote(f.str().c_str()); |
487 | 0 | return false; |
488 | 0 | } |
489 | 0 | unsigned sz=unsigned(input->readULong(4)); |
490 | 0 | f << "first[sz]=" << sz << ","; |
491 | 0 | int N=int(input->readULong(2)); |
492 | 0 | f << "N=" << N << ","; |
493 | 0 | if (int(sz)<0 || headerSz+long(sz)>len || (len-long(sz)-headerSz)/dataSz<N || |
494 | 0 | headerSz+int(sz+unsigned(dataSz)*unsigned(N))<headerSz+dataSz || |
495 | 0 | len<headerSz+long(sz+unsigned(dataSz)*unsigned(N))) { |
496 | 0 | f << "###"; |
497 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readHatch: the number of line seems bad\n")); |
498 | 0 | ascFile.addPos(pos); |
499 | 0 | ascFile.addNote(f.str().c_str()); |
500 | 0 | return false; |
501 | 0 | } |
502 | 0 | int val; |
503 | 0 | if (vers<9) { |
504 | 0 | val=int(input->readULong(2)); |
505 | 0 | if (val!=0xf6f6) f << "fl=" << std::hex << val << std::dec << ","; |
506 | 0 | } |
507 | 0 | else { |
508 | 0 | for (int i=0; i<3; ++i) { // f2=0|1 |
509 | 0 | val=int(input->readLong(2)); |
510 | 0 | if (!val) continue; |
511 | 0 | f << "f" << i << "=" << val << ","; |
512 | 0 | } |
513 | 0 | } |
514 | 0 | ascFile.addPos(pos); |
515 | 0 | ascFile.addNote(f.str().c_str()); |
516 | |
|
517 | 0 | if (sz) { |
518 | 0 | pos=input->tell(); |
519 | 0 | f.str(""); |
520 | 0 | f << "Hatch[color,back]:"; |
521 | 0 | unsigned type=unsigned(input->readULong(4)); |
522 | 0 | if (sz>4) { |
523 | 0 | auto bgColor=readColorStyle(stream, type, sz-4); |
524 | 0 | if (!bgColor) |
525 | 0 | f << "###"; |
526 | 0 | else { |
527 | 0 | backColor=bgColor->m_color; |
528 | 0 | f << *bgColor; |
529 | 0 | ascFile.addPos(pos+4); |
530 | 0 | ascFile.addNote(f.str().c_str()); |
531 | 0 | } |
532 | 0 | } |
533 | 0 | else if (type!=0) |
534 | 0 | f << "###"; |
535 | 0 | ascFile.addPos(pos); |
536 | 0 | ascFile.addNote(f.str().c_str()); |
537 | 0 | input->seek(pos+sz, librevenge::RVNG_SEEK_SET); |
538 | 0 | } |
539 | 0 | if (N<=0) |
540 | 0 | return true; |
541 | | |
542 | 0 | hatch.m_type= N==1 ? MWAWGraphicStyle::Hatch::H_Single : |
543 | 0 | N==2 ? MWAWGraphicStyle::Hatch::H_Double : MWAWGraphicStyle::Hatch::H_Triple; |
544 | 0 | float offset=0; |
545 | 0 | for (int i=0; i<N; ++i) { |
546 | 0 | pos=input->tell(); |
547 | 0 | f.str(""); |
548 | 0 | f << "Hatch-L" << i << ":"; |
549 | 0 | double w=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
550 | 0 | if (w<0 || w>0) |
551 | 0 | f << "w=" << w << ","; |
552 | 0 | double angle=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
553 | 0 | if (angle<0 || angle>0) |
554 | 0 | f << "angle=" << angle << ","; |
555 | 0 | if (i==0) |
556 | 0 | hatch.m_rotation=90-float(angle); |
557 | 0 | double offs=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
558 | 0 | offset+=float(offs); |
559 | 0 | f << "offset=" << offs << ","; |
560 | 0 | double orig=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
561 | 0 | if (orig<0 || orig>0) |
562 | 0 | f << "orig=" << orig << ","; |
563 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
564 | 0 | input->seek(pos+dataSz-24, librevenge::RVNG_SEEK_SET); |
565 | 0 | ascFile.addPos(pos); |
566 | 0 | ascFile.addNote(f.str().c_str()); |
567 | |
|
568 | 0 | pos=input->tell(); |
569 | 0 | f.str(""); |
570 | 0 | f << "Hatch-C" << i << ":"; |
571 | 0 | std::string extra; |
572 | 0 | MWAWVariable<MWAWColor> col; |
573 | 0 | if (!readColor(*stream, col, extra)) |
574 | 0 | input->seek(pos+24, librevenge::RVNG_SEEK_SET); |
575 | 0 | else if (col.isSet()) |
576 | 0 | hatch.m_color=*col; |
577 | 0 | f << extra; |
578 | 0 | ascFile.addPos(pos); |
579 | 0 | ascFile.addNote(f.str().c_str()); |
580 | 0 | } |
581 | 0 | hatch.m_distance=offset/float(N)/72; |
582 | 0 | return true; |
583 | 0 | } |
584 | | |
585 | | bool Canvas5StyleManager::readArrows(std::shared_ptr<Canvas5Structure::Stream> stream) |
586 | 0 | { |
587 | 0 | if (!stream) { |
588 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readArrows: no stream\n")); |
589 | 0 | return false; |
590 | 0 | } |
591 | 0 | auto input=stream->input(); |
592 | 0 | long pos=input->tell(); |
593 | |
|
594 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
595 | 0 | libmwaw::DebugStream f; |
596 | 0 | f << "Entries(Arrow):"; |
597 | 0 | ascFile.addPos(pos); |
598 | 0 | ascFile.addNote(f.str().c_str()); |
599 | 0 | if (!m_mainParser->readUsed(*stream, "Arrow")) // checkme: probably a type |
600 | 0 | return false; |
601 | | |
602 | 0 | if (!m_mainParser->readIndexMap(stream, "Arrow", |
603 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
604 | 0 | auto lInput=lStream->input(); |
605 | 0 | libmwaw::DebugStream lF; |
606 | 0 | auto &asciiFile=lStream->ascii(); |
607 | 0 | lF << "Arrow" << item.m_id << ","; |
608 | 0 | MWAWGraphicStyle::Arrow arrow; |
609 | 0 | if (!readArrow(lStream, arrow, 1, item.m_length)) |
610 | 0 | lF << "###"; |
611 | 0 | else |
612 | 0 | m_state->m_idToArrow[item.m_id]=arrow; |
613 | 0 | asciiFile.addPos(item.m_pos); |
614 | 0 | asciiFile.addNote(lF.str().c_str()); |
615 | 0 | })) |
616 | 0 | return false; |
617 | 0 | return true; |
618 | 0 | } |
619 | | |
620 | | bool Canvas5StyleManager::readArrow(std::shared_ptr<Canvas5Structure::Stream> stream, MWAWGraphicStyle::Arrow &arrow, unsigned, long len) |
621 | 0 | { |
622 | 0 | if (!stream) { |
623 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readArrow: no stream\n")); |
624 | 0 | return false; |
625 | 0 | } |
626 | 0 | auto input=stream->input(); |
627 | 0 | long pos=input->tell(); |
628 | 0 | int const vers=version(); |
629 | 0 | int const headerLen=vers<9 ? 24 : 88; |
630 | 0 | if (len<headerLen || !input->checkPosition(pos+headerLen)) { |
631 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readArrow: file is to short\n")); |
632 | 0 | return false; |
633 | 0 | } |
634 | 0 | auto &ascFile=stream->ascii(); |
635 | 0 | libmwaw::DebugStream f; |
636 | 0 | long dataLen=long(input->readULong(4)); |
637 | 0 | if (dataLen==len) dataLen=len-headerLen; // can happen sometimes |
638 | 0 | if (pos+headerLen+dataLen<pos+headerLen || headerLen+dataLen>len) { |
639 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readArrow: can not read the arrow's data size\n")); |
640 | 0 | return false; |
641 | 0 | } |
642 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
643 | 0 | ascFile.addPos(pos); |
644 | 0 | ascFile.addNote(f.str().c_str()); |
645 | 0 | input->seek(pos+headerLen, librevenge::RVNG_SEEK_SET); |
646 | |
|
647 | 0 | if (headerLen+dataLen!=len) { |
648 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readArrow: find unknown length data\n")); |
649 | 0 | ascFile.addPos(pos+headerLen+dataLen); |
650 | 0 | ascFile.addNote("Arrow-End:###"); |
651 | 0 | } |
652 | |
|
653 | 0 | if (dataLen==0) { |
654 | 0 | arrow=MWAWGraphicStyle::Arrow(); |
655 | 0 | return true; |
656 | 0 | } |
657 | 0 | std::shared_ptr<Canvas5ImageInternal::VKFLImage> image; |
658 | 0 | if (!getImageParser()->readVKFL(stream, dataLen, image) || !image |
659 | 0 | || !getImageParser()->getArrow(image, arrow)) |
660 | 0 | arrow=MWAWGraphicStyle::Arrow::plain(); |
661 | |
|
662 | 0 | return true; |
663 | 0 | } |
664 | | |
665 | | bool Canvas5StyleManager::readInks(std::shared_ptr<Canvas5Structure::Stream> stream) |
666 | 0 | { |
667 | 0 | if (!stream || !stream->input()) |
668 | 0 | return false; |
669 | 0 | auto input=stream->input(); |
670 | 0 | long pos=input->tell(); |
671 | |
|
672 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
673 | 0 | libmwaw::DebugStream f; |
674 | 0 | f << "Entries(Color):type,"; |
675 | 0 | ascFile.addPos(pos); |
676 | 0 | ascFile.addNote(f.str().c_str()); |
677 | |
|
678 | 0 | std::map<int, std::pair<unsigned, int> > idToTypeNameMap; |
679 | 0 | if (!m_mainParser->readExtendedHeader(stream, 8, "Color", |
680 | 0 | [&idToTypeNameMap](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
681 | 0 | auto lInput=lStream->input(); |
682 | 0 | libmwaw::DebugStream lF; |
683 | 0 | auto &asciiFile=lStream->ascii(); |
684 | 0 | lF << "Co" << item.m_id << "[type]:"; |
685 | 0 | Canvas5StyleManagerInternal::ColorStyle color; |
686 | 0 | unsigned type=unsigned(lInput->readULong(4)); // 1, TXUR: texture, ObFl, htch: hatch, vkfl: symbol |
687 | 0 | if (type!=1) |
688 | 0 | lF << "type=" << Canvas5Structure::getString(type) << ","; |
689 | 0 | int nameId=int(lInput->readLong(4)); |
690 | 0 | if (nameId) |
691 | 0 | lF << "id[name]=" << nameId << ","; |
692 | 0 | idToTypeNameMap[item.m_id]=std::make_pair(type,nameId); |
693 | 0 | asciiFile.addPos(item.m_pos); |
694 | 0 | asciiFile.addNote(lF.str().c_str()); |
695 | 0 | })) |
696 | 0 | return false; |
697 | | |
698 | 0 | if (!m_mainParser->readIndexMap(stream, "Color", |
699 | 0 | [this, &idToTypeNameMap](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
700 | 0 | auto lInput=lStream->input(); |
701 | 0 | libmwaw::DebugStream lF; |
702 | 0 | auto &asciiFile=lStream->ascii(); |
703 | 0 | lF << "Co" << item.m_id << ","; |
704 | 0 | unsigned type=1; |
705 | 0 | int nameId=0; |
706 | 0 | auto const &it=idToTypeNameMap.find(item.m_id); |
707 | 0 | if (it!=idToTypeNameMap.end()) |
708 | 0 | std::tie(type,nameId)=it->second; |
709 | 0 | auto color=readColorStyle(lStream, type, item.m_length); |
710 | 0 | if (color) { |
711 | 0 | color->m_nameId=nameId; |
712 | 0 | m_state->m_idToColor[item.m_id]=color; |
713 | 0 | } |
714 | 0 | else |
715 | 0 | lF << "###"; |
716 | 0 | asciiFile.addPos(item.m_pos); |
717 | 0 | asciiFile.addNote(lF.str().c_str()); |
718 | 0 | })) |
719 | 0 | return false; |
720 | | |
721 | 0 | if (!m_mainParser->readUsed(*stream, "Color")) |
722 | 0 | return false; |
723 | | |
724 | 0 | std::multimap<int,int> nameIdToColor; |
725 | 0 | for (auto &it : m_state->m_idToColor) { |
726 | 0 | if (it.second && it.second->m_nameId) |
727 | 0 | nameIdToColor.insert(std::make_pair(it.second->m_nameId, it.first)); |
728 | 0 | } |
729 | |
|
730 | 0 | pos=input->tell(); |
731 | 0 | f.str(""); |
732 | 0 | f << "Color:names"; |
733 | 0 | int N; |
734 | 0 | if (!m_mainParser->readDataHeader(*stream, 4, N)) { |
735 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readInks: can not read the last zone N\n")); |
736 | 0 | f << "###"; |
737 | 0 | ascFile.addPos(pos); |
738 | 0 | ascFile.addNote(f.str().c_str()); |
739 | 0 | return false; |
740 | 0 | } |
741 | 0 | f << "N=" << N << ","; |
742 | 0 | f << "id=["; |
743 | 0 | for (int i=0; i<N; ++i) f << input->readLong(4) << ","; |
744 | 0 | f << "],"; |
745 | 0 | ascFile.addPos(pos); |
746 | 0 | ascFile.addNote(f.str().c_str()); |
747 | |
|
748 | 0 | return m_mainParser->readIndexMap(stream, "Color", |
749 | 0 | [&nameIdToColor](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
750 | 0 | auto lInput=lStream->input(); |
751 | 0 | libmwaw::DebugStream lF; |
752 | 0 | auto &asciiFile=lStream->ascii(); |
753 | 0 | std::string name; |
754 | 0 | for (int i=0; i<int(item.m_length); ++i) { |
755 | 0 | char c=char(lInput->readULong(1)); |
756 | 0 | if (c==0) |
757 | 0 | break; |
758 | 0 | name+=c; |
759 | 0 | } |
760 | 0 | lF << name << ","; |
761 | 0 | auto it = nameIdToColor.find(item.m_id); |
762 | 0 | lF << "["; |
763 | 0 | while (it!=nameIdToColor.end() && it->first==item.m_id) { |
764 | 0 | lF << "Co" << it->second << ","; |
765 | 0 | ++it; |
766 | 0 | } |
767 | 0 | lF << "],"; |
768 | 0 | asciiFile.addPos(item.m_pos); |
769 | 0 | asciiFile.addNote(lF.str().c_str()); |
770 | 0 | }); |
771 | 0 | } |
772 | | |
773 | | |
774 | | bool Canvas5StyleManager::readInks9(std::shared_ptr<Canvas5Structure::Stream> stream) |
775 | 0 | { |
776 | 0 | if (!stream || !stream->input()) |
777 | 0 | return false; |
778 | 0 | auto input=stream->input(); |
779 | 0 | auto &ascFile=stream->ascii(); |
780 | 0 | long pos=input->tell(); |
781 | 0 | libmwaw::DebugStream f; |
782 | 0 | f << "Entries(Color)[list]:"; |
783 | 0 | ascFile.addPos(pos); |
784 | 0 | ascFile.addNote(f.str().c_str()); |
785 | |
|
786 | 0 | if (!m_mainParser->readArray9(stream, "Color", |
787 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
788 | 0 | auto lInput=lStream->input(); |
789 | 0 | libmwaw::DebugStream lF; |
790 | 0 | auto &asciiFile=lStream->ascii(); |
791 | 0 | if (item.m_length<8) { |
792 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readInks9: can not find the color type\n")); |
793 | 0 | lF << "###"; |
794 | 0 | asciiFile.addPos(item.m_pos); |
795 | 0 | asciiFile.addNote(lF.str().c_str()); |
796 | 0 | return; |
797 | 0 | } |
798 | 0 | lF << "Co" << item.m_id << ","; |
799 | 0 | int lVal=int(lInput->readLong(4)); |
800 | 0 | if (lVal!=item.m_id) |
801 | 0 | lF << "#g0=" << lVal << ","; |
802 | 0 | long len2=long(lInput->readULong(4)); |
803 | 0 | auto color=readColorStyle(lStream, item.m_type, std::min(item.m_length-8,len2)); |
804 | 0 | if (color) |
805 | 0 | m_state->m_idToColor[item.m_id]=color; |
806 | 0 | else |
807 | 0 | lF << "###"; |
808 | 0 | asciiFile.addPos(item.m_pos); |
809 | 0 | asciiFile.addNote(lF.str().c_str()); |
810 | 0 | })) |
811 | 0 | return false; |
812 | 0 | if (!m_mainParser->readArray9(stream, "Color[name]", &Canvas5Parser::stringDataFunction)) |
813 | 0 | return false; |
814 | 0 | pos=input->tell(); |
815 | 0 | if (!input->checkPosition(pos+4)) { |
816 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readInks9: can not find the array block\n")); |
817 | 0 | ascFile.addPos(pos); |
818 | 0 | ascFile.addNote("Color-End###"); |
819 | 0 | return false; |
820 | 0 | } |
821 | 0 | pos=input->tell(); |
822 | 0 | f.str(""); |
823 | 0 | f << "Color-End:"; |
824 | 0 | int val=int(input->readLong(4)); |
825 | 0 | if (val!=-1) // checkme: maybe another length |
826 | 0 | f << "f0=" << val << ","; |
827 | 0 | ascFile.addPos(pos); |
828 | 0 | ascFile.addNote(f.str().c_str()); |
829 | 0 | return true; |
830 | 0 | } |
831 | | |
832 | | std::shared_ptr<Canvas5StyleManagerInternal::ColorStyle> Canvas5StyleManager::readColorStyle(std::shared_ptr<Canvas5Structure::Stream> stream, unsigned type, long len) |
833 | 0 | { |
834 | 0 | if (!stream || !stream->input()) { |
835 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readColorStyle: can not find the input\n")); |
836 | 0 | return nullptr; |
837 | 0 | } |
838 | 0 | auto input=stream->input(); |
839 | 0 | long pos=input->tell(); |
840 | 0 | if (len<0 || !input->checkPosition(pos+len)) { |
841 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readColorStyle: the zone seems too short\n")); |
842 | 0 | return nullptr; |
843 | 0 | } |
844 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
845 | 0 | libmwaw::DebugStream f; |
846 | 0 | if (version()>=9) |
847 | 0 | f << "Color:"; |
848 | 0 | auto color=std::make_shared<Canvas5StyleManagerInternal::ColorStyle>(); |
849 | 0 | color->m_type=type; |
850 | 0 | switch (type) { |
851 | 0 | case 0: |
852 | 0 | if (len==24) { // gray? |
853 | 0 | std::string extra; |
854 | 0 | if (!readColor(*stream, color->m_color, extra)) { |
855 | 0 | color->m_color.setSet(false); |
856 | 0 | f << "##"; |
857 | 0 | } |
858 | 0 | f << extra << ","; |
859 | 0 | break; |
860 | 0 | } |
861 | 0 | if (len!=4) { |
862 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readColorStyle: unexpected length\n")); |
863 | 0 | f << "###"; |
864 | 0 | break; |
865 | 0 | } |
866 | 0 | color->m_color=MWAWColor(0,0,0,0); |
867 | 0 | for (int i=0; i<2; ++i) { |
868 | 0 | int val=int(input->readLong(2)); |
869 | 0 | if (val) |
870 | 0 | f << "f" << i << "=" << val << ","; |
871 | 0 | } |
872 | 0 | break; |
873 | 0 | case 1: { |
874 | 0 | if (len<24) { |
875 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readColorStyle: unexpected length\n")); |
876 | 0 | f << "###"; |
877 | 0 | break; |
878 | 0 | } |
879 | 0 | std::string extra; |
880 | 0 | if (!readColor(*stream, color->m_color, extra)) { |
881 | 0 | color->m_color.setSet(false); |
882 | 0 | f << "##"; |
883 | 0 | } |
884 | 0 | f << extra << ","; |
885 | 0 | if (len==24 || version()<=5) |
886 | 0 | break; |
887 | | // normally only in v6 |
888 | 0 | std::string name; |
889 | 0 | for (int i=0; i<len-24; ++i) { |
890 | 0 | char c=char(input->readULong(1)); |
891 | 0 | if (!c) |
892 | 0 | break; |
893 | 0 | name+=c; |
894 | 0 | } |
895 | 0 | f << name << ","; |
896 | 0 | break; |
897 | 0 | } |
898 | 0 | case 0x68746368: { // htch |
899 | 0 | color->m_color=MWAWColor(0,0,0,0); |
900 | 0 | color->m_color.setSet(false); |
901 | 0 | if (!readHatch(stream, len, color->m_hatch, color->m_color)) |
902 | 0 | f << "###"; |
903 | 0 | break; |
904 | 0 | } |
905 | 0 | case 0x4f62466c: // ObFl |
906 | 0 | color->m_color.setSet(false); |
907 | 0 | f << "ObFl,"; |
908 | 0 | if (!readGradient(stream, len, color->m_gradient)) |
909 | 0 | f << "###"; |
910 | 0 | break; |
911 | 0 | case 0x50415453: // PATS: v9 |
912 | 0 | case 0x54585552: { // TXUR |
913 | 0 | MWAWVariable<MWAWColor> bgColor; |
914 | 0 | auto image=readSymbol(stream, len, bgColor); |
915 | 0 | MWAWColor avgColor; |
916 | 0 | color->m_color.setSet(false); |
917 | 0 | if (!image || !getImageParser()->getTexture(image, color->m_texture, color->m_textureDim, avgColor)) |
918 | 0 | f << "###"; |
919 | 0 | else |
920 | 0 | color->m_color=avgColor; |
921 | 0 | break; |
922 | 0 | } |
923 | 0 | case 0x766b666c: { // vkfl |
924 | 0 | color->m_color=MWAWColor(0,0,0,0); |
925 | 0 | color->m_color.setSet(false); |
926 | 0 | if (!readSymbol(stream, len, color->m_color)) |
927 | 0 | f << "###"; |
928 | 0 | break; |
929 | 0 | } |
930 | 0 | default: { |
931 | 0 | static bool first=true; |
932 | 0 | if (first) { |
933 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readColorStyle: can not read some complex ink color\n")); |
934 | 0 | first=false; |
935 | 0 | } |
936 | 0 | f << "type=" << Canvas5Structure::getString(color->m_type) << "##"; |
937 | 0 | color->m_color.setSet(false); |
938 | 0 | break; |
939 | 0 | } |
940 | 0 | } |
941 | 0 | ascFile.addPos(pos); |
942 | 0 | ascFile.addNote(f.str().c_str()); |
943 | 0 | return color; |
944 | 0 | } |
945 | | |
946 | | std::shared_ptr<Canvas5ImageInternal::VKFLImage> Canvas5StyleManager::readSymbol |
947 | | (std::shared_ptr<Canvas5Structure::Stream> stream, long len, MWAWVariable<MWAWColor> &backColor) |
948 | 0 | { |
949 | 0 | if (!stream || !stream->input()) { |
950 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readSymbol: bad input\n")); |
951 | 0 | return nullptr; |
952 | 0 | } |
953 | 0 | auto input=stream->input(); |
954 | 0 | long pos=input->tell(); |
955 | 0 | int const vers=version(); |
956 | 0 | int const headerLen=vers<9 ? 36 : 56; |
957 | 0 | if (len<headerLen || !input->checkPosition(pos+len)) { |
958 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readSymbol: the zone seems too short\n")); |
959 | 0 | return nullptr; |
960 | 0 | } |
961 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
962 | 0 | libmwaw::DebugStream f; |
963 | 0 | f << "Entries(Symbol):"; |
964 | 0 | for (int i=0; i<5; ++i) { |
965 | 0 | double value=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
966 | 0 | if (value<=0 && value>=0) |
967 | 0 | continue; |
968 | 0 | char const *wh[]= { "deplX", "deplY", "stagger", "rotation", "scale" }; |
969 | 0 | f << wh[i] << "=" << value << ","; |
970 | 0 | } |
971 | 0 | long sz=input->readLong(4); |
972 | 0 | f << "sz=" << sz << ","; |
973 | 0 | long endSize=long(input->readULong(4)); |
974 | 0 | if (endSize) |
975 | 0 | f << "sz[end]=" << endSize << ","; |
976 | 0 | long endPos=pos+headerLen+sz; |
977 | 0 | if (sz<0 || endSize<0 || headerLen+sz+endSize<0 || headerLen+sz+endSize>len) { |
978 | 0 | f << "###"; |
979 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readSymbol: can not read the symbox sz\n")); |
980 | 0 | ascFile.addPos(pos); |
981 | 0 | ascFile.addNote(f.str().c_str()); |
982 | 0 | return nullptr; |
983 | 0 | } |
984 | 0 | int val; |
985 | 0 | for (int i=0; i<2; ++i) { // g0=0|2e2e, g1=0|c3|e6e6 |
986 | 0 | val=int(input->readLong(2)); |
987 | 0 | if (val) |
988 | 0 | f << "g" << i << "=" << std::hex << val << std::dec << ","; |
989 | 0 | } |
990 | 0 | val=int(input->readLong(1)); |
991 | 0 | if (val!=1) f << "type?=" << val << ","; |
992 | 0 | input->seek(3, librevenge::RVNG_SEEK_CUR); |
993 | 0 | ascFile.addPos(pos); |
994 | 0 | ascFile.addNote(f.str().c_str()); |
995 | |
|
996 | 0 | std::shared_ptr<Canvas5ImageInternal::VKFLImage> image; |
997 | 0 | if (sz>0) |
998 | 0 | getImageParser()->readVKFL(stream, sz, image); |
999 | |
|
1000 | 0 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1001 | 0 | if (!endSize) |
1002 | 0 | return image; |
1003 | | |
1004 | 0 | f.str(""); |
1005 | 0 | f << "Symbol-End:"; |
1006 | 0 | if (endSize>4) { |
1007 | 0 | unsigned type=unsigned(input->readULong(4)); |
1008 | 0 | f << Canvas5Structure::getString(type) << ","; |
1009 | 0 | auto endColor=readColorStyle(stream, type, endSize-4); |
1010 | 0 | if (!endColor) |
1011 | 0 | f << "###"; |
1012 | 0 | else { |
1013 | 0 | backColor=endColor->m_color; |
1014 | 0 | ascFile.addPos(endPos+4); |
1015 | 0 | ascFile.addNote(f.str().c_str()); |
1016 | 0 | } |
1017 | 0 | } |
1018 | 0 | ascFile.addPos(endPos); |
1019 | 0 | ascFile.addNote(f.str().c_str()); |
1020 | |
|
1021 | 0 | return image; |
1022 | 0 | } |
1023 | | |
1024 | | bool Canvas5StyleManager::readDashes(std::shared_ptr<Canvas5Structure::Stream> stream) |
1025 | 0 | { |
1026 | 0 | if (!stream || !stream->input()) |
1027 | 0 | return false; |
1028 | 0 | auto input=stream->input(); |
1029 | 0 | long pos=input->tell(); |
1030 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
1031 | 0 | libmwaw::DebugStream f; |
1032 | 0 | f << "Entries(Dash):"; |
1033 | 0 | ascFile.addPos(pos); |
1034 | 0 | ascFile.addNote(f.str().c_str()); |
1035 | |
|
1036 | 0 | if (!m_mainParser->readUsed(*stream, "Dash")) // checkme: probably a type list |
1037 | 0 | return false; |
1038 | | |
1039 | 0 | return m_mainParser->readExtendedHeader(stream, 64, "Dash", |
1040 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
1041 | 0 | auto lInput=lStream->input(); |
1042 | 0 | libmwaw::DebugFile &asciiFile = lStream->ascii(); |
1043 | 0 | libmwaw::DebugStream lF; |
1044 | 0 | lF << "Da" << item.m_id << ","; |
1045 | 0 | std::vector<float> dashes; |
1046 | 0 | if (!readDash(*lStream, dashes, 1, item.m_length)) |
1047 | 0 | lF << "###"; |
1048 | 0 | else |
1049 | 0 | m_state->m_idToDash[item.m_id]=dashes; |
1050 | 0 | asciiFile.addPos(item.m_pos); |
1051 | 0 | asciiFile.addNote(lF.str().c_str()); |
1052 | 0 | }); |
1053 | 0 | } |
1054 | | |
1055 | | bool Canvas5StyleManager::readDash(Canvas5Structure::Stream &stream, std::vector<float> &dashes, unsigned /*type*/, long len) |
1056 | 0 | { |
1057 | 0 | dashes.clear(); |
1058 | 0 | MWAWInputStreamPtr input = stream.input(); |
1059 | 0 | long pos=input->tell(); |
1060 | 0 | int const vers=version(); |
1061 | 0 | int expectedSize=vers<9 ? 64 : 136; |
1062 | 0 | if (len<expectedSize || !input->checkPosition(pos+expectedSize)) { |
1063 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readDash: the zone seems too short\n")); |
1064 | 0 | return false; |
1065 | 0 | } |
1066 | | |
1067 | 0 | libmwaw::DebugFile &ascFile = stream.ascii(); |
1068 | 0 | libmwaw::DebugStream f; |
1069 | 0 | f << "Entries(Dash):"; |
1070 | 0 | int val; |
1071 | 0 | for (int i=0; i<2; ++i) { |
1072 | 0 | val=int(input->readLong(2)); |
1073 | 0 | if (val) |
1074 | 0 | f << "f" << i << "=" << val << ","; |
1075 | 0 | } |
1076 | 0 | int N; |
1077 | 0 | bool inverted=input->readInverted(); |
1078 | 0 | if (vers<9) { |
1079 | 0 | N=int(input->readLong(2)); |
1080 | 0 | val=int(input->readLong(2)); |
1081 | 0 | if (val!=1) f << "f2=" << val << ","; |
1082 | 0 | } |
1083 | 0 | else { |
1084 | 0 | input->seek(pos+124, librevenge::RVNG_SEEK_SET); |
1085 | 0 | N=int(input->readLong(2)); // checkme: maybe 4 |
1086 | 0 | for (int i=0; i<5; ++i) { |
1087 | 0 | val=int(input->readLong(2)); |
1088 | 0 | if (val!=(i==0 ? 1 : 0)) f << "f" << i+1 << "=" << val << ","; |
1089 | 0 | } |
1090 | 0 | input->seek(pos+4, librevenge::RVNG_SEEK_SET); |
1091 | 0 | } |
1092 | 0 | f << "N=" << N << ","; |
1093 | 0 | if (N>14) { |
1094 | 0 | if (N>0 && (N%512)==0 && (N>>8)<14) { // look for potential inversion and N even |
1095 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readDash: endian seems inverted\n")); |
1096 | 0 | input->setReadInverted(!inverted); |
1097 | 0 | N=(N>>8); |
1098 | 0 | f << "#N=" << N << ","; |
1099 | 0 | } |
1100 | 0 | else { |
1101 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readDash: N seems bad\n")); |
1102 | 0 | f << "###"; |
1103 | 0 | N=0; |
1104 | 0 | } |
1105 | 0 | } |
1106 | 0 | f << "dash=["; |
1107 | 0 | for (int i=0; i<N; ++i) { |
1108 | 0 | double value=m_mainParser->readDouble(stream, vers<9 ? 4 : 8); |
1109 | 0 | dashes.push_back(float(value)); |
1110 | 0 | f << value << ","; |
1111 | 0 | } |
1112 | 0 | f << "],"; |
1113 | 0 | input->setReadInverted(inverted); |
1114 | 0 | ascFile.addPos(pos); |
1115 | 0 | ascFile.addNote(f.str().c_str()); |
1116 | 0 | return true; |
1117 | 0 | } |
1118 | | |
1119 | | bool Canvas5StyleManager::readFonts(std::shared_ptr<Canvas5Structure::Stream> stream, int numFonts) |
1120 | 0 | { |
1121 | 0 | if (!stream || !stream->input()) |
1122 | 0 | return false; |
1123 | 0 | MWAWInputStreamPtr input = stream->input(); |
1124 | 0 | long pos=input->tell(); |
1125 | 0 | if (numFonts<=0 || !input->checkPosition(pos+136*numFonts)) { |
1126 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readFonts: zone seems too short\n")); |
1127 | 0 | return false; |
1128 | 0 | } |
1129 | | |
1130 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
1131 | 0 | libmwaw::DebugStream f; |
1132 | 0 | f << "Entries(Font):N=" << numFonts << ","; |
1133 | 0 | ascFile.addPos(pos-4); |
1134 | 0 | ascFile.addNote(f.str().c_str()); |
1135 | |
|
1136 | 0 | auto fontConverter=m_parserState->m_fontConverter; |
1137 | 0 | std::string const family=m_mainParser->isWindowsFile() ? "CP1252" : ""; |
1138 | 0 | for (int fo=0; fo<numFonts; ++fo) { |
1139 | 0 | pos=input->tell(); |
1140 | 0 | f.str(""); |
1141 | 0 | f << "Font-F" << fo << ":"; |
1142 | 0 | int id=int(input->readULong(2)); |
1143 | 0 | f << "id=" << id << ","; |
1144 | 0 | for (int i=0; i<3; ++i) { |
1145 | 0 | int val=int(input->readLong(2)); |
1146 | 0 | if (val!=(i==0 ? 4 : 0)) f << "f" << i << "=" << val << ","; |
1147 | 0 | } |
1148 | 0 | int dSz=int(input->readULong(1)); |
1149 | 0 | if (dSz>=127) { |
1150 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readFonts: can not read a name\n")); |
1151 | 0 | f << "###name"; |
1152 | 0 | } |
1153 | 0 | else { |
1154 | 0 | std::string name; |
1155 | 0 | for (int s=0; s<dSz; ++s) name+=char(input->readULong(1)); |
1156 | 0 | if (!name.empty()) |
1157 | 0 | fontConverter->setCorrespondance(fo+1, name, family); |
1158 | 0 | f << name << ","; |
1159 | 0 | } |
1160 | 0 | ascFile.addPos(pos); |
1161 | 0 | ascFile.addNote(f.str().c_str()); |
1162 | 0 | input->seek(pos+136, librevenge::RVNG_SEEK_SET); |
1163 | 0 | } |
1164 | 0 | return true; |
1165 | 0 | } |
1166 | | |
1167 | | bool Canvas5StyleManager::readFormats(std::shared_ptr<Canvas5Structure::Stream> stream) |
1168 | 0 | { |
1169 | 0 | if (!stream || !stream->input()) { |
1170 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readFormats: can not find the input\n")); |
1171 | 0 | return false; |
1172 | 0 | } |
1173 | 0 | auto input=stream->input(); |
1174 | 0 | long pos=input ? input->tell() : 0; |
1175 | 0 | if (!input || !input->checkPosition(pos+7*44+4)) { |
1176 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readFormats: file is too short\n")); |
1177 | 0 | return false; |
1178 | 0 | } |
1179 | | |
1180 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
1181 | 0 | libmwaw::DebugStream f; |
1182 | 0 | f << "Entries(Format):"; |
1183 | 0 | ascFile.addPos(pos); |
1184 | 0 | ascFile.addNote(f.str().c_str()); |
1185 | |
|
1186 | 0 | for (int fo=0; fo<7; ++fo) { |
1187 | 0 | pos=input->tell(); |
1188 | 0 | f.str(""); |
1189 | 0 | f << "Format-" << fo << ":"; |
1190 | 0 | int val=int(input->readLong(2)); |
1191 | 0 | if (val) // small integer |
1192 | 0 | f << "f0=" << val << ","; |
1193 | 0 | val=int(input->readLong(2)); // 1|a|c|10 |
1194 | 0 | f << "f1=" << val << ","; |
1195 | 0 | for (int i=0; i<2; ++i) { // f2=0|1, f3=0|3|10 |
1196 | 0 | val=int(input->readLong(2)); |
1197 | 0 | if (val) |
1198 | 0 | f << "f" << i+2 << "=" << val << ","; |
1199 | 0 | } |
1200 | 0 | for (int i=0; i<4; ++i) { |
1201 | 0 | val=int(input->readULong(4)); |
1202 | 0 | if (val!=0x10000) |
1203 | 0 | f << "dim" << i << "=" << double(val)/double(0x10000) << ","; |
1204 | 0 | } |
1205 | 0 | int len=int(input->readULong(1)); |
1206 | 0 | if (len<=19) { |
1207 | 0 | std::string text; |
1208 | 0 | for (int i=0; i<len; ++i) text+=char(input->readULong(1)); |
1209 | 0 | f << "name=" << text << ","; |
1210 | 0 | } |
1211 | 0 | else { |
1212 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readFormats: can not read the format name\n")); |
1213 | 0 | f << "###name,"; |
1214 | 0 | } |
1215 | 0 | ascFile.addPos(pos); |
1216 | 0 | ascFile.addNote(f.str().c_str()); |
1217 | 0 | input->seek(pos+44, librevenge::RVNG_SEEK_SET); |
1218 | 0 | if (fo!=0) continue; |
1219 | | |
1220 | 0 | pos=input->tell(); |
1221 | 0 | f.str(""); |
1222 | 0 | f << "Format-unk:"; |
1223 | 0 | for (int i=0; i<2; ++i) { // f0: small number |
1224 | 0 | val=int(input->readLong(2)); |
1225 | 0 | if (val) |
1226 | 0 | f << "f" << i << "=" << val << ","; |
1227 | 0 | } |
1228 | 0 | ascFile.addPos(pos); |
1229 | 0 | ascFile.addNote(f.str().c_str()); |
1230 | 0 | } |
1231 | 0 | return true; |
1232 | 0 | } |
1233 | | |
1234 | | bool Canvas5StyleManager::readPenSize(std::shared_ptr<Canvas5Structure::Stream> stream) |
1235 | 0 | { |
1236 | 0 | if (!stream || !stream->input()) { |
1237 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readPenSize: can not find the input\n")); |
1238 | 0 | return false; |
1239 | 0 | } |
1240 | 0 | auto input=stream->input(); |
1241 | 0 | long pos=input->tell(); |
1242 | 0 | if (!input->checkPosition(pos+20)) { |
1243 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readPenSize: file is too short\n")); |
1244 | 0 | return false; |
1245 | 0 | } |
1246 | | |
1247 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
1248 | 0 | libmwaw::DebugStream f; |
1249 | 0 | f << "Entries(PenSize):sz=["; |
1250 | 0 | for (int i=0; i<10; ++i) |
1251 | 0 | f << double(input->readULong(2))/256. << ","; |
1252 | 0 | f << "],"; |
1253 | 0 | ascFile.addPos(pos); |
1254 | 0 | ascFile.addNote(f.str().c_str()); |
1255 | 0 | return true; |
1256 | 0 | } |
1257 | | |
1258 | | bool Canvas5StyleManager::readPenStyles(std::shared_ptr<Canvas5Structure::Stream> stream) |
1259 | 0 | { |
1260 | 0 | if (!stream || !stream->input()) |
1261 | 0 | return false; |
1262 | 0 | auto input=stream->input(); |
1263 | 0 | long pos=input->tell(); |
1264 | |
|
1265 | 0 | libmwaw::DebugStream f; |
1266 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
1267 | 0 | f << "Entries(PenStyl):"; |
1268 | 0 | ascFile.addPos(pos); |
1269 | 0 | ascFile.addNote(f.str().c_str()); |
1270 | |
|
1271 | 0 | std::map<int, unsigned> idToTypeMap; |
1272 | 0 | if (!m_mainParser->readExtendedHeader(stream, 4, "PenStyl", |
1273 | 0 | [&idToTypeMap](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
1274 | 0 | auto lInput=lStream->input(); |
1275 | 0 | libmwaw::DebugFile &asciiFile = lStream->ascii(); |
1276 | 0 | libmwaw::DebugStream lF; |
1277 | 0 | lF << "Pe" << item.m_id << ","; |
1278 | 0 | unsigned type=unsigned(lInput->readULong(4)); |
1279 | 0 | lF << "type=" << Canvas5Structure::getString(type) << ","; |
1280 | 0 | idToTypeMap[item.m_id]=type; |
1281 | 0 | asciiFile.addPos(item.m_pos); |
1282 | 0 | asciiFile.addNote(lF.str().c_str()); |
1283 | 0 | })) |
1284 | 0 | return false; |
1285 | | |
1286 | 0 | if (!m_mainParser->readIndexMap(stream, "PenStyl", |
1287 | 0 | [this, &idToTypeMap](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
1288 | 0 | auto lInput=lStream->input(); |
1289 | 0 | auto &asciiFile=lStream->ascii(); |
1290 | 0 | libmwaw::DebugStream lF; |
1291 | 0 | lF << "Pe" << item.m_id << ","; |
1292 | 0 | unsigned type=1; |
1293 | 0 | auto it=idToTypeMap.find(item.m_id); |
1294 | 0 | if (it!=idToTypeMap.end()) type=it->second; |
1295 | 0 | auto style=readPenStyle(*lStream, type, item.m_length); |
1296 | 0 | if (!style) |
1297 | 0 | lF << "###"; |
1298 | 0 | else |
1299 | 0 | m_state->m_idToPen[item.m_id]=style; |
1300 | 0 | asciiFile.addPos(item.m_pos); |
1301 | 0 | asciiFile.addNote(lF.str().c_str()); |
1302 | 0 | })) |
1303 | 0 | return false; |
1304 | 0 | return m_mainParser->readUsed(*stream, "PenStyl"); |
1305 | 0 | } |
1306 | | |
1307 | | std::shared_ptr<Canvas5StyleManagerInternal::PenStyle> Canvas5StyleManager::readPenStyle(Canvas5Structure::Stream &stream, unsigned type, long len) |
1308 | 0 | { |
1309 | 0 | auto input=stream.input(); |
1310 | 0 | long pos=input->tell(); |
1311 | |
|
1312 | 0 | libmwaw::DebugStream f; |
1313 | 0 | libmwaw::DebugFile &ascFile = stream.ascii(); |
1314 | 0 | f << "Entries(PenStyl):"; |
1315 | |
|
1316 | 0 | auto style=std::make_shared<Canvas5StyleManagerInternal::PenStyle>(); |
1317 | 0 | style->m_type=type; |
1318 | 0 | int const vers=version(); |
1319 | 0 | switch (type) { |
1320 | | // case 0: find one time with size=0x70 and inverted endian, so unsure |
1321 | 0 | case 1: { |
1322 | 0 | int expectedLength=vers<9 ? 32 : 0x70; |
1323 | 0 | if (len<expectedLength) { |
1324 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readPenStyle: find unexpected size for type 1\n")); |
1325 | 0 | return nullptr; |
1326 | 0 | } |
1327 | 0 | float widths[2]; |
1328 | 0 | for (auto &w : widths) { |
1329 | 0 | if (vers<9) { |
1330 | 0 | w=float(input->readLong(4))/65536.f; |
1331 | 0 | continue; |
1332 | 0 | } |
1333 | 0 | double dVal; |
1334 | 0 | bool isNan; |
1335 | 0 | if (m_mainParser->readDouble(stream, dVal, isNan)) |
1336 | 0 | w=float(dVal); |
1337 | 0 | else { |
1338 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readPenStyle: can not read a width\n")); |
1339 | 0 | w=0; |
1340 | 0 | f << "###bad value,"; |
1341 | 0 | } |
1342 | 0 | } |
1343 | 0 | style->m_size=MWAWVec2f(widths[0],widths[1]); |
1344 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
1345 | 0 | break; |
1346 | 0 | } |
1347 | 0 | case 0x706c696e: { // plin |
1348 | 0 | int headerLen=vers==5 ? 16 : vers<9 ? 60 : 64; |
1349 | 0 | int dataLen=vers==5 ? 128 : vers<9 ? 164 : 328; |
1350 | 0 | if (len<headerLen) { |
1351 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readPenStyle: find unexpected size for plin\n")); |
1352 | 0 | return nullptr; |
1353 | 0 | } |
1354 | 0 | if (vers>5) { |
1355 | | // checkme: look like ObFl structure |
1356 | 0 | for (int i=0; i<2; ++i) { |
1357 | 0 | int lVal=int(input->readLong(4)); |
1358 | 0 | int const expected[]= {vers<9 ? 0xfa : 0xdf, vers<9 ? 0x600 : 0x700}; |
1359 | 0 | if (lVal!=expected[i]) |
1360 | 0 | f << "f" << i << "=" << lVal << ","; |
1361 | 0 | } |
1362 | 0 | } |
1363 | 0 | int N=m_mainParser->readInteger(stream, vers==5 ? 4 : vers<9 ? 2 : 8); |
1364 | |
|
1365 | 0 | f << "plin,N=" << N << ","; |
1366 | 0 | if (N<0 || (len-headerLen)/dataLen<N) { |
1367 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readPenStyle: find unexpected value of N for plin\n")); |
1368 | 0 | f << "###"; |
1369 | 0 | ascFile.addPos(pos); |
1370 | 0 | ascFile.addNote(f.str().c_str()); |
1371 | 0 | return nullptr; |
1372 | 0 | } |
1373 | 0 | style->m_usePenColor=false; |
1374 | 0 | for (int i=0; i<2; ++i) { |
1375 | 0 | int val=int(input->readLong(1)); |
1376 | 0 | if (!val) continue; |
1377 | 0 | char const *wh[]= {"equidistant", "usePenLine" }; |
1378 | 0 | if (val==1) { |
1379 | 0 | f << wh[i] << ","; |
1380 | 0 | if (i==1) |
1381 | 0 | style->m_usePenColor=true; |
1382 | 0 | } |
1383 | 0 | else |
1384 | 0 | f << wh[i] << "=" << val << ","; |
1385 | 0 | } |
1386 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
1387 | 0 | input->seek(pos+headerLen, librevenge::RVNG_SEEK_SET); |
1388 | 0 | libmwaw::DebugStream f2; |
1389 | 0 | std::vector<float> offsets; |
1390 | 0 | float sumOffsets=0; |
1391 | 0 | for (int i=0; i<N; ++i) { |
1392 | 0 | long actPos=input->tell(); |
1393 | 0 | f2.str(""); |
1394 | 0 | f2 << "PenStyl,Pe[plin" << i << "]:"; |
1395 | 0 | Canvas5StyleManagerInternal::PenStyle::Line line; |
1396 | 0 | std::string extra; |
1397 | 0 | if (!readColor(stream, line.m_color, extra)) { |
1398 | 0 | f2 << "##"; |
1399 | 0 | input->seek(actPos+24, librevenge::RVNG_SEEK_SET); |
1400 | 0 | } |
1401 | 0 | f2 << extra; |
1402 | 0 | if (vers>5) { |
1403 | 0 | std::string name; |
1404 | 0 | for (int j=0; j<32; ++j) { |
1405 | 0 | char c=char(input->readULong(1)); |
1406 | 0 | if (!c) |
1407 | 0 | break; |
1408 | 0 | name+=c; |
1409 | 0 | } |
1410 | 0 | f2 << name << ","; |
1411 | 0 | input->seek(actPos+24+32, librevenge::RVNG_SEEK_SET); |
1412 | 0 | } |
1413 | 0 | float width[2]; |
1414 | 0 | for (auto &w : width) w=float(m_mainParser->readDouble(stream, vers<9 ? 4 : 8)); |
1415 | 0 | line.m_size=MWAWVec2f(width[0],width[1]); |
1416 | 0 | f2 << "w=" << line.m_size << ","; |
1417 | 0 | for (int j=0; j<46; ++j) { // 0 |
1418 | 0 | int val=int(input->readLong(2)); |
1419 | 0 | if (val) f2 << "g" << j << "=" << val << ","; |
1420 | 0 | } |
1421 | 0 | if (vers==5) { |
1422 | 0 | offsets.push_back(float(input->readULong(4))/65536); |
1423 | 0 | sumOffsets+=offsets.back(); |
1424 | 0 | f2 << "decal=" << offsets.back() << ","; |
1425 | 0 | } |
1426 | 0 | else { |
1427 | 0 | input->seek(actPos+dataLen-(vers<9 ? 8 : 16), librevenge::RVNG_SEEK_SET); |
1428 | 0 | offsets.push_back(float(m_mainParser->readDouble(stream, vers<9 ? 4 : 8))); |
1429 | 0 | sumOffsets+=offsets.back(); |
1430 | 0 | f2 << "decal=" << offsets.back() << ","; |
1431 | 0 | for (int j=0; j<(vers<9 ? 1 : 2); ++j) { |
1432 | 0 | int val=int(input->readLong(4)); |
1433 | 0 | if (val) f2 << "h" << j << "=" << val << ","; |
1434 | 0 | } |
1435 | 0 | } |
1436 | 0 | style->m_lines.push_back(line); |
1437 | 0 | ascFile.addPos(actPos); |
1438 | 0 | ascFile.addNote(f2.str().c_str()); |
1439 | 0 | } |
1440 | 0 | float actualOffset=sumOffsets/2; |
1441 | 0 | for (size_t i=0; i<std::min(style->m_lines.size(),offsets.size()); ++i) { |
1442 | 0 | style->m_lines[i].m_offset=actualOffset; |
1443 | 0 | actualOffset-=offsets[i]; |
1444 | 0 | } |
1445 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
1446 | 0 | break; |
1447 | 0 | } |
1448 | 0 | case 0x766e656f: { // vneo |
1449 | 0 | int headerLen=vers==5 ? 68 : vers<9 ? 184 : 236; |
1450 | 0 | if (len<headerLen) { |
1451 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readPenStyle: the vneo zone seems too short\n")); |
1452 | 0 | return nullptr; |
1453 | 0 | } |
1454 | 0 | if (vers!=5) { // checkme: look like ObFl structure |
1455 | 0 | for (int i=0; i<3; ++i) { |
1456 | 0 | int lVal=int(input->readLong(4)); |
1457 | 0 | int const expected[]= {vers<9 ? 0xdf : 0xadf, vers<9 ? 0x600 : 0xa00, 0}; |
1458 | 0 | if (lVal!=expected[i]) |
1459 | 0 | f << "f" << i << "=" << lVal << ","; |
1460 | 0 | } |
1461 | 0 | if (vers>=9) { |
1462 | 0 | int lVal=int(input->readULong(4)); |
1463 | 0 | if (lVal) f << "type=" << Canvas5Structure::getString(unsigned(lVal)) << ","; |
1464 | 0 | } |
1465 | 0 | } |
1466 | 0 | float w=float(m_mainParser->readDouble(stream, vers<9 ? 4 : 8)); |
1467 | 0 | f << "w=" << w << ","; |
1468 | 0 | style->m_size=MWAWVec2f(w,w); |
1469 | 0 | if (vers>=9) { |
1470 | 0 | ascFile.addDelimiter(input->tell(), '|'); |
1471 | 0 | input->seek(16, librevenge::RVNG_SEEK_CUR); // 01040004000000000000000100000000 |
1472 | 0 | ascFile.addDelimiter(input->tell(), '|'); |
1473 | 0 | f << "values=["; |
1474 | 0 | for (int i=0; i<3; ++i) // unkn, width, angle |
1475 | 0 | f << m_mainParser->readDouble(stream, 8) << ","; |
1476 | 0 | f << "],"; |
1477 | 0 | ascFile.addDelimiter(input->tell(), '|'); |
1478 | 0 | input->seek(52, librevenge::RVNG_SEEK_CUR); |
1479 | 0 | ascFile.addDelimiter(input->tell(), '|'); |
1480 | 0 | } |
1481 | 0 | for (int i=0; i<2; ++i) { |
1482 | 0 | std::string extra; |
1483 | 0 | long actPos=input->tell(); |
1484 | 0 | if (!readColor(stream, style->m_colors[i], extra)) { |
1485 | 0 | f << "##"; |
1486 | 0 | input->seek(actPos+24, librevenge::RVNG_SEEK_SET); |
1487 | 0 | } |
1488 | 0 | f << "col" << i << "=[" << extra << "],"; |
1489 | 0 | if (vers>5) { |
1490 | 0 | std::string name; |
1491 | 0 | for (int j=0; j<32; ++j) { |
1492 | 0 | char c=char(input->readULong(1)); |
1493 | 0 | if (!c) |
1494 | 0 | break; |
1495 | 0 | name+=c; |
1496 | 0 | } |
1497 | 0 | f << name << ","; |
1498 | 0 | input->seek(actPos+24+32, librevenge::RVNG_SEEK_SET); |
1499 | 0 | } |
1500 | 0 | } |
1501 | 0 | if (vers>=9) |
1502 | 0 | break; |
1503 | 0 | int val=int(input->readLong(2)); |
1504 | 0 | if (val) |
1505 | 0 | f << "f0=" << val << ","; |
1506 | 0 | val=int(input->readULong(2)); |
1507 | 0 | if (val&0x100) |
1508 | 0 | f << "axial,"; |
1509 | 0 | val &= 0xfeff; |
1510 | 0 | if (val!=0xdd) |
1511 | 0 | f << "fl=" << std::hex << val << std::dec << ","; |
1512 | 0 | for (int i=0; i<2; ++i) { |
1513 | 0 | val=int(input->readULong(4)); |
1514 | 0 | if (!val) continue; |
1515 | 0 | if (i==0) |
1516 | 0 | f << "corner=" << val << ","; // 0: none, 1: round, 2: square |
1517 | 0 | else |
1518 | 0 | f << "join=" << val << ","; // 0: mitter, 1: round, 2:bevel |
1519 | 0 | } |
1520 | 0 | f << "angle=" << float(input->readLong(4))/65536 << "rad,"; |
1521 | 0 | if (vers!=5) |
1522 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
1523 | 0 | break; |
1524 | 0 | } |
1525 | 0 | default: |
1526 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readPenStyle: find unexpected type=%s\n", Canvas5Structure::getString(type).c_str())); |
1527 | 0 | return nullptr; |
1528 | 0 | } |
1529 | 0 | f << *style; |
1530 | 0 | ascFile.addPos(pos); |
1531 | 0 | ascFile.addNote(f.str().c_str()); |
1532 | 0 | return style; |
1533 | 0 | } |
1534 | | |
1535 | | bool Canvas5StyleManager::readStrokes(std::shared_ptr<Canvas5Structure::Stream> stream) |
1536 | 0 | { |
1537 | 0 | if (!stream || !stream->input()) |
1538 | 0 | return false; |
1539 | 0 | auto input=stream->input(); |
1540 | 0 | long pos=input->tell(); |
1541 | |
|
1542 | 0 | libmwaw::DebugStream f; |
1543 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
1544 | 0 | f << "Entries(Stroke):"; |
1545 | 0 | ascFile.addPos(pos); |
1546 | 0 | ascFile.addNote(f.str().c_str()); |
1547 | 0 | if (!m_mainParser->readUsed(*stream, "Stroke")) |
1548 | 0 | return false; |
1549 | 0 | if (!m_mainParser->readExtendedHeader(stream, 20, "Stroke", |
1550 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
1551 | 0 | auto lInput=lStream->input(); |
1552 | 0 | libmwaw::DebugFile &asciiFile = lStream->ascii(); |
1553 | 0 | libmwaw::DebugStream lF; |
1554 | 0 | lF << "St" << item.m_id << ","; |
1555 | 0 | Canvas5StyleManagerInternal::Stroke style; |
1556 | 0 | style.m_type=unsigned(lInput->readULong(4)); |
1557 | 0 | style.m_penId=int(lInput->readLong(4)); |
1558 | 0 | style.m_dashId=int(lInput->readLong(4)); |
1559 | 0 | for (int i=0; i<2; ++i) |
1560 | 0 | style.m_arrowId[i]=int(lInput->readLong(4)); |
1561 | 0 | lF << style; |
1562 | 0 | m_state->m_idToStroke[item.m_id]=style; |
1563 | 0 | asciiFile.addPos(item.m_pos); |
1564 | 0 | asciiFile.addNote(lF.str().c_str()); |
1565 | 0 | })) |
1566 | 0 | return false; |
1567 | | |
1568 | 0 | return true; |
1569 | 0 | } |
1570 | | |
1571 | | //////////////////////////////////////////////////////////// |
1572 | | // styles |
1573 | | //////////////////////////////////////////////////////////// |
1574 | | bool Canvas5StyleManager::readCharStyle(Canvas5Structure::Stream &stream, int id, CharStyle &font, |
1575 | | bool useFileColors) |
1576 | 0 | { |
1577 | 0 | auto input=stream.input(); |
1578 | 0 | libmwaw::DebugFile &ascFile = stream.ascii(); |
1579 | 0 | int const vers=version(); |
1580 | 0 | long pos=input->tell(); |
1581 | 0 | libmwaw::DebugStream f; |
1582 | 0 | if (id<0) |
1583 | 0 | f << "Entries(CharStyl):"; |
1584 | 0 | else |
1585 | 0 | f << "CharStyl-" << id << ":"; |
1586 | 0 | ascFile.addPos(pos); |
1587 | 0 | ascFile.addNote(f.str().c_str()); |
1588 | 0 | font.m_paragraphId=font.m_linkId=0; |
1589 | 0 | int const sz=vers<9 ? 60 : 96; |
1590 | 0 | if (!input->checkPosition(pos+sz)) { |
1591 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readCharStyle: the zone is too short\n")); |
1592 | 0 | f << "###"; |
1593 | 0 | ascFile.addPos(pos); |
1594 | 0 | ascFile.addNote(f.str().c_str()); |
1595 | 0 | return false; |
1596 | 0 | } |
1597 | 0 | f.str(""); |
1598 | 0 | int val=int(input->readLong(2)); |
1599 | 0 | if (val!=1) f << "used=" << val << ","; |
1600 | 0 | f << "h=["; |
1601 | 0 | for (int i=0; i<2; ++i) |
1602 | 0 | f << input->readLong(2) << ","; |
1603 | 0 | f << "],"; |
1604 | 0 | int fId=int(input->readULong(2)); |
1605 | 0 | font.m_font.setId(fId); |
1606 | 0 | val=int(input->readULong(1)); |
1607 | 0 | uint32_t flags = 0; |
1608 | 0 | if (val&0x1) flags |= MWAWFont::boldBit; |
1609 | 0 | if (val&0x2) flags |= MWAWFont::italicBit; |
1610 | 0 | if (val&0x4) font.m_font.setUnderlineStyle(MWAWFont::Line::Simple); |
1611 | 0 | if (val&0x8) flags |= MWAWFont::embossBit; |
1612 | 0 | if (val&0x10) flags |= MWAWFont::shadowBit; |
1613 | 0 | if (val&0x80) font.m_font.setStrikeOutStyle(MWAWFont::Line::Simple); |
1614 | 0 | if (val&0x60) f << "fl=" << std::hex << (val&0x60) << std::dec << ","; |
1615 | 0 | val=int(input->readULong(1)); |
1616 | 0 | if (val) f << "fl1=" << std::hex << val << std::dec; |
1617 | 0 | if (vers<9) |
1618 | 0 | font.m_font.setSize(float(input->readULong(2))); |
1619 | 0 | else { |
1620 | 0 | for (int i=0; i<3; ++i) { |
1621 | 0 | val=int(input->readLong(2)); |
1622 | 0 | if (val) |
1623 | 0 | f << "f" << i << "=" << val << ","; |
1624 | 0 | } |
1625 | 0 | font.m_font.setSize(float(m_mainParser->readDouble(stream, 8))); |
1626 | 0 | } |
1627 | 0 | val=int(input->readLong(4)); |
1628 | 0 | if (val) { |
1629 | | // CHECKME: inside a Vkfl image, colorId and linkId are a negative number, |
1630 | | // I do not know how to retrieve the color/link using this number |
1631 | 0 | if (!useFileColors) |
1632 | 0 | f << "##COLOR=" << val << ","; |
1633 | 0 | else { |
1634 | 0 | auto it=m_state->m_idToColor.find(val); |
1635 | 0 | if (it!=m_state->m_idToColor.end() && it->second && it->second->m_color.isSet()) |
1636 | 0 | font.m_font.setColor(*it->second->m_color); |
1637 | 0 | else |
1638 | 0 | f << "#Co1" << val << ","; |
1639 | 0 | } |
1640 | 0 | } |
1641 | 0 | for (int i=0; i<2; ++i) { // |
1642 | 0 | val=int(input->readLong(2)); |
1643 | 0 | if (!val) continue; |
1644 | 0 | if (i==0) { |
1645 | 0 | f << "E" << val << ","; |
1646 | 0 | font.m_paragraphId=val; |
1647 | 0 | } |
1648 | 0 | else |
1649 | 0 | f << "f" << i << "=" << val << ","; |
1650 | 0 | } |
1651 | 0 | float stretchs[]= {1,1}; |
1652 | 0 | if (vers<9) { |
1653 | 0 | val=int(input->readLong(4)); |
1654 | 0 | if ((val>=-60*65536 && val<0) || (val>0 && val<60*65536)) // is 30 pt is big enough ? |
1655 | 0 | font.m_font.setDeltaLetterSpacing(float(val)/2/65536, librevenge::RVNG_POINT); |
1656 | 0 | else if (val) { |
1657 | 0 | MWAW_DEBUG_MSG(("Canvas5Style::readCharStyle: unknown delta spacing\n")); |
1658 | 0 | f << "##delta[spacing]=" << val/65536 << ","; |
1659 | 0 | } |
1660 | |
|
1661 | 0 | int lVals[4]; |
1662 | 0 | for (auto &l : lVals) l=int(input->readLong(2)); |
1663 | 0 | for (int i=0; i<2; ++i) { |
1664 | 0 | if (lVals[i]==lVals[i+2]) |
1665 | 0 | continue; |
1666 | 0 | f << "scaling[" << (i==0 ? "hori" : "verti") << "]=" << lVals[i] << "/" << lVals[i+2] << ","; |
1667 | 0 | if (lVals[i]<=0 || lVals[i+2]<=0) { |
1668 | 0 | MWAW_DEBUG_MSG(("Canvas5Style::readCharStyle: invalid scaling\n")); |
1669 | 0 | f << "###"; |
1670 | 0 | } |
1671 | 0 | else |
1672 | 0 | stretchs[i]=float(lVals[i])/float(lVals[i+2]); |
1673 | 0 | } |
1674 | 0 | val=int(input->readLong(4)); |
1675 | 0 | if (val) |
1676 | 0 | font.m_font.set(MWAWFont::Script(float(val)/65536,librevenge::RVNG_POINT)); |
1677 | 0 | } |
1678 | 0 | else { |
1679 | 0 | for (int i=0; i<4; ++i) { |
1680 | 0 | double dVal=m_mainParser->readDouble(stream, 8); |
1681 | 0 | double const expected=i==0 || i==3 ? 0 : 1; |
1682 | 0 | if (dVal<=expected && dVal>=expected) |
1683 | 0 | continue; |
1684 | 0 | if (i==0) |
1685 | 0 | font.m_font.setDeltaLetterSpacing(float(dVal), librevenge::RVNG_POINT); |
1686 | 0 | else if (i==3) |
1687 | 0 | font.m_font.set(MWAWFont::Script(float(dVal), librevenge::RVNG_POINT)); |
1688 | 0 | else { |
1689 | 0 | stretchs[i-1]=float(dVal); |
1690 | 0 | f << "scaling[" << (i==1 ? "hori" : "verti") << "]=" << dVal << ","; |
1691 | 0 | } |
1692 | 0 | } |
1693 | 0 | } |
1694 | 0 | if (stretchs[1]>1-1e-4f && stretchs[1]<1+1e-4f) { |
1695 | 0 | if (stretchs[0]<1-1e-4f || stretchs[0]>1+1e-4f) |
1696 | 0 | font.m_font.setWidthStreching(stretchs[0]); |
1697 | 0 | } |
1698 | 0 | else { |
1699 | 0 | font.m_font.setSize(font.m_font.size()*stretchs[1]); |
1700 | 0 | font.m_font.setWidthStreching(stretchs[0]/stretchs[1]); |
1701 | 0 | } |
1702 | 0 | val=int(input->readLong(2)); |
1703 | 0 | if (val) f << "h0=" << std::hex << val << std::dec << ","; // 4 or 8, 4 a link? |
1704 | 0 | val=int(input->readULong(2)); |
1705 | 0 | if (val&1) |
1706 | 0 | flags |= MWAWFont::smallCapsBit; |
1707 | 0 | if (val&2) |
1708 | 0 | flags |= MWAWFont::uppercaseBit; |
1709 | 0 | if (val&4) |
1710 | 0 | flags |= MWAWFont::lowercaseBit; |
1711 | 0 | if (val&8) |
1712 | 0 | flags |= MWAWFont::initialcaseBit; |
1713 | 0 | if (val&0x200) |
1714 | 0 | f << "spread,"; |
1715 | 0 | if (val&0x800) |
1716 | 0 | f << "overprint,"; |
1717 | 0 | val &= 0xF5F0; |
1718 | 0 | if (val) { |
1719 | 0 | MWAW_DEBUG_MSG(("Canvas5Style::readCharStyle: unknown small caps bits\n")); |
1720 | 0 | f << "##smallCaps=" << std::hex << val << std::dec << ","; |
1721 | 0 | } |
1722 | 0 | for (int i=0; i<4; ++i) { // h2=0|1 a link id? |
1723 | 0 | val=int(input->readLong(4)); |
1724 | 0 | if (!val) continue; |
1725 | 0 | if (i==0) { |
1726 | 0 | if (!useFileColors) |
1727 | 0 | f << "###LINK=" << val << ","; |
1728 | 0 | else { |
1729 | 0 | font.m_linkId=val; |
1730 | 0 | f << "link[id]=Tl" << val << ","; |
1731 | 0 | } |
1732 | 0 | } |
1733 | 0 | else if (i==3 && font.m_paragraphId==0) { // checkme: there is two color: the para color and the font color |
1734 | 0 | if (!useFileColors) |
1735 | 0 | f << "###COLOR=" << val << ","; |
1736 | 0 | else { |
1737 | 0 | auto it=m_state->m_idToColor.find(val); |
1738 | 0 | if (it!=m_state->m_idToColor.end() && it->second && it->second->m_color.isSet()) |
1739 | 0 | font.m_font.setColor(*it->second->m_color); |
1740 | 0 | else |
1741 | 0 | f << "#Co2" << val << ","; |
1742 | 0 | } |
1743 | 0 | } |
1744 | 0 | else |
1745 | 0 | f << "h" << i+1 << "=" << val << ","; |
1746 | 0 | } |
1747 | 0 | for (int i=0; i<(vers<9 ? 2 : 6); ++i) { |
1748 | 0 | val=int(input->readLong(2)); |
1749 | 0 | if (!val) continue; |
1750 | 0 | f << "h" << i+5 << "=" << val << ","; |
1751 | 0 | } |
1752 | |
|
1753 | 0 | font.m_font.setFlags(flags); |
1754 | 0 | std::string const extra=f.str(); |
1755 | 0 | f.str(""); |
1756 | 0 | f << font.m_font.getDebugString(m_parserState->m_fontConverter) << "," << extra; |
1757 | 0 | ascFile.addPos(pos); |
1758 | 0 | ascFile.addNote(f.str().c_str()); |
1759 | 0 | return true; |
1760 | 0 | } |
1761 | | |
1762 | | bool Canvas5StyleManager::readCharStyles(std::shared_ptr<Canvas5Structure::Stream> stream) |
1763 | 0 | { |
1764 | 0 | if (!stream || !stream->input()) |
1765 | 0 | return false; |
1766 | 0 | auto input=stream->input(); |
1767 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
1768 | 0 | int const vers=version(); |
1769 | 0 | ascFile.addPos(input->tell()); |
1770 | 0 | ascFile.addNote("Entries(CharStyl):"); |
1771 | 0 | if (vers>=9) { |
1772 | 0 | return m_mainParser->readArray9(stream, "CharStyl", |
1773 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &what) { |
1774 | 0 | auto lInput=lStream->input(); |
1775 | 0 | long endPos=lInput->tell()+item.m_length; |
1776 | 0 | lInput->seek(-4, librevenge::RVNG_SEEK_CUR); |
1777 | 0 | CharStyle font; |
1778 | 0 | if (!readCharStyle(*lStream, item.m_id, font)) |
1779 | 0 | return; |
1780 | | |
1781 | 0 | long pos=lInput->tell(); |
1782 | 0 | libmwaw::DebugStream f; |
1783 | 0 | libmwaw::DebugFile &asciiFile = lStream->ascii(); |
1784 | 0 | f << what << "-" << item.m_id << "[A]:"; |
1785 | 0 | if (pos+44>endPos) { |
1786 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readCharStyles: the zone seems too short\n")); |
1787 | 0 | f << "###"; |
1788 | 0 | asciiFile.addPos(pos); |
1789 | 0 | asciiFile.addNote(f.str().c_str()); |
1790 | 0 | return; |
1791 | 0 | } |
1792 | 0 | for (int i=0; i<4; ++i) { |
1793 | 0 | int val=int(lInput->readLong(2)); |
1794 | 0 | if (val) |
1795 | 0 | f << "f" << i << "=" << val << ","; |
1796 | 0 | } |
1797 | 0 | asciiFile.addPos(pos); |
1798 | 0 | asciiFile.addNote(f.str().c_str()); |
1799 | |
|
1800 | 0 | pos=lInput->tell(); |
1801 | 0 | f.str(""); |
1802 | 0 | f << what << "-" << item.m_id << "[name]:"; |
1803 | 0 | std::string name; |
1804 | 0 | for (int i=0; i<32; ++i) { |
1805 | 0 | char c=char(lInput->readLong(1)); |
1806 | 0 | if (c==0) break; |
1807 | 0 | name+=c; |
1808 | 0 | } |
1809 | 0 | f << name << ","; |
1810 | 0 | lInput->seek(pos+32, librevenge::RVNG_SEEK_SET); |
1811 | 0 | int val=int(lInput->readLong(4)); // unsure can be an extended size |
1812 | 0 | if (val) |
1813 | 0 | f << "f0=" << val << ","; |
1814 | 0 | asciiFile.addPos(pos); |
1815 | 0 | asciiFile.addNote(f.str().c_str()); |
1816 | 0 | }); |
1817 | 0 | } |
1818 | 0 | if (!m_mainParser->readExtendedHeader(stream, 0x64, "CharStyl", |
1819 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &what) { |
1820 | 0 | CharStyle font; |
1821 | 0 | if (!readCharStyle(*lStream, item.m_id, font)) |
1822 | 0 | return; |
1823 | 0 | auto lInput=lStream->input(); |
1824 | 0 | long pos=lInput->tell(); |
1825 | 0 | libmwaw::DebugStream f; |
1826 | 0 | libmwaw::DebugFile &asciiFile = lStream->ascii(); |
1827 | |
|
1828 | 0 | f << what << "-" << item.m_id << "[A]:"; |
1829 | 0 | for (int i=0; i<4; ++i) { |
1830 | 0 | int val=int(lInput->readLong(2)); |
1831 | 0 | if (val) |
1832 | 0 | f << "f" << i << "=" << val << ","; |
1833 | 0 | } |
1834 | 0 | asciiFile.addPos(pos); |
1835 | 0 | asciiFile.addNote(f.str().c_str()); |
1836 | |
|
1837 | 0 | pos=lInput->tell(); |
1838 | 0 | f.str(""); |
1839 | 0 | f << what << "-" << item.m_id << "[name]:"; |
1840 | 0 | std::string name; |
1841 | 0 | for (int i=0; i<32; ++i) { |
1842 | 0 | char c=char(lInput->readLong(1)); |
1843 | 0 | if (c==0) break; |
1844 | 0 | name+=c; |
1845 | 0 | } |
1846 | 0 | f << name << ","; |
1847 | 0 | lInput->seek(pos+32, librevenge::RVNG_SEEK_SET); |
1848 | 0 | asciiFile.addPos(pos); |
1849 | 0 | asciiFile.addNote(f.str().c_str()); |
1850 | 0 | })) |
1851 | 0 | return false; |
1852 | 0 | if (!m_mainParser->readIndexMap(stream, "CharStyl")) |
1853 | 0 | return false; |
1854 | 0 | std::vector<bool> defined; |
1855 | 0 | if (!m_mainParser->readDefined(*stream, defined, "CharStyl")) |
1856 | 0 | return false; |
1857 | 0 | if (!m_mainParser->readUsed(*stream, "CharStyl")) |
1858 | 0 | return false; |
1859 | 0 | return m_mainParser->readExtendedHeader(stream, 8, "CharStyl[data2]", &Canvas5Parser::defDataFunction); |
1860 | 0 | } |
1861 | | |
1862 | | bool Canvas5StyleManager::readParaStyle(std::shared_ptr<Canvas5Structure::Stream> stream, int id, Canvas5StyleManager::StyleList *styles) |
1863 | 0 | { |
1864 | 0 | if (!stream || !stream->input()) |
1865 | 0 | return false; |
1866 | 0 | auto input=stream->input(); |
1867 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
1868 | 0 | int const vers=version(); |
1869 | |
|
1870 | 0 | long pos=input->tell(); |
1871 | 0 | libmwaw::DebugStream f; |
1872 | 0 | if (id<0) |
1873 | 0 | f << "Entries(ParaStyl):"; |
1874 | |
|
1875 | 0 | if (!input->checkPosition(pos+(vers<9 ? 128 : 224))) { |
1876 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readParaStyle: the zone is too short\n")); |
1877 | 0 | f << "###"; |
1878 | 0 | ascFile.addPos(pos); |
1879 | 0 | ascFile.addNote(f.str().c_str()); |
1880 | 0 | return false; |
1881 | 0 | } |
1882 | 0 | std::pair<MWAWParagraph,int> *paraId=nullptr; |
1883 | 0 | if (styles && id>=0) { |
1884 | 0 | if (styles->m_paragraphs.size()<=size_t(id)) |
1885 | 0 | styles->m_paragraphs.resize(size_t(id+1)); |
1886 | 0 | paraId=&styles->m_paragraphs[size_t(id)]; |
1887 | 0 | paraId->second=0; |
1888 | 0 | } |
1889 | 0 | MWAWParagraph *para=paraId ? ¶Id->first : nullptr; |
1890 | 0 | int val=int(input->readLong(4)); |
1891 | 0 | if (val!=1) |
1892 | 0 | f << "used=" << val << ","; |
1893 | 0 | val=int(input->readLong(4)); |
1894 | 0 | if (val) { |
1895 | 0 | if (paraId) paraId->second=val; |
1896 | 0 | f << "Tab" << val << ","; |
1897 | 0 | } |
1898 | 0 | for (int i=0; i<2; ++i) { // 0 |
1899 | 0 | val=int(input->readLong(2)); |
1900 | 0 | if (!val) continue; |
1901 | 0 | if (i==0) { |
1902 | 0 | switch (val) { |
1903 | 0 | case -1: |
1904 | 0 | if (para) para->m_justify=MWAWParagraph::JustificationRight; |
1905 | 0 | f << "align=right,"; |
1906 | 0 | break; |
1907 | | // 0: left |
1908 | 0 | case 1: |
1909 | 0 | if (para) para->m_justify=MWAWParagraph::JustificationCenter; |
1910 | 0 | f << "align=center,"; |
1911 | 0 | break; |
1912 | | // 2: ? |
1913 | 0 | case 4: |
1914 | 0 | if (para) para->m_justify=MWAWParagraph::JustificationFull; |
1915 | 0 | f << "align=justify,"; |
1916 | 0 | break; |
1917 | 0 | default: |
1918 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readParaStyle: find unexpected align\n")); |
1919 | 0 | f << "##align=" << val << ","; |
1920 | 0 | break; |
1921 | 0 | } |
1922 | 0 | } |
1923 | 0 | else |
1924 | 0 | f << "f" << i << "=" << val << ","; |
1925 | 0 | } |
1926 | 0 | if (vers>=9) // align? |
1927 | 0 | input->seek(4, librevenge::RVNG_SEEK_CUR); |
1928 | 0 | double dVal=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
1929 | 0 | if (dVal>0) { |
1930 | 0 | f << "interline=" << dVal << "pt,"; |
1931 | 0 | if (para) |
1932 | 0 | para->setInterline(dVal, librevenge::RVNG_POINT); |
1933 | 0 | } |
1934 | 0 | dVal=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
1935 | 0 | if (dVal>0 && (dVal<1 || dVal>1)) { |
1936 | 0 | f << "interline=" << dVal << ","; |
1937 | 0 | if (para) |
1938 | 0 | para->setInterline(dVal, librevenge::RVNG_PERCENT); |
1939 | 0 | } |
1940 | 0 | for (int i=0; i<4; ++i) { |
1941 | 0 | val=int(input->readULong(2)); |
1942 | 0 | if (val) |
1943 | 0 | f << "g" << i << "=" << val << ","; |
1944 | 0 | } |
1945 | 0 | if (para) para->m_marginsUnit=librevenge::RVNG_POINT; |
1946 | 0 | for (int i=0; i<3; ++i) { |
1947 | 0 | dVal=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
1948 | 0 | if (dVal<=0 && dVal>=0) continue; |
1949 | 0 | char const *wh[]= {"first", "left", "right"}; |
1950 | 0 | f << wh[i] << "[marg]=" << dVal << ","; |
1951 | 0 | if (para) |
1952 | 0 | para->m_margins[i]=dVal; |
1953 | 0 | } |
1954 | 0 | if (para) |
1955 | 0 | para->m_margins[0]=*(para->m_margins[0])-*(para->m_margins[1]); |
1956 | 0 | for (int i=0; i<2; ++i) { |
1957 | 0 | dVal=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
1958 | 0 | if (dVal<=0 && dVal>=0) continue; |
1959 | 0 | f << "space[" << (i==0 ? "before" : "after") << "]=" << dVal << ","; |
1960 | 0 | if (para) |
1961 | 0 | para->m_spacings[i+1]=dVal/72; |
1962 | 0 | } |
1963 | 0 | val=int(input->readULong(4)); |
1964 | 0 | if (val) f << "g8=" << val << ","; |
1965 | 0 | dVal=m_mainParser->readDouble(*stream, 4); |
1966 | 0 | if (dVal<0 || dVal>0) f << "wrap[object]=" << dVal << ","; // useme: unit in point |
1967 | 0 | for (int i=0; i<(vers<9 ? 2 : 8); ++i) { // g9=0|2 |
1968 | 0 | val=int(input->readULong(2)); |
1969 | 0 | if (!val) continue; |
1970 | 0 | f << "g" << i+9 << "=" << val << ","; |
1971 | 0 | } |
1972 | 0 | if (vers>=9) { |
1973 | 0 | dVal=m_mainParser->readDouble(*stream, 8); |
1974 | 0 | if (dVal<0 || dVal>0) |
1975 | 0 | f << "unkn=" << dVal << ","; |
1976 | 0 | } |
1977 | 0 | int dropChar=int(input->readULong(2)); |
1978 | 0 | int dropLine=int(input->readULong(2)); |
1979 | 0 | if (dropChar>0 && dropLine>1) { |
1980 | 0 | if (para) { |
1981 | 0 | para->m_dropNumCharacters=dropChar; |
1982 | 0 | para->m_dropNumLines=dropLine; |
1983 | 0 | } |
1984 | 0 | f << "drop=" << dropChar << "[l=" << dropLine << "],"; |
1985 | 0 | } |
1986 | 0 | if (vers>=9) |
1987 | 0 | input->seek(4, librevenge::RVNG_SEEK_CUR); |
1988 | 0 | ascFile.addPos(pos); |
1989 | 0 | ascFile.addNote(f.str().c_str()); |
1990 | |
|
1991 | 0 | MWAWFont *font=nullptr; |
1992 | 0 | if (styles) { |
1993 | 0 | for (auto &fId : styles->m_fonts) { |
1994 | 0 | if (fId.m_paragraphId==id) |
1995 | 0 | font=&fId.m_font; |
1996 | 0 | } |
1997 | 0 | } |
1998 | |
|
1999 | 0 | return readStyleEnd(stream, font, para); |
2000 | 0 | } |
2001 | | |
2002 | | bool Canvas5StyleManager::readStyleEnd(std::shared_ptr<Canvas5Structure::Stream> stream, MWAWFont *font, MWAWParagraph *para) |
2003 | 0 | { |
2004 | 0 | if (!stream || !stream->input()) |
2005 | 0 | return false; |
2006 | 0 | auto input=stream->input(); |
2007 | 0 | long pos=input->tell(); |
2008 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
2009 | 0 | libmwaw::DebugStream f; |
2010 | 0 | f << "ParaStyl[A]:"; |
2011 | |
|
2012 | 0 | int const vers=version(); |
2013 | 0 | if (!input->checkPosition(pos+(vers<9 ? 64 : 104))) { |
2014 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readStyleEnd: the zone seems too short\n")); |
2015 | 0 | f << "###"; |
2016 | 0 | ascFile.addPos(pos); |
2017 | 0 | ascFile.addNote(f.str().c_str()); |
2018 | 0 | return false; |
2019 | 0 | } |
2020 | 0 | double dVal=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
2021 | 0 | if (dVal>0) |
2022 | 0 | f << "justify[last,width]=" << 100-dVal << "%,"; |
2023 | 0 | for (int i=0; i<6; ++i) { |
2024 | 0 | dVal=m_mainParser->readDouble(*stream, vers<9 ? 4 : 8); |
2025 | 0 | if (dVal<=0 && dVal>=0) continue; |
2026 | 0 | char const *wh[]= {"spacing[word,min]", "spacing[word]", "spacing[word,max]", "spacing[min]", "spacing", "spacing[max]"}; |
2027 | 0 | if (i==4 && font) |
2028 | 0 | font->setDeltaLetterSpacing(1+float(dVal), librevenge::RVNG_PERCENT); |
2029 | 0 | f << wh[i] << "=" << 100+100*dVal << "%,"; |
2030 | 0 | } |
2031 | 0 | int val; |
2032 | 0 | f << "hyphen=["; |
2033 | 0 | for (int i=0; i<4; ++i) { |
2034 | 0 | val=int(input->readLong(2)); |
2035 | 0 | int const expected[]= {3,2,6,3}; // after word, before word, smallest word, consecutive limite |
2036 | 0 | if (val!=expected[i]) |
2037 | 0 | f << val << ","; |
2038 | 0 | else |
2039 | 0 | f << "_,"; |
2040 | 0 | } |
2041 | 0 | f << "],"; |
2042 | 0 | for (int i=0; i<4; ++i) { // g2=0|-1, g3=0|-1|0x140 |
2043 | 0 | val=i==2 ? int(input->readULong(2)) : int(input->readLong(2)); |
2044 | 0 | if (i==2) { |
2045 | 0 | int flags=0; |
2046 | 0 | if ((val&2)==0) |
2047 | 0 | f << "no[hyphen],"; |
2048 | 0 | if ((val&4)==0) |
2049 | 0 | f << "skip[cap],"; |
2050 | 0 | if ((val&0x200)==0) |
2051 | 0 | f << "orphan,"; |
2052 | 0 | if ((val&0x400)==0) { |
2053 | 0 | flags|=MWAWParagraph::NoBreakBit; |
2054 | 0 | f << "keep[alllines],"; |
2055 | 0 | } |
2056 | 0 | if ((val&0x800)==0) { |
2057 | 0 | flags|=MWAWParagraph::NoBreakWithNextBit; |
2058 | 0 | f << "keep[with,next],"; |
2059 | 0 | } |
2060 | 0 | if (flags&¶) |
2061 | 0 | para->m_breakStatus=flags; |
2062 | 0 | val&=0xf1f9; |
2063 | 0 | if (val) |
2064 | 0 | f << "g2=" << std::hex << val << std::dec << ","; |
2065 | 0 | continue; |
2066 | 0 | } |
2067 | 0 | if (!val) continue; |
2068 | 0 | f << "g" << i << "=" << val << ","; |
2069 | 0 | } |
2070 | 0 | if (version()<9) { |
2071 | 0 | for (int i=0; i<10; ++i) { // 0 |
2072 | 0 | val=int(input->readLong(2)); |
2073 | 0 | if (!val) |
2074 | 0 | continue; |
2075 | 0 | if (i==2) { // checkme, something is bad here |
2076 | 0 | if (val!=100) |
2077 | 0 | f << "min[line,width]=" << 100-val << ","; |
2078 | 0 | } |
2079 | 0 | else if (i==3) |
2080 | 0 | f << "para[orphan]=" << val << ","; |
2081 | 0 | else if (i==4) |
2082 | 0 | f << "para[window]=" << val << ","; |
2083 | 0 | else |
2084 | 0 | f << "h" << i << "=" << val << ","; |
2085 | 0 | } |
2086 | 0 | } |
2087 | 0 | else { |
2088 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
2089 | 0 | input->seek(pos+104, librevenge::RVNG_SEEK_SET); |
2090 | 0 | } |
2091 | 0 | ascFile.addPos(pos); |
2092 | 0 | ascFile.addNote(f.str().c_str()); |
2093 | 0 | return true; |
2094 | 0 | } |
2095 | | |
2096 | | bool Canvas5StyleManager::readParaStyles(std::shared_ptr<Canvas5Structure::Stream> stream) |
2097 | 0 | { |
2098 | 0 | if (!stream || !stream->input()) |
2099 | 0 | return false; |
2100 | 0 | auto input=stream->input(); |
2101 | 0 | libmwaw::DebugFile &ascFile = stream->ascii(); |
2102 | 0 | ascFile.addPos(input->tell()); |
2103 | 0 | ascFile.addNote("Entries(ParaStyl):"); |
2104 | |
|
2105 | 0 | if (version()>=9) { |
2106 | 0 | return m_mainParser->readArray9(stream, "ParaStyl", |
2107 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &what) { |
2108 | 0 | libmwaw::DebugStream f; |
2109 | 0 | auto &asciiFile=lStream->ascii(); |
2110 | 0 | auto lInput=lStream->input(); |
2111 | 0 | long endPos=lInput->tell()+item.m_length; |
2112 | 0 | lInput->seek(-4, librevenge::RVNG_SEEK_CUR); |
2113 | 0 | long pos=lInput->tell(); |
2114 | 0 | f << what << "-" << item.m_id << ":"; |
2115 | |
|
2116 | 0 | asciiFile.addPos(pos); |
2117 | 0 | asciiFile.addNote(f.str().c_str()); |
2118 | 0 | if (!readParaStyle(lStream, item.m_id)) |
2119 | 0 | return; |
2120 | | |
2121 | 0 | pos=lInput->tell(); |
2122 | 0 | f.str(""); |
2123 | 0 | f << what << "-" << item.m_id << "[B]:"; |
2124 | 0 | if (pos+44>endPos) { |
2125 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readParaStyles: the zone seems too short\n")); |
2126 | 0 | f << "###"; |
2127 | 0 | asciiFile.addPos(pos); |
2128 | 0 | asciiFile.addNote(f.str().c_str()); |
2129 | 0 | return; |
2130 | 0 | } |
2131 | 0 | for (int i=0; i<4; ++i) { // f1=0|1, f3=0|1 |
2132 | 0 | int val=int(lInput->readLong(2)); |
2133 | 0 | if (val) |
2134 | 0 | f << "f" << i << "=" << val << ","; |
2135 | 0 | } |
2136 | 0 | asciiFile.addPos(pos); |
2137 | 0 | asciiFile.addNote(f.str().c_str()); |
2138 | |
|
2139 | 0 | pos=lInput->tell(); |
2140 | 0 | f.str(""); |
2141 | 0 | f << what << "-" << item.m_id << "[name]:"; |
2142 | 0 | std::string name; |
2143 | 0 | for (int i=0; i<32; ++i) { |
2144 | 0 | char c=char(lInput->readLong(1)); |
2145 | 0 | if (c==0) break; |
2146 | 0 | name+=c; |
2147 | 0 | } |
2148 | 0 | f << name << ","; |
2149 | 0 | lInput->seek(pos+32, librevenge::RVNG_SEEK_SET); |
2150 | 0 | int val=int(lInput->readLong(4)); // unsure can be an extended size |
2151 | 0 | if (val) |
2152 | 0 | f << "f0=" << val << ","; |
2153 | 0 | asciiFile.addPos(pos); |
2154 | 0 | asciiFile.addNote(f.str().c_str()); |
2155 | 0 | }); |
2156 | 0 | } |
2157 | | |
2158 | 0 | if (!m_mainParser->readUsed(*stream, "ParaStyl")) |
2159 | 0 | return false; |
2160 | | |
2161 | 0 | if (!m_mainParser->readExtendedHeader(stream, 0x114, "ParaStyl", &Canvas5Parser::stringDataFunction)) // string:256 + 5xlong? |
2162 | 0 | return false; |
2163 | | |
2164 | 0 | if (!m_mainParser->readExtendedHeader(stream, 0xa8, "ParaStyl", |
2165 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &what) { |
2166 | 0 | if (!readParaStyle(lStream, item.m_id)) |
2167 | 0 | return; |
2168 | 0 | auto lInput=lStream->input(); |
2169 | 0 | long pos=lInput->tell(); |
2170 | 0 | libmwaw::DebugStream f; |
2171 | 0 | auto &asciiFile=lStream->ascii(); |
2172 | 0 | f << what << "-" << item.m_id << "[B]:"; |
2173 | 0 | for (int i=0; i<4; ++i) { // f1=0|1, f3=0|1 |
2174 | 0 | int val=int(lInput->readLong(2)); |
2175 | 0 | if (val) |
2176 | 0 | f << "f" << i << "=" << val << ","; |
2177 | 0 | } |
2178 | 0 | asciiFile.addPos(pos); |
2179 | 0 | asciiFile.addNote(f.str().c_str()); |
2180 | |
|
2181 | 0 | pos=lInput->tell(); |
2182 | 0 | f.str(""); |
2183 | 0 | f << what << "-" << item.m_id << "[name]:"; |
2184 | 0 | std::string name; |
2185 | 0 | for (int i=0; i<32; ++i) { |
2186 | 0 | char c=char(lInput->readLong(1)); |
2187 | 0 | if (c==0) break; |
2188 | 0 | name+=c; |
2189 | 0 | } |
2190 | 0 | f << name << ","; |
2191 | 0 | lInput->seek(pos+32, librevenge::RVNG_SEEK_SET); |
2192 | 0 | asciiFile.addPos(pos); |
2193 | 0 | asciiFile.addNote(f.str().c_str()); |
2194 | 0 | })) |
2195 | 0 | return false; |
2196 | 0 | if (!m_mainParser->readIndexMap(stream, "ParaStyl")) |
2197 | 0 | return false; |
2198 | 0 | std::vector<bool> defined; |
2199 | 0 | return m_mainParser->readDefined(*stream, defined, "ParaStyl"); |
2200 | 0 | } |
2201 | | |
2202 | | bool Canvas5StyleManager::readFrameStyles9(std::shared_ptr<Canvas5Structure::Stream> stream) |
2203 | 0 | { |
2204 | 0 | if (!stream || !stream->input()) return false; |
2205 | 0 | auto input=stream->input(); |
2206 | 0 | auto &ascFile=stream->ascii(); |
2207 | 0 | long pos=input->tell(); |
2208 | 0 | libmwaw::DebugStream f; |
2209 | 0 | f << "Entries(FrameStyl):"; |
2210 | 0 | ascFile.addPos(pos); |
2211 | 0 | ascFile.addNote(f.str().c_str()); |
2212 | |
|
2213 | 0 | if (!m_mainParser->readArray9(stream, "FrameStyl[stroke]", |
2214 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
2215 | 0 | auto lInput=lStream->input(); |
2216 | 0 | libmwaw::DebugFile &asciiFile = lStream->ascii(); |
2217 | 0 | libmwaw::DebugStream lF; |
2218 | 0 | lF << "St" << item.m_id << ","; |
2219 | 0 | if (item.m_length!=20) { |
2220 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readFrameStyles9[stroke]: unexpected lengths\n")); |
2221 | 0 | lF << "###"; |
2222 | 0 | asciiFile.addPos(item.m_pos); |
2223 | 0 | asciiFile.addNote(lF.str().c_str()); |
2224 | 0 | return; |
2225 | 0 | } |
2226 | 0 | Canvas5StyleManagerInternal::Stroke style; |
2227 | 0 | style.m_type=item.m_type; |
2228 | 0 | style.m_penId=int(lInput->readLong(4)); |
2229 | 0 | style.m_dashId=int(lInput->readLong(4)); |
2230 | 0 | for (int i=0; i<2; ++i) |
2231 | 0 | style.m_arrowId[i]=int(lInput->readLong(4)); |
2232 | 0 | int val=int(lInput->readLong(4)); |
2233 | 0 | if (val) { |
2234 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readFrameStyles9[stroke]: find extra value\n")); |
2235 | 0 | lF << "###f0=" << val << ","; |
2236 | 0 | } |
2237 | 0 | lF << style; |
2238 | 0 | m_state->m_idToStroke[item.m_id]=style; |
2239 | 0 | asciiFile.addPos(item.m_pos); |
2240 | 0 | asciiFile.addNote(lF.str().c_str()); |
2241 | 0 | })) |
2242 | 0 | return false; |
2243 | | |
2244 | 0 | if (!m_mainParser->readArray9(stream, "FrameStyl[pen]", |
2245 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
2246 | 0 | auto lInput=lStream->input(); |
2247 | 0 | auto &asciiFile=lStream->ascii(); |
2248 | 0 | libmwaw::DebugStream lF; |
2249 | 0 | lF << "Pe" << item.m_id << ","; |
2250 | 0 | if (item.m_decal!=4 || item.m_length<4) { |
2251 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::readFrameStyles9[pen]: the zone seems bad\n")); |
2252 | 0 | lF << "###"; |
2253 | 0 | asciiFile.addPos(item.m_pos); |
2254 | 0 | asciiFile.addNote(lF.str().c_str()); |
2255 | 0 | return; |
2256 | 0 | } |
2257 | 0 | lInput->seek(4, librevenge::RVNG_SEEK_CUR); |
2258 | 0 | auto style=readPenStyle(*lStream, item.m_type, item.m_length-4); |
2259 | 0 | if (!style) |
2260 | 0 | lF << "###"; |
2261 | 0 | else |
2262 | 0 | m_state->m_idToPen[item.m_id]=style; |
2263 | 0 | asciiFile.addPos(item.m_pos); |
2264 | 0 | asciiFile.addNote(lF.str().c_str()); |
2265 | 0 | })) |
2266 | 0 | return false; |
2267 | | |
2268 | 0 | if (!m_mainParser->readArray9(stream, "FrameStyl[arrow]", |
2269 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
2270 | 0 | auto lInput=lStream->input(); |
2271 | 0 | libmwaw::DebugStream lF; |
2272 | 0 | auto &asciiFile=lStream->ascii(); |
2273 | 0 | lF << "Arrow" << item.m_id << ","; |
2274 | 0 | MWAWGraphicStyle::Arrow arrow; |
2275 | 0 | if (!readArrow(lStream, arrow, 1, item.m_length)) |
2276 | 0 | lF << "###"; |
2277 | 0 | else |
2278 | 0 | m_state->m_idToArrow[item.m_id]=arrow; |
2279 | 0 | asciiFile.addPos(item.m_pos); |
2280 | 0 | asciiFile.addNote(lF.str().c_str()); |
2281 | 0 | })) |
2282 | 0 | return false; |
2283 | | |
2284 | 0 | return m_mainParser->readArray9(stream, "FrameStyl[dash]", |
2285 | 0 | [this](std::shared_ptr<Canvas5Structure::Stream> lStream, Canvas5Parser::Item const &item, std::string const &) { |
2286 | 0 | auto lInput=lStream->input(); |
2287 | 0 | libmwaw::DebugFile &asciiFile = lStream->ascii(); |
2288 | 0 | libmwaw::DebugStream lF; |
2289 | 0 | lF << "Da" << item.m_id << ","; |
2290 | 0 | std::vector<float> dashes; |
2291 | 0 | if (!readDash(*lStream, dashes, 1, item.m_length)) |
2292 | 0 | lF << "###"; |
2293 | 0 | else |
2294 | 0 | m_state->m_idToDash[item.m_id]=dashes; |
2295 | 0 | asciiFile.addPos(item.m_pos); |
2296 | 0 | asciiFile.addNote(lF.str().c_str()); |
2297 | 0 | }); |
2298 | 0 | } |
2299 | | |
2300 | | //////////////////////////////////////////////////////////// |
2301 | | // |
2302 | | // Windows resource |
2303 | | // |
2304 | | //////////////////////////////////////////////////////////// |
2305 | | |
2306 | | //////////////////////////////////////////////////////////// |
2307 | | // |
2308 | | // send data |
2309 | | // |
2310 | | //////////////////////////////////////////////////////////// |
2311 | | bool Canvas5StyleManager::updateLineColor(int cId, MWAWGraphicStyle &style) |
2312 | 0 | { |
2313 | 0 | auto it=m_state->m_idToColor.find(cId); |
2314 | 0 | if (it==m_state->m_idToColor.end() || !it->second) { |
2315 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLineColor: can not find color %d\n", cId)); |
2316 | 0 | return false; |
2317 | 0 | } |
2318 | 0 | return updateLineColor(*it->second, style); |
2319 | 0 | } |
2320 | | |
2321 | | bool Canvas5StyleManager::updateLineColor(Canvas5StyleManagerInternal::ColorStyle const &color, MWAWGraphicStyle &style) |
2322 | 0 | { |
2323 | 0 | switch (color.m_type) { |
2324 | 0 | case 0: // checkme |
2325 | 0 | style.m_lineOpacity=0; |
2326 | 0 | break; |
2327 | 0 | case 1: |
2328 | 0 | if (!color.m_color.isSet()) { |
2329 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLineColor: can not find color\n")); |
2330 | 0 | break; |
2331 | 0 | } |
2332 | 0 | style.m_lineColor=*color.m_color; |
2333 | 0 | if (color.m_color->getAlpha()!=255) |
2334 | 0 | style.m_lineOpacity=float(color.m_color->getAlpha())/255; |
2335 | 0 | break; |
2336 | 0 | case 0x50415453: // pats |
2337 | 0 | case 0x54585552: // texture |
2338 | 0 | if (color.m_color.isSet()) |
2339 | 0 | style.m_lineColor=*color.m_color; |
2340 | 0 | break; |
2341 | 0 | case 0x68746368: // hatch |
2342 | 0 | case 0x766b666c: // vkfl |
2343 | 0 | if (color.m_color.isSet()) |
2344 | 0 | style.m_lineColor=*color.m_color; |
2345 | 0 | break; |
2346 | 0 | case 0x4f62466c: // ObFl |
2347 | 0 | if (color.m_gradient.hasGradient()) |
2348 | 0 | color.m_gradient.getAverageColor(style.m_lineColor); |
2349 | 0 | break; |
2350 | 0 | default: |
2351 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLineColor: can not send type=%s\n", Canvas5Structure::getString(color.m_type).c_str())); |
2352 | 0 | break; |
2353 | 0 | } |
2354 | 0 | return true; |
2355 | 0 | } |
2356 | | |
2357 | | bool Canvas5StyleManager::updateSurfaceColor(int cId, MWAWGraphicStyle &style) |
2358 | 0 | { |
2359 | 0 | auto it=m_state->m_idToColor.find(cId); |
2360 | 0 | if (it==m_state->m_idToColor.end() || !it->second) { |
2361 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateSurfaceColor: can not find color %d\n", cId)); |
2362 | 0 | return false; |
2363 | 0 | } |
2364 | 0 | return updateSurfaceColor(*it->second, style); |
2365 | 0 | } |
2366 | | |
2367 | | bool Canvas5StyleManager::updateSurfaceColor(Canvas5StyleManagerInternal::ColorStyle const &color, MWAWGraphicStyle &style) |
2368 | 0 | { |
2369 | 0 | switch (color.m_type) { |
2370 | 0 | case 0: |
2371 | 0 | style.m_surfaceOpacity=0; |
2372 | 0 | break; |
2373 | 0 | case 1: |
2374 | 0 | if (color.m_color.isSet()) |
2375 | 0 | style.setSurfaceColor(*color.m_color, float(color.m_color->getAlpha())/255); |
2376 | 0 | else { |
2377 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateSurfaceColor: can not find the color\n")); |
2378 | 0 | return false; |
2379 | 0 | } |
2380 | 0 | break; |
2381 | 0 | case 0x50415453: // pats |
2382 | 0 | case 0x54585552: // txur |
2383 | 0 | if (color.m_texture.isEmpty()) { |
2384 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateSurfaceColor: can not find the texture\n")); |
2385 | 0 | return false; |
2386 | 0 | } |
2387 | 0 | style.setPattern(MWAWGraphicStyle::Pattern(color.m_textureDim, color.m_texture, *color.m_color)); |
2388 | 0 | break; |
2389 | 0 | case 0x4f62466c: |
2390 | 0 | if (!color.m_gradient.hasGradient()) { |
2391 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateSurfaceColor: can not find the gradient\n")); |
2392 | 0 | return false; |
2393 | 0 | } |
2394 | 0 | style.m_gradient=color.m_gradient; |
2395 | 0 | break; |
2396 | 0 | case 0x68746368: |
2397 | 0 | if (!color.m_hatch.hasHatch()) { |
2398 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateSurfaceColor: can not find the hatch\n")); |
2399 | 0 | return false; |
2400 | 0 | } |
2401 | 0 | style.m_hatch=color.m_hatch; |
2402 | 0 | if (color.m_color.isSet()) |
2403 | 0 | style.setSurfaceColor(*color.m_color, float(color.m_color->getAlpha())/255); |
2404 | 0 | break; |
2405 | 0 | case 0x766b666c: { // vkfl |
2406 | 0 | if (color.m_color.isSet()) { |
2407 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateSurfaceColor: can not find the symbol color\n")); |
2408 | 0 | return false; |
2409 | 0 | } |
2410 | 0 | style.setSurfaceColor(*color.m_color, float(color.m_color->getAlpha())/255); |
2411 | 0 | static bool first=true; |
2412 | 0 | if (first) { |
2413 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateSurfaceColor: symbol color are replaced by background color\n")); |
2414 | 0 | first=false; |
2415 | 0 | } |
2416 | 0 | break; |
2417 | 0 | } |
2418 | 0 | default: |
2419 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateSurfaceColor: can not send type=%s\n", Canvas5Structure::getString(color.m_type).c_str())); |
2420 | 0 | break; |
2421 | 0 | } |
2422 | 0 | return true; |
2423 | 0 | } |
2424 | | |
2425 | | bool Canvas5StyleManager::updateLine(Canvas5StyleManagerInternal::PenStyle const &pen, MWAWGraphicStyle &style, int &numLines, int lineId, float *offset) |
2426 | 0 | { |
2427 | 0 | numLines=1; |
2428 | 0 | if (offset) *offset=0; |
2429 | 0 | style.m_lineWidth=0; |
2430 | |
|
2431 | 0 | switch (pen.m_type) { |
2432 | 0 | case 1: |
2433 | 0 | style.m_lineWidth=(pen.m_size[0]+pen.m_size[1])/2; |
2434 | 0 | break; |
2435 | 0 | case 0x766e656f: { // vneo |
2436 | 0 | style.m_lineWidth=(pen.m_size[0]+pen.m_size[1])/2; |
2437 | | // fixme: normally a gradient, let's replace it by it barycenters color... |
2438 | 0 | style.m_lineColor=MWAWColor::barycenter(0.5, *pen.m_colors[0], 0.5, *pen.m_colors[1]); |
2439 | 0 | static bool first=true; |
2440 | 0 | if (first) { |
2441 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLine: replace line gradient with their average color\n")); |
2442 | 0 | first=false; |
2443 | 0 | } |
2444 | 0 | break; |
2445 | 0 | } |
2446 | 0 | case 0x706c696e: // plin |
2447 | 0 | numLines=int(pen.m_lines.size()); |
2448 | 0 | if ((lineId>=0 && lineId<numLines) || (numLines==1 && lineId<0)) { |
2449 | 0 | auto const &line = pen.m_lines[size_t(lineId)]; |
2450 | 0 | style.m_lineWidth=(line.m_size[0]+line.m_size[1])/2; |
2451 | 0 | style.m_lineColor=*line.m_color; |
2452 | 0 | if (offset) *offset=line.m_offset; |
2453 | 0 | } |
2454 | 0 | else if (lineId>=0) { |
2455 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLine: can not find the line with: %d\n", lineId)); |
2456 | 0 | return false; |
2457 | 0 | } |
2458 | 0 | break; |
2459 | 0 | default: |
2460 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLineStyle: can not send pen with type %s\n", Canvas5Structure::getString(pen.m_type).c_str())); |
2461 | 0 | return false; |
2462 | 0 | } |
2463 | 0 | return true; |
2464 | 0 | } |
2465 | | |
2466 | | bool Canvas5StyleManager::updateLineStyle(int sId, MWAWGraphicStyle &style, int &numLines, int lineId, float *offset) |
2467 | 0 | { |
2468 | 0 | numLines=1; |
2469 | 0 | if (offset) *offset=0; |
2470 | 0 | auto it=m_state->m_idToStroke.find(sId); |
2471 | 0 | if (it==m_state->m_idToStroke.end()) { |
2472 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLineStyle: can not find stroke %d\n", sId)); |
2473 | 0 | return false; |
2474 | 0 | } |
2475 | 0 | auto const &stroke=it->second; |
2476 | 0 | style.m_lineWidth=0; |
2477 | 0 | if (stroke.m_penId) { |
2478 | 0 | auto pIt=m_state->m_idToPen.find(stroke.m_penId); |
2479 | 0 | if (pIt==m_state->m_idToPen.end() || !pIt->second) { |
2480 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLineStyle: can not find pen %d\n", stroke.m_penId)); |
2481 | 0 | } |
2482 | 0 | else |
2483 | 0 | updateLine(*pIt->second, style, numLines, lineId, offset); |
2484 | 0 | } |
2485 | 0 | if (stroke.m_dashId) { |
2486 | 0 | auto dIt=m_state->m_idToDash.find(stroke.m_dashId); |
2487 | 0 | if (dIt==m_state->m_idToDash.end()) { |
2488 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLineStyle: can not find dash %d\n", stroke.m_dashId)); |
2489 | 0 | } |
2490 | 0 | else |
2491 | 0 | style.m_lineDashWidth=dIt->second; |
2492 | 0 | } |
2493 | 0 | for (int i=0; i<2; ++i) { |
2494 | 0 | if (!stroke.m_arrowId[i]) |
2495 | 0 | continue; |
2496 | 0 | auto dIt=m_state->m_idToArrow.find(stroke.m_arrowId[i]); |
2497 | 0 | if (dIt==m_state->m_idToArrow.end()) { |
2498 | 0 | MWAW_DEBUG_MSG(("Canvas5StyleManager::updateLineStyle: can not find arrow %d\n", stroke.m_arrowId[i])); |
2499 | 0 | } |
2500 | 0 | else |
2501 | 0 | style.m_arrows[i]=dIt->second; |
2502 | 0 | } |
2503 | 0 | return true; |
2504 | 0 | } |
2505 | | |
2506 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |