source: trunk/poppler/mypoppler/splash/SplashClip.cc @ 461

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

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