text:
package java.awt.image;

import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.ImageCapabilities;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Point2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Hashtable;
import java.util.Vector;

import sun.awt.image.BytePackedRaster;
import sun.awt.image.ShortComponentRaster;
import sun.awt.image.ByteComponentRaster;
import sun.awt.image.IntegerComponentRaster;
import sun.awt.image.OffScreenImageSource;

/**
 *
 * The BufferedImage subclass describes an {@link
 * java.awt.Image Image} with an accessible buffer of image data.
 * A BufferedImage is comprised of a {@link ColorModel} and a
 * {@link Raster} of image data.
 * The number and types of bands in the {@link SampleModel} of the
 * Raster must match the number and types required by the
 * ColorModel to represent its color and alpha components.
 * All BufferedImage objects have an upper left corner
 * coordinate of (0, 0).  Any Raster used to construct a
 * BufferedImage must therefore have minX=0 and minY=0.
 *
 *

 * This class relies on the data fetching and setting methods
 * of Raster,
 * and on the color characterization methods of ColorModel.
 *
 * @see ColorModel
 * @see Raster
 * @see WritableRaster
 */

public class BufferedImage extends java.awt.Image
                           implements WritableRenderedImage, Transparency
{
    int        imageType = TYPE_CUSTOM;
    ColorModel colorModel;
    WritableRaster raster;
    OffScreenImageSource osis;
    Hashtable properties;

    boolean    isAlphaPremultiplied;// If true, alpha has been premultiplied in
    // color channels

    /**
     * Image Type Constants
     */

    /**
     * Image type is not recognized so it must be a customized
     * image.  This type is only used as a return value for the getType()
     * method.
     */
    public static final int TYPE_CUSTOM = 0;

    /**
     * Represents an image with 8-bit RGB color components packed into
     * integer pixels.  The image has a {@link DirectColorModel} without
     * alpha.
     * When data with non-opaque alpha is stored
     * in an image of this type,
     * the color data must be adjusted to a non-premultiplied form
     * and the alpha discarded,
     * as described in the
     * {@link java.awt.AlphaComposite} documentation.
     */
    public static final int TYPE_INT_RGB = 1;

    /**
     * Represents an image with 8-bit RGBA color components packed into
     * integer pixels.  The image has a DirectColorModel
     * with alpha. The color data in this image is considered not to be
     * premultiplied with alpha.  When this type is used as the
     * imageType argument to a BufferedImage
     * constructor, the created image is consistent with images
     * created in the JDK1.1 and earlier releases.
     */
    public static final int TYPE_INT_ARGB = 2;

    /**
     * Represents an image with 8-bit RGBA color components packed into
     * integer pixels.  The image has a DirectColorModel
     * with alpha.  The color data in this image is considered to be
     * premultiplied with alpha.
     */
    public static final int TYPE_INT_ARGB_PRE = 3;

    /**
     * Represents an image with 8-bit RGB color components, corresponding
     * to a Windows- or Solaris- style BGR color model, with the colors
     * Blue, Green, and Red packed into integer pixels.  There is no alpha.
     * The image has a {@link DirectColorModel}.
     * When data with non-opaque alpha is stored
     * in an image of this type,
     * the color data must be adjusted to a non-premultiplied form
     * and the alpha discarded,
     * as described in the
     * {@link java.awt.AlphaComposite} documentation.
     */
    public static final int TYPE_INT_BGR = 4;

    /**
     * Represents an image with 8-bit RGB color components, corresponding
     * to a Windows-style BGR color model) with the colors Blue, Green,
     * and Red stored in 3 bytes.  There is no alpha.  The image has a
     * ComponentColorModel.
     * When data with non-opaque alpha is stored
     * in an image of this type,
     * the color data must be adjusted to a non-premultiplied form
     * and the alpha discarded,
     * as described in the
     * {@link java.awt.AlphaComposite} documentation.
     */
    public static final int TYPE_3BYTE_BGR = 5;

    /**
     * Represents an image with 8-bit RGBA color components with the colors
     * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha.  The
     * image has a ComponentColorModel with alpha.  The
     * color data in this image is considered not to be premultiplied with
     * alpha.  The byte data is interleaved in a single
     * byte array in the order A, B, G, R
     * from lower to higher byte addresses within each pixel.
     */
    public static final int TYPE_4BYTE_ABGR = 6;

    /**
     * Represents an image with 8-bit RGBA color components with the colors
     * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha.  The
     * image has a ComponentColorModel with alpha. The color
     * data in this image is considered to be premultiplied with alpha.
     * The byte data is interleaved in a single byte array in the order
     * A, B, G, R from lower to higher byte addresses within each pixel.
     */
    public static final int TYPE_4BYTE_ABGR_PRE = 7;

    /**
     * Represents an image with 5-6-5 RGB color components (5-bits red,
     * 6-bits green, 5-bits blue) with no alpha.  This image has
     * a DirectColorModel.
     * When data with non-opaque alpha is stored
     * in an image of this type,
     * the color data must be adjusted to a non-premultiplied form
     * and the alpha discarded,
     * as described in the
     * {@link java.awt.AlphaComposite} documentation.
     */
    public static final int TYPE_USHORT_565_RGB = 8;

    /**
     * Represents an image with 5-5-5 RGB color components (5-bits red,
     * 5-bits green, 5-bits blue) with no alpha.  This image has
     * a DirectColorModel.
     * When data with non-opaque alpha is stored
     * in an image of this type,
     * the color data must be adjusted to a non-premultiplied form
     * and the alpha discarded,
     * as described in the
     * {@link java.awt.AlphaComposite} documentation.
     */
    public static final int TYPE_USHORT_555_RGB = 9;

    /**
     * Represents a unsigned byte grayscale image, non-indexed.  This
     * image has a ComponentColorModel with a CS_GRAY
     * {@link ColorSpace}.
     * When data with non-opaque alpha is stored
     * in an image of this type,
     * the color data must be adjusted to a non-premultiplied form
     * and the alpha discarded,
     * as described in the
     * {@link java.awt.AlphaComposite} documentation.
     */
    public static final int TYPE_BYTE_GRAY = 10;

    /**
     * Represents an unsigned short grayscale image, non-indexed).  This
     * image has a ComponentColorModel with a CS_GRAY
     * ColorSpace.
     * When data with non-opaque alpha is stored
     * in an image of this type,
     * the color data must be adjusted to a non-premultiplied form
     * and the alpha discarded,
     * as described in the
     * {@link java.awt.AlphaComposite} documentation.
     */
    public static final int TYPE_USHORT_GRAY = 11;

    /**
     * Represents an opaque byte-packed 1, 2, or 4 bit image.  The
     * image has an {@link IndexColorModel} without alpha.  When this
     * type is used as the imageType argument to the
     * BufferedImage constructor that takes an
     * imageType argument but no ColorModel
     * argument, a 1-bit image is created with an
     * IndexColorModel with two colors in the default
     * sRGB ColorSpace: {0, 0, 0} and
     * {255, 255, 255}.
     *
     *
 Images with 2 or 4 bits per pixel may be constructed via
     * the BufferedImage constructor that takes a
     * ColorModel argument by supplying a
     * ColorModel with an appropriate map size.
     *
     *
 Images with 8 bits per pixel should use the image types
     * TYPE_BYTE_INDEXED or TYPE_BYTE_GRAY
     * depending on their ColorModel.

     *
 When color data is stored in an image of this type,
     * the closest color in the colormap is determined
     * by the IndexColorModel and the resulting index is stored.
     * Approximation and loss of alpha or color components
     * can result, depending on the colors in the
     * IndexColorModel colormap.
     */
    public static final int TYPE_BYTE_BINARY = 12;

    /**
     * Represents an indexed byte image.  When this type is used as the
     * imageType argument to the BufferedImage
     * constructor that takes an imageType argument
     * but no ColorModel argument, an
     * IndexColorModel is created with
     * a 256-color 6/6/6 color cube palette with the rest of the colors
     * from 216-255 populated by grayscale values in the
     * default sRGB ColorSpace.
     *
     *
 When color data is stored in an image of this type,
     * the closest color in the colormap is determined
     * by the IndexColorModel and the resulting index is stored.
     * Approximation and loss of alpha or color components
     * can result, depending on the colors in the
     * IndexColorModel colormap.
     */
    public static final int TYPE_BYTE_INDEXED = 13;

    private static final int DCM_RED_MASK   = 0x00ff0000;
    private static final int DCM_GREEN_MASK = 0x0000ff00;
    private static final int DCM_BLUE_MASK  = 0x000000ff;
    private static final int DCM_ALPHA_MASK = 0xff000000;
    private static final int DCM_565_RED_MASK = 0xf800;
    private static final int DCM_565_GRN_MASK = 0x07E0;
    private static final int DCM_565_BLU_MASK = 0x001F;
    private static final int DCM_555_RED_MASK = 0x7C00;
    private static final int DCM_555_GRN_MASK = 0x03E0;
    private static final int DCM_555_BLU_MASK = 0x001F;
    private static final int DCM_BGR_RED_MASK = 0x0000ff;
    private static final int DCM_BGR_GRN_MASK = 0x00ff00;
    private static final int DCM_BGR_BLU_MASK = 0xff0000;

    static private native void initIDs();
    static {
        ColorModel.loadLibraries();
        initIDs();
    }

    /**
     * Constructs a BufferedImage of one of the predefined
     * image types.  The ColorSpace for the image is the
     * default sRGB space.
     * @param width     width of the created image
     * @param height    height of the created image
     * @param imageType type of the created image
     * @see ColorSpace
     * @see #TYPE_INT_RGB
     * @see #TYPE_INT_ARGB
     * @see #TYPE_INT_ARGB_PRE
     * @see #TYPE_INT_BGR
     * @see #TYPE_3BYTE_BGR
     * @see #TYPE_4BYTE_ABGR
     * @see #TYPE_4BYTE_ABGR_PRE
     * @see #TYPE_BYTE_GRAY
     * @see #TYPE_USHORT_GRAY
     * @see #TYPE_BYTE_BINARY
     * @see #TYPE_BYTE_INDEXED
     * @see #TYPE_USHORT_565_RGB
     * @see #TYPE_USHORT_555_RGB
     */
    public BufferedImage(int width,
                         int height,
                         int imageType) {
        switch (imageType) {
        case TYPE_INT_RGB:
            {
                colorModel = new DirectColorModel(24,
                                                  0x00ff0000,   // Red
                                                  0x0000ff00,   // Green
                                                  0x000000ff,   // Blue
                                                  0x0           // Alpha
                                                  );
                  raster = colorModel.createCompatibleWritableRaster(width,
                                                                      height);
            }
        break;

        case TYPE_INT_ARGB:
            {
                colorModel = ColorModel.getRGBdefault();

                raster = colorModel.createCompatibleWritableRaster(width,
                                                                   height);
            }
        break;

        case TYPE_INT_ARGB_PRE:
            {
                colorModel = new
                    DirectColorModel(
                                     ColorSpace.getInstance(ColorSpace.CS_sRGB),
                                     32,
                                     0x00ff0000,// Red
                                     0x0000ff00,// Green
                                     0x000000ff,// Blue
                                     0xff000000,// Alpha
                                     true,       // Alpha Premultiplied
                                     DataBuffer.TYPE_INT
                                     );

                  raster = colorModel.createCompatibleWritableRaster(width,
                                                                      height);
            }
        break;

        case TYPE_INT_BGR:
            {
                colorModel = new DirectColorModel(24,
                                                  0x000000ff,   // Red
                                                  0x0000ff00,   // Green
                                                  0x00ff0000    // Blue
                                                  );
                  raster = colorModel.createCompatibleWritableRaster(width,
                                                                      height);
            }
        break;

        case TYPE_3BYTE_BGR:
            {
                ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
                int[] nBits = {8, 8, 8};
                int[] bOffs = {2, 1, 0};
                colorModel = new ComponentColorModel(cs, nBits, false, false,
                                                     Transparency.OPAQUE,
                                                     DataBuffer.TYPE_BYTE);
                raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
                                                        width, height,
                                                        width*3, 3,
                                                        bOffs, null);
            }
        break;

        case TYPE_4BYTE_ABGR:
            {
                ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
                int[] nBits = {8, 8, 8, 8};
                int[] bOffs = {3, 2, 1, 0};
                colorModel = new ComponentColorModel(cs, nBits, true, false,
                                                     Transparency.TRANSLUCENT,
                                                     DataBuffer.TYPE_BYTE);
                raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
                                                        width, height,
                                                        width*4, 4,
                                                        bOffs, null);
            }
        break;

        case TYPE_4BYTE_ABGR_PRE:
            {
                ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
                int[] nBits = {8, 8, 8, 8};
                int[] bOffs = {3, 2, 1, 0};
                colorModel = new ComponentColorModel(cs, nBits, true, true,
                                                     Transparency.TRANSLUCENT,
                                                     DataBuffer.TYPE_BYTE);
                raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
                                                        width, height,
                                                        width*4, 4,
                                                        bOffs, null);
            }
        break;

        case TYPE_BYTE_GRAY:
            {
                ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
                int[] nBits = {8};
                colorModel = new ComponentColorModel(cs, nBits, false, true,
                                                     Transparency.OPAQUE,
                                                     DataBuffer.TYPE_BYTE);
                raster = colorModel.createCompatibleWritableRaster(width,
                                                                   height);
            }
        break;

        case TYPE_USHORT_GRAY:
            {
                ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
                int[] nBits = {16};
                colorModel = new ComponentColorModel(cs, nBits, false, true,
                                                     Transparency.OPAQUE,
                                                     DataBuffer.TYPE_USHORT);
                raster = colorModel.createCompatibleWritableRaster(width,
                                                                   height);
            }
        break;

        case TYPE_BYTE_BINARY:
            {
                byte[] arr = {(byte)0, (byte)0xff};

                colorModel = new IndexColorModel(1, 2, arr, arr, arr);
                raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
                                                   width, height, 1, 1, null);
            }
        break;

        case TYPE_BYTE_INDEXED:
            {
                // Create a 6x6x6 color cube
                int[] cmap = new int[256];
                int i=0;
                for (int r=0; r < 256; r += 51) {
                    for (int g=0; g < 256; g += 51) {
                        for (int b=0; b < 256; b += 51) {
                            cmap[i++] = (r<<16)|(g<<8)|b;
                        }
                    }
                }
                // And populate the rest of the cmap with gray values
                int grayIncr = 256/(256-i);

                // The gray ramp will be between 18 and 252
                int gray = grayIncr*3;
                for (; i < 256; i++) {
                    cmap[i] = (gray<<16)|(gray<<8)|gray;
                    gray += grayIncr;
                }

                colorModel = new IndexColorModel(8, 256, cmap, 0, false, -1,
                                                 DataBuffer.TYPE_BYTE);
                raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
                                                      width, height, 1, null);
            }
        break;

        case TYPE_USHORT_565_RGB:
            {
                colorModel = new DirectColorModel(16,
                                                  DCM_565_RED_MASK,
                                                  DCM_565_GRN_MASK,
                                                  DCM_565_BLU_MASK
                                                  );
                raster = colorModel.createCompatibleWritableRaster(width,
                                                                   height);
            }
            break;

        case TYPE_USHORT_555_RGB:
            {
                colorModel = new DirectColorModel(15,
                                                  DCM_555_RED_MASK,
                                                  DCM_555_GRN_MASK,
                                                  DCM_555_BLU_MASK
                                                  );
                raster = colorModel.createCompatibleWritableRaster(width,
                                                                   height);
            }
            break;

        default:
            throw new IllegalArgumentException ("Unknown image type " +
                                                imageType);
        }

        this.imageType = imageType;
    }

    /**
     * Constructs a BufferedImage of one of the predefined
     * image types:
     * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED.
     *
     *
 If the image type is TYPE_BYTE_BINARY, the number of
     * entries in the color model is used to determine whether the
     * image should have 1, 2, or 4 bits per pixel.  If the color model
     * has 1 or 2 entries, the image will have 1 bit per pixel.  If it
     * has 3 or 4 entries, the image with have 2 bits per pixel.  If
     * it has between 5 and 16 entries, the image will have 4 bits per
     * pixel.  Otherwise, an IllegalArgumentException will be thrown.
     *
     * @param width     width of the created image
     * @param height    height of the created image
     * @param imageType type of the created image
     * @param cm        IndexColorModel of the created image
     * @throws IllegalArgumentException   if the imageType is not
     * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED or if the imageType is
     * TYPE_BYTE_BINARY and the color map has more than 16 entries.
     * @see #TYPE_BYTE_BINARY
     * @see #TYPE_BYTE_INDEXED
     */
    public BufferedImage (int width,
                          int height,
                          int imageType,
                          IndexColorModel cm) {
        if (cm.hasAlpha() && cm.isAlphaPremultiplied()) {
            throw new IllegalArgumentException("This image types do not have "+
                                               "premultiplied alpha.");
        }

        switch(imageType) {
        case TYPE_BYTE_BINARY:
            int bits; // Will be set below
            int mapSize = cm.getMapSize();
            if (mapSize <= 2) {
                bits = 1;
            } else if (mapSize <= 4) {
                bits = 2;
            } else if (mapSize <= 16) {
                bits = 4;
            } else {
                throw new IllegalArgumentException
                    ("Color map for TYPE_BYTE_BINARY " +
                     "must have no more than 16 entries");
            }
            raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
                                                width, height, 1, bits, null);
            break;

        case TYPE_BYTE_INDEXED:
            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
                                                    width, height, 1, null);
            break;
        default:
            throw new IllegalArgumentException("Invalid image type (" +
                                               imageType+").  Image type must"+
                                               " be either TYPE_BYTE_BINARY or "+
                                               " TYPE_BYTE_INDEXED");
        }

        if (!cm.isCompatibleRaster(raster)) {
            throw new IllegalArgumentException("Incompatible image type and IndexColorModel");
        }

        colorModel = cm;
        this.imageType = imageType;
    }

    /**
     * Constructs a new BufferedImage with a specified
     * ColorModel and Raster.  If the number and
     * types of bands in the SampleModel of the
     * Raster do not match the number and types required by
     * the ColorModel to represent its color and alpha
     * components, a {@link RasterFormatException} is thrown.  This
     * method can multiply or divide the color Raster data by
     * alpha to match the alphaPremultiplied state
     * in the ColorModel.  Properties for this
     * BufferedImage can be established by passing
     * in a {@link Hashtable} of String/Object
     * pairs.
     * @param cm ColorModel for the new image
     * @param raster     Raster for the image data
     * @param isRasterPremultiplied   if true, the data in
     *                  the raster has been premultiplied with alpha.
     * @param properties Hashtable of
     *                  String/Object pairs.
     * @exception RasterFormatException if the number and
     * types of bands in the SampleModel of the
     * Raster do not match the number and types required by
     * the ColorModel to represent its color and alpha
     * components.
     * @exception IllegalArgumentException if
     *          raster is incompatible with cm
     * @see ColorModel
     * @see Raster
     * @see WritableRaster
     */

