/*
 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#ifndef LoopMacros_h_Included
#define LoopMacros_h_Included

#include "j2d_md.h"

#include "LineUtils.h"

/*
 * This file contains macros to aid in defining native graphics
 * primitive functions.
 *
 * A number of useful building block macros are defined, but the
 * vast majority of primitives are defined completely by a single
 * macro expansion which uses macro names in the argument list to
 * choose not only from a small number of strategies but also to
 * choose macro packages specific to the source and destination
 * pixel formats - greatly simplifying all aspects of creating
 * a new loop.
 *
 * See the following macros which define entire functions with
 * just one or two surface names and sometimes a strategy name:
 *     DEFINE_ISOCOPY_BLIT(ANYTYPE)
 *     DEFINE_ISOXOR_BLIT(ANYTYPE)
 *     DEFINE_CONVERT_BLIT(SRC, DST, CONV_METHOD)
 *     DEFINE_CONVERT_BLIT_LUT(SRC, DST, LUT_STRATEGY)
 *     DEFINE_XPAR_CONVERT_BLIT_LUT(SRC, DST, LUT_STRATEGY)
 *     DEFINE_XPAR_BLITBG_LUT(SRC, DST, LUT_STRATEGY)
 *     DEFINE_SOLID_FILLRECT(DST)
 *     DEFINE_SOLID_FILLSPANS(DST)
 *     DEFINE_SOLID_DRAWLINE(DST)
 *
 * Many of these loop macros take the name of a SurfaceType as
 * an argument and use the ANSI CPP token concatenation operator
 * "##" to reference macro and type definitions that are specific
 * to that type of surface.
 *
 * A description of the various surface specific macro utilities
 * that are used by these loop macros appears at the end of the
 * file.  The definitions of these surface-specific macros will
 * usually appear in a header file named after the SurfaceType
 * name (i.e. IntArgb.h, ByteGray.h, etc.).
 */

/*
 * This loop is the standard "while (--height > 0)" loop used by
 * some of the blits below.
 */
#define BlitLoopHeight(SRCTYPE, SRCPTR, SRCBASE, SRCINFO, \
                       DSTTYPE, DSTPTR, DSTBASE, DSTINFO, DSTPREFIX, \
                       HEIGHT, BODY) \
    do { \
        SRCTYPE ## DataType *SRCPTR = (SRCTYPE ## DataType *) (SRCBASE); \
        DSTTYPE ## DataType *DSTPTR = (DSTTYPE ## DataType *) (DSTBASE); \
        jint srcScan = (SRCINFO)->scanStride; \
        jint dstScan = (DSTINFO)->scanStride; \
        Init ## DSTTYPE ## StoreVarsY(DSTPREFIX, DSTINFO); \
        do { \
            BODY; \
            SRCPTR = PtrAddBytes(SRCPTR, srcScan); \
            DSTPTR = PtrAddBytes(DSTPTR, dstScan); \
            Next ## DSTTYPE ## StoreVarsY(DSTPREFIX); \
        } while (--HEIGHT > 0); \
    } while (0)

/*
 * This loop is the standard nested "while (--width/height > 0)" loop
 * used by most of the basic blits below.
 */
#define BlitLoopWidthHeight(SRCTYPE, SRCPTR, SRCBASE, SRCINFO, \
                            DSTTYPE, DSTPTR, DSTBASE, DSTINFO, DSTPREFIX, \
                            WIDTH, HEIGHT, BODY) \
    do { \
        SRCTYPE ## DataType *SRCPTR = (SRCTYPE ## DataType *) (SRCBASE); \
        DSTTYPE ## DataType *DSTPTR = (DSTTYPE ## DataType *) (DSTBASE); \
        jint srcScan = (SRCINFO)->scanStride; \
        jint dstScan = (DSTINFO)->scanStride; \
        Init ## DSTTYPE ## StoreVarsY(DSTPREFIX, DSTINFO); \
        srcScan -= (WIDTH) * SRCTYPE ## PixelStride; \
        dstScan -= (WIDTH) * DSTTYPE ## PixelStride; \
        do { \
            juint w = WIDTH; \
            Init ## DSTTYPE ## StoreVarsX(DSTPREFIX, DSTINFO); \
            do { \
                BODY; \
                SRCPTR = PtrAddBytes(SRCPTR, SRCTYPE ## PixelStride); \
                DSTPTR = PtrAddBytes(DSTPTR, DSTTYPE ## PixelStride); \
                Next ## DSTTYPE ## StoreVarsX(DSTPREFIX); \
            } while (--w > 0); \
            SRCPTR = PtrAddBytes(SRCPTR, srcScan); \
            DSTPTR = PtrAddBytes(DSTPTR, dstScan); \
            Next ## DSTTYPE ## StoreVarsY(DSTPREFIX); \
        } while (--HEIGHT > 0); \
    } while (0)

/*
 * This loop is the standard nested "while (--width/height > 0)" loop
 * used by most of the scaled blits below.  It calculates the proper
 * X source variable
 */
#define BlitLoopScaleWidthHeight(SRCTYPE, SRCPTR, SRCBASE, SRCINFO, \
                                 DSTTYPE, DSTPTR, DSTBASE, DSTINFO, DSTPREFIX, \
                                 XVAR, WIDTH, HEIGHT, \
                                 SXLOC, SYLOC, SXINC, SYINC, SHIFT, \
                                 BODY) \
    do { \
        SRCTYPE ## DataType *SRCPTR; \
        DSTTYPE ## DataType *DSTPTR = (DSTTYPE ## DataType *) (DSTBASE); \
        jint srcScan = (SRCINFO)->scanStride; \
        jint dstScan = (DSTINFO)->scanStride; \
        Init ## DSTTYPE ## StoreVarsY(DSTPREFIX, DSTINFO); \
        dstScan -= (WIDTH) * DSTTYPE ## PixelStride; \
        do { \
            juint w = WIDTH; \
            jint tmpsxloc = SXLOC; \
            SRCPTR = PtrAddBytes(SRCBASE, ((SYLOC >> SHIFT) * srcScan)); \
            Init ## DSTTYPE ## StoreVarsX(DSTPREFIX, DSTINFO); \
            do { \
                jint XVAR = (tmpsxloc >> SHIFT); \
                BODY; \
                DSTPTR = PtrAddBytes(DSTPTR, DSTTYPE ## PixelStride); \
                Next ## DSTTYPE ## StoreVarsX(DSTPREFIX); \
                tmpsxloc += SXINC; \
            } while (--w > 0); \
            DSTPTR = PtrAddBytes(DSTPTR, dstScan); \
            Next ## DSTTYPE ## StoreVarsY(DSTPREFIX); \
            SYLOC += SYINC; \
        } while (--HEIGHT > 0); \
    } while (0)

/*
 * This loop is a standard horizontal loop iterating with a "relative"
 * X coordinate (0 <= X < WIDTH) used primarily by the LUT conversion
 * preprocessing loops below.
 */
#define BlitLoopXRel(DSTTYPE, DSTINFO, DSTPREFIX, \
                     XVAR, WIDTH, BODY) \
    do { \
        juint XVAR = 0; \
        Init ## DSTTYPE ## StoreVarsX(DSTPREFIX, DSTINFO); \
        do { \
            BODY; \
            Next ## DSTTYPE ## StoreVarsX(DSTPREFIX); \
        } while (++XVAR < WIDTH); \
    } while (0)

/*
 * This is a "conversion strategy" for use with the DEFINE_CONVERT_BLIT
 * macros.  It converts from the source pixel format to the destination
 * via an intermediate "jint rgb" format.
 */
#define ConvertVia1IntRgb(SRCPTR, SRCTYPE, SRCPREFIX, \
                          DSTPTR, DSTTYPE, DSTPREFIX, \
                          SXVAR, DXVAR) \
    do { \
        int rgb; \
        Load ## SRCTYPE ## To1IntRgb(SRCPTR, SRCPREFIX, SXVAR, rgb); \
        Store ## DSTTYPE ## From1IntRgb(DSTPTR, DSTPREFIX, DXVAR, rgb); \
    } while (0)

/*
 * This is a "conversion strategy" for use with the DEFINE_CONVERT_BLIT
 * macros.  It converts from the source pixel format to the destination
 * via an intermediate "jint argb" format.
 */
#define ConvertVia1IntArgb(SRCPTR, SRCTYPE, SRCPREFIX, \
                           DSTPTR, DSTTYPE, DSTPREFIX, \
                           SXVAR, DXVAR) \
    do { \
        int argb; \
        Load ## SRCTYPE ## To1IntArgb(SRCPTR, SRCPREFIX, SXVAR, argb); \
        Store ## DSTTYPE ## From1IntArgb(DSTPTR, DSTPREFIX, DXVAR, argb); \
    } while (0)

/*
 * This is a "conversion strategy" for use with the DEFINE_CONVERT_BLIT
 * macros.  It converts from the source pixel format to the destination
 * via an intermediate set of 3 component variables "jint r, g, b".
 */
#define ConvertVia3ByteRgb(SRCPTR, SRCTYPE, SRCPREFIX, \
                           DSTPTR, DSTTYPE, DSTPREFIX, \
                           SXVAR, DXVAR) \
    do { \
        jint r, g, b; \
        Load ## SRCTYPE ## To3ByteRgb(SRCPTR, SRCPREFIX, SXVAR, r, g, b); \
        Store ## DSTTYPE ## From3ByteRgb(DSTPTR, DSTPREFIX, DXVAR, r, g, b); \
    } while (0)

/*
 * This is a "conversion strategy" for use with the DEFINE_CONVERT_BLIT
 * macros.  It converts from the source pixel format to the destination
 * via an intermediate set of 4 component variables "jint a, r, g, b".
 */
#define ConvertVia4ByteArgb(SRCPTR, SRCTYPE, SRCPREFIX, \
                            DSTPTR, DSTTYPE, DSTPREFIX, \
                            SXVAR, DXVAR) \
    do { \
        jint a, r, g, b; \
        Load ## SRCTYPE ## To4ByteArgb(SRCPTR, SRCPREFIX, SXVAR, a, r, g, b); \
        Store ## DSTTYPE ## From4ByteArgb(DSTPTR, DSTPREFIX, DXVAR, \
                                          a, r, g, b); \
    } while (0)

/*
 * This is a "conversion strategy" for use with the DEFINE_CONVERT_BLIT
 * macros.  It converts from the source pixel format to the destination
 * via an intermediate "jint gray" format.
 */
#define ConvertVia1ByteGray(SRCPTR, SRCTYPE, SRCPREFIX, \
                            DSTPTR, DSTTYPE, DSTPREFIX, \
                            SXVAR, DXVAR) \
    do { \
        jint gray; \
        Load ## SRCTYPE ## To1ByteGray(SRCPTR, SRCPREFIX, SXVAR, gray); \
        Store ## DSTTYPE ## From1ByteGray(DSTPTR, DSTPREFIX, DXVAR, gray); \
    } while (0)

/*
 * This is a "conversion strategy" for use with the DEFINE_XPAR_CONVERT_BLIT
 * macros.  It converts from the source pixel format to the destination
 * via the specified intermediate format while testing for transparent pixels.
 */
#define ConvertXparVia1IntRgb(SRCPTR, SRCTYPE, SRCPREFIX, \
                              DSTPTR, DSTTYPE, DSTPREFIX, \
                              SXVAR, DXVAR) \
    do { \
        Declare ## SRCTYPE ## Data(XparLoad); \
        Load ## SRCTYPE ## Data(SRCPTR, SRCPREFIX, SXVAR, XparLoad); \
        if (! (Is ## SRCTYPE ## DataTransparent(XparLoad))) { \
            int rgb; \
            Convert ## SRCTYPE ## DataTo1IntRgb(XparLoad, rgb); \
            Store ## DSTTYPE ## From1IntRgb(DSTPTR, DSTPREFIX, DXVAR, rgb); \
        } \
    } while (0)

/*
 * This is a "conversion strategy" for use with the DEFINE_XPAR_BLITBG
 * macros.  It converts from the source pixel format to the destination
 * via the specified intermediate format while substituting the specified
 * bgcolor for transparent pixels.
 */
#define BgCopyXparVia1IntRgb(SRCPTR, SRCTYPE, SRCPREFIX, \
                             DSTPTR, DSTTYPE, DSTPREFIX, \
                             SXVAR, DXVAR, BGPIXEL, BGPREFIX) \
    do { \
        Declare ## SRCTYPE ## Data(XparLoad); \
        Load ## SRCTYPE ## Data(SRCPTR, SRCPREFIX, SXVAR, XparLoad); \
        if (Is ## SRCTYPE ## DataTransparent(XparLoad)) { \
            Store ## DSTTYPE ## PixelData(DSTPTR, DXVAR, BGPIXEL, BGPREFIX); \
        } else { \
            int rgb; \
            Convert ## SRCTYPE ## DataTo1IntRgb(XparLoad, rgb); \
            Store ## DSTTYPE ## From1IntRgb(DSTPTR, DSTPREFIX, DXVAR, rgb); \
        } \
    } while (0)

/*
 * This macro determines whether or not the given pixel is considered
 * "transparent" for XOR purposes.  The ARGB pixel is considered
 * "transparent" if the alpha value is < 0.5.
 */
#define IsArgbTransparent(pixel) \
    (((jint) pixel) >= 0)

/*
 * This is a "conversion strategy" for use with the DEFINE_XOR_BLIT macro.  It
 * converts the source pixel to an intermediate ARGB value and then converts
 * the ARGB value to the pixel representation for the destination surface.  It
 * then XORs the srcpixel, xorpixel, and destination pixel together and stores
 * the result in the destination surface.
 */
