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

« back to all changes in this revision

Viewing changes to src/ipelib/ipereference.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
// --------------------------------------------------------------------
 
2
// The reference object.
 
3
// --------------------------------------------------------------------
 
4
/*
 
5
 
 
6
    This file is part of the extensible drawing editor Ipe.
 
7
    Copyright (C) 1993-2009  Otfried Cheong
 
8
 
 
9
    Ipe is free software; you can redistribute it and/or modify it
 
10
    under the terms of the GNU General Public License as published by
 
11
    the Free Software Foundation; either version 3 of the License, or
 
12
    (at your option) any later version.
 
13
 
 
14
    As a special exception, you have permission to link Ipe with the
 
15
    CGAL library and distribute executables, as long as you follow the
 
16
    requirements of the Gnu General Public License in regard to all of
 
17
    the software in the executable aside from CGAL.
 
18
 
 
19
    Ipe is distributed in the hope that it will be useful, but WITHOUT
 
20
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
21
    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 
22
    License for more details.
 
23
 
 
24
    You should have received a copy of the GNU General Public License
 
25
    along with Ipe; if not, you can find it at
 
26
    "http://www.gnu.org/copyleft/gpl.html", or write to the Free
 
27
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
28
 
 
29
*/
 
30
 
 
31
#include "ipereference.h"
 
32
#include "ipestyle.h"
 
33
#include "ipepainter.h"
 
34
 
 
35
using namespace ipe;
 
36
 
 
37
/*! \class ipe::Reference
 
38
  \ingroup obj
 
39
  \brief The reference object.
 
40
 
 
41
  A Reference uses a symbol, that is, an object defined in an Ipe
 
42
  StyleSheet. The object is defined as a named symbol in the style
 
43
  sheet, and can be reused arbitrarily often in the document.  This
 
44
  can, for instance, be used for backgrounds on multi-page documents.
 
45
 
 
46
  It is admissible to refer to an undefined object (that is, the
 
47
  current style sheet cascade does not define a symbol with the given
 
48
  name).  Nothing will be drawn in this case.
 
49
 
 
50
  The Reference has a stroke, fill, and pen attribute.  When drawing a
 
51
  symbol, these attributes are made available to the symbol through
 
52
  the names "sym-stroke", "sym-fill", and "sym-pen". These are not
 
53
  defined by the style sheet, but resolved by the Painter when the
 
54
  symbol sets its attributes.
 
55
 
 
56
  Note that it is not possible to determine \e whether a symbol is
 
57
  filled from the Reference object.
 
58
 
 
59
  The size attribute is of type ESymbolSize, and indicates a
 
60
  magnification factor applied to the symbol.  This magnification is
 
61
  applied after the untransformation indicated in the Reference and in
 
62
  the Symbol has been performed, so that symbols are magnified even if
 
63
  they specify ETransformationsTranslations.
 
64
 
 
65
  The size is meant for symbols such as marks, that can be shown in
 
66
  different sizes.  Another application of symbols is for backgrounds
 
67
  and logos.  Their size should not be changed when the user changes
 
68
  the symbolsize for the entire page.  For such symbols, the size
 
69
  attribute of the Reference should be set to the absolute value zero.
 
70
  This means that no magnification is applied to the object, and it
 
71
  also \e stops setAttribute() from modifying the size.  (The size can
 
72
  still be changed using setSize(), but this is not available from
 
73
  Lua.)
 
74
*/
 
75
 
 
76
//! Create a reference to the named object in stylesheet.
 
77
Reference::Reference(const AllAttributes &attr, Attribute name, Vector pos)
 
78
  : Object()
 
79
{
 
80
  assert(name.isSymbolic());
 
81
  iName = name;
 
82
  iPos = pos;
 
83
  iPen = Attribute::NORMAL();
 
84
  iSize = Attribute::ONE();
 
85
  iStroke = Attribute::BLACK();
 
86
  iFill = Attribute::WHITE();
 
87
  iFlags = flagsFromName(name.string());
 
88
  if (iFlags & EHasPen)
 
89
    iPen = attr.iPen;
 
90
  if (iFlags & EHasSize)
 
91
    iSize = attr.iSymbolSize;
 
92
  if (iFlags & EHasStroke)
 
93
    iStroke = attr.iStroke;
 
94
  if (iFlags & EHasFill)
 
95
    iFill = attr.iFill;
 
96
}
 
97
 
 
98
//! Create from XML stream.
 
99
Reference::Reference(const XmlAttributes &attr, String /* data */)
 
100
  : Object(attr)
 
101
{
 
102
  iName = Attribute(true, attr["name"]);
 
103
  String str;
 
104
  if (attr.has("pos", str)) {
 
105
    Lex st(str);
 
106
    st >> iPos.x >> iPos.y;
 
107
  } else
 
108
    iPos = Vector::ZERO;
 
109
  iPen = Attribute::makeScalar(attr["pen"], Attribute::NORMAL());
 
110
  iSize = Attribute::makeScalar(attr["size"], Attribute::ONE());
 
111
  iStroke = Attribute::makeColor(attr["stroke"], Attribute::BLACK());
 
112
  iFill = Attribute::makeColor(attr["fill"], Attribute::WHITE());
 
113
  iFlags = flagsFromName(iName.string());
 
114
}
 