/*
 *
 *  FOR NOW THE CODE WHICH DEFINES THE RASTER TYPE IS DUPLICATED BY DVF
 *  SEE THE METHOD DEFINERASTERTYPE @ RASTEROUTPUTMANAGER
 *
 */
    public BufferedImage (ColorModel cm,
                          WritableRaster raster,
                          boolean isRasterPremultiplied,
                          Hashtable<?,?> properties) {

        if (!cm.isCompatibleRaster(raster)) {
            throw new
                IllegalArgumentException("Raster "+raster+
                                         " is incompatible with ColorModel "+
                                         cm);
        }

        if ((raster.minX != 0) || (raster.minY != 0)) {
            throw new
                IllegalArgumentException("Raster "+raster+
                                         " has minX or minY not equal to zero: "
                                         + raster.minX + " " + raster.minY);
        }

        colorModel = cm;
        this.raster  = raster;
        this.properties = properties;
        int numBands = raster.getNumBands();
        boolean isAlphaPre = cm.isAlphaPremultiplied();
        ColorSpace cs;

        // Force the raster data alpha state to match the premultiplied
        // state in the color model
        coerceData(isRasterPremultiplied);

        SampleModel sm = raster.getSampleModel();
        cs = cm.getColorSpace();
        int csType = cs.getType();
        if (csType != ColorSpace.TYPE_RGB) {
            if (csType == ColorSpace.TYPE_GRAY
                && cm instanceof ComponentColorModel) {
                // Check if this might be a child raster (fix for bug 4240596)
                if (sm instanceof ComponentSampleModel &&
                    ((ComponentSampleModel)sm).getPixelStride() != numBands) {
                    imageType = TYPE_CUSTOM;
                } else if (raster instanceof ByteComponentRaster &&
                       raster.getNumBands() == 1 &&
                       cm.getComponentSize(0) == 8 &&
                       ((ByteComponentRaster)raster).getPixelStride() == 1) {
                    imageType = TYPE_BYTE_GRAY;
                } else if (raster instanceof ShortComponentRaster &&
                       raster.getNumBands() == 1 &&
                       cm.getComponentSize(0) == 16 &&
                       ((ShortComponentRaster)raster).getPixelStride() == 1) {
                    imageType = TYPE_USHORT_GRAY;
                }
            } else {
                imageType = TYPE_CUSTOM;
            }
            return;
        }

        if ((raster instanceof IntegerComponentRaster) &&
            (numBands == 3 || numBands == 4)) {
            IntegerComponentRaster iraster =
                (IntegerComponentRaster) raster;
            // Check if the raster params and the color model
            // are correct
            int pixSize = cm.getPixelSize();
            if (iraster.getPixelStride() == 1 &&
                cm instanceof DirectColorModel  &&
                (pixSize == 32 || pixSize == 24))
            {
                // Now check on the DirectColorModel params
                DirectColorModel dcm = (DirectColorModel) cm;
                int rmask = dcm.getRedMask();
                int gmask = dcm.getGreenMask();
                int bmask = dcm.getBlueMask();
                if (rmask == DCM_RED_MASK && gmask == DCM_GREEN_MASK &&
                    bmask == DCM_BLUE_MASK)
                {
                    if (dcm.getAlphaMask() == DCM_ALPHA_MASK) {
                        imageType = (isAlphaPre
                                     ? TYPE_INT_ARGB_PRE
                                     : TYPE_INT_ARGB);
                    }
                    else {
                        // No Alpha
                        if (!dcm.hasAlpha()) {
                            imageType = TYPE_INT_RGB;
                        }
                    }
                }   // if (dcm.getRedMask() == DCM_RED_MASK &&
                else if (rmask == DCM_BGR_RED_MASK && gmask == DCM_BGR_GRN_MASK
                         && bmask == DCM_BGR_BLU_MASK) {
                    if (!dcm.hasAlpha()) {
                        imageType = TYPE_INT_BGR;
                    }
                }  // if (rmask == DCM_BGR_RED_MASK &&
            }   // if (iraster.getPixelStride() == 1
        }   // ((raster instanceof IntegerComponentRaster) &&
        else if ((cm instanceof IndexColorModel) && (numBands == 1) &&
                 (!cm.hasAlpha() || !isAlphaPre))
        {
            IndexColorModel icm = (IndexColorModel) cm;
            int pixSize = icm.getPixelSize();

            if (raster instanceof BytePackedRaster) {
                imageType = TYPE_BYTE_BINARY;
            }   // if (raster instanceof BytePackedRaster)
            else if (raster instanceof ByteComponentRaster) {
                ByteComponentRaster braster = (ByteComponentRaster) raster;
                if (braster.getPixelStride() == 1 && pixSize <= 8) {
                    imageType = TYPE_BYTE_INDEXED;
                }
            }
        }   // else if (cm instanceof IndexColorModel) && (numBands == 1))
        else if ((raster instanceof ShortComponentRaster)
                 && (cm instanceof DirectColorModel)
                 && (numBands == 3)
                 && !cm.hasAlpha())
        {
            DirectColorModel dcm = (DirectColorModel) cm;
            if (dcm.getRedMask() == DCM_565_RED_MASK) {
                if (dcm.getGreenMask() == DCM_565_GRN_MASK &&
                    dcm.getBlueMask()  == DCM_565_BLU_MASK) {
                    imageType = TYPE_USHORT_565_RGB;
                }
            }
            else if (dcm.getRedMask() == DCM_555_RED_MASK) {
                if (dcm.getGreenMask() == DCM_555_GRN_MASK &&
                    dcm.getBlueMask() == DCM_555_BLU_MASK) {
                    imageType = TYPE_USHORT_555_RGB;
                }
            }
        }   // else if ((cm instanceof IndexColorModel) && (numBands == 1))
        else if ((raster instanceof ByteComponentRaster)
                 && (cm instanceof ComponentColorModel)
                 && (raster.getSampleModel() instanceof PixelInterleavedSampleModel)
                 && (numBands == 3 || numBands == 4))
        {
            ComponentColorModel ccm = (ComponentColorModel) cm;
            PixelInterleavedSampleModel csm =
                (PixelInterleavedSampleModel)raster.getSampleModel();
            ByteComponentRaster braster = (ByteComponentRaster) raster;
            int[] offs = csm.getBandOffsets();
            if (ccm.getNumComponents() != numBands) {
                throw new RasterFormatException("Number of components in "+
                                                "ColorModel ("+
                                                ccm.getNumComponents()+
                                                ") does not match # in "+
                                                " Raster ("+numBands+")");
            }
            int[] nBits = ccm.getComponentSize();
            boolean is8bit = true;
            for (int i=0; i < numBands; i++) {
                if (nBits[i] != 8) {
                    is8bit = false;
                    break;
                }
            }
            if (is8bit &&
                offs[0] == numBands-1 &&
                offs[1] == numBands-2 &&
                offs[2] == numBands-3)
            {
                if (numBands == 3) {
                    imageType = TYPE_3BYTE_BGR;
                }
                else if (offs[3] == 0) {
                    imageType = (isAlphaPre
                                 ? TYPE_4BYTE_ABGR_PRE
                                 : TYPE_4BYTE_ABGR);
                }
            }
        }   // else if ((raster instanceof ByteComponentRaster) &&
    }

    /**
     * Returns the image type.  If it is not one of the known types,
     * TYPE_CUSTOM is returned.
     * @return the image type of this BufferedImage.
     * @see #TYPE_INT_RGB
     * @see #TYPE_INT_ARGB
     * @see #TYPE_INT_ARGB_PRE
     * @see #TYPE_INT_BGR
     * @see #TYPE_3BYTE_BGR
     * @see #TYPE_4BYTE_ABGR
     * @see #TYPE_4BYTE_ABGR_PRE
     * @see #TYPE_BYTE_GRAY
     * @see #TYPE_BYTE_BINARY
     * @see #TYPE_BYTE_INDEXED
     * @see #TYPE_USHORT_GRAY
     * @see #TYPE_USHORT_565_RGB
     * @see #TYPE_USHORT_555_RGB
     * @see #TYPE_CUSTOM
     */
    public int getType() {
        return imageType;
    }

    /**
     * Returns the ColorModel.
     * @return the ColorModel of this
     *  BufferedImage.
     */
    public ColorModel getColorModel() {
        return colorModel;
    }

    /**
     * Returns the {@link WritableRaster}.
     * @return the WriteableRaster of this
     *  BufferedImage.
     */
    public WritableRaster getRaster() {
        return raster;
    }

    /**
     * Returns a WritableRaster representing the alpha
     * channel for BufferedImage objects
     * with ColorModel objects that support a separate
     * spatial alpha channel, such as ComponentColorModel and
     * DirectColorModel.  Returns null if there
     * is no alpha channel associated with the ColorModel in
     * this image.  This method assumes that for all
     * ColorModel objects other than
     * IndexColorModel, if the ColorModel
     * supports alpha, there is a separate alpha channel
     * which is stored as the last band of image data.
     * If the image uses an IndexColorModel that
     * has alpha in the lookup table, this method returns
     * null since there is no spatially discrete alpha
     * channel.  This method creates a new
     * WritableRaster, but shares the data array.
     * @return a WritableRaster or null if this
     *          BufferedImage has no alpha channel associated
     *          with its ColorModel.
     */
    public WritableRaster getAlphaRaster() {
        return colorModel.getAlphaRaster(raster);
    }

    /**
     * Returns an integer pixel in the default RGB color model
     * (TYPE_INT_ARGB) and default sRGB colorspace.  Color
     * conversion takes place if this default model does not match
     * the image ColorModel.  There are only 8-bits of
     * precision for each color component in the returned data when using
     * this method.
     *
     *

     *
     * An ArrayOutOfBoundsException may be thrown
     * if the coordinates are not in bounds.
     * However, explicit bounds checking is not guaranteed.
     *
     * @param x the X coordinate of the pixel from which to get
     *          the pixel in the default RGB color model and sRGB
     *          color space
     * @param y the Y coordinate of the pixel from which to get
     *          the pixel in the default RGB color model and sRGB
     *          color space
     * @return an integer pixel in the default RGB color model and
     *          default sRGB colorspace.
     * @see #setRGB(int, int, int)
     * @see #setRGB(int, int, int, int, int[], int, int)
     */
    public int getRGB(int x, int y) {
        return colorModel.getRGB(raster.getDataElements(x, y, null));
    }

    /**
     * Returns an array of integer pixels in the default RGB color model
     * (TYPE_INT_ARGB) and default sRGB color space,
     * from a portion of the image data.  Color conversion takes
     * place if the default model does not match the image
     * ColorModel.  There are only 8-bits of precision for
     * each color component in the returned data when
     * using this method.  With a specified coordinate (x, y) in the
     * image, the ARGB pixel can be accessed in this way:
     *

     *
     *

     *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)];

     *
     *

     *
     * An ArrayOutOfBoundsException may be thrown
     * if the region is not in bounds.
     * However, explicit bounds checking is not guaranteed.
     *
     * @param startX      the starting X coordinate
     * @param startY      the starting Y coordinate
     * @param w           width of region
     * @param h           height of region
     * @param rgbArray    if not null, the rgb pixels are
     *          written here
     * @param offset      offset into the rgbArray
     * @param scansize    scanline stride for the rgbArray
     * @return            array of RGB pixels.
     * @see #setRGB(int, int, int)
     * @see #setRGB(int, int, int, int, int[], int, int)
     */
    public int[] getRGB(int startX, int startY, int w, int h,
                        int[] rgbArray, int offset, int scansize) {
        int yoff  = offset;
        int off;
        Object data;
        int nbands = raster.getNumBands();
        int dataType = raster.getDataBuffer().getDataType();
        switch (dataType) {
        case DataBuffer.TYPE_BYTE:
            data = new byte[nbands];
            break;
        case DataBuffer.TYPE_USHORT:
            data = new short[nbands];
            break;
        case DataBuffer.TYPE_INT:
            data = new int[nbands];
            break;
        case DataBuffer.TYPE_FLOAT:
            data = new float[nbands];
            break;
        case DataBuffer.TYPE_DOUBLE:
            data = new double[nbands];
            break;
        default:
            throw new IllegalArgumentException("Unknown data buffer type: "+
                                               dataType);
        }

        if (rgbArray == null) {
            rgbArray = new int[offset+h*scansize];
        }

        for (int y = startY; y < startY+h; y++, yoff+=scansize) {
            off = yoff;
            for (int x = startX; x < startX+w; x++) {
                rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x,
                                                                        y,
                                                                        data));
            }
        }

        return rgbArray;
    }

    /**
     * Sets a pixel in this BufferedImage to the specified
     * RGB value. The pixel is assumed to be in the default RGB color
     * model, TYPE_INT_ARGB, and default sRGB color space.  For images
     * with an IndexColorModel, the index with the nearest
     * color is chosen.
     *
     *

     *
     * An ArrayOutOfBoundsException may be thrown
     * if the coordinates are not in bounds.
     * However, explicit bounds checking is not guaranteed.
     *
     * @param x the X coordinate of the pixel to set
     * @param y the Y coordinate of the pixel to set
     * @param rgb the RGB value
     * @see #getRGB(int, int)
     * @see #getRGB(int, int, int, int, int[], int, int)
     */
    public synchronized void setRGB(int x, int y, int rgb) {
        raster.setDataElements(x, y, colorModel.getDataElements(rgb, null));
    }

    /**
     * Sets an array of integer pixels in the default RGB color model
     * (TYPE_INT_ARGB) and default sRGB color space,
     * into a portion of the image data.  Color conversion takes place
     * if the default model does not match the image
     * ColorModel.  There are only 8-bits of precision for
     * each color component in the returned data when
     * using this method.  With a specified coordinate (x, y) in the
     * this image, the ARGB pixel can be accessed in this way:
     *

     *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)];
     *

     * WARNING: No dithering takes place.
     *
     *

     *
     * An ArrayOutOfBoundsException may be thrown
     * if the region is not in bounds.
     * However, explicit bounds checking is not guaranteed.
     *
     * @param startX      the starting X coordinate
     * @param startY      the starting Y coordinate
     * @param w           width of the region
     * @param h           height of the region
     * @param rgbArray    the rgb pixels
     * @param offset      offset into the rgbArray
     * @param scansize    scanline stride for the rgbArray
     * @see #getRGB(int, int)
     * @see #getRGB(int, int, int, int, int[], int, int)
     */
    public void setRGB(int startX, int startY, int w, int h,
                        int[] rgbArray, int offset, int scansize) {
        int yoff  = offset;
        int off;
        Object pixel = null;

        for (int y = startY; y < startY+h; y++, yoff+=scansize) {
            off = yoff;
            for (int x = startX; x < startX+w; x++) {
                pixel = colorModel.getDataElements(rgbArray[off++], pixel);
                raster.setDataElements(x, y, pixel);
            }
        }
    }

    /**
     * Returns the width of the BufferedImage.
     * @return the width of this BufferedImage
     */
    public int getWidth() {
        return raster.getWidth();
    }

    /**
     * Returns the height of the BufferedImage.
     * @return the height of this BufferedImage
     */
    public int getHeight() {
        return raster.getHeight();
    }

    /**
     * Returns the width of the BufferedImage.
     * @param observer ignored
     * @return the width of this BufferedImage
     */
    public int getWidth(ImageObserver observer) {
        return raster.getWidth();
    }

    /**
     * Returns the height of the BufferedImage.
     * @param observer ignored
     * @return the height of this BufferedImage
     */
    public int getHeight(ImageObserver observer) {
        return raster.getHeight();
    }

    /**
     * Returns the object that produces the pixels for the image.
     * @return the {@link ImageProducer} that is used to produce the
     * pixels for this image.
     * @see ImageProducer
     */
    public ImageProducer getSource() {
        if (osis == null) {
            if (properties == null) {
                properties = new Hashtable();
            }
            osis = new OffScreenImageSource(this, properties);
        }
        return osis;
    }

    /**
     * Returns a property of the image by name.  Individual property names
     * are defined by the various image formats.  If a property is not
     * defined for a particular image, this method returns the
     * UndefinedProperty field.  If the properties
     * for this image are not yet known, then this method returns
     * null and the ImageObserver object is
     * notified later.  The property name "comment" should be used to
     * store an optional comment that can be presented to the user as a
     * description of the image, its source, or its author.
     * @param name the property name
     * @param observer the ImageObserver that receives
     *  notification regarding image information
     * @return an {@link Object} that is the property referred to by the
     *          specified name or null if the
     *          properties of this image are not yet known.
     * @throws NullPointerException if the property name is null.
     * @see ImageObserver
     * @see java.awt.Image#UndefinedProperty
     */
    public Object getProperty(String name, ImageObserver observer) {
        return getProperty(name);
    }

    /**
     * Returns a property of the image by name.
     * @param name the property name
     * @return an Object that is the property referred to by
     *          the specified name.
     * @throws NullPointerException if the property name is null.
     */
    public Object getProperty(String name) {
        if (name == null) {
            throw new NullPointerException("null property name is not allowed");
        }
        if (properties == null) {
            return java.awt.Image.UndefinedProperty;
        }
        Object o = properties.get(name);
        if (o == null) {
            o = java.awt.Image.UndefinedProperty;
        }
        return o;
    }

    /**
     * This method returns a {@link Graphics2D}, but is here
     * for backwards compatibility.  {@link #createGraphics() createGraphics} is more
     * convenient, since it is declared to return a
     * Graphics2D.
     * @return a Graphics2D, which can be used to draw into
     *          this image.
     */
    public java.awt.Graphics getGraphics() {
        return createGraphics();
    }

    /**
     * Creates a Graphics2D, which can be used to draw into
     * this BufferedImage.
     * @return a Graphics2D, used for drawing into this
     *          image.
     */
    public Graphics2D createGraphics() {
        GraphicsEnvironment env =
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        return env.createGraphics(this);
    }

    /**
     * Returns a subimage defined by a specified rectangular region.
     * The returned BufferedImage shares the same
     * data array as the original image.
     * @param x the X coordinate of the upper-left corner of the
     *          specified rectangular region
     * @param y the Y coordinate of the upper-left corner of the
     *          specified rectangular region
     * @param w the width of the specified rectangular region
     * @param h the height of the specified rectangular region
     * @return a BufferedImage that is the subimage of this
     *          BufferedImage.
     * @exception RasterFormatException if the specified
     * area is not contained within this BufferedImage.
     */
    public BufferedImage getSubimage (int x, int y, int w, int h) {
        return new BufferedImage (colorModel,
                                  raster.createWritableChild(x, y, w, h,
                                                             0, 0, null),
                                  colorModel.isAlphaPremultiplied(),
                                  properties);
    }

    /**
     * Returns whether or not the alpha has been premultiplied.  It
     * returns false if there is no alpha.
     * @return true if the alpha has been premultiplied;
     *          false otherwise.
     */
    public boolean isAlphaPremultiplied() {
        return colorModel.isAlphaPremultiplied();
    }

    /**
     * Forces the data to match the state specified in the
     * isAlphaPremultiplied variable.  It may multiply or
     * divide the color raster data by alpha, or do nothing if the data is
     * in the correct state.
     * @param isAlphaPremultiplied true if the alpha has been
     *          premultiplied; false otherwise.
     */
    public void coerceData (boolean isAlphaPremultiplied) {
        if (colorModel.hasAlpha() &&
            colorModel.isAlphaPremultiplied() != isAlphaPremultiplied) {
            // Make the color model do the conversion
            colorModel = colorModel.coerceData (raster, isAlphaPremultiplied);
        }
    }

    /**
     * Returns a String representation of this
     * BufferedImage object and its values.
     * @return a String representing this
     *          BufferedImage.
     */
    public String toString() {
        return new String("BufferedImage@"+Integer.toHexString(hashCode())
                          +": type = "+imageType
                          +" "+colorModel+" "+raster);
    }

    /**
     * Returns a {@link Vector} of {@link RenderedImage} objects that are
     * the immediate sources, not the sources of these immediate sources,
     * of image data for this BufferedImage.  This
     * method returns null if the BufferedImage
     * has no information about its immediate sources.  It returns an
     * empty Vector if the BufferedImage has no
     * immediate sources.
     * @return a Vector containing immediate sources of
     *          this BufferedImage object's image date, or
     *          null if this BufferedImage has
     *          no information about its immediate sources, or an empty
     *          Vector if this BufferedImage
     *          has no immediate sources.
     */
    public Vector<RenderedImage> getSources() {
        return null;
    }

    /**
     * Returns an array of names recognized by
     * {@link #getProperty(String) getProperty(String)}
     * or null, if no property names are recognized.
     * @return a String array containing all of the property
     *          names that getProperty(String) recognizes;
     *          or null if no property names are recognized.
     */
    public String[] getPropertyNames() {
         return null;
    }

    /**
     * Returns the minimum x coordinate of this
     * BufferedImage.  This is always zero.
     * @return the minimum x coordinate of this
     *          BufferedImage.
     */
    public int getMinX() {
        return raster.getMinX();
    }

    /**
     * Returns the minimum y coordinate of this
     * BufferedImage.  This is always zero.
     * @return the minimum y coordinate of this
     *          BufferedImage.
     */
    public int getMinY() {
        return raster.getMinY();
    }

    /**
     * Returns the SampleModel associated with this
     * BufferedImage.
     * @return the SampleModel of this
     *          BufferedImage.
     */
    public SampleModel getSampleModel() {
        return raster.getSampleModel();
    }

    /**
     * Returns the number of tiles in the x direction.
     * This is always one.
     * @return the number of tiles in the x direction.
     */
    public int getNumXTiles() {
        return 1;
    }

    /**
     * Returns the number of tiles in the y direction.
     * This is always one.
     * @return the number of tiles in the y direction.
     */
    public int getNumYTiles() {
        return 1;
    }

    /**
     * Returns the minimum tile index in the x direction.
     * This is always zero.
     * @return the minimum tile index in the x direction.
     */
    public int getMinTileX() {
        return 0;
    }

    /**
     * Returns the minimum tile index in the y direction.
     * This is always zero.
     * @return the mininum tile index in the y direction.
     */
    public int getMinTileY() {
        return 0;
    }

    /**
     * Returns the tile width in pixels.
     * @return the tile width in pixels.
     */
    public int getTileWidth() {
       return raster.getWidth();
    }

    /**
     * Returns the tile height in pixels.
     * @return the tile height in pixels.
     */
    public int getTileHeight() {
       return raster.getHeight();
    }

    /**
     * Returns the x offset of the tile grid relative to the origin,
     * For example, the x coordinate of the location of tile
     * (0, 0).  This is always zero.
     * @return the x offset of the tile grid.
     */
    public int getTileGridXOffset() {
        return raster.getSampleModelTranslateX();
    }

    /**
     * Returns the y offset of the tile grid relative to the origin,
     * For example, the y coordinate of the location of tile
     * (0, 0).  This is always zero.
     * @return the y offset of the tile grid.
     */
    public int getTileGridYOffset() {
        return raster.getSampleModelTranslateY();
    }

    /**
     * Returns tile (tileX, tileY).  Note
     * that tileX and tileY are indices
     * into the tile array, not pixel locations.  The Raster
     * that is returned is live, which means that it is updated if the
     * image is changed.
     * @param tileX the x index of the requested tile in the tile array
     * @param tileY the y index of the requested tile in the tile array
     * @return a Raster that is the tile defined by the
     *          arguments tileX and tileY.
     * @exception ArrayIndexOutOfBoundsException if both
     *          tileX and tileY are not
     *          equal to 0
     */
    public Raster getTile(int tileX, int tileY) {
        if (tileX == 0 && tileY == 0) {
            return raster;
        }
        throw new ArrayIndexOutOfBoundsException("BufferedImages only have"+
             " one tile with index 0,0");
    }

    /**
     * Returns the image as one large tile.  The Raster
     * returned is a copy of the image data is not updated if the
     * image is changed.
     * @return a Raster that is a copy of the image data.
     * @see #setData(Raster)
     */
    public Raster getData() {

        // REMIND : this allocates a whole new tile if raster is a
        // subtile.  (It only copies in the requested area)
        // We should do something smarter.
        int width = raster.getWidth();
        int height = raster.getHeight();
        int startX = raster.getMinX();
        int startY = raster.getMinY();
        WritableRaster wr =
           Raster.createWritableRaster(raster.getSampleModel(),
                         new Point(raster.getSampleModelTranslateX(),
                                   raster.getSampleModelTranslateY()));

        Object tdata = null;

        for (int i = startY; i < startY+height; i++)  {
            tdata = raster.getDataElements(startX,i,width,1,tdata);
            wr.setDataElements(startX,i,width,1, tdata);
        }
        return wr;
    }

    /**
     * Computes and returns an arbitrary region of the
     * BufferedImage.  The Raster returned is a
     * copy of the image data and is not updated if the image is
     * changed.
     * @param rect the region of the BufferedImage to be
     * returned.
     * @return a Raster that is a copy of the image data of
     *          the specified region of the BufferedImage
     * @see #setData(Raster)
     */
    public Raster getData(Rectangle rect) {
        SampleModel sm = raster.getSampleModel();
        SampleModel nsm = sm.createCompatibleSampleModel(rect.width,
                                                         rect.height);
        WritableRaster wr = Raster.createWritableRaster(nsm,
                                                  rect.getLocation());
        int width = rect.width;
        int height = rect.height;
        int startX = rect.x;
        int startY = rect.y;

        Object tdata = null;

        for (int i = startY; i < startY+height; i++)  {
            tdata = raster.getDataElements(startX,i,width,1,tdata);
            wr.setDataElements(startX,i,width,1, tdata);
        }
        return wr;
    }

    /**
     * Computes an arbitrary rectangular region of the
     * BufferedImage and copies it into a specified
     * WritableRaster.  The region to be computed is
     * determined from the bounds of the specified
     * WritableRaster.  The specified
     * WritableRaster must have a
     * SampleModel that is compatible with this image.  If
     * outRaster is null,
     * an appropriate WritableRaster is created.
     * @param outRaster a WritableRaster to hold the returned
     *          part of the image, or null
     * @return a reference to the supplied or created
     *          WritableRaster.
     */
    public WritableRaster copyData(WritableRaster outRaster) {
        if (outRaster == null) {
            return (WritableRaster) getData();
        }
        int width = outRaster.getWidth();
        int height = outRaster.getHeight();
        int startX = outRaster.getMinX();
        int startY = outRaster.getMinY();

        Object tdata = null;

        for (int i = startY; i < startY+height; i++)  {
            tdata = raster.getDataElements(startX,i,width,1,tdata);
            outRaster.setDataElements(startX,i,width,1, tdata);
        }

        return outRaster;
    }

  /**
     * Sets a rectangular region of the image to the contents of the
     * specified Raster r, which is
     * assumed to be in the same coordinate space as the
     * BufferedImage. The operation is clipped to the bounds
     * of the BufferedImage.
     * @param r the specified Raster
     * @see #getData
     * @see #getData(Rectangle)
    */
    public void setData(Raster r) {
        int width = r.getWidth();
        int height = r.getHeight();
        int startX = r.getMinX();
        int startY = r.getMinY();

        int[] tdata = null;

        // Clip to the current Raster
        Rectangle rclip = new Rectangle(startX, startY, width, height);
        Rectangle bclip = new Rectangle(0, 0, raster.width, raster.height);
        Rectangle intersect = rclip.intersection(bclip);
        if (intersect.isEmpty()) {
            return;
        }
        width = intersect.width;
        height = intersect.height;
        startX = intersect.x;
        startY = intersect.y;

        // remind use get/setDataElements for speed if Rasters are
        // compatible
        for (int i = startY; i < startY+height; i++)  {
            tdata = r.getPixels(startX,i,width,1,tdata);
            raster.setPixels(startX,i,width,1, tdata);
        }
    }

  /**
   * Adds a tile observer.  If the observer is already present,
   * it receives multiple notifications.
   * @param to the specified {@link TileObserver}
   */
    public void addTileObserver (TileObserver to) {
    }

  /**
   * Removes a tile observer.  If the observer was not registered,
   * nothing happens.  If the observer was registered for multiple
   * notifications, it is now registered for one fewer notification.
   * @param to the specified TileObserver.
   */
    public void removeTileObserver (TileObserver to) {
    }

    /**
     * Returns whether or not a tile is currently checked out for writing.
     * @param tileX the x index of the tile.
     * @param tileY the y index of the tile.
     * @return true if the tile specified by the specified
     *          indices is checked out for writing; false
     *          otherwise.
     * @exception ArrayIndexOutOfBoundsException if both
     *          tileX and tileY are not equal
     *          to 0
     */
    public boolean isTileWritable (int tileX, int tileY) {
        if (tileX == 0 && tileY == 0) {
            return true;
        }
        throw new IllegalArgumentException("Only 1 tile in image");
    }

    /**
     * Returns an array of {@link Point} objects indicating which tiles
     * are checked out for writing.  Returns null if none are
     * checked out.
     * @return a Point array that indicates the tiles that
     *          are checked out for writing, or null if no
     *          tiles are checked out for writing.
     */
    public Point[] getWritableTileIndices() {
        Point[] p = new Point[1];
        p[0] = new Point(0, 0);

        return p;
    }

    /**
     * Returns whether or not any tile is checked out for writing.
     * Semantically equivalent to
     *

     * (getWritableTileIndices() != null).
     *

     * @return true if any tile is checked out for writing;
     *          false otherwise.
     */
    public boolean hasTileWriters () {
        return true;
    }

  /**
   * Checks out a tile for writing.  All registered
   * TileObservers are notified when a tile goes from having
   * no writers to having one writer.
   * @param tileX the x index of the tile
   * @param tileY the y index of the tile
   * @return a WritableRaster that is the tile, indicated by
   *            the specified indices, to be checked out for writing.
   */
    public WritableRaster getWritableTile (int tileX, int tileY) {
        return raster;
    }

  /**
   * Relinquishes permission to write to a tile.  If the caller
   * continues to write to the tile, the results are undefined.
   * Calls to this method should only appear in matching pairs
   * with calls to {@link #getWritableTile(int, int) getWritableTile(int, int)}.  Any other leads
   * to undefined results.  All registered TileObservers
   * are notified when a tile goes from having one writer to having no
   * writers.
   * @param tileX the x index of the tile
   * @param tileY the y index of the tile
   */
    public void releaseWritableTile (int tileX, int tileY) {
    }

    /**
     * Returns the transparency.  Returns either OPAQUE, BITMASK,
     * or TRANSLUCENT.
     * @return the transparency of this BufferedImage.
     * @see Transparency#OPAQUE
     * @see Transparency#BITMASK
     * @see Transparency#TRANSLUCENT
     * @since 1.5
     */
    public int getTransparency() {
        return colorModel.getTransparency();
    }
}