#define XorVia1IntArgb(SRCPTR, SRCTYPE, SRCPREFIX, \
                       DSTPTR, DSTTYPE, DSTANYTYPE, \
                       XVAR, XORPIXEL, XORPREFIX, \
                       MASK, MASKPREFIX, DSTINFOPTR) \
    do { \
        jint srcpixel; \
        Declare ## DSTANYTYPE ## PixelData(pix) \
        Load ## SRCTYPE ## To1IntArgb(SRCPTR, SRCPREFIX, XVAR, srcpixel); \
 \
        if (IsArgbTransparent(srcpixel)) { \
            break; \
        } \
 \
        DSTTYPE ## PixelFromArgb(srcpixel, srcpixel, DSTINFOPTR); \
 \
        Extract ## DSTANYTYPE ## PixelData(srcpixel, pix); \
        Xor ## DSTANYTYPE ## PixelData(srcpixel, pix, DSTPTR, XVAR, \
                                       XORPIXEL, XORPREFIX, \
                                       MASK, MASKPREFIX); \
    } while (0)

/*
 * "LUT_STRATEGY" macro sets.
 *
 * There are 2 major strategies for dealing with luts and 3
 * implementations of those strategies.
 *
 * The 2 strategies are "PreProcessLut" and "ConvertOnTheFly".
 *
 * For the "PreProcessLut" strategy, the raw ARGB lut supplied
 * by the SD_LOCK_LUT flag is converted at the beginning into a
 * form that is more suited for storing into the destination
 * pixel format.  The inner loop consists of a series of table
 * lookups with very little conversion from that intermediate
 * pixel format.
 *
 * For the "ConvertOnTheFly" strategy, the raw ARGB values are
 * converted on a pixel by pixel basis in the inner loop itself.
 * This strategy is most useful for formats which tend to use
 * the ARGB color format as their pixel format also.
 *
 * Each of these strategies has 3 implementations which are needed
 * for the special cases:
 * - straight conversion (invoked from DEFINE_CONVERT_BLIT_LUT)
 * - straight conversion with transparency handling (invoked from
 *   DEFINE_XPAR_CONVERT_BLIT_LUT)
 * - straight conversion with a bgcolor for the transparent pixels
 *   (invoked from DEFINE_XPAR_BLITBG_LUT)
 */

/***
 * Start of PreProcessLut strategy macros, CONVERT_BLIT implementation.
 */
#define LutSize(TYPE) \
    (1 << TYPE ## BitsPerPixel)

#define DeclarePreProcessLutLut(SRC, DST, PIXLUT) \
    DST ## PixelType PIXLUT[LutSize(SRC)];

#define SetupPreProcessLutLut(SRC, DST, PIXLUT, SRCINFO, DSTINFO) \
    do { \
        jint *srcLut = (SRCINFO)->lutBase; \
        juint lutSize = (SRCINFO)->lutSize; \
        Declare ## DST ## StoreVars(PreLut) \
        Init ## DST ## StoreVarsY(PreLut, DSTINFO); \
        if (lutSize >= LutSize(SRC)) { \
            lutSize = LutSize(SRC); \
        } else { \
            DST ## PixelType *pPIXLUT = &PIXLUT[lutSize]; \
            do { \
                Store ## DST ## From1IntArgb(pPIXLUT, PreLut, 0, 0); \
            } while (++pPIXLUT < &PIXLUT[LutSize(SRC)]); \
        } \
        BlitLoopXRel(DST, DSTINFO, PreLut, x, lutSize, \
                     do { \
                         jint argb = srcLut[x]; \
                         Store ## DST ## From1IntArgb(PIXLUT, PreLut, x, argb); \
                     } while (0)); \
    } while (0)

#define BodyPreProcessLutLut(SRCPTR, SRCTYPE, PIXLUT, \
                             DSTPTR, DSTTYPE, DSTPREFIX, \
                             SXVAR, DXVAR) \
    DSTPTR[DXVAR] = PIXLUT[SRCPTR[SXVAR]]

/*
 * End of PreProcessLut/CONVERT_BLIT macros.
 ***/

/***
 * Start of ConvertOnTheFly strategy macros, CONVERT_BLIT implementation.
 */
#define DeclareConvertOnTheFlyLut(SRC, DST, PIXLUT) \
    Declare ## SRC ## LoadVars(PIXLUT)

#define SetupConvertOnTheFlyLut(SRC, DST, PIXLUT, SRCINFO, DSTINFO) \
    Init ## SRC ## LoadVars(PIXLUT, SRCINFO)

#define BodyConvertOnTheFlyLut(SRCPTR, SRCTYPE, PIXLUT, \
                               DSTPTR, DSTTYPE, DSTPREFIX, \
                               SXVAR, DXVAR) \
    ConvertVia1IntArgb(SRCPTR, SRCTYPE, PIXLUT, \
                       DSTPTR, DSTTYPE, DSTPREFIX, \
                       SXVAR, DXVAR)

/*
 * End of ConvertOnTheFly/CONVERT_BLIT macros.
 ***/

/***
 * Start of PreProcessLut strategy macros, XPAR_CONVERT_BLIT implementation.
 */
#define DeclarePreProcessLutXparLut(SRC, DST, PIXLUT) \
    jint PIXLUT[LutSize(SRC)];

#define SetupPreProcessLutXparLut(SRC, DST, PIXLUT, SRCINFO, DSTINFO) \
    do { \
        jint *srcLut = (SRCINFO)->lutBase; \
        juint lutSize = (SRCINFO)->lutSize; \
        Declare ## DST ## StoreVars(PreLut) \
        Init ## DST ## StoreVarsY(PreLut, DSTINFO); \
        if (lutSize >= LutSize(SRC)) { \
            lutSize = LutSize(SRC); \
        } else { \
            jint *pPIXLUT = &PIXLUT[lutSize]; \
            do { \
                pPIXLUT[0] = DST ## XparLutEntry; \
            } while (++pPIXLUT < &PIXLUT[LutSize(SRC)]); \
        } \
        BlitLoopXRel(DST, DSTINFO, PreLut, x, lutSize, \
                     do { \
                         jint argb = srcLut[x]; \
                         if (argb < 0) { \
                             Store ## DST ## NonXparFromArgb \
                                 (PIXLUT, PreLut, x, argb); \
                         } else { \
                             PIXLUT[x] = DST ## XparLutEntry; \
                         } \
                     } while (0)); \
    } while (0)

#define BodyPreProcessLutXparLut(SRCPTR, SRCTYPE, PIXLUT, \
                                 DSTPTR, DSTTYPE, DSTPREFIX, \
                                 SXVAR, DXVAR) \
    do { \
        jint pix = PIXLUT[SRCPTR[SXVAR]]; \
        if (! DSTTYPE ## IsXparLutEntry(pix)) { \
            DSTPTR[DXVAR] = (DSTTYPE ## PixelType) pix; \
        } \
    } while (0)

/*
 * End of PreProcessLut/XPAR_CONVERT_BLIT macros.
 ***/

/***
 * Start of ConvertOnTheFly strategy macros, CONVERT_BLIT implementation.
 */
#define DeclareConvertOnTheFlyXparLut(SRC, DST, PIXLUT) \
    Declare ## SRC ## LoadVars(PIXLUT)

#define SetupConvertOnTheFlyXparLut(SRC, DST, PIXLUT, SRCINFO, DSTINFO) \
    Init ## SRC ## LoadVars(PIXLUT, SRCINFO)

#define BodyConvertOnTheFlyXparLut(SRCPTR, SRCTYPE, PIXLUT, \
                                   DSTPTR, DSTTYPE, DSTPREFIX, \
                                   SXVAR, DXVAR) \
    do { \
        jint argb; \
        Load ## SRCTYPE ## To1IntArgb(SRCPTR, PIXLUT, SXVAR, argb); \
        if (argb < 0) { \
            Store ## DSTTYPE ## From1IntArgb(DSTPTR, DSTPREFIX, DXVAR, argb); \
        } \
    } while (0)

/*
 * End of ConvertOnTheFly/CONVERT_BLIT macros.
 ***/

/***
 * Start of PreProcessLut strategy macros, BLITBG implementation.
 */
#define DeclarePreProcessLutBgLut(SRC, DST, PIXLUT) \
    jint PIXLUT[LutSize(SRC)];

#define SetupPreProcessLutBgLut(SRC, DST, PIXLUT, SRCINFO, DSTINFO, BGPIXEL) \
    do { \
        jint *srcLut = (SRCINFO)->lutBase; \
        juint lutSize = (SRCINFO)->lutSize; \
        Declare ## DST ## StoreVars(PreLut) \
        Init ## DST ## StoreVarsY(PreLut, DSTINFO); \
        if (lutSize >= LutSize(SRC)) { \
            lutSize = LutSize(SRC); \
        } else { \
            jint *pPIXLUT = &PIXLUT[lutSize]; \
            do { \
                pPIXLUT[0] = BGPIXEL; \
            } while (++pPIXLUT < &PIXLUT[LutSize(SRC)]); \
        } \
        BlitLoopXRel(DST, DSTINFO, PreLut, x, lutSize, \
                     do { \
                         jint argb = srcLut[x]; \
                         if (argb < 0) { \
                             Store ## DST ## From1IntArgb(PIXLUT, PreLut, \
                                                          x, argb); \
                         } else { \
                             PIXLUT[x] = BGPIXEL; \
                         } \
                     } while (0)); \
    } while (0)

#define BodyPreProcessLutBgLut(SRCPTR, SRCTYPE, PIXLUT, \
                               DSTPTR, DSTTYPE, DSTPREFIX, \
                               SXVAR, DXVAR, BGPIXEL) \
    do { \
        jint pix = PIXLUT[SRCPTR[SXVAR]]; \
        Store ## DSTTYPE ## Pixel(DSTPTR, DXVAR, pix); \
    } while (0)

/*
 * End of PreProcessLut/BLITBG implementation.
 ***/

/***
 * Start of ConvertOnTheFly strategy macros, BLITBG implementation.
 */
#define DeclareConvertOnTheFlyBgLut(SRC, DST, PIXLUT) \
    Declare ## SRC ## LoadVars(PIXLUT) \
    Declare ## DST ## PixelData(bgpix);

#define SetupConvertOnTheFlyBgLut(SRC, DST, PIXLUT, SRCINFO, DSTINFO, BGPIXEL) \
    do { \
        Init ## SRC ## LoadVars(PIXLUT, SRCINFO); \
        Extract ## DST ## PixelData(BGPIXEL, bgpix); \
    } while (0)

#define BodyConvertOnTheFlyBgLut(SRCPTR, SRCTYPE, PIXLUT, \
                                 DSTPTR, DSTTYPE, DSTPREFIX, \
                                 SXVAR, DXVAR, BGPIXEL) \
    do { \
        jint argb; \
        Load ## SRCTYPE ## To1IntArgb(SRCPTR, PIXLUT, SXVAR, argb); \
        if (argb < 0) { \
            Store ## DSTTYPE ## From1IntArgb(DSTPTR, DSTPREFIX, DXVAR, argb); \
        } else { \
            Store ## DSTTYPE ## PixelData(DSTPTR, DXVAR, BGPIXEL, bgpix); \
        } \
    } while (0)

/*
 * End of ConvertOnTheFly/BLITBG macros.
 ***/

/*
 * These macros provide consistent naming conventions for the
 * various types of native primitive inner loop functions.
 * The names are mechanically constructed from the SurfaceType names.
 */
#define NAME_CONVERT_BLIT(SRC, DST)      SRC ## To ## DST ## Convert

#define NAME_SCALE_BLIT(SRC, DST)        SRC ## To ## DST ## ScaleConvert

#define NAME_XPAR_CONVERT_BLIT(SRC, DST) SRC ## To ## DST ## XparOver

#define NAME_XPAR_SCALE_BLIT(SRC, DST)   SRC ## To ## DST ## ScaleXparOver

#define NAME_XPAR_BLITBG(SRC, DST)       SRC ## To ## DST ## XparBgCopy

#define NAME_XOR_BLIT(SRC, DST)          SRC ## To ## DST ## XorBlit

#define NAME_ISOCOPY_BLIT(ANYTYPE)       ANYTYPE ## IsomorphicCopy

#define NAME_ISOSCALE_BLIT(ANYTYPE)      ANYTYPE ## IsomorphicScaleCopy

#define NAME_ISOXOR_BLIT(ANYTYPE)        ANYTYPE ## IsomorphicXorCopy

#define NAME_SOLID_FILLRECT(TYPE)        TYPE ## SetRect

#define NAME_SOLID_FILLSPANS(TYPE)       TYPE ## SetSpans

#define NAME_SOLID_DRAWLINE(TYPE)        TYPE ## SetLine

#define NAME_XOR_FILLRECT(TYPE)          TYPE ## XorRect

#define NAME_XOR_FILLSPANS(TYPE)         TYPE ## XorSpans

#define NAME_XOR_DRAWLINE(TYPE)          TYPE ## XorLine

#define NAME_SRC_MASKFILL(TYPE)          TYPE ## SrcMaskFill

#define NAME_SRCOVER_MASKFILL(TYPE)      TYPE ## SrcOverMaskFill

#define NAME_ALPHA_MASKFILL(TYPE)        TYPE ## AlphaMaskFill

#define NAME_SRCOVER_MASKBLIT(SRC, DST)  SRC ## To ## DST ## SrcOverMaskBlit

