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

« back to all changes in this revision

Viewing changes to src/ipelib/ipebitmap.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve M. Robbins
  • Date: 2004-06-08 00:44:02 UTC
  • Revision ID: james.westby@ubuntu.com-20040608004402-72yu51xlh7vt6p9m
Tags: upstream-6.0pre16
ImportĀ upstreamĀ versionĀ 6.0pre16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// --------------------------------------------------------------------
 
2
// Bitmaps
 
3
// --------------------------------------------------------------------
 
4
/*
 
5
 
 
6
    This file is part of the extensible drawing editor Ipe.
 
7
    Copyright (C) 1993-2004  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 2 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 "ipebitmap.h"
 
32
 
 
33
// --------------------------------------------------------------------
 
34
 
 
35
/*! \class IpeBitmap
 
36
  \ingroup base
 
37
  \brief A bitmap.
 
38
 
 
39
  Bitmaps are explicitely shared using reference-counting.  Copying is
 
40
  cheap, so IpeBitmap objects are meant to be passed by value.
 
41
 
 
42
  The bitmap can cache data to speed up rendering. This data can be
 
43
  set only once (as the bitmap is conceptually immutable).
 
44
 
 
45
  The bitmap also provides a slot for short-term storage of an "object
 
46
  number".  The PDF embedder, for instance, sets it to the PDF object
 
47
  number when embedding the bitmap, and can reuse it when "drawing"
 
48
  the bitmap.
 
49
*/
 
50
 
 
51
//! Default constructor constructs null bitmap.
 
52
IpeBitmap::IpeBitmap()
 
53
{
 
54
  iImp = 0;
 
55
}
 
56
 
 
57
//! Create from XML stream.
 
58
IpeBitmap::IpeBitmap(const IpeXmlAttributes &attr, IpeString data,
 
59
                     bool rawData)
 
60
{
 
61
  iImp = new Imp;
 
62
  iImp->iRefCount = 1;
 
63
  iImp->iObjNum = IpeLex(attr["id"]).GetInt();
 
64
  iImp->iRender = 0;
 
65
  iImp->iWidth = IpeLex(attr["width"]).GetInt();
 
66
  iImp->iHeight = IpeLex(attr["height"]).GetInt();
 
67
  int length = IpeLex(attr["length"]).GetInt();
 
68
  assert(iImp->iWidth > 0 && iImp->iHeight > 0);
 
69
  IpeString cs = attr["ColorSpace"];
 
70
  if (cs == "DeviceGray") {
 
71
    iImp->iComponents = 1;
 
72
    iImp->iColorSpace = EDeviceGray;
 
73
  } else if (cs == "DeviceCMYK") {
 
74
    iImp->iComponents = 4;
 
75
    iImp->iColorSpace = EDeviceCMYK;
 
76
  } else {
 
77
    iImp->iComponents = 3;
 
78
    iImp->iColorSpace = EDeviceRGB;
 
79
  }
 
80
  IpeString fi = attr["Filter"];
 
81
  if (fi == "DCTDecode")
 
82
    iImp->iFilter = EDCTDecode;
 
83
  else if (fi == "FlateDecode")
 
84
    iImp->iFilter = EFlateDecode;
 
85
  else
 
86
    iImp->iFilter = EDirect;
 
87
  iImp->iBitsPerComponent = IpeLex(attr["BitsPerComponent"]).GetInt();
 
88
  if (length == 0) {
 
89
    assert(iImp->iFilter == EDirect);
 
90
    int bitsPerRow = Width() * Components() * BitsPerComponent();
 
91
    int bytesPerRow = (bitsPerRow + 7) / 8;
 
92
    length = Height() * bytesPerRow;
 
93
  }
 
94
  if (rawData) {
 
95
    assert(length == data.size());
 
96
    iImp->iData = IpeBuffer(data.data(), length);
 
97
  } else {
 
98
    // decode data
 
99
    iImp->iData = IpeBuffer(length);
 
100
    char *p = iImp->iData.data();
 
101
    IpeLex datalex(data);
 
102
    while (length-- > 0)
 
103
      *p++ = char(datalex.GetHexByte());
 
104
  }
 
105
  ComputeChecksum();
 
106
}
 
107
 
 
108
//! Create a new image
 
109
IpeBitmap::IpeBitmap(int width, int height,
 
110
                     TColorSpace colorSpace, int bitsPerComponent,
 
111
                     IpeBuffer data, TFilter filter)
 
112
{
 
113
  iImp = new Imp;
 
114
  iImp->iRefCount = 1;
 
115
  iImp->iObjNum = -1;
 
116
  iImp->iRender = 0;
 
117
  iImp->iWidth = width;
 
118
  iImp->iHeight = height;
 
119
  assert(iImp->iWidth > 0 && iImp->iHeight > 0);
 
120
  iImp->iColorSpace = colorSpace;
 
121
  switch (colorSpace) {
 
122
  case EDeviceGray:
 
123
    iImp->iComponents = 1;
 
124
    break;
 
125
  case EDeviceRGB:
 
126
    iImp->iComponents = 3;
 
127
    break;
 
128
  case EDeviceCMYK:
 
129
    iImp->iComponents = 4;
 
130
    break;
 
131
  }
 
132
  iImp->iFilter = filter;
 
133
  iImp->iBitsPerComponent = bitsPerComponent;
 
134
  iImp->iData = data;
 
135
  ComputeChecksum();
 
136
}
 
137
 
 
138
//! Copy constructor.
 
139
IpeBitmap::IpeBitmap(const IpeBitmap &rhs)
 
140
{
 
141
  iImp = rhs.iImp;
 
142
  if (iImp)
 
143
    iImp->iRefCount++;
 
144
}
 
145
 
 
146
//! Destructor.
 
147
IpeBitmap::~IpeBitmap()
 
148
{
 
149
  if (iImp && --iImp->iRefCount == 0)
 
150
    delete iImp;
 
151
}
 
152
 
 
153
//! Assignment operator (takes care of reference counting).
 
154
IpeBitmap &IpeBitmap::operator=(const IpeBitmap &rhs)
 
155
{
 
156
  if (this != &rhs) {
 
157
    if (iImp && --iImp->iRefCount == 0)
 
158
      delete iImp;
 
159
    iImp = rhs.iImp;
 
160
    if (iImp)
 
161
      iImp->iRefCount++;
 
162
  }
 
163
  return *this;
 
164
}
 
165
 
 
166
//! Save bitmap in XML stream.
 
167
void IpeBitmap::SaveAsXml(IpeStream &stream, int id, int pdfObjNum) const
 
168
{
 
169
  assert(iImp);
 
170
  stream << "<bitmap";
 
171
  stream << " id=\"" << id << "\"";
 
172
  stream << " width=\"" << Width() << "\"";
 
173
  stream << " height=\"" << Height() << "\"";
 
174
  stream << " length=\"" << Size() << "\"";
 
175
  switch (ColorSpace()) {
 
176
  case EDeviceGray:
 
177
    stream << " ColorSpace=\"DeviceGray\"";
 
178
    break;
 
179
  case EDeviceRGB:
 
180
    stream << " ColorSpace=\"DeviceRGB\"";
 
181
    break;
 
182
  case EDeviceCMYK:
 
183
    stream << " ColorSpace=\"DeviceCMYK\"";
 
184
    break;
 
185
  }
 
186
  switch (Filter()) {
 
187
  case EFlateDecode:
 
188
    stream << " Filter=\"FlateDecode\"";
 
189
    break;
 
190
  case EDCTDecode:
 
191
    stream << " Filter=\"DCTDecode\"";
 
192
    break;
 
193
  default:
 
194
    // no filter
 
195
    break;
 
196
  }
 
197
  stream << " BitsPerComponent=\"" << BitsPerComponent() << "\"";
 
198
 
 
199
  if (pdfObjNum >= 0) {
 
200
    stream << " pdfObject=\"" << pdfObjNum << "\"/>\n";
 
201
  } else {
 
202
    // save data
 
203
    stream << ">\n";
 
204
    const char *data = Data();
 
205
    const char *fin = data + Size();
 
206
    int col = 0;
 
207
    while (data != fin) {
 
208
      stream.PutHexByte(*data++);
 
209
      if (++col == 36) {
 
210
        stream << "\n";
 
211
        col = 0;
 
212
      }
 
213
    }
 
214
    if (col > 0)
 
215
      stream << "\n";
 
216
    stream << "</bitmap>\n";
 
217
  }
 
218
}
 
219
 
 
220
//! Set a cached bitmap for fast rendering.
 
221
void IpeBitmap::SetRenderData(void *data) const
 
222
{
 
223
  assert(iImp && iImp->iRender == 0);
 
224
  iImp->iRender = data;
 
225
}
 
226
 
 
227
bool IpeBitmap::Equal(IpeBitmap rhs) const
 
228
{
 
229
  if (iImp == rhs.iImp)
 
230
    return true;
 
231
  if (!iImp || !rhs.iImp)
 
232
    return false;
 
233
 
 
234
  if (iImp->iColorSpace != rhs.iImp->iColorSpace ||
 
235
      iImp->iBitsPerComponent != rhs.iImp->iBitsPerComponent ||
 
236
      iImp->iWidth != rhs.iImp->iWidth ||
 
237
      iImp->iHeight != rhs.iImp->iHeight ||
 
238
      iImp->iComponents != rhs.iImp->iComponents ||
 
239
      iImp->iFilter != rhs.iImp->iFilter ||
 
240
      iImp->iChecksum != rhs.iImp->iChecksum ||
 
241
      iImp->iData.size() != rhs.iImp->iData.size())
 
242
    return false;
 
243
  // check actual data
 
244
  int len = iImp->iData.size();
 
245
  char *p = iImp->iData.data();
 
246
  char *q = rhs.iImp->iData.data();
 
247
  while (len--) {
 
248
    if (*p++ != *q++)
 
249
      return false;
 
250
  }
 
251
  return true;
 
252
}
 
253
 
 
254
void IpeBitmap::ComputeChecksum()
 
255
{
 
256
  int s = 0;
 
257
  int len = iImp->iData.size();
 
258
  char *p = iImp->iData.data();
 
259
  while (len--) {
 
260
    s = (s & 0x0fffffff) << 3;
 
261
    s += *p++;
 
262
  }
 
263
  iImp->iChecksum = s;
 
264
}
 
265
 
 
266
// --------------------------------------------------------------------