text:
#ifndef QANIMATIONJOBUTIL_P_H
#define QANIMATIONJOBUTIL_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#define RETURN_IF_DELETED(func) \
{ \
    bool *prevWasDeleted = m_wasDeleted; \
    bool wasDeleted = false; \
    m_wasDeleted = &wasDeleted; \
    func; \
    if (wasDeleted) { \
        if (prevWasDeleted) \
            *prevWasDeleted = true; \
        return; \
    } \
    m_wasDeleted = prevWasDeleted; \
}

#endif // QANIMATIONJOBUTIL_P_H

redpajama_set_name: RedPajamaGithub


text:
package org.jfree.data.function;

import java.util.Arrays;
import org.jfree.chart.TestUtilities;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
 * Tests for the {@link PolynomialFunction2D} class.
 */
public class PolynomialFunction2DTest {

    /**
     * Some tests for the constructor.
     */
    @Test
    public void testConstructor() {
        PolynomialFunction2D f = new PolynomialFunction2D(new double[] {1.0,
                2.0});
        assertTrue(Arrays.equals(new double[] {1.0, 2.0}, f.getCoefficients()));

        boolean pass = false;
        try {
            f = new PolynomialFunction2D(null);
        }
        catch (IllegalArgumentException e) {
            pass = true;
        }
        assertTrue(pass);
    }