#define NAME_ALPHA_MASKBLIT(SRC, DST)    SRC ## To ## DST ## AlphaMaskBlit

#define NAME_SOLID_DRAWGLYPHLIST(TYPE)   TYPE ## DrawGlyphList

#define NAME_SOLID_DRAWGLYPHLISTAA(TYPE) TYPE ## DrawGlyphListAA

#define NAME_SOLID_DRAWGLYPHLISTLCD(TYPE) TYPE ## DrawGlyphListLCD

#define NAME_XOR_DRAWGLYPHLIST(TYPE)     TYPE ## DrawGlyphListXor

#define NAME_TRANSFORMHELPER(TYPE, MODE) TYPE ## MODE ## TransformHelper

#define NAME_TRANSFORMHELPER_NN(TYPE)    NAME_TRANSFORMHELPER(TYPE, NrstNbr)
#define NAME_TRANSFORMHELPER_BL(TYPE)    NAME_TRANSFORMHELPER(TYPE, Bilinear)
#define NAME_TRANSFORMHELPER_BC(TYPE)    NAME_TRANSFORMHELPER(TYPE, Bicubic)

#define NAME_TRANSFORMHELPER_FUNCS(TYPE) TYPE ## TransformHelperFuncs

#define NAME_SOLID_FILLPGRAM(TYPE)       TYPE ## SetParallelogram
#define NAME_SOLID_PGRAM_FUNCS(TYPE)     TYPE ## SetParallelogramFuncs

#define NAME_XOR_FILLPGRAM(TYPE)         TYPE ## XorParallelogram
#define NAME_XOR_PGRAM_FUNCS(TYPE)       TYPE ## XorParallelogramFuncs

/*
 * These macros conveniently name and declare the indicated native
 * primitive loop function for forward referencing.
 */
#define DECLARE_CONVERT_BLIT(SRC, DST) \
    BlitFunc NAME_CONVERT_BLIT(SRC, DST)

#define DECLARE_SCALE_BLIT(SRC, DST) \
    ScaleBlitFunc NAME_SCALE_BLIT(SRC, DST)

#define DECLARE_XPAR_CONVERT_BLIT(SRC, DST) \
    BlitFunc NAME_XPAR_CONVERT_BLIT(SRC, DST)

#define DECLARE_XPAR_SCALE_BLIT(SRC, DST) \
    ScaleBlitFunc NAME_XPAR_SCALE_BLIT(SRC, DST)

#define DECLARE_XPAR_BLITBG(SRC, DST) \
    BlitBgFunc NAME_XPAR_BLITBG(SRC, DST)

#define DECLARE_XOR_BLIT(SRC, DST) \
    BlitFunc NAME_XOR_BLIT(SRC, DST)

#define DECLARE_ISOCOPY_BLIT(ANYTYPE) \
    BlitFunc NAME_ISOCOPY_BLIT(ANYTYPE)

#define DECLARE_ISOSCALE_BLIT(ANYTYPE) \
    ScaleBlitFunc NAME_ISOSCALE_BLIT(ANYTYPE)

#define DECLARE_ISOXOR_BLIT(ANYTYPE) \
    BlitFunc NAME_ISOXOR_BLIT(ANYTYPE)

#define DECLARE_SOLID_FILLRECT(TYPE) \
    FillRectFunc NAME_SOLID_FILLRECT(TYPE)

#define DECLARE_SOLID_FILLSPANS(TYPE) \
    FillSpansFunc NAME_SOLID_FILLSPANS(TYPE)

#define DECLARE_SOLID_DRAWLINE(TYPE) \
    DrawLineFunc NAME_SOLID_DRAWLINE(TYPE)

#define DECLARE_XOR_FILLRECT(TYPE) \
    FillRectFunc NAME_XOR_FILLRECT(TYPE)

#define DECLARE_XOR_FILLSPANS(TYPE) \
    FillSpansFunc NAME_XOR_FILLSPANS(TYPE)

#define DECLARE_XOR_DRAWLINE(TYPE) \
    DrawLineFunc NAME_XOR_DRAWLINE(TYPE)

#define DECLARE_ALPHA_MASKFILL(TYPE) \
    MaskFillFunc NAME_ALPHA_MASKFILL(TYPE)

#define DECLARE_SRC_MASKFILL(TYPE) \
    MaskFillFunc NAME_SRC_MASKFILL(TYPE)

#define DECLARE_SRCOVER_MASKFILL(TYPE) \
    MaskFillFunc NAME_SRCOVER_MASKFILL(TYPE)

#define DECLARE_SRCOVER_MASKBLIT(SRC, DST) \
    MaskBlitFunc NAME_SRCOVER_MASKBLIT(SRC, DST)

#define DECLARE_ALPHA_MASKBLIT(SRC, DST) \
    MaskBlitFunc NAME_ALPHA_MASKBLIT(SRC, DST)

#define DECLARE_SOLID_DRAWGLYPHLIST(TYPE) \
    DrawGlyphListFunc NAME_SOLID_DRAWGLYPHLIST(TYPE)

#define DECLARE_SOLID_DRAWGLYPHLISTAA(TYPE) \
    DrawGlyphListAAFunc NAME_SOLID_DRAWGLYPHLISTAA(TYPE)

#define DECLARE_SOLID_DRAWGLYPHLISTLCD(TYPE) \
    DrawGlyphListLCDFunc NAME_SOLID_DRAWGLYPHLISTLCD(TYPE)

#define DECLARE_XOR_DRAWGLYPHLIST(TYPE) \
    DrawGlyphListFunc NAME_XOR_DRAWGLYPHLIST(TYPE)

#define DECLARE_TRANSFORMHELPER_FUNCS(TYPE) \
    TransformHelperFunc NAME_TRANSFORMHELPER_NN(TYPE); \
    TransformHelperFunc NAME_TRANSFORMHELPER_BL(TYPE); \
    TransformHelperFunc NAME_TRANSFORMHELPER_BC(TYPE); \
    TransformHelperFuncs NAME_TRANSFORMHELPER_FUNCS(TYPE)

#define DECLARE_SOLID_PARALLELOGRAM(TYPE) \
    FillParallelogramFunc NAME_SOLID_FILLPGRAM(TYPE); \
    DECLARE_SOLID_DRAWLINE(TYPE); \
    DrawParallelogramFuncs NAME_SOLID_PGRAM_FUNCS(TYPE)

#define DECLARE_XOR_PARALLELOGRAM(TYPE) \
    FillParallelogramFunc NAME_XOR_FILLPGRAM(TYPE); \
    DECLARE_XOR_DRAWLINE(TYPE); \
    DrawParallelogramFuncs NAME_XOR_PGRAM_FUNCS(TYPE)

/*
 * These macros construct the necessary NativePrimitive structure
 * for the indicated native primitive loop function which will be
 * declared somewhere prior and defined elsewhere (usually after).
 */
#define REGISTER_CONVERT_BLIT(SRC, DST) \
    REGISTER_BLIT(SRC, SrcNoEa, DST, NAME_CONVERT_BLIT(SRC, DST))

#define REGISTER_CONVERT_BLIT_FLAGS(SRC, DST, SFLAGS, DFLAGS) \
    REGISTER_BLIT_FLAGS(SRC, SrcNoEa, DST, NAME_CONVERT_BLIT(SRC, DST), \
                        SFLAGS, DFLAGS)

#define REGISTER_CONVERT_BLIT_EQUIV(SRC, DST, FUNC) \
    REGISTER_BLIT(SRC, SrcNoEa, DST, FUNC)

#define REGISTER_SCALE_BLIT(SRC, DST) \
    REGISTER_SCALEBLIT(SRC, SrcNoEa, DST, NAME_SCALE_BLIT(SRC, DST))

#define REGISTER_SCALE_BLIT_FLAGS(SRC, DST, SFLAGS, DFLAGS) \
    REGISTER_SCALEBLIT_FLAGS(SRC, SrcNoEa, DST, NAME_SCALE_BLIT(SRC, DST), \
                             SFLAGS, DFLAGS)

#define REGISTER_SCALE_BLIT_EQUIV(SRC, DST, FUNC) \
    REGISTER_SCALEBLIT(SRC, SrcNoEa, DST, FUNC)

#define REGISTER_XPAR_CONVERT_BLIT(SRC, DST) \
    REGISTER_BLIT(SRC, SrcOverBmNoEa, DST, NAME_XPAR_CONVERT_BLIT(SRC, DST))

#define REGISTER_XPAR_CONVERT_BLIT_EQUIV(SRC, DST, FUNC) \
    REGISTER_BLIT(SRC, SrcOverBmNoEa, DST, FUNC)

#define REGISTER_XPAR_SCALE_BLIT(SRC, DST) \
    REGISTER_SCALEBLIT(SRC, SrcOverBmNoEa, DST, NAME_XPAR_SCALE_BLIT(SRC, DST))

#define REGISTER_XPAR_SCALE_BLIT_EQUIV(SRC, DST, FUNC) \
    REGISTER_SCALEBLIT(SRC, SrcOverBmNoEa, DST, FUNC)

#define REGISTER_XPAR_BLITBG(SRC, DST) \
    REGISTER_BLITBG(SRC, SrcNoEa, DST, NAME_XPAR_BLITBG(SRC, DST))

#define REGISTER_XPAR_BLITBG_EQUIV(SRC, DST, FUNC) \
    REGISTER_BLITBG(SRC, SrcNoEa, DST, FUNC)

#define REGISTER_XOR_BLIT(SRC, DST) \
    REGISTER_BLIT(SRC, Xor, DST, NAME_XOR_BLIT(SRC, DST))

#define REGISTER_ISOCOPY_BLIT(THISTYPE, ANYTYPE) \
    REGISTER_BLIT(THISTYPE, SrcNoEa, THISTYPE, NAME_ISOCOPY_BLIT(ANYTYPE))

#define REGISTER_ISOSCALE_BLIT(THISTYPE, ANYTYPE) \
    REGISTER_SCALEBLIT(THISTYPE, SrcNoEa, THISTYPE, NAME_ISOSCALE_BLIT(ANYTYPE))

#define REGISTER_ISOXOR_BLIT(THISTYPE, ANYTYPE) \
    REGISTER_BLIT(THISTYPE, Xor, THISTYPE, NAME_ISOXOR_BLIT(ANYTYPE))

#define REGISTER_SOLID_FILLRECT(TYPE) \
    REGISTER_FILLRECT(AnyColor, SrcNoEa, TYPE, NAME_SOLID_FILLRECT(TYPE))

#define REGISTER_SOLID_FILLSPANS(TYPE) \
    REGISTER_FILLSPANS(AnyColor, SrcNoEa, TYPE, NAME_SOLID_FILLSPANS(TYPE))

#define REGISTER_SOLID_LINE_PRIMITIVES(TYPE) \
    REGISTER_LINE_PRIMITIVES(AnyColor, SrcNoEa, TYPE, \
                             NAME_SOLID_DRAWLINE(TYPE))

#define REGISTER_XOR_FILLRECT(TYPE) \
    REGISTER_FILLRECT(AnyColor, Xor, TYPE, NAME_XOR_FILLRECT(TYPE))

#define REGISTER_XOR_FILLSPANS(TYPE) \
    REGISTER_FILLSPANS(AnyColor, Xor, TYPE, NAME_XOR_FILLSPANS(TYPE))

#define REGISTER_XOR_LINE_PRIMITIVES(TYPE) \
    REGISTER_LINE_PRIMITIVES(AnyColor, Xor, TYPE, NAME_XOR_DRAWLINE(TYPE))

#define REGISTER_ALPHA_MASKFILL(TYPE) \
    REGISTER_MASKFILL(AnyColor, AnyAlpha, TYPE, NAME_ALPHA_MASKFILL(TYPE))

#define REGISTER_SRC_MASKFILL(TYPE) \
    REGISTER_MASKFILL(AnyColor, Src, TYPE, NAME_SRC_MASKFILL(TYPE))

#define REGISTER_SRCOVER_MASKFILL(TYPE) \
    REGISTER_MASKFILL(AnyColor, SrcOver, TYPE, NAME_SRCOVER_MASKFILL(TYPE))

#define REGISTER_SRCOVER_MASKBLIT(SRC, DST) \
    REGISTER_MASKBLIT(SRC, SrcOver, DST, NAME_SRCOVER_MASKBLIT(SRC, DST))

#define REGISTER_ALPHA_MASKBLIT(SRC, DST) \
    REGISTER_MASKBLIT(SRC, AnyAlpha, DST, NAME_ALPHA_MASKBLIT(SRC, DST))

#define REGISTER_SOLID_DRAWGLYPHLIST(TYPE) \
    REGISTER_DRAWGLYPHLIST(AnyColor, SrcNoEa, TYPE, \
                           NAME_SOLID_DRAWGLYPHLIST(TYPE))

#define REGISTER_SOLID_DRAWGLYPHLISTAA(TYPE) \
    REGISTER_DRAWGLYPHLISTAA(AnyColor, SrcNoEa, TYPE, \
                             NAME_SOLID_DRAWGLYPHLISTAA(TYPE))

#define REGISTER_SOLID_DRAWGLYPHLISTLCD(TYPE) \
    REGISTER_DRAWGLYPHLISTLCD(AnyColor, SrcNoEa, TYPE, \
                             NAME_SOLID_DRAWGLYPHLISTLCD(TYPE))

