Coverage Report

Created: 2026-03-12 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/WingzGraph.cxx
Line
Count
Source
1
/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2
3
/* libmwaw
4
* Version: MPL 2.0 / LGPLv2+
5
*
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 2.0 (the "License"); you may not use this file except in compliance with
8
* the License or as specified alternatively below. You may obtain a copy of
9
* the License at http://www.mozilla.org/MPL/
10
*
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
14
* License.
15
*
16
* Major Contributor(s):
17
* Copyright (C) 2002 William Lachance (wrlach@gmail.com)
18
* Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
19
* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
20
* Copyright (C) 2006, 2007 Andrew Ziem
21
* Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
22
*
23
*
24
* All Rights Reserved.
25
*
26
* For minor contributions see the git repository.
27
*
28
* Alternatively, the contents of this file may be used under the terms of
29
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
30
* in which case the provisions of the LGPLv2+ are applicable
31
* instead of those above.
32
*/
33
34
#include <algorithm>
35
#include <cmath>
36
#include <iomanip>
37
#include <iostream>
38
#include <limits>
39
#include <map>
40
#include <sstream>
41
#include <stack>
42
43
#include <librevenge/librevenge.h>
44
45
#include "MWAWFont.hxx"
46
#include "MWAWFontConverter.hxx"
47
#include "MWAWGraphicShape.hxx"
48
#include "MWAWListener.hxx"
49
#include "MWAWParagraph.hxx"
50
#include "MWAWPosition.hxx"
51
#include "MWAWSubDocument.hxx"
52
53
#include "WingzParser.hxx"
54
55
#include "WingzGraph.hxx"
56
57
/** Internal: the structures of a WingzGraph */
58
namespace WingzGraphInternal
59
{
60
//! Internal a Graphic of a WingzGraph
61
struct Graphic {
62
  //! the constructor
63
  Graphic()
64
521k
    : m_type(-1)
65
521k
    , m_order(-1)
66
521k
    , m_position()
67
521k
    , m_relativePosition()
68
521k
    , m_style(MWAWGraphicStyle::emptyStyle())
69
521k
    , m_vertices()
70
521k
    , m_children()
71
72
521k
    , m_textType(-1)
73
521k
    , m_textEntry()
74
521k
    , m_fontList()
75
521k
    , m_posToFontId()
76
521k
    , m_paragraph()
77
78
521k
    , m_flag(0)
79
521k
  {
80
1.04M
    for (auto &angle : m_angles) angle=0;
81
521k
  }
82
  //! the file type
83
  int m_type;
84
  //! the order
85
  int m_order;
86
  //! the cell
87
  MWAWBox2i m_position;
88
  //! the relative position (% of cell)
89
  MWAWBox2f m_relativePosition;
90
  //! the graphic style
91
  MWAWGraphicStyle m_style;
92
  //! the angles: for arc
93
  float m_angles[2];
94
  //! the vertices list: poly (% of box)
95
  std::vector<MWAWVec2f> m_vertices;
96
  //! the children: group
97
  std::vector<std::shared_ptr<Graphic> > m_children;
98
  //! the data : if picture 0: data, if textbox/button 0:button, 1:title
99
  MWAWEntry m_entry[2];
100
  //! the name/title basic font
101
  MWAWFont m_font[2];
102
103
  // textbox
104
  //! the textbox type
105
  int m_textType;
106
  //! the textbox entry
107
  MWAWEntry m_textEntry;
108
  //! list of fonts: textbox
109
  std::vector<MWAWFont> m_fontList;
110
  //! map pos to fontId
111
  std::map<int, size_t> m_posToFontId;
112
  //! the paragraph: textbox
113
  MWAWParagraph m_paragraph;
114
115
  //! some flag (depending of type)
116
  int m_flag;
117
};
118
119
////////////////////////////////////////
120
//! Internal: the state of a WingzGraph
121
struct State {
122
  //! constructor
123
  State()
124
8.31k
    : m_patternList()
125
8.31k
    , m_pictureList()
126
8.31k
    , m_groupStack()
127
8.31k
    , m_inGroupDepth(0)
128
8.31k
  {
129
8.31k
  }
130
  //! init the pattern list
131
  void initPatterns(int vers);
132
  //! add a new graphic
133
  void addGraphic(std::shared_ptr<WingzGraphInternal::Graphic> graphic)
134
203k
  {
135
203k
    if (!m_groupStack.empty() && m_groupStack.top())
136
132k
      m_groupStack.top()->m_children.push_back(graphic);
137
71.1k
    else
138
71.1k
      m_pictureList.push_back(graphic);
139
203k
  }
140
  //! the patterns list
141
  std::vector<MWAWGraphicStyle::Pattern> m_patternList;
142
  //! the list of picture
143
  std::vector<std::shared_ptr<Graphic> > m_pictureList;
144
  //! the group stack
145
  std::stack<std::shared_ptr<Graphic> > m_groupStack;
146
  //! the group actual depth
147
  int m_inGroupDepth;
148
};
149
150
void State::initPatterns(int vers)
151
1.57k
{
152
1.57k
  if (!m_patternList.empty())
153
0
    return;
154
1.57k
  static uint16_t const patternsWingz[] = {
155
1.57k
    0x0,0x0,0x0,0x0/*none*/, 0xffff,0xffff,0xffff,0xffff, 0xfffb,0xffbf,0xfffb,0xffbf, 0xff77,0xffdd,0xff77,0xffdd,
156
1.57k
    0x4411,0x4411,0x4411,0x4411, 0xfffb,0xfffb,0xfffb,0xfffb, 0x3333,0x3333,0x3333,0x3333, 0xfcf9,0xf3e7,0xcf9f,0x3f8e,
157
1.57k
    0x1111,0x1111,0x1111,0x1111, 0x1881,0xb136,0x0660,0x631b, 0x2004,0x8010,0x0108,0x4002, 0x1010,0x1010,0x1010,0x01ff,
158
1.57k
    0x0101,0x01ff,0x1010,0x10ff,
159
1.57k
    0x0001,0x0010,0x0001,0x0010, 0x8040,0x2000,0x0001,0x0204, 0x7088,0x0505,0x0588,0x7002, 0xc7ab,0x11ba,0x7cba,0x91eb,
160
1.57k
    0x1010,0x3844,0x8283,0x4428, 0x8142,0x2424,0x2424,0x1800, 0x007e,0x7e62,0x6262,0x7e00, 0x0000,0x0000,0x0000,0x0000,
161
1.57k
    0x0000,0x0010,0x0000,0x0001, 0x0001,0x0010,0x0001,0x0010, 0x0044,0x0011,0x0044,0x0011, 0x0011,0x0011,0x0011,0x0011,
162
1.57k
    0x00ff,0x00ff,0x00ff,0x00ff,
163
1.57k
    0x1122,0x4488,0x1122,0x4488, 0x000f,0x000f,0x000f,0x000f, 0x1020,0x4080,0x1020,0x4080, 0x4000,0x40aa,0x4000,0x4000,
164
1.57k
    0x4040,0x40ff,0x4040,0x4040, 0x1028,0x4482,0x0102,0x0408, 0x0814,0x2241,0x8800,0xaa00, 0x40a0,0x0000,0x040a,0x0000,
165
1.57k
    0x8004,0x040a,0x1221,0xa030, 0xa141,0x221a,0x0808,0x1422, 0x0102,0x0408,0x102a,0x66ff, 0x62e3,0xe3dd,0x263e,0x3edd,
166
1.57k
    0x0502,0x0002,0x058a,0x558a
167
1.57k
  };
168
1.57k
  static uint16_t const patternsResolve[] = {
169
1.57k
    0x0, 0x0, 0x0, 0x0, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff, 0xffff, 0xf7ff, 0xffff, 0x7fff, 0xf7ff, 0x7fff, 0xf7ff,
170
1.57k
    0xffee, 0xffbb, 0xffee, 0xffbb, 0x77dd, 0x77dd, 0x77dd, 0x77dd, 0xaa55, 0xaa55, 0xaa55, 0xaa55, 0x8822, 0x8822, 0x8822, 0x8822,
171
1.57k
    0xaa00, 0xaa00, 0xaa00, 0xaa00, 0xaa00, 0x4400, 0xaa00, 0x1100, 0x8800, 0xaa00, 0x8800, 0xaa00, 0x8800, 0x2200, 0x8800, 0x2200,
172
1.57k
    0x8000, 0x800, 0x8000, 0x800, 0x0, 0x11, 0x0, 0x11, 0x8000, 0x0, 0x800, 0x0, 0x0, 0x0, 0x0, 0x0,
173
1.57k
    0xeedd, 0xbb77, 0xeedd, 0xbb77, 0x3366, 0xcc99, 0x3366, 0xcc99, 0x1122, 0x4488, 0x1122, 0x4488, 0x8307, 0xe1c, 0x3870, 0xe0c1,
174
1.57k
    0x306, 0xc18, 0x3060, 0xc081, 0x102, 0x408, 0x1020, 0x4080, 0xffff, 0x0, 0x0, 0x0, 0xff00, 0x0, 0x0, 0x0,
175
1.57k
    0x77bb, 0xddee, 0x77bb, 0xddee, 0x99cc, 0x6633, 0x99cc, 0x6633, 0x8844, 0x2211, 0x8844, 0x2211, 0xe070, 0x381c, 0xe07, 0x83c1,
176
1.57k
    0xc060, 0x3018, 0xc06, 0x381, 0x8040, 0x2010, 0x804, 0x201, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0x8080, 0x8080, 0x8080, 0x8080,
177
1.57k
    0xffaa, 0xffaa, 0xffaa, 0xffaa, 0xe4e4, 0xe4e4, 0xe4e4, 0xe4e4, 0xffff, 0xff00, 0xff, 0x0, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
178
1.57k
    0xff00, 0xff00, 0xff00, 0xff00, 0xff00, 0x0, 0xff00, 0x0, 0x8888, 0x8888, 0x8888, 0x8888, 0xff80, 0x8080, 0x8080, 0x8080,
179
1.57k
    0x4ecf, 0xfce4, 0x473f, 0xf372, 0x6006, 0x36b1, 0x8118, 0x1b63, 0x2004, 0x4002, 0x1080, 0x801, 0x9060, 0x609, 0x9060, 0x609,
180
1.57k
    0x8814, 0x2241, 0x8800, 0xaa00, 0x2050, 0x8888, 0x8888, 0x502, 0xaa00, 0x8000, 0x8800, 0x8000, 0x2040, 0x8000, 0x804, 0x200,
181
1.57k
    0xf0f0, 0xf0f0, 0xf0f, 0xf0f, 0x77, 0x7777, 0x77, 0x7777, 0xff88, 0x8888, 0xff88, 0x8888, 0xaa44, 0xaa11, 0xaa44, 0xaa11,
182
1.57k
    0x8244, 0x2810, 0x2844, 0x8201, 0x8080, 0x413e, 0x808, 0x14e3, 0x8142, 0x2418, 0x1020, 0x4080, 0x40a0, 0x0, 0x40a, 0x0,
183
1.57k
    0x7789, 0x8f8f, 0x7798, 0xf8f8, 0xf1f8, 0x6cc6, 0x8f1f, 0x3663, 0xbf00, 0xbfbf, 0xb0b0, 0xb0b0, 0xff80, 0x8080, 0xff08, 0x808,
184
1.57k
    0x1020, 0x54aa, 0xff02, 0x408, 0x8, 0x142a, 0x552a, 0x1408, 0x55a0, 0x4040, 0x550a, 0x404, 0x8244, 0x3944, 0x8201, 0x101
185
1.57k
  };
186
1.57k
  MWAWGraphicStyle::Pattern pat;
187
1.57k
  pat.m_dim=MWAWVec2i(8,8);
188
1.57k
  pat.m_data.resize(8);
189
1.57k
  pat.m_colors[0]=MWAWColor::white();
190
1.57k
  pat.m_colors[1]=MWAWColor::black();
191
1.57k
  uint16_t const *patPtr=vers==2 ? patternsWingz : patternsResolve;
192
101k
  for (int i=0; i<(vers==2 ? 39 : 64); ++i) {
193
499k
    for (size_t j=0; j<8; j+=2, ++patPtr) {
194
399k
      pat.m_data[j]=uint8_t((*patPtr)>>8);
195
399k
      pat.m_data[j+1]=uint8_t((*patPtr)&0xFF);
196
399k
    }
197
99.9k
    m_patternList.push_back(pat);
198
99.9k
  }
199
1.57k
}
200
201
////////////////////////////////////////
202
//! Internal: the subdocument of a WingzGraph
203
class SubDocument final : public MWAWSubDocument
204
{
205
public:
206
  SubDocument(WingzGraph &pars, MWAWInputStreamPtr const &input, Graphic const &graph)
207
60.5k
    : MWAWSubDocument(pars.m_mainParser, input, MWAWEntry())
208
60.5k
    , m_graphParser(pars)
209
60.5k
    , m_graphic(graph)
210
60.5k
  {
211
60.5k
  }
212
213
  //! destructor
214
0
  ~SubDocument() final {}
215
216
  //! operator!=
217
  bool operator!=(MWAWSubDocument const &doc) const final;
218
219
  //! the parser function
220
  void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final;
221
222
protected:
223
  /** the graph parser */
224
  WingzGraph &m_graphParser;
225
  /** the graphic */
226
  Graphic const &m_graphic;
227
private:
228
  SubDocument(SubDocument const &orig) = delete;
229
  SubDocument &operator=(SubDocument const &orig) = delete;
230
};
231
232
void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/)
233
60.5k
{
234
60.5k
  if (!listener.get()) {
235
0
    MWAW_DEBUG_MSG(("WingzGraphInternal::SubDocument::parse: no listener\n"));
236
0
    return;
237
0
  }
238
60.5k
  long pos = m_input->tell();
239
60.5k
  m_graphParser.sendText(m_graphic);
240
60.5k
  m_input->seek(pos, librevenge::RVNG_SEEK_SET);
241
60.5k
}
242
243
bool SubDocument::operator!=(MWAWSubDocument const &doc) const
244
0
{
245
0
  if (MWAWSubDocument::operator!=(doc)) return true;
246
0
  auto const *sDoc = dynamic_cast<SubDocument const *>(&doc);
247
0
  if (!sDoc) return true;
248
0
  if (&m_graphParser != &sDoc->m_graphParser) return true;
249
0
  if (&m_graphic != &sDoc->m_graphic) return true;
250
0
  return false;
251
0
}
252
}
253
254
////////////////////////////////////////////////////////////
255
// constructor/destructor, ...
256
////////////////////////////////////////////////////////////
257
WingzGraph::WingzGraph(WingzParser &parser)
258
8.31k
  : m_parserState(parser.getParserState())