    /**
     * Some checks for the getCoefficients() method.
     */
    @Test
    public void testGetCoefficients() {
        PolynomialFunction2D f = new PolynomialFunction2D(new double[] {1.0,
                2.0});
        double[] c = f.getCoefficients();
        assertTrue(Arrays.equals(new double[] {1.0, 2.0}, c));

        // make sure that modifying the returned array doesn't change the
        // function
        c[0] = 99.9;
        assertTrue(Arrays.equals(new double[] {1.0, 2.0}, f.getCoefficients()));
    }

    /**
     * Some checks for the getOrder() method.
     */
    @Test
    public void testGetOrder() {
        PolynomialFunction2D f = new PolynomialFunction2D(new double[] {1.0,
                2.0});
        assertEquals(1, f.getOrder());
    }

    /**
     * For datasets, the equals() method just checks keys and values.
     */
    @Test
    public void testEquals() {
        PolynomialFunction2D f1 = new PolynomialFunction2D(new double[] {1.0,
                2.0});
        PolynomialFunction2D f2 = new PolynomialFunction2D(new double[] {1.0,
                2.0});
        assertTrue(f1.equals(f2));
        f1 = new PolynomialFunction2D(new double[] {2.0, 3.0});
        assertFalse(f1.equals(f2));
        f2 = new PolynomialFunction2D(new double[] {2.0, 3.0});
        assertTrue(f1.equals(f2));
    }

