]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mfb/mfbfillsp.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / mfb / mfbfillsp.c
1 /* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */
2 /***********************************************************
3
4 Copyright (c) 1987  X Consortium
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23 Except as contained in this notice, the name of the X Consortium shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the X Consortium.
26
27
28 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
29
30                         All Rights Reserved
31
32 Permission to use, copy, modify, and distribute this software and its 
33 documentation for any purpose and without fee is hereby granted, 
34 provided that the above copyright notice appear in all copies and that
35 both that copyright notice and this permission notice appear in 
36 supporting documentation, and that the name of Digital not be
37 used in advertising or publicity pertaining to distribution of the
38 software without specific, written prior permission.  
39
40 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
41 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
42 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
43 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
44 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
45 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 SOFTWARE.
47
48 ******************************************************************/
49 /* $XConsortium: mfbfillsp.c,v 5.13 94/04/17 20:28:21 dpw Exp $ */
50 #include "X.h"
51 #include "Xmd.h"
52 #include "gcstruct.h"
53 #include "window.h"
54 #include "pixmapstr.h"
55 #include "scrnintstr.h"
56 #include "windowstr.h"
57 #include "mfb.h"
58 #include "maskbits.h"
59
60 #include "mergerop.h"
61
62 #include "servermd.h"
63 #include "mi.h"
64 #include "mispans.h"
65
66 /* scanline filling for monochrome frame buffer
67    written by drewry, oct 1986
68
69    these routines all clip.  they assume that anything that has called
70 them has already translated the points (i.e. pGC->miTranslate is
71 non-zero, which is howit gets set in mfbCreateGC().)
72
73    the number of new scnalines created by clipping ==
74 MaxRectsPerBand * nSpans.
75
76     FillSolid is overloaded to be used for OpaqueStipple as well,
77 if fgPixel == bgPixel.  
78
79
80     FillTiled is overloaded to be used for OpaqueStipple, if
81 fgPixel != bgPixel.  based on the fill style, it uses
82 {RotatedPixmap, gc.alu} or {RotatedPixmap, PrivGC.ropOpStip}
83 */
84
85
86 void
87 mfbBlackSolidFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
88     DrawablePtr pDrawable;
89     GCPtr       pGC;
90     int         nInit;          /* number of spans to fill */
91     DDXPointPtr pptInit;        /* pointer to list of start points */
92     int         *pwidthInit;    /* pointer to list of n widths */
93     int         fSorted;
94 {
95                                 /* next three parameters are post-clip */
96     int n;                      /* number of spans to fill */
97     register DDXPointPtr ppt;   /* pointer to list of start points */
98     register int *pwidth;       /* pointer to list of n widths */
99     PixelType *addrlBase;       /* pointer to start of bitmap */
100     int nlwidth;                /* width in longwords of bitmap */
101     register PixelType *addrl;/* pointer to current longword in bitmap */
102     register int nlmiddle;
103     register PixelType startmask;
104     register PixelType endmask;
105     int *pwidthFree;            /* copies of the pointers to free */
106     DDXPointPtr pptFree;
107
108     if (!(pGC->planemask & 1))
109         return;
110
111     n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
112     pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int));
113     pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec));
114     if(!pptFree || !pwidthFree)
115     {
116         if (pptFree) DEALLOCATE_LOCAL(pptFree);
117         if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
118         return;
119     }
120     pwidth = pwidthFree;
121     ppt = pptFree;
122     n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip,
123                     pptInit, pwidthInit, nInit,
124                     ppt, pwidth, fSorted);
125
126     mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
127
128     while (n--)
129     {
130         addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
131
132         if (*pwidth)
133         {
134             if ( ((ppt->x & PIM) + *pwidth) < PPW)
135             {
136                 /* all bits inside same longword */
137                 maskpartialbits(ppt->x, *pwidth, startmask);
138                     *addrl &= ~startmask;
139             }
140             else
141             {
142                 maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle);
143                 if (startmask)
144                     *addrl++ &= ~startmask;
145                 Duff (nlmiddle, *addrl++ = 0x0);
146                 if (endmask)
147                     *addrl &= ~endmask;
148             }
149         }
150         pwidth++;
151         ppt++;
152     }
153     DEALLOCATE_LOCAL(pptFree);
154     DEALLOCATE_LOCAL(pwidthFree);
155 }
156
157
158
159 void
160 mfbWhiteSolidFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
161     DrawablePtr pDrawable;
162     GCPtr       pGC;
163     int         nInit;          /* number of spans to fill */
164     DDXPointPtr pptInit;        /* pointer to list of start points */
165     int         *pwidthInit;    /* pointer to list of n widths */
166     int         fSorted;
167 {
168                                 /* next three parameters are post-clip */
169     int n;                      /* number of spans to fill */
170     register DDXPointPtr ppt;   /* pointer to list of start points */
171     register int *pwidth;       /* pointer to list of n widths */
172     PixelType *addrlBase;       /* pointer to start of bitmap */
173     int nlwidth;                /* width in longwords of bitmap */
174     register PixelType *addrl;/* pointer to current longword in bitmap */
175     register int nlmiddle;
176     register PixelType startmask;
177     register PixelType endmask;
178     int *pwidthFree;            /* copies of the pointers to free */
179     DDXPointPtr pptFree;
180
181     if (!(pGC->planemask & 1))
182         return;
183
184     n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
185     pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int));
186     pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec));
187     if(!pptFree || !pwidthFree)
188     {
189         if (pptFree) DEALLOCATE_LOCAL(pptFree);
190         if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
191         return;
192     }
193     pwidth = pwidthFree;
194     ppt = pptFree;
195     n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip,
196                     pptInit, pwidthInit, nInit,
197                     ppt, pwidth, fSorted);
198
199     mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
200
201     while (n--)
202     {
203         addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
204
205         if (*pwidth)
206         {
207             if ( ((ppt->x & PIM) + *pwidth) < PPW)
208             {
209                 /* all bits inside same longword */
210                 maskpartialbits(ppt->x, *pwidth, startmask);
211                 *addrl |= startmask;
212             }
213             else
214             {
215                 maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle);
216                 if (startmask)
217                     *addrl++ |= startmask;
218                 Duff (nlmiddle, *addrl++ = ~0);
219                 if (endmask)
220                     *addrl |= endmask;
221             }
222         }
223         pwidth++;
224         ppt++;
225     }
226     DEALLOCATE_LOCAL(pptFree);
227     DEALLOCATE_LOCAL(pwidthFree);
228 }
229
230
231
232 void
233 mfbInvertSolidFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
234     DrawablePtr pDrawable;
235     GCPtr       pGC;
236     int         nInit;          /* number of spans to fill */
237     DDXPointPtr pptInit;        /* pointer to list of start points */
238     int         *pwidthInit;    /* pointer to list of n widths */
239     int         fSorted;
240 {
241                                 /* next three parameters are post-clip */
242     int n;                      /* number of spans to fill */
243     register DDXPointPtr ppt;   /* pointer to list of start points */
244     register int *pwidth;       /* pointer to list of n widths */
245     PixelType *addrlBase;       /* pointer to start of bitmap */
246     int nlwidth;                /* width in longwords of bitmap */
247     register PixelType *addrl;/* pointer to current longword in bitmap */
248     register int nlmiddle;
249     register PixelType startmask;
250     register PixelType endmask;
251     int *pwidthFree;            /* copies of the pointers to free */
252     DDXPointPtr pptFree;
253
254     if (!(pGC->planemask & 1))
255         return;
256
257     n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
258     pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int));
259     pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec));
260     if(!pptFree || !pwidthFree)
261     {
262         if (pptFree) DEALLOCATE_LOCAL(pptFree);
263         if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
264         return;
265     }
266     pwidth = pwidthFree;
267     ppt = pptFree;
268     n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip,
269                     pptInit, pwidthInit, nInit,
270                     ppt, pwidth, fSorted);
271
272     mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
273
274     while (n--)
275     {
276         addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
277
278         if (*pwidth)
279         {
280             if ( ((ppt->x & PIM) + *pwidth) < PPW)
281             {
282                 /* all bits inside same longword */
283                 maskpartialbits(ppt->x, *pwidth, startmask);
284                 *addrl ^= startmask;
285             }
286             else
287             {
288                 maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle);
289                 if (startmask)
290                     *addrl++ ^= startmask;
291                 Duff (nlmiddle, *addrl++ ^= ~0);
292                 if (endmask)
293                     *addrl ^= endmask;
294             }
295         }
296         pwidth++;
297         ppt++;
298     }
299     DEALLOCATE_LOCAL(pptFree);
300     DEALLOCATE_LOCAL(pwidthFree);
301 }
302
303
304 void 
305 mfbWhiteStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
306     DrawablePtr pDrawable;
307     GC *pGC;
308     int nInit;                  /* number of spans to fill */
309     DDXPointPtr pptInit;        /* pointer to list of start points */
310     int *pwidthInit;            /* pointer to list of n widths */
311     int fSorted;
312 {
313                                 /* next three parameters are post-clip */
314     int n;                      /* number of spans to fill */
315     register DDXPointPtr ppt;   /* pointer to list of start points */
316     register int *pwidth;       /* pointer to list of n widths */
317     PixelType *addrlBase;       /* pointer to start of bitmap */
318     int nlwidth;                /* width in longwords of bitmap */
319     register PixelType *addrl;/* pointer to current longword in bitmap */
320     register PixelType src;
321     register int nlmiddle;
322     register PixelType startmask;
323     register PixelType endmask;
324     PixmapPtr pStipple;
325     PixelType *psrc;
326     int tileHeight;
327     int *pwidthFree;            /* copies of the pointers to free */
328     DDXPointPtr pptFree;
329
330     if (!(pGC->planemask & 1))
331         return;
332
333     n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
334     pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int));
335     pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec));
336     if(!pptFree || !pwidthFree)
337     {
338         if (pptFree) DEALLOCATE_LOCAL(pptFree);
339         if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
340         return;
341     }
342     pwidth = pwidthFree;
343     ppt = pptFree;
344     n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip,
345                     pptInit, pwidthInit, nInit, 
346                     ppt, pwidth, fSorted);
347
348     mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
349
350     pStipple = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pRotatedPixmap;
351     tileHeight = pStipple->drawable.height;
352     psrc = (PixelType *)(pStipple->devPrivate.ptr);
353
354     while (n--)
355     {
356         addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
357         src = psrc[ppt->y % tileHeight];
358
359         /* all bits inside same longword */
360         if ( ((ppt->x & PIM) + *pwidth) < PPW)
361         {
362             maskpartialbits(ppt->x, *pwidth, startmask);
363             *addrl |= (src & startmask);
364         }
365         else
366         {
367             maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle);
368             if (startmask)
369                 *addrl++ |= (src & startmask);
370             Duff (nlmiddle, *addrl++ |= src);
371             if (endmask)
372                 *addrl |= (src & endmask);
373         }
374         pwidth++;
375         ppt++;
376     }
377     DEALLOCATE_LOCAL(pptFree);
378     DEALLOCATE_LOCAL(pwidthFree);
379 }
380
381
382 void 
383 mfbBlackStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
384     DrawablePtr pDrawable;
385     GC *pGC;
386     int nInit;                  /* number of spans to fill */
387     DDXPointPtr pptInit;        /* pointer to list of start points */
388     int *pwidthInit;            /* pointer to list of n widths */
389     int fSorted;
390 {
391                                 /* next three parameters are post-clip */
392     int n;                      /* number of spans to fill */
393     register DDXPointPtr ppt;   /* pointer to list of start points */
394     register int *pwidth;       /* pointer to list of n widths */
395     PixelType *addrlBase;       /* pointer to start of bitmap */
396     int nlwidth;                /* width in longwords of bitmap */
397     register PixelType *addrl;  /* pointer to current longword in bitmap */
398     register PixelType src;
399     register int nlmiddle;
400     register PixelType startmask;
401     register PixelType endmask;
402     PixmapPtr pStipple;
403     PixelType *psrc;
404     int tileHeight;
405     int *pwidthFree;            /* copies of the pointers to free */
406     DDXPointPtr pptFree;
407
408     if (!(pGC->planemask & 1))
409         return;
410
411     n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
412     pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int));
413     pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec));
414     if(!pptFree || !pwidthFree)
415     {
416         if (pptFree) DEALLOCATE_LOCAL(pptFree);
417         if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
418         return;
419     }
420     pwidth = pwidthFree;
421     ppt = pptFree;
422     n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip,
423                     pptInit, pwidthInit, nInit, 
424                     ppt, pwidth, fSorted);
425
426     mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
427
428     pStipple = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pRotatedPixmap;
429     tileHeight = pStipple->drawable.height;
430     psrc = (PixelType *)(pStipple->devPrivate.ptr);
431
432     while (n--)
433     {
434         addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
435         src = psrc[ppt->y % tileHeight];
436
437         /* all bits inside same longword */
438         if ( ((ppt->x & PIM) + *pwidth) < PPW)
439         {
440             maskpartialbits(ppt->x, *pwidth, startmask);
441             *addrl &= ~(src & startmask);
442         }
443         else
444         {
445             maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle);
446             if (startmask)
447                 *addrl++ &= ~(src & startmask);
448             Duff (nlmiddle, *addrl++ &= ~src);
449             if (endmask)
450                 *addrl &= ~(src & endmask);
451         }
452         pwidth++;
453         ppt++;
454     }
455     DEALLOCATE_LOCAL(pptFree);
456     DEALLOCATE_LOCAL(pwidthFree);
457 }
458
459
460 void 
461 mfbInvertStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
462     DrawablePtr pDrawable;
463     GC *pGC;
464     int nInit;                  /* number of spans to fill */
465     DDXPointPtr pptInit;        /* pointer to list of start points */
466     int *pwidthInit;            /* pointer to list of n widths */
467     int fSorted;
468 {
469                                 /* next three parameters are post-clip */
470     int n;                      /* number of spans to fill */
471     register DDXPointPtr ppt;   /* pointer to list of start points */
472     register int *pwidth;       /* pointer to list of n widths */
473     PixelType *addrlBase;       /* pointer to start of bitmap */
474     int nlwidth;                /* width in longwords of bitmap */
475     register PixelType *addrl;  /* pointer to current longword in bitmap */
476     register PixelType src;
477     register int nlmiddle;
478     register PixelType startmask;
479     register PixelType endmask;
480     PixmapPtr pStipple;
481     PixelType *psrc;
482     int tileHeight;
483     int *pwidthFree;            /* copies of the pointers to free */
484     DDXPointPtr pptFree;
485
486     if (!(pGC->planemask & 1))
487         return;
488
489     n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
490     pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int));
491     pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec));
492     if(!pptFree || !pwidthFree)
493     {
494         if (pptFree) DEALLOCATE_LOCAL(pptFree);
495         if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
496         return;
497     }
498     pwidth = pwidthFree;
499     ppt = pptFree;
500     n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip,
501                     pptInit, pwidthInit, nInit, 
502                     ppt, pwidth, fSorted);
503
504     mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
505
506     pStipple = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pRotatedPixmap;
507     tileHeight = pStipple->drawable.height;
508     psrc = (PixelType *)(pStipple->devPrivate.ptr);
509
510     while (n--)
511     {
512         addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
513         src = psrc[ppt->y % tileHeight];
514
515         /* all bits inside same longword */
516         if ( ((ppt->x & PIM) + *pwidth) < PPW)
517         {
518             maskpartialbits(ppt->x, *pwidth, startmask);
519             *addrl ^= (src & startmask);
520         }
521         else
522         {
523             maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle);
524             if (startmask)
525                 *addrl++ ^= (src & startmask);
526             Duff(nlmiddle, *addrl++ ^= src);
527             if (endmask)
528                 *addrl ^= (src & endmask);
529         }
530         pwidth++;
531         ppt++;
532     }
533     DEALLOCATE_LOCAL(pptFree);
534     DEALLOCATE_LOCAL(pwidthFree);
535 }
536
537
538 /* this works with tiles of width == PPW */
539 #define FILLSPANPPW(ROP) \
540     while (n--) \
541     { \
542         if (*pwidth) \
543         { \
544             addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth); \
545             src = psrc[ppt->y % tileHeight]; \
546             if ( ((ppt->x & PIM) + *pwidth) < PPW) \
547             { \
548                 maskpartialbits(ppt->x, *pwidth, startmask); \
549                 *addrl = (*addrl & ~startmask) | \
550                          (ROP(src, *addrl) & startmask); \
551             } \
552             else \
553             { \
554                 maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle); \
555                 if (startmask) \
556                 { \
557                     *addrl = (*addrl & ~startmask) | \
558                              (ROP(src, *addrl) & startmask); \
559                     addrl++; \
560                 } \
561                 while (nlmiddle--) \
562                 { \
563                     *addrl = ROP(src, *addrl); \
564                     addrl++; \
565                 } \
566                 if (endmask) \
567                     *addrl = (*addrl & ~endmask) | \
568                              (ROP(src, *addrl) & endmask); \
569             } \
570         } \
571         pwidth++; \
572         ppt++; \
573     }
574
575
576
577 void
578 mfbTileFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
579     DrawablePtr pDrawable;
580     GC *pGC;
581     int nInit;                  /* number of spans to fill */
582     DDXPointPtr pptInit;        /* pointer to list of start points */
583     int *pwidthInit;            /* pointer to list of n widths */
584     int fSorted;
585 {
586                                 /* next three parameters are post-clip */
587     int n;                      /* number of spans to fill */
588     register DDXPointPtr ppt;   /* pointer to list of start points */
589     register int *pwidth;       /* pointer to list of n widths */
590     PixelType *addrlBase;       /* pointer to start of bitmap */
591     int nlwidth;                /* width in longwords of bitmap */
592     register PixelType *addrl;  /* pointer to current longword in bitmap */
593     register PixelType src;
594     register int nlmiddle;
595     register PixelType startmask;
596     register PixelType endmask;
597     PixmapPtr pTile;
598     PixelType *psrc;
599     int tileHeight;
600     int rop;
601     int *pwidthFree;            /* copies of the pointers to free */
602     DDXPointPtr pptFree;
603     unsigned long   flip;
604
605
606     if (!(pGC->planemask & 1))
607         return;
608
609     n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
610     pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int));
611     pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec));
612     if(!pptFree || !pwidthFree)
613     {
614         if (pptFree) DEALLOCATE_LOCAL(pptFree);
615         if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
616         return;
617     }
618     pwidth = pwidthFree;
619     ppt = pptFree;
620     n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip,
621                     pptInit, pwidthInit, nInit, 
622                     ppt, pwidth, fSorted);
623
624     mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
625
626     pTile = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pRotatedPixmap;
627     tileHeight = pTile->drawable.height;
628     psrc = (PixelType *)(pTile->devPrivate.ptr);
629     if (pGC->fillStyle == FillTiled)
630         rop = pGC->alu;
631     else
632         rop = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->ropOpStip;
633
634     flip = 0;
635     switch(rop)
636     {
637       case GXcopyInverted:  /* for opaque stipples */
638         flip = ~0;
639       case GXcopy:
640         {
641
642 #define DoMaskCopyRop(src,dst,mask)     ((dst) & ~(mask) | (src) & (mask))
643
644             while (n--)
645             {
646                 if (*pwidth)
647                 {
648                     addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
649                     src = psrc[ppt->y % tileHeight] ^ flip;
650                     if ( ((ppt->x & PIM) + *pwidth) < PPW)
651                     {
652                         maskpartialbits(ppt->x, *pwidth, startmask);
653                         *addrl = DoMaskCopyRop (src, *addrl, startmask);
654                     }
655                     else
656                     {
657                         maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle);
658                         if (startmask)
659                         {
660                             *addrl = DoMaskCopyRop (src, *addrl, startmask);
661                             addrl++;
662                         }
663                         while (nlmiddle--)
664                         {
665                             *addrl = src;
666                             addrl++;
667                         }
668                         if (endmask)
669                             *addrl = DoMaskCopyRop (src, *addrl, endmask);
670                     }
671                 }
672                 pwidth++;
673                 ppt++;
674             }
675         }
676         break;
677       default:
678         {
679             register DeclareMergeRop ();
680
681             InitializeMergeRop(rop,~0);
682             while (n--)
683             {
684                 if (*pwidth)
685                 {
686                     addrl = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
687                     src = psrc[ppt->y % tileHeight];
688                     if ( ((ppt->x & PIM) + *pwidth) < PPW)
689                     {
690                         maskpartialbits(ppt->x, *pwidth, startmask);
691                         *addrl = DoMaskMergeRop (src, *addrl, startmask);
692                     }
693                     else
694                     {
695                         maskbits(ppt->x, *pwidth, startmask, endmask, nlmiddle);
696                         if (startmask)
697                         {
698                             *addrl = DoMaskMergeRop (src, *addrl, startmask);
699                             addrl++;
700                         }
701                         while (nlmiddle--)
702                         {
703                             *addrl = DoMergeRop (src, *addrl);
704                             addrl++;
705                         }
706                         if (endmask)
707                             *addrl = DoMaskMergeRop (src, *addrl, endmask);
708                     }
709                 }
710                 pwidth++;
711                 ppt++;
712             }
713         }
714         break;
715     }
716     DEALLOCATE_LOCAL(pptFree);
717     DEALLOCATE_LOCAL(pwidthFree);
718 }
719
720
721 /* Fill spans with tiles that aren't PPW bits wide */
722 void
723 mfbUnnaturalTileFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
724     DrawablePtr pDrawable;
725     GC          *pGC;
726     int         nInit;          /* number of spans to fill */
727     DDXPointPtr pptInit;        /* pointer to list of start points */
728     int *pwidthInit;            /* pointer to list of n widths */
729     int fSorted;
730 {
731     int         iline;          /* first line of tile to use */
732                                 /* next three parameters are post-clip */
733     int n;                      /* number of spans to fill */
734     register DDXPointPtr ppt;   /* pointer to list of start points */
735     register int *pwidth;       /* pointer to list of n widths */
736     PixelType *addrlBase;       /* pointer to start of bitmap */
737     int          nlwidth;       /* width in longwords of bitmap */
738     register PixelType *pdst;/* pointer to current word in bitmap */
739     register PixelType *psrc;/* pointer to current word in tile */
740     register int nlMiddle;
741     register int rop, nstart;
742     PixelType startmask;
743     PixmapPtr   pTile;          /* pointer to tile we want to fill with */
744     int         w, width, x, xSrc, ySrc, srcStartOver, nend;
745     int         tlwidth, rem, tileWidth, tileHeight, endinc;
746     PixelType      endmask, *psrcT;
747     int *pwidthFree;            /* copies of the pointers to free */
748     DDXPointPtr pptFree;
749
750     if (!(pGC->planemask & 1))
751         return;
752
753     n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
754     pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int));
755     pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec));
756     if(!pptFree || !pwidthFree)
757     {
758         if (pptFree) DEALLOCATE_LOCAL(pptFree);
759         if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
760         return;
761     }
762     pwidth = pwidthFree;
763     ppt = pptFree;
764     n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip,
765                     pptInit, pwidthInit, nInit, 
766                     ppt, pwidth, fSorted);
767
768     if (pGC->fillStyle == FillTiled)
769     {
770         pTile = pGC->tile.pixmap;
771         tlwidth = pTile->devKind / PGSZB;
772         rop = pGC->alu;
773     }
774     else
775     {
776         pTile = pGC->stipple;
777         tlwidth = pTile->devKind / PGSZB;
778         rop = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->ropOpStip;
779     }
780
781     xSrc = pDrawable->x;
782     ySrc = pDrawable->y;
783
784     mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
785
786     tileWidth = pTile->drawable.width;
787     tileHeight = pTile->drawable.height;
788
789     /* this replaces rotating the tile. Instead we just adjust the offset
790      * at which we start grabbing bits from the tile.
791      * Ensure that ppt->x - xSrc >= 0 and ppt->y - ySrc >= 0,
792      * so that iline and rem always stay within the tile bounds.
793      */
794     xSrc += (pGC->patOrg.x % tileWidth) - tileWidth;
795     ySrc += (pGC->patOrg.y % tileHeight) - tileHeight;
796
797     while (n--)
798     {
799         iline = (ppt->y - ySrc) % tileHeight;
800         pdst = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
801         psrcT = (PixelType *) pTile->devPrivate.ptr + (iline * tlwidth);
802         x = ppt->x;
803
804         if (*pwidth)
805         {
806             width = *pwidth;
807             while(width > 0)
808             {
809                 psrc = psrcT;
810                 w = min(tileWidth, width);
811                 if((rem = (x - xSrc)  % tileWidth) != 0)
812                 {
813                     /* if we're in the middle of the tile, get
814                        as many bits as will finish the span, or
815                        as many as will get to the left edge of the tile,
816                        or a longword worth, starting at the appropriate
817                        offset in the tile.
818                     */
819                     w = min(min(tileWidth - rem, width), BITMAP_SCANLINE_PAD);
820                     endinc = rem / BITMAP_SCANLINE_PAD;
821                     getandputrop((psrc+endinc), (rem&PIM), (x & PIM), w, pdst, rop);
822                     if((x & PIM) + w >= PPW)
823                         pdst++;
824                 }
825                 else if(((x & PIM) + w) < PPW)
826                 {
827                     /* doing < PPW bits is easy, and worth special-casing */
828                     putbitsrop(*psrc, x & PIM, w, pdst, rop);
829                 }
830                 else
831                 {
832                     /* start at the left edge of the tile,
833                        and put down as much as we can
834                     */
835                     maskbits(x, w, startmask, endmask, nlMiddle);
836
837                     if (startmask)
838                         nstart = PPW - (x & PIM);
839                     else
840                         nstart = 0;
841                     if (endmask)
842                         nend = (x + w)  & PIM;
843                     else
844                         nend = 0;
845
846                     srcStartOver = nstart > PLST;
847
848                     if(startmask)
849                     {
850                         putbitsrop(*psrc, (x & PIM), nstart, pdst, rop);
851                         pdst++;
852                         if(srcStartOver)
853                             psrc++;
854                     }
855                      
856                     while(nlMiddle--)
857                     {
858                             getandputrop0(psrc, nstart, PPW, pdst, rop);
859                             pdst++;
860                             psrc++;
861                     }
862                     if(endmask)
863                     {
864                         getandputrop0(psrc, nstart, nend, pdst, rop);
865                     }
866                  }
867                  x += w;
868                  width -= w;
869             }
870         }
871         ppt++;
872         pwidth++;
873     }
874     DEALLOCATE_LOCAL(pptFree);
875     DEALLOCATE_LOCAL(pwidthFree);
876 }
877
878
879 /* Fill spans with stipples that aren't PPW bits wide */
880 void
881 mfbUnnaturalStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
882     DrawablePtr pDrawable;
883     GC          *pGC;
884     int         nInit;          /* number of spans to fill */
885     DDXPointPtr pptInit;        /* pointer to list of start points */
886     int *pwidthInit;            /* pointer to list of n widths */
887     int fSorted;
888 {
889                                 /* next three parameters are post-clip */
890     int n;                      /* number of spans to fill */
891     register DDXPointPtr ppt;   /* pointer to list of start points */
892     register int *pwidth;       /* pointer to list of n widths */
893     int         iline;          /* first line of tile to use */
894     PixelType           *addrlBase;     /* pointer to start of bitmap */
895     int          nlwidth;       /* width in longwords of bitmap */
896     register PixelType *pdst;           /* pointer to current word in bitmap */
897     register PixelType *psrc;           /* pointer to current word in tile */
898     register int nlMiddle;
899     register int rop, nstart;
900     PixelType startmask;
901     PixmapPtr   pTile;          /* pointer to tile we want to fill with */
902     int         w, width,  x, xSrc, ySrc, srcStartOver, nend;
903     PixelType   endmask, *psrcT;
904     int         tlwidth, rem, tileWidth, endinc;
905     int         tileHeight;
906     int *pwidthFree;            /* copies of the pointers to free */
907     DDXPointPtr pptFree;
908
909     if (!(pGC->planemask & 1))
910         return;
911
912     n = nInit * miFindMaxBand(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
913     pwidthFree = (int *)ALLOCATE_LOCAL(n * sizeof(int));
914     pptFree = (DDXPointRec *)ALLOCATE_LOCAL(n * sizeof(DDXPointRec));
915     if(!pptFree || !pwidthFree)
916     {
917         if (pptFree) DEALLOCATE_LOCAL(pptFree);
918         if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
919         return;
920     }
921     pwidth = pwidthFree;
922     ppt = pptFree;
923     n = miClipSpans(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip,
924                     pptInit, pwidthInit, nInit, 
925                     ppt, pwidth, fSorted);
926
927     pTile = pGC->stipple;
928     rop = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop;
929     tlwidth = pTile->devKind / PGSZB;
930     xSrc = pDrawable->x;
931     ySrc = pDrawable->y;
932     mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
933
934     tileWidth = pTile->drawable.width;
935     tileHeight = pTile->drawable.height;
936
937     /* this replaces rotating the stipple.  Instead, we just adjust the offset
938      * at which we start grabbing bits from the stipple.
939      * Ensure that ppt->x - xSrc >= 0 and ppt->y - ySrc >= 0,
940      * so that iline and rem always stay within the tile bounds.
941      */
942     xSrc += (pGC->patOrg.x % tileWidth) - tileWidth;
943     ySrc += (pGC->patOrg.y % tileHeight) - tileHeight;
944     while (n--)
945     {
946         iline = (ppt->y - ySrc) % tileHeight;
947         pdst = mfbScanline(addrlBase, ppt->x, ppt->y, nlwidth);
948         psrcT = (PixelType *) pTile->devPrivate.ptr + (iline * tlwidth);
949         x = ppt->x;
950
951         if (*pwidth)
952         {
953             width = *pwidth;
954             while(width > 0)
955             {
956                 psrc = psrcT;
957                 w = min(tileWidth, width);
958                 if((rem = (x - xSrc) % tileWidth) != 0)
959                 {
960                     /* if we're in the middle of the tile, get
961                        as many bits as will finish the span, or
962                        as many as will get to the left edge of the tile,
963                        or a longword worth, starting at the appropriate
964                        offset in the tile.
965                     */
966                     w = min(min(tileWidth - rem, width), BITMAP_SCANLINE_PAD);
967                     endinc = rem / BITMAP_SCANLINE_PAD;
968                     getandputrrop((psrc + endinc), (rem & PIM), (x & PIM),
969                                  w, pdst, rop)
970                     if((x & PIM) + w >= PPW)
971                         pdst++;
972                 }
973
974                 else if(((x & PIM) + w) < PPW)
975                 {
976                     /* doing < PPW bits is easy, and worth special-casing */
977                     putbitsrrop(*psrc, x & PIM, w, pdst, rop);
978                 }
979                 else
980                 {
981                     /* start at the left edge of the tile,
982                        and put down as much as we can
983                     */
984                     maskbits(x, w, startmask, endmask, nlMiddle);
985
986                     if (startmask)
987                         nstart = PPW - (x & PIM);
988                     else
989                         nstart = 0;
990                     if (endmask)
991                         nend = (x + w)  & PIM;
992                     else
993                         nend = 0;
994
995                     srcStartOver = nstart > PLST;
996
997                     if(startmask)
998                     {
999                         putbitsrrop(*psrc, (x & PIM), nstart, pdst, rop);
1000                         pdst++;
1001                         if(srcStartOver)
1002                             psrc++;
1003                     }
1004                      
1005                     while(nlMiddle--)
1006                     {
1007                             getandputrrop0(psrc, nstart, PPW, pdst, rop);
1008                             pdst++;
1009                             psrc++;
1010                     }
1011                     if(endmask)
1012                     {
1013                         getandputrrop0(psrc, nstart, nend, pdst, rop);
1014                     }
1015                  }
1016                  x += w;
1017                  width -= w;
1018             }
1019         }
1020         ppt++;
1021         pwidth++;
1022     }
1023     DEALLOCATE_LOCAL(pptFree);
1024     DEALLOCATE_LOCAL(pwidthFree);
1025 }