Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/ReadySetGoGraph.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 <array>
35
#include <cmath>
36
#include <iomanip>
37
#include <iostream>
38
#include <limits>
39
#include <map>
40
#include <set>
41
#include <sstream>
42
43
#include <librevenge/librevenge.h>
44
45
#include "MWAWFont.hxx"
46
#include "MWAWFontConverter.hxx"
47
#include "MWAWGraphicListener.hxx"
48
#include "MWAWGraphicShape.hxx"
49
#include "MWAWParagraph.hxx"
50
#include "MWAWPictData.hxx"
51
#include "MWAWPosition.hxx"
52
#include "MWAWSubDocument.hxx"
53
54
#include "ReadySetGoParser.hxx"
55
#include "ReadySetGoStyleManager.hxx"
56
57
#include "ReadySetGoGraph.hxx"
58
59
/** Internal: the structures of a ReadySetGoGraph */
60
namespace ReadySetGoGraphInternal
61
{
62
////////////////////////////////////////
63
//! Internal: a shape in a ReadySetGoGraph document
64
struct Shape {
65
  //! the shape type
66
  enum Type { T_Empty, T_Line, T_Oval, T_Picture, T_Polygon, T_Rectangle, T_RectOval, T_Text, T_Unknown };
67
  //! constructor
68
  explicit Shape(Type type)
69
653
    : m_type(type)
70
653
    , m_box()
71
653
    , m_rotate(0)
72
653
    , m_style(MWAWGraphicStyle::emptyStyle())
73
653
    , m_groupId(0)
74
653
    , m_wrapRoundAround(false)
75
653
    , m_cornerSize(-1, -1)
76
653
    , m_vertices()
77
653
    , m_textId(-1)
78
653
    , m_paragraph()
79
653
    , m_hasPicture(false)
80
653
  {
81
1.30k
    for (auto &link : m_linkIds) link=-1;
82
1.30k
    for (auto &cPos : m_textPositions) cPos=-1;
83
653
  }
84
85
  //! the shape type
86
  Type m_type;
87
  //! the bounding box
88
  MWAWBox2f m_box;
89
  //! the shape rotation: v6
90
  int m_rotate;
91
  //! the graphic style
92
  MWAWGraphicStyle m_style;
93
  //! the group id: v6
94
  int m_groupId; // FIXME: useme
95
  //! the round around wraping flag
96
  bool m_wrapRoundAround;
97
  //! the line points
98
  MWAWVec2f m_points[2];
99
  //! the corner size: rectangle oval
100
  MWAWVec2i m_cornerSize;
101
  //! the list of vertices : polygon
102
  std::vector<MWAWVec2f> m_vertices;
103
104
  //! the text limits: v4
105
  int m_textPositions[2];
106
  //! the text link id
107
  int m_textId;
108
  //! the text links: prev/next
109
  int m_linkIds[2];
110
  //! the paragraph style
111
  MWAWParagraph m_paragraph;
112
113
  //! a flag to know if a picture is empty or not
114
  bool m_hasPicture;
115
116
  //! the zone entries: picture or text zones
117
  MWAWEntry m_entries[3];
118
};
119
120
////////////////////////////////////////
121
//! Internal: a layout in a ReadySetGoGraph document
122
struct Layout {
123
  //! constructor
124
  Layout()
125
136
    : m_useMasterPage(true)
126
136
    , m_masterId(0)
127
136
    , m_shapes()
128
136
  {
129
136
  }
130
131
  //! a flag to know if we use or not the master page
132
  bool m_useMasterPage;
133
  //! the master id: v6
134
  int m_masterId;
135
  //! a map id to shape
136
  std::vector<Shape> m_shapes;
137
};
138
139
////////////////////////////////////////
140
//! Internal: the state of a ReadySetGoGraph
141
struct State {
142
  //! constructor
143
  State()
144
19.0k
    : m_version(-1)
145
19.0k
    , m_layouts()
146
19.0k
    , m_masterLayouts()
147
19.0k
  {
148
19.0k
  }
149
150
  //! the file version
151
  int m_version;
152
  //! the list of layout (one by potential master + page)
153
  std::vector<Layout> m_layouts;
154
  //! the list of master layouts: v6
155
  std::vector<Layout> m_masterLayouts;
156
};
157
158
////////////////////////////////////////
159
//! Internal: the subdocument of a ReadySetGoGraph
160
class SubDocument final : public MWAWSubDocument
161
{
162
public:
163
  SubDocument(ReadySetGoGraph &pars, MWAWInputStreamPtr const &input, Shape const &shape)
164
10
    : MWAWSubDocument(&pars.m_parser, input, MWAWEntry())
165
10
    , m_graphParser(&pars)
166
10
    , m_shape(&shape)
167
10
  {
168
10
  }
169
170
  //! destructor
171
0
  ~SubDocument() final {}
172
173
  //! operator!=
174
  bool operator!=(MWAWSubDocument const &doc) const final
175
0
  {
176
0
    if (MWAWSubDocument::operator!=(doc)) return true;
177
0
    auto const *sDoc = dynamic_cast<SubDocument const *>(&doc);
178
0
    if (!sDoc) return true;
179
0
    if (m_graphParser != sDoc->m_graphParser) return true;
180
0
    if (m_shape != sDoc->m_shape) return true;
181
0
    return false;
182
0
  }
183
184
  //! the parser function
185
  void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final;
186
187
protected:
188
  /** the graph parser */
189
  ReadySetGoGraph *m_graphParser;
190
  //! the text shape
191
  Shape const *m_shape;
192
private:
193
  SubDocument(SubDocument const &orig) = delete;
194
  SubDocument &operator=(SubDocument const &orig) = delete;
195
};
196
197
void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/)
198
10
{
199
10
  if (!listener || !listener->canWriteText()) {
200
0
    MWAW_DEBUG_MSG(("ReadySetGoParserInternal::SubDocument::parse: no listener\n"));
201
0
    return;
202
0
  }
203
10
  if (!m_graphParser || !m_shape) {
204
0
    MWAW_DEBUG_MSG(("ReadySetGoParserInternal::SubDocument::parse: no parser\n"));
205
0
    return;
206
0
  }
207
10
  long pos = m_input->tell();
208
10
  m_graphParser->sendText(*m_shape);
209
10
  m_input->seek(pos, librevenge::RVNG_SEEK_SET);
210
10
}
211
212
}
213
214
////////////////////////////////////////////////////////////
215
// constructor/destructor, ...
216
////////////////////////////////////////////////////////////
217
ReadySetGoGraph::ReadySetGoGraph(ReadySetGoParser &parser)
218
19.0k
  : m_state(new ReadySetGoGraphInternal::State)
219
19.0k
  , m_parser(parser)
220
19.0k
  , m_styleManager(parser.m_styleManager)
221
19.0k
{
222
19.0k
}
223
224
ReadySetGoGraph::~ReadySetGoGraph()
225
19.0k
{
226
19.0k
}
227
228
int ReadySetGoGraph::version() const
229
379
{
230
379
  if (m_state->m_version==-1)
231
135
    m_state->m_version=m_parser.version();
232
379
  return m_state->m_version;
233
379
}
234
235
void ReadySetGoGraph::updatePageSpanList(std::vector<MWAWPageSpan> &spanList) const
236
78
{
237
  // create the page list
238
78
  int const vers=version();
239
78
  int num=int(m_state->m_layouts.size());
240
78
  if (vers>=3)
241
0
    num=std::max<int>(0,num-2);
242
78
  if (vers<3) {
243
78
    MWAWPageSpan ps(m_parser.getPageSpan());
244
78
    ps.setPageSpan(std::max<int>(1,num));
245
78
    spanList.push_back(ps);
246
78
  }
247
0
  else {
248
0
    bool const sharedList=vers<6 || (vers==6 && m_parser.isDesignStudioFile());
249
0
    std::vector<std::array<bool, 2> > hasMasters;
250
0
    size_t numMasters=!sharedList ? (m_state->m_masterLayouts.size()+1)/2 : 1;
251
0
    hasMasters.resize(numMasters);
252
0
    for (auto &hasMaster : hasMasters) hasMaster= {{false, false}};
253
0
    if (sharedList) {
254
0
      for (size_t i=0; i<2; ++i) {
255
0
        if (i>=m_state->m_layouts.size()) break;
256
0
        hasMasters[0][i]=!m_state->m_layouts[i].m_shapes.empty();
257
0
      }
258
0
    }
259
0
    else {
260
0
      for (size_t i=0; i<m_state->m_masterLayouts.size(); ++i)
261
0
        hasMasters[i/2][i%2] =!m_state->m_masterLayouts[i].m_shapes.empty();
262
0
    }
263
0
    for (size_t i=(sharedList ? 2 : 0); i<m_state->m_layouts.size(); ++i) {
264
0
      auto const &layout=m_state->m_layouts[i];
265
0
      MWAWPageSpan ps(m_parser.getPageSpan());
266
0
      ps.setPageSpan(1);
267
0
      int whichMaster= !sharedList ? layout.m_masterId : 0;
268
0
      if (layout.m_useMasterPage && whichMaster>=0 && whichMaster<int(hasMasters.size()) && hasMasters[size_t(whichMaster)][(i+1)%2]) {
269
0
        librevenge::RVNGString name;
270
0
        name.sprintf("MasterPage%d", 2*whichMaster+int((i+1)%2));
271
0
        ps.setMasterPageName(name);
272
0
      }
273
0
      spanList.push_back(ps);
274
0
    }
275
0
  }
276
78
}
277
278
bool ReadySetGoGraph::updateTextBoxLinks()
279
0
{
280
0
  int const vers=version();
281
0
  if (vers<=2)
282
0
    return true;
283
0
  std::map<int, ReadySetGoGraphInternal::Shape *> idToShapeMap;
284
0
  std::map<int, int> idToLinkIdsMap[2];
285
0
  for (int st=0; st<2; ++st) {
286
0
    auto &layouts = st==0 ?  m_state->m_layouts : m_state->m_masterLayouts;
287
0
    for (auto &layout : layouts) {
288
0
      for (auto &shape : layout.m_shapes) {
289
0
        if (shape.m_linkIds[0]<0 && shape.m_linkIds[1]<0)
290
0
          continue;
291
0
        if (idToShapeMap.find(shape.m_textId)!=idToShapeMap.end()) {
292
0
          MWAW_DEBUG_MSG(("ReadySetGoGraph::updateTextBoxLinks: find dupplicated text id=%d\n", shape.m_textId));
293
0
          return false;
294
0
        }
295
0
        idToShapeMap[shape.m_textId]=&shape;
296
0
        for (int i=0; i<2; ++i) {
297
0
          if (shape.m_linkIds[i]<0) continue;
298
0
          if (idToLinkIdsMap[i].find(shape.m_linkIds[i])!=idToLinkIdsMap[i].end()) {
299
0
            MWAW_DEBUG_MSG(("ReadySetGoGraph::updateTextBoxLinks[%d]: find dupplicated text id=%d\n", i, shape.m_linkIds[i]));
300
0
            return false;
301
0
          }
302
0
          idToLinkIdsMap[i][shape.m_linkIds[i]]=shape.m_textId;
303
0
        }
304
0
      }
305
0
    }
306
0
  }
307
308
  // check that the link are coherent, ie. for each link, there exists a reciprocal link
309
0
  for (auto st=0; st<2; ++st) {
310
0
    std::set<int> badIds;
311
0
    for (auto const &it : idToLinkIdsMap[st]) {
312
0
      auto rIt=idToLinkIdsMap[1-st].find(it.second);
313
0
      if (rIt==idToLinkIdsMap[1-st].end() || rIt->second!=it.first) {
314
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::updateTextBoxLinks: find no reciprocal link for link=%d-%d\n", it.first, it.second));
315
0
        badIds.insert(it.first);
316
0
      }
317
0
    }
318
0
    for (auto bad : badIds)
319
0
      idToLinkIdsMap[st].erase(bad);
320
0
  }
321
322
  // check that there is no loop: following next path
323
0
  for (auto const &iIt : idToShapeMap) {
324
0
    std::set<int> ids;
325
0
    int id=iIt.first, firstId=id;
326
0
    bool ok=true;
327
0
    while (true) {
328
0
      if (ids.find(id)!=ids.end()) {
329
0
        ok=false;
330
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::updateTextBoxLinks: find a loop for link id=%d\n", id));
331
0
        break;
332
0
      }
333
0
      ids.insert(id);
334
0
      auto const &nextIt=idToLinkIdsMap[1].find(id);
335
0
      if (nextIt==idToLinkIdsMap[1].end())
336
0
        break;
337
0
      id=nextIt->second;
338
0
    }
339
0
    if (ok) continue;
340
    // ok: remove this loop
341
0
    id=firstId;
342
0
    while (true) {
343
0
      auto const &nextIt=idToLinkIdsMap[1].find(id);
344
0
      if (nextIt==idToLinkIdsMap[1].end())
345
0
        break;
346
0
      int nextId=nextIt->second;
347
0
      idToLinkIdsMap[1].erase(id);
348
0
      idToLinkIdsMap[0].erase(nextId);
349
0
      id=nextId;
350
0
    }
351
0
  }
352
353
0
  if (vers<4) {
354
    // update the shape's style name
355
0
    for (auto const &iIt : idToShapeMap) {
356
0
      auto &shape=*iIt.second;
357
0
      int prevId=shape.m_linkIds[0];
358
0
      if (prevId>=0 && idToLinkIdsMap[0].find(prevId)!=idToLinkIdsMap[0].end()) {
359
0
        std::stringstream s;
360
0
        s << "Frame" << iIt.first;
361
0
        shape.m_style.m_frameName=s.str();
362
0
      }
363
0
      int nextId=shape.m_linkIds[1];
364
0
      if (nextId>=0 && idToLinkIdsMap[1].find(nextId)!=idToLinkIdsMap[1].end()) {
365
0
        std::stringstream s;
366
0
        s << "Frame" << nextId;
367
0
        shape.m_style.m_frameNextName=s.str();
368
0
      }
369
0
    }
370
0
  }
371
0
  else {
372
0
    for (auto const &iIt : idToShapeMap) {
373
0
      auto &shape=*iIt.second;
374
0
      if (shape.m_linkIds[0]>=0 || shape.m_linkIds[1]<0) continue;
375
      // shape is the first node of a loop
376
0
      int nextId=shape.m_linkIds[1];
377
0
      auto *currentShape=&shape;
378
0
      while (nextId>=0) {
379
0
        if (idToLinkIdsMap[1].find(nextId)==idToLinkIdsMap[1].end()) // the link has been cutted
380
0
          break;
381
0
        auto nextShapeIt=idToShapeMap.find(nextId);
382
0
        if (nextShapeIt==idToShapeMap.end()) {
383
0
          MWAW_DEBUG_MSG(("ReadySetGoGraph::updateTextBoxLinks: can not find shape corresponding to id=%d\n", nextId));
384
0
          break;
385
0
        }
386
0
        auto *nextShape=nextShapeIt->second;
387
0
        for (int l=0; l<3; ++l) // update the shape entries
388
0
          nextShape->m_entries[l]=shape.m_entries[l];
389
0
        nextId=nextShape->m_linkIds[1];
390
0
        if (currentShape->m_textPositions[1]>=nextShape->m_textPositions[0]-1)
391
0
          currentShape->m_textPositions[1]=std::max(0,nextShape->m_textPositions[0]-1);
392
0
        else if (currentShape->m_textPositions[1]<nextShape->m_textPositions[0]-10) { // a difference of 2 characters seems ok
393
0
          MWAW_DEBUG_MSG(("ReadySetGoGraph::updateTextBoxLinks: can not update the text limits\n"));
394
0
        }
395
0
        currentShape=nextShape;
396
0
      }
397
0
    }
398
0
  }
399
0
  return true;
400
0
}
401
402
////////////////////////////////////////////////////////////
403
//
404
// Intermediate level
405
//
406
////////////////////////////////////////////////////////////
407
bool ReadySetGoGraph::readLayoutsList(int numLayouts, bool master)
408
0
{
409
0
  int const vers=version();
410
0
  if (vers<3) {
411
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readLayoutsList: unexpected version\n"));
412
0
    return false;
413
0
  }
414
0
  MWAWInputStreamPtr input = m_parser.getInput();
415
0
  if (!input)
416
0
    return false;
417
0
  long pos=input->tell();
418
0
  if (!input->checkPosition(pos+4)) {
419
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readLayoutsList: can not read the zone length\n"));
420
0
    return false;
421
0
  }
422
0
  libmwaw::DebugFile &ascFile = m_parser.ascii();
423
0
  libmwaw::DebugStream f;
424
0
  bool const designStudio=m_parser.isDesignStudioFile();
425
0
  f << "Entries(Layout):";
426
0
  long len=long(input->readLong(4));
427
0
  long endPos=pos+4+len;
428
0
  int const dataSize=vers==3 ? 10 : vers==4 ? 14 : vers==5 ? 136 : (designStudio ? 210 : 212);
429
0
  if (len<0 || len/dataSize<numLayouts || endPos<pos+4 || !input->checkPosition(endPos)) {
430
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readLayoutsList: can not read the zone length\n"));
431
0
    f << "###";
432
0
    ascFile.addPos(pos);
433
0
    ascFile.addNote(f.str().c_str());
434
0
    return false;
435
0
  }
436
0
  f << "N=" << numLayouts << ",";
437
0
  ascFile.addPos(pos);
438
0
  ascFile.addNote(f.str().c_str());
439
0
  std::vector<ReadySetGoGraphInternal::Layout> &layouts= master ? m_state->m_masterLayouts : m_state->m_layouts;
440
0
  for (int l=0; l<numLayouts; ++l) { // LR,1:R,2:L,...
441
0
    pos=input->tell();
442
0
    f.str("");
443
0
    f << "Layout-" << (master ? "M" : "L") << l << ":";
444
0
    layouts.push_back(ReadySetGoGraphInternal::Layout());
445
0
    auto &layout=layouts.back();
446
0
    if (vers==3) {
447
0
      for (int i=0; i<2; ++i) { // f0=0 or 8(rare)
448
0
        int val=int(input->readLong(2));
449
0
        if (val)
450
0
          f << "f" << i << "=" << val << ",";
451
0
      }
452
0
    }
453
0
    else {
454
0
      int dim[4];
455
0
      for (auto &d : dim) d=int(input->readLong(2));
456
0
      if (dim[2]!=dim[0] || dim[3]!=dim[1])
457
0
        f << "box?=" << MWAWBox2i(MWAWVec2i(dim[0],dim[1]), MWAWVec2i(dim[2],dim[3])) << ",";
458
0
    }
459
0
    int val=int(input->readULong(4));
460
0
    if (val)
461
0
      f << "ID=" << std::hex << val << std::dec << ","; // last shape id in layout?
462
0
    val=int(input->readULong(2)); // 1|3
463
0
    if ((val&1)==0) {
464
0
      f << "use[master]=false,";
465
0
      layout.m_useMasterPage=false;
466
0
    }
467
0
    val &= 0xfffe;
468
0
    if (val)
469
0
      f << "fl=" << std::hex << val << std::dec << ",";
470
0
    if (vers>=6 && !designStudio) {
471
0
      ascFile.addDelimiter(input->tell(),'|');
472
0
      input->seek(pos+210, librevenge::RVNG_SEEK_SET);
473
0
      ascFile.addDelimiter(input->tell(),'|');
474
0
      layout.m_masterId=int(input->readULong(2));
475
0
      if (layout.m_masterId)
476
0
        f << "master=" << layout.m_masterId << ",";
477
0
    }
478
0
    if (input->tell()!=pos+dataSize)
479
0
      ascFile.addDelimiter(input->tell(),'|');
480
0
    input->seek(pos+dataSize, librevenge::RVNG_SEEK_SET);
481
0
    ascFile.addPos(pos);
482
0
    ascFile.addNote(f.str().c_str());
483
0
  }
484
485
0
  if (input->tell()!=endPos) {
486
0
    if (!master) {
487
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readLayoutsList: find extra data\n"));
488
0
      ascFile.addPos(input->tell());
489
0
      ascFile.addNote("Layout-extra:###");
490
0
    }
491
0
    else {
492
0
      ascFile.addPos(input->tell());
493
0
      ascFile.addNote("_");
494
0
    }
495
0
  }
496
0
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
497
0
  return true;
498
0
}
499
500
bool ReadySetGoGraph::readShapes()
501
135
{
502
135
  MWAWInputStreamPtr input = m_parser.getInput();
503
135
  if (!input)
504
0
    return false;
505
135
  long pos=input->tell();
506
507
135
  int const vers=version();
508
135
  libmwaw::DebugFile &ascFile = m_parser.ascii();
509
135
  libmwaw::DebugStream f;
510
135
  if (vers<=2) {
511
135
    f << "Entries(Pages):";
512
135
    if (!input->checkPosition(pos+2)) {
513
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapes: the zone seems too short\n"));
514
0
      f << "###";
515
0
      ascFile.addPos(pos);
516
0
      ascFile.addNote(f.str().c_str());
517
0
      return false;
518
0
    }
519
135
    int numPages=1;
520
135
    if (vers==2) {
521
61
      numPages=int(input->readULong(2));
522
61
      if (!input->checkPosition(pos+2+2*numPages)) {
523
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapes: the zone seems too short\n"));
524
0
        f << "###N=" << numPages << ",";
525
0
        ascFile.addPos(pos);
526
0
        ascFile.addNote(f.str().c_str());
527
0
        return false;
528
0
      }
529
61
      ascFile.addPos(pos);
530
61
      ascFile.addNote(f.str().c_str());
531
61
    }
532
135
    std::vector<int> numShapesByPage;
533
135
    f << "N=[";
534
271
    for (int i=0; i<numPages; ++i) {
535
136
      numShapesByPage.push_back(int(input->readULong(2)));
536
136
      f << numShapesByPage.back();
537
136
    }
538
135
    f << "],";
539
135
    ascFile.addPos(pos);
540
135
    ascFile.addNote(f.str().c_str());
541
542
214
    for (size_t p=0; p<size_t(numPages); ++p) {
543
136
      m_state->m_layouts.push_back(ReadySetGoGraphInternal::Layout());
544
136
      auto &layout=m_state->m_layouts.back();
545
762
      for (int sh=0; sh<numShapesByPage[p]; ++sh) {
546
683
        pos=input->tell();
547
683
        if (vers==1) {
548
683
          if (readShapeV1() && !layout.m_shapes.empty() &&
549
635
              (layout.m_shapes.back().m_type!=ReadySetGoGraphInternal::Shape::T_Empty || sh+1==numShapesByPage[p]))
550
626
            continue;
551
57
          MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapes: can not read a shape\n"));
552
57
          ascFile.addPos(pos);
553
57
          ascFile.addNote("Entries(BadShape):###");
554
57
          return false;
555
683
        }
556
0
        else if (!readShapeV2(layout))
557
0
          return false;
558
683
      }
559
136
    }
560
78
    return true;
561
135
  }
562
563
  // Design Studio v2
564
0
  if (m_parser.isDesignStudioFile()) {
565
0
    for (auto &layout : m_state->m_layouts) {
566
0
      while (!input->isEnd()) {
567
0
        bool last;
568
0
        if (!readShapeDSV2(layout, last))
569
0
          return false;
570
0
        if (last)
571
0
          break;
572
0
      }
573
0
    }
574
0
    updateTextBoxLinks();
575
0
    return true;
576
0
  }
577
  // v3, v4, v4.5
578
0
  if (vers<=5) {
579
0
    for (auto &layout : m_state->m_layouts) {
580
0
      while (!input->isEnd()) {
581
0
        bool last;
582
0
        if (!readShapeV3(layout, last))
583
0
          return false;
584
0
        if (last)
585
0
          break;
586
0
      }
587
0
    }
588
0
    updateTextBoxLinks();
589
0
    return true;
590
0
  }
591
  // v6
592
  // normally two layouts by master labelled from 'A'-'Z'
593
0
  for (size_t i=0; i<m_state->m_masterLayouts.size(); ++i) {
594
0
    while (!input->isEnd()) {
595
0
      bool last;
596
0
      if (!readShapeV6(m_state->m_masterLayouts[i], last))
597
0
        return false;
598
0
      if (last)
599
0
        break;
600
0
    }
601
0
  }
602
  // followed by num layouts-2,
603
  // I supposed that layouts 0 and 1 remain only to be "coherent" with v4.5 format
604
0
  for (size_t i=2; i<m_state->m_layouts.size(); ++i) {
605
0
    while (!input->isEnd()) {
606
0
      bool last;
607
0
      if (!readShapeV6(m_state->m_layouts[i], last))
608
0
        return false;
609
0
      if (last)
610
0
        break;
611
0
    }
612
0
  }
613
0
  updateTextBoxLinks();
614
0
  return true;
615
0
}
616
617
bool ReadySetGoGraph::readShapesInObject()
618
0
{
619
0
  if (version()<6) {
620
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapesInObject: unexpected version\n"));
621
0
    return false;
622
0
  }
623
0
  MWAWInputStreamPtr input = m_parser.getInput();
624
0
  if (!input)
625
0
    return false;
626
0
  ReadySetGoGraphInternal::Layout dummy;
627
0
  if (m_parser.isDesignStudioFile()) {
628
0
    while (!input->isEnd()) {
629
0
      bool last;
630
0
      if (!readShapeDSV2(dummy, last))
631
0
        return false;
632
0
      if (last)
633
0
        break;
634
0
    }
635
0
  }
636
0
  else {
637
0
    while (!input->isEnd()) {
638
0
      bool last;
639
0
      if (!readShapeV6(dummy, last))
640
0
        return false;
641
0
      if (last)
642
0
        break;
643
0
    }
644
0
  }
645
0
  return true;
646
0
}
647
648
649
////////////////////////////////////////////////////////////
650
// low level
651
////////////////////////////////////////////////////////////
652
bool ReadySetGoGraph::readShapeV1()
653
683
{
654
683
  MWAWInputStreamPtr input = m_parser.getInput();
655
683
  if (!input)
656
0
    return false;
657
683
  long pos=input->tell();
658
683
  if (!input->checkPosition(pos+26)) {
659
6
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV1: can not read a shape\n"));
660
6
    return false;
661
6
  }
662
677
  if (m_state->m_layouts.empty()) {
663
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV1: oops, must create a new layout\n"));
664
0
    m_state->m_layouts.resize(1);
665
0
  }
666
677
  int type=int(input->readULong(2));
667
668
677
  static char const* const wh[]= {"EndZone", "Text", nullptr, "Frame", "Solid", "Picture"};
669
677
  if (type<0 || type==2 || type>5) {
670
22
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV1: unknown type\n"));
671
22
    return false;
672
22
  }
673
655
  libmwaw::DebugFile &ascFile = m_parser.ascii();
674
655
  libmwaw::DebugStream f;
675
655
  if (wh[type])
676
655
    f << "Entries(" << wh[type] << "):";
677
0
  else
678
0
    f << "Entries(Zone" << type << "):";
679
655
  int const expectedSize[]= {26, 74, 0, 30, 28, 28};
680
655
  if (expectedSize[type]<=0 || !input->checkPosition(pos+expectedSize[type])) {
681
2
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV1: the zone seems too short for a shape\n"));
682
2
    f << "###";
683
2
    ascFile.addPos(pos);
684
2
    ascFile.addNote(f.str().c_str());
685
2
    return false;
686
2
  }
687
653
  static ReadySetGoGraphInternal::Shape::Type const shapeTypes[]= {
688
653
    ReadySetGoGraphInternal::Shape::T_Empty,
689
653
    ReadySetGoGraphInternal::Shape::T_Text,
690
653
    ReadySetGoGraphInternal::Shape::T_Unknown,
691
653
    ReadySetGoGraphInternal::Shape::T_Rectangle, // frame
692
653
    ReadySetGoGraphInternal::Shape::T_Rectangle, // solid
693
653
    ReadySetGoGraphInternal::Shape::T_Picture
694
653
  };
695
653
  ReadySetGoGraphInternal::Shape shape(shapeTypes[type]);
696
653
  float dim[4];
697
2.61k
  for (auto &d : dim) d=float(input->readLong(2));
698
653
  shape.m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]), MWAWVec2f(dim[0]+dim[2],dim[1]+dim[3]));