    /**
     * Serialize an instance, restore it, and check for equality.
     */
    @Test
    public void testSerialization() {
        PolynomialFunction2D f1 = new PolynomialFunction2D(new double[] {1.0,
                2.0});
        PolynomialFunction2D f2 = (PolynomialFunction2D)
                TestUtilities.serialised(f1);
        assertEquals(f1, f2);
    }

    /**
     * Objects that are equal should have the same hash code otherwise FindBugs
     * will tell on us...
     */
    @Test
    public void testHashCode() {
        PolynomialFunction2D f1 = new PolynomialFunction2D(new double[] {1.0,
                2.0});
        PolynomialFunction2D f2 = new PolynomialFunction2D(new double[] {1.0,
                2.0});
        assertEquals(f1.hashCode(), f2.hashCode());

    }

}


text:
#include <Python.h>

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
#include "pycairo-private.h"

/* PycairoContext_FromContext
 * Create a new PycairoContext from a cairo_t
 * ctx  - a cairo_t to 'wrap' into a Python object.
 *        it is unreferenced if the PycairoContext creation fails, or if
 *        the cairo_t has an error status
 * type - the type of the object to instantiate; it can be NULL,
 *        meaning a base cairo.Context type, or it can be a subclass of
 *        cairo.Context.
 * base - the base object used to create the context, or NULL.
 *        it is referenced to keep it alive while the cairo_t is being used
 * Return value: New reference or NULL on failure
 */
