1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* This file is part of the libsw602 project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDED_SW602_GRAPHIC_STYLE_H
#define INCLUDED_SW602_GRAPHIC_STYLE_H
#include <ostream>
#include <string>
#include <vector>
#include "librevenge/librevenge.h"
#include "SW602Types.h"
namespace libsw602
{
/** a structure used to define a picture style
\note in order to define the internal surface style, first it looks for
a gradient, if so it uses it. Then it looks for a pattern. Finally if
it found nothing, it uses surfaceColor and surfaceOpacity.*/
class SW602GraphicStyle
{
public:
//! an enum used to define the basic line cap
enum LineCap { C_Butt, C_Square, C_Round };
//! an enum used to define the basic line join
enum LineJoin { J_Miter, J_Round, J_Bevel };
//! an enum used to define the gradient type
enum GradientType { G_None, G_Axial, G_Linear, G_Radial, G_Rectangular, G_Square, G_Ellipsoid };
//! a structure used to define an arrow
struct Arrow
{
//! constructor ( no arrow)
Arrow() : m_width(0), m_viewBox(), m_path(""), m_isCentered(false)
{
}
//! constructor
Arrow(float w, SW602Box2i const &box, std::string path, bool centered=false) :
m_width(w), m_viewBox(box), m_path(path), m_isCentered(centered)
{
}
//! returns a basic plain arrow
static Arrow plain()
{
return Arrow(5, SW602Box2i(SW602Vec2i(0,0),SW602Vec2i(20,30)), "m10 0-10 30h20z", false);
}
//! operator<<
friend std::ostream &operator<<(std::ostream &o, Arrow const &arrow)
{
if (arrow.isEmpty()) return o;
o << "w=" << arrow.m_width << ",";
o << "viewbox=" << arrow.m_viewBox << ",";
o << "path=" << arrow.m_path << ",";
if (arrow.m_isCentered) o << "centered,";
return o;
}
//! operator==
bool operator==(Arrow const &arrow) const
{
return m_width>=arrow.m_width && m_width<=arrow.m_width &&
m_viewBox==arrow.m_viewBox && m_path==arrow.m_path && m_isCentered==arrow.m_isCentered;
}
//! operator!=
bool operator!=(Arrow const &arrow) const
{
return !(*this==arrow);
}
//! operator<
bool operator<(Arrow const &arrow) const
{
if (m_isCentered<arrow.m_isCentered) return m_isCentered ? true : false;
return m_width<arrow.m_width && m_viewBox<arrow.m_viewBox && m_path < arrow.m_path;
}
//! operator<=
bool operator<=(Arrow const &arrow) const
{
return *this<arrow || *this==arrow;
}
//! operator>
bool operator>(Arrow const &arrow) const
{
return !(*this<=arrow);
}
//! operator>=
bool operator>=(Arrow const &arrow) const
{
return !(*this<arrow);
}
//! returns true if there is no arrow
bool isEmpty() const
{
return m_width<=0 || m_path.empty();
}
//! add a arrow to the propList knowing the type (start, end)
void addTo(librevenge::RVNGPropertyList &propList, std::string const &type) const;
//! the arrow width in point
float m_width;
//! the arrow viewbox
SW602Box2i m_viewBox;
//! the arrow path
std::string m_path;
//! flag to know if the arrow is centered
bool m_isCentered;
};
//! a structure used to define the gradient limit in SW602GraphicStyle
struct GradientStop
{
//! constructor
GradientStop(float offset=0.0, SW602Color const &col=SW602Color::black(), float opacity=1.0) :
m_offset(offset), m_color(col), m_opacity(opacity)
{
}
/** compare two gradient */
int cmp(GradientStop const &a) const
{
if (m_offset < a.m_offset) return -1;
if (m_offset > a.m_offset) return 1;
if (m_color < a.m_color) return -1;
if (m_color > a.m_color) return 1;
if (m_opacity < a.m_opacity) return -1;
if (m_opacity > a.m_opacity) return 1;
return 0;
}
//! a print operator
friend std::ostream &operator<<(std::ostream &o, GradientStop const &st)
{
o << "offset=" << st.m_offset << ",";
o << "color=" << st.m_color << ",";
if (st.m_opacity<1.0)
o << "opacity=" << st.m_opacity*100.f << "%,";
return o;
}
//! the offset
float m_offset;
//! the color
SW602Color m_color;
//! the opacity
float m_opacity;
};
/** a basic pattern used in a SW602GraphicStyle:
- either given a list of 8x8, 16x16, 32x32 bytes with two colors
- or with a picture ( and an average color)
*/
struct Pattern
{
//! constructor
Pattern() : m_dim(0,0), m_data(), m_picture(), m_pictureAverageColor(SW602Color::white())
{
m_colors[0]=SW602Color::black();
m_colors[1]=SW602Color::white();
}
//! constructor from a binary data
Pattern(SW602Vec2i dim, SW602EmbeddedObject const &picture, SW602Color const &avColor) :
m_dim(dim), m_data(), m_picture(picture), m_pictureAverageColor(avColor)
{
m_colors[0]=SW602Color::black();
m_colors[1]=SW602Color::white();
}
//! virtual destructor
virtual ~Pattern() {}
//! return true if we does not have a pattern
bool empty() const
{
if (m_dim[0]==0 || m_dim[1]==0) return true;
if (!m_picture.m_dataList.empty()) return false;
if (m_dim[0]!=8 && m_dim[0]!=16 && m_dim[0]!=32) return true;
return m_data.size()!=size_t((m_dim[0]/8)*m_dim[1]);
}
//! return the average color
bool getAverageColor(SW602Color &col) const;
//! check if the pattern has only one color; if so returns true...
bool getUniqueColor(SW602Color &col) const;
/** tries to convert the picture in a binary data ( ppm) */
bool getBinary(SW602EmbeddedObject &picture) const;
/** compare two patterns */
int cmp(Pattern const &a) const
{
int diff = m_dim.cmp(a.m_dim);
if (diff) return diff;
if (m_data.size() < a.m_data.size()) return -1;
if (m_data.size() > a.m_data.size()) return 1;
for (size_t h=0; h < m_data.size(); ++h)
{
if (m_data[h]<a.m_data[h]) return 1;
if (m_data[h]>a.m_data[h]) return -1;
}
for (int i=0; i<2; ++i)
{
if (m_colors[i] < a.m_colors[i]) return 1;
if (m_colors[i] > a.m_colors[i]) return -1;
}
if (m_pictureAverageColor < a.m_pictureAverageColor) return 1;
if (m_pictureAverageColor > a.m_pictureAverageColor) return -1;
diff=m_picture.cmp(a.m_picture);
if (diff) return diff;
return 0;
}
//! a print operator
friend std::ostream &operator<<(std::ostream &o, Pattern const &pat)
{
o << "dim=" << pat.m_dim << ",";
if (!pat.m_picture.isEmpty())
{
o << "pict=" << pat.m_picture << ",";
o << "col[average]=" << pat.m_pictureAverageColor << ",";
}
else
{
if (!pat.m_colors[0].isBlack()) o << "col0=" << pat.m_colors[0] << ",";
if (!pat.m_colors[1].isWhite()) o << "col1=" << pat.m_colors[1] << ",";
o << "[";
for (size_t h=0; h < pat.m_data.size(); ++h)
o << std::hex << (int) pat.m_data[h] << std::dec << ",";
o << "],";
}
return o;
}
//! the dimension width x height
SW602Vec2i m_dim;
//! the two indexed colors
SW602Color m_colors[2];
//! the pattern data: a sequence of data: p[0..7,0],p[8..15,0]...p[0..7,1],p[8..15,1], ...
std::vector<unsigned char> m_data;
protected:
//! a picture
SW602EmbeddedObject m_picture;
//! the picture average color
SW602Color m_pictureAverageColor;
};
//! constructor
SW602GraphicStyle() : m_lineWidth(1), m_lineDashWidth(), m_lineCap(C_Butt), m_lineJoin(J_Miter), m_lineOpacity(1), m_lineColor(SW602Color::black()),
m_fillRuleEvenOdd(false), m_surfaceColor(SW602Color::white()), m_surfaceOpacity(0),
m_shadowColor(SW602Color::black()), m_shadowOpacity(0), m_shadowOffset(1,1),
m_pattern(),
m_gradientType(G_None), m_gradientStopList(), m_gradientAngle(0), m_gradientBorder(0), m_gradientPercentCenter(0.5f,0.5f), m_gradientRadius(1),
m_backgroundColor(SW602Color::white()), m_backgroundOpacity(-1), m_bordersList(), m_frameName(""), m_frameNextName(""),
m_rotate(0), m_extra("")
{
m_arrows[0]=m_arrows[1]=Arrow();
m_flip[0]=m_flip[1]=false;
m_gradientStopList.push_back(GradientStop(0.0, SW602Color::white()));
m_gradientStopList.push_back(GradientStop(1.0, SW602Color::black()));
}
/** returns an empty style. Can be used to initialize a default frame style...*/
static SW602GraphicStyle emptyStyle()
{
SW602GraphicStyle res;
res.m_lineWidth=0;
return res;
}
//! virtual destructor
virtual ~SW602GraphicStyle() { }
//! returns true if the border is defined
bool hasLine() const
{
return m_lineWidth>0 && m_lineOpacity>0;
}
//! set the surface color
void setSurfaceColor(SW602Color const &col, float opacity = 1)
{
m_surfaceColor = col;
m_surfaceOpacity = opacity;
}
//! returns true if the surface is defined
bool hasSurfaceColor() const
{
return m_surfaceOpacity > 0;
}
//! set the pattern
void setPattern(Pattern const &pat, float opacity = 1)
{
m_pattern=pat;
m_surfaceOpacity = opacity;
}
//! returns true if the pattern is defined
bool hasPattern() const
{
return !m_pattern.empty() && m_surfaceOpacity > 0;
}
//! returns true if the gradient is defined
bool hasGradient(bool complex=false) const
{
return m_gradientType != G_None && (int) m_gradientStopList.size() >= (complex ? 3 : 2);
}
//! returns true if the interior surface is defined
bool hasSurface() const
{
return hasSurfaceColor() || hasPattern() || hasGradient();
}
//! set the background color
void setBackgroundColor(SW602Color const &col, float opacity = 1)
{
m_backgroundColor = col;
m_backgroundOpacity = opacity;
}
//! returns true if the background is defined
bool hasBackgroundColor() const
{
return m_backgroundOpacity > 0;
}
//! set the shadow color
void setShadowColor(SW602Color const &col, float opacity = 1)
{
m_shadowColor = col;
m_shadowOpacity = opacity;
}
//! returns true if the shadow is defined
bool hasShadow() const
{
return m_shadowOpacity > 0;
}
//! return true if the frame has some border
bool hasBorders() const
{
return !m_bordersList.empty();
}
//! return true if the frame has some border
bool hasSameBorders() const
{
if (m_bordersList.empty()) return true;
if (m_bordersList.size()!=4) return false;
for (size_t i=1; i<m_bordersList.size(); ++i)
{
if (m_bordersList[i]!=m_bordersList[0])
return false;
}
return true;
}
//! return the frame border: libsw602::Left | ...
std::vector<SW602Border> const &borders() const
{
return m_bordersList;
}
//! reset the border
void resetBorders()
{
m_bordersList.resize(0);
}
//! sets the cell border: wh=libsw602::LeftBit|...
void setBorders(int wh, SW602Border const &border);
//! a print operator
friend std::ostream &operator<<(std::ostream &o, SW602GraphicStyle const &st);
//! add all the parameters to the propList excepted the frame parameter: the background and the borders
void addTo(librevenge::RVNGPropertyList &pList, bool only1d=false) const;
//! add all the frame parameters to propList: the background and the borders
void addFrameTo(librevenge::RVNGPropertyList &pList) const;
/** compare two styles */
int cmp(SW602GraphicStyle const &a) const;
//! the linewidth
float m_lineWidth;
//! the dash array: a sequence of (fullsize, emptysize)
std::vector<float> m_lineDashWidth;
//! the line cap
LineCap m_lineCap;
//! the line join
LineJoin m_lineJoin;
//! the line opacity: 0=transparent
float m_lineOpacity;
//! the line color
SW602Color m_lineColor;
//! true if the fill rule is evenod
bool m_fillRuleEvenOdd;
//! the surface color
SW602Color m_surfaceColor;
//! true if the surface has some color
float m_surfaceOpacity;
//! the shadow color
SW602Color m_shadowColor;
//! true if the shadow has some color
float m_shadowOpacity;
//! the shadow offset
SW602Vec2f m_shadowOffset;
//! the pattern if it exists
Pattern m_pattern;
//! the gradient type
GradientType m_gradientType;
//! the list of gradient limits
std::vector<GradientStop> m_gradientStopList;
//! the gradient angle
float m_gradientAngle;
//! the gradient border opacity
float m_gradientBorder;
//! the gradient center
SW602Vec2f m_gradientPercentCenter;
//! the gradient radius
float m_gradientRadius;
//! the two arrows corresponding to start and end extremity
Arrow m_arrows[2];
//
// related to the frame
//
//! the background color
SW602Color m_backgroundColor;
//! true if the background has some color
float m_backgroundOpacity;
//! the borders SW602Border::Pos (for a frame)
std::vector<SW602Border> m_bordersList;
//! the frame name
std::string m_frameName;
//! the frame next name (if there is a link)
std::string m_frameNextName;
//
// some transformation: must probably be somewhere else
//
//! the rotation
float m_rotate;
//! two bool to indicated we need to flip the shape or not
bool m_flip[2];
//! extra data
std::string m_extra;
};
}
#endif
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|