105b261ecSmrg/***********************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2605b261ecSmrg
2705b261ecSmrg                        All Rights Reserved
2805b261ecSmrg
2935c4bbdfSmrgPermission to use, copy, modify, and distribute this software and its
3035c4bbdfSmrgdocumentation for any purpose and without fee is hereby granted,
3105b261ecSmrgprovided that the above copyright notice appear in all copies and that
3235c4bbdfSmrgboth that copyright notice and this permission notice appear in
3305b261ecSmrgsupporting documentation, and that the name of Digital not be
3405b261ecSmrgused in advertising or publicity pertaining to distribution of the
3535c4bbdfSmrgsoftware without specific, written prior permission.
3605b261ecSmrg
3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4305b261ecSmrgSOFTWARE.
4405b261ecSmrg
4505b261ecSmrg******************************************************************/
4605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
4705b261ecSmrg#include <dix-config.h>
4805b261ecSmrg#endif
4905b261ecSmrg
5005b261ecSmrg#include <X11/X.h>
5105b261ecSmrg#include "gcstruct.h"
5205b261ecSmrg#include "scrnintstr.h"
5305b261ecSmrg#include "pixmapstr.h"
5405b261ecSmrg#include "regionstr.h"
5505b261ecSmrg#include "mi.h"
564642e01fSmrg#include "servermd.h"
5705b261ecSmrg
5805b261ecSmrg#define NPT 128
5905b261ecSmrg
604642e01fSmrg/* These were stolen from mfb.  They don't really belong here. */
614642e01fSmrg#define LONG2CHARSSAMEORDER(x) ((MiBits)(x))
624642e01fSmrg#define LONG2CHARSDIFFORDER( x ) ( ( ( ( x ) & (MiBits)0x000000FF ) << 0x18 ) \
634642e01fSmrg                        | ( ( ( x ) & (MiBits)0x0000FF00 ) << 0x08 ) \
644642e01fSmrg                        | ( ( ( x ) & (MiBits)0x00FF0000 ) >> 0x08 ) \
654642e01fSmrg                        | ( ( ( x ) & (MiBits)0xFF000000 ) >> 0x18 ) )
664642e01fSmrg
674642e01fSmrg#define PGSZB	4
6835c4bbdfSmrg#define PPW	(PGSZB<<3)      /* assuming 8 bits per byte */
694642e01fSmrg#define PGSZ	PPW
704642e01fSmrg#define PLST	(PPW-1)
714642e01fSmrg#define PIM	PLST
724642e01fSmrg#define PWSH	5
734642e01fSmrg
7405b261ecSmrg/* miPushPixels -- squeegees the fill style of pGC through pBitMap
7505b261ecSmrg * into pDrawable.  pBitMap is a stencil (dx by dy of it is used, it may
7605b261ecSmrg * be bigger) which is placed on the drawable at xOrg, yOrg.  Where a 1 bit
7705b261ecSmrg * is set in the bitmap, the fill style is put onto the drawable using
7805b261ecSmrg * the GC's logical function. The drawable is not changed where the bitmap
7905b261ecSmrg * has a zero bit or outside the area covered by the stencil.
8005b261ecSmrg
8105b261ecSmrgWARNING:
8205b261ecSmrg    this code works if the 1-bit deep pixmap format returned by GetSpans
8305b261ecSmrgis the same as the format defined by the mfb code (i.e. 32-bit padding
8405b261ecSmrgper scanline, scanline unit = 32 bits; later, this might mean
8505b261ecSmrgbitsizeof(int) padding and sacnline unit == bitsizeof(int).)
8605b261ecSmrg
8705b261ecSmrg */
8805b261ecSmrg
8905b261ecSmrg/*
9005b261ecSmrg * in order to have both (MSB_FIRST and LSB_FIRST) versions of this
9105b261ecSmrg * in the server, we need to rename one of them
9205b261ecSmrg */
934642e01fSmrgvoid
944642e01fSmrgmiPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable,
954642e01fSmrg             int dx, int dy, int xOrg, int yOrg)
9605b261ecSmrg{
9735c4bbdfSmrg    int h, dxDivPPW, ibEnd;
9835c4bbdfSmrg    MiBits *pwLineStart;
9935c4bbdfSmrg    MiBits *pw, *pwEnd;
10035c4bbdfSmrg    MiBits msk;
10135c4bbdfSmrg    int ib, w;
10235c4bbdfSmrg    int ipt;                    /* index into above arrays */
10335c4bbdfSmrg    Bool fInBox;
10435c4bbdfSmrg    DDXPointRec pt[NPT], ptThisLine;
10535c4bbdfSmrg    int width[NPT];
10635c4bbdfSmrg
10705b261ecSmrg#if 1
10835c4bbdfSmrg    MiBits startmask;
10935c4bbdfSmrg
11005b261ecSmrg    if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
11135c4bbdfSmrg        if (screenInfo.bitmapBitOrder == LSBFirst)
11235c4bbdfSmrg            startmask = (MiBits) (-1) ^ LONG2CHARSSAMEORDER((MiBits) (-1) << 1);
11335c4bbdfSmrg        else
11435c4bbdfSmrg            startmask = (MiBits) (-1) ^ LONG2CHARSSAMEORDER((MiBits) (-1) >> 1);
11535c4bbdfSmrg    else if (screenInfo.bitmapBitOrder == LSBFirst)
11635c4bbdfSmrg        startmask = (MiBits) (-1) ^ LONG2CHARSDIFFORDER((MiBits) (-1) << 1);
11705b261ecSmrg    else
11835c4bbdfSmrg        startmask = (MiBits) (-1) ^ LONG2CHARSDIFFORDER((MiBits) (-1) >> 1);
11905b261ecSmrg#endif
12005b261ecSmrg
1216747b715Smrg    pwLineStart = malloc(BitmapBytePad(dx));
12205b261ecSmrg    if (!pwLineStart)
12335c4bbdfSmrg        return;
12405b261ecSmrg    ipt = 0;
12535c4bbdfSmrg    dxDivPPW = dx / PPW;
12635c4bbdfSmrg
12735c4bbdfSmrg    for (h = 0, ptThisLine.x = 0, ptThisLine.y = 0; h < dy; h++, ptThisLine.y++) {
12805b261ecSmrg
12935c4bbdfSmrg        (*pBitMap->drawable.pScreen->GetSpans) ((DrawablePtr) pBitMap, dx,
13035c4bbdfSmrg                                                &ptThisLine, &dx, 1,
13135c4bbdfSmrg                                                (char *) pwLineStart);
13205b261ecSmrg
13335c4bbdfSmrg        pw = pwLineStart;
13435c4bbdfSmrg        /* Process all words which are fully in the pixmap */
13505b261ecSmrg
13635c4bbdfSmrg        fInBox = FALSE;
13735c4bbdfSmrg        pwEnd = pwLineStart + dxDivPPW;
13835c4bbdfSmrg        while (pw < pwEnd) {
13935c4bbdfSmrg            w = *pw;
14005b261ecSmrg#if 1
14135c4bbdfSmrg            msk = startmask;
14205b261ecSmrg#else
14335c4bbdfSmrg            msk = (MiBits) (-1) ^ SCRRIGHT((MiBits) (-1), 1);
14405b261ecSmrg#endif
14535c4bbdfSmrg            for (ib = 0; ib < PPW; ib++) {
14635c4bbdfSmrg                if (w & msk) {
14735c4bbdfSmrg                    if (!fInBox) {
14835c4bbdfSmrg                        pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg;
14935c4bbdfSmrg                        pt[ipt].y = h + yOrg;
15035c4bbdfSmrg                        /* start new box */
15135c4bbdfSmrg                        fInBox = TRUE;
15235c4bbdfSmrg                    }
15335c4bbdfSmrg                }
15435c4bbdfSmrg                else {
15535c4bbdfSmrg                    if (fInBox) {
15635c4bbdfSmrg                        width[ipt] = ((pw - pwLineStart) << PWSH) +
15735c4bbdfSmrg                            ib + xOrg - pt[ipt].x;
15835c4bbdfSmrg                        if (++ipt >= NPT) {
15935c4bbdfSmrg                            (*pGC->ops->FillSpans) (pDrawable, pGC,
16035c4bbdfSmrg                                                    NPT, pt, width, TRUE);
16135c4bbdfSmrg                            ipt = 0;
16235c4bbdfSmrg                        }
16335c4bbdfSmrg                        /* end box */
16435c4bbdfSmrg                        fInBox = FALSE;
16535c4bbdfSmrg                    }
16635c4bbdfSmrg                }
16705b261ecSmrg#if 1
16835c4bbdfSmrg                /* This is not quite right, but it'll do for now */
16935c4bbdfSmrg                if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
17035c4bbdfSmrg                    if (screenInfo.bitmapBitOrder == LSBFirst)
17135c4bbdfSmrg                        msk =
17235c4bbdfSmrg                            LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1);
17335c4bbdfSmrg                    else
17435c4bbdfSmrg                        msk =
17535c4bbdfSmrg                            LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1);
17635c4bbdfSmrg                else if (screenInfo.bitmapBitOrder == LSBFirst)
17735c4bbdfSmrg                    msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1);
17835c4bbdfSmrg                else
17935c4bbdfSmrg                    msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1);
18005b261ecSmrg#else
18135c4bbdfSmrg                msk = SCRRIGHT(msk, 1);
18205b261ecSmrg#endif
18335c4bbdfSmrg            }
18435c4bbdfSmrg            pw++;
18535c4bbdfSmrg        }
18635c4bbdfSmrg        ibEnd = dx & PIM;
18735c4bbdfSmrg        if (ibEnd) {
18835c4bbdfSmrg            /* Process final partial word on line */
18935c4bbdfSmrg            w = *pw;
19005b261ecSmrg#if 1
19135c4bbdfSmrg            msk = startmask;
19205b261ecSmrg#else
19335c4bbdfSmrg            msk = (MiBits) (-1) ^ SCRRIGHT((MiBits) (-1), 1);
19405b261ecSmrg#endif
19535c4bbdfSmrg            for (ib = 0; ib < ibEnd; ib++) {
19635c4bbdfSmrg                if (w & msk) {
19735c4bbdfSmrg                    if (!fInBox) {
19835c4bbdfSmrg                        /* start new box */
19935c4bbdfSmrg                        pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg;
20035c4bbdfSmrg                        pt[ipt].y = h + yOrg;
20135c4bbdfSmrg                        fInBox = TRUE;
20235c4bbdfSmrg                    }
20335c4bbdfSmrg                }
20435c4bbdfSmrg                else {
20535c4bbdfSmrg                    if (fInBox) {
20635c4bbdfSmrg                        /* end box */
20735c4bbdfSmrg                        width[ipt] = ((pw - pwLineStart) << PWSH) +
20835c4bbdfSmrg                            ib + xOrg - pt[ipt].x;
20935c4bbdfSmrg                        if (++ipt >= NPT) {
21035c4bbdfSmrg                            (*pGC->ops->FillSpans) (pDrawable,
21135c4bbdfSmrg                                                    pGC, NPT, pt, width, TRUE);
21235c4bbdfSmrg                            ipt = 0;
21335c4bbdfSmrg                        }
21435c4bbdfSmrg                        fInBox = FALSE;
21535c4bbdfSmrg                    }
21635c4bbdfSmrg                }
21705b261ecSmrg#if 1
21835c4bbdfSmrg                /* This is not quite right, but it'll do for now */
21935c4bbdfSmrg                if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
22035c4bbdfSmrg                    if (screenInfo.bitmapBitOrder == LSBFirst)
22135c4bbdfSmrg                        msk =
22235c4bbdfSmrg                            LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1);
22335c4bbdfSmrg                    else
22435c4bbdfSmrg                        msk =
22535c4bbdfSmrg                            LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1);
22635c4bbdfSmrg                else if (screenInfo.bitmapBitOrder == LSBFirst)
22735c4bbdfSmrg                    msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1);
22835c4bbdfSmrg                else
22935c4bbdfSmrg                    msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1);
23005b261ecSmrg#else
23135c4bbdfSmrg                msk = SCRRIGHT(msk, 1);
23205b261ecSmrg#endif
23335c4bbdfSmrg            }
23435c4bbdfSmrg        }
23535c4bbdfSmrg        /* If scanline ended with last bit set, end the box */
23635c4bbdfSmrg        if (fInBox) {
23735c4bbdfSmrg            width[ipt] = dx + xOrg - pt[ipt].x;
23835c4bbdfSmrg            if (++ipt >= NPT) {
23935c4bbdfSmrg                (*pGC->ops->FillSpans) (pDrawable, pGC, NPT, pt, width, TRUE);
24035c4bbdfSmrg                ipt = 0;
24135c4bbdfSmrg            }
24235c4bbdfSmrg        }
24305b261ecSmrg    }
2446747b715Smrg    free(pwLineStart);
24505b261ecSmrg    /* Flush any remaining spans */
24635c4bbdfSmrg    if (ipt) {
24735c4bbdfSmrg        (*pGC->ops->FillSpans) (pDrawable, pGC, ipt, pt, width, TRUE);
24805b261ecSmrg    }
24905b261ecSmrg}
250