#define REGISTER_XOR_DRAWGLYPHLIST(TYPE) \
    REGISTER_DRAWGLYPHLIST(AnyColor, Xor, TYPE, \
                           NAME_XOR_DRAWGLYPHLIST(TYPE)), \
    REGISTER_DRAWGLYPHLISTAA(AnyColor, Xor, TYPE, \
                             NAME_XOR_DRAWGLYPHLIST(TYPE))

#define REGISTER_TRANSFORMHELPER_FUNCS(TYPE) \
    REGISTER_PRIMITIVE(TransformHelper, TYPE, SrcNoEa, IntArgbPre, \
                       (AnyFunc *) &NAME_TRANSFORMHELPER_FUNCS(TYPE))

#define REGISTER_SOLID_PARALLELOGRAM(TYPE) \
    REGISTER_PRIMITIVE(FillParallelogram, AnyColor, SrcNoEa, TYPE, \
                       NAME_SOLID_FILLPGRAM(TYPE)), \
    REGISTER_PRIMITIVE(DrawParallelogram, AnyColor, SrcNoEa, TYPE, \
                       (AnyFunc *) &NAME_SOLID_PGRAM_FUNCS(TYPE))

#define REGISTER_XOR_PARALLELOGRAM(TYPE) \
    REGISTER_PRIMITIVE(FillParallelogram, AnyColor, Xor, TYPE, \
                       NAME_XOR_FILLPGRAM(TYPE)), \
    REGISTER_PRIMITIVE(DrawParallelogram, AnyColor, Xor, TYPE, \
                       (AnyFunc *) &NAME_XOR_PGRAM_FUNCS(TYPE))

/*
 * This macro defines an entire function to implement a Blit inner loop
 * for copying pixels of a common type from one buffer to another.
 */
#define DEFINE_ISOCOPY_BLIT(ANYTYPE) \
void NAME_ISOCOPY_BLIT(ANYTYPE)(void *srcBase, void *dstBase, \
                                juint width, juint height, \
                                SurfaceDataRasInfo *pSrcInfo, \
                                SurfaceDataRasInfo *pDstInfo, \
                                NativePrimitive *pPrim, \
                                CompositeInfo *pCompInfo) \
{ \
    Declare ## ANYTYPE ## StoreVars(DstWrite) \
    BlitLoopHeight(ANYTYPE, pSrc, srcBase, pSrcInfo, \
                   ANYTYPE, pDst, dstBase, pDstInfo, DstWrite, \
                   height, \
                   memcpy(pDst, pSrc, width * ANYTYPE ## PixelStride)); \
}

/*
 * This macro defines an entire function to implement a ScaleBlit inner loop
 * for scaling pixels of a common type from one buffer to another.
 */
#define DEFINE_ISOSCALE_BLIT(ANYTYPE) \
void NAME_ISOSCALE_BLIT(ANYTYPE)(void *srcBase, void *dstBase, \
                                 juint width, juint height, \
                                 jint sxloc, jint syloc, \
                                 jint sxinc, jint syinc, jint shift, \
                                 SurfaceDataRasInfo *pSrcInfo, \
                                 SurfaceDataRasInfo *pDstInfo, \
                                 NativePrimitive *pPrim, \
                                 CompositeInfo *pCompInfo) \
{ \
    Declare ## ANYTYPE ## StoreVars(DstWrite) \
    BlitLoopScaleWidthHeight(ANYTYPE, pSrc, srcBase, pSrcInfo, \
                             ANYTYPE, pDst, dstBase, pDstInfo, DstWrite, \
                             x, width, height, \
                             sxloc, syloc, sxinc, syinc, shift, \
                             Copy ## ANYTYPE ## PixelData(pSrc, x, pDst, 0)); \
}

/*
 * This macro defines an entire function to implement a Blit inner loop
 * for XORing pixels of a common type from one buffer into another.
 */
#define DEFINE_ISOXOR_BLIT(ANYTYPE) \
void NAME_ISOXOR_BLIT(ANYTYPE)(void *srcBase, void *dstBase, \
                               juint width, juint height, \
                               SurfaceDataRasInfo *pSrcInfo, \
                               SurfaceDataRasInfo *pDstInfo, \
                               NativePrimitive *pPrim, \
                               CompositeInfo *pCompInfo) \
{ \
    jint xorpixel = pCompInfo->details.xorPixel; \
    Declare ## ANYTYPE ## PixelData(xor) \
    Declare ## ANYTYPE ## StoreVars(DstWrite) \
 \
    Extract ## ANYTYPE ## PixelData(xorpixel, xor); \
 \
    BlitLoopWidthHeight(ANYTYPE, pSrc, srcBase, pSrcInfo, \
                        ANYTYPE, pDst, dstBase, pDstInfo, DstWrite, \
                        width, height, \
                        XorCopy ## ANYTYPE ## PixelData(pSrc, pDst, 0, \
                                                        xorpixel, xor)); \
}

/*
 * This macro defines an entire function to implement a Blit inner loop
 * for converting pixels from a buffer of one type into a buffer of
 * another type.  No blending is done of the pixels.
 */
#define DEFINE_CONVERT_BLIT(SRC, DST, STRATEGY) \
void NAME_CONVERT_BLIT(SRC, DST)(void *srcBase, void *dstBase, \
                                 juint width, juint height, \
                                 SurfaceDataRasInfo *pSrcInfo, \
                                 SurfaceDataRasInfo *pDstInfo, \
                                 NativePrimitive *pPrim, \
                                 CompositeInfo *pCompInfo) \
{ \
    Declare ## SRC ## LoadVars(SrcRead) \
    Declare ## DST ## StoreVars(DstWrite) \
 \
    Init ## SRC ## LoadVars(SrcRead, pSrcInfo); \
    BlitLoopWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                        DST, pDst, dstBase, pDstInfo, DstWrite, \
                        width, height, \
                        ConvertVia ## STRATEGY(pSrc, SRC, SrcRead, \
                                               pDst, DST, DstWrite, \
                                               0, 0)); \
}

/*
 * This macro defines an entire function to implement a Blit inner loop
 * for converting pixels from a buffer of byte pixels with a lookup
 * table into a buffer of another type.  No blending is done of the pixels.
 */
#define DEFINE_CONVERT_BLIT_LUT(SRC, DST, LUT_STRATEGY) \
void NAME_CONVERT_BLIT(SRC, DST)(void *srcBase, void *dstBase, \
                                 juint width, juint height, \
                                 SurfaceDataRasInfo *pSrcInfo, \
                                 SurfaceDataRasInfo *pDstInfo, \
                                 NativePrimitive *pPrim, \
                                 CompositeInfo *pCompInfo) \
{ \
    Declare ## DST ## StoreVars(DstWrite) \
    Declare ## LUT_STRATEGY ## Lut(SRC, DST, pixLut) \
 \
    Setup ## LUT_STRATEGY ## Lut(SRC, DST, pixLut,\
                                 pSrcInfo, pDstInfo); \
    BlitLoopWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                        DST, pDst, dstBase, pDstInfo, DstWrite, \
                        width, height, \
                        Body ## LUT_STRATEGY ## Lut(pSrc, SRC, \
                                                    pixLut, \
                                                    pDst, DST, \
                                                    DstWrite, 0, 0));\
}
#define DEFINE_CONVERT_BLIT_LUT8(SRC, DST, LUT_STRATEGY) \
    DEFINE_CONVERT_BLIT_LUT(SRC, DST, LUT_STRATEGY)

/*
 * This macro defines an entire function to implement a ScaleBlit inner
 * loop for scaling and converting pixels from a buffer of one type into
 * a buffer of another type.  No blending is done of the pixels.
 */
#define DEFINE_SCALE_BLIT(SRC, DST, STRATEGY) \
void NAME_SCALE_BLIT(SRC, DST)(void *srcBase, void *dstBase, \
                               juint width, juint height, \
                               jint sxloc, jint syloc, \
                               jint sxinc, jint syinc, jint shift, \
                               SurfaceDataRasInfo *pSrcInfo, \
                               SurfaceDataRasInfo *pDstInfo, \
                               NativePrimitive *pPrim, \
                               CompositeInfo *pCompInfo) \
{ \
    Declare ## SRC ## LoadVars(SrcRead) \
    Declare ## DST ## StoreVars(DstWrite) \
 \
    Init ## SRC ## LoadVars(SrcRead, pSrcInfo); \
    BlitLoopScaleWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                             DST, pDst, dstBase, pDstInfo, DstWrite, \
                             x, width, height, \
                             sxloc, syloc, sxinc, syinc, shift, \
                             ConvertVia ## STRATEGY(pSrc, SRC, SrcRead, \
                                                    pDst, DST, DstWrite, \
                                                    x, 0)); \
}

/*
 * This macro defines an entire function to implement a ScaleBlit inner
 * loop for scaling and converting pixels from a buffer of byte pixels
 * with a lookup table into a buffer of another type.  No blending is
 * done of the pixels.
 */
#define DEFINE_SCALE_BLIT_LUT(SRC, DST, LUT_STRATEGY) \
void NAME_SCALE_BLIT(SRC, DST)(void *srcBase, void *dstBase, \
                               juint width, juint height, \
                               jint sxloc, jint syloc, \
                               jint sxinc, jint syinc, jint shift, \
                               SurfaceDataRasInfo *pSrcInfo, \
                               SurfaceDataRasInfo *pDstInfo, \
                               NativePrimitive *pPrim, \
                               CompositeInfo *pCompInfo) \
{ \
    Declare ## DST ## StoreVars(DstWrite) \
    Declare ## LUT_STRATEGY ## Lut(SRC, DST, pixLut) \
 \
    Setup ## LUT_STRATEGY ## Lut(SRC, DST, pixLut, pSrcInfo, pDstInfo); \
    BlitLoopScaleWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                             DST, pDst, dstBase, pDstInfo, DstWrite, \
                             x, width, height, \
                             sxloc, syloc, sxinc, syinc, shift, \
                             Body ## LUT_STRATEGY ## Lut(pSrc, SRC, pixLut, \
                                                         pDst, DST, \
                                                         DstWrite, x, 0));\
}
#define DEFINE_SCALE_BLIT_LUT8(SRC, DST, LUT_STRATEGY) \
    DEFINE_SCALE_BLIT_LUT(SRC, DST, LUT_STRATEGY)

/*
 * This macro defines an entire function to implement a Blit inner loop
 * for drawing opaque pixels from a buffer of one type onto a buffer of
 * another type, ignoring the transparent pixels in the source buffer.
 * No blending is done of the pixels - the converted pixel value is
 * either copied or the destination is left untouched.
 */
#define DEFINE_XPAR_CONVERT_BLIT(SRC, DST, STRATEGY) \
void NAME_XPAR_CONVERT_BLIT(SRC, DST)(void *srcBase, void *dstBase, \
                                      juint width, juint height, \
                                      SurfaceDataRasInfo *pSrcInfo, \
                                      SurfaceDataRasInfo *pDstInfo, \
                                      NativePrimitive *pPrim, \
                                      CompositeInfo *pCompInfo) \
{ \
    Declare ## SRC ## LoadVars(SrcRead) \
    Declare ## DST ## StoreVars(DstWrite) \
 \
    Init ## SRC ## LoadVars(SrcRead, pSrcInfo); \
    BlitLoopWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                        DST, pDst, dstBase, pDstInfo, DstWrite, \
                        width, height, \
                        ConvertXparVia ## STRATEGY(pSrc, SRC, SrcRead, \
                                                   pDst, DST, DstWrite, \
                                                   0, 0)); \
}

/*
 * This macro defines an entire function to implement a Blit inner loop
 * for converting pixels from a buffer of byte pixels with a lookup
 * table containing transparent pixels into a buffer of another type.
 * No blending is done of the pixels - the converted pixel value is
 * either copied or the destination is left untouched.
 */
#define DEFINE_XPAR_CONVERT_BLIT_LUT(SRC, DST, LUT_STRATEGY) \
void NAME_XPAR_CONVERT_BLIT(SRC, DST)(void *srcBase, void *dstBase, \
                                      juint width, juint height, \
                                      SurfaceDataRasInfo *pSrcInfo, \
                                      SurfaceDataRasInfo *pDstInfo, \
                                      NativePrimitive *pPrim, \
                                      CompositeInfo *pCompInfo) \
{ \
    Declare ## DST ## StoreVars(DstWrite) \
    Declare ## LUT_STRATEGY ## XparLut(SRC, DST, pixLut) \
 \
    Setup ## LUT_STRATEGY ## XparLut(SRC, DST, pixLut, pSrcInfo, pDstInfo); \
    BlitLoopWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                        DST, pDst, dstBase, pDstInfo, DstWrite, \
                        width, height, \
                        Body ## LUT_STRATEGY ## XparLut(pSrc, SRC, pixLut, \
                                                        pDst, DST, \
                                                        DstWrite, 0, 0)); \
}
#define DEFINE_XPAR_CONVERT_BLIT_LUT8(SRC, DST, LUT_STRATEGY) \
    DEFINE_XPAR_CONVERT_BLIT_LUT(SRC, DST, LUT_STRATEGY)

/*
 * This macro defines an entire function to implement a ScaleBlit inner
 * loop for scaling and converting pixels from a buffer of byte pixels
 * with a lookup table containing transparent pixels into a buffer of
 * another type.
 * No blending is done of the pixels - the converted pixel value is
 * either copied or the destination is left untouched.
 */