259
8.31k
  , m_state(new WingzGraphInternal::State)
260
8.31k
  , m_mainParser(&parser)
261
8.31k
{
262
8.31k
}
263
264
WingzGraph::~WingzGraph()
265
8.31k
{ }
266
267
int WingzGraph::version() const
268
523k
{
269
523k
  return m_parserState->m_version;
270
523k
}
271
272
////////////////////////////////////////////////////////////
273
//
274
// Intermediate level
275
//
276
////////////////////////////////////////////////////////////
277
278
////////////////////////////////////////////////////////////
279
// read a graphic zone
280
////////////////////////////////////////////////////////////
281
bool WingzGraph::readGraphic()
282
521k
{
283
521k
  auto input = m_parserState->m_input;
284
521k
  auto &ascFile = m_parserState->m_asciiFile;
285
521k
  long pos = input->tell();
286
521k
  if (!input->checkPosition(pos+60)) {
287
225
    MWAW_DEBUG_MSG(("WingzGraph::readGraphic: the header seems bad\n"));
288
225
    return false;
289
225
  }
290
521k
  auto graphic=std::make_shared<WingzGraphInternal::Graphic>();
291
521k
  auto type=static_cast<int>(input->readULong(1));
292
521k
  if (type!=0xe) return false;
293
521k
  auto fl=static_cast<int>(input->readULong(1));
294
521k
  auto dSz=static_cast<int>(input->readULong(2));
295
521k
  int id= (fl==0) ? 0 : static_cast<int>(input->readULong(2));
296
521k
  libmwaw::DebugStream f;
297
521k
  f << "Entries(Graphic):";
298
521k
  if (fl!=0x80) f << "fl=" << std::hex << fl << std::dec << ",";
299
521k
  if (id) f << "id=" << id << ",";
300
521k
  long actPos=input->tell();
301
521k
  auto nSz=static_cast<int>(input->readULong(1));
302
521k
  if (nSz>15) {
303
343k
    MWAW_DEBUG_MSG(("WingzGraph::readGraphic: the graphic title seems bad\n"));
304
343k
    f << "#nSz=" << nSz << ",";
305
343k
  }
306
178k
  else if (nSz) {
307
62.1k
    std::string name("");
308
519k
    for (int i=0; i<nSz; ++i) name+=char(input->readULong(1));
309
62.1k
    f << name << ",";
310
62.1k
  }
311
521k
  input->seek(actPos+16, librevenge::RVNG_SEEK_SET);
312
521k
  graphic->m_order=static_cast<int>(input->readULong(2));
313
521k
  f << "order=" << graphic->m_order << ",";
314
521k
  auto val=static_cast<int>(input->readULong(2)); // always 0
315
521k
  if (val) f << "f1=" << val << ",";
316
  // the position seem to be stored as cell + % of the cell width...
317
521k
  float decal[4];
318
2.08M
  for (auto &d : decal) d=static_cast<float>(input->readULong(1))/255.f;
319
521k
  graphic->m_relativePosition=MWAWBox2f(MWAWVec2f(decal[2],decal[0]),MWAWVec2f(decal[3],decal[1]));
320
521k
  int dim[4]; // the cells which included the picture
321
2.08M
  for (auto &d : dim) d=static_cast<int>(input->readULong(2));
322
521k
  graphic->m_position=MWAWBox2i(MWAWVec2i(dim[0],dim[1]),MWAWVec2i(dim[2],dim[3]));
323
521k
  f << "dim=" << dim[0] << ":" << decal[2] << "x"
324
521k
    << dim[1] << ":" << decal[0] << "<->"
325
521k
    << dim[2] << ":" << decal[3] << "x"
326
521k
    << dim[3] << ":" << decal[1] << ",";
327
521k
  type=graphic->m_type=static_cast<int>(input->readULong(2));
328
521k
  val=static_cast<int>(input->readULong(2)); // always 0
329
521k
  if (val) f << "f2=" << val << ",";
330
331
521k
  long endPos=pos+(version()==1 ? 4 : 8)+dSz;
332
521k
  long dataPos=input->tell();
333
521k
  if (type==0 || type==2) {
334
360k
    for (int i=0; i<2; ++i) { // name, title
335
240k
      auto sSz=static_cast<int>(input->readULong(1));
336
240k
      if (!input->checkPosition(input->tell()+sSz+1)) {
337
99
        MWAW_DEBUG_MSG(("WingzGraph::readGraphic: can not find the textbox name%d\n", i));
338
99
        return false;
339
99
      }
340
240k
      if (!sSz)
341
116k
        continue;
342
123k
      graphic->m_entry[i].setBegin(input->tell());
343
123k
      graphic->m_entry[i].setLength(sSz);
344
123k
      std::string name("");
345
5.32M
      for (int c=0; c<sSz; ++c) name+=char(input->readULong(1));
346
123k
      f << name << ",";
347
123k
    }
348
120k
    auto hasMacro=static_cast<int>(input->readLong(1));
349
120k
    if (hasMacro==1) {
350
8.61k
      f << "macro,";
351
8.61k
      if (!m_mainParser->readMacro()) return false;
352
8.61k
    }
353
111k
    else if (hasMacro) {
354
13.7k
      f << "###macro=" << hasMacro << ",";
355
13.7k
      ascFile.addPos(pos);
356
13.7k
      ascFile.addNote(f.str().c_str());
357
13.7k
      MWAW_DEBUG_MSG(("WingzGraph::readGraphic: can not find the textbox type\n"));
358
13.7k
      return false;
359
13.7k
    }
360
120k
  }
361
499k
  if (type==0 || type==2 || (type>=5 && type<=9)) {
362
114k
    bool canHaveShadow=true;
363
114k
    if (type>=5 && type<=9) {
364
16.7k
      static int const expectedSize[]= {0x38, 0x3c, 0x34, 0x40, 0x40 };
365
16.7k
      if (!input->checkPosition(endPos) || dSz < expectedSize[type-5]) {
366
1.62k
        MWAW_DEBUG_MSG(("WingzGraph::readGraphic: find bad size for shape\n"));
367
1.62k
        return false;
368
1.62k
      }
369
15.0k
      canHaveShadow=type==8;
370
15.0k
    }
371
98.0k
    else if (!input->checkPosition(input->tell()+30)) {
372
51
      MWAW_DEBUG_MSG(("WingzGraph::readGraphic: find bad size for text/button\n"));
373
51
      return false;
374
51
    }
375
113k
    int patId;
376
113k
    MWAWColor color;
377
113k
    MWAWGraphicStyle::Pattern pattern;
378
113k
    readPattern(pattern, patId);
379
113k
    if (patId) {
380
75.9k
      if (pattern.getUniqueColor(color)) {
381
61.1k
        graphic->m_style.setSurfaceColor(color);
382
61.1k
        if (!color.isWhite())
383
59.7k
          f << "surf[col]=" << color << ",";
384
61.1k
      }
385
14.8k
      else {
386
14.8k
        f << "surf=" << pattern << ",";
387
14.8k
        graphic->m_style.setPattern(pattern);
388
14.8k
      }
389
75.9k
    }
390
37.1k
    else
391
37.1k
      f << "surf[col]=none,";
392
113k
    val=int(input->readLong(1));
393
113k
    if (val!=1) f << "f0=" << val << ",";
394
113k
    if (canHaveShadow) {
395
98.7k
      graphic->m_flag=val;
396
98.7k
      readColor(color, patId);
397
98.7k
      if (patId) {
398
34.6k
        if (graphic->m_flag&2)
399
11.2k
          graphic->m_style.setShadowColor(color);
400
34.6k
        f << "shadow[col]=" << color << ",";
401
34.6k
      }
402
98.7k
      val=int(input->readLong(1));
403
98.7k
      if (val) f << "f1=" << val << ",";
404
98.7k
    }
405
113k
    readColor(color, patId);
406
113k
    bool hasLine=true;
407
113k
    if (patId && !color.isBlack()) {
408
68.9k
      f << "line[col]=" << color << ",";
409
68.9k
      graphic->m_style.m_lineColor=color;
410
68.9k
    }
411
44.1k
    else if (!patId) {
412
40.1k
      hasLine=false;
413
40.1k
      f << "line[col]=none,";
414
40.1k
    }
415
113k
    val=int(input->readLong(1));
416
113k
    if (val!=1) f << "f2=" << val << ",";
417
418
113k
    val=static_cast<int>(input->readLong(2));
419
113k
    if (hasLine) graphic->m_style.m_lineWidth=float(val)/20.f;
420
113k
    if (val!=5) f << "line[w]=" << float(val)/20.f << ",";
421
113k
    if (canHaveShadow) {
422
296k
      for (int i=0; i<2; ++i) dim[i]=int(input->readLong(2));
423
98.7k
      if (dim[0]!=20 || dim[1]!=20) {
424
98.5k
        graphic->m_style.m_shadowOffset=MWAWVec2f(float(dim[0])/20.f,float(dim[1])/20.f);
425
98.5k
        f << "shadow[pos]=" << graphic->m_style.m_shadowOffset << ",";
426
98.5k
      }
427
98.7k
    }
428
113k
  }
429
497k
  switch (type) {
430
86.8k
  case 0: // button
431
98.0k
  case 2: { // textbox
432
98.0k
    f << "TextZone,g0=" << std::hex << dSz << std::dec << ",";
433
98.0k
    ascFile.addPos(pos);
434
98.0k
    ascFile.addNote(f.str().c_str());
435
98.0k
    return readTextZone(graphic);
436
86.8k
  }
437
2.87k
  case 4:
438
2.87k
    f << "Chart,";
439
2.87k
    ascFile.addPos(pos);
440
2.87k
    ascFile.addNote(f.str().c_str());
441
2.87k
    return readChartData(graphic);
442
658
  case 5:
443
3.94k
  case 6:
444
4.86k
  case 7:
445
5.61k
  case 8:
446
15.0k
  case 9: {
447
15.0k
    static int const expectedSize[]= {0x38, 0x3c, 0x34, 0x40, 0x40 };
448
15.0k
    if (!input->checkPosition(endPos) || dSz < expectedSize[type-5]) {
449
0
      MWAW_DEBUG_MSG(("WingzGraph::readGraphic: find bad size for shape\n"));
450
0
      return false;
451
0
    }
452
15.0k
    static char const* const what[]= {"line", "arc", "circle", "rectangle", "poly" };
453
15.0k
    f << what[type-5] << ",";
454
15.0k
    switch (type) {
455
658
    case 5: {
456
658
      int arrowWidth=static_cast<int>(input->readLong(2));
457
658
      if (arrowWidth!=0x21c) f << "arrow[size]=" << double(arrowWidth)/20. << ","; // default 27 point
458
658
      val=static_cast<int>(input->readULong(2));
459
658
      if (val&0x40) {
460
269
        f << "start[arrow],";
461
269
        graphic->m_style.m_arrows[0]=
462
269
          MWAWGraphicStyle::Arrow(float(arrowWidth)/20.f, MWAWBox2i(MWAWVec2i(0,0),MWAWVec2i(3000,3000)),
463
269
                                  "M1500 0l1500 3000h-3000zM1500 447l-1176 2353h2353z", false);
464
269
      }
465
658
      if (val&0x80) {
466
271
        f << "start[end],";
467
271
        graphic->m_style.m_arrows[1]=
468
271
          MWAWGraphicStyle::Arrow(float(arrowWidth)/20.f, MWAWBox2i(MWAWVec2i(0,0),MWAWVec2i(3000,3000)),
469
271
                                  "M1500 0l1500 3000h-3000zM1500 447l-1176 2353h2353z", false);
470
271
      }
471
658
      graphic->m_flag=(val&3);
472
658
      if (graphic->m_flag&3) f << "rot=" << (graphic->m_flag&3) << ",";
473
658
      val &= 0xff3c;
474
658
      if (val) f << "fl=" << std::hex << val << std::dec << ",";
475
658
      break;
476
0
    }
477
3.29k
    case 6: {
478
9.87k
      for (int i=0; i<2; ++i) { // 0|3fff
479
6.58k
        val=int(input->readULong(2));
480
6.58k
        if (!val) continue;
481
5.79k
        if (val==0x3fff)
482
14
          f << "h" << i << "*,";
483
5.78k
        else
484
5.78k
          f << "h" << i << "=" << val << ",";
485
5.79k
      }
486
6.58k
      for (auto &angle : graphic->m_angles) angle=float(input->readLong(2))/10.f;
487
3.29k
      f << "angles=" << MWAWVec2f(graphic->m_angles[0],graphic->m_angles[1]) << ",";
488
3.29k
      break;
489
0
    }
490
918
    case 7:
491
918
      break;
492
743
    case 8: {
493
743
      break;
494
0
    }
495
9.48k
    case 9: {
496
9.48k
      val=static_cast<int>(input->readULong(2));
497
9.48k
      if (val&1) f << "closed,";
498
9.48k
      if (val&2) f << "smooth,";
499
9.48k
      graphic->m_flag=val;
500
9.48k
      int arrowWidth=static_cast<int>(input->readLong(2));
501
9.48k
      if (arrowWidth!=0x21c) f << "arrow[size]=" << double(arrowWidth)/20. << ","; // default 27 point
502
9.48k
      if (val&0x40) {
503
423
        f << "start[arrow],";
504
423
        graphic->m_style.m_arrows[0]=
505
423
          MWAWGraphicStyle::Arrow(float(arrowWidth)/20.f, MWAWBox2i(MWAWVec2i(0,0),MWAWVec2i(3000,3000)),
506
423
                                  "M1500 0l1500 3000h-3000zM1500 447l-1176 2353h2353z", false);
507
423
      }
508
9.48k
      if (val&0x80) {
509
2.81k
        f << "start[end],";
510
2.81k
        graphic->m_style.m_arrows[0]=
511
2.81k
          MWAWGraphicStyle::Arrow(float(arrowWidth)/20.f, MWAWBox2i(MWAWVec2i(0,0),MWAWVec2i(3000,3000)),
512
2.81k
                                  "M1500 0l1500 3000h-3000zM1500 447l-1176 2353h2353z", false);
513
2.81k
      }
514
9.48k
      val &= 0xff3c;
515
9.48k
      if (val) f << "h0=" << val << ",";
516
9.48k
      int nbPt=int(input->readULong(2));
517
9.48k
      f << "nbPt=" << nbPt << ",";
518
9.48k
      if (input->tell()+nbPt*4>endPos) {
519
1.84k
        f << "###";
520
1.84k
        break;
521
1.84k
      }
522
7.63k
      f << "pts=[";
523
47.5k
      for (int i=0; i<nbPt; ++i) {
524
39.9k
        float pts[2];
525
79.8k
        for (auto &pt : pts) pt=float(input->readULong(2))/float(0x3fff);
526
39.9k
        graphic->m_vertices.push_back(MWAWVec2f(pts[0],pts[1]));
527
39.9k
        f << graphic->m_vertices.back() << ",";
528
39.9k
      }
529
7.63k
      f << "],";
530
7.63k
      break;
531
9.48k
    }
532
0
    default:
533
0
      break;
534
15.0k
    }
535
15.0k
    break;
536
15.0k
  }
537
43.2k
  case 0xa: {
538
43.2k
    if (!input->checkPosition(endPos)) {
539
55
      MWAW_DEBUG_MSG(("WingzGraph::readGraphic: find bad size for picture\n"));
540
55
      return false;
541
55
    }
542
43.1k
    f << "picture,";
543
43.1k
    auto pSz=long(input->readULong(2));
544
129k
    for (int i=0; i<2; ++i) { // g0=0, g1=2
545
86.3k
      val=static_cast<int>(input->readULong(2));
546
86.3k
      if (val) f << "g" << i << "=" << val << ",";
547
86.3k
    }
548
43.1k
    ascFile.addPos(pos);
549
43.1k
    ascFile.addNote(f.str().c_str());
550
43.1k
    if (!pSz || !input->checkPosition(dataPos+6+pSz)) {
551
2.47k
      MWAW_DEBUG_MSG(("WingzGraph::readGraphic: can not find the picture data\n"));
552
2.47k
      return false;
553
2.47k
    }
554
40.6k
    graphic->m_entry[0].setBegin(dataPos+6);
555
40.6k
    graphic->m_entry[0].setLength(pSz);
556
#ifdef DEBUG_WITH_FILES
557
    ascFile.skipZone(dataPos+6, dataPos+6+pSz-1);
558
    librevenge::RVNGBinaryData file;
559
    input->seek(dataPos+6, librevenge::RVNG_SEEK_SET);
560
    input->readDataBlock(pSz, file);
561
    static int volatile pictName = 0;
562
    libmwaw::DebugStream f2;
563
    f2.str("");
564
    f2 << "PICT-" << ++pictName;
565
    libmwaw::Debug::dumpFile(file, f2.str().c_str());
566
#endif
567
40.6k
    input->seek(dataPos+6+pSz, librevenge::RVNG_SEEK_SET);
568
40.6k
    break;
569
43.1k
  }
570
86.8k
  case 0xb: {
571
86.8k
    if (!input->checkPosition(endPos)) {
572
57
      MWAW_DEBUG_MSG(("WingzGraph::readGraphic: find bad size for group\n"));
573
57
      return false;
574
57
    }
575
86.8k
    f << "group,";
576
86.8k
    break;
577
86.8k
  }
578
251k
  default:
579
251k
    MWAW_DEBUG_MSG(("WingzGraph::readGraphic: find some unknown type %d\n", type));
580
251k
    f << "#typ=" << type << ",";
581
251k
    ascFile.addPos(pos);
582
251k
    ascFile.addNote(f.str().c_str());
583
251k
    return false;
584
497k
  }
585
142k
  m_state->addGraphic(graphic);
586
142k
  if (graphic->m_type==0xb)
587
86.8k
    m_state->m_groupStack.push(graphic);
588
142k
  if (input->tell()!=pos && input->tell()!=endPos)
589
142k
    ascFile.addDelimiter(input->tell(),'|');
590
142k
  ascFile.addPos(pos);
591
142k
  ascFile.addNote(f.str().c_str());
592
142k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
593
142k
  return true;
594
497k
}
595
596
bool WingzGraph::readEndGroup()
597
601
{
598
601
  auto input = m_parserState->m_input;
599
601
  auto &ascFile = m_parserState->m_asciiFile;
600
601
  long pos = input->tell();
601
601
  if (!input->checkPosition(pos+4)) {
602
0
    MWAW_DEBUG_MSG(("WingzGraph::readEndGroup: the header seems bad\n"));
603
0
    return false;
604
0
  }
605
601
  auto type=static_cast<int>(input->readULong(1));
606
601
  if (type!=0xf) return false;
607
601
  auto fl=static_cast<int>(input->readULong(1));
608
601
  auto dSz=static_cast<int>(input->readULong(2));
609
601
  int id= (fl==0) ? 0 : static_cast<int>(input->readULong(2));
610
601
  libmwaw::DebugStream f;
611
601
  f << "Entries(Group)[end]:";
612
601
  if (fl!=0x80) f << "fl=" << std::hex << fl << std::dec << ",";
613
601
  if (id) f << "id=" << id << ",";
614
601
  if (!input->checkPosition(input->tell()+dSz)) {
615
9
    MWAW_DEBUG_MSG(("WingzGraph::readEndGroup: the header seems bad\n"));
616
9
    return false;
617
9
  }
618
592
  if (dSz) {
619
103
    ascFile.addDelimiter(input->tell(),'|');
620
103
    input->seek(dSz, librevenge::RVNG_SEEK_CUR);
621
103
  }
622
592
  ascFile.addPos(pos);
623
592
  ascFile.addNote(f.str().c_str());
624
592
  if (m_state->m_groupStack.empty()) {
625
490
    MWAW_DEBUG_MSG(("WingzGraph::readEndGroup: can not found the group beginning\n"));
626
490
  }
627
102
  else
628
102
    m_state->m_groupStack.pop();
629
592
  return true;
630
601
}
631
632
////////////////////////////////////////////////////////////
633
// text box
634
////////////////////////////////////////////////////////////
635
bool WingzGraph::readTextZone(std::shared_ptr<WingzGraphInternal::Graphic> graphic)
636
98.0k
{
637
98.0k
  auto input = m_parserState->m_input;
638
98.0k
  auto &ascFile = m_parserState->m_asciiFile;
639
98.0k
  long pos = input->tell();
640
98.0k
  if (!input->checkPosition(pos+18)) {
641
52
    MWAW_DEBUG_MSG(("WingzGraph::readTextZone: the zone seems too short\n"));
642
52
    input->seek(pos, librevenge::RVNG_SEEK_SET);
643
52
    return false;
644
52
  }
645
646
97.9k
  libmwaw::DebugStream f;
647
97.9k
  f << "Entries(TextZone):";
648
97.9k
  int patId;
649
97.9k
  MWAWColor color;
650
97.9k
  readColor(color, patId);
651
97.9k
  if (patId)
652
59.9k
    f << "col[unkn]=" << color << ",";
653
97.9k
  int val=int(input->readULong(1));
654
97.9k
  if (val!=1) f << "f0=" << val << ",";
655
97.9k
  auto fontConverter=m_parserState->m_fontConverter;
656
237k
  for (int i=0; i<2; ++i) { // actual font and generic font ?
657
176k
    MWAWFont font;
658
176k
    f << "font" << i << "=[";
659
176k
    unsigned char colors[3];
660
530k
    for (auto &c : colors) c=static_cast<unsigned char>(input->readULong(1));
661
176k
    font.setColor(MWAWColor(colors[0],colors[1],colors[2]));
662
176k
    val=int(input->readLong(1)); // 0
663
176k
    if (val) f << "f0=" << val << ",";
664
176k
    font.setSize(float(input->readULong(1)));
665
176k
    auto flag=static_cast<int>(input->readULong(1));
666
176k
    uint32_t flags=0;
667
176k
    if (flag&0x1) flags |= MWAWFont::boldBit;
668
176k
    if (flag&0x2) flags |= MWAWFont::italicBit;
669
176k
    if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple);
670
176k
    if (flag&0x8) flags |= MWAWFont::embossBit;
671
176k
    if (flag&0x10) flags |= MWAWFont::shadowBit;
672
176k
    if (flag&0x60)
673
32.5k
      f << "#font[flag]=" << std::hex << (flag&0x60) << std::dec << ",";
674
176k
    font.setFlags(flags);
675
176k
    auto sSz=static_cast<int>(input->readULong(1));
676
176k
    if (!sSz || !input->checkPosition(input->tell()+4+sSz)) {
677
36.8k
      MWAW_DEBUG_MSG(("WingzGraph::readTextZone: can not determine the string zone %d\n", i));
678
36.8k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
679
36.8k
      return false;
680
36.8k
    }
681
139k
    std::string name("");
682
5.37M
    for (int j=0; j<sSz; ++j)
683
5.23M
      name+=char(input->readLong(1));
684
139k
    font.setId(fontConverter->getId(name));
685
139k
    f << font.getDebugString(fontConverter);
686
139k
    f << "],";
687
139k
    graphic->m_font[i]=font;
688
139k
  }