699
653
  f << "box=" << shape.m_box << ",";
700
653
  if (type!=0) {
701
2.52k
    for (auto &d : dim) {
702
2.52k
      d=float(input->readLong(2));
703
2.52k
      d+=float(input->readLong(2))/10000;
704
2.52k
    }
705
630
    f << "box[inch]=" << MWAWBox2f(MWAWVec2f(dim[0],dim[1]), MWAWVec2f(dim[0]+dim[2],dim[1]+dim[3])) << ",";
706
630
    int val;
707
630
    if (type==3) {
708
32
      val=int(input->readLong(2));
709
32
      if (val<0 || val>100) {
710
6
        MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV1: the frame size seems bad\n"));
711
6
        f << "###";
712
6
      }
713
26
      else
714
26
        shape.m_style.m_lineWidth=float(val);
715
32
      if (val!=1)
716
32
        f << "frame[size]=" << val << ",";
717
32
    }
718
630
    if (type==5) {
719
304
      val=int(input->readLong(2));
720
304
      shape.m_hasPicture=val!=0;
721
304
      if (val==0)
722
3
        f <<"noPict,";
723
301
      else if (val!=1)
724
301
        f << "###pict=" << val << ",";
725
304
    }
726
326
    else if (type!=1) {
727
293
      val=int(input->readLong(2));
728
293
      if (val<0 || val>4) {
729
275
        MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV1: the color id seems bad\n"));
730
275
        f << "###col=" << val << ",";
731
275
      }
732
18
      else {
733
18
        uint8_t grey=uint8_t(val==0 ? 255 : 32*val);
734
18
        if (type==3)
735
11
          shape.m_style.m_lineColor=MWAWColor(grey,grey,grey);
736
7
        else
737
7
          shape.m_style.setSurfaceColor(MWAWColor(grey,grey,grey));
738
18
        f << "color="  << val << ","; // 0: none, 1: black, 2: grey1, .., 4: light grey
739
18
      }
740
293
    }
741
33
    else {
742
33
      shape.m_paragraph.m_marginsUnit=librevenge::RVNG_INCH;
743
99
      for (int i=0; i<2; ++i) { // 0
744
66
        val=int(input->readLong(2));
745
66
        shape.m_paragraph.m_margins[1-i]=float(val)+float(input->readULong(2))/10000;
746
66
        if (*shape.m_paragraph.m_margins[1-i]>0) f << (i==0 ? "para" : "left") << "[indent]=" << *shape.m_paragraph.m_margins[1-i] << ",";
747
66
      }
748
33
      shape.m_paragraph.m_margins[0]=*shape.m_paragraph.m_margins[0]-*shape.m_paragraph.m_margins[1];
749
33
      std::string extra;
750
33
      m_styleManager->readTabulationsV1(*shape.m_paragraph.m_tabs, extra);
751
33
      f << extra;
752
33
    }
753
630
  }
754
653
  if (input->tell()!=pos+expectedSize[type]) {
755
23
    ascFile.addDelimiter(input->tell(),'|');
756
23
    input->seek(pos+expectedSize[type], librevenge::RVNG_SEEK_SET);
757
23
  }
758
653
  ascFile.addPos(pos);
759
653
  ascFile.addNote(f.str().c_str());
760
653
  if (type!=1 && (type!=5 || !shape.m_hasPicture)) {
761
319
    m_state->m_layouts[0].m_shapes.push_back(shape);
762
319
    return true;
763
319
  }
764
  // before size zone0+zone1
765
381
  for (int st=0; st<2; ++st) { // zone1=[text, style], zone2=[para]
766
360
    pos=input->tell();
767
360
    f.str("");
768
360
    if (type==1)
769
59
      f << "Text-" << (st==0 ? "char" : "para") << ":";
770
301
    else
771
301
      f << "Picture:";
772
360
    int len=int(input->readULong(2));
773
360
    if (!input->checkPosition(pos+2+len)) {
774
18
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV1: the zone seems too short for a text sub zone\n"));
775
18
      f << "###";
776
18
      ascFile.addPos(pos);
777
18
      ascFile.addNote(f.str().c_str());
778
18
      return false;
779
18
    }
780
342
    shape.m_entries[st].setBegin(pos+2);
781
342
    shape.m_entries[st].setLength(len);
782
342
    ascFile.addPos(pos);
783
342
    ascFile.addNote(f.str().c_str());
784
342
    input->seek(pos+2+len+(len%2), librevenge::RVNG_SEEK_SET);
785
342
    if (type==5)
786
295
      break;
787
342
  }
788
789
316
  m_state->m_layouts[0].m_shapes.push_back(shape);
790
316
  return true;
791
334
}
792
793
bool ReadySetGoGraph::readShapeV2(ReadySetGoGraphInternal::Layout &layout)
794
0
{
795
0
  MWAWInputStreamPtr input = m_parser.getInput();
796
0
  if (!input)
797
0
    return false;
798
799
0
  long pos=input->tell();
800
0
  if (!input->checkPosition(pos+8)) {
801
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: can not read a shape\n"));
802
0
    return false;
803
0
  }
804
0
  int type=int(input->readULong(2));
805
0
  int id=int(input->readULong(2));
806
0
  libmwaw::DebugFile &ascFile = m_parser.ascii();
807
0
  libmwaw::DebugStream f;
808
0
  if (type<0 || type>6) {
809
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: find bad type=%d\n", type));
810
0
    f << "Entries(Zone" << type << ")[S" << id << "]:###";
811
0
    ascFile.addPos(pos);
812
0
    ascFile.addNote(f.str().c_str());
813
0
    return false;
814
0
  }
815
0
  char const *wh[]= { nullptr, "Solid", "Frame", "Picture", "Text", nullptr, nullptr };
816
0
  std::string what;
817
0
  if (wh[type])
818
0
    what=wh[type];
819
0
  else {
820
0
    std::stringstream s;
821
0
    s << "Zone" << type;
822
0
    what=s.str();
823
0
  }
824
0
  f << "Entries(" << what << ")[S" << id << "]:";
825
0
  static ReadySetGoGraphInternal::Shape::Type const shapeTypes[]= {
826
0
    ReadySetGoGraphInternal::Shape::T_Unknown,
827
0
    ReadySetGoGraphInternal::Shape::T_Rectangle, // solid
828
0
    ReadySetGoGraphInternal::Shape::T_Rectangle, // frame
829
0
    ReadySetGoGraphInternal::Shape::T_Picture,
830
0
    ReadySetGoGraphInternal::Shape::T_Text,
831
0
    ReadySetGoGraphInternal::Shape::T_Unknown,
832
0
    ReadySetGoGraphInternal::Shape::T_Unknown
833
0
  };
834
0
  ReadySetGoGraphInternal::Shape shape(shapeTypes[type]);
835
0
  int len=int(input->readULong(2));
836
0
  if (len<0x1c || !input->checkPosition(pos+6+len)) {
837
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: find unexpected size for generic data block\n"));
838
0
    f << "###";
839
0
    ascFile.addPos(pos);
840
0
    ascFile.addNote(f.str().c_str());
841
0
    return false;
842
0
  }
843
0
  int val=int(input->readLong(2));
844
0
  if (val!=type) f << "##type2=" << val << ",";
845
0
  for (int i=0; i<2; ++i) {
846
0
    val=int(input->readLong(2));
847
0
    if (val!=id) f << "id" << i+1 << "=" << val << ",";
848
0
  }
849
0
  val=int(input->readLong(2));
850
0
  if (val!=1) f << "f0=" << val << ",";
851
0
  float dim[4];
852
0
  for (auto &d : dim) {
853
0
    d=72*float(input->readLong(2));
854
0
    d+=72*float(input->readLong(2))/10000;
855
0
  }
856
0
  shape.m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]), MWAWVec2f(dim[0]+dim[2],dim[1]+dim[3]));
857
0
  f << "box=" << shape.m_box << ",";
858
0
  f << "ID=" << std::hex << input->readULong(4) << std::dec << ",";
859
0
  if (input->tell()!=pos+6+len) {
860
0
    ascFile.addDelimiter(input->tell(),'|');
861
0
    input->seek(pos+6+len, librevenge::RVNG_SEEK_SET);
862
0
  }
863
0
  ascFile.addPos(pos);
864
0
  ascFile.addNote(f.str().c_str());
865
866
0
  pos=input->tell();
867
0
  f.str("");
868
0
  f << what << "-data:S" << id << ",";
869
0
  len=int(input->readULong(2));
870
0
  long endPos=pos+2+len;
871
0
  if (len<0 || !input->checkPosition(endPos)) {
872
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: find unexpected size for shape data block\n"));
873
0
    f << "###";
874
0
    ascFile.addPos(pos);
875
0
    ascFile.addNote(f.str().c_str());
876
0
    return false;
877
0
  }