#define DEFINE_XPAR_SCALE_BLIT_LUT(SRC, DST, LUT_STRATEGY) \
void NAME_XPAR_SCALE_BLIT(SRC, DST)(void *srcBase, void *dstBase, \
                                    juint width, juint height, \
                                    jint sxloc, jint syloc, \
                                    jint sxinc, jint syinc, jint shift, \
                                    SurfaceDataRasInfo *pSrcInfo, \
                                    SurfaceDataRasInfo *pDstInfo, \
                                    NativePrimitive *pPrim, \
                                    CompositeInfo *pCompInfo) \
{ \
    Declare ## DST ## StoreVars(DstWrite) \
    Declare ## LUT_STRATEGY ## XparLut(SRC, DST, pixLut) \
 \
    Setup ## LUT_STRATEGY ## XparLut(SRC, DST, pixLut, pSrcInfo, pDstInfo); \
    BlitLoopScaleWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                             DST, pDst, dstBase, pDstInfo, DstWrite, \
                             x, width, height, \
                             sxloc, syloc, sxinc, syinc, shift, \
                             Body ## LUT_STRATEGY ## XparLut(pSrc, SRC, pixLut, \
                                                             pDst, DST, \
                                                             DstWrite, \
                                                             x, 0)); \
}
#define DEFINE_XPAR_SCALE_BLIT_LUT8(SRC, DST, LUT_STRATEGY) \
    DEFINE_XPAR_SCALE_BLIT_LUT(SRC, DST, LUT_STRATEGY)

/*
 * This macro defines an entire function to implement a ScaleBlit inner
 * loop for scaling and converting pixels from a buffer of one type
 * containing transparent pixels into a buffer of another type.
 *
 * No blending is done of the pixels - the converted pixel value is
 * either copied or the destination is left untouched.
 */
#define DEFINE_XPAR_SCALE_BLIT(SRC, DST, STRATEGY) \
void NAME_XPAR_SCALE_BLIT(SRC, DST)(void *srcBase, void *dstBase, \
                               juint width, juint height, \
                               jint sxloc, jint syloc, \
                               jint sxinc, jint syinc, jint shift, \
                               SurfaceDataRasInfo *pSrcInfo, \
                               SurfaceDataRasInfo *pDstInfo, \
                               NativePrimitive *pPrim, \
                               CompositeInfo *pCompInfo) \
{ \
    Declare ## SRC ## LoadVars(SrcRead) \
    Declare ## DST ## StoreVars(DstWrite) \
 \
    Init ## SRC ## LoadVars(SrcRead, pSrcInfo); \
    BlitLoopScaleWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                             DST, pDst, dstBase, pDstInfo, DstWrite, \
                             x, width, height, \
                             sxloc, syloc, sxinc, syinc, shift, \
                             ConvertXparVia ## STRATEGY(pSrc, SRC, SrcRead, \
                                                        pDst, DST, DstWrite, \
                                                        x, 0)); \
}

/*
 * This macro defines an entire function to implement a BlitBg inner loop
 * for converting pixels from a buffer of one type containing transparent
 * pixels into a buffer of another type with a specified bgcolor for the
 * transparent pixels.
 * No blending is done of the pixels other than to substitute the
 * bgcolor for any transparent pixels.
 */
#define DEFINE_XPAR_BLITBG(SRC, DST, STRATEGY) \
void NAME_XPAR_BLITBG(SRC, DST)(void *srcBase, void *dstBase, \
                                juint width, juint height, \
                                jint bgpixel, \
                                SurfaceDataRasInfo *pSrcInfo, \
                                SurfaceDataRasInfo *pDstInfo, \
                                NativePrimitive *pPrim, \
                                CompositeInfo *pCompInfo) \
{ \
    Declare ## SRC ## LoadVars(SrcRead) \
    Declare ## DST ## StoreVars(DstWrite) \
    Declare ## DST ## PixelData(bgdata) \
 \
    Extract ## DST ## PixelData(bgpixel, bgdata); \
    BlitLoopWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                        DST, pDst, dstBase, pDstInfo, DstWrite, \
                        width, height, \
                        BgCopyXparVia ## STRATEGY(pSrc, SRC, SrcRead, \
                                                  pDst, DST, DstWrite, \
                                                  0, 0, bgpixel, bgdata)); \
}

/*
 * This macro defines an entire function to implement a BlitBg inner loop
 * for converting pixels from a buffer of byte pixels with a lookup
 * table containing transparent pixels into a buffer of another type
 * with a specified bgcolor for the transparent pixels.
 * No blending is done of the pixels other than to substitute the
 * bgcolor for any transparent pixels.
 */
#define DEFINE_XPAR_BLITBG_LUT(SRC, DST, LUT_STRATEGY) \
void NAME_XPAR_BLITBG(SRC, DST)(void *srcBase, void *dstBase, \
                                juint width, juint height, \
                                jint bgpixel, \
                                SurfaceDataRasInfo *pSrcInfo, \
                                SurfaceDataRasInfo *pDstInfo, \
                                NativePrimitive *pPrim, \
                                CompositeInfo *pCompInfo) \
{ \
    Declare ## DST ## StoreVars(DstWrite) \
    Declare ## LUT_STRATEGY ## BgLut(SRC, DST, pixLut) \
 \
    Setup ## LUT_STRATEGY ## BgLut(SRC, DST, pixLut, pSrcInfo, pDstInfo, \
                                   bgpixel); \
    BlitLoopWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                        DST, pDst, dstBase, pDstInfo, DstWrite, \
                        width, height, \
                        Body ## LUT_STRATEGY ## BgLut(pSrc, SRC, pixLut, \
                                                      pDst, DST, \
                                                      DstWrite, 0, 0, \
                                                      bgpixel)); \
}
#define DEFINE_XPAR_BLITBG_LUT8(SRC, DST, LUT_STRATEGY) \
    DEFINE_XPAR_BLITBG_LUT(SRC, DST, LUT_STRATEGY)

/*
 * This macro defines an entire function to implement a Blit inner loop
 * for converting pixels from a buffer of one type into a buffer of
 * another type.  Each source pixel is XORed with the current XOR color value.
 * That result is then XORed with the destination pixel and the final
 * result is stored in the destination surface.
 */
#define DEFINE_XOR_BLIT(SRC, DST, DSTANYTYPE) \
void NAME_XOR_BLIT(SRC, DST)(void *srcBase, void *dstBase, \
                             juint width, juint height, \
                             SurfaceDataRasInfo *pSrcInfo, \
                             SurfaceDataRasInfo *pDstInfo, \
                             NativePrimitive *pPrim, \
                             CompositeInfo *pCompInfo) \
{ \
    jint xorpixel = pCompInfo->details.xorPixel; \
    juint alphamask = pCompInfo->alphaMask; \
    Declare ## DSTANYTYPE ## PixelData(xor) \
    Declare ## DSTANYTYPE ## PixelData(mask) \
    Declare ## SRC ## LoadVars(SrcRead) \
    Declare ## DST ## StoreVars(DstWrite) \
 \
    Extract ## DSTANYTYPE ## PixelData(xorpixel, xor); \
    Extract ## DSTANYTYPE ## PixelData(alphamask, mask); \
 \
    Init ## SRC ## LoadVars(SrcRead, pSrcInfo); \
    BlitLoopWidthHeight(SRC, pSrc, srcBase, pSrcInfo, \
                        DST, pDst, dstBase, pDstInfo, DstWrite, \
                        width, height, \
                        XorVia1IntArgb(pSrc, SRC, SrcRead, \
                                       pDst, DST, DSTANYTYPE, \
                                       0, xorpixel, xor, \
                                       alphamask, mask, pDstInfo)); \
}

/*
 * This macro defines an entire function to implement a FillRect inner loop
 * for setting a rectangular region of pixels to a specific pixel value.
 * No blending of the fill color is done with the pixels.
 */
#define DEFINE_SOLID_FILLRECT(DST) \
void NAME_SOLID_FILLRECT(DST)(SurfaceDataRasInfo *pRasInfo, \
                              jint lox, jint loy, \
                              jint hix, jint hiy, \
                              jint pixel, \
                              NativePrimitive *pPrim, \
                              CompositeInfo *pCompInfo) \
{ \
    Declare ## DST ## PixelData(pix) \
    DST ## DataType *pPix; \
    jint scan = pRasInfo->scanStride; \
    juint height = hiy - loy; \
    juint width = hix - lox; \
 \
    pPix = PtrCoord(pRasInfo->rasBase, lox, DST ## PixelStride, loy, scan); \
    Extract ## DST ## PixelData(pixel, pix); \
    do { \
        juint x = 0; \
        do { \
            Store ## DST ## PixelData(pPix, x, pixel, pix); \
        } while (++x < width); \
        pPix = PtrAddBytes(pPix, scan); \
    } while (--height > 0); \
}

/*
 * This macro defines an entire function to implement a FillSpans inner loop
 * for iterating through a list of spans and setting those regions of pixels
 * to a specific pixel value.  No blending of the fill color is done with
 * the pixels.
 */
#define DEFINE_SOLID_FILLSPANS(DST) \
void NAME_SOLID_FILLSPANS(DST)(SurfaceDataRasInfo *pRasInfo, \
                               SpanIteratorFuncs *pSpanFuncs, void *siData, \
                               jint pixel, NativePrimitive *pPrim, \
                               CompositeInfo *pCompInfo) \
{ \
    void *pBase = pRasInfo->rasBase; \
    Declare ## DST ## PixelData(pix) \
    jint scan = pRasInfo->scanStride; \
    jint bbox[4]; \
 \
    Extract ## DST ## PixelData(pixel, pix); \
    while ((*pSpanFuncs->nextSpan)(siData, bbox)) { \
        jint x = bbox[0]; \
        jint y = bbox[1]; \
        juint w = bbox[2] - x; \
        juint h = bbox[3] - y; \
        DST ## DataType *pPix = PtrCoord(pBase, \
                                         x, DST ## PixelStride, \
                                         y, scan); \
        do { \
            juint relx; \
            for (relx = 0; relx < w; relx++) { \
                Store ## DST ## PixelData(pPix, relx, pixel, pix); \
            } \
            pPix = PtrAddBytes(pPix, scan); \
        } while (--h > 0); \
    } \
}

/*
 * This macro defines an entire function to implement a FillParallelogram
 * inner loop for tracing 2 diagonal edges (left and right) and setting
 * those regions of pixels between them to a specific pixel value.
 * No blending of the fill color is done with the pixels.
 */
#define DEFINE_SOLID_FILLPGRAM(DST) \
void NAME_SOLID_FILLPGRAM(DST)(SurfaceDataRasInfo *pRasInfo, \
                               jint lox, jint loy, jint hix, jint hiy, \
                               jlong leftx, jlong dleftx, \
                               jlong rightx, jlong drightx, \
                               jint pixel, struct _NativePrimitive *pPrim, \
                               CompositeInfo *pCompInfo) \
{ \
    Declare ## DST ## PixelData(pix) \
    jint scan = pRasInfo->scanStride; \
    DST ## DataType *pPix = PtrCoord(pRasInfo->rasBase, 0, 0, loy, scan); \
 \
    Extract ## DST ## PixelData(pixel, pix); \
    while (loy < hiy) { \
        jint lx = WholeOfLong(leftx); \
        jint rx = WholeOfLong(rightx); \
        if (lx < lox) lx = lox; \
        if (rx > hix) rx = hix; \
        while (lx < rx) { \
            Store ## DST ## PixelData(pPix, lx, pixel, pix); \
            lx++; \
        } \
        pPix = PtrAddBytes(pPix, scan); \
        leftx += dleftx; \
        rightx += drightx; \
        loy++; \
    } \
}

#define DEFINE_SOLID_DRAWPARALLELOGRAM_FUNCS(DST) \
    DrawParallelogramFuncs NAME_SOLID_PGRAM_FUNCS(DST) = { \
        NAME_SOLID_FILLPGRAM(DST), \
        NAME_SOLID_DRAWLINE(DST), \
    };

#define DEFINE_SOLID_PARALLELOGRAM(DST) \
    DEFINE_SOLID_FILLPGRAM(DST) \
    DEFINE_SOLID_DRAWPARALLELOGRAM_FUNCS(DST)

/*
 * This macro declares the bumpmajor and bumpminor variables used for the
 * DrawLine functions.
 */
#define DeclareBumps(BUMPMAJOR, BUMPMINOR) \
    jint BUMPMAJOR, BUMPMINOR;

/*
 * This macro extracts "instructions" from the bumpmajor and bumpminor masks
 * that determine the initial bumpmajor and bumpminor values.  The bumpmajor
 * and bumpminor masks are laid out in the following format:
 *
 * bumpmajormask:                      bumpminormask:
 * bit0: bumpmajor = pixelStride       bit0: bumpminor = pixelStride
 * bit1: bumpmajor = -pixelStride      bit1: bumpminor = -pixelStride
 * bit2: bumpmajor = scanStride        bit2: bumpminor = scanStride
 * bit3: bumpmajor = -scanStride       bit3: bumpminor = -scanStride
 */
#define InitBumps(BUMPMAJOR, BUMPMINOR, \
                  BUMPMAJORMASK, BUMPMINORMASK, \
                  PIXELSTRIDE, SCANSTRIDE) \
    BUMPMAJOR = (BUMPMAJORMASK & BUMP_POS_PIXEL) ? PIXELSTRIDE : \
                    (BUMPMAJORMASK & BUMP_NEG_PIXEL) ? -PIXELSTRIDE : \
                        (BUMPMAJORMASK & BUMP_POS_SCAN) ? SCANSTRIDE : \
                                                          -SCANSTRIDE; \
    BUMPMINOR = (BUMPMINORMASK & BUMP_POS_PIXEL) ? PIXELSTRIDE : \
                    (BUMPMINORMASK & BUMP_NEG_PIXEL) ? -PIXELSTRIDE : \
                        (BUMPMINORMASK & BUMP_POS_SCAN) ? SCANSTRIDE : \
                            (BUMPMINORMASK & BUMP_NEG_SCAN) ? -SCANSTRIDE : \
                                                              0; \
    BUMPMINOR += BUMPMAJOR;

