~ubuntu-branches/ubuntu/natty/luatex/natty

« back to all changes in this revision

Viewing changes to source/libs/xpdf/xpdf-3.02/splash/SplashClip.cc

  • Committer: Package Import Robot
  • Author(s): Norbert Preining
  • Date: 2010-12-13 23:22:59 UTC
  • mfrom: (0.2.1) (1.5.4) (4.3.12 experimental)
  • Revision ID: package-import@ubuntu.com-20101213232259-nqq2mq5z5x6qldw3
Tags: 0.65.0-1
* new upstream release
* ship two source packages as they are distributed by upstream, only
  renamed to match source package requirements. Fix debian/rules
  to install the manual pdf from the right place

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//========================================================================
2
 
//
3
 
// SplashClip.cc
4
 
//
5
 
//========================================================================
6
 
 
7
 
#include <aconf.h>
8
 
 
9
 
#ifdef USE_GCC_PRAGMAS
10
 
#pragma implementation
11
 
#endif
12
 
 
13
 
#include <stdlib.h>
14
 
#include <string.h>
15
 
#include "gmem.h"
16
 
#include "SplashErrorCodes.h"
17
 
#include "SplashPath.h"
18
 
#include "SplashXPath.h"
19
 
#include "SplashXPathScanner.h"
20
 
#include "SplashBitmap.h"
21
 
#include "SplashClip.h"
22
 
 
23
 
//------------------------------------------------------------------------
24
 
// SplashClip.flags
25
 
//------------------------------------------------------------------------
26
 
 
27
 
#define splashClipEO       0x01 // use even-odd rule
28
 
 
29
 
//------------------------------------------------------------------------
30
 
// SplashClip
31
 
//------------------------------------------------------------------------
32
 
 
33
 
SplashClip::SplashClip(SplashCoord x0, SplashCoord y0,
34
 
                       SplashCoord x1, SplashCoord y1,
35
 
                       GBool antialiasA) {
36
 
  antialias = antialiasA;
37
 
  if (x0 < x1) {
38
 
    xMin = x0;
39
 
    xMax = x1;
40
 
  } else {
41
 
    xMin = x1;
42
 
    xMax = x0;
43
 
  }
44
 
  if (y0 < y1) {
45
 
    yMin = y0;
46
 
    yMax = y1;
47
 
  } else {
48
 
    yMin = y1;
49
 
    yMax = y0;
50
 
  }
51
 
  xMinI = splashFloor(xMin);
52
 
  yMinI = splashFloor(yMin);
53
 
  xMaxI = splashFloor(xMax);
54
 
  yMaxI = splashFloor(yMax);
55
 
  paths = NULL;
56
 
  flags = NULL;
57
 
  scanners = NULL;
58
 
  length = size = 0;
59
 
}
60
 
 
61
 
SplashClip::SplashClip(SplashClip *clip) {
62
 
  int i;
63
 
 
64
 
  antialias = clip->antialias;
65
 
  xMin = clip->xMin;
66
 
  yMin = clip->yMin;
67
 
  xMax = clip->xMax;
68
 
  yMax = clip->yMax;
69
 
  xMinI = clip->xMinI;
70
 
  yMinI = clip->yMinI;
71
 
  xMaxI = clip->xMaxI;
72
 
  yMaxI = clip->yMaxI;
73
 
  length = clip->length;
74
 
  size = clip->size;
75
 
  paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *));
76
 
  flags = (Guchar *)gmallocn(size, sizeof(Guchar));
77
 
  scanners = (SplashXPathScanner **)
78
 
                 gmallocn(size, sizeof(SplashXPathScanner *));
79
 
  for (i = 0; i < length; ++i) {
80
 
    paths[i] = clip->paths[i]->copy();
81
 
    flags[i] = clip->flags[i];
82
 
    scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO);
83
 
  }
84
 
}
85
 
 
86
 
SplashClip::~SplashClip() {
87
 
  int i;
88
 
 
89
 
  for (i = 0; i < length; ++i) {
90
 
    delete paths[i];
91
 
    delete scanners[i];
92
 
  }
93
 
  gfree(paths);
94
 
  gfree(flags);
95
 
  gfree(scanners);
96
 
}
97
 
 
98
 