689
244k
  for (int i=0; i<3; ++i) {
690
183k
    val=static_cast<int>(input->readLong(2));
691
183k
    if (val) f << "g" << i << "=" << val;
692
183k
  }
693
61.1k
  ascFile.addPos(pos);
694
61.1k
  ascFile.addNote(f.str().c_str());
695
696
61.1k
  pos=input->tell();
697
61.1k
  f.str("");
698
61.1k
  f << "TextZone-A:";
699
61.1k
  graphic->m_textType=static_cast<int>(input->readLong(1));
700
61.1k
  m_state->addGraphic(graphic);
701
61.1k
  bool ok=true;
702
61.1k
  switch (graphic->m_textType) {
703
1.32k
  case 0:
704
1.32k
    f << "button,";
705
1.32k
    val=static_cast<int>(input->readLong(1));
706
1.32k
    if (val!=3) f << "f0=" << val << ",";
707
1.32k
    val=static_cast<int>(input->readLong(1));
708
1.32k
    if (val==0) f << "noContent,";
709
1.20k
    else if (val!=1) f << "#content=" << val << ",";
710
1.32k
    val=static_cast<int>(input->readLong(1));
711
1.32k
    if (val==1) f << "title,";
712
1.28k
    else if (val) f << "#title=" << val << ",";
713
1.32k
    val=static_cast<int>(input->readULong(1));
714
1.32k
    if (val) f << "h[content]=" << val << ",";
715
1.32k
    val=static_cast<int>(input->readULong(1));
716
1.32k
    if (val) f << "h[title]=" << val << ",";
717
1.32k
    ascFile.addPos(pos);
718
1.32k
    ascFile.addNote(f.str().c_str());
719
1.32k
    return true;
720
43.1k
  case 1:
721
43.1k
    ok=input->checkPosition(pos+60);
722
43.1k
    if (!ok) break;
723
43.1k
    f << "text,";
724
43.1k
    break;
725
2.98k
  case 5: {
726
2.98k
    ok=input->checkPosition(pos+53);
727
2.98k
    if (!ok) break;
728
2.98k
    f << "wheel,";
729
17.9k
    for (int i=0; i<5; ++i) {
730
14.9k
      val=int(input->readLong(1));
731
14.9k
      int const expected[]= {3,0,0,0,0};
732
14.9k
      if (val!=expected[i]) f << "f" << i << "=" << val << ",";
733
14.9k
    }
734
2.98k
    bool isNan;
735
2.98k
    double value;
736
2.98k
    f << "val=[";
737
17.9k
    for (int i=0; i<5; ++i) { // val, minVal, maxVal, incr?, maxVal-minVal?
738
14.9k
      if (!input->readDoubleReverted8(value,isNan)) {
739
4.98k
        f << "###,";
740
4.98k
        input->seek(pos+6+8*(i+1), librevenge::RVNG_SEEK_SET);
741
4.98k
      }
742
9.94k
      else
743
9.94k
        f << value << ",";
744
14.9k
    }
745
2.98k
    f << "],";
746
11.9k
    for (int i=0; i<3; ++i) { // small number
747
8.95k
      val=int(input->readLong(2));
748
8.95k
      if (val) f << "g" << i << "=" << val << ",";
749
8.95k
    }
750
2.98k
    ascFile.addDelimiter(input->tell(),'|');
751
2.98k
    input->seek(pos+53, librevenge::RVNG_SEEK_SET);
752
2.98k
    break;
753
2.98k
  }
754
525
  case 6: {
755
525
    ok=input->checkPosition(pos+40);
756
525
    if (!ok) break;
757
524
    f << "button[wheel],";
758
3.14k
    for (int i=0; i<5; ++i) {
759
2.62k
      val=int(input->readLong(1));
760
2.62k
      int const expected[]= {3,0,0,0,0};
761
2.62k
      if (val!=expected[i]) f << "f" << i << "=" << val << ",";
762
2.62k
    }
763
524
    bool isNan;
764
524
    double value;
765
524
    f << "val=[";
766
2.62k
    for (int i=0; i<4; ++i) { // val?, min, max, increment?
767
2.09k
      if (!input->readDoubleReverted8(value,isNan)) {
768
1.02k
        f << "###,";
769
1.02k
        input->seek(pos+6+8*(i+1), librevenge::RVNG_SEEK_SET);
770
1.02k
      }
771
1.07k
      else
772
1.07k
        f << value << ",";
773
2.09k
    }
774
524
    f << "],";
775
524
    val=int(input->readLong(2)); // 0
776
524
    if (val) f << "f5=" << val << ",";
777
524
    input->seek(pos+40, librevenge::RVNG_SEEK_SET);
778
524
    break;
779
525
  }
780
13.1k
  default:
781
13.1k
    MWAW_DEBUG_MSG(("WingzGraph::readTextZone: find unknown type %d\n", graphic->m_textType));
782
13.1k
    f << "###type=" << graphic->m_textType;
783
13.1k
    ok=false;
784
13.1k
    break;
785
61.1k
  }