PyObject *
PycairoContext_FromContext(cairo_t *ctx, PyTypeObject *type, PyObject *base)
{
    PyObject *o;

    assert (ctx != NULL);

    if (Pycairo_Check_Status (cairo_status (ctx))) {
	cairo_destroy (ctx);
	return NULL;
    }

    if (type == NULL)
        type = &PycairoContext_Type;
    o = PycairoContext_Type.tp_alloc (type, 0);
    if (o) {
	((PycairoContext *)o)->ctx = ctx;
	Py_XINCREF(base);
	((PycairoContext *)o)->base = base;
    } else {
	cairo_destroy (ctx);
    }
    return o;
}

static void
pycairo_dealloc(PycairoContext *o)
{
#ifdef DEBUG
    printf("context_dealloc start\n");
#endif
    if (o->ctx) {
	cairo_destroy(o->ctx);
	o->ctx = NULL;
    }
    Py_CLEAR(o->base);

    o->ob_type->tp_free((PyObject *)o);
#ifdef DEBUG
    printf("context_dealloc end\n");
#endif
}

static PyObject *
pycairo_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    PyObject *o;
    PycairoSurface *s;

    if (!PyArg_ParseTuple(args, "O!:Context.__new__",
			  &PycairoSurface_Type, &s))
	return NULL;

    o = type->tp_alloc(type, 0);
    if (o) {
	cairo_t *ctx = cairo_create (s->surface);
	if (Pycairo_Check_Status (cairo_status (ctx))) {
	    cairo_destroy (ctx);
	    Py_DECREF(o);
	    return NULL;
	}
	((PycairoContext *)o)->ctx = ctx;
    }
    return o;
}