878
0
  switch (type) {
879
0
  case 1: // solid
880
0
  case 2: { // frame
881
0
    if (len!=2+2*type) {
882
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2[%d]: find unexpected size for shape data block\n", type));
883
0
      f << "###";
884
0
      break;
885
0
    }
886
0
    val=int(input->readLong(2));
887
0
    if (val<0 || val>4) {
888
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: the color id seems bad\n"));
889
0
      f << "###col=" << val << ",";
890
0
    }
891
0
    else {
892
0
      uint8_t grey=uint8_t(val==0 ? 255 : 32*val);
893
0
      if (type==2)
894
0
        shape.m_style.m_lineColor=MWAWColor(grey,grey,grey);
895
0
      else
896
0
        shape.m_style.setSurfaceColor(MWAWColor(grey,grey,grey));
897
0
      f << "color="  << val << ","; // 0: none, 1: black, 2: grey1, .., 4: light grey
898
0
    }
899
0
    if (type==2) {
900
0
      val=int(input->readLong(2));
901
0
      if (val<0 || val>100) {
902
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: the frame size seems bad\n"));
903
0
        f << "###";
904
0
      }
905
0
      else
906
0
        shape.m_style.m_lineWidth=float(val);
907
0
      if (val!=1)
908
0
        f << "frame[size]=" << val << ",";
909
0
    }
910
0
    int subType=int(input->readLong(2));
911
0
    switch (subType) {
912
0
    case 1: // rectangle
913
0
      break;
914
0
    case 2:
915
0
      shape.m_type=ReadySetGoGraphInternal::Shape::T_RectOval;
916
0
      f << "rectOval,";
917
0
      break;
918
0
    case 3:
919
0
      shape.m_type=ReadySetGoGraphInternal::Shape::T_Oval;
920
0
      f << "oval,";
921
0
      break;
922
0
    default:
923
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: unknown rectangle type\n"));
924
0
      f << "###type=" << subType << ",";
925
0
      break;
926
0
    }
927
0
    break;
928
0
  }
929
0
  case 3: {
930
0
    if (len!=16) {
931
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2[pict]: find unexpected size for shape data block\n"));
932
0
      f << "###";
933
0
      break;
934
0
    }
935
0
    for (int i=0; i<2; ++i) {
936
0
      val=int(input->readULong(2));
937
0
      if (val!=100)
938
0
        f << "scale" << (i==0 ? "X" : "Y") << "=" << val << "%,";
939
0
    }
940
0
    int iDim[2]; // some multiples of 6, link to decal?
941
0
    for (auto &d : iDim) d=int(input->readLong(2));
942
0
    if (iDim[0] || iDim[1])
943
0
      f << "crop=" << MWAWVec2i(iDim[1],iDim[0]) << ","; // checkme
944
0
    val=int(input->readULong(4));
945
0
    if (val) {
946
0
      shape.m_hasPicture=true;
947
0
      f << "ID=" << std::hex << val << std::dec << ",";
948
0
    }
949
0
    for (int i=0; i<2; ++i) { // 0
950
0
      val=int(input->readULong(2));
951
0
      if (val) f << "f" << i << "=" << val << ",";
952
0
    }
953
0
    break;
954
0
  }
955
0
  case 4: {
956
0
    if (len!=0x9a) {
957
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2[text]: find unexpected size for shape data block\n"));
958
0
      f << "###";
959
0
      break;
960
0
    }
961
0
    shape.m_paragraph.m_marginsUnit=librevenge::RVNG_INCH;
962
0
    for (int i=0; i<2; ++i) { // 0
963
0
      val=int(input->readLong(2));
964
0
      shape.m_paragraph.m_margins[1-i]=float(val)+float(input->readULong(2))/10000;
965
0
      if (*shape.m_paragraph.m_margins[1-i]>0) f << (i==0 ? "para" : "left") << "[indent]=" << *shape.m_paragraph.m_margins[i] << ",";
966
0
    }
967
0
    shape.m_paragraph.m_margins[0]=*shape.m_paragraph.m_margins[0]-*shape.m_paragraph.m_margins[1];
968
0
    std::string extra;
969
0
    m_styleManager->readTabulationsV1(*shape.m_paragraph.m_tabs, extra);
970
0
    f << extra;
971
0
    ascFile.addPos(pos);
972
0
    ascFile.addNote(f.str().c_str());
973
974
0
    pos=input->tell();
975
0
    f.str("");
976
0
    f << what << "-data1:";
977
0
    input->seek(pos+66, librevenge::RVNG_SEEK_SET);
978
0
    ascFile.addPos(pos);
979
0
    ascFile.addNote(f.str().c_str());
980
981
0
    pos=input->tell();
982
0
    f.str("");
983
0
    f << what << "-data2:";
984
    // pos+16: maybe alignement
985
0
    break;
986
0
  }
987
0
  default:
988
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: reading data of type=%d is not implemented\n", type));
989
0
    f << "###";
990
0
    break;
991
0
  }
992
0
  if (input->tell()!=pos && input->tell()!=endPos)
993
0
    ascFile.addDelimiter(input->tell(),'|');
994
0
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
995
0
  ascFile.addPos(pos);
996
0
  ascFile.addNote(f.str().c_str());
997
998
0
  if (type==3 && shape.m_hasPicture) {
999
0
    pos=input->tell();
1000
0
    len=int(input->readULong(2));
1001
0
    f.str("");
1002
0
    f << "Picture:";
1003
0
    if (!input->checkPosition(pos+2+len)) {
1004
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: find unexpected size for picture\n"));
1005
0
      f << "###";
1006
0
      ascFile.addPos(pos);
1007
0
      ascFile.addNote(f.str().c_str());
1008
0
      return false;
1009
0
    }
1010
0
    shape.m_entries[0].setBegin(pos+2);
1011
0
    shape.m_entries[0].setLength(len);
1012
0
    input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
1013
0
    ascFile.addPos(pos);
1014
0
    ascFile.addNote(f.str().c_str());
1015
0
  }
1016
0
  if (type!=4) {
1017
0
    layout.m_shapes.push_back(shape);
1018
0
    return true;
1019
0
  }
1020
0
  for (int st=0; st<2; ++st) { // zone1=[text, style], zone2=[para]
1021
0
    pos=input->tell();
1022
0
    f.str("");
1023
0
    f << "Text-" << (st==0 ? "char" : "para") << ":";
1024
0
    len=int(input->readULong(2));
1025
0
    if (!input->checkPosition(pos+2+len)) {
1026
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV2: find unexpected size for text sub zone=%d\n", st));
1027
0
      f << "###";
1028
0
      ascFile.addPos(pos);
1029
0
      ascFile.addNote(f.str().c_str());
1030
0
      return false;
1031
0
    }
1032
0
    shape.m_entries[st].setBegin(pos+2);
1033
0
    shape.m_entries[st].setLength(len);
1034
0
    input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
1035
0
    ascFile.addPos(pos);
1036
0
    ascFile.addNote(f.str().c_str());
1037
0
  }
1038
0
  layout.m_shapes.push_back(shape);
1039
0
  return true;
1040
0
}
1041
1042
bool ReadySetGoGraph::readShapeV3(ReadySetGoGraphInternal::Layout &layout, bool &last)
1043
0
{
1044
0
  last=false;
1045
0
  MWAWInputStreamPtr input = m_parser.getInput();
1046
0
  if (!input)
1047
0
    return false;
1048
1049
0
  int const vers=version();
1050
0
  long pos=input->tell();
1051
0
  if (!input->checkPosition(pos+2)) {
1052
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3: can not read a shape\n"));
1053
0
    return false;
1054
0
  }
1055
1056
0
  auto &ascFile = m_parser.ascii();
1057
0
  int type=int(input->readLong(2));
1058
0
  if (type==-1) {
1059
0
    ascFile.addPos(pos);
1060
0
    ascFile.addNote("Layout-end:");
1061
0
    last=true;
1062
0
    return true;
1063
0
  }
1064
0
  if (type<0 || type>6) {
1065
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3: the type seems bad\n"));
1066
0
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1067
0
    return false;
1068
0
  }
1069
0
  libmwaw::DebugStream f;
1070
1071
0
  long len=long(input->readLong(4));
1072
0
  int const decal=vers<=3 ? 0 : 4;
1073
0
  if (len<32+decal || (long)((unsigned long)pos+6+(unsigned long)len)<pos+6 || !input->checkPosition(pos+6+len)) {
1074
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3: can not find a shape length\n"));
1075
0
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1076
0
    f << "Entries(Shape" << type << "):";
1077
0
    f << "###";
1078
0
    ascFile.addPos(pos);
1079
0
    ascFile.addNote(f.str().c_str());
1080
0
    return false;
1081
0
  }
1082
0
  static ReadySetGoGraphInternal::Shape::Type const shapeTypes[]= {
1083
0
    ReadySetGoGraphInternal::Shape::T_Rectangle,
1084
0
    ReadySetGoGraphInternal::Shape::T_RectOval, // + oval size
1085
0
    ReadySetGoGraphInternal::Shape::T_Oval,
1086
0
    ReadySetGoGraphInternal::Shape::T_Picture,
1087
0
    ReadySetGoGraphInternal::Shape::T_Text,
1088
0
    ReadySetGoGraphInternal::Shape::T_Line,
1089
0
    ReadySetGoGraphInternal::Shape::T_Line
1090
0
  };
1091
0
  static char const* const what[]= { "Rectangle", "RectOval", "Oval", "Picture", "Text", "Line" /* hv*/, "Line" /* not axis aligned*/};
1092
0
  f << "Entries(" << what[type] << "):";
1093
0
  ReadySetGoGraphInternal::Shape shape(shapeTypes[type]);
1094
0
  f << "IDS=["; // next, prev
1095
0
  for (int i=0; i<2; ++i) f << std::hex << input->readULong(4) << std::dec << ",";
1096
0
  f << "],";
1097
0
  float dim[4];
1098
0
  for (auto &d : dim) d=72*float(input->readLong(4))/65536;
1099
0
  shape.m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]), MWAWVec2f(dim[0]+dim[2],dim[1]+dim[3]));
1100
0
  f << "box=" << shape.m_box << ",";
1101
0
  int val;
1102
0
  if (vers>3) {
1103
0
    val=int(input->readULong(4));
1104
0
    if (val!=0x1555)
1105
0
      f << "dist[text,repel]=" << float(val)/65536 << ",";;
1106
0
  }
1107
0
  val=int(input->readLong(1));
1108
0
  if (val!=type)
1109
0
    f << "##type1=" << val << ",";
1110
0
  val=int(input->readLong(1));
1111
0
  if (val==-1)
1112
0
    f << "selected,";
1113
0
  else if (val)
1114
0
    f << "#selected=" << val << ",";
1115
0
  bool hasPicture=false, hasTabs=false;
1116
0
  val=int(input->readLong(1));
1117
0
  if (val==-1) {
1118
0
    if (vers<4)
1119
0
      shape.m_wrapRoundAround=true;
1120
0
    f << "run[around],";
1121
0
  }
1122
0
  else if (val)
1123
0
    f << "run[around]=" << val << ",";
1124
0
  val=int(input->readULong(1)); // only v4?
1125
0
  if (val&1)
1126
0
    f << "locked,";
1127
0
  if (val&2)
1128
0
    f << "print[no],";
1129
0
  if (val&4) {
1130
0
    f << "run[around],";
1131
0
    if (vers>=4)
1132
0
      shape.m_wrapRoundAround=true;
1133
0
  }
1134
0
  val &=0xf8;
1135
0
  if (val)
1136
0
    f << "fl=" << std::hex << val << std::dec << ",";
1137
0
  switch (type) {
1138
0
  case 0:
1139
0
  case 1:
1140
0
  case 2:
1141
0
  case 5:
1142
0
  case 6: {
1143
0
    if (len!=(type==1 ? 36 : type==6 ? 40 : 32)+decal+(vers>=5 ? 4 : 0)) {
1144
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3[%d]: unexpected data length\n", type));
1145
0
      f << "###";
1146
0
      break;
1147
0
    }
1148
0
    auto &style=shape.m_style;
1149
0
    val=int(input->readLong(1));
1150
0
    int const extraVal=vers<5 ? 0 : 3;
1151
0
    if (val>=0 && val<=5+extraVal) {
1152
0
      float const w[]= {0.125f, 0.25f, 0.5f, 0.75f, 1, 2, 4, 6, 8};
1153
0
      style.m_lineWidth=w[val+(3-extraVal)];
1154
0
    }
1155
0
    else if (val>=6+extraVal && val<=10+extraVal) {
1156
0
      float const w[]= {1, 2, 4, 6, 8};
1157
0
      style.m_lineWidth=w[val-6-extraVal];
1158
0
      f << "dash,";
1159
0
      style.m_lineDashWidth= {10,10};
1160
0
    }
1161
0
    else if (val>=11+extraVal && val<=13+extraVal) {
1162
      // changeme: double line 2-1-1, 1-1-2, 1-1-1
1163
0
      style.m_lineWidth=val==13+extraVal ? 3 : 4;
1164
0
      f << "double[line],";
1165
0
    }
1166
0
    else {
1167
0
      style.m_lineWidth=1;
1168
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3[%d]: find unknown line style\n", type));
1169
0
      f << "###line[style]=" << val << ",";
1170
0
    }
1171
0
    if (style.m_lineWidth<1 || style.m_lineWidth>1)
1172
0
      f << "line[width]=" << style.m_lineWidth << ",";
1173
1174
0
    int patIds[2];
1175
0
    int const nonePatId=vers==3 ? 39 : 48;
1176
0
    for (auto &p : patIds) p=int(input->readULong(1));
1177
0
    input->seek(1, librevenge::RVNG_SEEK_CUR); // junk?
1178
1179
0
    int colIds[2]= {-1, -1};
1180
0
    MWAWColor colors[2]= {MWAWColor::white(), MWAWColor::black()};
1181
0
    if (vers>=5) {
1182
0
      for (int i=0; i<2; ++i) {
1183
0
        colIds[i]=int(input->readULong(2));
1184
0
        int const expected[]= {7, 60};
1185
0
        if (colIds[i]==expected[i]) continue;
1186
0
        f << "col[" << (i==0 ? "surf" : "line") << "]=";
1187
0
        if (colIds[i]>0 && m_styleManager->getColor(colIds[i], colors[i]))
1188
0
          f << colors[i] << ",";
1189
0
        else {
1190
0
          f << "###" << colIds[i] << ",";
1191
0
          colIds[i]=-1;
1192
0
        }
1193
0
      }
1194
0
    }
1195
0
    if (type==1) {
1196
0
      int corner[2];
1197
0
      for (auto &d : corner) d=int(input->readLong(2));
1198
0
      shape.m_cornerSize=MWAWVec2i(corner[0], corner[1]);
1199
0
      f << "corner=" << shape.m_cornerSize << ",";
1200
0
    }
1201
0
    if (type==5) { // we must retrieve the line points
1202
0
      auto const &box=shape.m_box;
1203
0
      if (box.size()[0]>box.size()[1]) {
1204
0
        auto y=(box[0][1]+box[1][1])/2;
1205
0
        shape.m_points[0]=MWAWVec2f(box[0][0],y);
1206
0
        shape.m_points[1]=MWAWVec2f(box[1][0],y);
1207
0
      }
1208
0
      else {
1209
0
        auto x=(box[0][0]+box[1][0])/2;
1210
0
        shape.m_points[0]=MWAWVec2f(x,box[0][1]);
1211
0
        shape.m_points[1]=MWAWVec2f(x,box[1][1]);
1212
0
      }
1213
0
    }
1214
0
    if (type==6) {
1215
0
      float iDim[4];
1216
0
      for (auto &d: iDim) d=float(input->readLong(2));
1217
0
      shape.m_points[0]=MWAWVec2f(iDim[1],iDim[0]);
1218
0
      shape.m_points[1]=MWAWVec2f(iDim[3],iDim[2]);
1219
0
      f << "pos=" << shape.m_points[0] << "<->" << shape.m_points[1] << ",";
1220
0
    }
1221
1222
    // time to set the patterns/colors
1223
0
    if (patIds[0]!=nonePatId && (type!=5 && type!=6)) {
1224
0
      MWAWGraphicStyle::Pattern pat;
1225
0
      MWAWColor color;
1226
0
      if (!m_styleManager->getPattern(patIds[0]-1, pat))
1227
0
        f << "##surface[color]=" << patIds[0] << ",";
1228
0
      else {
1229
0
        if (colIds[0]>=0)
1230
0
          pat.m_colors[0]=colors[0];
1231
0
        if (pat.getUniqueColor(color)) {
1232
0
          style.setSurfaceColor(color);
1233
0
          f << "surface[color]=" << color << ",";
1234
0
        }
1235
0
        else {
1236
0
          style.setPattern(pat);
1237
0
          f << "surface[pat]=" << pat << ",";
1238
0
        }
1239
0
      }
1240
0
    }
1241
0
    if (patIds[1]==nonePatId) // transparent
1242
0
      style.m_lineWidth=0;
1243
0
    else {
1244
0
      MWAWGraphicStyle::Pattern pat;
1245
0
      MWAWColor color;
1246
0
      if (!m_styleManager->getPattern(patIds[1]-1, pat))
1247
0
        f << "##line[color]=" << patIds[1] << ",";
1248
0
      else {
1249
0
        if (colIds[1]>=0)
1250
0
          pat.m_colors[0]=colors[1];
1251
0
        if (pat.getAverageColor(style.m_lineColor))
1252
0
          f << "line[color]=" << style.m_lineColor << ",";
1253
0
        else {
1254
0
          MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3[%d]: can not determine a shape color\n", type));
1255
0
          f << "###line[color]=" << patIds[1] << ",";
1256
0
        }
1257
0
      }
1258
0
    }
1259
0
    break;
1260
0
  }
1261
0
  case 3: {
1262
0
    if (len!=(vers==3 ? 40 : vers==4 ? 84 : 0x16c)) {
1263
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3[picture]: unexpected data length\n"));
1264
0
      f << "###";
1265
0
      break;
1266
0
    }
1267
0
    val=int(input->readLong(4));
1268
0
    if (val) {
1269
0
      f << "ID1=" << std::hex << val << std::dec << ",";
1270
0
      hasPicture=true;
1271
0
    }
1272
0
    if (vers>4) {
1273
0
      val=int(input->readLong(2));
1274
0
      if (val) f << "f2=" << val << ",";
1275
0
    }
1276
0
    int iDim[2]; // some multiples of 6, link to decal?
1277
0
    for (auto &d : iDim) d=int(input->readLong(2));
1278
0
    if (iDim[0] || iDim[1])
1279
0
      f << "crop=" << MWAWVec2i(iDim[1],iDim[0]) << ",";
1280
0
    for (int i=0; i<2; ++i) {
1281
0
      val=int(input->readULong(2));
1282
0
      if (val!=100)
1283
0
        f << "scale" << (i==0 ? "X" : "Y") << "=" << val << "%,";
1284
0
    }
1285
0
    if (vers==3)
1286
0
      break;
1287
0
    for (int i=0; i<(vers==4 ? 20 : 3); ++i) {
1288
0
      val=int(input->readLong(2));
1289
0
      if (!val) continue;
1290
0
      if (i==2) // g2&2 run around graphic/frame?, g2&200 print as gray
1291
0
        f << "g" << i << "=" << std::hex << val << std::dec << ",";
1292
0
      else
1293
0
        f << "g" << i << "=" << val << ",";
1294
0
    }
1295
0
    break;
1296
0
  }
1297
0
  case 4: {
1298
0
    if (len!=(vers==3 ? 80 : vers==4 ? 100 : 104)) {
1299
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3[text]: unexpected data length\n"));
1300
0
      f << "###";
1301
0
      break;
1302
0
    }
1303
0
    f << "IDS1=["; // next, prev
1304
0
    for (int i=0; i<2; ++i) f << std::hex << input->readULong(4) << std::dec << ",";
1305
0
    f << "],";
1306
0
    if (vers==3) {
1307
0
      f << "id=" << input->readLong(2) << ","; // 1-f
1308
0
      f << "ID2=" << std::hex << input->readULong(4) << std::dec << ",";
1309
0
      val=int(input->readULong(4));
1310
0
      if (val) {
1311
0
        f << "tab[ID]=" << std::hex << val << std::dec << ",";
1312
0
        hasTabs=true;
1313
0
      }
1314
0
    }
1315
0
    else {
1316
0
      val=int(input->readULong(4));
1317
0
      if (val) {
1318
0
        f << "tab[ID]=" << std::hex << val << std::dec << ",";
1319
0
        hasTabs=true;
1320
0
      }
1321
0
      f << "id=" << input->readLong(2) << ","; // 1-f
1322
0
      f << "ID2=" << std::hex << input->readULong(4) << std::dec << ",";
1323
0
    }
1324
0
    int tDim[4];
1325
0
    for (auto &d : tDim) d=int(input->readLong(2));
1326
0
    f << "unkn=" << MWAWBox2i(MWAWVec2i(tDim[0],tDim[1]),MWAWVec2i(tDim[2],tDim[3])) << ",";
1327
0
    for (int i=0; i<5; ++i) {
1328
0
      val=int(input->readLong(2));
1329
0
      if (val)
1330
0
        f << "f" << i+2 << "=" << val << ",";
1331
0
    }
1332
0
    val=int(input->readULong(2));
1333
0
    if (val&0x4)
1334
0
      f << "postscript,";
1335
0
    if (val&0x10) // useme: basically the text is hidden
1336
0
      f << "white[type],";
1337
0
    if (val&0x20)
1338
0
      f << "ignore[run,around],";
1339
0
    val&=0xffdb;
1340
0
    if (val)
1341
0
      f << "fl1=" << std::hex << val << std::dec << ",";
1342
0
    ascFile.addDelimiter(input->tell(),'|');
1343
0
    input->seek(pos+76+(vers==3 ? 0 : 4), librevenge::RVNG_SEEK_SET);
1344
0
    ascFile.addDelimiter(input->tell(),'|');
1345
0
    shape.m_textId=int(input->readLong(2));
1346
0
    f << "text[id]=" << shape.m_textId << ",";
1347
0
    for (int i=0; i<2; ++i) {
1348
0
      shape.m_linkIds[i]=int(input->readLong(2));
1349
0
      if (shape.m_linkIds[i]==-1)
1350
0
        continue;
1351
0
      f << (i==0 ? "prev" : "next") << "[link]=" << shape.m_linkIds[i] << ",";
1352
0
    }
1353
0
    for (int i=0; i<2; ++i) {
1354
0
      val=int(input->readLong(2));
1355
0
      if (val!=-1)
1356
0
        f << "g" << i << "=" << val << ",";
1357
0
    }
1358
0
    if (vers==3)
1359
0
      break;
1360
0
    for (int i=0; i<(vers==4 ? 8 : 9); ++i) { // g4=3100
1361
0
      val=int(input->readLong(2));
1362
0
      if (val)
1363
0
        f << "g" << i+2 << "=" << val << ",";
1364
0
    }
1365
0
    if (vers==4)
1366
0
      break;
1367
0
    val=int(input->readLong(1));
1368
0
    switch (val) {
1369
0
    case 0: // top
1370
0
      break;
1371
0
    case 1:
1372
0
      shape.m_style.m_verticalAlignment=MWAWGraphicStyle::V_AlignBottom;
1373
0
      f << "vAlign=bottom,";
1374
0
      break;
1375
0
    case 2:
1376
0
      shape.m_style.m_verticalAlignment=MWAWGraphicStyle::V_AlignCenter;
1377
0
      f << "vAlign=center,";
1378
0
      break;
1379
0
    case 3:
1380
0
      shape.m_style.m_verticalAlignment=MWAWGraphicStyle::V_AlignJustify;
1381
0
      f << "vAlign=justify[feathering],";
1382
0
      break;
1383
0
    case 4:
1384
0
      shape.m_style.m_verticalAlignment=MWAWGraphicStyle::V_AlignJustify;
1385
0
      f << "vAlign=justify[paragraph],";
1386
0
      break;
1387
0
    default:
1388
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3[text]: unknown vertical alignment\n"));
1389
0
      f << "##vAlign=" << val << ",";
1390
0
      break;
1391
0
    }
1392
0
    val=int(input->readLong(1));
1393
0
    if (val) f << "h0=" << val << ",";
1394
0
    break;
1395
0
  }
1396
0
  default:
1397
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3[%d]: unexpected data\n", type));
1398
0
    f << "###";
1399
0
    break;
1400
0
  }