786
787
59.8k
  if (!ok || graphic->m_textType!=1) {
788
16.6k
    ascFile.addPos(pos);
789
16.6k
    ascFile.addNote(f.str().c_str());
790
16.6k
    if (ok) return true;
791
13.1k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
792
13.1k
    return m_mainParser->findNextZone(0xe) && input->tell()>pos;
793
16.6k
  }
794
43.1k
  val=static_cast<int>(input->readLong(1));
795
43.1k
  if (val!=3) f<<"f0=" << val << ",";
796
43.1k
  auto &para=graphic->m_paragraph;
797
258k
  for (int i=0; i<5; ++i) {
798
215k
    val=static_cast<int>(input->readULong(2));
799
215k
    if (i==2 && (val>>12)) { // 1 left, 2 center, 3 right
800
25.5k
      switch ((val>>12)&3) {
801
1.34k
      case 0:
802
1.34k
      default:
803
1.34k
        f << "#align=0,";
804
1.34k
        break;
805
9.20k
      case 1: // left
806
9.20k
        break;
807
10.7k
      case 2:
808
10.7k
        para.m_justify = MWAWParagraph::JustificationCenter;
809
10.7k
        f << "center,";
810
10.7k
        break;
811
4.24k
      case 3:
812
4.24k
        para.m_justify = MWAWParagraph::JustificationRight;
813
4.24k
        f << "right,";
814
4.24k
        break;
815
25.5k
      }
816
25.5k
      val &= 0xCFFF;
817
25.5k
    }
818
215k
    if (val) f<<"f" << i+1 << "=" << std::hex << val << std::dec << ",";
819
215k
  }
820
43.1k
  val=static_cast<int>(input->readULong(4));
821
43.1k
  auto textSize=static_cast<int>(input->readLong(4));
822
43.1k
  if (val!=textSize)
823
37.2k
    f << "selection="<<val << ",";
824
43.1k
  val=static_cast<int>(input->readLong(2)); // 1|7
825
43.1k
  if (val!=1) f << "g0=" << val << ",";
826
43.1k
  val=static_cast<int>(input->readLong(2));
827
43.1k
  if (val) f << "g1=" << val << ",";
828
129k
  for (int i=0; i< 2; ++i) { // g2=0|1, g3=4|6, g3=64 -> scroll bar, g3&1 -> cell note?
829
86.2k
    val=static_cast<int>(input->readULong(1));
830
86.2k
    static int const expected[]= {0,0x40};
831
86.2k
    if (val!=expected[i])
832
60.2k
      f << "g" << i+2 << "=" << std::hex << val << std::dec << ",";
833
86.2k
  }
834
43.1k
  auto numFonts=static_cast<int>(input->readLong(2));
835
43.1k
  if (numFonts!=1) f << "numFonts=" << numFonts << ",";
836
43.1k
  val=static_cast<int>(input->readLong(2));
837
43.1k
  if (val) f << "h0=" << val << ",";
838
43.1k
  auto numPos=static_cast<int>(input->readULong(2));
839
43.1k
  if (numPos!=1) f << "numPos=" << numPos << ",";
840
647k
  for (int i=0; i<14; ++i) {
841
603k
    val=static_cast<int>(input->readLong(2));
842
603k
    if (!val) continue;
843
382k
    if (i==3) f << "marg[top]="  << double(val)/20. << ",";
844
352k
    else if (i==4) f << "marg[bottom]="  << double(val)/20. << ",";
845
326k
    else if (i==7) f << "tabs[repeat]=" << double(val)/20. << ",";
846
297k
    else
847
297k
      f << "h" << i+1 << "=" << val << ",";
848
382k
  }
849
43.1k
  ascFile.addPos(pos);
850
43.1k
  ascFile.addNote(f.str().c_str());
851
852
43.1k
  pos=input->tell();
853
43.1k
  if (textSize<0 || (long)((unsigned long)pos+(unsigned long)textSize)<pos || !input->checkPosition(pos+textSize)) {
854
4.84k
    MWAW_DEBUG_MSG(("WingzGraph::readTextZone: the text zone seems bad\n"));
855
4.84k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
856
4.84k
    return false;
857
4.84k
  }
858
38.2k
  f.str("");
859
38.2k
  f << "TextZone[text]:";
860
38.2k
  graphic->m_textEntry.setBegin(input->tell());
861
38.2k
  graphic->m_textEntry.setLength(textSize);
862
38.2k
  std::string text("");
863
2.20M
  for (int i=0; i< textSize; ++i) text+=char(input->readULong(1));
864
38.2k
  f << text;
865
38.2k
  ascFile.addPos(pos);
866
38.2k
  ascFile.addNote(f.str().c_str());
867
868
38.2k
  pos=input->tell();
869
38.2k
  if (!input->checkPosition(pos+numFonts*7)) {
870
2.66k
    MWAW_DEBUG_MSG(("WingzGraph::readTextZone: the fonts zone seems bad\n"));
871
2.66k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
872
2.66k
    return false;
873
2.66k
  }
874
35.6k
  f.str("");
875
35.6k
  f << "TextZone[fonts]:";
