~ubuntu-branches/ubuntu/precise/ipe/precise

« back to all changes in this revision

Viewing changes to src/ipelib/ipecolor.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve M. Robbins
  • Date: 2009-12-11 21:22:35 UTC
  • mfrom: (4.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20091211212235-5iio4nzpra64snab
Tags: 7.0.10-1
* New upstream.  Closes: #551192.
  - New build-depends: libcairo2-dev, liblua5.1-0-dev, gsfonts
  - patches/config.diff: Remove.  Upstream build system replaced.
  - Runtime lib package changed to libipe7.0.10 from libipe1c2a
  - Devel package renamed to libipe-dev (from libipe1-dev)
  - Package ipe depends on lua5.1 due to ipe-update-master.

* rules: Re-write to use dh.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// -*- C++ -*-
2
 
// --------------------------------------------------------------------
3
 
// Ipe object attributes (not just color!)
4
 
// --------------------------------------------------------------------
5
 
/*
6
 
 
7
 
    This file is part of the extensible drawing editor Ipe.
8
 
    Copyright (C) 1993-2007  Otfried Cheong
9
 
 
10
 
    Ipe is free software; you can redistribute it and/or modify it
11
 
    under the terms of the GNU General Public License as published by
12
 
    the Free Software Foundation; either version 2 of the License, or
13
 
    (at your option) any later version.
14
 
 
15
 
    As a special exception, you have permission to link Ipe with the
16
 
    CGAL library and distribute executables, as long as you follow the
17
 
    requirements of the Gnu General Public License in regard to all of
18
 
    the software in the executable aside from CGAL.
19
 
 
20
 
    Ipe is distributed in the hope that it will be useful, but WITHOUT
21
 
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22
 
    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
23
 
    License for more details.
24
 
 
25
 
    You should have received a copy of the GNU General Public License
26
 
    along with Ipe; if not, you can find it at
27
 
    "http://www.gnu.org/copyleft/gpl.html", or write to the Free
28
 
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29
 
 
30
 
*/
31
 
 
32
 
#include "ipecolor.h"
33
 
 
34
 
// --------------------------------------------------------------------
35
 
 
36
 
/*! \defgroup attr Ipe Attributes
37
 
  \brief Attributes for Ipe objects.
38
 
 
39
 
  To make the representation of IpeObjects reasonably compact, Ipe
40
 
  objects store attribute values as an index into an IpeRepository.
41
 
  IpeAttribute encapsulates this index.
42
 
*/
43
 
 
44
 
/*! \class IpeDashStyle
45
 
  \ingroup attr
46
 
  \brief An absolute dash style.
47
 
*/
48
 
 
49
 
/*! \class IpeStrokeStyle
50
 
  \ingroup attr
51
 
  \brief Encapsulates line join, line cap, and eofill vs windfill rule.
52
 
 
53
 
  This class encapsulates three IpeAttributes in the space of one \c int.
54
 
*/
55
 
 
56
 
/* Bit layout:
57
 
   0x1000 join set in 0x0003
58
 
   0x2000 cap set in 0x000c
59
 
   0x4000 wind set in 0x0010
60
 
 */
61
 
 
62
 
IpeAttribute IpeStrokeStyle::Join() const
63
 
{
64
 
  if (iBits & 0x1000)
65
 
    return IpeAttribute(IpeAttribute::ELineJoin, false, iBits & 3);
66
 
  return IpeAttribute();
67
 
}
68
 
 
69
 
IpeAttribute IpeStrokeStyle::Cap() const
70
 
{
71
 
  if (iBits & 0x2000)
72
 
    return IpeAttribute(IpeAttribute::ELineCap, false, (iBits & 0x0c) >> 2);
73
 
  return IpeAttribute();
74
 
}
75
 
 
76
 
IpeAttribute IpeStrokeStyle::WindRule() const
77
 
{
78
 
  if (iBits & 0x4000)
79
 
    return IpeAttribute(IpeAttribute::EWindRule, false, (iBits & 0x10) >> 4);
80
 
  return IpeAttribute();
81
 
}
82
 
 
83
 
//! Set line join.
84
 
/*! If \a val < 0 or \a val > 2, set to default. */
85
 
void IpeStrokeStyle::SetJoin(int val)
86
 
{
87
 
  if (0 <= val && val <= 2) {
88
 
    iBits &= ~0x03;
89
 
    iBits |= val + 0x1000;
90
 
  } else
91
 
    iBits &= ~0x1003;
92
 
}
93
 
 
94
 
//! Set line cap
95
 
/*! If \a val < 0 or \a val > 2, set to default. */
96
 
void IpeStrokeStyle::SetCap(int val)
97
 
{
98
 
  if (0 <= val && val <= 2) {
99
 
    iBits &= ~0x0c;
100
 
    iBits |= (val << 2) + 0x2000;
101
 
  } else
102
 
    iBits &= ~0x200c;
103
 
}
104
 
 
105
 
//! Set wind rule (0 = even-odd file, 1 = wind fill)
106
 
/*! If \a val < 0 or \a val > 1, set to default. */
107
 
void IpeStrokeStyle::SetWindRule(int val)
108
 
{
109
 
  if (0 <= val && val <= 1) {
110
 
    iBits &= ~0x10;
111
 
    iBits |= 0x4000;
112
 
    if (val)
113
 
      iBits |= 0x10;
114
 
  } else
115
 
    iBits &= ~0x4010;
116
 
}
117
 
 
118
 
//! Set join from attribute.
119
 
void IpeStrokeStyle::SetJoin(IpeAttribute val)
120
 
{
121
 
  if (val.IsNull())
122
 
    SetJoin(-1);
123
 
  else
124
 
    SetJoin(val.Index());
125
 
}
126
 
 
127
 
//! Set line cap from attribute.
128
 
void IpeStrokeStyle::SetCap(IpeAttribute val)
129
 
{
130
 
  if (val.IsNull())
131
 
    SetCap(-1);
132
 
  else
133
 
    SetCap(val.Index());
134
 
}
135
 
 
136
 
//! Set wind rule from attribute.
137
 
void IpeStrokeStyle::SetWindRule(IpeAttribute val)
138
 
{
139
 
  if (val.IsNull())
140
 
    SetWindRule(-1);
141
 
  else
142
 
    SetWindRule(val.Index());
143
 
}
144
 
 
145
 
// --------------------------------------------------------------------
146
 
 
147
 
/*! \class IpeAttribute
148
 
  \ingroup attr
149
 
  \brief An attribute of an Ipe object.
150
 
 
151
 
  An attribute is either null (i.e. not defined---it hasn't been set
152
 
  yet), or symbolic (a name that has to be looked up using an
153
 
  IpeStyleSheet), or an absolute value.
154
 
 
155
 
  A null value is used in higher levels of the hierarchy to defer the
156
 
  setting of the attribute to a lower level.  For example, if the pen
157
 
  width is set in an IpeGroup object, all its members have this
158
 
  uniform pen width.  To allow the members to have individual pen
159
 
  width, the IpeGroup must have a null pen width.
160
 
 
161
 
  To make the representation more compact, Ipe objects store attribute
162
 
  values as an index into an IpeRepository.  IpeAttribute encapsulates
163
 
  this index.  Its meaning is as follows:
164
 
 
165
 
   - 0 : a <b>null</b> argument, see below,
166
 
   - 1 : the void color or line style
167
 
   - 2 : the solid line style
168
 
   - 3 : the black color
169
 
   - 4 : the white color
170
 
   - if IsSymbolic: a symbolic name.
171
 
     Use IpeStyleSheet to map to an absolute value.
172
 
   - if IsNumeric: an absolute, numeric value.
173
 
     Use Number() to return the number, in the range 0.0 to 16777.215
174
 
     (with 3 digits fixed point precision).
175
 
   - if IsValue: an absolute value.
176
 
     Use IpeRepository to map to the absolute value.
177
 
 
178
 
  An attribute is absolute (IsAbsolute() returns true) if it is
179
 
  neither null nor symbolic.
180
 
 
181
 
  Furthermore, the attribute stores the type of attribute, such as
182
 
  scalar (a double value), color, dash style, etc.
183
 
 
184
 
  Note the difference between the null color, which means that the
185
 
  color has not yet been defined (it is left to lower-level objects),
186
 
  and the "void" color, which means that the object should not be
187
 
  filled.
188
 
 
189
 
  When rendering an object, a null color is interpreted as the void
190
 
  color. This allows leaf objects not to specify the void color.
191
 
 
192
 
  Note that it is impossible for style sheets to redefine the meaning
193
 
  of "black" and "white".  If a user needs a symbolic name that is
194
 
  black or white in some styles, she can always define another
195
 
  symbolic name, e.g. "Black" and "White".
196
 
 
197
 
  Note also the difference between null and "solid" (the special dash
198
 
  style of a solid line).  It is impossible for style sheets to
199
 
  redefine the meaning of "solid".
200
 
 
201
 
  When rendering an object, a null dash style is interpreted as solid.
202
 
 
203
 
*/
204
 
 
205
 
//! Return kind of attribute.
206
 
IpeKind IpeAttribute::Kind() const
207
 
{
208
 
  if (iName == 1 || iName == 3 || iName == 4)
209
 
    return EColor;
210
 
  if (iName == 2)
211
 
    return EDashStyle;
212
 
  return IpeKind((iName & EKindMask) >> EKindShift);
213
 
}
214
 
 
215
 
//! Create an attribute of given \a kind.
216
 
IpeAttribute::IpeAttribute(IpeKind kind, bool symbolic, int index)
217
 
{
218
 
  iName = index | (kind << EKindShift) | (symbolic ? ESymbolic : EValue);
219
 
}
220
 
 
221
 
//! Create an absolute numeric attribute.
222
 
IpeAttribute::IpeAttribute(IpeKind kind, IpeFixed value)
223
 
{
224
 
  iName = (kind << EKindShift) | EValue | ENumeric | value.Internal();
225
 
}
226
 
 
227
 
// --------------------------------------------------------------------
228
 
 
229
 
/*! \class IpeColor
230
 
  \ingroup attr
231
 
  \brief An absolute RGB color.
232
 
*/
233
 
 
234
 
//! Construct a color.
235
 
IpeColor::IpeColor(IpeScalar red, IpeScalar green, IpeScalar blue)
236
 
{
237
 
  iRed = red;
238
 
  iGreen = green;
239
 
  iBlue = blue;
240
 
}
241
 
 
242
 
//! Save to stream.
243
 
void IpeColor::Save(IpeStream &stream) const
244
 
{
245
 
  if (IsGray())
246
 
    stream << iRed;
247
 
  else
248
 
    stream << iRed << " " << iGreen << " " << iBlue;
249
 
}
250
 
 
251
 
//! Is it an absolute gray value?
252
 
bool IpeColor::IsGray() const
253
 
{
254
 
  return (iRed == iGreen && iRed == iBlue);
255
 
}
256
 
 
257
 
bool IpeColor::operator==(const IpeColor &rhs) const
258
 
{
259
 
  return (iRed == rhs.iRed) && (iGreen == rhs.iGreen) && (iBlue == rhs.iBlue);
260
 
}
261
 
 
262
 
// --------------------------------------------------------------------
263
 
 
264
 
/*! \class IpeRepository
265
 
  \ingroup attr
266
 
  \brief Repository of attribute values.
267
 
 
268
 
  Ipe documents can use symbolic attributes, such as 'normal', 'fat',
269
 
  or 'thin' for line thickness, or 'red', 'navy', 'turquoise' for
270
 
  color, as well as absolute attributes such as (0.5,0.5,0.5) for
271
 
  medium gray.  To avoid storing these very common values hundreds of
272
 
  times, IpeRepository keeps a repository of all the non-scalar
273
 
  attribute values in the document. Inside IpeObject's attributes are
274
 
  represented as integer indices into the repository.
275
 
 
276
 
  There are currently the following symbolic attributes with values
277
 
  stored in the repository.
278
 
  - Color
279
 
  - Line style (dash pattern)
280
 
  - Font size
281
 
  - Text style (Latex style)
282
 
 
283
 
  The following attributes can be symbolic, but if they are absolute
284
 
  then the scalar value is stored inside the IpeAttribute (not in the
285
 
  repository).
286
 
  - Mark size
287
 
  - Arrow size
288
 
  - Grid size
289
 
  - Angle size (for angular snap)
290
 
  - Line width
291
 
 
292
 
  Finally, line join, line cap, and the fill rule cannot be symbolic.
293
 
  They can be null, or have an absolute value stored inside the
294
 
  attribute.
295
 
*/
296
 
 
297
 
//! Constructor.
298
 
IpeRepository::IpeRepository()
299
 
{
300
 
  // ensure that string zero is 'normal'
301
 
  iStrings.push_back("normal");
302
 
  // ensure that symbolic dash styles 1 .. 4 are dashed, dotted, etc.
303
 
  iStrings.push_back("dashed");
304
 
  iStrings.push_back("dotted");
305
 
  iStrings.push_back("dash dotted");
306
 
  iStrings.push_back("dash dot dotted");
307
 
}
308
 
 
309
 
//! Return string with given index.
310
 
/*! Both symbolic and absolute values are possible. */
311
 
IpeString IpeRepository::ToString(IpeAttribute attr) const
312
 
{
313
 
  assert(attr.IsSymbolic() ||
314
 
         (attr.IsValue() &&
315
 
          (attr.Kind() == IpeAttribute::EDashStyle ||
316
 
           attr.Kind() == IpeAttribute::ETextStyle ||
317
 
           attr.Kind() == IpeAttribute::ETextSize)));
318
 
  return iStrings[attr.Index()];
319
 
}
320
 
 
321
 
//! Return color with given index
322
 
IpeColor IpeRepository::ToColor(IpeAttribute attr) const
323
 
{
324
 
  assert(attr.Kind() == IpeAttribute::EColor);
325
 
  if (attr.IsValue())
326
 
    return iColors[attr.Index()];
327
 
  if (attr.Index() == 3)
328
 
    return IpeColor(0.0, 0.0, 0.0);
329
 
  assert(attr.Index() == 4);
330
 
  return IpeColor(1.0, 1.0, 1.0);
331
 
}
332
 
 
333
 
//! Return value with given index.
334
 
IpeFixed IpeRepository::ToScalar(IpeAttribute attr) const
335
 
{
336
 
  assert(attr.Kind() < IpeAttribute::EDashStyle);
337
 
  assert(attr.IsNumeric());
338
 
  return attr.Number();
339
 
}
340
 
 
341
 
/*! Lookup a string (add it if it doesn't exist yet), and return
342
 
  symbolic attribute for it. */
343
 
IpeAttribute IpeRepository::ToSymbolic(IpeKind kind, IpeString name)
344
 
{
345
 
  assert(!name.empty());
346
 
  std::vector<IpeString>::const_iterator it =
347
 
    std::find(iStrings.begin(), iStrings.end(), name);
348
 
  if (it != iStrings.end())
349
 
    return IpeAttribute(kind, true, (it - iStrings.begin()));
350
 
  iStrings.push_back(name);
351
 
  return IpeAttribute(kind, true, iStrings.size() - 1);
352
 
}
353
 
 
354
 
//! Lookup a color (add it if it doesn't exist yet), and return index.
355
 
IpeAttribute IpeRepository::ToAttribute(const IpeColor &color)
356
 
{
357
 
  if (color == IpeColor(0.0, 0.0, 0.0))
358
 
    return IpeAttribute::Black();
359
 
  if (color == IpeColor(1.0, 1.0, 1.0))
360
 
    return IpeAttribute::White();
361
 
  std::vector<IpeColor>::const_iterator it =
362
 
    std::find(iColors.begin(), iColors.end(), color);
363
 
  if (it != iColors.end())
364
 
    return IpeAttribute(IpeAttribute::EColor, false, (it - iColors.begin()));
365
 
  iColors.push_back(color);
366
 
  return IpeAttribute(IpeAttribute::EColor, false, iColors.size() - 1);
367
 
}
368
 
 
369
 
//! Lookup \a value (add it if it doesn't exist yet), and return index.
370
 
IpeAttribute IpeRepository::ToAttribute(IpeKind kind, IpeFixed value)
371
 
{
372
 
  return IpeAttribute(kind, value);
373
 
}
374
 
 
375
 
//! Create an IpeAttribute representing the color described.
376
 
/*! Empty string creates null color, string starting with a letter
377
 
  creates a symbolic color (includes special case "void"), otherwise
378
 
  absolute color. */
379
 
IpeAttribute IpeRepository::MakeColor(IpeString str)
380
 
{
381
 
  if (str.empty()) {
382
 
    return IpeAttribute();
383
 
  } else if (str == "void") {
384
 
    return IpeAttribute::Void();
385
 
  } else if (str == "black") {
386
 
    return IpeAttribute::Black();
387
 
  } else if (str == "white") {
388
 
    return IpeAttribute::White();
389
 
  } else if (('a' <= str[0] && str[0] <= 'z') ||
390
 
             ('A' <= str[0] && str[0] <= 'Z')) {
391
 
    return ToSymbolic(IpeAttribute::EColor, str);
392
 
  } else {
393
 
    IpeLex st(str);
394
 
    IpeColor col;
395
 
    st >> col.iRed >> col.iGreen;
396
 
    if (st.Eos())
397
 
      col.iGreen = col.iBlue = col.iRed;
398
 
    else
399
 
      st >> col.iBlue;
400
 
    return ToAttribute(col);
401
 
  }
402
 
}
403
 
 
404
 
//! Construct dash style attribute from string.
405
 
/*! Empty string creates null value, string starting with '[' creates
406
 
  an absolute dash style, otherwise symbolic dash style (including the
407
 
  special case "solid").
408
 
*/
409
 
IpeAttribute IpeRepository::MakeDashStyle(IpeString str)
410
 
{
411
 
  if (str.empty()) {
412
 
    return IpeAttribute();
413
 
  } else if (str == "void") {
414
 
    return IpeAttribute::Void();
415
 
  } else if (str == "solid") {
416
 
    return IpeAttribute::Solid();
417
 
  } else if (str[0] == '[') {
418
 
    return MakeString(IpeAttribute::EDashStyle, str);
419
 
  } else
420
 
    return ToSymbolic(IpeAttribute::EDashStyle, str);
421
 
}
422
 
 
423
 
//! Construct text size attribute from string.
424
 
/*! Empty string creates null value, string starting with digit
425
 
  creates an numeric absolute value, string starting with letter
426
 
  creates symbolic text size, anything else creates absolute (string)
427
 
  text size.
428
 
*/
429
 
IpeAttribute IpeRepository::MakeTextSize(IpeString str)
430
 
{
431
 
  if (str.empty())
432
 
    return IpeAttribute();
433
 
  else if ('0' <= str[0] && str[0] <= '9')
434
 
    return IpeAttribute(IpeAttribute::ETextSize, IpeLex(str).GetFixed());
435
 
  else if (('a' <= str[0] && str[0] <= 'z') ||
436
 
           ('A' <= str[0] && str[0] <= 'Z'))
437
 
    return ToSymbolic(IpeAttribute::ETextSize, str);
438
 
  else
439
 
    return MakeString(IpeAttribute::ETextSize, str);
440
 
}
441
 
 
442
 
//! Construct absolute value (which is a string).
443
 
IpeAttribute IpeRepository::MakeString(IpeKind kind, IpeString str)
444
 
{
445
 
  if (str.empty())
446
 
    return IpeAttribute();
447
 
  int index = ToSymbolic(kind, str).Index();
448
 
  return IpeAttribute(kind, false, index);
449
 
}
450
 
 
451
 
//! Construct scalar attribute from string.
452
 
/*! Empty string creates null value, string starting with non-letter creates
453
 
  an absolute value, string starting with letter creates symbolic value. */
454
 
IpeAttribute IpeRepository::MakeScalar(IpeKind kind, IpeString str)
455
 
{
456
 
  if (str.empty()) {
457
 
    return IpeAttribute();
458
 
  } else if (('a' <= str[0] && str[0] <= 'z') ||
459
 
             ('A' <= str[0] && str[0] <= 'Z')) {
460
 
    return ToSymbolic(kind, str);
461
 
  } else {
462
 
    return ToAttribute(kind, IpeLex(str).GetFixed());
463
 
  }
464
 
}
465
 
 
466
 
//! Construct symbolic attribute from string.
467
 
/*! Empty string creates null value, anything else creates symbolic value. */
468
 
IpeAttribute IpeRepository::MakeSymbol(IpeKind kind, IpeString str)
469
 
{
470
 
  if (str.empty())
471
 
    return IpeAttribute();
472
 
  else
473
 
    return ToSymbolic(kind, str);
474
 
}
475
 
 
476
 
//! Construct symbolic attribute from string.
477
 
/*! Like MakeSymbol, but will not create new repository entry. */
478
 
IpeAttribute IpeRepository::GetSymbol(IpeKind kind, IpeString str) const
479
 
{
480
 
  if (!str.empty()) {
481
 
    std::vector<IpeString>::const_iterator it =
482
 
      std::find(iStrings.begin(), iStrings.end(), str);
483
 
    if (it != iStrings.end())
484
 
      return IpeAttribute(kind, true, (it - iStrings.begin()));
485
 
  }
486
 
  return IpeAttribute();
487
 
}
488
 
 
489
 
//! Return string representation of attribute (symbolic or absolute).
490
 
IpeString IpeRepository::String(IpeAttribute attr) const
491
 
{
492
 
  if (attr.IsNull())
493
 
    return IpeString();
494
 
  if (attr.IsSymbolic())
495
 
    return ToString(attr);
496
 
  if (attr.IsVoid())
497
 
    return "void";
498
 
  if (attr.IsSolid())
499
 
    return "solid";
500
 
  if (attr.IsBlack())
501
 
    return "black";
502
 
  if (attr.IsWhite())
503
 
    return "white";
504
 
 
505
 
  IpeString str;
506
 
  IpeStringStream stream(str);
507
 
  if (attr.IsNumeric()) {
508
 
    stream << attr.Number();
509
 
    return str;
510
 
  }
511
 
 
512
 
  switch (attr.Kind()) {
513
 
  case IpeAttribute::EColor:
514
 
    stream << ToColor(attr);
515
 
    return str;
516
 
  case IpeAttribute::EDashStyle:
517
 
  case IpeAttribute::ETextSize:
518
 
  case IpeAttribute::ETextStyle:
519
 
    return ToString(attr);
520
 
  default:
521
 
    stream << ToScalar(attr);
522
 
    return str;
523
 
  }
524
 
}
525
 
 
526
 
// --------------------------------------------------------------------