static PyObject *
pycairo_append_path (PycairoContext *o, PyObject *args)
{
    PycairoPath *p;

    if (!PyArg_ParseTuple(args, "O!:Context.append_path",
			  &PycairoPath_Type, &p))
	return NULL;

    cairo_append_path (o->ctx, p->path);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_arc (PycairoContext *o, PyObject *args)
{
    double xc, yc, radius, angle1, angle2;

    if (!PyArg_ParseTuple (args, "ddddd:Context.arc",
			   &xc, &yc, &radius, &angle1, &angle2))
	return NULL;

    cairo_arc (o->ctx, xc, yc, radius, angle1, angle2);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_arc_negative (PycairoContext *o, PyObject *args)
{
    double xc, yc, radius, angle1, angle2;

    if (!PyArg_ParseTuple (args, "ddddd:Context.arc_negative",
			   &xc, &yc, &radius, &angle1, &angle2))
	return NULL;

    cairo_arc_negative (o->ctx, xc, yc, radius, angle1, angle2);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_clip (PycairoContext *o)
{
    cairo_clip (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_clip_preserve (PycairoContext *o)
{
    cairo_clip_preserve (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_close_path (PycairoContext *o)
{
    cairo_close_path (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_copy_page (PycairoContext *o)
{
    cairo_copy_page (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_copy_path (PycairoContext *o)
{
    return PycairoPath_FromPath (cairo_copy_path (o->ctx));
}

static PyObject *
pycairo_copy_path_flat (PycairoContext *o)
{
    return PycairoPath_FromPath (cairo_copy_path_flat (o->ctx));
}

static PyObject *
pycairo_curve_to (PycairoContext *o, PyObject *args)
{
    double x1, y1, x2, y2, x3, y3;

    if (!PyArg_ParseTuple (args, "dddddd:Context.curve_to",
			   &x1, &y1, &x2, &y2, &x3, &y3))
	return NULL;

    cairo_curve_to (o->ctx, x1, y1, x2, y2, x3, y3);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_device_to_user(PycairoContext *o, PyObject *args)
{
    double x, y;

    if (!PyArg_ParseTuple(args, "dd:Context.device_to_user", &x, &y))
	return NULL;

    cairo_device_to_user(o->ctx, &x, &y);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    return Py_BuildValue("(dd)", x, y);
}

static PyObject *
pycairo_device_to_user_distance (PycairoContext *o, PyObject *args)
{
    double dx, dy;

    if (!PyArg_ParseTuple (args, "dd:Context.device_to_user_distance",
			   &dx, &dy))
	return NULL;

    cairo_device_to_user_distance (o->ctx, &dx, &dy);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    return Py_BuildValue("(dd)", dx, dy);
}

static PyObject *
pycairo_fill (PycairoContext *o)
{
    cairo_fill (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_fill_extents (PycairoContext *o)
{
    double x1, y1, x2, y2;
    cairo_fill_extents (o->ctx, &x1, &y1, &x2, &y2);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    return Py_BuildValue("(dddd)", x1, y1, x2, y2);
}

static PyObject *
pycairo_fill_preserve (PycairoContext *o)
{
    cairo_fill_preserve (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_font_extents (PycairoContext *o)
{
    cairo_font_extents_t e;

    cairo_font_extents (o->ctx, &e);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    return Py_BuildValue("(ddddd)", e.ascent, e.descent, e.height,
			 e.max_x_advance, e.max_y_advance);
}

static PyObject *
pycairo_get_antialias (PycairoContext *o)
{
    return PyInt_FromLong (cairo_get_antialias (o->ctx));
}

static PyObject *
pycairo_get_current_point (PycairoContext *o)
{
    double x, y;
    cairo_get_current_point (o->ctx, &x, &y);
    return Py_BuildValue("(dd)", x, y);
}

static PyObject *
pycairo_get_fill_rule (PycairoContext *o)
{
    return PyInt_FromLong(cairo_get_fill_rule (o->ctx));
}

static PyObject *
pycairo_get_font_face (PycairoContext *o)
{
    cairo_font_face_t *font_face = cairo_get_font_face (o->ctx);
    cairo_font_face_reference (font_face);
    return PycairoFontFace_FromFontFace (font_face);
}

static PyObject *
pycairo_get_font_matrix (PycairoContext *o)
{
    cairo_matrix_t matrix;
    cairo_get_font_matrix (o->ctx, &matrix);
    return PycairoMatrix_FromMatrix (&matrix);
}

static PyObject *
pycairo_get_font_options (PycairoContext *o)
{
    cairo_font_options_t *options = cairo_font_options_create();

    cairo_get_font_options (o->ctx, options);
    /* there is no reference fn */
    return PycairoFontOptions_FromFontOptions (options);
}

static PyObject *
pycairo_get_line_cap (PycairoContext *o)
{
    return PyInt_FromLong(cairo_get_line_cap (o->ctx));
}

static PyObject *
pycairo_get_line_join (PycairoContext *o)
{
    return PyInt_FromLong(cairo_get_line_join (o->ctx));
}

static PyObject *
pycairo_get_line_width (PycairoContext *o)
{
    return PyFloat_FromDouble(cairo_get_line_width (o->ctx));
}

static PyObject *
pycairo_get_matrix (PycairoContext *o)
{
    cairo_matrix_t matrix;
    cairo_get_matrix (o->ctx, &matrix);
    return PycairoMatrix_FromMatrix (&matrix);
}

static PyObject *
pycairo_get_miter_limit (PycairoContext *o)
{
    return PyFloat_FromDouble(cairo_get_miter_limit(o->ctx));
}

static PyObject *
pycairo_get_operator (PycairoContext *o)
{
    return PyInt_FromLong(cairo_get_operator (o->ctx));
}

static PyObject *
pycairo_get_source (PycairoContext *o)
{
    cairo_pattern_t *pattern = cairo_get_source (o->ctx);
    cairo_pattern_reference (pattern);
    /* bug #2765 - "How do we identify surface (and pattern) types?"
     * should pass pattern type as arg2
     */
    return PycairoPattern_FromPattern (pattern, NULL);
}

static PyObject *
pycairo_get_target (PycairoContext *o)
{
    cairo_surface_t *surface = cairo_get_target (o->ctx);
    cairo_surface_reference (surface);
    /* bug #2765 - "How do we identify surface types?"
     * should pass surface type as arg2
     */
    return PycairoSurface_FromSurface (surface, NULL, NULL);
}

static PyObject *
pycairo_get_tolerance (PycairoContext *o)
{
    return PyFloat_FromDouble (cairo_get_tolerance (o->ctx));
}

static PyObject *
pycairo_identity_matrix (PycairoContext *o)
{
    cairo_identity_matrix (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_in_fill (PycairoContext *o, PyObject *args)
{
    double x, y;
    PyObject *result;

    if (!PyArg_ParseTuple (args, "dd:Context.in_fill", &x, &y))
	return NULL;

    result = cairo_in_fill (o->ctx, x, y) ? Py_True : Py_False;
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_INCREF(result);
    return result;
}

static PyObject *
pycairo_in_stroke (PycairoContext *o, PyObject *args)
{
    double x, y;
    PyObject *result;

    if (!PyArg_ParseTuple (args, "dd:Context.in_stroke", &x, &y))
	return NULL;

    result = cairo_in_stroke (o->ctx, x, y) ? Py_True : Py_False;
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_INCREF(result);
    return result;
}

static PyObject *
pycairo_line_to (PycairoContext *o, PyObject *args)
{
    double x, y;

    if (!PyArg_ParseTuple (args, "dd:Context.line_to", &x, &y))
	return NULL;

    cairo_line_to (o->ctx, x, y);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_mask (PycairoContext *o, PyObject *args)
{
    PycairoPattern *p;

    if (!PyArg_ParseTuple(args, "O!:Context.mask", &PycairoPattern_Type, &p))
	return NULL;

    cairo_mask (o->ctx, p->pattern);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_mask_surface (PycairoContext *o, PyObject *args)
{
    PycairoSurface *s;
    double surface_x = 0.0, surface_y = 0.0;

    if (!PyArg_ParseTuple (args, "O!|dd:Context.mask_surface",
			   &PycairoSurface_Type, &s, &surface_x, &surface_y))
	return NULL;

    cairo_mask_surface (o->ctx, s->surface, surface_x, surface_y);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_move_to (PycairoContext *o, PyObject *args)
{
    double x, y;

    if (!PyArg_ParseTuple (args, "dd:Context.move_to", &x, &y))
	return NULL;

    cairo_move_to (o->ctx, x, y);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_new_path (PycairoContext *o)
{
    cairo_new_path (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_paint (PycairoContext *o)
{
    cairo_paint (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_paint_with_alpha (PycairoContext *o, PyObject *args)
{
    double alpha;

    if (!PyArg_ParseTuple (args, "d:Context.paint_with_alpha", &alpha))
	return NULL;

    cairo_paint_with_alpha (o->ctx, alpha);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_rectangle (PycairoContext *o, PyObject *args)
{
    double x, y, width, height;

    if (!PyArg_ParseTuple (args, "dddd:Context.rectangle",
			   &x, &y, &width, &height))
	return NULL;

    cairo_rectangle (o->ctx, x, y, width, height);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_rel_curve_to (PycairoContext *o, PyObject *args)
{
    double dx1, dy1, dx2, dy2, dx3, dy3;

    if (!PyArg_ParseTuple (args, "dddddd:Context.rel_curve_to",
			   &dx1, &dy1, &dx2, &dy2, &dx3, &dy3))
	return NULL;

    cairo_rel_curve_to (o->ctx, dx1, dy1, dx2, dy2, dx3, dy3);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_rel_line_to (PycairoContext *o, PyObject *args)
{
    double dx, dy;

    if (!PyArg_ParseTuple (args, "dd:Context.rel_line_to", &dx, &dy))
	return NULL;

    cairo_rel_line_to (o->ctx, dx, dy);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_rel_move_to (PycairoContext *o, PyObject *args)
{
    double dx, dy;

    if (!PyArg_ParseTuple (args, "dd:Context.rel_move_to", &dx, &dy))
	return NULL;

    cairo_rel_move_to (o->ctx, dx, dy);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_reset_clip (PycairoContext *o)
{
    cairo_reset_clip (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_restore (PycairoContext *o)
{
    cairo_restore (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_rotate (PycairoContext *o, PyObject *args)
{
    double angle;

    if (!PyArg_ParseTuple(args, "d:Context.rotate", &angle))
	return NULL;

    cairo_rotate (o->ctx, angle);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_save (PycairoContext *o)
{
    cairo_save (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_scale (PycairoContext *o, PyObject *args)
{
    double sx, sy;

    if (!PyArg_ParseTuple (args, "dd:Context.scale", &sx, &sy))
	return NULL;

    cairo_scale (o->ctx, sx, sy);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_select_font_face (PycairoContext *o, PyObject *args)
{
    const char *family;
    cairo_font_slant_t slant = CAIRO_FONT_SLANT_NORMAL;
    cairo_font_weight_t weight = CAIRO_FONT_WEIGHT_NORMAL;

    if (!PyArg_ParseTuple(args, "s|ii:Context.select_font_face",
			  &family, &slant, &weight))
	return NULL;

    cairo_select_font_face (o->ctx, family, slant, weight);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_antialias (PycairoContext *o, PyObject *args)
{
    cairo_antialias_t antialias = CAIRO_ANTIALIAS_DEFAULT;

    if (!PyArg_ParseTuple(args, "|i:Context.set_antialias", &antialias))
	return NULL;

    cairo_set_antialias (o->ctx, antialias);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_dash (PycairoContext *o, PyObject *args)
{
    double *dashes, offset = 0;
    int ndash, i;
    PyObject *py_dashes;

    if (!PyArg_ParseTuple (args, "O|d:Context.set_dash", &py_dashes, &offset))
	return NULL;

    py_dashes = PySequence_Fast (py_dashes,
				 "first argument must be a sequence");
    if (!py_dashes)
	return NULL;

    ndash = PySequence_Fast_GET_SIZE(py_dashes);
    dashes = malloc (ndash * sizeof(double));
    for (i = 0; i < ndash; i++) {
	PyObject *item = PySequence_Fast_GET_ITEM(py_dashes, i);

	dashes[i] = PyFloat_AsDouble(item);
	if (PyErr_Occurred()) {
	    free (dashes);
	    Py_DECREF(py_dashes);
	    return NULL;
	}
    }
    Py_DECREF(py_dashes);

    cairo_set_dash (o->ctx, dashes, ndash, offset);
    free (dashes);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_fill_rule (PycairoContext *o, PyObject *args)
{
    cairo_fill_rule_t fill_rule;

    if (!PyArg_ParseTuple (args, "i:Context.set_fill_rule", &fill_rule))
	return NULL;

    cairo_set_fill_rule (o->ctx, fill_rule);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_font_matrix (PycairoContext *o, PyObject *args)
{
    PycairoMatrix *matrix;

    if (!PyArg_ParseTuple (args, "O!:Context.set_font_matrix",
			   &PycairoMatrix_Type, &matrix))
	return NULL;

    cairo_set_font_matrix (o->ctx, &matrix->matrix);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_font_face (PycairoContext *o, PyObject *obj)
{
    if (PyObject_TypeCheck(obj, &PycairoFontFace_Type))
	cairo_set_font_face (o->ctx, ((PycairoFontFace *)obj)->font_face);
    else if (obj == Py_None)
	cairo_set_font_face (o->ctx, NULL);
    else {
	PyErr_SetString(PyExc_TypeError,
			"Context.set_font_face() argument must be "
			"cairo.FontFace or None");
	return NULL;
    }

    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_font_options (PycairoContext *o, PyObject *args)
{
    PycairoFontOptions *options;

    if (!PyArg_ParseTuple (args, "O!:Context.set_font_options",
			   &PycairoFontOptions_Type, &options))
	return NULL;

    cairo_set_font_options (o->ctx, options->font_options);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_font_size (PycairoContext *o, PyObject *args)
{
    double size;

    if (!PyArg_ParseTuple (args, "d:Context.set_font_size", &size))
	return NULL;

    cairo_set_font_size (o->ctx, size);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_line_cap (PycairoContext *o, PyObject *args)
{
    cairo_line_cap_t line_cap;

    if (!PyArg_ParseTuple (args, "i:Context.set_line_cap", &line_cap))
	return NULL;

    cairo_set_line_cap (o->ctx, line_cap);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_line_join (PycairoContext *o, PyObject *args)
{
    cairo_line_join_t line_join;

    if (!PyArg_ParseTuple (args, "i:Context.set_line_join", &line_join))
	return NULL;

    cairo_set_line_join (o->ctx, line_join);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_line_width (PycairoContext *o, PyObject *args)
{
    double width;

    if (!PyArg_ParseTuple (args, "d:Context.set_line_width", &width))
	return NULL;

    cairo_set_line_width (o->ctx, width);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_matrix (PycairoContext *o, PyObject *args)
{
    PycairoMatrix *matrix;

    if (!PyArg_ParseTuple (args, "O!:Context.set_matrix",
			   &PycairoMatrix_Type, &matrix))
	return NULL;

    cairo_set_matrix (o->ctx, &matrix->matrix);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_miter_limit (PycairoContext *o, PyObject *args)
{
    double limit;

    if (!PyArg_ParseTuple (args, "d:Context.set_miter_limit", &limit))
	return NULL;

    cairo_set_miter_limit (o->ctx, limit);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_operator(PycairoContext *o, PyObject *args)
{
    cairo_operator_t op;

    if (!PyArg_ParseTuple(args, "i:Context.set_operator", &op))
	return NULL;

    cairo_set_operator(o->ctx, op);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_source (PycairoContext *o, PyObject *args)
{
    PycairoPattern *p;

    if (!PyArg_ParseTuple( args, "O!:Context.set_source",
			   &PycairoPattern_Type, &p))
	return NULL;

    cairo_set_source (o->ctx, p->pattern);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_source_rgb (PycairoContext *o, PyObject *args)
{
    double red, green, blue;

    if (!PyArg_ParseTuple (args, "ddd:Context.set_source_rgb",
			   &red, &green, &blue))
	return NULL;

    cairo_set_source_rgb (o->ctx, red, green, blue);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_source_rgba (PycairoContext *o, PyObject *args)
{
    double red, green, blue;
    double alpha = 1.0;

    if (!PyArg_ParseTuple (args, "ddd|d:Context.set_source_rgba",
			   &red, &green, &blue, &alpha))
	return NULL;

    cairo_set_source_rgba (o->ctx, red, green, blue, alpha);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_source_surface (PycairoContext *o, PyObject *args)
{
    PycairoSurface *surface;
    double x = 0.0, y = 0.0;

    if (!PyArg_ParseTuple (args, "O!|dd:Context.set_source_surface",
			   &PycairoSurface_Type, &surface, &x, &y))
	return NULL;

    cairo_set_source_surface (o->ctx, surface->surface, x, y);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_set_tolerance (PycairoContext *o, PyObject *args)
{
    double tolerance;

    if (!PyArg_ParseTuple (args, "d:Context.set_tolerance", &tolerance))
	return NULL;

    cairo_set_tolerance (o->ctx, tolerance);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_show_page (PycairoContext *o)
{
    cairo_show_page (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_show_text (PycairoContext *o, PyObject *args)
{
    const char *utf8;

    if (!PyArg_ParseTuple(args, "s:Context.show_text", &utf8))
	return NULL;

    cairo_show_text (o->ctx, utf8);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_stroke (PycairoContext *o)
{
    cairo_stroke (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_stroke_extents (PycairoContext *o)
{
    double x1, y1, x2, y2;
    cairo_stroke_extents (o->ctx, &x1, &y1, &x2, &y2);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    return Py_BuildValue("(dddd)", x1, y1, x2, y2);
}

static PyObject *
pycairo_stroke_preserve (PycairoContext *o)
{
    cairo_stroke_preserve (o->ctx);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_text_extents (PycairoContext *o, PyObject *args)
{
    const char *utf8;
    cairo_text_extents_t extents;

    if (!PyArg_ParseTuple (args, "s:Context.text_extents", &utf8))
	return NULL;

    cairo_text_extents (o->ctx, utf8, &extents);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    return Py_BuildValue("(dddddd)", extents.x_bearing, extents.y_bearing,
			 extents.width, extents.height, extents.x_advance,
			 extents.y_advance);
}

static PyObject *
pycairo_text_path (PycairoContext *o, PyObject *args)
{
    const char *utf8;

    if (!PyArg_ParseTuple (args, "s:Context.text_path", &utf8))
	return NULL;

    cairo_text_path (o->ctx, utf8);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_translate (PycairoContext *o, PyObject *args)
{
    double tx, ty;

    if (!PyArg_ParseTuple (args, "dd:Context.translate", &tx, &ty))
	return NULL;

    cairo_translate (o->ctx, tx, ty);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_transform (PycairoContext *o, PyObject *args)
{
    PycairoMatrix *matrix;

    if (!PyArg_ParseTuple (args, "O!:Context.transform",
			   &PycairoMatrix_Type, &matrix))
	return NULL;

    cairo_transform (o->ctx, &matrix->matrix);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    Py_RETURN_NONE;
}

static PyObject *
pycairo_user_to_device (PycairoContext *o, PyObject *args)
{
    double x, y;

    if (!PyArg_ParseTuple (args, "dd:Context.user_to_device", &x, &y))
	return NULL;

    cairo_user_to_device (o->ctx, &x, &y);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    return Py_BuildValue("(dd)", x, y);
}

static PyObject *
pycairo_user_to_device_distance (PycairoContext *o, PyObject *args)
{
    double dx, dy;

    if (!PyArg_ParseTuple (args, "dd:Context.user_to_device_distance",
		 	  &dx, &dy))
	return NULL;

    cairo_user_to_device_distance (o->ctx, &dx, &dy);
    if (Pycairo_Check_Status (cairo_status (o->ctx)))
	return NULL;
    return Py_BuildValue("(dd)", dx, dy);
}

static PyMethodDef pycairo_methods[] = {
    /* methods never exposed in a language binding:
     * cairo_destroy()
     * cairo_reference()
     *
     * cairo_status()
     * cairo_status_string()
     * - not needed since Pycairo calls Pycairo_Check_Status() to check
     *   for errors and raise exceptions
     */
    {"append_path",     (PyCFunction)pycairo_append_path,    METH_VARARGS},
    {"arc",             (PyCFunction)pycairo_arc,            METH_VARARGS},
    {"arc_negative",    (PyCFunction)pycairo_arc_negative,   METH_VARARGS},
    {"clip",            (PyCFunction)pycairo_clip,           METH_NOARGS},
    {"clip_preserve",   (PyCFunction)pycairo_clip_preserve,  METH_NOARGS},
    {"close_path",      (PyCFunction)pycairo_close_path,     METH_NOARGS},
    {"copy_page",       (PyCFunction)pycairo_copy_page,      METH_NOARGS},
    {"copy_path",       (PyCFunction)pycairo_copy_path,      METH_NOARGS},
    {"copy_path_flat",  (PyCFunction)pycairo_copy_path_flat, METH_NOARGS},
    {"curve_to",        (PyCFunction)pycairo_curve_to,       METH_VARARGS},
    {"device_to_user",  (PyCFunction)pycairo_device_to_user, METH_VARARGS},
    {"device_to_user_distance",
               (PyCFunction)pycairo_device_to_user_distance, METH_VARARGS},
    {"fill",            (PyCFunction)pycairo_fill,           METH_NOARGS},
    {"fill_extents",    (PyCFunction)pycairo_fill_extents,   METH_NOARGS},
    {"fill_preserve",   (PyCFunction)pycairo_fill_preserve,  METH_NOARGS},
    {"font_extents",    (PyCFunction)pycairo_font_extents,   METH_NOARGS},
    {"get_antialias",   (PyCFunction)pycairo_get_antialias,  METH_NOARGS},
    {"get_fill_rule",   (PyCFunction)pycairo_get_fill_rule,  METH_NOARGS},
    {"get_font_face",   (PyCFunction)pycairo_get_font_face,  METH_NOARGS},
    {"get_font_matrix", (PyCFunction)pycairo_get_font_matrix,METH_NOARGS},
    {"get_font_options",(PyCFunction)pycairo_get_font_options,METH_NOARGS},
    {"get_line_cap",    (PyCFunction)pycairo_get_line_cap,   METH_NOARGS},
    {"get_line_join",   (PyCFunction)pycairo_get_line_join,  METH_NOARGS},
    {"get_line_width",  (PyCFunction)pycairo_get_line_width, METH_NOARGS},
    {"get_matrix",      (PyCFunction)pycairo_get_matrix,     METH_NOARGS},
    {"get_miter_limit", (PyCFunction)pycairo_get_miter_limit,METH_NOARGS},
    {"get_operator",    (PyCFunction)pycairo_get_operator,   METH_NOARGS},
    {"get_source",      (PyCFunction)pycairo_get_source,     METH_NOARGS},
    {"get_target",      (PyCFunction)pycairo_get_target,     METH_NOARGS},
    {"get_tolerance",   (PyCFunction)pycairo_get_tolerance,  METH_NOARGS},
    /* glyph_extents */
    /* glyph_path    - undocumented */
    {"identity_matrix", (PyCFunction)pycairo_identity_matrix,METH_NOARGS},
    {"in_fill",         (PyCFunction)pycairo_in_fill,        METH_VARARGS},
    {"in_stroke",       (PyCFunction)pycairo_in_stroke,      METH_VARARGS},
    {"line_to",         (PyCFunction)pycairo_line_to,        METH_VARARGS},
    {"mask",            (PyCFunction)pycairo_mask,           METH_VARARGS},
    {"mask_surface",    (PyCFunction)pycairo_mask_surface,   METH_VARARGS},
    {"move_to",         (PyCFunction)pycairo_move_to,        METH_VARARGS},
    {"new_path",        (PyCFunction)pycairo_new_path,       METH_NOARGS},
    {"paint",           (PyCFunction)pycairo_paint,          METH_NOARGS},
    {"paint_with_alpha",(PyCFunction)pycairo_paint_with_alpha,METH_VARARGS},
    {"get_current_point",(PyCFunction)pycairo_get_current_point,METH_NOARGS},
    {"rectangle",       (PyCFunction)pycairo_rectangle,      METH_VARARGS},
    {"rel_curve_to",    (PyCFunction)pycairo_rel_curve_to,   METH_VARARGS},
    {"rel_line_to",     (PyCFunction)pycairo_rel_line_to,    METH_VARARGS},
    {"rel_move_to",     (PyCFunction)pycairo_rel_move_to,    METH_VARARGS},
    {"reset_clip",      (PyCFunction)pycairo_reset_clip,     METH_NOARGS},
    {"restore",         (PyCFunction)pycairo_restore,        METH_NOARGS},
    {"rotate",          (PyCFunction)pycairo_rotate,         METH_VARARGS},
    {"save",            (PyCFunction)pycairo_save,           METH_NOARGS},
    {"scale",           (PyCFunction)pycairo_scale,          METH_VARARGS},
    {"select_font_face",(PyCFunction)pycairo_select_font_face,METH_VARARGS},
    {"set_antialias",   (PyCFunction)pycairo_set_antialias,  METH_VARARGS},
    {"set_dash",        (PyCFunction)pycairo_set_dash,       METH_VARARGS},
    {"set_fill_rule",   (PyCFunction)pycairo_set_fill_rule,  METH_VARARGS},
    {"set_font_face",   (PyCFunction)pycairo_set_font_face,  METH_O},
    {"set_font_matrix", (PyCFunction)pycairo_set_font_matrix,METH_VARARGS},
    {"set_font_options",(PyCFunction)pycairo_set_font_options,METH_VARARGS},
    {"set_font_size",   (PyCFunction)pycairo_set_font_size,  METH_VARARGS},
    {"set_line_cap",    (PyCFunction)pycairo_set_line_cap,   METH_VARARGS},
    {"set_line_join",   (PyCFunction)pycairo_set_line_join,  METH_VARARGS},
    {"set_line_width",  (PyCFunction)pycairo_set_line_width, METH_VARARGS},
    {"set_matrix",      (PyCFunction)pycairo_set_matrix,     METH_VARARGS},
    {"set_miter_limit", (PyCFunction)pycairo_set_miter_limit,METH_VARARGS},
    {"set_operator",    (PyCFunction)pycairo_set_operator,   METH_VARARGS},
    {"set_source",      (PyCFunction)pycairo_set_source,     METH_VARARGS},
    {"set_source_rgb",  (PyCFunction)pycairo_set_source_rgb, METH_VARARGS},
    {"set_source_rgba", (PyCFunction)pycairo_set_source_rgba,METH_VARARGS},
    {"set_source_surface",(PyCFunction)pycairo_set_source_surface,
                                                             METH_VARARGS},
    {"set_tolerance",   (PyCFunction)pycairo_set_tolerance,  METH_VARARGS},
    /* show_glyphs - undocumented */
    {"show_page",       (PyCFunction)pycairo_show_page,      METH_NOARGS},
    {"show_text",       (PyCFunction)pycairo_show_text,      METH_VARARGS},
    {"stroke",          (PyCFunction)pycairo_stroke,         METH_NOARGS},
    {"stroke_extents",  (PyCFunction)pycairo_stroke_extents, METH_NOARGS},
    {"stroke_preserve", (PyCFunction)pycairo_stroke_preserve,METH_NOARGS},
    {"text_extents",    (PyCFunction)pycairo_text_extents,   METH_VARARGS},
    {"text_path",       (PyCFunction)pycairo_text_path,      METH_VARARGS},
    {"transform",       (PyCFunction)pycairo_transform,      METH_VARARGS},
    {"translate",       (PyCFunction)pycairo_translate,      METH_VARARGS},
    {"user_to_device",  (PyCFunction)pycairo_user_to_device, METH_VARARGS},
    {"user_to_device_distance",(PyCFunction)pycairo_user_to_device_distance,
                                                             METH_VARARGS},
    {NULL, NULL, 0, NULL},
};

PyTypeObject PycairoContext_Type = {
    PyObject_HEAD_INIT(NULL)
    0,                                  /* ob_size */
    "enso_win32.cairo.Context",                    /* tp_name */
    sizeof(PycairoContext),             /* tp_basicsize */
    0,                                  /* tp_itemsize */
    (destructor)pycairo_dealloc,        /* tp_dealloc */
    0,                                  /* tp_print */
    0,                                  /* tp_getattr */
    0,                                  /* tp_setattr */
    0,                                  /* tp_compare */
    0,                                  /* tp_repr */
    0,                                  /* tp_as_number */
    0,                                  /* tp_as_sequence */
    0,                                  /* tp_as_mapping */
    0,                                  /* tp_hash */
    0,                                  /* tp_call */
    0,                                  /* tp_str */
    0,                                  /* tp_getattro */
    0,                                  /* tp_setattro */
    0,                                  /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */
    0,                                  /* tp_doc */
    0,                                  /* tp_traverse */
    0,                                  /* tp_clear */
    0,                                  /* tp_richcompare */
    0,                                  /* tp_weaklistoffset */
    0,                                  /* tp_iter */
    0,                                  /* tp_iternext */
    pycairo_methods,                    /* tp_methods */
    0,                                  /* tp_members */
    0,                                  /* tp_getset */
    0, /* &PyBaseObject_Type, */        /* tp_base */
    0,                                  /* tp_dict */
    0,                                  /* tp_descr_get */
    0,                                  /* tp_descr_set */
    0,                                  /* tp_dictoffset */
    0,                                  /* tp_init */
    0,                                  /* tp_alloc */
    (newfunc)pycairo_new,               /* tp_new */
    0,                                  /* tp_free */
    0,                                  /* tp_is_gc */
    0,                                  /* tp_bases */
};