/*
 * This macro defines an entire function to implement a DrawLine inner loop
 * for iterating along a horizontal or vertical line and setting the pixels
 * on that line to a specific pixel value.  No blending of the fill color
 * is done with the pixels.
 */
#define DEFINE_SOLID_DRAWLINE(DST) \
void NAME_SOLID_DRAWLINE(DST)(SurfaceDataRasInfo *pRasInfo, \
                              jint x1, jint y1, jint pixel, \
                              jint steps, jint error, \
                              jint bumpmajormask, jint errmajor, \
                              jint bumpminormask, jint errminor, \
                              NativePrimitive *pPrim, \
                              CompositeInfo *pCompInfo) \
{ \
    Declare ## DST ## PixelData(pix) \
    jint scan = pRasInfo->scanStride; \
    DST ## DataType *pPix = PtrCoord(pRasInfo->rasBase, \
                                     x1, DST ## PixelStride, \
                                     y1, scan); \
    DeclareBumps(bumpmajor, bumpminor) \
 \
    InitBumps(bumpmajor, bumpminor, bumpmajormask, bumpminormask, \
              DST ## PixelStride, scan); \
    Extract ## DST ## PixelData(pixel, pix); \
    if (errmajor == 0) { \
        do { \
            Store ## DST ## PixelData(pPix, 0, pixel, pix); \
            pPix = PtrAddBytes(pPix, bumpmajor); \
        } while (--steps > 0); \
    } else { \
        do { \
            Store ## DST ## PixelData(pPix, 0, pixel, pix); \
            if (error < 0) { \
                pPix = PtrAddBytes(pPix, bumpmajor); \
                error += errmajor; \
            } else { \
                pPix = PtrAddBytes(pPix, bumpminor); \
                error -= errminor; \
            } \
        } while (--steps > 0); \
    } \
}

/*
 * This macro defines an entire function to implement a FillRect inner loop
 * for setting a rectangular region of pixels to a specific pixel value.
 * Each destination pixel is XORed with the current XOR mode color as well as
 * the current fill color.
 */
#define DEFINE_XOR_FILLRECT(DST) \
void NAME_XOR_FILLRECT(DST)(SurfaceDataRasInfo *pRasInfo, \
                            jint lox, jint loy, \
                            jint hix, jint hiy, \
                            jint pixel, \
                            NativePrimitive *pPrim, \
                            CompositeInfo *pCompInfo) \
{ \
    jint xorpixel = pCompInfo->details.xorPixel; \
    juint alphamask = pCompInfo->alphaMask; \
    Declare ## DST ## PixelData(xor) \
    Declare ## DST ## PixelData(pix) \
    Declare ## DST ## PixelData(mask) \
    DST ## DataType *pPix; \
    jint scan = pRasInfo->scanStride; \
    juint height = hiy - loy; \
    juint width = hix - lox; \
 \
    pPix = PtrCoord(pRasInfo->rasBase, lox, DST ## PixelStride, loy, scan); \
    Extract ## DST ## PixelData(xorpixel, xor); \
    Extract ## DST ## PixelData(pixel, pix); \
    Extract ## DST ## PixelData(alphamask, mask); \
 \
    do { \
        juint x = 0; \
        do { \
            Xor ## DST ## PixelData(pixel, pix, pPix, x, \
                                    xorpixel, xor, alphamask, mask); \
        } while (++x < width); \
        pPix = PtrAddBytes(pPix, scan); \
    } while (--height > 0); \
}

/*
 * This macro defines an entire function to implement a FillSpans inner loop
 * for iterating through a list of spans and setting those regions of pixels
 * to a specific pixel value.  Each destination pixel is XORed with the
 * current XOR mode color as well as the current fill color.
 */
#define DEFINE_XOR_FILLSPANS(DST) \
void NAME_XOR_FILLSPANS(DST)(SurfaceDataRasInfo *pRasInfo, \
                             SpanIteratorFuncs *pSpanFuncs, \
                             void *siData, jint pixel, \
                             NativePrimitive *pPrim, \
                             CompositeInfo *pCompInfo) \
{ \
    void *pBase = pRasInfo->rasBase; \
    jint xorpixel = pCompInfo->details.xorPixel; \
    juint alphamask = pCompInfo->alphaMask; \
    Declare ## DST ## PixelData(xor) \
    Declare ## DST ## PixelData(pix) \
    Declare ## DST ## PixelData(mask) \
    jint scan = pRasInfo->scanStride; \
    jint bbox[4]; \
 \
    Extract ## DST ## PixelData(xorpixel, xor); \
    Extract ## DST ## PixelData(pixel, pix); \
    Extract ## DST ## PixelData(alphamask, mask); \
 \
    while ((*pSpanFuncs->nextSpan)(siData, bbox)) { \
        jint x = bbox[0]; \
        jint y = bbox[1]; \
        juint w = bbox[2] - x; \
        juint h = bbox[3] - y; \
        DST ## DataType *pPix = PtrCoord(pBase, \
                                         x, DST ## PixelStride, \
                                         y, scan); \
        do { \
            juint relx; \
            for (relx = 0; relx < w; relx++) { \
                Xor ## DST ## PixelData(pixel, pix, pPix, relx, \
                                        xorpixel, xor, alphamask, mask); \
            } \
            pPix = PtrAddBytes(pPix, scan); \
        } while (--h > 0); \
    } \
}

/*
 * This macro defines an entire function to implement a DrawLine inner loop
 * for iterating along a horizontal or vertical line and setting the pixels
 * on that line to a specific pixel value.  Each destination pixel is XORed
 * with the current XOR mode color as well as the current draw color.
 */
#define DEFINE_XOR_DRAWLINE(DST) \
void NAME_XOR_DRAWLINE(DST)(SurfaceDataRasInfo *pRasInfo, \
                            jint x1, jint y1, jint pixel, \
                            jint steps, jint error, \
                            jint bumpmajormask, jint errmajor, \
                            jint bumpminormask, jint errminor, \
                            NativePrimitive *pPrim, \
                            CompositeInfo *pCompInfo) \
{ \
    jint xorpixel = pCompInfo->details.xorPixel; \
    juint alphamask = pCompInfo->alphaMask; \
    Declare ## DST ## PixelData(xor) \
    Declare ## DST ## PixelData(pix) \
    Declare ## DST ## PixelData(mask) \
    jint scan = pRasInfo->scanStride; \
    DST ## DataType *pPix = PtrCoord(pRasInfo->rasBase, \
                                     x1, DST ## PixelStride, \
                                     y1, scan); \
    DeclareBumps(bumpmajor, bumpminor) \
 \
    InitBumps(bumpmajor, bumpminor, bumpmajormask, bumpminormask, \
              DST ## PixelStride, scan); \
    Extract ## DST ## PixelData(xorpixel, xor); \
    Extract ## DST ## PixelData(pixel, pix); \
    Extract ## DST ## PixelData(alphamask, mask); \
 \
    if (errmajor == 0) { \
        do { \
            Xor ## DST ## PixelData(pixel, pix, pPix, 0, \
                                    xorpixel, xor, alphamask, mask); \
            pPix = PtrAddBytes(pPix, bumpmajor); \
        } while (--steps > 0); \
    } else { \
        do { \
            Xor ## DST ## PixelData(pixel, pix, pPix, 0, \
                                    xorpixel, xor, alphamask, mask); \
            if (error < 0) { \
                pPix = PtrAddBytes(pPix, bumpmajor); \
                error += errmajor; \
            } else { \
                pPix = PtrAddBytes(pPix, bumpminor); \
                error -= errminor; \
            } \
        } while (--steps > 0); \
    } \
}

/*
 * This macro is used to declare the variables needed by the glyph clipping
 * macro.
 */
#define DeclareDrawGlyphListClipVars(PIXELS, ROWBYTES, WIDTH, HEIGHT, \
                                     LEFT, TOP, RIGHT, BOTTOM) \
    const jubyte * PIXELS; \
    int ROWBYTES; \
    int LEFT, TOP; \
    int WIDTH, HEIGHT; \
    int RIGHT, BOTTOM;

/*
 * This macro represents the glyph clipping code used in the various
 * DRAWGLYPHLIST macros.  This macro is typically used within a loop.  Note
 * that the body of this macro is NOT wrapped in a do..while block due to
 * the use of continue statements within the block (those continue statements
 * are intended skip the outer loop, not the do..while loop).  To combat this
 * problem, pass in the code (typically a continue statement) that should be
 * executed when a null glyph is encountered.
 */
#define ClipDrawGlyphList(DST, PIXELS, BYTESPERPIXEL, ROWBYTES, WIDTH, HEIGHT,\
                          LEFT, TOP, RIGHT, BOTTOM, \
                          CLIPLEFT, CLIPTOP, CLIPRIGHT, CLIPBOTTOM, \
                          GLYPHS, GLYPHCOUNTER, NULLGLYPHCODE) \
    PIXELS = (const jubyte *)GLYPHS[GLYPHCOUNTER].pixels; \
    if (!PIXELS) { \
        NULLGLYPHCODE; \
    } \
    ROWBYTES = GLYPHS[GLYPHCOUNTER].rowBytes; \
    LEFT     = GLYPHS[GLYPHCOUNTER].x; \
    TOP      = GLYPHS[GLYPHCOUNTER].y; \
    WIDTH    = GLYPHS[GLYPHCOUNTER].width; \
    HEIGHT   = GLYPHS[GLYPHCOUNTER].height; \
\
    /* if any clipping required, modify parameters now */ \
    RIGHT  = LEFT + WIDTH; \
    BOTTOM = TOP + HEIGHT; \
    if (LEFT < CLIPLEFT) { \
    /* Multiply needed for LCD text as PIXELS is really BYTES */ \
        PIXELS += (CLIPLEFT - LEFT) * BYTESPERPIXEL ; \
        LEFT = CLIPLEFT; \
    } \
    if (TOP < CLIPTOP) { \
        PIXELS += (CLIPTOP - TOP) * ROWBYTES; \
        TOP = CLIPTOP; \
    } \
    if (RIGHT > CLIPRIGHT) { \
        RIGHT = CLIPRIGHT; \
    } \
    if (BOTTOM > CLIPBOTTOM) { \
        BOTTOM = CLIPBOTTOM; \
    } \
    if (RIGHT <= LEFT || BOTTOM <= TOP) { \
        NULLGLYPHCODE; \
    } \
    WIDTH = RIGHT - LEFT; \
    HEIGHT = BOTTOM - TOP;

#define DEFINE_SOLID_DRAWGLYPHLIST(DST) \
void NAME_SOLID_DRAWGLYPHLIST(DST)(SurfaceDataRasInfo *pRasInfo, \
                                   ImageRef *glyphs, \
                                   jint totalGlyphs, jint fgpixel, \
                                   jint argbcolor, \
                                   jint clipLeft, jint clipTop, \
                                   jint clipRight, jint clipBottom, \
                                   NativePrimitive *pPrim, \
                                   CompositeInfo *pCompInfo) \
{ \
    jint glyphCounter; \
    jint scan = pRasInfo->scanStride; \
    Declare ## DST ## PixelData(pix) \
    DST ## DataType *pPix; \
\
    Extract ## DST ## PixelData(fgpixel, pix); \
    for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) { \
        DeclareDrawGlyphListClipVars(pixels, rowBytes, width, height, \
                                     left, top, right, bottom) \
        ClipDrawGlyphList(DST, pixels, 1, rowBytes, width, height, \
                          left, top, right, bottom, \
                          clipLeft, clipTop, clipRight, clipBottom, \
                          glyphs, glyphCounter, continue) \
        pPix = PtrCoord(pRasInfo->rasBase,left,DST ## PixelStride,top,scan); \
\
        do { \
            int x = 0; \
            do { \
                if (pixels[x]) { \
                    Store ## DST ## PixelData(pPix, x, fgpixel, pix); \
                } \
            } while (++x < width); \
            pPix = PtrAddBytes(pPix, scan); \
            pixels += rowBytes; \
        } while (--height > 0); \
    } \
}

#define GlyphListAABlend3ByteRgb(DST, GLYPH_PIXELS, PIXEL_INDEX, DST_PTR, \
                                 FG_PIXEL, PREFIX, SRC_PREFIX) \
   do { \
        DeclareCompVarsFor3ByteRgb(dst) \
        jint mixValSrc = GLYPH_PIXELS[PIXEL_INDEX]; \
        if (mixValSrc) { \
            if (mixValSrc < 255) { \
                jint mixValDst = 255 - mixValSrc; \
                Load ## DST ## To3ByteRgb(DST_PTR, pix, PIXEL_INDEX, \
                                          dstR, dstG, dstB); \
                MultMultAddAndStore3ByteRgbComps(dst, mixValDst, dst, \
                                                 mixValSrc, SRC_PREFIX); \
                Store ## DST ## From3ByteRgb(DST_PTR, pix, PIXEL_INDEX, \
                                             dstR, dstG, dstB); \
            } else { \
                Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \
                                          FG_PIXEL, PREFIX); \
            } \
        } \
    } while (0);

