~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xfree86/xaa/xaaLine.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86: xc/programs/Xserver/hw/xfree86/xaa/xaaLine.c,v 1.5 2001/10/28 03:34:04 tsi Exp $ */
 
2
 
 
3
#ifdef HAVE_XORG_CONFIG_H
 
4
#include <xorg-config.h>
 
5
#endif
 
6
 
 
7
#include <X11/X.h>
 
8
#include "misc.h"
 
9
#include "xf86.h"
 
10
#include "xf86_ansic.h"
 
11
#include "xf86_OSproc.h"
 
12
 
 
13
#include "scrnintstr.h"
 
14
#include "pixmapstr.h"
 
15
#include "miline.h"
 
16
#include "xf86str.h"
 
17
#include "xaa.h"
 
18
#include "xaalocal.h"
 
19
 
 
20
 
 
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
 
36
){
 
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;
 
49
 
 
50
    if(!nboxInit)
 
51
        return;
 
52
 
 
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;
 
61
 
 
62
        while (n--)
 
63
#else
 
64
        int n = npt;
 
65
        int xorgtmp = xorg;
 
66
        int yorgtmp = yorg;
 
67
 
 
68
        ppt = pptInit;
 
69
        x2 = ppt->x + xorgtmp;
 
70
        y2 = ppt->y + yorgtmp;
 
71
        while (--n)
 
72
#endif
 
73
        {
 
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;
 
87
            }
 
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;
 
101
            }
 
102
        }
 
103
    }
 
104
 
 
105
    (*infoRec->SetupForSolidLine)(infoRec->pScrn, pGC->fgPixel,
 
106
                                        pGC->alu, pGC->planemask);
 
107
 
 
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
 
116
    {
 
117
        nbox = nboxInit;
 
118
        pbox = pboxInit;
 
119
 
 
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;
 
133
        }
 
134
        x2 = ppt->x + xorg; 
 
135
        y2 = ppt->y + yorg;
 
136
#endif
 
137
 
 
138
        if (x1 == x2) { /* vertical line */
 
139
            /* make the line go top to bottom of screen, keeping
 
140
               endpoint semantics
 
141
            */
 
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
 
149
            }
 
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--;
 
157
            }
 
158
 
 
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);
 
166
                }
 
167
                nbox--;
 
168
                pbox++;
 
169
            }
 
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
 
182
            }
 
183
#ifdef POLYSEGMENT
 
184
            else if (pGC->capStyle != CapNotLast) x2++;
 
185
#endif
 
186
 
 
187
            /* find the correct band */
 
188
            while(nbox && (pbox->y2 <= y1)) {
 
189
                pbox++;
 
190
                nbox--;
 
191
            }
 
192
 
 
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;
 
203
                    }
 
204
 
 
205
                    /* stop if left of box is beyond right of line */
 
206
                    if (pbox->x1 >= x2) {
 
207
                        nbox = 0;
 
208
                        break;
 
209
                    }
 
210
 
 
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++;
 
217
                }
 
218
            }
 
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;
 
225
 
 
226
            if (infoRec->SubsequentSolidBresenhamLine) {
 
227
                if((dmaj = x2 - x1) < 0) {
 
228
                   dmaj = -dmaj;
 
229
                   octant = XDECREASING;
 
230
                } else octant = 0;                 
 
231
 
 
232
                if((dmin = y2 - y1) < 0) {
 
233
                   dmin = -dmin;
 
234
                   octant |= YDECREASING;
 
235
                }       
 
236
        
 
237
                if(dmin >= dmaj){
 
238
                    tmp = dmin; dmin = dmaj; dmaj = tmp;
 
239
                    octant |= YMAJOR;
 
240
                }
 
241
 
 
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;
 
248
            }
 
249
 
 
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
 
262
                        );
 
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);
 
270
                    }
 
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);
 
277
 
 
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
 
292
                        );
 
293
                    }
 
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;
 
300
                    
 
301
                    if(octant & YMAJOR) {
 
302
                        ady = dmaj >> 1;
 
303
                        adx = dmin >> 1;
 
304
                    } else {
 
305
                        ady = dmin >> 1;
 
306
                        adx = dmaj >> 1;
 
307
                    }
 
308
 
 
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)
 
314
                    {
 
315
                        pbox++;
 
316
                        continue;
 
317
                    }
 
318
 
 
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);
 
335
 
 
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;
 
342
 
 
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;
 
352
                        }
 
353
 
 
354
                        (*infoRec->SubsequentSolidBresenhamLine)(
 
355
                                infoRec->pScrn, new_x1, new_y1,
 
356
                                dmaj, dmin, err, len, octant);
 
357
                    }
 
358
                    pbox++;
 
359
                }
 
360
            } /* while (nbox--) */
 
361
        } /* sloped line */
 
362
    } /* while (nline--) */
 
363
 
 
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.)
 
368
    */
 
369
 
 
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)))
 
374
    {
 
375
        nbox = nboxInit;
 
376
        pbox = pboxInit;
 
377
        while (nbox--)
 
378
        {
 
379
            if ((x2 >= pbox->x1) && (y2 >= pbox->y1) &&
 
380
                (x2 <  pbox->x2) && (y2 <  pbox->y2))
 
381
            {
 
382
                (*infoRec->SubsequentSolidHorVertLine)(
 
383
                        infoRec->pScrn, x2, y2, 1, DEGREES_0);
 
384
                break;
 
385
            }
 
386
            else
 
387
                pbox++;
 
388
        }
 
389
    }
 
390
#endif
 
391
 
 
392
    SET_SYNC_FLAG(infoRec);
 
393
}
 
394