First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / xaa / xaaLine.c
blob7469de179dabf800b8f5ea6de36c459f6d22968b
2 #ifdef HAVE_XORG_CONFIG_H
3 #include <xorg-config.h>
4 #endif
6 #include <stdlib.h>
8 #include <X11/X.h>
9 #include "misc.h"
10 #include "xf86.h"
11 #include "xf86_OSproc.h"
13 #include "scrnintstr.h"
14 #include "pixmapstr.h"
15 #include "miline.h"
16 #include "xf86str.h"
17 #include "xaa.h"
18 #include "xaalocal.h"
21 void
22 #ifdef POLYSEGMENT
23 XAAPolySegment(
24 DrawablePtr pDrawable,
25 GCPtr pGC,
26 int nseg,
27 xSegment *pSeg
28 #else
29 XAAPolyLines(
30 DrawablePtr pDrawable,
31 GCPtr pGC,
32 int mode, /* Origin or Previous */
33 int npt, /* number of points */
34 DDXPointPtr pptInit
35 #endif
37 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
38 BoxPtr pboxInit = REGION_RECTS(pGC->pCompositeClip);
39 int nboxInit = REGION_NUM_RECTS(pGC->pCompositeClip);
40 unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
41 int xorg = pDrawable->x;
42 int yorg = pDrawable->y;
43 int nbox;
44 BoxPtr pbox;
45 #ifndef POLYSEGMENT
46 DDXPointPtr ppt;
47 #endif
48 int x1, x2, y1, y2, tmp, len;
50 if(!nboxInit)
51 return;
53 if (infoRec->SolidLineFlags & LINE_LIMIT_COORDS) {
54 int minValX = infoRec->SolidLineLimits.x1;
55 int maxValX = infoRec->SolidLineLimits.x2;
56 int minValY = infoRec->SolidLineLimits.y1;
57 int maxValY = infoRec->SolidLineLimits.y2;
58 #ifdef POLYSEGMENT
59 int n = nseg;
60 xSegment *s = pSeg;
62 while (n--)
63 #else
64 int n = npt;
65 int xorgtmp = xorg;
66 int yorgtmp = yorg;
68 ppt = pptInit;
69 x2 = ppt->x + xorgtmp;
70 y2 = ppt->y + yorgtmp;
71 while (--n)
72 #endif
74 #ifdef POLYSEGMENT
75 x1 = s->x1 + xorg;
76 y1 = s->y1 + yorg;
77 x2 = s->x2 + xorg;
78 y2 = s->y2 + yorg;
79 s++;
80 #else
81 x1 = x2;
82 y1 = y2;
83 ++ppt;
84 if (mode == CoordModePrevious) {
85 xorgtmp = x1;
86 yorgtmp = y1;
88 x2 = ppt->x + xorgtmp;
89 y2 = ppt->y + yorgtmp;
90 #endif
91 if (x1 > maxValX || x1 < minValX ||
92 x2 > maxValX || x2 < minValX ||
93 y1 > maxValY || y1 < minValY ||
94 y2 > maxValY || y2 < minValY) {
95 #ifdef POLYSEGMENT
96 XAAFallbackOps.PolySegment(pDrawable, pGC, nseg, pSeg);
97 #else
98 XAAFallbackOps.Polylines(pDrawable, pGC, mode, npt, pptInit);
99 #endif
100 return;
105 (*infoRec->SetupForSolidLine)(infoRec->pScrn, pGC->fgPixel,
106 pGC->alu, pGC->planemask);
108 #ifdef POLYSEGMENT
109 while (nseg--)
110 #else
111 ppt = pptInit;
112 x2 = ppt->x + xorg;
113 y2 = ppt->y + yorg;
114 while(--npt)
115 #endif
117 nbox = nboxInit;
118 pbox = pboxInit;
120 #ifdef POLYSEGMENT
121 x1 = pSeg->x1 + xorg;
122 y1 = pSeg->y1 + yorg;
123 x2 = pSeg->x2 + xorg;
124 y2 = pSeg->y2 + yorg;
125 pSeg++;
126 #else
127 x1 = x2;
128 y1 = y2;
129 ++ppt;
130 if (mode == CoordModePrevious) {
131 xorg = x1;
132 yorg = y1;
134 x2 = ppt->x + xorg;
135 y2 = ppt->y + yorg;
136 #endif
138 if (x1 == x2) { /* vertical line */
139 /* make the line go top to bottom of screen, keeping
140 endpoint semantics
142 if (y1 > y2) {
143 tmp = y2;
144 y2 = y1 + 1;
145 y1 = tmp + 1;
146 #ifdef POLYSEGMENT
147 if (pGC->capStyle != CapNotLast) y1--;
148 #endif
150 #ifdef POLYSEGMENT
151 else if (pGC->capStyle != CapNotLast) y2++;
152 #endif
153 /* get to first band that might contain part of line */
154 while(nbox && (pbox->y2 <= y1)) {
155 pbox++;
156 nbox--;
159 /* stop when lower edge of box is beyond end of line */
160 while(nbox && (y2 >= pbox->y1)) {
161 if ((x1 >= pbox->x1) && (x1 < pbox->x2)) {
162 tmp = max(y1, pbox->y1);
163 len = min(y2, pbox->y2) - tmp;
164 if (len) (*infoRec->SubsequentSolidHorVertLine)(
165 infoRec->pScrn, x1, tmp, len, DEGREES_270);
167 nbox--;
168 pbox++;
170 #ifndef POLYSEGMENT
171 y2 = ppt->y + yorg;
172 #endif
173 } else if (y1 == y2) { /* horizontal line */
174 /* force line from left to right, keeping endpoint semantics */
175 if (x1 > x2) {
176 tmp = x2;
177 x2 = x1 + 1;
178 x1 = tmp + 1;
179 #ifdef POLYSEGMENT
180 if (pGC->capStyle != CapNotLast) x1--;
181 #endif
183 #ifdef POLYSEGMENT
184 else if (pGC->capStyle != CapNotLast) x2++;
185 #endif
187 /* find the correct band */
188 while(nbox && (pbox->y2 <= y1)) {
189 pbox++;
190 nbox--;
193 /* try to draw the line, if we haven't gone beyond it */
194 if (nbox && (pbox->y1 <= y1)) {
195 int orig_y = pbox->y1;
196 /* when we leave this band, we're done */
197 while(nbox && (orig_y == pbox->y1)) {
198 if (pbox->x2 <= x1) {
199 /* skip boxes until one might contain start point */
200 nbox--;
201 pbox++;
202 continue;
205 /* stop if left of box is beyond right of line */
206 if (pbox->x1 >= x2) {
207 nbox = 0;
208 break;
211 tmp = max(x1, pbox->x1);
212 len = min(x2, pbox->x2) - tmp;
213 if (len) (*infoRec->SubsequentSolidHorVertLine)(
214 infoRec->pScrn, tmp, y1, len, DEGREES_0);
215 nbox--;
216 pbox++;
219 #ifndef POLYSEGMENT
220 x2 = ppt->x + xorg;
221 #endif
222 } else{ /* sloped line */
223 unsigned int oc1, oc2;
224 int dmin, dmaj, e, octant;
226 if (infoRec->SubsequentSolidBresenhamLine) {
227 if((dmaj = x2 - x1) < 0) {
228 dmaj = -dmaj;
229 octant = XDECREASING;
230 } else octant = 0;
232 if((dmin = y2 - y1) < 0) {
233 dmin = -dmin;
234 octant |= YDECREASING;
237 if(dmin >= dmaj){
238 tmp = dmin; dmin = dmaj; dmaj = tmp;
239 octant |= YMAJOR;
242 e = -dmaj - ((bias >> octant) & 1);
243 len = dmaj;
244 dmin <<= 1;
245 dmaj <<= 1;
246 } else { /* Muffle compiler */
247 dmin = dmaj = e = octant = len = 0;
250 while(nbox--) {
251 oc1 = oc2 = 0;
252 OUTCODES(oc1, x1, y1, pbox);
253 OUTCODES(oc2, x2, y2, pbox);
254 if (!(oc1 | oc2)) { /* unclipped */
255 if(infoRec->SubsequentSolidTwoPointLine) {
256 (*infoRec->SubsequentSolidTwoPointLine)(
257 infoRec->pScrn, x1, y1, x2, y2,
258 #ifdef POLYSEGMENT
259 (pGC->capStyle != CapNotLast) ? 0 :
260 #endif
261 OMIT_LAST
263 } else {
264 (*infoRec->SubsequentSolidBresenhamLine)(
265 infoRec->pScrn, x1, y1, dmaj, dmin, e,
266 #ifdef POLYSEGMENT
267 (pGC->capStyle != CapNotLast) ? (len+1) :
268 #endif
269 len, octant);
271 break;
272 } else if (oc1 & oc2) { /* completely clipped */
273 pbox++;
274 } else if (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_LINE) {
275 (*infoRec->SetClippingRectangle)(infoRec->pScrn,
276 pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1);
278 if(infoRec->SubsequentSolidBresenhamLine) {
279 (*infoRec->SubsequentSolidBresenhamLine)(
280 infoRec->pScrn, x1, y1, dmaj, dmin, e,
281 #ifdef POLYSEGMENT
282 (pGC->capStyle != CapNotLast) ? (len+1) :
283 #endif
284 len, octant);
285 } else {
286 (*infoRec->SubsequentSolidTwoPointLine)(
287 infoRec->pScrn, x1, y1, x2, y2,
288 #ifdef POLYSEGMENT
289 (pGC->capStyle != CapNotLast) ? 0 :
290 #endif
291 OMIT_LAST
294 (*infoRec->DisableClipping)(infoRec->pScrn);
295 pbox++;
296 } else {
297 int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
298 int clip1 = 0, clip2 = 0;
299 int err, adx, ady;
301 if(octant & YMAJOR) {
302 ady = dmaj >> 1;
303 adx = dmin >> 1;
304 } else {
305 ady = dmin >> 1;
306 adx = dmaj >> 1;
309 if (miZeroClipLine(pbox->x1, pbox->y1,
310 pbox->x2 - 1, pbox->y2 - 1,
311 &new_x1, &new_y1, &new_x2, &new_y2,
312 adx, ady, &clip1, &clip2,
313 octant, bias, oc1, oc2) == -1)
315 pbox++;
316 continue;
319 if (octant & YMAJOR)
320 len = abs(new_y2 - new_y1);
321 else
322 len = abs(new_x2 - new_x1);
323 #ifdef POLYSEGMENT
324 if (clip2 != 0 || pGC->capStyle != CapNotLast)
325 len++;
326 #else
327 len += (clip2 != 0);
328 #endif
329 if (len) {
330 int abserr, clipdx, clipdy;
331 /* unwind bresenham error term to first point */
332 if (clip1) {
333 clipdx = abs(new_x1 - x1);
334 clipdy = abs(new_y1 - y1);
336 if (octant & YMAJOR)
337 err = e + clipdy*dmin - clipdx*dmaj;
338 else
339 err = e + clipdx*dmin - clipdy*dmaj;
340 } else
341 err = e;
343 #define range infoRec->SolidBresenhamLineErrorTermBits
344 abserr = abs(err);
345 while((abserr & range) ||
346 (dmaj & range) ||
347 (dmin & range)) {
348 dmin >>= 1;
349 dmaj >>= 1;
350 abserr >>= 1;
351 err /= 2;
354 (*infoRec->SubsequentSolidBresenhamLine)(
355 infoRec->pScrn, new_x1, new_y1,
356 dmaj, dmin, err, len, octant);
358 pbox++;
360 } /* while (nbox--) */
361 } /* sloped line */
362 } /* while (nline--) */
364 #ifndef POLYSEGMENT
365 /* paint the last point if the end style isn't CapNotLast.
366 (Assume that a projecting, butt, or round cap that is one
367 pixel wide is the same as the single pixel of the endpoint.)
370 if ((pGC->capStyle != CapNotLast) &&
371 ((ppt->x + xorg != pptInit->x + pDrawable->x) ||
372 (ppt->y + yorg != pptInit->y + pDrawable->y) ||
373 (ppt == pptInit + 1)))
375 nbox = nboxInit;
376 pbox = pboxInit;
377 while (nbox--)
379 if ((x2 >= pbox->x1) && (y2 >= pbox->y1) &&
380 (x2 < pbox->x2) && (y2 < pbox->y2))
382 (*infoRec->SubsequentSolidHorVertLine)(
383 infoRec->pScrn, x2, y2, 1, DEGREES_0);
384 break;
386 else
387 pbox++;
390 #endif
392 SET_SYNC_FLAG(infoRec);