115
 
 
116
//! Clone object
 
117
Object *Reference::clone() const
 
118
{
 
119
  return new Reference(*this);
 
120
}
 
121
 
 
122
//! Return pointer to this object.
 
123
Reference *Reference::asReference()
 
124
{
 
125
  return this;
 
126
}
 
127
 
 
128
Object::Type Reference::type() const
 
129
{
 
130
  return EReference;
 
131
}
 
132
 
 
133
//! Call visitReference of visitor.
 
134
void Reference::accept(Visitor &visitor) const
 
135
{
 
136
  visitor.visitReference(this);
 
137
}
 
138
 
 
139
//! Save in XML format.
 
140
void Reference::saveAsXml(Stream &stream, String layer) const
 
141
{
 
142
  stream << "<use";
 
143
  saveAttributesAsXml(stream, layer);
 
144
  stream << " name=\"" << iName.string() << "\"";
 
145
  if (iPos != Vector::ZERO)
 
146
    stream << " pos=\"" << iPos << "\"";
 
147
  if ((iFlags & EHasPen) && !iPen.isNormal())
 
148
    stream << " pen=\"" << iPen.string() << "\"";
 
149
  if ((iFlags & EHasSize) && iSize != Attribute::ONE())
 
150
    stream << " size=\"" << iSize.string() << "\"";
 
151
  if ((iFlags & EHasStroke) && iStroke != Attribute::BLACK())
 
152
    stream << " stroke=\"" << iStroke.string() << "\"";
 
153
  if ((iFlags & EHasFill) && iFill != Attribute::WHITE())
 
154
    stream << " fill=\"" << iFill.string() << "\"";
 
155
  stream << "/>\n";
 
156
}
 
157
 
 
158
//! Draw reference.
 
159
/*! If the symbolic attribute is not defined in the current style sheet,
 
160
  nothing is drawn at all. */
 
161
void Reference::draw(Painter &painter) const
 
162
{
 
163
  const Symbol *symbol = painter.cascade()->findSymbol(iName);
 
164
  if (symbol) {
 
165
    Attribute si = painter.cascade()->find(ESymbolSize, iSize);
 
166
    double s = si.number().toDouble();
 
167
    painter.pushMatrix();
 
168
    painter.transform(matrix());
 
169
    painter.translate(iPos);
 
170
    painter.untransform(transformations());
 
171
    painter.untransform(symbol->iTransformations);
 
172
    if (iFlags & EHasSize) {
 
173
      Matrix m(s, 0, 0, s, 0, 0);
 
174
      painter.transform(m);
 
175
    }
 
176
    painter.push();
 
177
    if (iFlags & EHasStroke)
 
178
      painter.setSymStroke(iStroke);
 
179
    if (iFlags & EHasFill)
 
180
      painter.setSymFill(iFill);
 
181
    if (iFlags & EHasPen)
 
182
      painter.setSymPen(iPen);
 
183
    painter.drawSymbol(iName);
 
184
    painter.pop();
 
185
    painter.popMatrix();
 
186
  }
 
187
}
 
188
 
 
189
void Reference::drawSimple(Painter &painter) const
 
190
{
 
191
  const int size = 10;
 
192
  painter.pushMatrix();
 
193
  painter.transform(matrix());
 
194
  painter.translate(iPos);
 
195
  painter.untransform(ETransformationsTranslations);
 
196
  painter.newPath();
 
197
  painter.moveTo(Vector(-size, 0));
 
198
  painter.lineTo(Vector(size, 0));
 
199
  painter.moveTo(Vector(0, -size));
 
200
  painter.lineTo(Vector(0, size));
 
201
  painter.drawPath(EStrokedOnly);
 
202
  painter.popMatrix();
 
203
}
 
204
 
 
205
/*! \copydoc Object::addToBBox
 
206
 
 
207
  This only adds the position to the \a box. */
 
208
void Reference::addToBBox(Rect &box, const Matrix &m, bool cp) const
 
209
{
 
210
  box.addPoint((m * matrix()) * iPos);
 
211
}
 
212
 
 
213
void Reference::checkStyle(const Cascade *sheet, AttributeSeq &seq) const
 
214
{
 
215
  if (!sheet->findSymbol(iName)) {
 
216
    if (std::find(seq.begin(), seq.end(), iName) == seq.end())
 
217
      seq.push_back(iName);
 
218
  }
 
219
  if (iFlags & EHasStroke)
 
220
    checkSymbol(EColor, iStroke, sheet, seq);
 
221
  if (iFlags & EHasFill)
 
222
    checkSymbol(EColor, iFill, sheet, seq);
 
223
  if (iFlags & EHasPen)
 
224
    checkSymbol(EPen, iPen, sheet, seq);
 
225
  if (iFlags & EHasSize)
 
226
    checkSymbol(ESymbolSize, iSize, sheet, seq);
 
227
}
 
228
 
 
229
double Reference::distance(const Vector &v, const Matrix &m, double) const
 