#define GlyphListAABlend4ByteArgb(DST, GLYPH_PIXELS, PIXEL_INDEX, DST_PTR, \
                                  FG_PIXEL, PREFIX, SRC_PREFIX) \
   do { \
        DeclareAlphaVarFor4ByteArgb(dstA) \
        DeclareCompVarsFor4ByteArgb(dst) \
        jint mixValSrc = GLYPH_PIXELS[PIXEL_INDEX]; \
        if (mixValSrc) { \
            if (mixValSrc < 255) { \
                jint mixValDst = 255 - mixValSrc; \
                Load ## DST ## To4ByteArgb(DST_PTR, pix, PIXEL_INDEX, \
                                           dstA, dstR, dstG, dstB); \
                dstA = MUL8(dstA, mixValDst) + \
                       MUL8(SRC_PREFIX ## A, mixValSrc); \
                MultMultAddAndStore4ByteArgbComps(dst, mixValDst, dst, \
                                                  mixValSrc, SRC_PREFIX); \
                if (!(DST ## IsOpaque) && \
                    !(DST ## IsPremultiplied) && dstA && dstA < 255) { \
                    DivideAndStore4ByteArgbComps(dst, dst, dstA); \
                } \
                Store ## DST ## From4ByteArgbComps(DST_PTR, pix, \
                                                   PIXEL_INDEX, dst); \
            } else { \
                Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \
                                          FG_PIXEL, PREFIX); \
            } \
        } \
    } while (0);

#define GlyphListAABlend1ByteGray(DST, GLYPH_PIXELS, PIXEL_INDEX, DST_PTR, \
                                  FG_PIXEL, PREFIX, SRC_PREFIX) \
   do { \
        DeclareCompVarsFor1ByteGray(dst) \
        jint mixValSrc = GLYPH_PIXELS[PIXEL_INDEX]; \
        if (mixValSrc) { \
            if (mixValSrc < 255) { \
                jint mixValDst = 255 - mixValSrc; \
                Load ## DST ## To1ByteGray(DST_PTR, pix, PIXEL_INDEX, \
                                           dstG); \
                MultMultAddAndStore1ByteGrayComps(dst, mixValDst, dst, \
                                                  mixValSrc, SRC_PREFIX); \
                Store ## DST ## From1ByteGray(DST_PTR, pix, PIXEL_INDEX, \
                                              dstG); \
            } else { \
                Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \
                                          FG_PIXEL, PREFIX); \
            } \
        } \
    } while (0);

#define GlyphListAABlend1ShortGray(DST, GLYPH_PIXELS, PIXEL_INDEX, DST_PTR, \
                                   FG_PIXEL, PREFIX, SRC_PREFIX) \
   do { \
        DeclareCompVarsFor1ShortGray(dst) \
        juint mixValSrc = GLYPH_PIXELS[PIXEL_INDEX]; \
        if (mixValSrc) { \
            if (mixValSrc < 255) { \
                juint mixValDst; \
                PromoteByteAlphaFor1ShortGray(mixValSrc); \
                mixValDst = 0xffff - mixValSrc; \
                Load ## DST ## To1ShortGray(DST_PTR, pix, PIXEL_INDEX, \
                                            dstG); \
                MultMultAddAndStore1ShortGrayComps(dst, mixValDst, dst, \
                                                   mixValSrc, SRC_PREFIX); \
                Store ## DST ## From1ShortGray(DST_PTR, pix, PIXEL_INDEX, \
                                               dstG); \
            } else { \
                Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \
                                          FG_PIXEL, PREFIX); \
            } \
        } \
    } while (0);

#define DEFINE_SOLID_DRAWGLYPHLISTAA(DST, STRATEGY) \
void NAME_SOLID_DRAWGLYPHLISTAA(DST)(SurfaceDataRasInfo *pRasInfo, \
                                     ImageRef *glyphs, \
                                     jint totalGlyphs, jint fgpixel, \
                                     jint argbcolor, \
                                     jint clipLeft, jint clipTop, \
                                     jint clipRight, jint clipBottom, \
                                     NativePrimitive *pPrim, \
                                     CompositeInfo *pCompInfo) \
{ \
    jint glyphCounter; \
    jint scan = pRasInfo->scanStride; \
    DST ## DataType *pPix; \
    Declare ## DST ## PixelData(solidpix) \
    DeclareAlphaVarFor ## STRATEGY(srcA) \
    DeclareCompVarsFor ## STRATEGY(src) \
\
    Declare ## DST ## LoadVars(pix) \
    Declare ## DST ## StoreVars(pix) \
\
    Init ## DST ## LoadVars(pix, pRasInfo); \
    Init ## DST ## StoreVarsY(pix, pRasInfo); \
    Init ## DST ## StoreVarsX(pix, pRasInfo); \
    Extract ## STRATEGY ## CompsAndAlphaFromArgb(argbcolor, src); \
    Extract ## DST ## PixelData(fgpixel, solidpix); \
\
    for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) { \
        DeclareDrawGlyphListClipVars(pixels, rowBytes, width, height, \
                                     left, top, right, bottom) \
        ClipDrawGlyphList(DST, pixels, 1, rowBytes, width, height, \
                          left, top, right, bottom, \
                          clipLeft, clipTop, clipRight, clipBottom, \
                          glyphs, glyphCounter, continue) \
        pPix = PtrCoord(pRasInfo->rasBase,left,DST ## PixelStride,top,scan); \
\
        Set ## DST ## StoreVarsYPos(pix, pRasInfo, top); \
        do { \
            int x = 0; \
            Set ## DST ## StoreVarsXPos(pix, pRasInfo, left); \
            do { \
                GlyphListAABlend ## STRATEGY(DST, pixels, x, pPix, \
                                             fgpixel, solidpix, src); \
                Next ## DST ## StoreVarsX(pix); \
            } while (++x < width); \
            pPix = PtrAddBytes(pPix, scan); \
            pixels += rowBytes; \
            Next ## DST ## StoreVarsY(pix); \
        } while (--height > 0); \
    } \
}


#define GlyphListLCDBlend3ByteRgb(DST, GLYPH_PIXELS, PIXEL_INDEX, DST_PTR, \
                                  FG_PIXEL, PREFIX, SRC_PREFIX) \
   do { \
        DeclareCompVarsFor3ByteRgb(dst) \
        jint mixValSrcG = GLYPH_PIXELS[PIXEL_INDEX*3+1]; \
        jint mixValSrcR, mixValSrcB; \
        if (rgbOrder) { \
            mixValSrcR = GLYPH_PIXELS[PIXEL_INDEX*3]; \
            mixValSrcB = GLYPH_PIXELS[PIXEL_INDEX*3+2]; \
        } else { \
            mixValSrcR = GLYPH_PIXELS[PIXEL_INDEX*3+2]; \
            mixValSrcB = GLYPH_PIXELS[PIXEL_INDEX*3]; \
        } \
        if ((mixValSrcR | mixValSrcG | mixValSrcB) != 0) { \
            if ((mixValSrcR & mixValSrcG & mixValSrcB) < 255) { \
                jint mixValDstR = 255 - mixValSrcR; \
                jint mixValDstG = 255 - mixValSrcG; \
                jint mixValDstB = 255 - mixValSrcB; \
                Load ## DST ## To3ByteRgb(DST_PTR, pix, PIXEL_INDEX, \
                                          dstR, dstG, dstB); \
                dstR = invGammaLut[dstR]; \
                dstG = invGammaLut[dstG]; \
                dstB = invGammaLut[dstB]; \
                MultMultAddAndStoreLCD3ByteRgbComps(dst, mixValDst, dst, \
                                                    mixValSrc, SRC_PREFIX); \
                dstR = gammaLut[dstR]; \
                dstG = gammaLut[dstG]; \
                dstB = gammaLut[dstB]; \
                Store ## DST ## From3ByteRgb(DST_PTR, pix, PIXEL_INDEX, \
                                             dstR, dstG, dstB); \
            } else { \
                Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \
                                          FG_PIXEL, PREFIX); \
            } \
        } \
    } while (0)


/* There is no alpha channel in the glyph data with which to interpolate
 * between the src and dst alphas, but a reasonable approximation is to
 * sum the coverage alphas of the colour channels and divide by 3.
 * We can approximate division by 3 using mult and shift. See
 * sun/font/scalerMethods.c for a detailed explanation of why "21931"
 */
#define GlyphListLCDBlend4ByteArgb(DST, GLYPH_PIXELS, PIXEL_INDEX, DST_PTR, \
                                  FG_PIXEL, PREFIX, SRC_PREFIX) \
   do { \
        DeclareAlphaVarFor4ByteArgb(dstA) \
        DeclareCompVarsFor4ByteArgb(dst) \
        jint mixValSrcG = GLYPH_PIXELS[PIXEL_INDEX*3+1]; \
        jint mixValSrcR, mixValSrcB; \
        if (rgbOrder) { \
            mixValSrcR = GLYPH_PIXELS[PIXEL_INDEX*3]; \
            mixValSrcB = GLYPH_PIXELS[PIXEL_INDEX*3+2]; \
        } else { \
            mixValSrcR = GLYPH_PIXELS[PIXEL_INDEX*3+2]; \
            mixValSrcB = GLYPH_PIXELS[PIXEL_INDEX*3]; \
        } \
        if ((mixValSrcR | mixValSrcG | mixValSrcB) != 0) { \
            if ((mixValSrcR & mixValSrcG & mixValSrcB) < 255) { \
                jint mixValDstR = 255 - mixValSrcR; \
                jint mixValDstG = 255 - mixValSrcG; \
                jint mixValDstB = 255 - mixValSrcB; \
                jint mixValSrcA = ((mixValSrcR + mixValSrcG + mixValSrcB) \
                                    * 21931) >> 16;\
                jint mixValDstA = 255 - mixValSrcA; \
                Load ## DST ## To4ByteArgb(DST_PTR, pix, PIXEL_INDEX, \
                                           dstA, dstR, dstG, dstB); \
                dstR = invGammaLut[dstR]; \
                dstG = invGammaLut[dstG]; \
                dstB = invGammaLut[dstB]; \
                dstA = MUL8(dstA, mixValDstA) + \
                       MUL8(SRC_PREFIX ## A, mixValSrcA); \
                MultMultAddAndStoreLCD4ByteArgbComps(dst, mixValDst, dst, \
                                                  mixValSrc, SRC_PREFIX); \
                dstR = gammaLut[dstR]; \
                dstG = gammaLut[dstG]; \
                dstB = gammaLut[dstB]; \
                if (!(DST ## IsOpaque) && \
                    !(DST ## IsPremultiplied) && dstA && dstA < 255) { \
                    DivideAndStore4ByteArgbComps(dst, dst, dstA); \
                } \
                Store ## DST ## From4ByteArgbComps(DST_PTR, pix, \
                                                   PIXEL_INDEX, dst); \
            } else { \
                Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \
                                          FG_PIXEL, PREFIX); \
            } \
        } \
    } while (0);

#define DEFINE_SOLID_DRAWGLYPHLISTLCD(DST, STRATEGY) \
void NAME_SOLID_DRAWGLYPHLISTLCD(DST)(SurfaceDataRasInfo *pRasInfo, \
                                     ImageRef *glyphs, \
                                     jint totalGlyphs, jint fgpixel, \
                                     jint argbcolor, \
                                     jint clipLeft, jint clipTop, \
                                     jint clipRight, jint clipBottom, \
                                     jint rgbOrder, \
                                     unsigned char *gammaLut, \
                                     unsigned char * invGammaLut, \
                                     NativePrimitive *pPrim, \
                                     CompositeInfo *pCompInfo) \
{ \
    jint glyphCounter, bpp; \
    jint scan = pRasInfo->scanStride; \
    DST ## DataType *pPix; \
    Declare ## DST ## PixelData(solidpix) \
    DeclareAlphaVarFor ## STRATEGY(srcA) \
    DeclareCompVarsFor ## STRATEGY(src) \
\
    Declare ## DST ## LoadVars(pix) \
    Declare ## DST ## StoreVars(pix) \
\
    Init ## DST ## LoadVars(pix, pRasInfo); \
    Init ## DST ## StoreVarsY(pix, pRasInfo); \
    Init ## DST ## StoreVarsX(pix, pRasInfo); \
    Extract ## STRATEGY ## CompsAndAlphaFromArgb(argbcolor, src); \
    Extract ## DST ## PixelData(fgpixel, solidpix); \
    srcR = invGammaLut[srcR]; \
    srcG = invGammaLut[srcG]; \
    srcB = invGammaLut[srcB]; \
\
    for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) { \
        DeclareDrawGlyphListClipVars(pixels, rowBytes, width, height, \
                                     left, top, right, bottom) \
        bpp = \
        (glyphs[glyphCounter].rowBytes == glyphs[glyphCounter].width) ? 1 : 3;\
        ClipDrawGlyphList(DST, pixels, bpp, rowBytes, width, height, \
                          left, top, right, bottom, \
                          clipLeft, clipTop, clipRight, clipBottom, \
                          glyphs, glyphCounter, continue) \
        pPix = PtrCoord(pRasInfo->rasBase,left,DST ## PixelStride,top,scan); \
\
        Set ## DST ## StoreVarsYPos(pix, pRasInfo, top); \
        if (bpp!=1) { \
           /* subpixel positioning adjustment */ \
            pixels += glyphs[glyphCounter].rowBytesOffset; \
        } \
        do { \
            int x = 0; \
            Set ## DST ## StoreVarsXPos(pix, pRasInfo, left); \
            if (bpp==1) { \
                do { \
                    if (pixels[x]) { \
                        Store ## DST ## PixelData(pPix, x, fgpixel, solidpix);\
                    } \
                } while (++x < width); \
            } else { \
                do { \
                    GlyphListLCDBlend ## STRATEGY(DST, pixels, x, pPix, \
                                                   fgpixel, solidpix, src); \
                    Next ## DST ## StoreVarsX(pix); \
                } while (++x < width); \
            } \
            pPix = PtrAddBytes(pPix, scan); \
            pixels += rowBytes; \
            Next ## DST ## StoreVarsY(pix); \
        } while (--height > 0); \
    } \
}