876
92.7k
  for (int i=0; i<numFonts; ++i) {
877
70.0k
    f << "font" << i << "=[";
878
70.0k
    MWAWFont font;
879
70.0k
    unsigned char colors[3];
880
210k
    for (auto &c : colors) c=static_cast<unsigned char>(input->readULong(1));
881
70.0k
    font.setColor(MWAWColor(colors[0],colors[1],colors[2]));
882
70.0k
    val=int(input->readLong(1)); // 0
883
70.0k
    if (val) f << "f0=" << val << ",";
884
70.0k
    font.setSize(float(input->readULong(1)));
885
70.0k
    auto flag=static_cast<int>(input->readULong(1));
886
70.0k
    uint32_t flags=0;
887
70.0k
    if (flag&0x1) flags |= MWAWFont::boldBit;
888
70.0k
    if (flag&0x2) flags |= MWAWFont::italicBit;
889
70.0k
    if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple);
890
70.0k
    if (flag&0x8) flags |= MWAWFont::embossBit;
891
70.0k
    if (flag&0x10) flags |= MWAWFont::shadowBit;
892
70.0k
    if (flag&0x60)
893
34.3k
      f << "#font[flag]=" << std::hex << (flag&0x60) << std::dec << ",";
894
70.0k
    font.setFlags(flags);
895
70.0k
    auto sSz=static_cast<int>(input->readULong(1));
896
70.0k
    if (!sSz || !input->checkPosition(input->tell()+sSz)) {
897
12.9k
      MWAW_DEBUG_MSG(("WingzGraph::readTextZone: can not determine the string zone %d\n", i));
898
12.9k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
899
12.9k
      return false;
900
12.9k
    }
901
57.1k
    std::string name("");
902
4.11M
    for (int j=0; j<sSz; ++j)
903
4.05M
      name+=char(input->readLong(1));
904
57.1k
    font.setId(fontConverter->getId(name));
905
57.1k
    f << font.getDebugString(fontConverter);
906
57.1k
    f << "],";
907
57.1k
    graphic->m_fontList.push_back(font);
908
57.1k
  }
909
22.7k
  ascFile.addPos(pos);
910
22.7k
  ascFile.addNote(f.str().c_str());
911
912
22.7k
  pos=input->tell();
913
22.7k
  if (!input->checkPosition(pos+16+numPos*6)) {
914
1.26k
    MWAW_DEBUG_MSG(("WingzGraph::readTextZone: the last zone seems bad\n"));
915
1.26k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
916
1.26k
    return false;
917
1.26k
  }
918
21.4k
  f.str("");
919
21.4k
  f << "TextZone-B:";
920
21.4k
  double extraLeading=0;
921
21.4k
  para.m_marginsUnit=librevenge::RVNG_POINT;
922
171k
  for (int i=0; i<7; ++i) {
923
150k
    val=static_cast<int>(input->readLong(2));
924
150k
    if (val==0) continue;
925
91.5k
    switch (i) {
926
16.0k
    case 2:
927
16.0k
      para.m_margins[1]=double(val)/20.;
928
16.0k
      f << "marg[left]=" << double(val)/20. << ",";
929
16.0k
      break;
930
11.8k
    case 3:
931
11.8k
      para.m_margins[2]=double(val)/20.;
932
11.8k
      f << "marg[right]=" << double(val)/20. << ",";
933
11.8k
      break;
934
14.9k
    case 4:
935
14.9k
      para.m_margins[0]=double(val)/20.;
936
14.9k
      f << "para[indent]=" << double(val)/20. << ",";
937
14.9k
      break;
938
13.7k
    case 5:
939
13.7k
      extraLeading=double(val)/20;
940
13.7k
      f << "height[leading]=" << extraLeading << ",";
941
13.7k
      break;
942
35.0k
    default:
943
35.0k
      f << "f" << i << "=" << val << ",";
944
35.0k
      break;
945
91.5k
    }
946
91.5k
  }
947
21.4k
  val=static_cast<int>(input->readLong(1));
948
21.4k
  switch (val) {
949
1.50k
  case 1: // normal
950
1.50k
    break;
951
363
  case 2:
952
363
    para.setInterline(2, librevenge::RVNG_PERCENT);
953
363
    f << "interline=200%,";
954
363
    break;
955
413
  case 3:
956
413
    para.setInterline(1.5, librevenge::RVNG_PERCENT);
957
413
    f << "interline=150%,";
958
413
    break;
959
4
  case 4:
960
4
    f << "interline=fixed,";
961
4
    break;
962
477
  case 5:
963
477
    para.m_spacings[1]=extraLeading/72.;
964
477
    f << "interline=extra[leading],";
965
477
    break;
966
18.7k
  default:
967
18.7k
    f << "#interline=" << val << ",";
968
18.7k
    break;
969
21.4k
  }
970
21.4k
  val=static_cast<int>(input->readLong(1)); // 1|2
971
21.4k
  if (val!=1) f << "f8=" << val << ",";
972
21.4k
  int lastPos=0;
973
21.4k
  f << "pos=[";
974
49.2k
  for (int i=0; i<numPos; ++i) {
975
49.1k
    auto newPos=static_cast<int>(input->readULong(4));
976
49.1k
    auto ft=static_cast<int>(input->readULong(2));
977
49.1k
    if ((i==0 && newPos!=0) || (i && (newPos<lastPos || newPos>textSize)) || (ft>numFonts)) {
978
21.2k
      MWAW_DEBUG_MSG(("WingzGraph::readTextZone: the position zone seems bad\n"));
979
21.2k
      f << "##";
980
21.2k
      ascFile.addPos(pos);
981
21.2k
      ascFile.addNote(f.str().c_str());
982
21.2k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
983
21.2k
      return false;
984
21.2k
    }
985
27.8k
    if (ft<numFonts)
986
25.5k
      graphic->m_posToFontId[newPos]=size_t(ft);
987
27.8k
    f << std::hex << newPos << std::dec << ":" << ft << ",";
988
27.8k
  }
989
173
  f << "],";
990
991
173
  ascFile.addPos(pos);
992
173
  ascFile.addNote(f.str().c_str());
993
173
  return true;