230
{
 
231
  return (v - (m * (matrix() * iPos))).len();
 
232
}
 
233
 
 
234
void Reference::snapVtx(const Vector &mouse, const Matrix &m,
 
235
                        Vector &pos, double &bound) const
 
236
{
 
237
  (m * (matrix() * iPos)).snap(mouse, pos, bound);
 
238
}
 
239
 
 
240
void Reference::snapBnd(const Vector &, const Matrix &,
 
241
                        Vector &, double &) const
 
242
{
 
243
  // nothing
 
244
}
 
245
 
 
246
//! Set name of symbol referenced.
 
247
void Reference::setName(Attribute name)
 
248
{
 
249
  iName = name;
 
250
  iFlags = flagsFromName(name.string());
 
251
}
 
252
 
 
253
//! Set pen.
 
254
void Reference::setPen(Attribute pen)
 
255
{
 
256
  iPen = pen;
 
257
}
 
258
 
 
259
//! Set stroke color.
 
260
void Reference::setStroke(Attribute color)
 
261
{
 
262
  iStroke = color;
 
263
}
 
264
 
 
265
//! Set fill color.
 
266
void Reference::setFill(Attribute color)
 
267
{
 
268
  iFill = color;
 
269
}
 
270
 
 
271
//! Set size (magnification) of symbol.
 
272
void Reference::setSize(Attribute size)
 
273
{
 
274
  iSize = size;
 
275
}
 
276
 
 
277
//! \copydoc Object::setAttribute
 
278
bool Reference::setAttribute(Property prop, Attribute value,
 
279
                             Attribute nStroke, Attribute nFill)
 
280
{
 
281
  switch (prop) {
 
282
  case EPropPen:
 
283
    if ((iFlags & EHasPen) && value != pen()) {
 
284
      setPen(value);
 
285
      return true;
 
286
    }
 
287
    break;
 
288
  case EPropStrokeColor:
 
289
    if ((iFlags & EHasStroke) && value != stroke()) {
 
290
      setStroke(value);
 
291
      return true;
 
292
    }
 
293
    break;
 
294
  case EPropFillColor:
 
295
    if ((iFlags & EHasFill) && value != fill()) {
 
296
      setFill(value);
 
297
      return true;
 
298
    }
 
299
    break;
 
300
  case EPropSymbolSize:
 
301
    if ((iFlags & EHasSize) && value != size()) {
 
302
      setSize(value);
 
303
      return true;
 
304
    }
 
305
    break;
 
306
  case EPropMarkShape:
 
307
    if ((iFlags & EIsMark) && value != name()) {
 
308
      uint nFlags = flagsFromName(value.string());
 
309
      if (!(iFlags & EHasStroke) && (nFlags & EHasStroke))
 
310
        setStroke(nStroke);
 
311
      if (!(iFlags & EHasFill) && (nFlags & EHasFill))
 
312
        setFill(nFill);
 
313
      setName(value);
 
314
      return true;
 
315
    }
 
316
    break;
 
317
  default:
 
318
    return Object::setAttribute(prop, value, nStroke, nFill);
 
319
  }
 
320
  return false;
 
321
}
 
322
 
 
323
Attribute Reference::getAttribute(Property prop)
 
324
{
 
325
  switch (prop) {
 
326
  case EPropPen:
 
327
    if (iFlags & EHasPen)
 
328
      return pen();
 
329
    break;
 
330
  case EPropStrokeColor:
 
331
    if (iFlags & EHasStroke)
 
332
      return stroke();
 
333
    break;
 
334
  case EPropFillColor:
 
335
    if (iFlags & EHasFill)
 
336
      return fill();
 
337
    break;
 
338
  case EPropSymbolSize:
 
339
    if (iFlags & EHasSize)
 
340
      return size();
 
341
    break;
 
342
  case EPropMarkShape:
 
343
    if (iFlags & EIsMark)
 
344
      return name();
 
345
    break;
 
346
  default:
 
347
    break;
 
348
  }
 
349
  return Object::getAttribute(prop);
 
350
}
 
351
 
 
352
// --------------------------------------------------------------------
 
353
 
 
354
uint Reference::flagsFromName(String name)
 
355
{
 
356
  uint flags = 0;
 
357
  if (name.left(5) == "mark/")
 
358
    flags |= EIsMark;
 
359
  if (name.left(6) == "arrow/")
 
360
    flags |= EIsArrow;
 
361
  int i = name.rfind('(');
 
362
  if (i < 0 || name[name.size() - 1] != ')')
 
363
    return flags;
 
364
  String letters = name.substr(i+1, name.size() - i - 2);
 
365
  if (letters.find('x') >= 0)
 
366
    flags |= EHasSize;
 
367
  if (letters.find('s') >= 0)
 
368
    flags |= EHasStroke;
 
369
  if (letters.find('f') >= 0)
 
370
    flags |= EHasFill;
 
371
  if (letters.find('p') >= 0)
 
372
    flags |= EHasPen;
 
373
  return flags;
 
374
}
 
375
 
 
376
// --------------------------------------------------------------------
 
377