Coverage Report

Created: 2026-03-12 06:42

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