994
21.4k
}
995
996
////////////////////////////////////////////////////////////
997
// color/pattern
998
////////////////////////////////////////////////////////////
999
bool WingzGraph::readPattern(MWAWGraphicStyle::Pattern &pattern, int &patId)
1000
511k
{
1001
511k
  auto input = m_parserState->m_input;
1002
511k
  long pos = input->tell();
1003
511k
  if (!input->checkPosition(pos+7)) {
1004
0
    MWAW_DEBUG_MSG(("WingzGraph::readPattern: the zone seems to short\n"));
1005
0
    return false;
1006
0
  }
1007
511k
  MWAWColor colors[2];
1008
511k
  unsigned char col[3];
1009
1.53M
  for (auto &c : col) c=static_cast<unsigned char>(input->readULong(1));
1010
511k
  colors[0]=MWAWColor(col[0],col[1],col[2]);
1011
511k
  patId=int(input->readULong(1));
1012
1.53M
  for (auto &c : col) c=static_cast<unsigned char>(input->readULong(1));
1013
511k
  colors[1]=MWAWColor(col[0],col[1],col[2]);
1014
511k
  if (m_state->m_patternList.empty())
1015
1.57k
    m_state->initPatterns(version());
1016
511k
  if (patId>=0 && patId<int(m_state->m_patternList.size()))
1017
359k
    pattern=m_state->m_patternList[size_t(patId)];
1018
151k
  else
1019
151k
    pattern=m_state->m_patternList[0];
1020
1.53M
  for (int i=0; i<2; ++i)
1021
1.02M
    pattern.m_colors[i]=colors[1-i];
1022
511k
  return true;
1023
511k
}
1024
1025
bool WingzGraph::readColor(MWAWColor &color, int &patId)
1026
398k
{
1027
398k
  MWAWGraphicStyle::Pattern pat;
1028
398k
  if (!readPattern(pat, patId))
1029
0
    return false;
1030
398k
  pat.getAverageColor(color);
1031
398k
  return true;
1032
398k
}
1033
1034
////////////////////////////////////////////////////////////
1035
// chart
1036
////////////////////////////////////////////////////////////
1037
bool WingzGraph::readChartData(std::shared_ptr<WingzGraphInternal::Graphic>)
1038
2.87k
{
1039
2.87k
  auto input = m_parserState->m_input;
1040
2.87k
  auto &ascFile = m_parserState->m_asciiFile;
1041
2.87k
  long pos = input->tell(), debPos=pos;
1042
2.87k
  libmwaw::DebugStream f;
1043
2.87k
  f << "Entries(Chart):";
1044
2.87k
  auto val=static_cast<int>(input->readLong(2));
1045
2.87k
  f << "f0=" << val << ",";
1046
2.87k
  val=static_cast<int>(input->readLong(2));
1047
2.87k
  f << "f1=" << val << ",";
1048
2.87k
  ascFile.addPos(pos);
1049
2.87k
  ascFile.addNote(f.str().c_str());
1050
2.87k
  if (val>0)
1051
1.22k
    return true;
1052
1.65k
  if (!input->checkPosition(pos+866)) {
1053
45
    MWAW_DEBUG_MSG(("WingzGraph::readChartData: the zone seems to short\n"));
1054
45
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1055
45
    return false;
1056
45
  }
1057
1.60k
  MWAWColor color;
1058
1.60k
  int patId;
1059
1.60k
  bool ok=true;
1060
11.2k
  for (int i=0; i<6; ++i) {
1061
9.65k
    pos=input->tell();
1062
9.65k
    f.str("");
1063
9.65k
    char const *wh[]= {"title", "footnote", "background", "plotArea", "serie,label", "interior"};
1064
9.65k
    f << "Chart[" << wh[i] << "]:";
1065
9.65k
    if (!readColor(color, patId)) {
1066
0
      ok=false;
1067
0
      break;
1068
0
    }
1069
9.65k
    if (patId && !color.isWhite())
1070
4.28k
      f << "surf[col]=" << color << ",";
1071
5.36k
    else if (!patId)
1072
3.51k
      f << "surf[col]=none,";
1073
9.65k
    if (i==5) {
1074
1.60k
      val=int(input->readLong(1));
1075
1.60k
      if (val!=1) f << "f0=" << val << ",";
1076
1.60k
    }
1077
8.04k
    else {
1078
8.04k
      val=int(input->readLong(1)); // shadow type 4: none, 5: 2d, 6: 3d
1079
8.04k
      if (val!=4) f << "shadow[type]=" << val << ",";
1080
8.04k
      if (!readColor(color, patId)) {
1081
0
        ok=false;
1082
0
        break;
1083
0
      }
1084
8.04k
      if (patId && !color.isBlack())
1085
3.82k
        f << "shadow[col]=" << color << ",";
1086
4.22k
      else if (!patId)
1087
2.18k
        f << "shadow[col]=none,";
1088
8.04k
      val=int(input->readULong(1)); // related to shadow
1089
8.04k
      if (val!=0xff) f << "f1=" << std::hex << val << std::dec << ",";
1090
8.04k
    }
1091
9.65k
    if (!readColor(color, patId)) {
1092
0
      ok=false;
1093
0
      break;
1094
0
    }
1095
9.65k
    if (patId && !color.isBlack())
1096
6.19k
      f << "line[col]=" << color << ",";
1097
3.46k
    else if (!patId)
1098
2.51k
      f << "line[col]=none,";
1099
9.65k
    val=int(input->readLong(1));
1100
9.65k
    if (val!=1) f << "h0=" << val << ",";
1101
9.65k
    val=int(input->readULong(1));
1102
9.65k
    if (val!=5) f << "line[w]=" << float(val)/20.f << ",";
1103
9.65k
    val=int(input->readLong(1));
1104
9.65k
    if (val) f << "h1=" << val << ",";
1105
9.65k
    if (i!=5) {
1106
8.04k
      int dim[2];
1107
16.0k
      for (auto &d : dim) d=int(input->readULong(2));
1108
8.04k
      if (dim[0]!=20 || dim[1]!=20) f << "shadow[pos]=" << 0.05f * MWAWVec2f(float(dim[0]), float(dim[1])) << ",";
1109
8.04k
    }
1110
9.65k
    if (i<2) {
1111
3.21k
      int cell[4];
1112
12.8k
      for (auto &d : cell) d=int(input->readLong(2));
1113
3.21k
      if (cell[1]>=0)
1114
2.15k
        f << MWAWBox2i(MWAWVec2i(cell[0],cell[1]),MWAWVec2i(cell[2],cell[3])) << ",";
1115
3.21k
      ascFile.addDelimiter(input->tell(),'|');
1116
3.21k
      input->seek(pos+42, librevenge::RVNG_SEEK_SET);
1117
3.21k
    }
1118
9.65k
    ascFile.addPos(pos);
1119
9.65k
    ascFile.addNote(f.str().c_str());
1120
9.65k
  }
1121
1.60k
  if (!ok) {
1122
0
    input->seek(debPos, librevenge::RVNG_SEEK_SET);
1123
0
    return false;
1124
0
  }
1125
1.60k
  pos=input->tell();
1126
1.60k
  f.str("");
1127
1.60k
  f << "Chart-A5:";
1128
12.8k
  for (int j=0; j<7; ++j) { // 0 and 1 : the table's data
1129
11.2k
    int cell[4];
1130
45.0k
    for (auto &d : cell) d=int(input->readLong(2));
1131
11.2k
    if (cell[1]>=0)
1132
5.46k
      f << "ce" << j << "=" << MWAWBox2i(MWAWVec2i(cell[0],cell[1]),MWAWVec2i(cell[2],cell[3])) << ",";
1133
11.2k
  }
1134
11.2k
  for (int j=0; j<6; ++j) { // f0=0|1,f3=1|2|b|e|13:type?,f5=1-4,b-c|10|1b|23|40|47
1135
9.65k
    val=int(input->readLong(2));
1136
9.65k
    int const expected[]= {0,0xf0,0,0,0,0};
1137
9.65k
    if (j==3)
1138
      /* 0: bar, 1: line, 2:layer, 3:step, 4: bar/line
1139
         5: bar 3d, 6: line 3d, 7: layer 3d, 8: step 3d, 9: bar/line 3d
1140
         10:pie, 11: pie 3d, 12:High-Low, 14: XY, 16: scatter,
1141
         17: polar, 18:  wireframe, 19: contour, 20: surface
1142
       */
1143
1.60k
      f << "type=" << val << ",";
1144
8.04k
    else if (val!=expected[j])
1145
7.36k
      f << "f" << j << "=" << val << ",";
1146
9.65k
  }
1147
1.60k
  ascFile.addDelimiter(input->tell(),'|');
1148
1.60k
  ascFile.addPos(pos);
1149
1.60k
  ascFile.addNote(f.str().c_str());
1150
1.60k
  pos+=70;
1151
1152
1.60k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
1153
1.60k
  f.str("");
1154
1.60k
  f << "Chart-header:";
1155
1.60k
  auto numSeries=static_cast<int>(input->readULong(2));
1156
1.60k
  f << "numSerie=" << numSeries << ",";
1157
1.60k
  long endPos=debPos+866+73*numSeries;
1158
1.60k
  if (!input->checkPosition(endPos)) {
1159
1.48k
    MWAW_DEBUG_MSG(("WingzGraph::readChartData: the zone seems to short\n"));
1160
1.48k
    ok=input->checkPosition(debPos+866);
1161
1.48k
    if (ok) {
1162
1.48k
      input->seek(debPos+866, librevenge::RVNG_SEEK_SET);
1163
1.48k
      ok=m_mainParser->findNextZone(0xe);
1164
1.48k
    }
1165
1.48k
    if (!ok) {
1166
22
      MWAW_DEBUG_MSG(("WingzGraph::readChartData: can not find the next zone\n"));
1167
22
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1168
22
      return false;
1169
22
    }
1170
1.45k
    numSeries=0;
1171
1.45k
    endPos=input->tell();
1172
1.45k
    input->seek(pos+2, librevenge::RVNG_SEEK_SET);
1173
1.45k
  }
1174
6.34k
  for (int i=0; i<3; ++i) { // f1: some id, f2&0xff: subtype
1175
4.76k
    val=int(input->readULong(2));
1176
4.76k
    if (val)
1177
4.30k
      f << "f" << i << "=" << std::hex << val << std::dec << ",";
1178
4.76k
  }
1179
1.58k
  readColor(color, patId);
1180
1.58k
  if (patId && !color.isWhite())
1181
833
    f << "surf[col]=" << color << ",";
1182
754
  else if (!patId)
1183
286
    f << "surf[col]=none,";
1184
1.58k
  val=int(input->readLong(1)); // shadow type 4: none, 5: 2d, 6: 3d
1185
1.58k
  if (val!=4) f << "shadow[type]=" << val << ",";
1186
1.58k
  readColor(color, patId);
1187
1.58k
  if (patId && !color.isBlack())
1188
1.27k
    f << "shadow[col]=" << color << ",";
1189
314
  else if (!patId)
1190
193
    f << "shadow[col]=none,";
1191
1.58k
  val=int(input->readULong(1)); // related to shadow
1192
1.58k
  if (val!=0xff)
1193
1.09k
    f << "f4=" << std::hex << val << std::dec << ",";
1194
1.58k
  readColor(color, patId);
1195
1.58k
  if (patId && !color.isBlack())
1196
1.43k
    f << "line[col]=" << color << ",";
1197
152
  else if (!patId)
1198
52
    f << "line[col]=none,";
1199
1.58k
  val=int(input->readLong(1));
1200
1.58k
  if (val!=1) f << "g0=" << val << ",";
1201
1.58k
  val=int(input->readULong(1));
1202
1.58k
  if (val!=5) f << "line[w]=" << float(val)/20.f << ",";
1203
1.58k
  val=int(input->readLong(1));
1204
1.58k
  if (val) f << "g1=" << val << ",";
1205
1.58k
  int dim[2];
1206
3.17k
  for (auto &d : dim) d=int(input->readULong(2));
1207
1.58k
  if (dim[0]!=20 || dim[1]!=20) f << "shadow[pos]=" << 0.05f * MWAWVec2f(float(dim[0]), float(dim[1])) << ",";
1208
1.58k
  ascFile.addDelimiter(input->tell(),'|');
1209
1.58k
  input->seek(18, librevenge::RVNG_SEEK_CUR);
1210
1.58k
  ascFile.addDelimiter(input->tell(),'|');
1211
1.58k
  val=int(input->readLong(1));
1212
1.58k
  if (val!=1)
1213
1.57k
    f << "g2=" << val << ",";
1214
1.58k
  val=int(input->readLong(1));
1215
1.58k
  if (val!=1)
1216
1.46k
    f << "g3=" << val << ",";
1217
19.0k
  for (int i=0; i<11; ++i) {
1218
17.4k
    val=int(input->readLong(1));
1219
17.4k
    if (val)
1220
10.5k
      f << "h" << i << "=" << val << ",";
1221
17.4k
  }
1222
1.58k
  ascFile.addPos(pos);
1223
1.58k
  ascFile.addNote(f.str().c_str());
1224
1225
1.58k
  pos+=80;
1226
1.58k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
1227
7.93k
  for (int i=0; i<4; ++i) {
1228
6.34k
    pos=input->tell();
1229
6.34k
    f.str("");
1230
6.34k
    char const *wh[]= {"axisX", "axisZ", "axisY", "B3"};
1231
6.34k
    f << "Chart[" << wh[i] << "]:";
1232
6.34k
    val=int(input->readULong(2));
1233
6.34k
    if (val!=0x4024) f << "fl=" << std::hex << val << std::dec << ",";
1234
6.34k
    if (!readColor(color, patId)) {
1235
0
      ok=false;
1236
0
      break;
1237
0
    }
1238
6.34k
    if (patId && !color.isWhite())
1239
3.54k
      f << "surf[col]=" << color << ",";
1240
2.80k
    else if (!patId)
1241
2.02k
      f << "surf[col]=none,";
1242
6.34k
    val=int(input->readLong(1)); // shadow type 4: none, 5: 2d, 6: 3d
1243
6.34k
    if (val!=4) f << "shadow[type]=" << val << ",";
1244
6.34k
    if (!readColor(color, patId)) {
1245
0
      ok=false;
1246
0
      break;
1247
0
    }
1248
6.34k
    if (patId && !color.isBlack())
1249
3.95k
      f << "shadow[col]=" << color << ",";
1250
2.39k
    else if (!patId)
1251
1.96k
      f << "shadow[col]=none,";
1252
6.34k
    val=int(input->readULong(1)); // related to shadow
1253
6.34k
    if (val!=0xff) f << "f1=" << std::hex << val << std::dec << ",";
1254
6.34k
    if (!readColor(color, patId)) {
1255
0
      ok=false;
1256
0
      break;
1257
0
    }
1258
6.34k
    if (patId && !color.isBlack())
1259
3.92k
      f << "line[col]=" << color << ",";
1260
2.42k
    else if (!patId)
1261
1.89k
      f << "line[col]=none,";
1262
6.34k
    val=int(input->readLong(1));
1263
6.34k
    if (val!=1) f << "h0=" << val << ",";
1264
6.34k
    val=int(input->readULong(1));
1265
6.34k
    if (val!=5) f << "line[w]=" << float(val)/20.f << ",";
1266
6.34k
    val=int(input->readLong(1));
1267
6.34k
    if (val) f << "h1=" << val << ",";
1268
12.6k
    for (auto &d : dim) d=int(input->readULong(2));
1269
6.34k
    if (dim[0]!=20 || dim[1]!=20) f << "shadow[pos]=" << 0.05f * MWAWVec2f(float(dim[0]), float(dim[1])) << ",";
1270
6.34k
    int cell[4];
1271
25.3k
    for (auto &d : cell) d=int(input->readLong(2));
1272
6.34k
    if (cell[1]>=0)
1273
4.54k
      f << MWAWBox2i(MWAWVec2i(cell[0],cell[1]),MWAWVec2i(cell[2],cell[3])) << ",";
1274
19.0k
    for (int j=0; j<2; ++j) { // h2=1 for axisY
1275
12.6k
      int const expected[]= {0,2};
1276
12.6k
      val=int(input->readLong(2));
1277
12.6k
      if (val!=expected[j]) f << "h" << j+2 << "=" << val << ",";
1278
12.6k
    }
1279
19.0k
    for (int k=0; k<2; ++k) { // k=0, real axis line color
1280
12.6k
      std::string what(k==0 ? "line2" : "unkn");
1281
12.6k
      if (!readColor(color, patId)) {
1282
0
        ok=false;
1283
0
        break;
1284
0
      }
1285
12.6k
      if (patId && !color.isBlack())
1286
7.38k
        f << what << "[col]=" << color << ",";
1287
5.31k
      else if (!patId)
1288
3.81k
        f << what << "[col]=none,";
1289
12.6k
      val=int(input->readLong(1));
1290
12.6k
      if (val!=1) f << what << "[f0]=" << val << ",";
1291
12.6k
      val=int(input->readULong(1));
1292
12.6k
      if (val!=5) f << what << "[w]=" << float(val)/20.f << ",";
1293
12.6k
      val=int(input->readLong(1));
1294
12.6k
      if (val) f << what << "[f1]=" << val << ",";
1295
12.6k
    }
1296
6.34k
    if (!readColor(color, patId)) {
1297
0
      ok=false;
1298
0
      break;
1299
0
    }
1300
6.34k
    if (patId)
1301
4.49k
      f << "unkn2[col]=" << color << ",";
1302
6.34k
    val=int(input->readLong(1));
1303
6.34k
    if (val!=1) f << "l0=" << val << ",";
1304
6.34k
    ascFile.addDelimiter(input->tell(),'|');
1305
6.34k
    ascFile.addPos(pos);
1306
6.34k
    ascFile.addNote(f.str().c_str());
1307
1308
6.34k
    input->seek(pos+113, librevenge::RVNG_SEEK_SET);
1309
6.34k
  }
1310
1.58k
  if (!ok) {
1311
0
    input->seek(debPos, librevenge::RVNG_SEEK_SET);
1312
0
    return false;
1313
0
  }
1314
1.58k
  pos=input->tell();
1315
1.58k
  f.str("");
1316
1.58k
  f << "Chart-B5:";
1317
9.52k
  for (int i=0; i<5; ++i) {
1318
7.93k
    int const expected[]= {0x1e, 0x1e, 0x32, 0x32, 0x109};
1319
7.93k
    val=int(input->readLong(2));
1320
7.93k
    if (val==expected[i]) continue;
1321
7.55k
    char const *wh[] = {"f0", "f1", "x[vanish,3d]", "y[vanish,3d]", "distance[3d]"};
1322
7.55k
    f << wh[i] << "=" << val << ",";
1323
7.55k
  }
1324
7.93k
  for (int i=0; i<4; ++i) {
1325
6.34k
    if (!readColor(color, patId)) {
1326
0
      ok=false;
1327
0
      break;
1328
0
    }
1329
6.34k
    char const *wh[] = {"top", "side", "shadow", "line"};
1330
6.34k
    if (patId && ((i<2 && !color.isWhite()) || (i>=2 && !color.isBlack())))
1331
3.28k
      f << wh[i] << "[3d,col]=" << color << ",";
1332
3.06k
    else if (!patId)
1333
2.09k
      f << wh[i] << "[3d,col]=none,";
1334
6.34k
    val=int(input->readULong(1));
1335
6.34k
    if (i<2) {
1336
3.17k
      if (val!=4)
1337
2.97k
        f << "f" << i+2 << "=" << val << ",";
1338
3.17k
    }
1339
3.17k
    else if (i==2) {
1340
1.58k
      if (val!=0x4b) // val something like ~2*tint in percent
1341
1.58k
        f << "shadow[tint]=" << val << ",";
1342
1.58k
    }
1343
1.58k
    else if (val!=1)
1344
1.43k
      f << "f" << i+2 << "=" << val << ",";
1345
6.34k
  }
1346
1.58k
  val=int(input->readULong(1));
1347
1.58k
  if (val!=5) f << "line[w,3d]=" << float(val)/20.f << ",";
1348
1.58k
  if (!ok) {
1349
0
    input->seek(debPos, librevenge::RVNG_SEEK_SET);
1350
0
    return false;
1351
0
  }
1352
1.58k
  ascFile.addDelimiter(input->tell(),'|');
1353
1.58k
  ascFile.addPos(pos);
1354
1.58k
  ascFile.addNote(f.str().c_str());
1355
1.58k
  pos+=68;
1356
1.58k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
1357
1358
15.1k
  for (int i=0; i<numSeries; ++i) {
1359
13.5k
    pos=input->tell();
1360
13.5k
    f.str("");
1361
13.5k
    f << "Chart-Serie" << i << ":";
1362
1363
13.5k
    input->seek(pos+70, librevenge::RVNG_SEEK_SET);
1364
13.5k
    val=int(input->readLong(1));
1365
13.5k
    if (val!=2) {
1366
10.6k
      if (val) {
1367
6.29k
        f << "###type=" << val << ",";
1368
6.29k
        MWAW_DEBUG_MSG(("WingzGraph::readChartData: find unexpected serie type\n"));
1369
6.29k
      }
1370
10.6k
      f << "_,";
1371
10.6k
      ascFile.addPos(pos);
1372
10.6k
      ascFile.addNote(f.str().c_str());
1373
10.6k
      input->seek(pos+73, librevenge::RVNG_SEEK_SET);
1374
10.6k
      continue;
1375
10.6k
    }
1376
1377
2.91k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1378
2.91k
    if (!readColor(color, patId))
1379
0
      break;
1380
2.91k
    if (patId && !color.isWhite())
1381
2.83k
      f << "surf[col]=" << color << ",";
1382
85
    else if (!patId)
1383
77
      f << "surf[col]=none,";
1384
2.91k
    val=int(input->readLong(1));
1385
2.91k
    if (val!=1) f << "f0=" << val << ",";
1386
1387
2.91k
    if (!readColor(color, patId))
1388
0
      break;
1389
2.91k
    if (patId)
1390
2.62k
      f << "shadow[col]=" << color << ",";
1391
1392
2.91k
    val=int(input->readLong(1));
1393
2.91k
    if (val) f << "f1=" << val << ",";
1394
2.91k
    if (!readColor(color, patId))
1395
0
      break;
1396
2.91k
    if (patId && !color.isBlack())
1397
2.74k
      f << "line[col]=" << color << ",";
1398
176
    else if (!patId)
1399
82
      f << "line[col]=none,";
1400
2.91k
    val=int(input->readLong(1));
1401
2.91k
    if (val!=1) f << "f2=" << val << ",";
1402
2.91k
    val=int(input->readLong(2));
1403
2.91k
    if (val!=40) f << "f3=" << val << ",";
1404
2.91k
    if (!readColor(color, patId))
1405
0
      break;
1406
2.91k
    if (patId && !color.isBlack())
1407
2.60k
      f << "unkn[col]=" << color << ",";
1408
313
    else if (!patId)
1409
67
      f << "unkn[col]=none,";
1410
2.91k
    val=int(input->readLong(1));
1411
2.91k
    if (val!=1) f << "g0=" << val << ",";
1412
2.91k
    val=int(input->readULong(1));
1413
2.91k
    if (val!=5) f << "line[w]=" << float(val)/20.f << ",";
1414
2.91k
    val=int(input->readLong(1));
1415
2.91k
    if (val) f << "g1=" << val << ",";
1416
11.6k
    for (int j=0; j<3; ++j) { // 0: data, 1: label?
1417
8.75k
      int cell[4];
1418
35.0k
      for (auto &c : cell) c=int(input->readLong(2));
1419
8.75k
      if (cell[1]>=0)
1420
8.24k
        f << "cells" << j << "=" << MWAWBox2i(MWAWVec2i(cell[0],cell[1]),MWAWVec2i(cell[2],cell[3])) << ",";
1421
8.75k
    }
1422
17.5k
    for (int j=0; j<5; ++j) { // h1=serie[id] ?
1423
14.5k
      val=int(input->readLong(2));
1424
14.5k
      if (val)
1425
13.4k
        f << "h" << j << "=" << val << ",";
1426
14.5k
    }
1427
2.91k
    ascFile.addDelimiter(input->tell(),'|');
1428
2.91k
    ascFile.addPos(pos);
1429
2.91k
    ascFile.addNote(f.str().c_str());
1430
2.91k
    input->seek(pos+73, librevenge::RVNG_SEEK_SET);
1431
2.91k
  }
1432
1.58k
  if (input->tell()!=endPos) {
1433
1.45k
    MWAW_DEBUG_MSG(("WingzGraph::readChartData: find some extra data\n"));
1434
1.45k
    ascFile.addPos(input->tell());
1435
1.45k
    ascFile.addNote("Chart-end:###");
1436
1.45k
  }
1437
1.58k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1438
1.58k
  return true;
1439
1.58k
}
1440
1441
////////////////////////////////////////////////////////////
1442
// send data
1443
////////////////////////////////////////////////////////////
1444
bool WingzGraph::sendGraphic(WingzGraphInternal::Graphic const &graphic, MWAWPosition const &pos)
1445
125k
{
1446
125k
  MWAWListenerPtr listener=m_parserState->getMainListener();
1447
125k
  if (!listener) {
1448
0
    MWAW_DEBUG_MSG(("WingzGraph::sendGraphic: listener is not set\n"));
1449
0
    return false;
1450
0
  }
1451
125k
  MWAWPosition fPos;
1452
125k
  if (!m_state->m_inGroupDepth) {
1453
71.1k
    MWAWVec2f begPos=m_mainParser->getPosition(graphic.m_position[0], graphic.m_relativePosition[0]);
1454
71.1k
    MWAWVec2f endPos=m_mainParser->getPosition(graphic.m_position[1], graphic.m_relativePosition[1]);
1455
71.1k
    fPos=MWAWPosition(begPos, endPos-begPos, librevenge::RVNG_POINT);
1456
71.1k
  }
1457
54.2k
  else { // special case relative to the group box
1458
54.2k
    auto const &orig=pos.origin();
1459
54.2k
    auto const &size=pos.size();
1460
54.2k
    MWAWVec2f begPos(orig[0]+size[0]*float(graphic.m_position[0][0])/float(0x3fff),
1461
54.2k
                     orig[1]+size[1]*float(graphic.m_position[0][1])/float(0x3fff));
1462
54.2k
    MWAWVec2f endPos(orig[0]+size[0]*float(graphic.m_position[1][0])/float(0x3fff),
1463
54.2k
                     orig[1]+size[1]*float(graphic.m_position[1][1])/float(0x3fff));
1464
54.2k
    fPos=MWAWPosition(begPos, endPos-begPos, librevenge::RVNG_POINT);
1465
54.2k
  }
1466
125k
  fPos.m_anchorTo=MWAWPosition::Page;
1467
125k
  fPos.setOrder(graphic.m_order);
1468
125k
  switch (graphic.m_type) {
1469
51.9k
  case 0:
1470
60.5k
  case 2: {
1471
60.5k
    std::shared_ptr<MWAWSubDocument> doc(new WingzGraphInternal::SubDocument(*this, m_parserState->m_input, graphic));
1472
60.5k
    listener->insertTextBox(fPos, doc, graphic.m_style);
1473
60.5k
    return true;
1474
51.9k
  }
1475
658
  case 5:
1476
3.88k
  case 6:
1477
4.59k
  case 7:
1478
5.18k
  case 8:
1479
14.6k
  case 9:
1480
14.6k
    return sendShape(graphic, fPos);
1481
24.3k
  case 0xa:
1482
24.3k
    return sendPicture(graphic, fPos);
1483
25.8k
  case 0xb: // group
1484
25.8k
    listener->openGroup(pos);
1485
25.8k
    ++m_state->m_inGroupDepth;
1486
54.2k
    for (auto const &c : graphic.m_children) {
1487
54.2k
      if (c) sendGraphic(*c, fPos);
1488
54.2k
    }
1489
25.8k
    --m_state->m_inGroupDepth;
1490
25.8k
    listener->closeGroup();
1491
25.8k
    return true;
1492
0
  default:
1493
0
    break;
1494
125k
  }
1495
0
  static bool first=true;
1496
0
  if (first) {
1497
0
    MWAW_DEBUG_MSG(("WingzGraph::sendGraphic: oops, unsure how to send some graphic[%d]\n", graphic.m_type));
1498
0
    first=false;
1499
0
  }
1500
0
  return false;
1501
125k
}
1502
1503
bool WingzGraph::sendPicture(WingzGraphInternal::Graphic const &graphic, MWAWPosition const &pos)
1504
24.3k
{
1505
24.3k
  MWAWListenerPtr listener=m_parserState->getMainListener();
1506
24.3k
  if (!listener) {
1507
0
    MWAW_DEBUG_MSG(("WingzGraph::sendPicture: listener is not set\n"));
1508
0
    return false;
1509
0
  }
1510
24.3k
  if (!graphic.m_entry[0].valid()) {
1511
0
    MWAW_DEBUG_MSG(("WingzGraph::sendPicture: can not find the picture\n"));
1512
0
    return false;
1513
0
  }
1514
24.3k
  auto input = m_parserState->m_input;
1515
24.3k
  long actPos=input->tell();
1516
24.3k
  librevenge::RVNGBinaryData file;
1517
24.3k
  input->seek(graphic.m_entry[0].begin(), librevenge::RVNG_SEEK_SET);
1518
24.3k
  input->readDataBlock(graphic.m_entry[0].length(), file);
1519
24.3k
  MWAWEmbeddedObject object(file);
1520
24.3k
  listener->insertPicture(pos, object);
1521
24.3k
  input->seek(actPos, librevenge::RVNG_SEEK_SET);
1522
24.3k
  return true;
1523
24.3k
}
1524
1525
bool WingzGraph::sendShape(WingzGraphInternal::Graphic const &graphic, MWAWPosition const &pos)
1526
14.6k
{
1527
14.6k
  MWAWListenerPtr listener=m_parserState->getMainListener();
1528
14.6k
  if (!listener) {
1529
0
    MWAW_DEBUG_MSG(("WingzGraph::sendShape: listener is not set\n"));
1530
0
    return false;
1531
0
  }
1532
14.6k
  auto const &orig=pos.origin();
1533
14.6k
  auto end=orig+pos.size();
1534
14.6k
  MWAWGraphicShape shape;
1535
14.6k
  switch (graphic.m_type) {
1536
658
  case 5:
1537
658
    switch (graphic.m_flag&3) {
1538
77
    case 1:
1539
77
      shape=MWAWGraphicShape::line(MWAWVec2f(end[0],orig[1]),MWAWVec2f(orig[0],end[1]));
1540
77
      break;
1541
65
    case 2:
1542
65
      shape=MWAWGraphicShape::line(MWAWVec2f(orig[0],end[1]),MWAWVec2f(end[0],orig[1]));
1543
65
      break;
1544
194
    case 3:
1545
194
      shape=MWAWGraphicShape::line(end,orig);
1546
194
      break;
1547
322
    case 0:
1548
322
    default:
1549
322
      shape=MWAWGraphicShape::line(orig,end);
1550
322
      break;
1551
658
    }
1552
658
    break;
1553
3.22k
  case 6: {
1554
3.22k
    float angle[2] = { graphic.m_angles[0], graphic.m_angles[1] };
1555
3.22k
    if (angle[0] > angle[1]) std::swap(angle[0],angle[1]);
1556
20.0k
    while (angle[1] > 360) {
1557
16.8k
      angle[0]-=360;
1558
16.8k
      angle[1]-=360;
1559
16.8k
    }
1560
13.7k
    while (angle[0] < -360) {
1561
10.5k
      angle[0]+=360;
1562
10.5k
      angle[1]+=360;
1563
10.5k
    }
1564
1565
3.22k
    MWAWBox2f box(orig,end);
1566
    // we must compute the real bd box
1567
3.22k
    float minVal[2] = { 0, 0 }, maxVal[2] = { 0, 0 };
1568
3.22k
    int limitAngle[2];
1569
9.66k
    for (int i = 0; i < 2; i++)
1570
6.44k
      limitAngle[i] = (angle[i] < 0) ? int(angle[i]/90)-1 : int(angle[i]/90);
1571
59.8k
    for (int bord = limitAngle[0]; bord <= limitAngle[1]+1; bord++) {
1572
56.6k
      float ang = (bord == limitAngle[0]) ? float(angle[0]) :
1573
56.6k
                  (bord == limitAngle[1]+1) ? float(angle[1]) : float(90 * bord);
1574
56.6k
      ang *= float(M_PI/180.);
1575
56.6k
      float const actVal[2] = { std::cos(ang), -std::sin(ang)};
1576
56.6k
      if (actVal[0] < minVal[0]) minVal[0] = actVal[0];
1577
52.0k
      else if (actVal[0] > maxVal[0]) maxVal[0] = actVal[0];
1578
56.6k
      if (actVal[1] < minVal[1]) minVal[1] = actVal[1];
1579
53.0k
      else if (actVal[1] > maxVal[1]) maxVal[1] = actVal[1];
1580
56.6k
    }
1581
3.22k
    MWAWBox2f circleBox(orig,end);
1582
    // we have the shape box, we need to reconstruct the circle box
1583
3.22k
    if (maxVal[0]>minVal[0] && maxVal[1]>minVal[1]) {
1584
2.92k
      float const scaling[2]= { (box[1][0]-box[0][0])/(maxVal[0]-minVal[0]),
1585
2.92k
                                (box[1][1]-box[0][1])/(maxVal[1]-minVal[1])
1586
2.92k
                              };
1587
2.92k
      float const constant[2]= { box[0][0]-minVal[0] *scaling[0], box[0][1]-minVal[1] *scaling[1]};
1588
2.92k
      circleBox=MWAWBox2f(MWAWVec2f(constant[0]-scaling[0], constant[1]-scaling[1]),
1589
2.92k
                          MWAWVec2f(constant[0]+scaling[0], constant[1]+scaling[1]));
1590
2.92k
    }
1591
3.22k
    if (graphic.m_style.hasSurface())
1592
48
      shape = MWAWGraphicShape::pie(box, circleBox, MWAWVec2f(float(angle[0]),float(angle[1])));
1593
3.17k
    else
1594
3.17k
      shape = MWAWGraphicShape::arc(box, circleBox, MWAWVec2f(float(angle[0]),float(angle[1])));
1595
3.22k
    break;
1596
658
  }
1597
717
  case 7:
1598
717
    shape=MWAWGraphicShape::circle(MWAWBox2f(orig,end));
1599
717
    break;
1600
590
  case 8:
1601
590
    if (graphic.m_flag&0x20)
1602
543
      shape=MWAWGraphicShape::rectangle(MWAWBox2f(orig,end), 0.2f*pos.size());
1603
47
    else
1604
47
      shape=MWAWGraphicShape::rectangle(MWAWBox2f(orig,end));
1605
590
    break;
1606
9.46k
  case 9: {
1607
9.46k
    if (graphic.m_vertices.empty()) {
1608
2.15k
      MWAW_DEBUG_MSG(("WingzGraph::sendPageGraphics: oops, can not find any vertices\n"));
1609
2.15k
      return false;
1610
2.15k
    }
1611
7.31k
    auto size=pos.size();
1612
7.31k
    if (graphic.m_flag&2) { // smooth
1613
2.85k
      shape.m_bdBox=MWAWBox2f(orig,end);
1614
2.85k
      shape.m_type=MWAWGraphicShape::Path;
1615
2.85k
      shape.m_path.push_back(MWAWGraphicShape::PathData('M', MWAWVec2f(orig[0]+graphic.m_vertices[0][0]*size[0],orig[1]+graphic.m_vertices[0][1]*size[1])));
1616
20.2k
      for (size_t i=1; i+1<graphic.m_vertices.size(); ++i) {
1617
17.4k
        MWAWVec2f pt=MWAWVec2f(orig[0]+graphic.m_vertices[i][0]*size[0],
1618
17.4k
                               orig[1]+graphic.m_vertices[i][1]*size[1]);
1619
17.4k
        MWAWVec2f dir=graphic.m_vertices[i+1]-graphic.m_vertices[i-1];
1620
17.4k
        shape.m_path.push_back(MWAWGraphicShape::PathData('S', pt, pt-0.1f*MWAWVec2f(dir[0]*size[0],dir[1]*size[1])));
1621
17.4k
      }
1622
2.85k
      if (graphic.m_vertices.size()>1)
1623
2.35k
        shape.m_path.push_back(MWAWGraphicShape::PathData('L', MWAWVec2f(orig[0]+graphic.m_vertices.back()[0]*size[0],orig[1]+graphic.m_vertices.back()[1]*size[1])));
1624
2.85k
      if (graphic.m_flag&1)
1625
538
        shape.m_path.push_back(MWAWGraphicShape::PathData('Z'));
1626
2.85k
      break;
1627
2.85k
    }
1628
4.45k
    if (graphic.m_flag&1)
1629
263
      shape=MWAWGraphicShape::polygon(MWAWBox2f(orig,end));
1630
4.19k
    else
1631
4.19k
      shape=MWAWGraphicShape::polyline(MWAWBox2f(orig,end));
1632
4.45k
    for (auto const &pt : graphic.m_vertices)
1633
17.2k
      shape.m_vertices.push_back(MWAWVec2f(orig[0]+pt[0]*size[0],orig[1]+pt[1]*size[1]));
1634
4.45k
    break;
1635
7.31k
  }
1636
0
  default:
1637
0
    shape=MWAWGraphicShape::rectangle(MWAWBox2f(orig,end));
1638
0
    break;
1639
14.6k
  }
1640
12.4k
  listener->insertShape(pos, shape, graphic.m_style);
1641
12.4k
  return true;
1642
14.6k
}
1643
1644
bool WingzGraph::sendText(WingzGraphInternal::Graphic const &graphic)
1645
60.5k
{
1646
60.5k
  MWAWListenerPtr listener=m_parserState->getMainListener();
1647
60.5k
  if (!listener) {
1648
0
    MWAW_DEBUG_MSG(("WingzGraph::sendText: listener is not set\n"));
1649
0
    return false;
1650
0
  }
1651
60.5k
  auto input=m_parserState->m_input;
1652
1653
60.5k
  bool first=true;
1654
181k
  for (int i=0; i<2; ++i) {
1655
121k
    if (!graphic.m_entry[i].valid()) continue;
1656
65.1k
    if (!first) listener->insertEOL();
1657
65.1k
    listener->setFont(graphic.m_font[graphic.m_textType==1 ? 0 : 1]);
1658
65.1k
    input->seek(graphic.m_entry[i].begin(), librevenge::RVNG_SEEK_SET);
1659
1.50M
    for (long l=graphic.m_entry[i].length(); l>0; --l) {
1660
1.44M
      auto c=static_cast<unsigned char>(input->readULong(1));
1661
1.44M
      if (c==0x9)
1662
11.3k
        listener->insertTab();
1663
1.42M
      else if (c==0xd)
1664
42.6k
        listener->insertEOL();
1665
1.38M
      else
1666
1.38M
        listener->insertCharacter(c);
1667
1.44M
    }
1668
65.1k
    first=false;
1669
65.1k
  }
1670
1671
60.5k
  if (!graphic.m_textEntry.valid())
1672
36.6k
    return true;
1673
23.9k
  if (!first) listener->insertEOL();
1674
23.9k
  listener->setParagraph(graphic.m_paragraph);
1675
23.9k
  input->seek(graphic.m_textEntry.begin(), librevenge::RVNG_SEEK_SET);
1676
2.18M
  for (long l=0; l<graphic.m_textEntry.length(); ++l) {
1677
2.16M
    if (graphic.m_posToFontId.find(int(l))!=graphic.m_posToFontId.end()) {
1678
11.0k
      auto fId=graphic.m_posToFontId.find(int(l))->second;
1679
11.0k
      if (fId<graphic.m_fontList.size())
1680
11.0k
        listener->setFont(graphic.m_fontList[fId]);
1681
11.0k
    }
1682
2.16M
    auto c=static_cast<unsigned char>(input->readULong(1));
1683
2.16M
    if (c==0x9)
1684
26.5k
      listener->insertTab();
1685
2.13M
    else if (c==0xd)
1686
43.3k
      listener->insertEOL();
1687
2.09M
    else
1688
2.09M
      listener->insertCharacter(c);
1689
2.16M
  }
1690
23.9k
  return true;
1691
60.5k
}
1692
1693
bool WingzGraph::sendPageGraphics()
1694
2.61k
{
1695
2.61k
  if (!m_state->m_groupStack.empty()) {
1696
401
    MWAW_DEBUG_MSG(("WingzGraph::sendPageGraphics: oops, some groups are not closed\n"));
1697
401
  }
1698
2.61k
  MWAWListenerPtr listener=m_parserState->getMainListener();
1699
2.61k
  if (!listener) {
1700
0
    MWAW_DEBUG_MSG(("WingzGraph::sendPageGraphics: listener is not set\n"));
1701
0
    return false;
1702
0
  }
1703
2.61k
  MWAWPosition pos(MWAWVec2f(0,0), MWAWVec2f(0,0), librevenge::RVNG_POINT);
1704
2.61k
  pos.m_anchorTo=MWAWPosition::Page;
1705
1706
71.1k
  for (auto const &graph : m_state->m_pictureList) {
1707
71.1k
    if (graph) sendGraphic(*graph, pos);
1708
71.1k
  }
1709
2.61k
  return true;
1710
2.61k
}
1711
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: