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

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

File size: 6.5 KB
Line 
1//========================================================================
2//
3// SplashClip.cc
4//
5//========================================================================
6
7#include <config.h>
8
9#ifdef USE_GCC_PRAGMAS
10#pragma implementation
11#endif
12
13#include <stdlib.h>
14#include <string.h>
15#include "goo/gmem.h"
16#include "SplashErrorCodes.h"
17#include "SplashMath.h"
18#include "SplashPath.h"
19#include "SplashXPath.h"
20#include "SplashXPathScanner.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
33SplashClip::SplashClip(SplashCoord x0, SplashCoord y0,
34                       SplashCoord x1, SplashCoord y1) {
35  if (x0 < x1) {
36    xMin = splashFloor(x0);
37    xMax = splashFloor(x1);
38  } else {
39    xMin = splashFloor(x1);
40    xMax = splashFloor(x0);
41  }
42  if (y0 < y1) {
43    yMin = splashFloor(y0);
44    yMax = splashFloor(y1);
45  } else {
46    yMin = splashFloor(y1);
47    yMax = splashFloor(y0);
48  }
49  paths = NULL;
50  flags = NULL;
51  scanners = NULL;
52  length = size = 0;
53}
54
55SplashClip::SplashClip(SplashClip *clip) {
56  int i;
57
58  xMin = clip->xMin;
59  yMin = clip->yMin;
60  xMax = clip->xMax;
61  yMax = clip->yMax;
62  length = clip->length;
63  size = clip->size;
64  paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *));
65  flags = (Guchar *)gmallocn(size, sizeof(Guchar));
66  scanners = (SplashXPathScanner **)
67                 gmallocn(size, sizeof(SplashXPathScanner *));
68  for (i = 0; i < length; ++i) {
69    paths[i] = clip->paths[i]->copy();
70    flags[i] = clip->flags[i];
71    scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO);
72  }
73}
74
75SplashClip::~SplashClip() {
76  int i;
77
78  for (i = 0; i < length; ++i) {
79    delete paths[i];
80    delete scanners[i];
81  }
82  gfree(paths);
83  gfree(flags);
84  gfree(scanners);
85}
86
87void SplashClip::grow(int nPaths) {
88  if (length + nPaths > size) {
89    if (size == 0) {
90      size = 32;
91    }
92    while (size < length + nPaths) {
93      size *= 2;
94    }
95    paths = (SplashXPath **)greallocn(paths, size, sizeof(SplashXPath *));
96    flags = (Guchar *)greallocn(flags, size, sizeof(Guchar));
97    scanners = (SplashXPathScanner **)
98                   greallocn(scanners, size, sizeof(SplashXPathScanner *));
99  }
100}
101
102void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
103                             SplashCoord x1, SplashCoord y1) {
104  int i;
105
106  for (i = 0; i < length; ++i) {
107    delete paths[i];
108    delete scanners[i];
109  }
110  gfree(paths);
111  gfree(flags);
112  gfree(scanners);
113  paths = NULL;
114  flags = NULL;
115  scanners = NULL;
116  length = size = 0;
117
118  if (x0 < x1) {
119    xMin = splashFloor(x0);
120    xMax = splashFloor(x1);
121  } else {
122    xMin = splashFloor(x1);
123    xMax = splashFloor(x0);
124  }
125  if (y0 < y1) {
126    yMin = splashFloor(y0);
127    yMax = splashFloor(y1);
128  } else {
129    yMin = splashFloor(y1);
130    yMax = splashFloor(y0);
131  }
132}
133
134SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
135                                   SplashCoord x1, SplashCoord y1) {
136  int x0I, y0I, x1I, y1I;
137
138  if (x0 < x1) {
139    x0I = splashFloor(x0);
140    x1I = splashFloor(x1);
141  } else {
142    x0I = splashFloor(x1);
143    x1I = splashFloor(x0);
144  }
145  if (x0I > xMin) {
146    xMin = x0I;
147  }
148  if (x1I < xMax) {
149    xMax = x1I;
150  }
151  if (y0 < y1) {
152    y0I = splashFloor(y0);
153    y1I = splashFloor(y1);
154  } else {
155    y0I = splashFloor(y1);
156    y1I = splashFloor(y0);
157  }
158  if (y0I > yMin) {
159    yMin = y0I;
160  }
161  if (y1I < yMax) {
162    yMax = y1I;
163  }
164  return splashOk;
165}
166
167SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord flatness,
168                                   GBool eo) {
169  SplashXPath *xPath;
170
171  xPath = new SplashXPath(path, flatness, gTrue);
172
173  // check for an empty path
174  if (xPath->length == 0) {
175    xMax = xMin - 1;
176    yMax = yMin - 1;
177    delete xPath;
178
179  // check for a rectangle
180  } else if (xPath->length == 4 &&
181      ((xPath->segs[0].x0 == xPath->segs[0].x1 &&
182        xPath->segs[0].x0 == xPath->segs[1].x0 &&
183        xPath->segs[0].x0 == xPath->segs[3].x1 &&
184        xPath->segs[2].x0 == xPath->segs[2].x1 &&
185        xPath->segs[2].x0 == xPath->segs[1].x1 &&
186        xPath->segs[2].x0 == xPath->segs[3].x0 &&
187        xPath->segs[1].y0 == xPath->segs[1].y1 &&
188        xPath->segs[1].y0 == xPath->segs[0].y1 &&
189        xPath->segs[1].y0 == xPath->segs[2].y0 &&
190        xPath->segs[3].y0 == xPath->segs[3].y1 &&
191        xPath->segs[3].y0 == xPath->segs[0].y0 &&
192        xPath->segs[3].y0 == xPath->segs[2].y1) ||
193       (xPath->segs[0].y0 == xPath->segs[0].y1 &&
194        xPath->segs[0].y0 == xPath->segs[1].y0 &&
195        xPath->segs[0].y0 == xPath->segs[3].y1 &&
196        xPath->segs[2].y0 == xPath->segs[2].y1 &&
197        xPath->segs[2].y0 == xPath->segs[1].y1 &&
198        xPath->segs[2].y0 == xPath->segs[3].y0 &&
199        xPath->segs[1].x0 == xPath->segs[1].x1 &&
200        xPath->segs[1].x0 == xPath->segs[0].x1 &&
201        xPath->segs[1].x0 == xPath->segs[2].x0 &&
202        xPath->segs[3].x0 == xPath->segs[3].x1 &&
203        xPath->segs[3].x0 == xPath->segs[0].x0 &&
204        xPath->segs[3].x0 == xPath->segs[2].x1))) {
205    clipToRect(xPath->segs[0].x0, xPath->segs[0].y0,
206               xPath->segs[2].x0, xPath->segs[2].y0);
207    delete xPath;
208
209  } else {
210    grow(1);
211    xPath->sort();
212    paths[length] = xPath;
213    flags[length] = eo ? splashClipEO : 0;
214    scanners[length] = new SplashXPathScanner(xPath, eo);
215    ++length;
216  }
217
218  return splashOk;
219}
220
221GBool SplashClip::test(int x, int y) {
222  int i;
223
224  // check the rectangle
225  if (x < xMin || x > xMax || y < yMin || y > yMax) {
226    return gFalse;
227  }
228
229  // check the paths
230  for (i = 0; i < length; ++i) {
231    if (!scanners[i]->test(x, y)) {
232      return gFalse;
233    }
234  }
235
236  return gTrue;
237}
238
239SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
240                                      int rectXMax, int rectYMax) {
241  if (rectXMax < xMin || rectXMin > xMax ||
242      rectYMax < yMin || rectYMin > yMax) {
243    return splashClipAllOutside;
244  }
245  if (rectXMin >= xMin && rectXMax <= xMax &&
246      rectYMin >= yMin && rectYMax <= yMax &&
247      length == 0) {
248    return splashClipAllInside;
249  }
250  return splashClipPartial;
251}
252
253SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) {
254  int i;
255
256  if (spanXMax < xMin || spanXMin > xMax ||
257      spanY < yMin || spanY > yMax) {
258    return splashClipAllOutside;
259  }
260  if (!(spanXMin >= xMin && spanXMax <= xMax &&
261        spanY >= yMin && spanY <= yMax)) {
262    return splashClipPartial;
263  }
264  for (i = 0; i < length; ++i) {
265    if (!scanners[i]->testSpan(xMin, xMax, spanY)) {
266      return splashClipPartial;
267    }
268  }
269  return splashClipAllInside;
270}
Note: See TracBrowser for help on using the repository browser.