68
70
// --------------------------------------------------------------------
72
/*! \class IpeBBoxPainter
74
\brief Paint objects using this painter to compute an accurate bounding box.
76
The IpeObjct::BBox member function computes a bounding box useful
77
for distance calculations and optimizations. To find a bounding box
78
that is accurate for the actual \b drawn object, paint the object
79
using an IpeBBoxPainter, and retrieve the box with BBox.
70
82
IpeBBoxPainter::IpeBBoxPainter(const IpeStyleSheet *style)
71
83
: IpePainter(style)
76
void IpeBBoxPainter::BeginPath(const IpeVector &v)
82
void IpeBBoxPainter::BeginClosedPath(const IpeVector &v)
88
void IpeBBoxPainter::LineTo(const IpeVector &v)
94
void IpeBBoxPainter::CurveTo(const IpeVector &v1, const IpeVector &v2,
88
void IpeBBoxPainter::DoMoveTo(const IpeVector &v)
94
void IpeBBoxPainter::DoLineTo(const IpeVector &v)
100
void IpeBBoxPainter::DoCurveTo(const IpeVector &v1, const IpeVector &v2,
97
103
IpeBezier bez(iV, Matrix() * v1, Matrix() * v2, Matrix() * v3);
98
104
IpeRect bb = bez.BBox();
101
lw = Repository()->ToScalar(LineWidth());
107
lw = Repository()->ToScalar(LineWidth()).ToDouble();
102
108
iBBox.AddPoint(bb.Min() - IpeVector(lw, lw));
103
109
iBBox.AddPoint(bb.Max() + IpeVector(lw, lw));
104
110
iV = Matrix() * v3;
107
void IpeBBoxPainter::DrawBitmap(IpeBitmap)
113
void IpeBBoxPainter::DoDrawBitmap(IpeBitmap)
109
115
iBBox.AddPoint(Matrix() * IpeVector(0.0, 0.0));
110
116
iBBox.AddPoint(Matrix() * IpeVector(0.0, 1.0));
127
lw = Repository()->ToScalar(LineWidth());
133
lw = Repository()->ToScalar(LineWidth()).ToDouble();
128
134
iBBox.AddPoint(IpeVector(pos.iX - lw, pos.iY - lw));
129
135
iBBox.AddPoint(IpeVector(pos.iX + lw, pos.iY + lw));
132
138
// --------------------------------------------------------------------
140
/*! \class IpeA85Stream
142
\brief Filter stream adding ASCII85 encoding.
145
inline uint A85Word(const uchar *p)
147
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
150
inline void A85Encode(uint w, char *p)
152
p[4] = char(w % 85 + 33);
154
p[3] = char(w % 85 + 33);
156
p[2] = char(w % 85 + 33);
158
p[1] = char(w % 85 + 33);
159
p[0] = char(w / 85 + 33);
162
IpeA85Stream::IpeA85Stream(IpeStream &stream)
169
void IpeA85Stream::PutChar(char ch)
174
uint w = A85Word(iCh);
176
iStream.PutChar('z');
182
iStream.PutCString(buf);
186
iStream.PutChar('\n');
193
void IpeA85Stream::Close()
196
for (int k = iN; k < 4; ++k)
198
uint w = A85Word(iCh);
202
iStream.PutCString(buf);
204
iStream.PutCString("~>\n");
208
// --------------------------------------------------------------------
210
/*! \class IpeA85Source
212
\brief Filter source adding ASCII85 decoding.
215
IpeA85Source::IpeA85Source(IpeDataSource &source)
219
iN = 0; // number of characters buffered
220
iIndex = 0; // next character to return
223
int IpeA85Source::GetChar()
226
return iBuf[iIndex++];
233
ch = iSource.GetChar();
234
} while (ch == '\n' || ch == '\r' || ch == ' ');
236
if (ch == '~' || ch == EOF) {
238
iN = 0; // no more data, immediate EOF
246
iBuf[0] = iBuf[1] = iBuf[2] = iBuf[3] = 0;
252
for (int k = 1; k < 5; ++k) {
254
c[k] = iSource.GetChar();
255
} while (c[k] == '\n' || c[k] == '\r' || c[k] == ' ');
256
if (c[k] == '~' || c[k] == EOF) {
263
for (int k = iN + 1; k < 5; ++k)
267
for (int k = 0; k < 5; ++k)
268
t = t * 85 + (c[k] - 0x21);
270
for (int k = 3; k >= 0; --k) {
271
iBuf[k] = char(t & 0xff);
278
// --------------------------------------------------------------------
280
/*! \class IpeDeflateStream
282
\brief Filter stream adding flate compression.
285
struct IpeDeflateStream::Private {
289
IpeDeflateStream::IpeDeflateStream(IpeStream &stream, int level)
290
: iStream(stream), iIn(0x400), iOut(0x400) // create buffers
293
z_streamp z = &iPriv->iFlate;
299
int err = deflateInit(z, level);
301
ipeDebug("deflateInit returns error %d", err);
308
IpeDeflateStream::~IpeDeflateStream()
311
z_streamp z = &iPriv->iFlate;
317
void IpeDeflateStream::PutChar(char ch)
323
// compress and write
324
z_streamp z = &iPriv->iFlate;
325
z->next_in = (Bytef *) iIn.data();
326
z->avail_in = iIn.size();
327
while (z->avail_in) {
328
z->next_out = (Bytef *) iOut.data();
329
z->avail_out = iOut.size();
330
int err = deflate(z, Z_NO_FLUSH);
332
ipeDebug("deflate returns error %d", err);
336
iStream.PutRaw(iOut.data(), z->next_out - (Bytef *) iOut.data());
341
void IpeDeflateStream::Close()
343
// compress and write remaining data
344
z_streamp z = &iPriv->iFlate;
345
z->next_in = (Bytef *) iIn.data();
350
z->next_out = (Bytef *) iOut.data();
351
z->avail_out = iOut.size();
352
err = deflate(z, Z_FINISH);
353
if (err != Z_OK && err != Z_STREAM_END) {
354
ipeDebug("deflate returns error %d", err);
357
iStream.PutRaw(iOut.data(), z->next_out - (Bytef *) iOut.data());
358
} while (err == Z_OK);
362
ipeDebug("deflateEnd returns error %d", err);
367
iPriv = 0; // make sure no more writing possible
371
//! Deflate a buffer in a single run.
372
/*! The returned buffer may be larger than necessary: \a deflatedSize is set to
373
the number of bytes actually used. */
374
IpeBuffer IpeDeflateStream::Deflate(const char *data, int size, int &deflatedSize, int compressLevel)
376
ulong dfsize = ulong(size * 1.001 + 13);
377
IpeBuffer deflatedData(dfsize);
378
int err = compress2((Bytef *) deflatedData.data(), &dfsize,
379
(const Bytef *) data, size, compressLevel);
381
ipeDebug("Zlib compress2 returns errror %d", err);
384
deflatedSize = dfsize;
388
// --------------------------------------------------------------------
390
/*! \class IpeInflateSource
392
\brief Filter source adding flate decompression.
395
struct IpeInflateSource::Private {
399
IpeInflateSource::IpeInflateSource(IpeDataSource &source)
400
: iSource(source), iIn(0x400), iOut(0x400)
403
z_streamp z = &iPriv->iFlate;
411
int err = inflateInit(z);
413
ipeDebug("inflateInit returns error %d", err);
415
iPriv = 0; // set EOF
420
z->next_out = (Bytef *) iP;
423
IpeInflateSource::~IpeInflateSource()
426
z_streamp z = &iPriv->iFlate;
432
void IpeInflateSource::FillBuffer()
434
char *p = iIn.data();
435
char *p1 = iIn.data() + iIn.size();
436
z_streamp z = &iPriv->iFlate;
437
z->next_in = (Bytef *) p;
440
int ch = iSource.GetChar();
448
//! Get one more character, or EOF.
449
int IpeInflateSource::GetChar()
454
z_streamp z = &iPriv->iFlate;
455
if (iP < (char *) z->next_out)
458
// next to decompress some data
459
if (z->avail_in == 0)
462
if (z->avail_in > 0) {
464
z->next_out = (Bytef *) iOut.data();
465
z->avail_out = iOut.size();
466
int err = inflate(z, Z_NO_FLUSH);
467
if (err != Z_OK && err != Z_STREAM_END) {
468
ipeDebug("inflate returns error %d", err);
471
iPriv = 0; // set EOF
475
if (iP < (char *) z->next_out)
477
// didn't get any new data, must be EOF
480
// FillBuffer didn't get any data, must be EOF, so we are done
487
// --------------------------------------------------------------------