void SplashClip::grow(int nPaths) {
99
 
  if (length + nPaths > size) {
100
 
    if (size == 0) {
101
 
      size = 32;
102
 
    }
103
 
    while (size < length + nPaths) {
104
 
      size *= 2;
105
 
    }
106
 
    paths = (SplashXPath **)greallocn(paths, size, sizeof(SplashXPath *));
107
 
    flags = (Guchar *)greallocn(flags, size, sizeof(Guchar));
108
 
    scanners = (SplashXPathScanner **)
109
 
                   greallocn(scanners, size, sizeof(SplashXPathScanner *));
110
 
  }
111
 
}
112
 
 
113
 
void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
114
 
                             SplashCoord x1, SplashCoord y1) {
115
 
  int i;
116
 
 
117
 
  for (i = 0; i < length; ++i) {
118
 
    delete paths[i];
119
 
    delete scanners[i];
120
 
  }
121
 
  gfree(paths);
122
 
  gfree(flags);
123
 
  gfree(scanners);
124
 
  paths = NULL;
125
 
  flags = NULL;
126
 
  scanners = NULL;
127
 
  length = size = 0;
128
 
 
129
 
  if (x0 < x1) {
130
 
    xMin = x0;
131
 
    xMax = x1;
132
 
  } else {
133
 
    xMin = x1;
134
 
    xMax = x0;
135
 
  }
136
 
  if (y0 < y1) {
137
 
    yMin = y0;
138
 
    yMax = y1;
139
 
  } else {
140
 
    yMin = y1;
141
 
    yMax = y0;
142
 
  }
143
 
  xMinI = splashFloor(xMin);
144
 
  yMinI = splashFloor(yMin);
145
 
  xMaxI = splashFloor(xMax);
146
 
  yMaxI = splashFloor(yMax);
147
 
}
148
 
 
149
 
SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
150
 
                                   SplashCoord x1, SplashCoord y1) {
151
 
  if (x0 < x1) {
152
 
    if (x0 > xMin) {
153
 
      xMin = x0;
154
 
      xMinI = splashFloor(xMin);
155
 
    }
156
 
    if (x1 < xMax) {
157
 
      xMax = x1;
158
 
      xMaxI = splashFloor(xMax);
159
 
    }
160
 
  } else {
161
 
    if (x1 > xMin) {
162
 
      xMin = x1;
163
 
      xMinI = splashFloor(xMin);
164
 
    }
165
 
    if (x0 < xMax) {
166
 
      xMax = x0;
167
 
      xMaxI = splashFloor(xMax);
168
 
    }
169
 
  }
170
 
  if (y0 < y1) {
171
 
    if (y0 > yMin) {
172
 
      yMin = y0;
173
 
      yMinI = splashFloor(yMin);
174
 
    }
175
 
    if (y1 < yMax) {
176
 
      yMax = y1;
177
 
      yMaxI = splashFloor(yMax);
178
 
    }
179
 
  } else {
180
 
    if (y1 > yMin) {
181
 
      yMin = y1;
182
 
      yMinI = splashFloor(yMin);
183
 
    }
184
 
    if (y0 < yMax) {
185
 
      yMax = y0;
186
 
      yMaxI = splashFloor(yMax);
187
 
    }
188
 
  }
189
 
  return splashOk;
190
 
}
191
 
 
192
 
SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
193
 
                                   SplashCoord flatness, GBool eo) {
194
 
  SplashXPath *xPath;
195
 
 
196
 
  xPath = new SplashXPath(path, matrix, flatness, gTrue);
197
 
 
198
 
  // check for an empty path
199
 
  if (xPath->length == 0) {
200
 
    xMax = xMin - 1;
201
 
    yMax = yMin - 1;
202
 
    xMaxI = splashFloor(xMax);
203
 
    yMaxI = splashFloor(yMax);
204
 
    delete xPath;
205
 
 
206
 
  // check for a rectangle
207
 
  } else if (xPath->length == 4 &&
208
 
             ((xPath->segs[0].x0 == xPath->segs[0].x1 &&
209
 
               xPath->segs[0].x0 == xPath->segs[1].x0 &&
210
 
               xPath->segs[0].x0 == xPath->segs[3].x1 &&
211
 
               xPath->segs[2].x0 == xPath->segs[2].x1 &&
212
 
               xPath->segs[2].x0 == xPath->segs[1].x1 &&
213
 
               xPath->segs[2].x0 == xPath->segs[3].x0 &&
214
 
               xPath->segs[1].y0 == xPath->segs[1].y1 &&
215
 
               xPath->segs[1].y0 == xPath->segs[0].y1 &&
216
 
               xPath->segs[1].y0 == xPath->segs[2].y0 &&
217
 
               xPath->segs[3].y0 == xPath->segs[3].y1 &&
218
 
               xPath->segs[3].y0 == xPath->segs[0].y0 &&
219
 
               xPath->segs[3].y0 == xPath->segs[2].y1) ||
220
 
              (xPath->segs[0].y0 == xPath->segs[0].y1 &&
221
 
               xPath->segs[0].y0 == xPath->segs[1].y0 &&
222
 
               xPath->segs[0].y0 == xPath->segs[3].y1 &&
223
 
               xPath->segs[2].y0 == xPath->segs[2].y1 &&
224
 
               xPath->segs[2].y0 == xPath->segs[1].y1 &&
225
 
               xPath->segs[2].y0 == xPath->segs[3].y0 &&
226
 
               xPath->segs[1].x0 == xPath->segs[1].x1 &&
227
 
               xPath->segs[1].x0 == xPath->segs[0].x1 &&
228
 
               xPath->segs[1].x0 == xPath->segs[2].x0 &&
229
 
               xPath->segs[3].x0 == xPath->segs[3].x1 &&
230
 
               xPath->segs[3].x0 == xPath->segs[0].x0 &&
231
 
               xPath->segs[3].x0 == xPath->segs[2].x1))) {
232
 
    clipToRect(xPath->segs[0].x0, xPath->segs[0].y0,
233
 
               xPath->segs[2].x0, xPath->segs[2].y0);
234
 
    delete xPath;
235
 
 
236
 
  } else {
237
 
    grow(1);
238
 
    if (antialias) {
239
 
      xPath->aaScale();
240
 
    }
241
 
    xPath->sort();
242
 
    paths[length] = xPath;
243
 
    flags[length] = eo ? splashClipEO : 0;
244
 
    scanners[length] = new SplashXPathScanner(xPath, eo);
245
 
    ++length;
246
 
  }
247
 
 
248
 
  return splashOk;
249
 
}
250
 
 
251
 
GBool SplashClip::test(int x, int y) {
252
 
  int i;
253
 
 
254
 
  // check the rectangle
255
 
  if (x < xMinI || x > xMaxI || y < yMinI || y > yMaxI) {
256
 
    return gFalse;
257
 
  }
258
 
 
259
 
  // check the paths
260
 
  if (antialias) {
261
 
    for (i = 0; i < length; ++i) {
262
 
      if (!scanners[i]->test(x * splashAASize, y * splashAASize)) {
263
 
        return gFalse;
264
 
      }
265
 
    }
266
 
  } else {
267
 
    for (i = 0; i < length; ++i) {
268
 
      if (!scanners[i]->test(x, y)) {
269
 
        return gFalse;
270
 
      }
271
 
    }
272
 
  }
273
 
 
274
 
  return gTrue;
275
 
}
276
 
 
277
 
SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
278
 
                                      int rectXMax, int rectYMax) {
279
 
  // This tests the rectangle:
280
 
  //     x = [rectXMin, rectXMax + 1)    (note: rect coords are ints)
281
 
  //     y = [rectYMin, rectYMax + 1)
282
 
  // against the clipping region:
283
 
  //     x = [xMin, xMax]                (note: clipping coords are fp)
284
 
  //     y = [yMin, yMax]
285
 
  if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin > xMax ||
286
 
      (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin > yMax) {
287
 
    return splashClipAllOutside;
288
 
  }
289
 
  if ((SplashCoord)rectXMin >= xMin && (SplashCoord)(rectXMax + 1) <= xMax &&
290
 
      (SplashCoord)rectYMin >= yMin && (SplashCoord)(rectYMax + 1) <= yMax &&
291
 
      length == 0) {
292
 
    return splashClipAllInside;
293
 
  }
294
 
  return splashClipPartial;
295
 
}
296
 
 
297
 
SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) {
298
 
  int i;
299
 
 
300
 
  // This tests the rectangle:
301
 
  //     x = [spanXMin, spanXMax + 1)    (note: span coords are ints)
302
 
  //     y = [spanY, spanY + 1)
303
 
  // against the clipping region:
304
 
  //     x = [xMin, xMax]                (note: clipping coords are fp)
305
 
  //     y = [yMin, yMax]
306
 
  if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin > xMax ||
307
 
      (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY > yMax) {
308
 
    return splashClipAllOutside;
309
 
  }
310
 
  if (!((SplashCoord)spanXMin >= xMin && (SplashCoord)(spanXMax + 1) <= xMax &&
311
 
        (SplashCoord)spanY >= yMin && (SplashCoord)(spanY + 1) <= yMax)) {
312
 
    return splashClipPartial;
313
 
  }
314
 
  if (antialias) {
315
 
    for (i = 0; i < length; ++i) {
316
 
      if (!scanners[i]->testSpan(spanXMin * splashAASize,
317
 
                                 spanXMax * splashAASize + (splashAASize - 1),
318
 
                                 spanY * splashAASize)) {
319
 
        return splashClipPartial;
320
 
      }
321
 
    }
322
 
  } else {
323
 
    for (i = 0; i < length; ++i) {
324
 
      if (!scanners[i]->testSpan(spanXMin, spanXMax, spanY)) {
325
 
        return splashClipPartial;
326
 
      }
327
 
    }
328
 
  }
329
 
  return splashClipAllInside;
330
 
}
331
 
 
332
 
void SplashClip::clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y) {
333
 
  int xx0, xx1, xx, yy, i;
334
 
  SplashColorPtr p;
335
 
 
336
 
  // zero out pixels with x < xMin
337
 
  xx0 = *x0 * splashAASize;
338
 
  xx1 = splashFloor(xMin * splashAASize);
339
 
  if (xx1 > aaBuf->getWidth()) {
340
 
    xx1 = aaBuf->getWidth();
341
 
  }
342
 
  if (xx0 < xx1) {
343
 
    xx0 &= ~7;
344
 
    for (yy = 0; yy < splashAASize; ++yy) {
345
 
      p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3);
346
 
      for (xx = xx0; xx + 7 < xx1; xx += 8) {
347
 
        *p++ = 0;
348
 
      }
349
 
      if (xx < xx1) {
350
 
        *p &= 0xff >> (xx1 & 7);
351
 
      }
352
 
    }
353
 
    *x0 = splashFloor(xMin);
354
 
  }
355
 
 
356
 
  // zero out pixels with x > xMax
357
 
  xx0 = splashFloor(xMax * splashAASize) + 1;
358
 
  if (xx0 < 0) {
359
 
    xx0 = 0;
360
 
  }
361
 
  xx1 = (*x1 + 1) * splashAASize;
362
 
  if (xx0 < xx1) {
363
 
    for (yy = 0; yy < splashAASize; ++yy) {
364
 
      p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3);
365
 
      xx = xx0;
366
 
      if (xx & 7) {
367
 
        *p &= 0xff00 >> (xx & 7);
368
 
        xx = (xx & ~7) + 8;
369
 
        ++p;
370
 
      }
371
 
      for (; xx < xx1; xx += 8) {
372
 
        *p++ = 0;
373
 
      }
374
 
    }
375
 
    *x1 = splashFloor(xMax);
376
 
  }
377
 
 
378
 
  // check the paths
379
 
  for (i = 0; i < length; ++i) {
380
 
    scanners[i]->clipAALine(aaBuf, x0, x1, y);
381
 
  }
382
 
}