1401
0
  if (input->tell()!=pos+6+len)
1402
0
    ascFile.addDelimiter(input->tell(),'|');
1403
0
  ascFile.addPos(pos);
1404
0
  ascFile.addNote(f.str().c_str());
1405
0
  input->seek(pos+6+len, librevenge::RVNG_SEEK_SET);
1406
1407
0
  if (hasPicture) {
1408
0
    pos=input->tell();
1409
0
    len=long(input->readLong(4));
1410
0
    if ((len&0xffff)<7 || !input->checkPosition(pos+4+len))
1411
0
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1412
0
    else {
1413
0
      shape.m_entries[0].setBegin(pos+4);
1414
0
      shape.m_entries[0].setLength(len);
1415
0
      input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
1416
0
      ascFile.addPos(pos);
1417
0
      ascFile.addNote("Picture-data:");
1418
0
    }
1419
0
  }
1420
0
  if (type==4 && vers>3) {
1421
0
    pos=input->tell();
1422
0
    f.str("");
1423
0
    f << "Text-limits:";
1424
0
    if (!input->checkPosition(pos+8)) {
1425
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3: can not find the text limits positions\n"));
1426
0
      f << "###";
1427
0
      ascFile.addPos(pos);
1428
0
      ascFile.addNote(f.str().c_str());
1429
0
      return false;
1430
0
    }
1431
0
    for (int i=0; i<2; ++i) {
1432
0
      shape.m_textPositions[i]=int(input->readLong(4));
1433
0
      if (shape.m_textPositions[i]==0) continue;
1434
0
      f << (i==0 ? "min[pos]" : "max[pos]") << "=" << shape.m_textPositions[i] << ",";
1435
0
    }
1436
0
    ascFile.addPos(pos);
1437
0
    ascFile.addNote(f.str().c_str());
1438
0
  }
1439
0
  if (type==4 && shape.m_linkIds[0]<0) {
1440
0
    for (int st=0; st<(!hasTabs ? 2 : 3); ++st) {
1441
0
      pos=input->tell();
1442
0
      len=long(input->readLong(4));
1443
0
      if (len<10 || (long)((unsigned long)pos+4+(unsigned long)len)<pos+4 || !input->checkPosition(pos+4+len)) {
1444
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV3[text]: can not find a shape length\n"));
1445
0
        input->seek(pos, librevenge::RVNG_SEEK_SET);
1446
0
        f << "###";
1447
0
        ascFile.addPos(pos);
1448
0
        ascFile.addNote("Text-####");
1449
0
        return false;
1450
0
      }
1451
0
      shape.m_entries[st].setBegin(pos+4);
1452
0
      shape.m_entries[st].setLength(len);
1453
0
      ascFile.addPos(pos);
1454
0
      ascFile.addNote(st==0 ? "Text-text" : st==1 ? "Entries(Style):" : "Entries(Tabs):");
1455
0
      input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
1456
0
    }
1457
0
  }
1458
0
  layout.m_shapes.push_back(shape);
1459
0
  return true;
1460
0
}
1461
1462
bool ReadySetGoGraph::readShapeV6(ReadySetGoGraphInternal::Layout &layout, bool &last)
1463
0
{
1464
0
  last=false;
1465
0
  MWAWInputStreamPtr input = m_parser.getInput();
1466
0
  if (!input)
1467
0
    return false;
1468
1469
0
  int const vers=version();
1470
0
  if (vers<6 || m_parser.isDesignStudioFile()) {
1471
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6: unexpected version\n"));
1472
0
    return false;
1473
0
  }
1474
0
  long pos=input->tell();
1475
0
  if (!input->checkPosition(pos+2)) {
1476
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6: can not read a shape\n"));
1477
0
    return false;
1478
0
  }
1479
1480
0
  auto &ascFile = m_parser.ascii();
1481
0
  int type=int(input->readLong(2));
1482
0
  if (type==-1) {
1483
0
    ascFile.addPos(pos);
1484
0
    ascFile.addNote("Layout-end:");
1485
0
    last=true;
1486
0
    return true;
1487
0
  }
1488
0
  libmwaw::DebugStream f;
1489
0
  if (type<0 || type>7) {
1490
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6: the type seems bad\n"));
1491
0
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1492
0
    f << "Entries(Shape" << type << "):";
1493
0
    f << "###";
1494
0
    ascFile.addPos(pos);
1495
0
    ascFile.addNote(f.str().c_str());
1496
0
    return false;
1497
0
  }
1498
1499
0
  long len=long(input->readLong(4));
1500
0
  int const minSize[]= {0x98, 0x9c, 0x98, 0x1e6, 0xe0, 0x98, 0xa0, 0xa0};
1501
0
  if (len<minSize[type] || (long)((unsigned long)pos+6+(unsigned long)len)<pos+6 || !input->checkPosition(pos+6+len)) {
1502
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6: can not find a shape length\n"));
1503
0
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1504
0
    f << "Entries(Shape" << type << "):";
1505
0
    f << "###";
1506
0
    ascFile.addPos(pos);
1507
0
    ascFile.addNote(f.str().c_str());
1508
0
    return false;
1509
0
  }
1510
0
  static ReadySetGoGraphInternal::Shape::Type const shapeTypes[]= {
1511
0
    ReadySetGoGraphInternal::Shape::T_Rectangle,
1512
0
    ReadySetGoGraphInternal::Shape::T_RectOval, // + oval size
1513
0
    ReadySetGoGraphInternal::Shape::T_Oval,
1514
0
    ReadySetGoGraphInternal::Shape::T_Picture,
1515
0
    ReadySetGoGraphInternal::Shape::T_Text,
1516
0
    ReadySetGoGraphInternal::Shape::T_Line,
1517
0
    ReadySetGoGraphInternal::Shape::T_Line,
1518
0
    ReadySetGoGraphInternal::Shape::T_Polygon,
1519
0
  };
1520
0
  static char const* const what[]= { "Rectangle", "RectOval", "Oval", "Picture", "Text", "Line" /* hv*/, "Line" /* not axis aligned*/, "Polygon" };
1521
0
  f << "Entries(" << what[type] << "):";
1522
0
  ReadySetGoGraphInternal::Shape shape(shapeTypes[type]);
1523
0
  f << "IDS=["; // next, prev
1524
0
  for (int i=0; i<2; ++i) f << std::hex << input->readULong(4) << std::dec << ",";
1525
0
  f << "],";
1526
0
  float dim[4];
1527
0
  for (auto &d : dim) d=72*float(input->readLong(4))/65536;
1528
0
  shape.m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]), MWAWVec2f(dim[0]+dim[2],dim[1]+dim[3]));
1529
0
  f << "box=" << shape.m_box << ",";
1530
0
  int val;
1531
0
  val=int(input->readULong(4));
1532
0
  if (val!=0x1555)
1533
0
    f << "dist[text,repel]=" << float(val)/65536 << ",";;
1534
0
  val=int(input->readLong(1));
1535
0
  if (val!=type)
1536
0
    f << "##type1=" << val << ",";
1537
0
  val=int(input->readLong(1));
1538
0
  if (val==-1)
1539
0
    f << "selected,";
1540
0
  else if (val)
1541
0
    f << "#selected=" << val << ",";
1542
0
  bool hasTabs=false;
1543
0
  int numPictures=0;
1544
0
  int numPoints=0;
1545
0
  val=int(input->readLong(1));
1546
0
  if (val==-1)
1547
0
    f << "run[around],";
1548
0
  else if (val)
1549
0
    f << "run[around]=" << val << ",";
1550
0
  val=int(input->readULong(1)); // only v4?
1551
0
  if (val&1)
1552
0
    f << "locked,";
1553
0
  if (val&2)
1554
0
    f << "print[no],";
1555
0
  if (val&4) {
1556
0
    f << "run[around],";
1557
0
    shape.m_wrapRoundAround=true;
1558
0
  }
1559
0
  val &=0xf8;
1560
0
  if (val)
1561
0
    f << "fl=" << std::hex << val << std::dec << ",";
1562
0
  auto &style=shape.m_style;
1563
0
  shape.m_rotate=int(input->readLong(2));
1564
0
  if (shape.m_rotate) {
1565
0
    f << "rot=" << double(shape.m_rotate)/10 << ",";
1566
0
    style.m_rotate=float(shape.m_rotate)/10;
1567
0
  }
1568
0
  val=int(input->readULong(2));
1569
0
  if (val&0x100) {
1570
0
    f << "flipY,";
1571
0
    style.m_flip[1]=true;
1572
0
  }
1573
0
  if (val&0x200) {
1574
0
    f << "flipX,";
1575
0
    style.m_flip[0]=true;
1576
0
  }
1577
0
  val&=0xfcff;
1578
0
  if (val) f << "f7" << "=" << std::hex << val << std::dec << ",";
1579
0
  for (auto &d : dim) d=float(input->readLong(2));
1580
0
  if (dim[0]<dim[2] || dim[1]<dim[3])
1581
0
    f << "box1=" << MWAWBox2f(MWAWVec2f(dim[1],dim[0]), MWAWVec2f(dim[3],dim[2])) << ",";
1582
0
  for (int i=0; i<2; ++i) {
1583
0
    val=int(input->readLong(2));
1584
0
    if (val) f << "f" << 8+i << "=" << val << ",";
1585
0
  }
1586
0
  for (int i=0; i<2; ++i) {
1587
0
    for (auto &d : dim) d=float(input->readLong(2));
1588
0
    if (dim[0]<dim[2] || dim[1]<dim[3])
1589
0
      f << "box" << 2+i << "=" << MWAWBox2f(MWAWVec2f(dim[1],dim[0]), MWAWVec2f(dim[3],dim[2])) << ",";
1590
0
  }
1591
0
  for (int i=0; i<14; ++i) {
1592
0
    val=int(input->readLong(2));
1593
0
    if (val) f << "f" << 10+i << "=" << val << ",";
1594
0
  }
1595
0
  shape.m_groupId=int(input->readLong(2));
1596
0
  if (shape.m_groupId) f << "group=" << shape.m_groupId << ",";
1597
0
  ascFile.addDelimiter(input->tell(),'|');
1598
0
  input->seek(32, librevenge::RVNG_SEEK_CUR);
1599
0
  ascFile.addDelimiter(input->tell(),'|');
1600
0
  val=int(input->readULong(4));
1601
0
  if (val)
1602
0
    f << "ID[unk]=" << std::hex << val << std::dec << ",";
1603
0
  ascFile.addDelimiter(input->tell(),'|');
1604
0
  input->seek(8, librevenge::RVNG_SEEK_CUR);
1605
0
  ascFile.addDelimiter(input->tell(),'|');
1606
1607
0
  int const nonePatId=4;
1608
0
  int backColId=60;
1609
0
  int backPatId=nonePatId;
1610
0
  if (type==4) {
1611
0
    f << "IDS1=["; // next, prev
1612
0
    for (int i=0; i<2; ++i) f << std::hex << input->readULong(4) << std::dec << ",";
1613
0
    f << "],";
1614
0
    val=int(input->readULong(4));
1615
0
    if (val) {
1616
0
      f << "tab[ID]=" << std::hex << val << std::dec << ",";
1617
0
      hasTabs=true;
1618
0
    }
1619
0
    f << "id=" << input->readLong(2) << ","; // 1-f
1620
0
    f << "ID2=" << std::hex << input->readULong(4) << std::dec << ",";
1621
0
    int tDim[4];
1622
0
    for (auto &d : tDim) d=int(input->readLong(2));
1623
0
    f << "unkn=" << MWAWBox2i(MWAWVec2i(tDim[0],tDim[1]),MWAWVec2i(tDim[2],tDim[3])) << ",";
1624
0
    for (int i=0; i<5; ++i) {
1625
0
      val=int(input->readLong(2));
1626
0
      if (!val) continue;
1627
0
      f << "f" << i+2 << "=" << val << ",";
1628
0
    }
1629
0
    val=int(input->readULong(2));
1630
0
    if (val&0x4)
1631
0
      f << "postscript,";
1632
0
    if (val&0x10) // useme: basically the text is hidden
1633
0
      f << "white[type],";
1634
0
    if (val&0x20)
1635
0
      f << "ignore[run,around],";
1636
0
    val&=0xffdb;
1637
0
    if (val)
1638
0
      f << "fl1=" << std::hex << val << std::dec << ",";
1639
0
    ascFile.addDelimiter(input->tell(),'|');
1640
0
    input->seek(pos+76+110, librevenge::RVNG_SEEK_SET);
1641
0
    ascFile.addDelimiter(input->tell(),'|');
1642
0
    shape.m_textId=int(input->readLong(2));
1643
0
    f << "text[id]=" << shape.m_textId << ",";
1644
0
    for (int i=0; i<2; ++i) {
1645
0
      shape.m_linkIds[i]=int(input->readLong(2));
1646
0
      if (shape.m_linkIds[i]==-1)
1647
0
        continue;
1648
0
      f << (i==0 ? "prev" : "next") << "[link]=" << shape.m_linkIds[i] << ",";
1649
0
    }
1650
0
    for (int i=0; i<2; ++i) {
1651
0
      val=int(input->readLong(2));
1652
0
      if (val!=-1)
1653
0
        f << "g" << i << "=" << val << ",";
1654
0
    }
1655
0
    bool hasBackPattern=false;
1656
0
    uint8_t backPattern[8];
1657
0
    for (auto &p : backPattern) {
1658
0
      p=uint8_t(input->readULong(1));
1659
0
      if (p) hasBackPattern=true;
1660
0
    }
1661
0
    if (hasBackPattern) {
1662
0
      f << "back[pat]=[";
1663
0
      for (auto const &p : backPattern) f << std::hex << int(p) << std::dec << ",";
1664
0
      f << "],";
1665
0
    }
1666
0
    backColId=int(input->readLong(2));
1667
0
    if (backColId!=60)
1668
0
      f << "back[col,id]=" << backColId << ",";
1669
0
    backPatId=int(input->readULong(1));
1670
0
    if (backPatId!=nonePatId)
1671
0
      f << "back[pat,id]=" << backPatId << ",";
1672
0
    input->seek(1, librevenge::RVNG_SEEK_CUR);
1673
0
    for (int i=0; i<3; ++i) {
1674
0
      val=int(input->readLong(2));
1675
0
      if (!val)
1676
0
        continue;
1677
0
      f << "g" << i+2 << "=" << val << ",";
1678
0
    }
1679
0
    val=int(input->readLong(1));
1680
0
    switch (val) {
1681
0
    case 0: // top
1682
0
      break;
1683
0
    case 1:
1684
0
      style.m_verticalAlignment=MWAWGraphicStyle::V_AlignBottom;
1685
0
      f << "vAlign=bottom,";
1686
0
      break;
1687
0
    case 2:
1688
0
      style.m_verticalAlignment=MWAWGraphicStyle::V_AlignCenter;
1689
0
      f << "vAlign=center,";
1690
0
      break;
1691
0
    case 3:
1692
0
      style.m_verticalAlignment=MWAWGraphicStyle::V_AlignJustify;
1693
0
      f << "vAlign=justify[feathering],";
1694
0
      break;
1695
0
    case 4:
1696
0
      style.m_verticalAlignment=MWAWGraphicStyle::V_AlignJustify;
1697
0
      f << "vAlign=justify[paragraph],";
1698
0
      break;
1699
0
    default:
1700
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6[text]: unknown vertical alignment\n"));
1701
0
      f << "##vAlign=" << val << ",";
1702
0
      break;
1703
0
    }
1704
0
    val=int(input->readLong(1));
1705
0
    if (val) f << "h0=" << val << ",";
1706
0
  }
