예제 #1
0
void
fbGlyph24(FbBits * dstBits,
          FbStride dstStride,
          int dstBpp, FbStip * stipple, FbBits fg, int x, int height)
{
    int lshift;

    FbStip bits;

    CARD8 *dstLine;

    CARD8 *dst;

    FbStip f0, f1, f2;

    int n;

    int shift;

    f0 = fg;
    f1 = FbRot24(f0, 16);
    f2 = FbRot24(f0, 8);

    dstLine = (CARD8 *) dstBits;
    dstLine += (x & ~3) * 3;
    dstStride *= (sizeof(FbBits) / sizeof(CARD8));
    shift = x & 3;
    lshift = 4 - shift;
    while (height--) {
        bits = *stipple++;
        n = lshift;
        dst = dstLine;
        while (bits) {
            switch (FbStipMoveLsb(FbLeftStipBits(bits, n), 4, n)) {
            case CASE(0, 0, 0, 0):
                break;
            case CASE(1, 0, 0, 0):
                WRITE2(dst, 0, _AB);
                WRITE1(dst, 2, _C);
                break;
            case CASE(0, 1, 0, 0):
                WRITE1(dst, 3, _A);
                WRITE2(dst, 4, _BC);
                break;
            case CASE(1, 1, 0, 0):
                WRITE4(dst, 0, _ABCA);
                WRITE2(dst, 4, _BC);
                break;
            case CASE(0, 0, 1, 0):
                WRITE2(dst, 6, _AB);
                WRITE1(dst, 8, _C);
                break;
            case CASE(1, 0, 1, 0):
                WRITE2(dst, 0, _AB);
                WRITE1(dst, 2, _C);

                WRITE2(dst, 6, _AB);
                WRITE1(dst, 8, _C);
                break;
            case CASE(0, 1, 1, 0):
                WRITE1(dst, 3, _A);
                WRITE4(dst, 4, _BCAB);
                WRITE1(dst, 8, _C);
                break;
            case CASE(1, 1, 1, 0):
                WRITE8(dst);
                WRITE1(dst, 8, _C);
                break;
            case CASE(0, 0, 0, 1):
                WRITE1(dst, 9, _A);
                WRITE2(dst, 10, _BC);
                break;
            case CASE(1, 0, 0, 1):
                WRITE2(dst, 0, _AB);
                WRITE1(dst, 2, _C);

                WRITE1(dst, 9, _A);
                WRITE2(dst, 10, _BC);
                break;
            case CASE(0, 1, 0, 1):
                WRITE1(dst, 3, _A);
                WRITE2(dst, 4, _BC);

                WRITE1(dst, 9, _A);
                WRITE2(dst, 10, _BC);
                break;
            case CASE(1, 1, 0, 1):
                WRITE4(dst, 0, _ABCA);
                WRITE2(dst, 4, _BC);

                WRITE1(dst, 9, _A);
                WRITE2(dst, 10, _BC);
                break;
            case CASE(0, 0, 1, 1):
                WRITE2(dst, 6, _AB);
                WRITE4(dst, 8, _CABC);
                break;
            case CASE(1, 0, 1, 1):
                WRITE2(dst, 0, _AB);
                WRITE1(dst, 2, _C);

                WRITE2(dst, 6, _AB);
                WRITE4(dst, 8, _CABC);
                break;
            case CASE(0, 1, 1, 1):
                WRITE1(dst, 3, _A);
                WRITE4(dst, 4, _BCAB);
                WRITE4(dst, 8, _CABC);
                break;
            case CASE(1, 1, 1, 1):
                WRITE8(dst);
                WRITE4(dst, 8, _CABC);
                break;
            }
            bits = FbStipLeft(bits, n);
            n = 4;
            dst += 12;
        }
        dstLine += dstStride;
    }
}
예제 #2
0
파일: fbbltone.c 프로젝트: Agnesa/xserver
void
fbBltOne(FbStip * src, FbStride srcStride,      /* FbStip units per scanline */
         int srcX,              /* bit position of source */
         FbBits * dst, FbStride dstStride,      /* FbBits units per scanline */
         int dstX,              /* bit position of dest */
         int dstBpp,            /* bits per destination unit */
         int width,             /* width in bits of destination */
         int height,            /* height in scanlines */
         FbBits fgand,          /* rrop values */
         FbBits fgxor, FbBits bgand, FbBits bgxor)
{
    const FbBits *fbBits;
    FbBits *srcEnd;
    int pixelsPerDst;           /* dst pixels per FbBits */
    int unitsPerSrc;            /* src patterns per FbStip */
    int leftShift, rightShift;  /* align source with dest */
    FbBits startmask, endmask;  /* dest scanline masks */
    FbStip bits = 0, bitsLeft, bitsRight;       /* source bits */
    FbStip left;
    FbBits mask;
    int nDst;                   /* dest longwords (w.o. end) */
    int w;
    int n, nmiddle;
    int dstS;                   /* stipple-relative dst X coordinate */
    Bool copy;                  /* accelerate dest-invariant */
    Bool transparent;           /* accelerate 0 nop */
    int srcinc;                 /* source units consumed */
    Bool endNeedsLoad = FALSE;  /* need load for endmask */
    CARD8 *fbLane;
    int startbyte, endbyte;

    if (dstBpp == 24) {
        fbBltOne24(src, srcStride, srcX,
                   dst, dstStride, dstX, dstBpp,
                   width, height, fgand, fgxor, bgand, bgxor);
        return;
    }

    /*
     * Do not read past the end of the buffer!
     */
    srcEnd = src + height * srcStride;

    /*
     * Number of destination units in FbBits == number of stipple pixels
     * used each time
     */
    pixelsPerDst = FB_UNIT / dstBpp;

    /*
     * Number of source stipple patterns in FbStip 
     */
    unitsPerSrc = FB_STIP_UNIT / pixelsPerDst;

    copy = FALSE;
    transparent = FALSE;
    if (bgand == 0 && fgand == 0)
        copy = TRUE;
    else if (bgand == FB_ALLONES && bgxor == 0)
        transparent = TRUE;

    /*
     * Adjust source and dest to nearest FbBits boundary
     */
    src += srcX >> FB_STIP_SHIFT;
    dst += dstX >> FB_SHIFT;
    srcX &= FB_STIP_MASK;
    dstX &= FB_MASK;

    FbMaskBitsBytes(dstX, width, copy,
                    startmask, startbyte, nmiddle, endmask, endbyte);

    /*
     * Compute effective dest alignment requirement for
     * source -- must align source to dest unit boundary
     */
    dstS = dstX / dstBpp;
    /*
     * Compute shift constants for effective alignement
     */
    if (srcX >= dstS) {
        leftShift = srcX - dstS;
        rightShift = FB_STIP_UNIT - leftShift;
    }
    else {
        rightShift = dstS - srcX;
        leftShift = FB_STIP_UNIT - rightShift;
    }
    /*
     * Get pointer to stipple mask array for this depth
     */
    fbBits = 0;                 /* unused */
    if (pixelsPerDst <= 8)
        fbBits = fbStippleTable[pixelsPerDst];
    fbLane = 0;
    if (transparent && fgand == 0 && dstBpp >= 8)
        fbLane = fbLaneTable[dstBpp];

    /*
     * Compute total number of destination words written, but 
     * don't count endmask 
     */
    nDst = nmiddle;
    if (startmask)
        nDst++;

    dstStride -= nDst;

    /*
     * Compute total number of source words consumed
     */

    srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc;

    if (srcX > dstS)
        srcinc++;
    if (endmask) {
        endNeedsLoad = nDst % unitsPerSrc == 0;
        if (endNeedsLoad)
            srcinc++;
    }

    srcStride -= srcinc;

    /*
     * Copy rectangle
     */
    while (height--) {
        w = nDst;               /* total units across scanline */
        n = unitsPerSrc;        /* units avail in single stipple */
        if (n > w)
            n = w;

        bitsLeft = 0;
        if (srcX > dstS)
            bitsLeft = READ(src++);
        if (n) {
            /*
             * Load first set of stipple bits
             */
            LoadBits;

            /*
             * Consume stipple bits for startmask
             */
            if (startmask) {
#if FB_UNIT > 32
                if (pixelsPerDst == 16)
                    mask = FbStipple16Bits(FbLeftStipBits(bits, 16));
                else
#endif
                    mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
                if (fbLane) {
                    fbTransparentSpan(dst, mask & startmask, fgxor, 1);
                }
                else {
                    if (mask || !transparent)
                        FbDoLeftMaskByteStippleRRop(dst, mask,
                                                    fgand, fgxor, bgand, bgxor,
                                                    startbyte, startmask);
                }
                bits = FbStipLeft(bits, pixelsPerDst);
                dst++;
                n--;
                w--;
            }
            /*
             * Consume stipple bits across scanline
             */
            for (;;) {
                w -= n;
                if (copy) {
                    while (n--) {
#if FB_UNIT > 32
                        if (pixelsPerDst == 16)
                            mask = FbStipple16Bits(FbLeftStipBits(bits, 16));
                        else
#endif
                            mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
                        WRITE(dst, FbOpaqueStipple(mask, fgxor, bgxor));
                        dst++;
                        bits = FbStipLeft(bits, pixelsPerDst);
                    }
                }
                else {
                    if (fbLane) {
                        while (bits && n) {
                            switch (fbLane[FbLeftStipBits(bits, pixelsPerDst)]) {
                                LaneCases((CARD8 *) dst);
                            }
                            bits = FbStipLeft(bits, pixelsPerDst);
                            dst++;
                            n--;
                        }
                        dst += n;
                    }
                    else {
                        while (n--) {
                            left = FbLeftStipBits(bits, pixelsPerDst);
                            if (left || !transparent) {
                                mask = fbBits[left];
                                WRITE(dst, FbStippleRRop(READ(dst), mask,
                                                         fgand, fgxor, bgand,
                                                         bgxor));
                            }
                            dst++;
                            bits = FbStipLeft(bits, pixelsPerDst);
                        }
                    }
                }
                if (!w)
                    break;
                /*
                 * Load another set and reset number of available units
                 */
                LoadBits;
                n = unitsPerSrc;
                if (n > w)
                    n = w;
            }
        }
        /*
         * Consume stipple bits for endmask
         */
        if (endmask) {
            if (endNeedsLoad) {
                LoadBits;
            }
#if FB_UNIT > 32
            if (pixelsPerDst == 16)
                mask = FbStipple16Bits(FbLeftStipBits(bits, 16));
            else
#endif
                mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
            if (fbLane) {
                fbTransparentSpan(dst, mask & endmask, fgxor, 1);
            }
            else {
                if (mask || !transparent)
                    FbDoRightMaskByteStippleRRop(dst, mask,
                                                 fgand, fgxor, bgand, bgxor,
                                                 endbyte, endmask);
            }
        }
        dst += dstStride;
        src += srcStride;
    }
}