mipushpxl.c revision 35c4bbdf
1/***********************************************************
2
3Copyright 1987, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27                        All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Digital not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45******************************************************************/
46#ifdef HAVE_DIX_CONFIG_H
47#include <dix-config.h>
48#endif
49
50#include <X11/X.h>
51#include "gcstruct.h"
52#include "scrnintstr.h"
53#include "pixmapstr.h"
54#include "regionstr.h"
55#include "mi.h"
56#include "servermd.h"
57
58#define NPT 128
59
60/* These were stolen from mfb.  They don't really belong here. */
61#define LONG2CHARSSAMEORDER(x) ((MiBits)(x))
62#define LONG2CHARSDIFFORDER( x ) ( ( ( ( x ) & (MiBits)0x000000FF ) << 0x18 ) \
63                        | ( ( ( x ) & (MiBits)0x0000FF00 ) << 0x08 ) \
64                        | ( ( ( x ) & (MiBits)0x00FF0000 ) >> 0x08 ) \
65                        | ( ( ( x ) & (MiBits)0xFF000000 ) >> 0x18 ) )
66
67#define PGSZB	4
68#define PPW	(PGSZB<<3)      /* assuming 8 bits per byte */
69#define PGSZ	PPW
70#define PLST	(PPW-1)
71#define PIM	PLST
72#define PWSH	5
73
74/* miPushPixels -- squeegees the fill style of pGC through pBitMap
75 * into pDrawable.  pBitMap is a stencil (dx by dy of it is used, it may
76 * be bigger) which is placed on the drawable at xOrg, yOrg.  Where a 1 bit
77 * is set in the bitmap, the fill style is put onto the drawable using
78 * the GC's logical function. The drawable is not changed where the bitmap
79 * has a zero bit or outside the area covered by the stencil.
80
81WARNING:
82    this code works if the 1-bit deep pixmap format returned by GetSpans
83is the same as the format defined by the mfb code (i.e. 32-bit padding
84per scanline, scanline unit = 32 bits; later, this might mean
85bitsizeof(int) padding and sacnline unit == bitsizeof(int).)
86
87 */
88
89/*
90 * in order to have both (MSB_FIRST and LSB_FIRST) versions of this
91 * in the server, we need to rename one of them
92 */
93void
94miPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable,
95             int dx, int dy, int xOrg, int yOrg)
96{
97    int h, dxDivPPW, ibEnd;
98    MiBits *pwLineStart;
99    MiBits *pw, *pwEnd;
100    MiBits msk;
101    int ib, w;
102    int ipt;                    /* index into above arrays */
103    Bool fInBox;
104    DDXPointRec pt[NPT], ptThisLine;
105    int width[NPT];
106
107#if 1
108    MiBits startmask;
109
110    if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
111        if (screenInfo.bitmapBitOrder == LSBFirst)
112            startmask = (MiBits) (-1) ^ LONG2CHARSSAMEORDER((MiBits) (-1) << 1);
113        else
114            startmask = (MiBits) (-1) ^ LONG2CHARSSAMEORDER((MiBits) (-1) >> 1);
115    else if (screenInfo.bitmapBitOrder == LSBFirst)
116        startmask = (MiBits) (-1) ^ LONG2CHARSDIFFORDER((MiBits) (-1) << 1);
117    else
118        startmask = (MiBits) (-1) ^ LONG2CHARSDIFFORDER((MiBits) (-1) >> 1);
119#endif
120
121    pwLineStart = malloc(BitmapBytePad(dx));
122    if (!pwLineStart)
123        return;
124    ipt = 0;
125    dxDivPPW = dx / PPW;
126
127    for (h = 0, ptThisLine.x = 0, ptThisLine.y = 0; h < dy; h++, ptThisLine.y++) {
128
129        (*pBitMap->drawable.pScreen->GetSpans) ((DrawablePtr) pBitMap, dx,
130                                                &ptThisLine, &dx, 1,
131                                                (char *) pwLineStart);
132
133        pw = pwLineStart;
134        /* Process all words which are fully in the pixmap */
135
136        fInBox = FALSE;
137        pwEnd = pwLineStart + dxDivPPW;
138        while (pw < pwEnd) {
139            w = *pw;
140#if 1
141            msk = startmask;
142#else
143            msk = (MiBits) (-1) ^ SCRRIGHT((MiBits) (-1), 1);
144#endif
145            for (ib = 0; ib < PPW; ib++) {
146                if (w & msk) {
147                    if (!fInBox) {
148                        pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg;
149                        pt[ipt].y = h + yOrg;
150                        /* start new box */
151                        fInBox = TRUE;
152                    }
153                }
154                else {
155                    if (fInBox) {
156                        width[ipt] = ((pw - pwLineStart) << PWSH) +
157                            ib + xOrg - pt[ipt].x;
158                        if (++ipt >= NPT) {
159                            (*pGC->ops->FillSpans) (pDrawable, pGC,
160                                                    NPT, pt, width, TRUE);
161                            ipt = 0;
162                        }
163                        /* end box */
164                        fInBox = FALSE;
165                    }
166                }
167#if 1
168                /* This is not quite right, but it'll do for now */
169                if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
170                    if (screenInfo.bitmapBitOrder == LSBFirst)
171                        msk =
172                            LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1);
173                    else
174                        msk =
175                            LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1);
176                else if (screenInfo.bitmapBitOrder == LSBFirst)
177                    msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1);
178                else
179                    msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1);
180#else
181                msk = SCRRIGHT(msk, 1);
182#endif
183            }
184            pw++;
185        }
186        ibEnd = dx & PIM;
187        if (ibEnd) {
188            /* Process final partial word on line */
189            w = *pw;
190#if 1
191            msk = startmask;
192#else
193            msk = (MiBits) (-1) ^ SCRRIGHT((MiBits) (-1), 1);
194#endif
195            for (ib = 0; ib < ibEnd; ib++) {
196                if (w & msk) {
197                    if (!fInBox) {
198                        /* start new box */
199                        pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg;
200                        pt[ipt].y = h + yOrg;
201                        fInBox = TRUE;
202                    }
203                }
204                else {
205                    if (fInBox) {
206                        /* end box */
207                        width[ipt] = ((pw - pwLineStart) << PWSH) +
208                            ib + xOrg - pt[ipt].x;
209                        if (++ipt >= NPT) {
210                            (*pGC->ops->FillSpans) (pDrawable,
211                                                    pGC, NPT, pt, width, TRUE);
212                            ipt = 0;
213                        }
214                        fInBox = FALSE;
215                    }
216                }
217#if 1
218                /* This is not quite right, but it'll do for now */
219                if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
220                    if (screenInfo.bitmapBitOrder == LSBFirst)
221                        msk =
222                            LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1);
223                    else
224                        msk =
225                            LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1);
226                else if (screenInfo.bitmapBitOrder == LSBFirst)
227                    msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1);
228                else
229                    msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1);
230#else
231                msk = SCRRIGHT(msk, 1);
232#endif
233            }
234        }
235        /* If scanline ended with last bit set, end the box */
236        if (fInBox) {
237            width[ipt] = dx + xOrg - pt[ipt].x;
238            if (++ipt >= NPT) {
239                (*pGC->ops->FillSpans) (pDrawable, pGC, NPT, pt, width, TRUE);
240                ipt = 0;
241            }
242        }
243    }
244    free(pwLineStart);
245    /* Flush any remaining spans */
246    if (ipt) {
247        (*pGC->ops->FillSpans) (pDrawable, pGC, ipt, pt, width, TRUE);
248    }
249}
250