1707
0
  val=int(input->readLong(1));
1708
0
  if (val>=0 && val<=8) {
1709
0
    float const w[]= {0.125f, 0.25f, 0.5f, 0.75f, 1, 2, 4, 6, 8};
1710
0
    style.m_lineWidth=w[val];
1711
0
  }
1712
0
  else if (val>=9 && val<=13) {
1713
0
    float const w[]= {1, 2, 4, 6, 8};
1714
0
    style.m_lineWidth=w[val-9];
1715
0
    f << "dash,";
1716
0
    style.m_lineDashWidth= {10,10};
1717
0
  }
1718
0
  else if (val>=14 && val<=16) {
1719
    // changeme: double line 2-1-1, 1-1-2, 1-1-1
1720
0
    style.m_lineWidth=val==16 ? 3 : 4;
1721
0
    f << "double[line],";
1722
0
  }
1723
0
  else {
1724
0
    style.m_lineWidth=1;
1725
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6[%d]: find unknown line style\n", type));
1726
0
    f << "###line[style]=" << val << ",";
1727
0
  }
1728
0
  if (style.m_lineWidth<1 || style.m_lineWidth>1)
1729
0
    f << "line[width]=" << style.m_lineWidth << ",";
1730
0
  val=int(input->readLong(1));
1731
0
  if (val!=1)
1732
0
    f << "g0=" << val << ",";
1733
1734
0
  if (type==3) // fixme
1735
0
    style.m_lineWidth=0;
1736
0
  int numColors=(type<=2 || (type>=5 && type<=7)) ? 2 : 1;
1737
0
  int patIds[2];
1738
0
  for (auto &p : patIds) p=int(input->readULong(1));
1739
0
  int colIds[2]= {-1, -1};
1740
0
  MWAWColor colors[2]= {MWAWColor::white(), MWAWColor::black()};
1741
0
  for (int i=0; i<numColors; ++i) {
1742
0
    colIds[i]=int(input->readULong(2));
1743
0
    int const expected[]= {7, 60};
1744
0
    if (colIds[i]==(type==3 ? 60 : expected[i])) continue;
1745
0
    if (numColors==1)
1746
0
      f << "col=";
1747
0
    else
1748
0
      f << "col[" << (i==0 ? "surf" : "line") << "]=";
1749
0
    if (colIds[i]>0 && m_styleManager->getColor(colIds[i], colors[i]))
1750
0
      f << colors[i] << ",";
1751
0
    else {
1752
0
      f << "###" << colIds[i] << ",";
1753
0
      colIds[i]=-1;
1754
0
    }
1755
0
  }
1756
0
  for (int i=0; i<numColors; ++i) {
1757
0
    int tint=int(input->readLong(2));
1758
0
    if (tint==10000) continue;
1759
0
    f << "tints[" << (i==0 ? "surf" : "line") << "]=" << float(tint)/100 << "%,";
1760
0
    if (tint<0 || tint>10000) {
1761
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6: find bad tint\n"));
1762
0
      f << "###";
1763
0
      continue;
1764
0
    }
1765
0
    colors[i]=MWAWColor::barycenter(float(10000-tint)/10000, MWAWColor::white(), float(tint)/10000, colors[i]);
1766
0
  }
1767
0
  val=int(input->readLong(2));
1768
0
  if (val!=100) f << "g3=" << val << ",";
1769
1770
0
  switch (type) {
1771
0
  case 0:
1772
0
  case 1:
1773
0
  case 2:
1774
0
  case 5:
1775
0
  case 6:
1776
0
  case 7: {
1777
0
    if (type==1) {
1778
0
      int corner[2];
1779
0
      for (auto &d : corner) d=int(input->readLong(2));
1780
0
      shape.m_cornerSize=MWAWVec2i(corner[0], corner[1]);
1781
0
      f << "corner=" << shape.m_cornerSize << ",";
1782
0
    }
1783
0
    if (type==5) { // we must retrieve the line points
1784
0
      auto const &box=shape.m_box;
1785
0
      if (box.size()[0]>box.size()[1]) {
1786
0
        auto y=(box[0][1]+box[1][1])/2;
1787
0
        shape.m_points[0]=MWAWVec2f(box[0][0],y);
1788
0
        shape.m_points[1]=MWAWVec2f(box[1][0],y);
1789
0
      }
1790
0
      else {
1791
0
        auto x=(box[0][0]+box[1][0])/2;
1792
0
        shape.m_points[0]=MWAWVec2f(x,box[0][1]);
1793
0
        shape.m_points[1]=MWAWVec2f(x,box[1][1]);
1794
0
      }
1795
0
    }
1796
0
    if (type==6) {
1797
0
      float iDim[4];
1798
0
      for (auto &d: iDim) d=float(input->readLong(2));
1799
0
      shape.m_points[0]=MWAWVec2f(iDim[1],iDim[0]);
1800
0
      shape.m_points[1]=MWAWVec2f(iDim[3],iDim[2]);
1801
0
      f << "pos=" << shape.m_points[0] << "<->" << shape.m_points[1] << ",";
1802
0
    }
1803
0
    if (type==7) {
1804
0
      numPoints=int(input->readULong(2));
1805
0
      f << "N=" << numPoints << ",";
1806
0
      val=int(input->readULong(2));
1807
0
      if (val!=0x100)
1808
0
        f << "g4=" << val << ",";
1809
0
      auto ID=input->readULong(4);
1810
0
      if (ID)
1811
0
        f << "ID=" << std::hex << ID << std::dec << ",";
1812
      // checkme
1813
0
    }
1814
    // time to set the patterns/colors
1815
0
    if (patIds[0]!=nonePatId && (type!=5 && type!=6)) {
1816
0
      MWAWGraphicStyle::Pattern pat;
1817
0
      MWAWColor color;
1818
0
      if (!m_styleManager->getPattern(patIds[0]-1, pat))
1819
0
        f << "##surface[color]=" << patIds[0] << ",";
1820
0
      else {
1821
0
        if (colIds[0]>=0)
1822
0
          pat.m_colors[0]=colors[0];
1823
0
        if (pat.getUniqueColor(color)) {
1824
0
          style.setSurfaceColor(color);
1825
0
          f << "surface[color]=" << color << ",";
1826
0
        }
1827
0
        else {
1828
0
          style.setPattern(pat);
1829
0
          f << "surface[pat]=" << pat << ",";
1830
0
        }
1831
0
      }
1832
0
    }
1833
0
    if (patIds[1]==nonePatId) // transparent
1834
0
      style.m_lineWidth=0;
1835
0
    else {
1836
0
      MWAWGraphicStyle::Pattern pat;
1837
0
      MWAWColor color;
1838
0
      if (!m_styleManager->getPattern(patIds[1]-1, pat))
1839
0
        f << "##line[color]=" << patIds[1] << ",";
1840
0
      else {
1841
0
        if (colIds[1]>=0)
1842
0
          pat.m_colors[0]=colors[1];
1843
0
        if (pat.getAverageColor(style.m_lineColor))
1844
0
          f << "line[color]=" << style.m_lineColor << ",";
1845
0
        else {
1846
0
          MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6[%d]: can not determine a shape color\n", type));
1847
0
          f << "###line[color]=" << patIds[1] << ",";
1848
0
        }
1849
0
      }
1850
0
    }
1851
0
    break;
1852
0
  }
1853
0
  case 3: {
1854
0
    if (patIds[0]!=4)
1855
0
      f << "pattern[line]=" << patIds[0] << ",";
1856
0
    if (vers==6) {
1857
0
      val=int(input->readLong(2));
1858
0
      if (val) f << "g4=" << val << ",";
1859
0
    }
1860
0
    val=int(input->readULong(4));
1861
0
    if (val) {
1862
0
      f << "ID[pict]=" << std::hex << val << std::dec << ",";
1863
0
      ++numPictures;
1864
0
    }
1865
0
    for (int i=0; i<(vers==6 ? 1 : 2); ++i) {
1866
0
      val=int(input->readLong(2));
1867
0
      if (val) f << "g" << i+3 << "=" << val << ",";
1868
0
    }
1869
0
    int iDim[2]; // some multiples of 6, link to decal?
1870
0
    for (auto &d : iDim) d=int(input->readLong(2));
1871
0
    if (iDim[0] || iDim[1])
1872
0
      f << "crop=" << MWAWVec2i(iDim[1],iDim[0]) << ",";
1873
0
    for (int i=0; i<2; ++i) {
1874
0
      val=int(input->readULong(2));
1875
0
      if (val!=100)
1876
0
        f << "scale" << (i==0 ? "X" : "Y") << "=" << val << "%,";
1877
0
    }
1878
0
    long aPos=input->tell(); // checkme probably identical in v4.5
1879
0
    std::string pictType;
1880
0
    for (int i=0; i<4; ++i) {
1881
0
      char c=char(input->readULong(1));
1882
0
      if (!c) break;
1883
0
      pictType+=c;
1884
0
    }
1885
0
    if (!pictType.empty()) {
1886
0
      f << "type=" << pictType << ",";
1887
0
      ++numPictures;
1888
0
    }
1889
0
    input->seek(aPos+4, librevenge::RVNG_SEEK_SET);
1890
0
    val=int(input->readLong(2));
1891
0
    if (val) // run around graphic/frame?, g2&200 print as gray
1892
0
      f << "fl=" << std::hex << val << std::dec << ",";
1893
1894
0
    long actPos=input->tell();
1895
0
    libmwaw::DebugStream f2;
1896
0
    f2 << "Picture-A:";
1897
0
    input->seek(actPos+314, librevenge::RVNG_SEEK_SET);
1898
0
    ascFile.addDelimiter(input->tell(),'|');
1899
0
    val=int(input->readULong(1));
1900
0
    if (val)
1901
0
      f << "shape=" << val << ",";
1902
0
    ascFile.addPos(actPos);
1903
0
    ascFile.addNote(f2.str().c_str());
1904
0
    break;
1905
0
  }
1906
0
  case 4: {
1907
0
    if (patIds[0]==nonePatId) // transparent
1908
0
      style.m_lineWidth=0;
1909
0
    else {
1910
0
      MWAWGraphicStyle::Pattern pat;
1911
0
      MWAWColor color;
1912
0
      if (!m_styleManager->getPattern(patIds[0]-1, pat))
1913
0
        f << "##line[color]=" << patIds[0] << ",";
1914
0
      else {
1915
0
        if (colIds[0]>=0)
1916
0
          pat.m_colors[0]=colors[0];
1917
0
        if (pat.getAverageColor(style.m_lineColor))
1918
0
          f << "line[color]=" << style.m_lineColor << ",";
1919
0
        else {
1920
0
          MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6[%d]: can not determine a shape color\n", type));
1921
0
          f << "###line[color]=" << patIds[0] << ",";
1922
0
        }
1923
0
      }
1924
0
    }
1925
1926
0
    val=int(input->readLong(2));
1927
0
    if (val)
1928
0
      f << "h0=" << val << ",";
1929
0
    int backTint=int(input->readLong(2));
1930
0
    if (backTint) f << "tint=" << float(backTint)/100 << "%,";
1931
0
    if (backPatId==nonePatId)
1932
0
      break;
1933
1934
0
    MWAWColor color = MWAWColor::black();
1935
0
    if (backColId!=60)
1936
0
      m_styleManager->getColor(backColId, color);
1937
0
    color=MWAWColor::barycenter(float(10000-backTint)/10000, MWAWColor::white(), float(backTint)/10000, color);
1938
0
    MWAWGraphicStyle::Pattern pat;
1939
0
    if (backPatId<1 || !m_styleManager->getPattern(backPatId-1, pat))
1940
0
      style.setSurfaceColor(color);
1941
0
    else {
1942
0
      pat.m_colors[0]=color;
1943
0
      if (pat.getUniqueColor(color))
1944
0
        style.setSurfaceColor(color);
1945
0
      else
1946
0
        style.setPattern(pat);
1947
0
    }
1948
0
    break;
1949
0
  }
1950
0
  default:
1951
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6[%d]: unexpected data\n", type));
1952
0
    f << "###";
1953
0
    break;
1954
0
  }
1955
0
  if (input->tell()!=pos+6+len)
1956
0
    ascFile.addDelimiter(input->tell(),'|');
1957
0
  ascFile.addPos(pos);
1958
0
  ascFile.addNote(f.str().c_str());
1959
0
  input->seek(pos+6+len, librevenge::RVNG_SEEK_SET);
1960
1961
0
  for (int p=0; p<numPictures; ++p) {
1962
0
    pos=input->tell();
1963
0
    len=long(input->readLong(4));
1964
0
    if (len==0 && p==1) { // can happen in v7 files
1965
0
      ascFile.addPos(pos);
1966
0
      ascFile.addNote("_");
1967
0
      continue;
1968
0
    }
1969
0
    if ((len&0xffff)<7 || !input->checkPosition(pos+4+len)) {
1970
0
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1971
0
      break;
1972
0
    }
1973
0
    shape.m_entries[p].setBegin(pos+4);
1974
0
    shape.m_entries[p].setLength(len);
1975
0
    input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
1976
0
    ascFile.addPos(pos);
1977
0
    ascFile.addNote("Picture-data:");
1978
0
  }
1979
0
  if (numPoints) { // FIXME
1980
0
    pos=input->tell();
1981
0
    len=long(input->readLong(4));
1982
0
    if ((len&0xffff)<2 || !input->checkPosition(pos+4+len))
1983
0
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1984
0
    else {
1985
0
      f.str("");
1986
0
      f << "Polygon-point:";
1987
0
      int len2=int(input->readLong(2));
1988
0
      if (len2>len || 2+4*(2+numPoints)>len2) {
1989
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6: the number of points seems bad\n"));
1990
0
        f << "###";
1991
0
        numPoints=0;
1992
0
      }
1993
0
      f << "box=[";
1994
0
      for (int i=0; i<2; ++i) {
1995
0
        int pts[2];
1996
0
        for (auto &pt : pts) pt=int(input->readLong(2));
1997
0
        f << MWAWVec2i(pts[1], pts[0]) << ",";
1998
0
      }
1999
0
      f << "],";
2000
0
      f << "pts=[";
2001
0
      for (int i=0; i<numPoints; ++i) {
2002
0
        float pts[2];
2003
0
        for (auto &pt : pts) pt=float(input->readLong(2));
2004
0
        shape.m_vertices.push_back(MWAWVec2f(pts[1], pts[0]));
2005
0
        f << shape.m_vertices.back() << ",";
2006
0
      }
2007
0
      f << "],";
2008
0
      input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
2009
0
      ascFile.addPos(pos);
2010
0
      ascFile.addNote(f.str().c_str());
2011
0
    }
2012
0
  }
2013
0
  if (type==4) {
2014
0
    pos=input->tell();
2015
0
    f.str("");
2016
0
    f << "Text-limits:";
2017
0
    if (!input->checkPosition(pos+8)) {
2018
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6: can not find the text limits positions\n"));
2019
0
      f << "###";
2020
0
      ascFile.addPos(pos);
2021
0
      ascFile.addNote(f.str().c_str());
2022
0
      return false;
2023
0
    }
2024
0
    for (int i=0; i<2; ++i) {
2025
0
      shape.m_textPositions[i]=int(input->readLong(4));
2026
0
      if (shape.m_textPositions[i]==0) continue;
2027
0
      f << (i==0 ? "min[pos]" : "max[pos]") << "=" << shape.m_textPositions[i] << ",";
2028
0
    }
2029
0
    ascFile.addPos(pos);
2030
0
    ascFile.addNote(f.str().c_str());
2031
0
  }
2032
0
  if (type==4 && shape.m_linkIds[0]<0) {
2033
0
    for (int st=0; st<(!hasTabs ? 2 : 3); ++st) {
2034
0
      pos=input->tell();
2035
0
      len=long(input->readLong(4));
2036
0
      if (len<10 || (long)((unsigned long)pos+4+(unsigned long)len)<pos+4 || !input->checkPosition(pos+4+len)) {
2037
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV6[text]: can not find a shape length\n"));
2038
0
        input->seek(pos, librevenge::RVNG_SEEK_SET);
2039
0
        f << "###";
2040
0
        ascFile.addPos(pos);
2041
0
        ascFile.addNote("Text-####");
2042
0
        return false;
2043
0
      }
2044
0
      shape.m_entries[st].setBegin(pos+4);
2045
0
      shape.m_entries[st].setLength(len);
2046
0
      ascFile.addPos(pos);
2047
0
      ascFile.addNote(st==0 ? "Text-text" : st==1 ? "Entries(Style):" : "Entries(Tabs):");
2048
0
      input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
2049
0
    }
2050
0
  }
2051
0
  layout.m_shapes.push_back(shape);
2052
0
  return true;