#define DEFINE_XOR_DRAWGLYPHLIST(DST) \
void NAME_XOR_DRAWGLYPHLIST(DST)(SurfaceDataRasInfo *pRasInfo, \
                                 ImageRef *glyphs, \
                                 jint totalGlyphs, jint fgpixel, \
                                 jint argbcolor, \
                                 jint clipLeft, jint clipTop, \
                                 jint clipRight, jint clipBottom, \
                                 NativePrimitive *pPrim, \
                                 CompositeInfo *pCompInfo) \
{ \
    jint glyphCounter; \
    jint scan = pRasInfo->scanStride; \
    jint xorpixel = pCompInfo->details.xorPixel; \
    juint alphamask = pCompInfo->alphaMask; \
    Declare ## DST ## PixelData(xor) \
    Declare ## DST ## PixelData(pix) \
    Declare ## DST ## PixelData(mask) \
    DST ## DataType *pPix; \
 \
    Extract ## DST ## PixelData(xorpixel, xor); \
    Extract ## DST ## PixelData(fgpixel, pix); \
    Extract ## DST ## PixelData(alphamask, mask); \
    for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) { \
        DeclareDrawGlyphListClipVars(pixels, rowBytes, width, height, \
                                     left, top, right, bottom) \
        ClipDrawGlyphList(DST, pixels, 1, rowBytes, width, height, \
                          left, top, right, bottom, \
                          clipLeft, clipTop, clipRight, clipBottom, \
                          glyphs, glyphCounter, continue) \
        pPix = PtrCoord(pRasInfo->rasBase,left,DST ## PixelStride,top,scan); \
 \
        do { \
            int x = 0; \
            do { \
                if (pixels[x]) { \
                    Xor ## DST ## PixelData(fgpixel, pix, pPix, x, \
                                            xorpixel, xor, alphamask, mask); \
                } \
            } while (++x < width); \
            pPix = PtrAddBytes(pPix, scan); \
            pixels += rowBytes; \
        } while (--height > 0); \
    } \
}

#define DEFINE_TRANSFORMHELPER_NN(SRC) \
void NAME_TRANSFORMHELPER_NN(SRC)(SurfaceDataRasInfo *pSrcInfo, \
                                  jint *pRGB, jint numpix, \
                                  jlong xlong, jlong dxlong, \
                                  jlong ylong, jlong dylong) \
{ \
    Declare ## SRC ## LoadVars(SrcRead) \
    SRC ## DataType *pBase = pSrcInfo->rasBase; \
    jint scan = pSrcInfo->scanStride; \
    jint *pEnd = pRGB + numpix; \
 \
    xlong += IntToLong(pSrcInfo->bounds.x1); \
    ylong += IntToLong(pSrcInfo->bounds.y1); \
 \
    Init ## SRC ## LoadVars(SrcRead, pSrcInfo); \
    while (pRGB < pEnd) { \
        SRC ## DataType *pRow = PtrAddBytes(pBase, WholeOfLong(ylong) * scan); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 0, \
                                    SrcRead, pRow, WholeOfLong(xlong)); \
        pRGB++; \
        xlong += dxlong; \
        ylong += dylong; \
    } \
}

#define DEFINE_TRANSFORMHELPER_BL(SRC) \
void NAME_TRANSFORMHELPER_BL(SRC)(SurfaceDataRasInfo *pSrcInfo, \
                                  jint *pRGB, jint numpix, \
                                  jlong xlong, jlong dxlong, \
                                  jlong ylong, jlong dylong) \
{ \
    Declare ## SRC ## LoadVars(SrcRead) \
    jint scan = pSrcInfo->scanStride; \
    jint cx, cy, cw, ch; \
    jint *pEnd = pRGB + numpix*4; \
 \
    cx = pSrcInfo->bounds.x1; \
    cw = pSrcInfo->bounds.x2-cx; \
 \
    cy = pSrcInfo->bounds.y1; \
    ch = pSrcInfo->bounds.y2-cy; \
 \
    xlong -= LongOneHalf; \
    ylong -= LongOneHalf; \
 \
    Init ## SRC ## LoadVars(SrcRead, pSrcInfo); \
    while (pRGB < pEnd) { \
        jint xwhole = WholeOfLong(xlong); \
        jint ywhole = WholeOfLong(ylong); \
        jint xdelta, ydelta, isneg; \
        SRC ## DataType *pRow; \
 \
        xdelta = ((juint) (xwhole + 1 - cw)) >> 31; \
        isneg = xwhole >> 31; \
        xwhole -= isneg; \
        xdelta += isneg; \
 \
        ydelta = ((ywhole + 1 - ch) >> 31); \
        isneg = ywhole >> 31; \
        ywhole -= isneg; \
        ydelta -= isneg; \
        ydelta &= scan; \
 \
        xwhole += cx; \
        pRow = PtrAddBytes(pSrcInfo->rasBase, (ywhole + cy) * scan); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 0, SrcRead, pRow, xwhole); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 1, SrcRead, pRow, xwhole+xdelta); \
        pRow = PtrAddBytes(pRow, ydelta); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 2, SrcRead, pRow, xwhole); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 3, SrcRead, pRow, xwhole+xdelta); \
 \
        pRGB += 4; \
        xlong += dxlong; \
        ylong += dylong; \
    } \
}

#define DEFINE_TRANSFORMHELPER_BC(SRC) \
void NAME_TRANSFORMHELPER_BC(SRC)(SurfaceDataRasInfo *pSrcInfo, \
                                  jint *pRGB, jint numpix, \
                                  jlong xlong, jlong dxlong, \
                                  jlong ylong, jlong dylong) \
{ \
    Declare ## SRC ## LoadVars(SrcRead) \
    jint scan = pSrcInfo->scanStride; \
    jint cx, cy, cw, ch; \
    jint *pEnd = pRGB + numpix*16; \
 \
    cx = pSrcInfo->bounds.x1; \
    cw = pSrcInfo->bounds.x2-cx; \
 \
    cy = pSrcInfo->bounds.y1; \
    ch = pSrcInfo->bounds.y2-cy; \
 \
    xlong -= LongOneHalf; \
    ylong -= LongOneHalf; \
 \
    Init ## SRC ## LoadVars(SrcRead, pSrcInfo); \
    while (pRGB < pEnd) { \
        jint xwhole = WholeOfLong(xlong); \
        jint ywhole = WholeOfLong(ylong); \
        jint xdelta0, xdelta1, xdelta2; \
        jint ydelta0, ydelta1, ydelta2; \
        jint isneg; \
        SRC ## DataType *pRow; \
 \
        xdelta0 = (-xwhole) >> 31; \
        xdelta1 = ((juint) (xwhole + 1 - cw)) >> 31; \
        xdelta2 = ((juint) (xwhole + 2 - cw)) >> 31; \
        isneg = xwhole >> 31; \
        xwhole -= isneg; \
        xdelta1 += isneg; \
        xdelta2 += xdelta1; \
 \
        ydelta0 = ((-ywhole) >> 31) & (-scan); \
        ydelta1 = ((ywhole + 1 - ch) >> 31) & scan; \
        ydelta2 = ((ywhole + 2 - ch) >> 31) & scan; \
        isneg = ywhole >> 31; \
        ywhole -= isneg; \
        ydelta1 += (isneg & -scan); \
 \
        xwhole += cx; \
        pRow = PtrAddBytes(pSrcInfo->rasBase, (ywhole + cy) * scan); \
        pRow = PtrAddBytes(pRow, ydelta0); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  0, SrcRead, pRow, xwhole+xdelta0); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  1, SrcRead, pRow, xwhole        ); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  2, SrcRead, pRow, xwhole+xdelta1); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  3, SrcRead, pRow, xwhole+xdelta2); \
        pRow = PtrAddBytes(pRow, -ydelta0); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  4, SrcRead, pRow, xwhole+xdelta0); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  5, SrcRead, pRow, xwhole        ); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  6, SrcRead, pRow, xwhole+xdelta1); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  7, SrcRead, pRow, xwhole+xdelta2); \
        pRow = PtrAddBytes(pRow, ydelta1); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  8, SrcRead, pRow, xwhole+xdelta0); \
        Copy ## SRC ## ToIntArgbPre(pRGB,  9, SrcRead, pRow, xwhole        ); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 10, SrcRead, pRow, xwhole+xdelta1); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 11, SrcRead, pRow, xwhole+xdelta2); \
        pRow = PtrAddBytes(pRow, ydelta2); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 12, SrcRead, pRow, xwhole+xdelta0); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 13, SrcRead, pRow, xwhole        ); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 14, SrcRead, pRow, xwhole+xdelta1); \
        Copy ## SRC ## ToIntArgbPre(pRGB, 15, SrcRead, pRow, xwhole+xdelta2); \
 \
        pRGB += 16; \
        xlong += dxlong; \
        ylong += dylong; \
    } \
}

#define DEFINE_TRANSFORMHELPER_FUNCS(SRC) \
    TransformHelperFuncs NAME_TRANSFORMHELPER_FUNCS(SRC) = { \
        NAME_TRANSFORMHELPER_NN(SRC), \
        NAME_TRANSFORMHELPER_BL(SRC), \
        NAME_TRANSFORMHELPER_BC(SRC), \
    };

#define DEFINE_TRANSFORMHELPERS(SRC) \
    DEFINE_TRANSFORMHELPER_NN(SRC) \
    DEFINE_TRANSFORMHELPER_BL(SRC) \
    DEFINE_TRANSFORMHELPER_BC(SRC) \
    DEFINE_TRANSFORMHELPER_FUNCS(SRC)

/*
 * The macros defined above use the following macro definitions supplied
 * for the various surface types to manipulate pixels and pixel data.
 * The surface-specific macros are typically supplied by header files
 * named after the SurfaceType name (i.e. IntArgb.h, ByteGray.h, etc.).
 *
 * In the macro names in the following definitions, the string <stype>
 * is used as a place holder for the SurfaceType name (i.e. IntArgb).
 * The macros above access these type specific macros using the ANSI
 * CPP token concatenation operator "##".
 *
 * <stype>DataType               A typedef for the type of the pointer
 *                               that is used to access the raster data
 *                               for the given surface type.
 * <stype>PixelStride            Pixel stride for the surface type.
 *
 * Declare<stype>LoadVars        Declare the variables needed to control
 *                               loading color information from an stype
 *                               raster (i.e. lookup tables).
 * Init<stype>LoadVars           Init the lookup table variables.
 * Declare<stype>StoreVars       Declare the storage variables needed to
 *                               control storing pixel data based on the
 *                               pixel coordinate (i.e. dithering variables).
 * Init<stype>StoreVarsY         Init the dither variables for starting Y.
 * Next<stype>StoreVarsY         Increment the dither variables for next Y.
 * Init<stype>StoreVarsX         Init the dither variables for starting X.
 * Next<stype>StoreVarsX         Increment the dither variables for next X.
 *
 * Load<stype>To1IntRgb          Load a pixel and form an INT_RGB integer.
 * Store<stype>From1IntRgb       Store a pixel from an INT_RGB integer.
 * Load<stype>To1IntArgb         Load a pixel and form an INT_ARGB integer.
 * Store<stype>From1IntArgb      Store a pixel from an INT_ARGB integer.
 * Load<stype>To3ByteRgb         Load a pixel into R, G, and B components.
 * Store<stype>From3ByteRgb      Store a pixel from R, G, and B components.
 * Load<stype>To4ByteArgb        Load a pixel into A, R, G, and B components.
 * Store<stype>From4ByteArgb     Store a pixel from A, R, G, and B components.
 * Load<stype>To1ByteGray        Load a pixel and form a BYTE_GRAY byte.
 * Store<stype>From1ByteGray     Store a pixel from a BYTE_GRAY byte.
 *
 * <stype>PixelType              Typedef for a "single quantity pixel" (SQP)
 *                               that can hold the data for one stype pixel.
 * <stype>XparLutEntry           An SQP that can be used to represent a
 *                               transparent pixel for stype.
 * Store<stype>NonXparFromArgb   Store an SQP from an INT_ARGB integer in
 *                               such a way that it would not be confused
 *                               with the XparLutEntry value for stype.
 * <stype>IsXparLutEntry         Test an SQP for the XparLutEntry value.
 * Store<stype>Pixel             Store the pixel data from an SQP.
 * <stype>PixelFromArgb          Converts an INT_ARGB value into the specific
 *                               pixel representation for the surface type.
 *
 * Declare<stype>PixelData       Declare the pixel data variables (PDV) needed
 *                               to hold the elements of pixel data ready to
 *                               store into an stype raster (may be empty for
 *                               stypes whose SQP format is their data format).
 * Extract<stype>PixelData       Extract an SQP value into the PDVs.
 * Store<stype>PixelData         Store the PDVs into an stype raster.
 * XorCopy<stype>PixelData       Xor the PDVs into an stype raster.
 */
#endif /* LoopMacros_h_Included */
