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