2053
0
}
2054
2055
bool ReadySetGoGraph::readShapeDSV2(ReadySetGoGraphInternal::Layout &layout, bool &last)
2056
0
{
2057
0
  last=false;
2058
0
  MWAWInputStreamPtr input = m_parser.getInput();
2059
0
  if (!input)
2060
0
    return false;
2061
2062
0
  int const vers=version();
2063
0
  if (vers<6 || !m_parser.isDesignStudioFile()) {
2064
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2: unexpected version\n"));
2065
0
    return false;
2066
0
  }
2067
0
  long pos=input->tell();
2068
0
  if (!input->checkPosition(pos+2)) {
2069
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2: can not read a shape\n"));
2070
0
    return false;
2071
0
  }
2072
2073
0
  auto &ascFile = m_parser.ascii();
2074
0
  int type=int(input->readLong(2));
2075
0
  if (type==-1) {
2076
0
    ascFile.addPos(pos);
2077
0
    ascFile.addNote("Layout-end:");
2078
0
    last=true;
2079
0
    return true;
2080
0
  }
2081
0
  libmwaw::DebugStream f;
2082
0
  if (type<0 || type>7) {
2083
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2: the type seems bad\n"));
2084
0
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2085
0
    f << "Entries(Shape" << type << "):";
2086
0
    f << "###";
2087
0
    ascFile.addPos(pos);
2088
0
    ascFile.addNote(f.str().c_str());
2089
0
    return false;
2090
0
  }
2091
2092
0
  long len=long(input->readLong(4));
2093
0
  int const minSize[]= {0x7c, 0x80, 0x7c, 0x1ca, 0xc4, 0x84, 0x84, 0x84};
2094
0
  if (len<minSize[type]-28 || (long)((unsigned long)pos+6+(unsigned long)len)<pos+6 || !input->checkPosition(pos+6+len)) {
2095
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2: can not find a shape length\n"));
2096
0
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2097
0
    f << "Entries(Shape" << type << "):";
2098
0
    f << "###";
2099
0
    ascFile.addPos(pos);
2100
0
    ascFile.addNote(f.str().c_str());
2101
0
    return false;
2102
0
  }
2103
0
  static ReadySetGoGraphInternal::Shape::Type const shapeTypes[]= {
2104
0
    ReadySetGoGraphInternal::Shape::T_Rectangle,
2105
0
    ReadySetGoGraphInternal::Shape::T_RectOval, // + oval size
2106
0
    ReadySetGoGraphInternal::Shape::T_Oval,
2107
0
    ReadySetGoGraphInternal::Shape::T_Picture,
2108
0
    ReadySetGoGraphInternal::Shape::T_Text,
2109
0
    ReadySetGoGraphInternal::Shape::T_Line,
2110
0
    ReadySetGoGraphInternal::Shape::T_Line,
2111
0
    ReadySetGoGraphInternal::Shape::T_Polygon,
2112
0
  };
2113
  // checkme can type=1 and type=6 exists
2114
0
  static char const* const what[]= { "Rectangle", "RectOval", "Oval", "Picture", "Text", "Line" /* hv*/, "Line" /* not axis aligned*/, "Polygon" };
2115
0
  f << "Entries(" << what[type] << "):";
2116
0
  ReadySetGoGraphInternal::Shape shape(shapeTypes[type]);
2117
0
  f << "IDS=["; // next, prev
2118
0
  for (int i=0; i<2; ++i) f << std::hex << input->readULong(4) << std::dec << ",";
2119
0
  f << "],";
2120
0
  float dim[4];
2121
0
  for (auto &d : dim) d=72*float(input->readLong(4))/65536;
2122
0
  shape.m_box=MWAWBox2f(MWAWVec2f(dim[0],dim[1]), MWAWVec2f(dim[0]+dim[2],dim[1]+dim[3]));
2123
0
  f << "box=" << shape.m_box << ",";
2124
0
  int val;
2125
0
  val=int(input->readULong(4));
2126
0
  if (val!=0x1555)
2127
0
    f << "dist[text,repel]=" << float(val)/65536 << ",";;
2128
0
  val=int(input->readLong(1));
2129
0
  if (val!=type)
2130
0
    f << "##type1=" << val << ",";
2131
0
  val=int(input->readLong(1));
2132
0
  if (val==-1)
2133
0
    f << "selected,";
2134
0
  else if (val)
2135
0
    f << "#selected=" << val << ",";
2136
0
  bool hasTabs=false;
2137
0
  int numPictures=0;
2138
0
  int numPoints=0;
2139
0
  val=int(input->readLong(1));
2140
0
  if (val==-1)
2141
0
    f << "run[around],";
2142
0
  else if (val)
2143
0
    f << "run[around]=" << val << ",";
2144
0
  val=int(input->readULong(1)); // only v4?
2145
0
  if (val&1)
2146
0
    f << "locked,";
2147
0
  if (val&2)
2148
0
    f << "print[no],";
2149
0
  if (val&4) {
2150
0
    f << "run[around],";
2151
0
    shape.m_wrapRoundAround=true;
2152
0
  }
2153
0
  val &=0xf8;
2154
0
  if (val)
2155
0
    f << "fl=" << std::hex << val << std::dec << ",";
2156
0
  auto &style=shape.m_style;
2157
0
  shape.m_rotate=int(input->readLong(2));
2158
0
  if (shape.m_rotate) {
2159
0
    f << "rot=" << double(shape.m_rotate)/10 << ",";
2160
0
    style.m_rotate=float(shape.m_rotate)/10;
2161
0
  }
2162
0
  val=int(input->readULong(2));
2163
0
  if (val&0x100) {
2164
0
    f << "flipY,";
2165
0
    style.m_flip[1]=true;
2166
0
  }
2167
0
  if (val&0x200) {
2168
0
    f << "flipX,";
2169
0
    style.m_flip[0]=true;
2170
0
  }
2171
0
  val&=0xfcff;
2172
0
  if (val) f << "f7" << "=" << std::hex << val << std::dec << ",";
2173
0
  for (auto &d : dim) d=float(input->readLong(2));
2174
0
  if (dim[0]<dim[2] || dim[1]<dim[3])
2175
0
    f << "box1=" << MWAWBox2f(MWAWVec2f(dim[1],dim[0]), MWAWVec2f(dim[3],dim[2])) << ",";
2176
0
  for (int i=0; i<2; ++i) {
2177
0
    val=int(input->readLong(2));
2178
0
    if (val) f << "f" << 8+i << "=" << val << ",";
2179
0
  }
2180
0
  for (int i=0; i<2; ++i) {
2181
0
    for (auto &d : dim) d=float(input->readLong(2));
2182
0
    if (dim[0]<dim[2] || dim[1]<dim[3])
2183
0
      f << "box" << 2+i << "=" << MWAWBox2f(MWAWVec2f(dim[1],dim[0]), MWAWVec2f(dim[3],dim[2])) << ",";
2184
0
  }
2185
0
  for (int i=0; i<14; ++i) {
2186
0
    val=int(input->readLong(2));
2187
0
    if (val) f << "f" << 10+i << "=" << val << ",";
2188
0
  }
2189
0
  shape.m_groupId=int(input->readLong(2));
2190
0
  if (shape.m_groupId) f << "group=" << shape.m_groupId << ",";
2191
0
  ascFile.addDelimiter(input->tell(),'|');
2192
0
  input->seek(14, librevenge::RVNG_SEEK_CUR); // 0000002d003c0000002d003c0[12]00 12: maybe left/right page
2193
0
  ascFile.addDelimiter(input->tell(),'|');
2194
0
  val=int(input->readULong(4));
2195
0
  if (val)
2196
0
    f << "ID[unk]=" << std::hex << val << std::dec << ",";
2197
0
  ascFile.addDelimiter(input->tell(),'|');
2198
0
  val=int(input->readLong(2));
2199
0
  if (val!=60) // a color index
2200
0
    f << "g0=" << val << ",";
2201
0
  for (int i=0; i<2; ++i) { // g1=2-4, g2=0-3
2202
0
    val=int(input->readULong(1));
2203
0
    if (val!=(i==0 ? 4 : 0))
2204
0
      f << "g" << i+1 << "=" << val << ",";
2205
0
  }
2206
2207
0
  int const nonePatId=48;
2208
0
  int backColId=60;
2209
0
  int backPatId=nonePatId;
2210
0
  if (type==4) {
2211
0
    f << "IDS1=["; // next, prev
2212
0
    for (int i=0; i<2; ++i) f << std::hex << input->readULong(4) << std::dec << ",";
2213
0
    f << "],";
2214
0
    val=int(input->readULong(4));
2215
0
    if (val) {
2216
0
      f << "tab[ID]=" << std::hex << val << std::dec << ",";
2217
0
      hasTabs=true;
2218
0
    }
2219
0
    f << "id=" << input->readLong(2) << ","; // 1-f
2220
0
    f << "ID2=" << std::hex << input->readULong(4) << std::dec << ",";
2221
0
    int tDim[4];
2222
0
    for (auto &d : tDim) d=int(input->readLong(2));
2223
0
    f << "unkn=" << MWAWBox2i(MWAWVec2i(tDim[0],tDim[1]),MWAWVec2i(tDim[2],tDim[3])) << ",";
2224
0
    for (int i=0; i<5; ++i) {
2225
0
      val=int(input->readLong(2));
2226
0
      if (!val) continue;
2227
0
      f << "f" << i+2 << "=" << val << ",";
2228
0
    }
2229
0
    val=int(input->readULong(2));
2230
0
    if (val&0x4)
2231
0
      f << "postscript,";
2232
0
    if (val&0x10) // useme: basically the text is hidden
2233
0
      f << "white[type],";
2234
0
    if (val&0x20)
2235
0
      f << "ignore[run,around],";
2236
0
    val&=0xffdb;
2237
0
    if (val)
2238
0
      f << "fl1=" << std::hex << val << std::dec << ",";
2239
0
    ascFile.addDelimiter(input->tell(),'|');
2240
0
    input->seek(pos+76+88, librevenge::RVNG_SEEK_SET);
2241
0
    ascFile.addDelimiter(input->tell(),'@');
2242
0
    shape.m_textId=int(input->readLong(2));
2243
0
    f << "text[id]=" << shape.m_textId << ",";
2244
0
    for (int i=0; i<2; ++i) {
2245
0
      shape.m_linkIds[i]=int(input->readLong(2));
2246
0
      if (shape.m_linkIds[i]==-1)
2247
0
        continue;
2248
0
      f << (i==0 ? "prev" : "next") << "[link]=" << shape.m_linkIds[i] << ",";
2249
0
    }
2250
0
    for (int i=0; i<2; ++i) {
2251
0
      val=int(input->readLong(2));
2252
0
      if (val!=-1)
2253
0
        f << "g" << i << "=" << val << ",";
2254
0
    }
2255
0
    ascFile.addDelimiter(input->tell(),'@');
2256
0
    bool hasBackPattern=false;
2257
0
    uint8_t backPattern[8];
2258
0
    for (auto &p : backPattern) {
2259
0
      p=uint8_t(input->readULong(1));
2260
0
      if (p) hasBackPattern=true;
2261
0
    }
2262
0
    if (hasBackPattern) {
2263
0
      f << "back[pat]=[";
2264
0
      for (auto const &p : backPattern) f << std::hex << int(p) << std::dec << ",";
2265
0
      f << "],";
2266
0
    }
2267
0
    backColId=int(input->readLong(2));
2268
0
    if (backColId!=60)
2269
0
      f << "back[col,id]=" << backColId << ",";
2270
0
    backPatId=int(input->readULong(1));
2271
0
    if (backPatId!=nonePatId)
2272
0
      f << "back[pat,id]=" << backPatId << ",";
2273
0
    input->seek(1, librevenge::RVNG_SEEK_CUR);
2274
0
    for (int i=0; i<3; ++i) {
2275
0
      val=int(input->readLong(2));
2276
0
      if (!val)
2277
0
        continue;
2278
0
      f << "g" << i+2 << "=" << val << ",";
2279
0
    }
2280
0
    val=int(input->readLong(1));
2281
0
    switch (val) {
2282
0
    case 0: // top
2283
0
      break;
2284
0
    case 1:
2285
0
      style.m_verticalAlignment=MWAWGraphicStyle::V_AlignBottom;
2286
0
      f << "vAlign=bottom,";
2287
0
      break;
2288
0
    case 2:
2289
0
      style.m_verticalAlignment=MWAWGraphicStyle::V_AlignCenter;
2290
0
      f << "vAlign=center,";
2291
0
      break;
2292
0
    case 3:
2293
0
      style.m_verticalAlignment=MWAWGraphicStyle::V_AlignJustify;
2294
0
      f << "vAlign=justify[feathering],";
2295
0
      break;
2296
0
    case 4:
2297
0
      style.m_verticalAlignment=MWAWGraphicStyle::V_AlignJustify;
2298
0
      f << "vAlign=justify[paragraph],";
2299
0
      break;
2300
0
    default:
2301
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2[text]: unknown vertical alignment\n"));
2302
0
      f << "##vAlign=" << val << ",";
2303
0
      break;
2304
0
    }
2305
0
    val=int(input->readLong(1));
2306
0
    if (val) f << "h0=" << val << ",";
2307
0
  }
2308
0
  val=int(input->readLong(1));
2309
0
  int width=int(input->readULong(1));
2310
0
  if (val>=0 && val<=8) {
2311
0
    float const w[]= {0.125f, 0.25f, 0.5f, 0.75f, 1, 2, 4, 6, 8};
2312
0
    style.m_lineWidth=w[val];
2313
0
  }
2314
0
  else if (val==9)
2315
0
    style.m_lineWidth=float(width);
2316
0
  else if (val>=11 && val<=14) {
2317
0
    float const w[]= {1, 2, 4, 6, 8};
2318
0
    style.m_lineWidth=w[val-11];
2319
0
    f << "dash,";
2320
0
    style.m_lineDashWidth= {10,10};
2321
0
  }
2322
0
  else if (val>=16 && val<=18) {
2323
    // changeme: double line 2-1-1, 1-1-2, 1-1-1
2324
0
    style.m_lineWidth=val==18 ? 3 : 4;
2325
0
    f << "double[line],";
2326
0
  }
2327
0
  else {
2328
0
    style.m_lineWidth=1;
2329
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2[%d]: find unknown line style\n", type));
2330
0
    f << "###line[style]=" << val << "[" << width << "],";
2331
0
  }
2332
0
  if (style.m_lineWidth<1 || style.m_lineWidth>1)
2333
0
    f << "line[width]=" << style.m_lineWidth << ",";
2334
2335
0
  if (type==3) // fixme
2336
0
    style.m_lineWidth=0;
2337
0
  int numColors=(type<=2 || (type>=5 && type<=7)) ? 2 : 1;
2338
0
  int patIds[2]; // 31 1
2339
0
  for (auto &p : patIds) p=int(input->readULong(1));
2340
0
  int colIds[2]= {-1, -1};
2341
0
  MWAWColor colors[2]= {MWAWColor::white(), MWAWColor::black()};
2342
0
  for (int i=0; i<numColors; ++i) {
2343
0
    colIds[i]=int(input->readULong(2));
2344
0
    int const expected[]= {7, 60};
2345
0
    if (colIds[i]==(type==3 ? 60 : expected[i])) continue;
2346
0
    if (numColors==1)
2347
0
      f << "col=";
2348
0
    else
2349
0
      f << "col[" << (i==0 ? "surf" : "line") << "]=";
2350
0
    if (colIds[i]>0 && m_styleManager->getColor(colIds[i], colors[i]))
2351
0
      f << colors[i] << ",";
2352
0
    else {
2353
0
      f << "###" << colIds[i] << ",";
2354
0
      colIds[i]=-1;
2355
0
    }
2356
0
  }
2357
2358
0
  switch (type) {
2359
0
  case 0:
2360
0
  case 1:
2361
0
  case 2:
2362
0
  case 5:
2363
0
  case 6:
2364
0
  case 7: {
2365
0
    if (type==1) {
2366
0
      int corner[2];
2367
0
      for (auto &d : corner) d=int(input->readLong(2));
2368
0
      shape.m_cornerSize=MWAWVec2i(corner[0], corner[1]);
2369
0
      f << "corner=" << shape.m_cornerSize << ",";
2370
0
    }
2371
0
    if (type==5) { // we must retrieve the line points
2372
0
      auto const &box=shape.m_box;
2373
0
      if (box.size()[0]>box.size()[1]) {
2374
0
        auto y=(box[0][1]+box[1][1])/2;
2375
0
        shape.m_points[0]=MWAWVec2f(box[0][0],y);
2376
0
        shape.m_points[1]=MWAWVec2f(box[1][0],y);
2377
0
      }
2378
0
      else {
2379
0
        auto x=(box[0][0]+box[1][0])/2;
2380
0
        shape.m_points[0]=MWAWVec2f(x,box[0][1]);
2381
0
        shape.m_points[1]=MWAWVec2f(x,box[1][1]);
2382
0
      }
2383
0
      int arrowDim[3];
2384
0
      for (auto &d: arrowDim) d=int(input->readLong(2));
2385
0
      if (arrowDim[1]!=20 || arrowDim[2]!=10)
2386
0
        f << "arrow[pt0]=" << MWAWVec2i(arrowDim[1], arrowDim[2]) << ",";
2387
0
      if (arrowDim[0]!=20)
2388
0
        f << "arrow[pt1]=" << MWAWVec2i(arrowDim[0], 0) << ",";
2389
0
      float w=float(std::max<int>(5,arrowDim[2]));
2390
0
      val=int(input->readULong(2));
2391
0
      MWAWGraphicStyle::Arrow arrow;
2392
0
      if (val&4) {
2393
        // changeme normally the polygon is defined by O, pt0, pt1, arrowDim[1]x-arrowDim[2]
2394
0
        f << "bound[arrow,only],";
2395
0
        arrow=MWAWGraphicStyle::Arrow(w, MWAWBox2i(MWAWVec2i(0,0),MWAWVec2i(1122,2243)), "M0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z", false);
2396
0
      }
2397
0
      else {
2398
0
        bool ok=true;
2399
0
        for (auto const &d : arrowDim) {
2400
0
          if (d<=0) ok=false;
2401
0
        }
2402
0
        if (ok) {
2403
0
          std::stringstream s;
2404
0
          s << "M " << arrowDim[2] << " 0 "
2405
0
            << 2*arrowDim[2] << " " << arrowDim[1] << " "
2406
0
            << arrowDim[2] << " " << arrowDim[0] << " "
2407
0
            << "0 " << arrowDim[1] << "z";
2408
0
          arrow=MWAWGraphicStyle::Arrow(float(arrowDim[2]), MWAWBox2i(MWAWVec2i(0,0),MWAWVec2i(2*arrowDim[2],std::max(arrowDim[0],arrowDim[1]))), s.str(), false);
2409
0
        }
2410
0
        else
2411
0
          arrow=MWAWGraphicStyle::Arrow(w, MWAWBox2i(MWAWVec2i(0,0),MWAWVec2i(20,30)), "m10 0l-10 30h20z", false);
2412
0
      }
2413
0
      if (val&1) {
2414
0
        style.m_arrows[0]=arrow;
2415
0
        f << "arrow[beg],";
2416
0
      }
2417
0
      if (val&2) {
2418
0
        style.m_arrows[1]=arrow;
2419
0
        f << "arrow[end],";
2420
0
      }
2421
0
      val&=0xfff8;
2422
0
      if (val)
2423
0
        f << "arrow[fl]=" << std::hex << val << std::dec << ",";
2424
0
    }
2425
0
    if (type==6) {
2426
0
      float iDim[4];
2427
0
      for (auto &d: iDim) d=float(input->readLong(2));
2428
0
      shape.m_points[0]=MWAWVec2f(iDim[1],iDim[0]);
2429
0
      shape.m_points[1]=MWAWVec2f(iDim[3],iDim[2]);
2430
0
      f << "pos=" << shape.m_points[0] << "<->" << shape.m_points[1] << ",";
2431
0
    }
2432
0
    if (type==7) {
2433
0
      numPoints=int(input->readULong(2));
2434
0
      f << "N=" << numPoints << ",";
2435
0
      val=int(input->readULong(2));
2436
0
      if (val!=0x100)
2437
0
        f << "g4=" << val << ",";
2438
0
      auto ID=input->readULong(4);
2439
0
      if (ID)
2440
0
        f << "ID=" << std::hex << ID << std::dec << ",";
2441
      // checkme
2442
0
    }
2443
    // time to set the patterns/colors
2444
0
    if (patIds[0]!=nonePatId && (type!=5 && type!=6)) {
2445
0
      MWAWGraphicStyle::Pattern pat;
2446
0
      MWAWColor color;
2447
0
      if (!m_styleManager->getPattern(patIds[0]-1, pat))
2448
0
        f << "##surface[color]=" << patIds[0] << ",";
2449
0
      else {
2450
0
        if (colIds[0]>=0)
2451
0
          pat.m_colors[0]=colors[0];
2452
0
        if (pat.getUniqueColor(color)) {
2453
0
          style.setSurfaceColor(color);
2454
0
          f << "surface[color]=" << color << ",";
2455
0
        }
2456
0
        else {
2457
0
          style.setPattern(pat);
2458
0
          f << "surface[pat]=" << pat << ",";
2459
0
        }
2460
0
      }
2461
0
    }
2462
0
    if (patIds[1]==nonePatId) // transparent
2463
0
      style.m_lineWidth=0;
2464
0
    else {
2465
0
      MWAWGraphicStyle::Pattern pat;
2466
0
      MWAWColor color;
2467
0
      if (!m_styleManager->getPattern(patIds[1]-1, pat))
2468
0
        f << "##line[color]=" << patIds[1] << ",";
2469
0
      else {
2470
0
        if (colIds[1]>=0)
2471
0
          pat.m_colors[0]=colors[1];
2472
0
        if (pat.getAverageColor(style.m_lineColor))
2473
0
          f << "line[color]=" << style.m_lineColor << ",";
2474
0
        else {
2475
0
          MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2[%d]: can not determine a shape color\n", type));
2476
0
          f << "###line[color]=" << patIds[1] << ",";
2477
0
        }
2478
0
      }
2479
0
    }
2480
0
    break;
2481
0
  }
2482
0
  case 3: {
2483
0
    if (patIds[0]!=4)
2484
0
      f << "pattern[line]=" << patIds[0] << ",";
2485
0
    if (vers==6) {
2486
0
      val=int(input->readLong(2));
2487
0
      if (val) f << "g4=" << val << ",";
2488
0
    }
2489
0
    val=int(input->readULong(2));
2490
0
    if (val) {
2491
0
      f << "num[pict]=" << val << ",";
2492
0
      ++numPictures;
2493
0
    }
2494
0
    auto ID=int(input->readULong(4));
2495
0
    if (ID)
2496
0
      f << "ID[pict]=" << std::hex << ID << std::dec << ",";
2497
0
    int iDim[2]; // some multiples of 6, link to decal?
2498
0
    for (auto &d : iDim) d=int(input->readLong(2));
2499
0
    if (iDim[0] || iDim[1])
2500
0
      f << "crop=" << MWAWVec2i(iDim[1],iDim[0]) << ",";
2501
0
    for (int i=0; i<2; ++i) {
2502
0
      val=int(input->readULong(2));
2503
0
      if (val!=100)
2504
0
        f << "scale" << (i==0 ? "X" : "Y") << "=" << val << "%,";
2505
0
    }
2506
0
    long aPos=input->tell(); // checkme probably identical in v4.5
2507
0
    std::string pictType;
2508
0
    for (int i=0; i<4; ++i) {
2509
0
      char c=char(input->readULong(1));
2510
0
      if (!c) break;
2511
0
      pictType+=c;
2512
0
    }
2513
0
    if (!pictType.empty())
2514
0
      f << "type=" << pictType << ",";
2515
0
    input->seek(aPos+4, librevenge::RVNG_SEEK_SET);
2516
0
    val=int(input->readULong(2));
2517
0
    if (val) // run around graphic/frame?, g2&200 print as gray
2518
0
      f << "fl=" << std::hex << val << std::dec << ",";
2519
2520
0
    long actPos=input->tell();
2521
0
    libmwaw::DebugStream f2;
2522
0
    f2 << "Picture-A:";
2523
0
    int cPos=int(input->readULong(1));
2524
0
    std::string name;
2525
0
    if (cPos>=32) {
2526
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2[pict]: can not read the filename\n"));
2527
0
      f2 << "###filename";
2528
0
      cPos=0;
2529
0
    }
2530
0
    for (int i=0; i<cPos; ++i) {
2531
0
      char c=char(input->readULong(1));
2532
0
      if (!c) break;
2533
0
      name+=c;
2534
0
    }
2535
0
    if (!name.empty())
2536
0
      f2 << "file=" << name << ",";
2537
0
    input->seek(actPos+314, librevenge::RVNG_SEEK_SET);
2538
0
    ascFile.addDelimiter(input->tell(),'|');
2539
0
    val=int(input->readULong(1));
2540
0
    if (val)
2541
0
      f << "shape=" << val << ",";
2542
0
    ascFile.addPos(actPos);
2543
0
    ascFile.addNote(f2.str().c_str());
2544
0
    break;
2545
0
  }
2546
0
  case 4: {
2547
0
    if (patIds[0]==nonePatId) // transparent
2548
0
      style.m_lineWidth=0;
2549
0
    else {
2550
0
      MWAWGraphicStyle::Pattern pat;
2551
0
      MWAWColor color;
2552
0
      if (!m_styleManager->getPattern(patIds[0]-1, pat))
2553
0
        f << "##line[color]=" << patIds[0] << ",";
2554
0
      else {
2555
0
        if (colIds[0]>=0)
2556
0
          pat.m_colors[0]=colors[0];
2557
0
        if (pat.getAverageColor(style.m_lineColor))
2558
0
          f << "line[color]=" << style.m_lineColor << ",";
2559
0
        else {
2560
0
          MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2[%d]: can not determine a shape color\n", type));
2561
0
          f << "###line[color]=" << patIds[0] << ",";
2562
0
        }
2563
0
      }
2564
0
    }
2565
2566
0
    if (backPatId==nonePatId)
2567
0
      break;
2568
2569
0
    MWAWColor color = MWAWColor::black();
2570
0
    if (backColId!=60)
2571
0
      m_styleManager->getColor(backColId, color);
2572
0
    MWAWGraphicStyle::Pattern pat;
2573
0
    if (backPatId<1 || !m_styleManager->getPattern(backPatId-1, pat))
2574
0
      style.setSurfaceColor(color);
2575
0
    else {
2576
0
      pat.m_colors[0]=color;
2577
0
      if (pat.getUniqueColor(color))
2578
0
        style.setSurfaceColor(color);
2579
0
      else
2580
0
        style.setPattern(pat);
2581
0
    }
2582
0
    break;
2583
0
  }
2584
0
  default:
2585
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2[%d]: unexpected data\n", type));
2586
0
    f << "###";
2587
0
    break;
2588
0
  }
2589
0
  if (input->tell()!=pos+6+len)
2590
0
    ascFile.addDelimiter(input->tell(),'|');
2591
0
  ascFile.addPos(pos);
2592
0
  ascFile.addNote(f.str().c_str());
2593
0
  input->seek(pos+6+len, librevenge::RVNG_SEEK_SET);
2594
2595
0
  for (int p=0; p<numPictures; ++p) {
2596
0
    pos=input->tell();
2597
0
    len=long(input->readLong(4));
2598
0
    if ((len&0xffff)<7 || !input->checkPosition(pos+4+len)) {
2599
0
      input->seek(pos, librevenge::RVNG_SEEK_SET);
2600
0
      break;
2601
0
    }
2602
0
    shape.m_entries[p].setBegin(pos+4);
2603
0
    shape.m_entries[p].setLength(len);
2604
0
    input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
2605
0
    ascFile.addPos(pos);
2606
0
    ascFile.addNote("Picture-data:");
2607
0
  }
2608
0
  if (numPoints) { // FIXME
2609
0
    pos=input->tell();
2610
0
    len=long(input->readLong(4));
2611
0
    if ((len&0xffff)<2 || !input->checkPosition(pos+4+len))
2612
0
      input->seek(pos, librevenge::RVNG_SEEK_SET);
2613
0
    else {
2614
0
      f.str("");
2615
0
      f << "Polygon-point:";
2616
0
      int len2=int(input->readLong(2));
2617
0
      if (len2>len || 2+4*(2+numPoints)>len2) {
2618
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2: the number of points seems bad\n"));
2619
0
        f << "###";
2620
0
        numPoints=0;
2621
0
      }
2622
0
      f << "box=[";
2623
0
      for (int i=0; i<2; ++i) {
2624
0
        int pts[2];
2625
0
        for (auto &pt : pts) pt=int(input->readLong(2));
2626
0
        f << MWAWVec2i(pts[1], pts[0]) << ",";
2627
0
      }
2628
0
      f << "],";
2629
0
      f << "pts=[";
2630
0
      for (int i=0; i<numPoints; ++i) {
2631
0
        float pts[2];
2632
0
        for (auto &pt : pts) pt=float(input->readLong(2));
2633
0
        shape.m_vertices.push_back(MWAWVec2f(pts[1], pts[0]));
2634
0
        f << shape.m_vertices.back() << ",";
2635
0
      }
2636
0
      f << "],";
2637
0
      input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
2638
0
      ascFile.addPos(pos);
2639
0
      ascFile.addNote(f.str().c_str());
2640
0
    }
2641
0
  }
2642
0
  if (type==4) {
2643
0
    pos=input->tell();
2644
0
    f.str("");
2645
0
    f << "Text-limits:";
2646
0
    if (!input->checkPosition(pos+8)) {
2647
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2: can not find the text limits positions\n"));
2648
0
      f << "###";
2649
0
      ascFile.addPos(pos);
2650
0
      ascFile.addNote(f.str().c_str());
2651
0
      return false;
2652
0
    }
2653
0
    for (int i=0; i<2; ++i) {
2654
0
      shape.m_textPositions[i]=int(input->readLong(4));
2655
0
      if (shape.m_textPositions[i]==0) continue;
2656
0
      f << (i==0 ? "min[pos]" : "max[pos]") << "=" << shape.m_textPositions[i] << ",";
2657
0
    }
2658
0
    ascFile.addPos(pos);
2659
0
    ascFile.addNote(f.str().c_str());
2660
0
  }
2661
0
  if (type==4 && shape.m_linkIds[0]<0) {
2662
0
    for (int st=0; st<(!hasTabs ? 2 : 3); ++st) {
2663
0
      pos=input->tell();
2664
0
      len=long(input->readLong(4));
2665
0
      if (len<10 || (long)((unsigned long)pos+4+(unsigned long)len)<pos+4 || !input->checkPosition(pos+4+len)) {
2666
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeDSV2[text]: can not find a shape length\n"));
2667
0
        input->seek(pos, librevenge::RVNG_SEEK_SET);
2668
0
        f << "###";
2669
0
        ascFile.addPos(pos);
2670
0
        ascFile.addNote("Text-####");
2671
0
        return false;
2672
0
      }
2673
0
      shape.m_entries[st].setBegin(pos+4);
2674
0
      shape.m_entries[st].setLength(len);
2675
0
      ascFile.addPos(pos);
2676
0
      ascFile.addNote(st==0 ? "Text-text" : st==1 ? "Entries(Style):" : "Entries(Tabs):");
2677
0
      input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
2678
0
    }
2679
0
  }
2680
0
  layout.m_shapes.push_back(shape);
2681
0
  return true;
2682
0
}
2683
2684
////////////////////////////////////////////////////////////
2685
// send data
2686
////////////////////////////////////////////////////////////
2687
bool ReadySetGoGraph::sendMasterPages()
2688
78
{
2689
78
  auto listener=m_parser.getGraphicListener();
2690
78
  if (!listener) {
2691
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::sendMasterPages: can not find the listener\n"));
2692
0
    return false;
2693
0
  }
2694
78
  int const vers=version();
2695
78
  if (vers<3)
2696
78
    return true;
2697
0
  bool const sharedList=vers<6 || (vers==6 && m_parser.isDesignStudioFile());
2698
0
  auto const &layouts = sharedList ? m_state->m_layouts : m_state->m_masterLayouts;
2699
0
  size_t const numMaster=sharedList ? std::min<size_t>(2,layouts.size()) : layouts.size();
2700
0
  for (size_t layout=0; layout<numMaster; ++layout) {
2701
0
    if (layouts[layout].m_shapes.empty())
2702
0
      continue;
2703
0
    MWAWPageSpan ps(m_parser.getPageSpan());
2704
0
    librevenge::RVNGString name;
2705
0
    name.sprintf("MasterPage%d", int(layout));
2706
0
    ps.setMasterPageName(name);
2707
0
    if (!listener->openMasterPage(ps)) {
2708
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::sendMasterPages: can not create the master page\n"));
2709
0
    }
2710
0
    else {
2711
0
      send(layouts[layout]);
2712
0
      listener->closeMasterPage();
2713
0
    }
2714
0
  }
2715
0
  return true;
2716
78
}
2717
2718
bool ReadySetGoGraph::sendPages()
2719
78
{
2720
78
  auto listener=m_parser.getGraphicListener();
2721
78
  if (!listener) {
2722
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::sendPages: can not find the listener\n"));
2723
0
    return false;
2724
0
  }
2725
78
  bool firstPage=true;
2726
78
  int const vers=version();
2727
157
  for (size_t layout=(vers<3 ? 0 : 2); layout<m_state->m_layouts.size(); ++layout) {
2728
79
    if (!firstPage)
2729
1
      listener->insertBreak(MWAWListener::PageBreak);
2730
79
    send(m_state->m_layouts[layout]);
2731
79
    firstPage=false;
2732
79
  }
2733
78
  return true;
2734
78
}
2735
2736
bool ReadySetGoGraph::send(ReadySetGoGraphInternal::Layout const &layout)
2737
79
{
2738
79
  auto listener=m_parser.getGraphicListener();
2739
79
  if (!listener) {
2740
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::send[layout]: can not find the listener\n"));
2741
0
    return false;
2742
0
  }
2743
220
  for (size_t i=0; i<layout.m_shapes.size();) {
2744
141
    auto const &shape=layout.m_shapes[i];
2745
141
    if (shape.m_groupId>0) {
2746
0
      int group=shape.m_groupId;
2747
0
      if (i+1<layout.m_shapes.size() && layout.m_shapes[i+1].m_groupId==group) {
2748
0
        MWAWPosition pos(shape.m_box[0], shape.m_box.size(), librevenge::RVNG_POINT);
2749
0
        pos.setRelativePosition(MWAWPosition::Page);
2750
0
        if (listener->openGroup(pos)) {
2751
0
          while (i<layout.m_shapes.size() && layout.m_shapes[i].m_groupId==group)
2752
0
            send(layout.m_shapes[i++]);
2753
0
          listener->closeGroup();
2754
0
          continue;
2755
0
        }
2756
0
      }
2757
0
    }
2758
141
    ++i;
2759
141
    send(shape);
2760
141
  }
2761
79
  return true;
2762
79
}
2763
2764
bool ReadySetGoGraph::send(ReadySetGoGraphInternal::Shape const &shape)
2765
141
{
2766
141
  auto input=m_parser.getInput();
2767
141
  auto listener=m_parser.getGraphicListener();
2768
141
  if (!input || !listener) {
2769
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::send: can not find the listener\n"));
2770
0
    return false;
2771
0
  }
2772
141
  MWAWPosition pos(shape.m_box[0], shape.m_box.size(), librevenge::RVNG_POINT);
2773
141
  pos.setRelativePosition(MWAWPosition::Page);
2774
141
  if (shape.m_wrapRoundAround)
2775
0
    pos.m_wrapping=MWAWPosition::WDynamic;
2776
141
  MWAWGraphicShape gShape;
2777
141
  switch (shape.m_type) {
2778
14
  case ReadySetGoGraphInternal::Shape::T_Empty:
2779
14
    return true;
2780
10
  case ReadySetGoGraphInternal::Shape::T_Text: {
2781
10
    auto subdoc=std::make_shared<ReadySetGoGraphInternal::SubDocument>(*this, input, shape);
2782
10
    listener->insertTextBox(pos, subdoc, shape.m_style);
2783
10
    return true;
2784
0
  }
2785
0
  case ReadySetGoGraphInternal::Shape::T_Line:
2786
0
    gShape=MWAWGraphicShape::line(shape.m_box[0]+shape.m_points[0], shape.m_box[0]+shape.m_points[1]);
2787
0
    break;
2788
0
  case ReadySetGoGraphInternal::Shape::T_Oval:
2789
0
    gShape=MWAWGraphicShape::circle(shape.m_box);
2790
0
    break;
2791
3
  case ReadySetGoGraphInternal::Shape::T_Rectangle:
2792
3
    gShape=MWAWGraphicShape::rectangle(shape.m_box);
2793
3
    break;
2794
0
  case ReadySetGoGraphInternal::Shape::T_RectOval:
2795
0
    gShape=MWAWGraphicShape::rectangle(shape.m_box, shape.m_cornerSize[0]>=0 ? 0.5f*MWAWVec2f(float(shape.m_cornerSize[0]), float(shape.m_cornerSize[1]))
2796
0
                                       : 0.25f*shape.m_box.size());
2797
0
    break;
2798
0
  case ReadySetGoGraphInternal::Shape::T_Polygon:
2799
0
    if (shape.m_vertices.size()<2) {
2800
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::send[polygon]: sorry, the number of points seem bad\n"));
2801
0
      return false;
2802
0
    }
2803
0
    if (shape.m_style.hasSurface())
2804
0
      gShape=MWAWGraphicShape::polygon(shape.m_box);
2805
0
    else
2806
0
      gShape=MWAWGraphicShape::polyline(shape.m_box);
2807
0
    gShape.m_vertices=shape.m_vertices;
2808
0
    break;
2809
114
  case ReadySetGoGraphInternal::Shape::T_Picture: {
2810
114
    if (!shape.m_entries[0].valid() || !input->checkPosition(shape.m_entries[0].end())) {
2811
1
      MWAWGraphicStyle style;
2812
1
      listener->openGroup(pos);
2813
4
      for (int w=0; w<3; ++w) {
2814
3
        if (w==0)
2815
1
          gShape=MWAWGraphicShape::rectangle(shape.m_box);
2816
2
        else if (w==1)
2817
1
          gShape=MWAWGraphicShape::line(shape.m_box[0],shape.m_box[1]);
2818
1
        else
2819
1
          gShape=MWAWGraphicShape::line(MWAWVec2f(shape.m_box[0][0],shape.m_box[1][1]), MWAWVec2f(shape.m_box[1][0],shape.m_box[0][1]));
2820
3
        if (shape.m_rotate) {
2821
0
          gShape=gShape.rotate(float(shape.m_rotate)/10, shape.m_box.center());
2822
0
          auto box=gShape.getBdBox(shape.m_style);
2823
0
          pos.setOrigin(box[0]);
2824
0
          pos.setSize(box.size());
2825
0
        }
2826
3
        if (shape.m_style.m_flip[0]) {
2827
0
          gShape.scale(MWAWVec2f(-1,1));
2828
0
          pos.setOrigin(pos.origin()+MWAWVec2f(pos.size()[0],0));
2829
0
        }
2830
3
        if (shape.m_style.m_flip[1]) {
2831
0
          gShape.scale(MWAWVec2f(1, -1));
2832
0
          pos.setOrigin(pos.origin()+MWAWVec2f(0,pos.size()[1]));
2833
0
        }
2834
2835
3
        listener->insertShape(pos, gShape, style);
2836
3
      }
2837
1
      listener->closeGroup();
2838
1
      return true;
2839
1
    }
2840
113
    MWAWEmbeddedObject object;
2841
339
    for (int w=0; w<2; w++) {
2842
226
      if (!shape.m_entries[w].valid())
2843
113
        continue;
2844
113
      input->seek(shape.m_entries[w].begin(), librevenge::RVNG_SEEK_SET);
2845
113
      std::shared_ptr<MWAWPict> pict(MWAWPictData::get(input, int(shape.m_entries[w].length())));
2846
113
      MWAWEmbeddedObject image;
2847
113
      if (pict && pict->getBinary(image) && !image.m_dataList.empty()) {
2848
0
        object.add(image.m_dataList[0], !image.m_typeList.empty() ? image.m_typeList[0] : "image/pict");
2849
#ifdef DEBUG_WITH_FILES
2850
        static int volatile pictName = 0;
2851
        libmwaw::DebugStream f2;
2852
        f2 << "PICT-" << ++pictName << ".pct";
2853
        libmwaw::Debug::dumpFile(object.m_dataList[0], f2.str().c_str());
2854
        m_parser.ascii().skipZone(shape.m_entries[w].begin(), shape.m_entries[w].end()-1);
2855
#endif
2856
0
      }
2857
113
      else {
2858
113
        MWAW_DEBUG_MSG(("ReadySetGoGraph::send: sorry, can not retrieve a picture\n"));
2859
113
      }
2860
113
    }
2861
113
    if (!object.isEmpty())
2862
0
      listener->insertPicture(pos, object);
2863
113
    return true;
2864
114
  }
2865
0
  case ReadySetGoGraphInternal::Shape::T_Unknown:
2866
0
  default:
2867
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::send: sorry sending a shape with type=%d is not implemented\n", int(shape.m_type)));
2868
0
    return false;
2869
141
  }
2870
3
  if (shape.m_rotate) {
2871
0
    gShape=gShape.rotate(float(shape.m_rotate)/10, shape.m_box.center());
2872
0
    auto box=gShape.getBdBox(shape.m_style);
2873
0
    pos.setOrigin(box[0]);
2874
0
    pos.setSize(box.size());
2875
0
  }
2876
3
  if (shape.m_style.m_flip[0]) {
2877
0
    gShape.scale(MWAWVec2f(-1,1));
2878
0
    pos.setOrigin(pos.origin()+MWAWVec2f(pos.size()[0],0));
2879
0
  }
2880
3
  if (shape.m_style.m_flip[1]) {
2881
0
    gShape.scale(MWAWVec2f(1, -1));
2882
0
    pos.setOrigin(pos.origin()+MWAWVec2f(0,pos.size()[1]));
2883
0
  }
2884
3
  listener->insertShape(pos, gShape, shape.m_style);
2885
3
  return true;
2886
141
}
2887
2888
bool ReadySetGoGraph::sendText(ReadySetGoGraphInternal::Shape const &shape)
2889
10
{
2890
10
  auto input=m_parser.getInput();
2891
10
  auto listener=m_parser.getGraphicListener();
2892
10
  int const vers=version();
2893
10
  bool const isDesign=m_parser.isDesignStudioFile();
2894
10
  if (!input || !listener) {
2895
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: can not find the listener\n"));
2896
0
    return false;
2897
0
  }
2898
10
  if (shape.m_type!=shape.T_Text) {
2899
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: unexpected type\n"));
2900
0
    return false;
2901
0
  }
2902
10
  if (!shape.m_entries[0].valid() || shape.m_entries[0].length()<4 || !input->checkPosition(shape.m_entries[0].end())) {
2903
10
    if (shape.m_linkIds[0]<0) {
2904
10
      MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: can not find the character zone\n"));
2905
10
      return false;
2906
10
    }
2907
0
    return true;
2908
10
  }
2909
0
  input->seek(shape.m_entries[0].begin(), librevenge::RVNG_SEEK_SET);
2910
0
  libmwaw::DebugFile &ascFile = m_parser.ascii();
2911
0
  libmwaw::DebugStream f;
2912
0
  int const lengthSize=vers<3 ? 2 : 4;
2913
0
  int len=int(input->readULong(lengthSize));
2914
0
  long begTextPos=shape.m_entries[0].begin()+(vers<3 ? 2 : vers<6 ? 20 : 58);
2915
0
  if (len+(vers<3 ? 2*lengthSize : vers<6 ? 20 : 58)>shape.m_entries[0].length()) {
2916
0
    MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: can not find the character zone\n"));
2917
0
    f << "###";
2918
0
    ascFile.addPos(shape.m_entries[0].begin());
2919
0
    ascFile.addNote("Text-text:###");
2920
0
    return false;
2921
0
  }
2922
2923
0
  int minCPos=0, maxCPos=len;
2924
2925
  // first try to read the pararagraph style: v1-v2 or the list of style v3
2926
0
  auto fontConverter=m_parser.getFontConverter();
2927
0
  std::map<int, MWAWFont> posToFont;
2928
0
  std::map<int, MWAWParagraph> posToPara;
2929
0
  std::map<int, std::vector<MWAWTabStop> > posToTabs;
2930
0
  if (vers<3) {
2931
0
    MWAWParagraph para=shape.m_paragraph;
2932
0
    if (!shape.m_entries[1].valid() || shape.m_entries[1].length()!=0x1e || !input->checkPosition(shape.m_entries[1].end())) {
2933
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: can not find the paragraph zone\n"));
2934
0
    }
2935
0
    else {
2936
0
      input->seek(shape.m_entries[1].begin(), librevenge::RVNG_SEEK_SET);
2937
0
      long pos=input->tell();
2938
0
      f.str("");
2939
      // unsure the first line's style is sometimes different than the
2940
      // other lines', but the interface is so weird that it is
2941
      // difficult to understand what happens
2942
0
      for (int i=0; i<2; ++i) { // left and right margins from left,
2943
0
        int val=int(input->readLong(2));
2944
0
        if (val) f << "margins[" << (i==0 ? "left" : "right") << "]=" << val << ",";
2945
0
      }
2946
0
      int val=int(input->readLong(1));
2947
0
      switch (val & 3) {
2948
0
      case 1:
2949
0
        para.m_justify = MWAWParagraph::JustificationCenter;
2950
0
        break;
2951
0
      case 2:
2952
0
        para.m_justify = MWAWParagraph::JustificationRight;
2953
0
        break;
2954
0
      case 3:
2955
0
        para.m_justify = MWAWParagraph::JustificationFull;
2956
0
        break;
2957
0
      case 0: // left
2958
0
      default:
2959
0
        break;
2960
0
      }
2961
0
      if (val&0xfc) f << "fl=" << std::hex << (val&0xfc) << std::dec << ",";
2962
0
      int interline=0;
2963
0
      for (int i=0; i<3; ++i) { // small number maybe another justification
2964
0
        val=int(input->readLong(1));
2965
0
        if (!val) continue;
2966
0
        if ((i==0 && vers==1) || (i==2 && vers==2))
2967
0
          interline=val;
2968
0
        else
2969
0
          f << "f" << i << "=" << val << ",";
2970
0
      }
2971
0
      switch (interline) {
2972
0
      case 0: // normal
2973
0
      case 1:
2974
0
      case 2:
2975
0
        para.setInterline(1+double(interline)/2, librevenge::RVNG_PERCENT);
2976
0
        break;
2977
0
      default:
2978
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: unknown interline\n"));
2979
0
        f << "interline=###" << interline << ",";
2980
0
        break;
2981
0
      }
2982
0
      int dim[4];
2983
0
      for (auto &d : dim) d=int(input->readLong(2));
2984
0
      f << "box?=" << MWAWBox2i(MWAWVec2i(dim[0],dim[1]),MWAWVec2i(dim[2],dim[3])) << ",";
2985
0
      f << para;
2986
0
      ascFile.addDelimiter(input->tell(),'|');
2987
0
      ascFile.addPos(pos-lengthSize);
2988
0
      ascFile.addNote(f.str().c_str());
2989
0
    }
2990
0
    listener->setParagraph(para);
2991
2992
    // now read the list of char style
2993
0
    input->seek(shape.m_entries[0].begin()+lengthSize+len+(len%2), librevenge::RVNG_SEEK_SET);
2994
0
    long pos=input->tell();
2995
0
    int cLen=int(input->readULong(lengthSize));
2996
0
    f.str("");
2997
0
    f << "Text-font:";
2998
0
    if (pos+2+cLen>shape.m_entries[0].end() || (cLen%6)) {
2999
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: can not find the find the number of fonts\n"));
3000
0
      f << "###";
3001
0
      cLen=0;
3002
0
    }
3003
0
    ascFile.addPos(pos);
3004
0
    ascFile.addNote(f.str().c_str());
3005
0
    for (int s=0; s<(cLen/6); ++s) {
3006
0
      pos=input->tell();
3007
0
      f.str("");
3008
0
      f << "Text-font" << s << ":";
3009
0
      int cPos=int(input->readULong(2));
3010
0
      if (cPos) f << "pos=" << cPos << ",";
3011
0
      MWAWFont font;
3012
0
      font.setSize(float(input->readULong(1)));
3013
0
      uint32_t flags=0;
3014
0
      int val=int(input->readULong(1));
3015
0
      if (val&0x1) flags |= MWAWFont::boldBit;
3016
0
      if (val&0x2) flags |= MWAWFont::italicBit;
3017
0
      if (val&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple);
3018
0
      if (val&0x8) flags |= MWAWFont::embossBit;
3019
0
      if (val&0x10) flags |= MWAWFont::shadowBit;
3020
0
      if (val&0xe0) f << "fl=#" << std::hex << (val&0xe0) << std::dec << ",";
3021
0
      font.setFlags(flags);
3022
0
      font.setId(int(input->readULong(2)));
3023
0
      f << font.getDebugString(fontConverter)  << ",";
3024
0
      if (posToFont.find(cPos)==posToFont.end())
3025
0
        posToFont[cPos]=font;
3026
0
      else {
3027
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: find duplicated position for font's style\n"));
3028
0
        f << "###";
3029
0
      }
3030
0
      ascFile.addPos(pos);
3031
0
      ascFile.addNote(f.str().c_str());
3032
0
      input->seek(pos+6, librevenge::RVNG_SEEK_SET);
3033
0
    }
3034
3035
3036
0
  }
3037
0
  else {
3038
0
    if (shape.m_entries[2].valid() && shape.m_entries[2].length()>2) {
3039
0
      input->seek(shape.m_entries[2].begin(), librevenge::RVNG_SEEK_SET);
3040
3041
0
      int numPara=1;
3042
0
      if (vers>3) {
3043
0
        f.str("");
3044
0
        numPara=int(input->readLong(2));
3045
0
        f << "N=" << numPara << ",";
3046
0
        if (2+(isDesign ? 218 : 148)*numPara>shape.m_entries[2].length()) {
3047
0
          MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: can not determine the number of differents tabulation\n"));
3048
0
          f << "###";
3049
0
          numPara=0;
3050
0
        }
3051
0
        ascFile.addPos(shape.m_entries[2].begin()-4);
3052
0
        ascFile.addNote(f.str().c_str());
3053
0
      }
3054
3055
0
      for (int p=0; p<numPara; ++p) {
3056
0
        int cPos=0;
3057
0
        std::vector<MWAWTabStop> tabs;
3058
0
        if (!m_styleManager->readTabulations(tabs, vers==3 ? shape.m_entries[2].length() : (isDesign ? 218 : 148), vers==3 ? nullptr : &cPos))
3059
0
          break;
3060
0
        posToTabs[cPos]=tabs;
3061
0
      }
3062
0
    }
3063
3064
0
    if (!shape.m_entries[1].valid() || shape.m_entries[1].length()<4 || !input->checkPosition(shape.m_entries[1].end())) {
3065
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: can not find the style zone\n"));
3066
0
    }
3067
0
    else {
3068
0
      input->seek(shape.m_entries[1].begin(), librevenge::RVNG_SEEK_SET);
3069
0
      f.str("");
3070
0
      int N=int(input->readLong(4));
3071
0
      f << "N=" << N << ",";
3072
0
      int const dataSize=vers==3 ? 26 : vers==4 ? 26 : vers==5 ? 34 : vers==6 ? 44 : 50;
3073
0
      if (N<0 || (shape.m_entries[1].length()-4)/dataSize<N || 4+N*dataSize>shape.m_entries[1].length()) {
3074
0
        f << "###";
3075
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: can not find the number of styles\n"));
3076
0
        N=0;
3077
0
      }
3078
0
      ascFile.addPos(shape.m_entries[1].begin()-4);
3079
0
      ascFile.addNote(f.str().c_str());
3080
0
      for (int s=0; s<N; ++s) {
3081
0
        int cPos;
3082
0
        MWAWFont font;
3083
0
        MWAWParagraph para;
3084
0
        if (!m_styleManager->readStyle(font,para, &cPos))
3085
0
          break;
3086
0
        if (vers>6)
3087
0
          input->seek(6, librevenge::RVNG_SEEK_CUR);
3088
        // the position can be sometimes dupplicated, so use the latter
3089
0
        posToFont[cPos]=font;
3090
0
        posToPara[cPos]=para;
3091
0
      }
3092
0
    }
3093
0
    if (shape.m_entries[0].valid() && shape.m_entries[0].length()>=20) {
3094
0
      input->seek(shape.m_entries[0].begin()+4, librevenge::RVNG_SEEK_SET);
3095
0
      f.str("");
3096
0
      f << "N=" << len << ",";
3097
0
      for (int i=0; i<2; ++i) { // probably the selection
3098
0
        int val=int(input->readLong(4));
3099
0
        if (val!=len)
3100
0
          f << "N" << i+1 << "=" << val << ",";
3101
0
      }
3102
0
      f << "IDS=[";
3103
0
      for (int i=0; i<2; ++i) {
3104
0
        auto val=input->readULong(4);
3105
0
        if (val)
3106
0
          f << std::hex << val << std::dec << ",";
3107
0
        else
3108
0
          f << "_,";
3109
0
      }
3110
0
      f << "],";
3111
0
      ascFile.addPos(shape.m_entries[0].begin());
3112
0
      ascFile.addNote(f.str().c_str());
3113
0
    }
3114
0
    if (vers>3) {
3115
      // time to use the text limit
3116
0
      if (shape.m_textPositions[0]<0 || shape.m_textPositions[0]>len) {
3117
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: the minimum position seems bad\n"));
3118
0
      }
3119
0
      else
3120
0
        minCPos=shape.m_textPositions[0];
3121
0
      if (shape.m_textPositions[1]<minCPos || shape.m_textPositions[1]>len) {
3122
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: the maximum position seems bad\n"));
3123
0
      }
3124
      // min=max=0 means all data
3125
      // if there is not a next frame, we do not want to cut the text
3126
0
      else if (shape.m_textPositions[1]>0 && shape.m_textPositions[1]+1<len && shape.m_linkIds[1]>=0)
3127
0
        maxCPos=shape.m_textPositions[1]+1;
3128
0
    }
3129
0
  }
3130
3131
0
  f.str("");
3132
0
  f << "Text-text:";
3133
0
  input->seek(begTextPos+minCPos, librevenge::RVNG_SEEK_SET);
3134
0
  std::vector<MWAWTabStop> tabs;
3135
0
  MWAWParagraph para;
3136
0
  if (minCPos!=0) {
3137
    // we need to retrieve the current style
3138
0
    auto tIt=posToTabs.lower_bound(minCPos);
3139
0
    if (tIt!=posToTabs.begin()) {
3140
0
      --tIt;
3141
0
      tabs=tIt->second;
3142
0
      para.m_tabs=tabs;
3143
0
      listener->setParagraph(para);
3144
0
    }
3145
0
    auto pIt=posToPara.lower_bound(minCPos);
3146
0
    if (pIt!=posToPara.begin()) {
3147
0
      --pIt;
3148
0
      para=pIt->second;
3149
0
      para.m_tabs=tabs;
3150
0
      listener->setParagraph(para);
3151
0
    }
3152
0
    auto fIt=posToFont.lower_bound(minCPos);
3153
0
    if (fIt!=posToFont.begin()) {
3154
0
      --fIt;
3155
0
      listener->setFont(fIt->second);
3156
0
    }
3157
0
  }
3158
0
  for (int c=minCPos; c<maxCPos; ++c) {
3159
0
    auto tIt=posToTabs.find(c);
3160
0
    if (tIt!=posToTabs.end()) {
3161
0
      tabs=tIt->second;
3162
0
      para.m_tabs=tabs;
3163
0
      listener->setParagraph(para);
3164
0
    }
3165
0
    auto pIt=posToPara.find(c);
3166
0
    if (pIt!=posToPara.end()) {
3167
0
      para=pIt->second;
3168
0
      para.m_tabs=tabs;
3169
0
      listener->setParagraph(para);
3170
0
    }
3171
0
    auto fIt=posToFont.find(c);
3172
0
    if (fIt!=posToFont.end())
3173
0
      listener->setFont(fIt->second);
3174
0
    if (input->isEnd()) {
3175
0
      MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: find end of input at pos=%d\n", c));
3176
0
      f << "###";
3177
0
      break;
3178
0
    }
3179
0
    unsigned char ch=(unsigned char)(input->readULong(1));
3180
0
    if (ch)
3181
0
      f << ch;
3182
0
    else
3183
0
      f << "[#page]";
3184
0
    switch (ch) {
3185
0
    case 0:
3186
0
      listener->insertField(MWAWField(MWAWField::PageNumber));
3187
0
      break;
3188
0
    case 5:
3189
0
      listener->insertField(MWAWField(MWAWField::PageCount));
3190
0
      break;
3191
0
    case 0x9:
3192
0
      listener->insertTab();
3193
0
      break;
3194
    // case 0xb: column break, useme
3195
0
    case 0xd:
3196
0
      listener->insertEOL();
3197
0
      break;
3198
0
    case 0x1f: // soft hyphen
3199
0
      break;
3200
0
    default:
3201
0
      if (ch<=0x1f) {
3202
0
        MWAW_DEBUG_MSG(("ReadySetGoGraph::sendText: find unknown char=%d at pos=%d\n", int(ch), c));
3203
0
        f << "###";
3204
0
        break;
3205
0
      }
3206
0
      listener->insertCharacter(ch);
3207
0
    }
3208
0
  }
3209
0
  ascFile.addPos(shape.m_entries[0].begin());
3210
0
  ascFile.addNote(f.str().c_str());
3211
0
  return true;
3212
0
}
3213
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: