Blame src/libbluray/bdj/java/java/awt/BDGraphicsBase.java

Packit 5e46da
/*
Packit 5e46da
 * This file is part of libbluray
Packit 5e46da
 * Copyright (C) 2012-2014  libbluray
Packit 5e46da
 *
Packit 5e46da
 * This library is free software; you can redistribute it and/or
Packit 5e46da
 * modify it under the terms of the GNU Lesser General Public
Packit 5e46da
 * License as published by the Free Software Foundation; either
Packit 5e46da
 * version 2.1 of the License, or (at your option) any later version.
Packit 5e46da
 *
Packit 5e46da
 * This library is distributed in the hope that it will be useful,
Packit 5e46da
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5e46da
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 5e46da
 * Lesser General Public License for more details.
Packit 5e46da
 *
Packit 5e46da
 * You should have received a copy of the GNU Lesser General Public
Packit 5e46da
 * License along with this library. If not, see
Packit 5e46da
 * <http://www.gnu.org/licenses/>.
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
package java.awt;
Packit 5e46da
Packit 5e46da
import java.lang.reflect.Field;
Packit 5e46da
import java.text.AttributedCharacterIterator;
Packit 5e46da
import java.util.ArrayList;
Packit 5e46da
import java.util.Arrays;
Packit 5e46da
import java.util.Collections;
Packit 5e46da
import java.util.HashSet;
Packit 5e46da
import java.awt.image.AreaAveragingScaleFilter;
Packit 5e46da
import java.awt.image.BufferedImage;
Packit 5e46da
import java.awt.image.ImageConsumer;
Packit 5e46da
import java.awt.image.ImageObserver;
Packit 5e46da
Packit 5e46da
import org.dvb.ui.DVBBufferedImage;
Packit 5e46da
import org.dvb.ui.DVBAlphaComposite;
Packit 5e46da
import org.dvb.ui.DVBGraphics;
Packit 5e46da
import org.dvb.ui.UnsupportedDrawingOperationException;
Packit 5e46da
Packit 5e46da
import sun.awt.ConstrainableGraphics;
Packit 5e46da
Packit 5e46da
import org.videolan.GUIManager;
Packit 5e46da
import org.videolan.Logger;
Packit 5e46da
Packit 5e46da
abstract class BDGraphicsBase extends DVBGraphics implements ConstrainableGraphics {
Packit 5e46da
    private static final Color DEFAULT_COLOR = Color.BLACK;
Packit 5e46da
    private static final Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, 12);
Packit 5e46da
Packit 5e46da
    private int width;
Packit 5e46da
    private int height;
Packit 5e46da
    private int[] backBuffer;
Packit 5e46da
    private Area dirty;
Packit 5e46da
    private GraphicsConfiguration gc;
Packit 5e46da
    private Color foreground;
Packit 5e46da
    protected Color background;
Packit 5e46da
    private Font font;
Packit 5e46da
    private BDFontMetrics fontMetrics;
Packit 5e46da
    private AlphaComposite composite;
Packit 5e46da
Packit 5e46da
    /** The current xor color. If null then we are in paint mode. */
Packit 5e46da
    private Color xorColor;
Packit 5e46da
Packit 5e46da
    /** Translated X, Y offset from native offset. */
Packit 5e46da
    private int originX;
Packit 5e46da
    private int originY;
Packit 5e46da
Packit 5e46da
    /** The actual clip rectangle that is intersection of user clip and constrained rectangle. */
Packit 5e46da
    private Rectangle actualClip;
Packit 5e46da
Packit 5e46da
    /** The current user clip rectangle or null if no clip has been set. This is stored in the
Packit 5e46da
     native coordinate system and not the (possibly) translated Java coordinate system. */
Packit 5e46da
    private Rectangle clip = null;
Packit 5e46da
Packit 5e46da
    /** The rectangle this graphics object has been constrained too. This is stored in the
Packit 5e46da
     native coordinate system and not the (possibly) translated Java coordinate system.
Packit 5e46da
     If it is null then this graphics has not been constrained. The constrained rectangle
Packit 5e46da
     is another layer of clipping independant of the user clip. */
Packit 5e46da
    private Rectangle constrainedRect = null;
Packit 5e46da
Packit 5e46da
    BDGraphicsBase(BDGraphicsBase g) {
Packit 5e46da
        backBuffer = g.backBuffer;
Packit 5e46da
        dirty = g.dirty;
Packit 5e46da
        width = g.width;
Packit 5e46da
        height = g.height;
Packit 5e46da
        gc = g.gc;
Packit 5e46da
        foreground = g.foreground;
Packit 5e46da
        background = g.background;
Packit 5e46da
        composite = g.composite;
Packit 5e46da
        font = g.font;
Packit 5e46da
        fontMetrics = g.fontMetrics;
Packit 5e46da
        originX = g.originX;
Packit 5e46da
        originY = g.originY;
Packit 5e46da
        if (g.clip != null) {
Packit 5e46da
            clip = new Rectangle(g.clip);
Packit 5e46da
        }
Packit 5e46da
        setupClip();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    BDGraphicsBase(BDRootWindow window) {
Packit 5e46da
        width = window.getWidth();
Packit 5e46da
        height = window.getHeight();
Packit 5e46da
        backBuffer = window.getBdBackBuffer();
Packit 5e46da
        dirty = window.getDirtyArea();
Packit 5e46da
        gc = window.getGraphicsConfiguration();
Packit 5e46da
        foreground = window.getForeground();
Packit 5e46da
        background = window.getBackground();
Packit 5e46da
        font = window.getFont();
Packit 5e46da
Packit 5e46da
        postInit();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    BDGraphicsBase(BDImage image) {
Packit 5e46da
        width = image.getWidth();
Packit 5e46da
        height = image.getHeight();
Packit 5e46da
        backBuffer = image.getBdBackBuffer();
Packit 5e46da
        dirty = image.getDirtyArea();
Packit 5e46da
Packit 5e46da
        gc = image.getGraphicsConfiguration();
Packit 5e46da
        Component component = image.getComponent();
Packit 5e46da
        if (component != null) {
Packit 5e46da
            foreground = component.getForeground();
Packit 5e46da
            background = component.getBackground();
Packit 5e46da
            font = component.getFont();
Packit 5e46da
        }
Packit 5e46da
        if (background == null)
Packit 5e46da
            background = new Color(0, 0, 0, 0);
Packit 5e46da
Packit 5e46da
        postInit();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void postInit() {
Packit 5e46da
        if (foreground == null)
Packit 5e46da
            foreground = DEFAULT_COLOR;
Packit 5e46da
        if (background == null)
Packit 5e46da
            background = DEFAULT_COLOR;
Packit 5e46da
Packit 5e46da
        /* if font is not set, use AWT default font from BDJO */
Packit 5e46da
        if (font == null) {
Packit 5e46da
            font = GUIManager.getInstance().getDefaultFont();
Packit 5e46da
            if (font == null) {
Packit 5e46da
                font = DEFAULT_FONT;
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
        fontMetrics = null;
Packit 5e46da
Packit 5e46da
        composite = AlphaComposite.SrcOver;
Packit 5e46da
        setupClip();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public Graphics create() {
Packit 5e46da
        return new BDGraphics((BDGraphics)this);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /*
Packit 5e46da
     * DVBGraphics methods
Packit 5e46da
     */
Packit 5e46da
Packit 5e46da
    public int[] getAvailableCompositeRules()
Packit 5e46da
    {
Packit 5e46da
        /*
Packit 5e46da
        int[] rules = { DVBAlphaComposite.CLEAR, DVBAlphaComposite.SRC,
Packit 5e46da
                        DVBAlphaComposite.SRC_OVER, DVBAlphaComposite.DST_OVER,
Packit 5e46da
                        DVBAlphaComposite.SRC_IN, DVBAlphaComposite.DST_IN,
Packit 5e46da
                        DVBAlphaComposite.SRC_OUT, DVBAlphaComposite.DST_OUT };
Packit 5e46da
        */
Packit 5e46da
        int[] rules = {
Packit 5e46da
            DVBAlphaComposite.CLEAR,
Packit 5e46da
            DVBAlphaComposite.SRC,
Packit 5e46da
            DVBAlphaComposite.SRC_OVER };
Packit 5e46da
Packit 5e46da
        return rules;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public DVBAlphaComposite getDVBComposite()
Packit 5e46da
    {
Packit 5e46da
        Composite comp = getComposite();
Packit 5e46da
        if (!(comp instanceof AlphaComposite))
Packit 5e46da
            return null;
Packit 5e46da
        return DVBAlphaComposite.getInstance(
Packit 5e46da
                                             ((AlphaComposite)comp).getRule(),
Packit 5e46da
                                             ((AlphaComposite)comp).getAlpha());
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void setDVBComposite(DVBAlphaComposite comp)
Packit 5e46da
                    throws UnsupportedDrawingOperationException
Packit 5e46da
    {
Packit 5e46da
        if ((comp.getRule() < DVBAlphaComposite.CLEAR) ||
Packit 5e46da
            (comp.getRule() > DVBAlphaComposite.SRC_OVER)) {
Packit 5e46da
            logger.error("setDVBComposite() FAILED: unsupported rule " + comp.getRule());
Packit 5e46da
            throw new UnsupportedDrawingOperationException("Unsupported composition rule: " + comp.getRule());
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        setComposite(AlphaComposite.getInstance(comp.getRule(), comp.getAlpha()));
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /*
Packit 5e46da
     *
Packit 5e46da
     */
Packit 5e46da
Packit 5e46da
    public void translate(int x, int y) {
Packit 5e46da
        originX += x;
Packit 5e46da
        originY += y;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void setFont(Font font) {
Packit 5e46da
        if (font != null && !font.equals(this.font)) {
Packit 5e46da
            this.font = font;
Packit 5e46da
            fontMetrics = null;
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public Font getFont() {
Packit 5e46da
        if (font == null)
Packit 5e46da
            return DEFAULT_FONT;
Packit 5e46da
        return font;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public FontMetrics getFontMetrics() {
Packit 5e46da
        if (font != null && fontMetrics == null) {
Packit 5e46da
            fontMetrics = BDFontMetrics.getFontMetrics(font);
Packit 5e46da
        }
Packit 5e46da
        if (fontMetrics == null) {
Packit 5e46da
            logger.error("getFontMetrics() failed");
Packit 5e46da
        }
Packit 5e46da
        return fontMetrics;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public FontMetrics getFontMetrics(Font font) {
Packit 5e46da
        if (font != null) {
Packit 5e46da
            return BDFontMetrics.getFontMetrics(font);
Packit 5e46da
        }
Packit 5e46da
        logger.error("getFontMetrics(null) from " + Logger.dumpStack());
Packit 5e46da
        return null;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void setColor(Color c) {
Packit 5e46da
        if ((c != null) && (c != foreground))
Packit 5e46da
            foreground = c;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public Color getColor() {
Packit 5e46da
        return foreground;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public Composite getComposite() {
Packit 5e46da
        return composite;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public GraphicsConfiguration getDeviceConfiguration() {
Packit 5e46da
        if (gc == null)
Packit 5e46da
            logger.error("getDeviceConfiguration() failed");
Packit 5e46da
        return gc;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void setComposite(Composite comp) {
Packit 5e46da
        if ((comp != null) && (comp != composite)) {
Packit 5e46da
            if (!(comp instanceof AlphaComposite)) {
Packit 5e46da
                logger.error("Composite is not AlphaComposite");
Packit 5e46da
                throw new IllegalArgumentException("Only AlphaComposite is supported");
Packit 5e46da
            }
Packit 5e46da
            composite = (AlphaComposite) comp;
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void setPaintMode() {
Packit 5e46da
        xorColor = null;
Packit 5e46da
        composite = AlphaComposite.SrcOver;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void setXORMode(Color color) {
Packit 5e46da
        xorColor = color;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Gets the current clipping area. */
Packit 5e46da
    public Rectangle getClipBounds() {
Packit 5e46da
        if (clip != null)
Packit 5e46da
            return new Rectangle (clip.x - originX, clip.y - originY, clip.width, clip.height);
Packit 5e46da
        return null;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void constrain(int x, int y, int w, int h) {
Packit 5e46da
        Rectangle rect;
Packit 5e46da
        if (constrainedRect != null)
Packit 5e46da
            rect = constrainedRect;
Packit 5e46da
        else
Packit 5e46da
            rect = new Rectangle(0, 0, width, height);
Packit 5e46da
        constrainedRect = rect.intersection(new Rectangle(rect.x + x, rect.y + y, w, h));
Packit 5e46da
        originX = constrainedRect.x;
Packit 5e46da
        originY = constrainedRect.y;
Packit 5e46da
        setupClip();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Returns a Shape object representing the clip. */
Packit 5e46da
    public Shape getClip() {
Packit 5e46da
        return getClipBounds();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Crops the clipping rectangle. */
Packit 5e46da
    public void clipRect(int x, int y, int w, int h) {
Packit 5e46da
        Rectangle rect = new Rectangle(x + originX, y + originY, w, h);
Packit 5e46da
        if (clip != null)
Packit 5e46da
            clip = clip.intersection(rect);
Packit 5e46da
        else
Packit 5e46da
            clip = rect;
Packit 5e46da
        setupClip();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Sets the clipping rectangle. */
Packit 5e46da
    public void setClip(int x, int y, int w, int h) {
Packit 5e46da
        clip = new Rectangle (x + originX, y + originY, w, h);
Packit 5e46da
        setupClip();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Sets the clip to a Shape (only Rectangle allowed). */
Packit 5e46da
    public void setClip(Shape clip) {
Packit 5e46da
        if (clip == null) {
Packit 5e46da
            this.clip = null;
Packit 5e46da
            setupClip();
Packit 5e46da
        } else if (clip instanceof Rectangle) {
Packit 5e46da
            Rectangle rect = (Rectangle) clip;
Packit 5e46da
            setClip(rect.x, rect.y, rect.width, rect.height);
Packit 5e46da
        } else {
Packit 5e46da
            logger.error("Shape is not Rectangle: " + clip.getClass().getName());
Packit 5e46da
            throw new IllegalArgumentException("setClip(Shape) only supports Rectangle objects");
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void setupClip() {
Packit 5e46da
        Rectangle rect;
Packit 5e46da
        if (constrainedRect != null)
Packit 5e46da
            rect = constrainedRect;
Packit 5e46da
        else
Packit 5e46da
            rect = new Rectangle(0, 0, width, height);
Packit 5e46da
        if (clip != null)
Packit 5e46da
            actualClip = clip.intersection(rect);
Packit 5e46da
        else
Packit 5e46da
            actualClip = rect;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private int alphaBlend(int dest, int src) {
Packit 5e46da
        int As = src >>> 24;
Packit 5e46da
        if (As == 0)
Packit 5e46da
            return dest;
Packit 5e46da
        if (As == 255)
Packit 5e46da
            return src;
Packit 5e46da
        int Ad = (dest >>> 24);
Packit 5e46da
        if (Ad == 0)
Packit 5e46da
            return src;
Packit 5e46da
        int R, G, B;
Packit 5e46da
        R = ((src >>> 16) & 255) * As * 255;
Packit 5e46da
        G = ((src >>> 8) & 255) * As * 255;
Packit 5e46da
        B = (src & 255) * As * 255;
Packit 5e46da
        Ad = Ad * (255 - As);
Packit 5e46da
        As = As * 255 + Ad;
Packit 5e46da
        R = (R + ((dest >>> 16) & 255) * Ad) / As;
Packit 5e46da
        G = (G + ((dest >>> 8) & 255) * Ad) / As;
Packit 5e46da
        B = (B + (dest & 255) * Ad) / As;
Packit 5e46da
        R = Math.min(255, R);
Packit 5e46da
        G = Math.min(255, G);
Packit 5e46da
        B = Math.min(255, B);
Packit 5e46da
        Ad = As / 255;
Packit 5e46da
        Ad = Math.min(255, Ad);
Packit 5e46da
        return (Ad << 24) | (R << 16) | (G << 8) | B;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private int applyComposite(int rgb) {
Packit 5e46da
        return ((int)((rgb >>> 24) * composite.getAlpha()) << 24) | (rgb & 0x00FFFFFF);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void drawSpanN(int x, int y, int length, int rgb) {
Packit 5e46da
Packit 5e46da
        Rectangle rect = new Rectangle(x, y, length, 1);
Packit 5e46da
        rect = actualClip.intersection(rect);
Packit 5e46da
Packit 5e46da
        if (rect.width <= 0 || rect.height <= 0 || rect.x < 0 || rect.y < 0 || backBuffer == null) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        x      = rect.x;
Packit 5e46da
        length = rect.width;
Packit 5e46da
Packit 5e46da
        if (xorColor != null) {
Packit 5e46da
            for (int i = 0; i < length; i++) {
Packit 5e46da
                backBuffer[y * width + x + i] ^= xorColor.getRGB() ^ rgb;
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            dirty.add(rect);
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        switch (composite.getRule()) {
Packit 5e46da
            case AlphaComposite.CLEAR:
Packit 5e46da
                for (int i = 0; i < length; i++) {
Packit 5e46da
                    backBuffer[y * width + x + i] = 0;
Packit 5e46da
                }
Packit 5e46da
                break;
Packit 5e46da
            case AlphaComposite.SRC:
Packit 5e46da
                rgb = applyComposite(rgb);
Packit 5e46da
                for (int i = 0; i < length; i++) {
Packit 5e46da
                    backBuffer[y * width + x + i] = rgb;
Packit 5e46da
                }
Packit 5e46da
                break;
Packit 5e46da
            case AlphaComposite.SRC_OVER:
Packit 5e46da
                rgb = applyComposite(rgb);
Packit 5e46da
                for (int i = 0; i < length; i++) {
Packit 5e46da
                    backBuffer[y * width + x + i] = alphaBlend(backBuffer[y * width + x + i], rgb);
Packit 5e46da
                }
Packit 5e46da
                break;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        dirty.add(rect);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void drawSpanN(int x, int y, int length, int src[], int srcOffset, boolean flipX) {
Packit 5e46da
Packit 5e46da
        /* avoid overreading source */
Packit 5e46da
        if (srcOffset + length > src.length) {
Packit 5e46da
            length -= srcOffset + length - src.length;
Packit 5e46da
        }
Packit 5e46da
        /* avoid underreading source */
Packit 5e46da
        if (srcOffset < 0) {
Packit 5e46da
            length += srcOffset;
Packit 5e46da
            x -= srcOffset;
Packit 5e46da
            srcOffset = 0;
Packit 5e46da
        }
Packit 5e46da
        if (length <= 0) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        Rectangle rect = new Rectangle(x, y, length, 1);
Packit 5e46da
        rect = actualClip.intersection(rect);
Packit 5e46da
Packit 5e46da
        if (rect.width <= 0 || rect.height <= 0 || rect.x < 0 || rect.y < 0 || backBuffer == null) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        int dstOffset;
Packit 5e46da
Packit 5e46da
        srcOffset += rect.x - x;
Packit 5e46da
        x          = rect.x;
Packit 5e46da
        length     = rect.width;
Packit 5e46da
        dstOffset  = y * width + x;
Packit 5e46da
Packit 5e46da
        if (xorColor != null) {
Packit 5e46da
Packit 5e46da
            if (flipX) {
Packit 5e46da
                for (int i = 0; i < length; i++) {
Packit 5e46da
                    backBuffer[dstOffset + length -1 - i] ^= xorColor.getRGB() ^ src[srcOffset + i];
Packit 5e46da
                }
Packit 5e46da
            } else {
Packit 5e46da
                for (int i = 0; i < length; i++) {
Packit 5e46da
                    backBuffer[dstOffset + i] ^= xorColor.getRGB() ^ src[srcOffset + i];
Packit 5e46da
                }
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            dirty.add(rect);
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        switch (composite.getRule()) {
Packit 5e46da
            case AlphaComposite.CLEAR:
Packit 5e46da
                for (int i = 0; i < length; i++) {
Packit 5e46da
                    backBuffer[dstOffset + i] = 0;
Packit 5e46da
                }
Packit 5e46da
                break;
Packit 5e46da
            case AlphaComposite.SRC:
Packit 5e46da
                if (flipX) {
Packit 5e46da
                    for (int i = 0; i < length; i++) {
Packit 5e46da
                        backBuffer[dstOffset + length -1 - i] = applyComposite(src[srcOffset + i]);
Packit 5e46da
                    }
Packit 5e46da
                } else {
Packit 5e46da
                    for (int i = 0; i < length; i++) {
Packit 5e46da
                        backBuffer[dstOffset + i] = applyComposite(src[srcOffset + i]);
Packit 5e46da
                    }
Packit 5e46da
                }
Packit 5e46da
                break;
Packit 5e46da
            case AlphaComposite.SRC_OVER:
Packit 5e46da
                if (flipX) {
Packit 5e46da
                    for (int i = 0; i < length; i++) {
Packit 5e46da
                        backBuffer[dstOffset + length -1 - i] = alphaBlend(backBuffer[dstOffset + length -1 - i], applyComposite(src[srcOffset + i]));
Packit 5e46da
                    }
Packit 5e46da
                } else {
Packit 5e46da
                    for (int i = 0; i < length; i++) {
Packit 5e46da
                        backBuffer[dstOffset + i] = alphaBlend(backBuffer[dstOffset + i], applyComposite(src[srcOffset + i]));
Packit 5e46da
                    }
Packit 5e46da
                }
Packit 5e46da
                break;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        dirty.add(rect);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void drawSpan(int x, int y, int length, int rgb) {
Packit 5e46da
        x += originX;
Packit 5e46da
        y += originY;
Packit 5e46da
        drawSpanN(x, y, length, rgb);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void drawSpan(int x, int y, int length, int src[], int srcOffset, boolean flipX) {
Packit 5e46da
        x += originX;
Packit 5e46da
        y += originY;
Packit 5e46da
        drawSpanN(x, y, length, src, srcOffset, flipX);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void drawPointN(int x, int y, int rgb) {
Packit 5e46da
        drawSpanN(x, y, 1, rgb);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void drawGlyph(int[] rgbArray, int x0, int y0, int w, int h) {
Packit 5e46da
        for (int y = 0; y < h; y++)
Packit 5e46da
            for (int x = 0; x < w; x++)
Packit 5e46da
                drawPoint(x + x0, y + y0, rgbArray[y * w + x]);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void drawPoint(int x, int y, int rgb) {
Packit 5e46da
        x += originX;
Packit 5e46da
        y += originY;
Packit 5e46da
        if (actualClip.contains(x, y))
Packit 5e46da
            drawPointN(x, y, rgb);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void clearRect(int x, int y, int w, int h) {
Packit 5e46da
        x += originX;
Packit 5e46da
        y += originY;
Packit 5e46da
        Rectangle rect = new Rectangle(x, y, w, h);
Packit 5e46da
        rect = actualClip.intersection(rect);
Packit 5e46da
        if (rect.isEmpty() || backBuffer == null) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
        x = rect.x;
Packit 5e46da
        y = rect.y;
Packit 5e46da
        w = rect.width;
Packit 5e46da
        h = rect.height;
Packit 5e46da
        int rgb = background.getRGB();
Packit 5e46da
        for (int i = 0; i < h; i++)
Packit 5e46da
            Arrays.fill(backBuffer, (y + i) * width + x, (y + i) * width + x + w, rgb);
Packit 5e46da
Packit 5e46da
        dirty.add(rect);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void fillRect(int x, int y, int w, int h) {
Packit 5e46da
        x += originX;
Packit 5e46da
        y += originY;
Packit 5e46da
        Rectangle rect = new Rectangle(x, y, w, h);
Packit 5e46da
        rect = actualClip.intersection(rect);
Packit 5e46da
        x = rect.x;
Packit 5e46da
        y = rect.y;
Packit 5e46da
        w = rect.width;
Packit 5e46da
        h = rect.height;
Packit 5e46da
        int rgb = foreground.getRGB();
Packit 5e46da
        for (int Y = y; Y < (y + h); Y++)
Packit 5e46da
            drawSpanN(x, Y, w, rgb);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void drawRect(int x, int y, int w, int h) {
Packit 5e46da
        x += originX;
Packit 5e46da
        y += originY;
Packit 5e46da
Packit 5e46da
        drawLineN(x, y, x + w, y);
Packit 5e46da
        drawLineN(x, y + h, x + w, y + h);
Packit 5e46da
        drawLineN(x, y, x, y + h);
Packit 5e46da
        drawLineN(x + w, y, x + w, y + h);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void drawLineN(int x1, int y1, int x2, int y2) {
Packit 5e46da
        int rgb = foreground.getRGB();
Packit 5e46da
        int dy = y2 - y1;
Packit 5e46da
        int dx = x2 - x1;
Packit 5e46da
        int stepx, stepy;
Packit 5e46da
        int fraction;
Packit 5e46da
        if (dy < 0) {
Packit 5e46da
            dy = -dy;
Packit 5e46da
            stepy = -1;
Packit 5e46da
        } else {
Packit 5e46da
            stepy = 1;
Packit 5e46da
        }
Packit 5e46da
        if (dx < 0) {
Packit 5e46da
            dx = -dx;
Packit 5e46da
            stepx = -1;
Packit 5e46da
        } else {
Packit 5e46da
            stepx = 1;
Packit 5e46da
        }
Packit 5e46da
        dy <<= 1;
Packit 5e46da
        dx <<= 1;
Packit 5e46da
Packit 5e46da
        drawPointN(x1, y1, rgb);
Packit 5e46da
Packit 5e46da
        if (dx > dy) {
Packit 5e46da
            fraction = dy - (dx >> 1);
Packit 5e46da
            while (x1 != x2) {
Packit 5e46da
                if (fraction >= 0) {
Packit 5e46da
                    y1 += stepy;
Packit 5e46da
                    fraction -= dx;
Packit 5e46da
                }
Packit 5e46da
                x1 += stepx;
Packit 5e46da
                fraction += dy;
Packit 5e46da
                drawPointN(x1, y1, rgb);
Packit 5e46da
            }
Packit 5e46da
        } else {
Packit 5e46da
            fraction = dx - (dy >> 1);
Packit 5e46da
            while (y1 != y2) {
Packit 5e46da
                if (fraction >= 0) {
Packit 5e46da
                    x1 += stepx;
Packit 5e46da
                    fraction -= dy;
Packit 5e46da
                }
Packit 5e46da
                y1 += stepy;
Packit 5e46da
                fraction += dx;
Packit 5e46da
                drawPointN(x1, y1, rgb);
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void drawLine(int x1, int y1, int x2, int y2) {
Packit 5e46da
Packit 5e46da
        x1 += originX;
Packit 5e46da
        y1 += originY;
Packit 5e46da
Packit 5e46da
        x2 += originX;
Packit 5e46da
        y2 += originY;
Packit 5e46da
Packit 5e46da
        drawLineN(x1, y1, x2, y2);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Copies an area of the canvas that this graphics context paints to.
Packit 5e46da
     * @param X the x-coordinate of the source.
Packit 5e46da
     * @param Y the y-coordinate of the source.
Packit 5e46da
     * @param W the width.
Packit 5e46da
     * @param H the height.
Packit 5e46da
     * @param dx the horizontal distance to copy the pixels.
Packit 5e46da
     * @param dy the vertical distance to copy the pixels.
Packit 5e46da
     */
Packit 5e46da
    public void copyArea(int x, int y, int w, int h, int dx, int dy) {
Packit 5e46da
Packit 5e46da
        x += originX;
Packit 5e46da
        y += originY;
Packit 5e46da
Packit 5e46da
        Rectangle rect = new Rectangle(x, y, w, h);
Packit 5e46da
        rect = actualClip.intersection(rect);
Packit 5e46da
Packit 5e46da
        if (rect.width <= 0 || rect.height <= 0 || backBuffer == null) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        x = rect.x;
Packit 5e46da
        y = rect.y;
Packit 5e46da
        w = rect.width;
Packit 5e46da
        h = rect.height;
Packit 5e46da
Packit 5e46da
        int subImage[] = new int[w * h];
Packit 5e46da
Packit 5e46da
        // copy back buffer
Packit 5e46da
        for (int i = 0; i < h; i++) {
Packit 5e46da
            System.arraycopy(backBuffer, ((y + i) * width) + x, subImage, w * i, w);
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // draw sub image
Packit 5e46da
        for (int i = 0; i < h; i++) {
Packit 5e46da
            drawSpanN(x + dx, y + i + dy, w, subImage, w * i, false);
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Draws lines defined by an array of x points and y points */
Packit 5e46da
    public void drawPolyline(int xPoints[], int yPoints[], int nPoints) {
Packit 5e46da
        if (nPoints == 1) {
Packit 5e46da
            drawPoint(xPoints[0], yPoints[0], foreground.getRGB());
Packit 5e46da
        } else {
Packit 5e46da
            for (int i = 0; i < (nPoints - 1); i++)
Packit 5e46da
                drawLine(xPoints[i], xPoints[i], xPoints[i + 1], xPoints[i + 1]);
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Draws a polygon defined by an array of x points and y points */
Packit 5e46da
    public void drawPolygon(int xPoints[], int yPoints[], int nPoints) {
Packit 5e46da
        if (nPoints == 1) {
Packit 5e46da
            drawPoint(xPoints[0], yPoints[0], foreground.getRGB());
Packit 5e46da
        } else {
Packit 5e46da
            for (int i = 0; i < (nPoints - 1); i++)
Packit 5e46da
                drawLine(xPoints[i], xPoints[i], xPoints[i + 1], xPoints[i + 1]);
Packit 5e46da
            if (nPoints > 2)
Packit 5e46da
                drawLine(xPoints[0], xPoints[0], xPoints[nPoints - 1], xPoints[nPoints - 1]);
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Fills a polygon with the current fill mask */
Packit 5e46da
    public void fillPolygon(int xPoints[], int yPoints[], int nPoints) {
Packit 5e46da
Packit 5e46da
        int minY = Integer.MAX_VALUE;
Packit 5e46da
        int maxY = Integer.MIN_VALUE;
Packit 5e46da
        int colour = foreground.getRGB();
Packit 5e46da
Packit 5e46da
        if (nPoints < 3) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        for (int i = 0; i < nPoints; i++) {
Packit 5e46da
            if (yPoints[i] > maxY) {
Packit 5e46da
                maxY = yPoints[i];
Packit 5e46da
            }
Packit 5e46da
            if (yPoints[i] < minY) {
Packit 5e46da
                minY = yPoints[i];
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // check the last point to see if its the same as the first
Packit 5e46da
        if (xPoints[0] == xPoints[nPoints - 1] && yPoints[0] == yPoints[nPoints - 1]) {
Packit 5e46da
            nPoints--;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        PolyEdge[] polyEdges = new PolyEdge[nPoints];
Packit 5e46da
Packit 5e46da
        for (int i = 0; i < nPoints - 1; i++) {
Packit 5e46da
            polyEdges[i] = new PolyEdge(xPoints[i], yPoints[i], xPoints[i + 1], yPoints[i + 1]);
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // add the last one
Packit 5e46da
        polyEdges[nPoints - 1] = new PolyEdge(xPoints[nPoints - 1], yPoints[nPoints - 1], xPoints[0], yPoints[0]);
Packit 5e46da
        ArrayList xList = new ArrayList();
Packit 5e46da
        for (int i = minY; i <= maxY; i++) {
Packit 5e46da
            for (int j = 0; j < nPoints; j++) {
Packit 5e46da
                if (polyEdges[j].intersects(i)) {
Packit 5e46da
                    int x = polyEdges[j].intersectionX(i);
Packit 5e46da
                    xList.add(new Integer(x));
Packit 5e46da
                }
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            // probably a better way of doing this (removing duplicates);
Packit 5e46da
            HashSet hs = new HashSet();
Packit 5e46da
            hs.addAll(xList);
Packit 5e46da
            xList.clear();
Packit 5e46da
            xList.addAll(hs);
Packit 5e46da
Packit 5e46da
            if (xList.size() % 2 > 0) {
Packit 5e46da
                xList.clear();
Packit 5e46da
                continue;                       // this should be impossible unless the poly is open somewhere
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            Collections.sort(xList);
Packit 5e46da
Packit 5e46da
            for (int j = 0; j < xList.size(); j +=2 ) {
Packit 5e46da
                int x1 = ((Integer)xList.get(j)).intValue();
Packit 5e46da
                int x2 = ((Integer)xList.get(j + 1)).intValue();
Packit 5e46da
Packit 5e46da
                drawSpan(x1, i, x2 - x1, colour);
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            xList.clear();
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Draws an oval to fit in the given rectangle */
Packit 5e46da
    public void drawOval(int x, int y, int w, int h) {
Packit 5e46da
Packit 5e46da
        int     startX;
Packit 5e46da
        int     endX;
Packit 5e46da
        int     offset;
Packit 5e46da
        int[]   xList;
Packit 5e46da
        int[]   yList;
Packit 5e46da
        int     numPoints;
Packit 5e46da
        int     count;
Packit 5e46da
        float   as;
Packit 5e46da
        float   bs;
Packit 5e46da
Packit 5e46da
        if (w <= 0 || h <=0 ) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        count = 0;
Packit 5e46da
        numPoints = ((h/2) + (h/2) + 1) * 2;
Packit 5e46da
        numPoints += 1; // to close
Packit 5e46da
        xList = new int[numPoints];
Packit 5e46da
        yList = new int[numPoints];
Packit 5e46da
Packit 5e46da
        as = (w/2.0f) * (w/2.0f);
Packit 5e46da
        bs = (h/2.0f) * (h/2.0f);
Packit 5e46da
Packit 5e46da
        for (int i = -h/2; i <= h/2; i++) {
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - ((i*i)/bs)) * as );
Packit 5e46da
            startX  = x - offset + w/2;
Packit 5e46da
Packit 5e46da
            xList[count] = startX;
Packit 5e46da
            yList[count] = y + i + h/2;
Packit 5e46da
            count++;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        for (int i = h/2; i >= -h/2; i--) {
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - ((i*i)/bs)) * as );
Packit 5e46da
            endX    = x + offset + w/2;
Packit 5e46da
Packit 5e46da
            xList[count] = endX;
Packit 5e46da
            yList[count] = y + i + h/2;
Packit 5e46da
            count++;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        xList[count] = xList[0];        // close the loop
Packit 5e46da
        yList[count] = yList[0];        // close the loop
Packit 5e46da
Packit 5e46da
        drawPolyline(xList, yList, numPoints);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Fills an oval to fit in the given rectangle */
Packit 5e46da
    public void fillOval(int x, int y, int w, int h) {
Packit 5e46da
Packit 5e46da
        int     startX;
Packit 5e46da
        int     endX;
Packit 5e46da
        int     offset;
Packit 5e46da
        int     colour;
Packit 5e46da
        float   as;
Packit 5e46da
        float   bs;
Packit 5e46da
Packit 5e46da
        if (w <= 0 || h <= 0) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        as = (w/2.0f) * (w/2.0f);
Packit 5e46da
        bs = (h/2.0f) * (h/2.0f);
Packit 5e46da
        colour = foreground.getRGB();
Packit 5e46da
Packit 5e46da
        for(int i=-h/2; i<=h/2; i++) {
Packit 5e46da
            offset  = (int) Math.sqrt( (1.0 - ((i*i)/bs)) * as );
Packit 5e46da
            startX  = x - offset + w/2;
Packit 5e46da
            endX    = x + offset + w/2;
Packit 5e46da
Packit 5e46da
            drawSpan(startX, y + i + h/2, endX - startX + 1, colour);
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private int getAngle(int centreX, int centreY, int pointX, int pointY) {
Packit 5e46da
Packit 5e46da
        float  vStartX;
Packit 5e46da
        float  vStartY;
Packit 5e46da
        float  vEndX;
Packit 5e46da
        float  vEndY;
Packit 5e46da
        float  length;
Packit 5e46da
        double angle;
Packit 5e46da
Packit 5e46da
        vStartX = 1;    // vector pointing right (this is where angle starts for arcs)
Packit 5e46da
        vStartY = 0;
Packit 5e46da
Packit 5e46da
        vEndX = pointX - centreX;
Packit 5e46da
        vEndY = pointY - centreY;
Packit 5e46da
Packit 5e46da
        length = (float) Math.sqrt(vEndX*vEndX + vEndY*vEndY);
Packit 5e46da
Packit 5e46da
        vEndX /= length;
Packit 5e46da
        vEndY /= length;
Packit 5e46da
Packit 5e46da
        angle = Math.acos(vStartX*vEndX + vStartY*vEndY);
Packit 5e46da
        angle = angle * 180.0 / Math.PI;
Packit 5e46da
Packit 5e46da
        if (vEndY > 0) {
Packit 5e46da
            angle = 360 - angle;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        return (int)(angle + 0.5);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private void drawArcI(boolean fill, int x, int y, int width, int height, int startAngle, int arcAngle) {
Packit 5e46da
Packit 5e46da
        int     endAngle;
Packit 5e46da
        int     startX;
Packit 5e46da
        int     endX;
Packit 5e46da
        int     offset;
Packit 5e46da
        int[]   xList;
Packit 5e46da
        int[]   yList;
Packit 5e46da
        int     count;
Packit 5e46da
        int     numPoints;
Packit 5e46da
        int     tempX;
Packit 5e46da
        int     tempY;
Packit 5e46da
        int     angle;
Packit 5e46da
        int     widthDiv2;
Packit 5e46da
        int     heightDiv2;
Packit 5e46da
        float   as;
Packit 5e46da
        float   bs;
Packit 5e46da
        boolean addedZero;
Packit 5e46da
        boolean circle;
Packit 5e46da
Packit 5e46da
        // sanity checks
Packit 5e46da
        if (width <= 0 || height <= 0 || arcAngle == 0) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // init variables
Packit 5e46da
        count           = 0;
Packit 5e46da
        addedZero       = false;
Packit 5e46da
        circle          = false;
Packit 5e46da
        widthDiv2       = (int)(width/2.0f + 0.5f);
Packit 5e46da
        heightDiv2      = (int)(height/2.0f + 0.5f);
Packit 5e46da
        numPoints       = ((height + 1/2) + (height + 1/2) + 1) * 2 + 1;
Packit 5e46da
        xList           = new int[numPoints];
Packit 5e46da
        yList           = new int[numPoints];
Packit 5e46da
Packit 5e46da
        as = (width/2.0f)  * (width/2.0f);
Packit 5e46da
        bs = (height/2.0f) * (height/2.0f);
Packit 5e46da
Packit 5e46da
        // check if we actually want to draw a circle
Packit 5e46da
        if (Math.abs(arcAngle) >= 360) {
Packit 5e46da
            circle = true;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (startAngle < 0) {
Packit 5e46da
            startAngle %= 360;
Packit 5e46da
            startAngle = Math.abs(startAngle);
Packit 5e46da
            startAngle = 360 - startAngle;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (arcAngle < 0) {
Packit 5e46da
            int temp;
Packit 5e46da
            temp = startAngle;
Packit 5e46da
            endAngle = startAngle;
Packit 5e46da
            startAngle = 360 + arcAngle + temp;
Packit 5e46da
        } else {
Packit 5e46da
            endAngle = startAngle + arcAngle;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        startAngle %= 360;
Packit 5e46da
        endAngle   %= 360;
Packit 5e46da
Packit 5e46da
        for (int i = heightDiv2; i >= -heightDiv2; i--) {
Packit 5e46da
            boolean hit = false;
Packit 5e46da
            int offsetAngle;
Packit 5e46da
            int startXAngle;
Packit 5e46da
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - i*i/bs) * as );
Packit 5e46da
            startX = x + offset + widthDiv2;
Packit 5e46da
Packit 5e46da
            offsetAngle = (int) Math.sqrt( (1.0 - i*i/bs) * bs );       // we calculate these as if it were a circle
Packit 5e46da
            startXAngle = x + offsetAngle + height/2;
Packit 5e46da
Packit 5e46da
            tempX = startX;
Packit 5e46da
            tempY = y + i + height/2;
Packit 5e46da
Packit 5e46da
            angle = getAngle(x + height/2, y + height/2, startXAngle, tempY);
Packit 5e46da
Packit 5e46da
            if (startAngle < endAngle) {
Packit 5e46da
                if (angle < endAngle && angle >= startAngle) {
Packit 5e46da
                    xList[count] = tempX;
Packit 5e46da
                    yList[count] = tempY;
Packit 5e46da
                    count++;
Packit 5e46da
                    hit = true;
Packit 5e46da
                }
Packit 5e46da
            } else {
Packit 5e46da
                if (!(angle > endAngle && angle < startAngle)) {
Packit 5e46da
                    xList[count] = tempX;
Packit 5e46da
                    yList[count] = tempY;
Packit 5e46da
                    count++;
Packit 5e46da
                    hit = true;
Packit 5e46da
                }
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            if (!hit && !addedZero && !circle && fill) {
Packit 5e46da
                xList[count] = x + width/2;
Packit 5e46da
                yList[count] = y + height/2;
Packit 5e46da
                count++;
Packit 5e46da
                addedZero = true;
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            if (!hit && !fill && !circle && count > 1) {
Packit 5e46da
                drawPolyline(xList, yList, count);
Packit 5e46da
                count = 0;
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
Packit 5e46da
        for (int i = -heightDiv2; i <= heightDiv2; i++) {
Packit 5e46da
            boolean hit = false;
Packit 5e46da
            int offsetAngle;
Packit 5e46da
            int endXAngle;
Packit 5e46da
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - i*i/bs) * as );
Packit 5e46da
            endX   = x - offset + width/2;
Packit 5e46da
Packit 5e46da
            offsetAngle = (int) Math.sqrt( (1.0 - i*i/bs) * bs );   // we calculate these as if it were a circle
Packit 5e46da
            endXAngle   = x - offsetAngle + height/2;
Packit 5e46da
Packit 5e46da
            tempX = endX;
Packit 5e46da
            tempY = y + i + height/2;
Packit 5e46da
Packit 5e46da
            angle = getAngle(x + height/2, y + height/2, endXAngle, tempY);
Packit 5e46da
Packit 5e46da
            if (startAngle < endAngle) {
Packit 5e46da
                if (angle <= endAngle && angle >= startAngle) {
Packit 5e46da
                    xList[count] = tempX;
Packit 5e46da
                    yList[count] = tempY;
Packit 5e46da
                    count++;
Packit 5e46da
                    hit = true;
Packit 5e46da
                }
Packit 5e46da
            } else {
Packit 5e46da
                if (!(angle > endAngle && angle < startAngle)) {
Packit 5e46da
                    xList[count] = tempX;
Packit 5e46da
                    yList[count] = tempY;
Packit 5e46da
                    count++;
Packit 5e46da
                    hit = true;
Packit 5e46da
                }
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            if (!hit && !addedZero && !circle && fill) {
Packit 5e46da
                xList[count] = x + width/2;
Packit 5e46da
                yList[count] = y + height/2;
Packit 5e46da
                count++;
Packit 5e46da
                addedZero = true;
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            if (!hit && !fill && !circle && count > 1) {
Packit 5e46da
                drawPolyline(xList, yList, count);
Packit 5e46da
                count = 0;
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (fill) {
Packit 5e46da
            fillPolygon(xList, yList, count);
Packit 5e46da
        } else {
Packit 5e46da
            if (circle) {
Packit 5e46da
                drawPolygon(xList, yList, count);   // we need to connect start to end in the case of 360
Packit 5e46da
            } else {
Packit 5e46da
                drawPolyline(xList, yList, count);  // shape must be open so no connection
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Draws an arc bounded by the given rectangle from startAngle to
Packit 5e46da
     * endAngle. 0 degrees is a vertical line straight up from the
Packit 5e46da
     * center of the rectangle. Positive start angle indicate clockwise
Packit 5e46da
     * rotations, negative angle are counter-clockwise.
Packit 5e46da
     */
Packit 5e46da
    public void drawArc(int x, int y, int w, int h, int startAngle, int endAngle) {
Packit 5e46da
        drawArcI(false, x, y, w, h, startAngle, endAngle);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** fills an arc. arguments are the same as drawArc. */
Packit 5e46da
    public void fillArc(int x, int y, int w, int h, int startAngle, int endAngle) {
Packit 5e46da
        drawArcI(true, x, y, w, h, startAngle, endAngle);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Draws a rounded rectangle. */
Packit 5e46da
    public void drawRoundRect(int x, int y, int w, int h, int arcWidth, int arcHeight) {
Packit 5e46da
Packit 5e46da
        int[]   xList;
Packit 5e46da
        int[]   yList;
Packit 5e46da
        int     numPoints;
Packit 5e46da
        int     count;
Packit 5e46da
        int     startX;
Packit 5e46da
        int     endX;
Packit 5e46da
        int     offset;
Packit 5e46da
Packit 5e46da
        if (w <= 0 || h <= 0) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (arcWidth == 0 || arcHeight == 0) {
Packit 5e46da
            drawRect(x, y, w, h);
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (arcWidth < 0) {                // matches behaviour of normal java version
Packit 5e46da
            arcWidth *= -1;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (arcHeight < 0) {
Packit 5e46da
            arcHeight *= -1;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        count = 0;
Packit 5e46da
        numPoints = ((arcHeight/2) + 1) * 2;
Packit 5e46da
        numPoints += ((arcHeight/2) + 1) * 2;
Packit 5e46da
        numPoints += 1; // last point to close the loop
Packit 5e46da
Packit 5e46da
        xList = new int[numPoints];
Packit 5e46da
        yList = new int[numPoints];
Packit 5e46da
Packit 5e46da
        float as = (arcWidth/2.0f)  * (arcWidth/2.0f);
Packit 5e46da
        float bs = (arcHeight/2.0f) * (arcHeight/2.0f);
Packit 5e46da
Packit 5e46da
        // draw top curved half of box
Packit 5e46da
Packit 5e46da
        for (int i = 0; -arcHeight/2 <= i; i--) {
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - ((i*i)/bs)) * as );
Packit 5e46da
            startX  = x - offset + arcWidth/2;
Packit 5e46da
Packit 5e46da
            xList[count] = startX;
Packit 5e46da
            yList[count] = y+i+(arcHeight/2);
Packit 5e46da
            count++;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        for (int i = -arcHeight / 2; i <= 0; i++) {
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - ((i*i)/bs)) * as );
Packit 5e46da
            endX    = x + offset + (w-arcWidth) + arcWidth/2;
Packit 5e46da
Packit 5e46da
            xList[count] = endX;
Packit 5e46da
            yList[count] = y + i + (arcHeight/2);
Packit 5e46da
            count++;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // draw bottom box
Packit 5e46da
        for (int i = 0; i <= arcHeight / 2; i++) {
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - ((i*i)/bs)) * as );
Packit 5e46da
            startX  = x - offset + arcWidth/2;
Packit 5e46da
            endX    = x + offset + (w - arcWidth) + arcWidth/2;
Packit 5e46da
Packit 5e46da
            xList[count] = endX;
Packit 5e46da
            yList[count] = y + i + h - arcHeight/2;
Packit 5e46da
            count++;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // draw bottom box
Packit 5e46da
        for (int i = arcHeight / 2; i >= 0; i--) {
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - ((i*i)/bs)) * as );
Packit 5e46da
            startX  = x - offset + arcWidth/2;
Packit 5e46da
            endX    = x + offset + (w-arcWidth) + arcWidth/2;
Packit 5e46da
Packit 5e46da
            xList[count] = startX;
Packit 5e46da
            yList[count] = y+i+h-arcHeight/2;
Packit 5e46da
            count++;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        xList[count] = xList[0];
Packit 5e46da
        yList[count] = yList[0];
Packit 5e46da
Packit 5e46da
        drawPolyline(xList, yList, numPoints);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Draws a filled rounded rectangle. */
Packit 5e46da
    public void fillRoundRect(int x, int y, int w, int h, int arcWidth, int arcHeight) {
Packit 5e46da
Packit 5e46da
        int startX;
Packit 5e46da
        int endX;
Packit 5e46da
        int offset;
Packit 5e46da
        int colour;
Packit 5e46da
Packit 5e46da
        if (w <= 0 || h <= 0) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (arcWidth == 0 || arcHeight == 0) {
Packit 5e46da
            fillRect(x,y,w,h);
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (arcWidth < 0) {                // matches behaviour of normal java version
Packit 5e46da
            arcWidth *= -1;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (arcHeight < 0) {
Packit 5e46da
            arcHeight *= -1;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        float as = (arcWidth/2.0f)  * (arcWidth/2.0f);
Packit 5e46da
        float bs = (arcHeight/2.0f) * (arcHeight/2.0f);
Packit 5e46da
Packit 5e46da
        colour = foreground.getRGB();
Packit 5e46da
Packit 5e46da
        // draw top curved half of box
Packit 5e46da
        for (int i = -arcHeight/2; i < 0; i++) {
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - ((i*i)/bs)) * as );
Packit 5e46da
            startX  = x - offset + arcWidth/2;
Packit 5e46da
            endX    = x + offset + (w - arcWidth) + arcWidth/2;
Packit 5e46da
Packit 5e46da
            drawSpan(startX, y + i + (arcHeight/2), endX - startX + 1, colour);
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // draw middle section
Packit 5e46da
        for (int i = 0; i < h - arcHeight; i++) {
Packit 5e46da
            drawSpan(x, y + i + arcHeight/2, w, colour);
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // draw bottom box
Packit 5e46da
        for (int i = 0; i <= arcHeight/2; i++) {
Packit 5e46da
            offset = (int) Math.sqrt( (1.0 - ((i*i)/bs)) * as );
Packit 5e46da
            startX  = x - offset + arcWidth/2;
Packit 5e46da
            endX    = x + offset + (w - arcWidth) + arcWidth/2;
Packit 5e46da
Packit 5e46da
            drawSpan(startX, y + i + h - 1 - arcHeight/2, endX - startX + 1, colour);
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    protected native void drawStringN(long ftFace, String string, int x, int y, int rgb);
Packit 5e46da
Packit 5e46da
    /** Draws the given string. */
Packit 5e46da
    public void drawString(String string, int x, int y) {
Packit 5e46da
        getFontMetrics();
Packit 5e46da
        if (fontMetrics != null) {
Packit 5e46da
            fontMetrics.drawString((BDGraphics)this, string, x, y, foreground.getRGB());
Packit 5e46da
        } else {
Packit 5e46da
            logger.error("drawString skipped: no font metrics. string=\"" + string + "\"");
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /** Draws the given character array. */
Packit 5e46da
    public void drawChars(char chars[], int offset, int length, int x, int y) {
Packit 5e46da
        drawString(new String(chars, offset, length), x, y);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void drawString(AttributedCharacterIterator arg0, int arg1, int arg2) {
Packit 5e46da
        logger.unimplemented("drawString");
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Draws an image at x,y in nonblocking mode with a callback object.
Packit 5e46da
     */
Packit 5e46da
    public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
Packit 5e46da
        return drawImage(img, x, y, null, observer);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Draws an image at x,y in nonblocking mode with a solid background
Packit 5e46da
     * color and a callback object.
Packit 5e46da
     */
Packit 5e46da
    public boolean drawImage(Image img, int x, int y, Color bg,
Packit 5e46da
        ImageObserver observer) {
Packit 5e46da
        return drawImageN(img, x, y, -1, -1, 0, 0, -1, -1, false, false, bg, observer);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Draws an image scaled to x,y,w,h in nonblocking mode with a
Packit 5e46da
     * callback object.
Packit 5e46da
     */
Packit 5e46da
    public boolean drawImage(Image img, int x, int y, int w, int h,
Packit 5e46da
        ImageObserver observer) {
Packit 5e46da
        return drawImage(img, x, y, w, h, null, observer);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Draws an image scaled to x,y,w,h in nonblocking mode with a
Packit 5e46da
     * solid background color and a callback object.
Packit 5e46da
     */
Packit 5e46da
    public boolean drawImage(Image img, int x, int y, int w, int h,
Packit 5e46da
        Color bg, ImageObserver observer) {
Packit 5e46da
        return drawImageN(img, x, y, w, h, 0, 0, -1, -1, false, false, bg, observer);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Draws a subrectangle of an image scaled to a destination rectangle
Packit 5e46da
     * in nonblocking mode with a callback object.
Packit 5e46da
     */
Packit 5e46da
    public boolean drawImage(Image img,
Packit 5e46da
        int dx1, int dy1, int dx2, int dy2,
Packit 5e46da
        int sx1, int sy1, int sx2, int sy2,
Packit 5e46da
        ImageObserver observer) {
Packit 5e46da
        return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Draws a subrectangle of an image scaled to a destination rectangle in
Packit 5e46da
     * nonblocking mode with a solid background color and a callback object.
Packit 5e46da
     */
Packit 5e46da
    public boolean drawImage(Image img,
Packit 5e46da
        int dx1, int dy1, int dx2, int dy2,
Packit 5e46da
        int sx1, int sy1, int sx2, int sy2,
Packit 5e46da
        Color bg, ImageObserver observer) {
Packit 5e46da
Packit 5e46da
        boolean flipX = false;
Packit 5e46da
        boolean flipY = false;
Packit 5e46da
Packit 5e46da
        if (dx1 > dx2) {
Packit 5e46da
            int swap = dx1;
Packit 5e46da
            dx1 = dx2;
Packit 5e46da
            dx2 = swap;
Packit 5e46da
            flipX = !flipX;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (dy1 > dy2) {
Packit 5e46da
            int swap = dy1;
Packit 5e46da
            dy1 = dy2;
Packit 5e46da
            dy2 = swap;
Packit 5e46da
            flipY = !flipY;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (sx1 > sx2) {
Packit 5e46da
            int swap = sx1;
Packit 5e46da
            sx1 = sx2;
Packit 5e46da
            sx2 = swap;
Packit 5e46da
            flipX = !flipX;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (sy1 > sy2) {
Packit 5e46da
            int swap = sy1;
Packit 5e46da
            sy1 = sy2;
Packit 5e46da
            sy2 = swap;
Packit 5e46da
            flipY = !flipY;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        return drawImageN(img, dx1, dy1, dx2 - dx1, dy2 - dy1,
Packit 5e46da
                          sx1, sy1, sx2 - sx1, sy2 - sy1,
Packit 5e46da
                          flipX, flipY, bg, observer);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Draws a subrectangle of an image scaled to a destination rectangle in
Packit 5e46da
     * nonblocking mode with a solid background color and a callback object.
Packit 5e46da
     */
Packit 5e46da
    protected boolean drawImageN(Image img,
Packit 5e46da
        int dx, int dy, int dw, int dh,
Packit 5e46da
        int sx, int sy, int sw, int sh,
Packit 5e46da
        boolean flipX, boolean flipY,
Packit 5e46da
        Color bg, ImageObserver observer) {
Packit 5e46da
Packit 5e46da
        if ((sw == 0) || (sh == 0) || (dw == 0) || (dh == 0))
Packit 5e46da
            return false;
Packit 5e46da
Packit 5e46da
        BDImage bdImage;
Packit 5e46da
        if (img instanceof BDImage) {
Packit 5e46da
            bdImage = (BDImage)img;
Packit 5e46da
        } else if (img instanceof DVBBufferedImage) {
Packit 5e46da
            bdImage = (BDImage)getBufferedImagePeer(
Packit 5e46da
                      (BufferedImage)(((DVBBufferedImage)img).getImage()));
Packit 5e46da
        } else if (img instanceof BufferedImage) {
Packit 5e46da
            bdImage = (BDImage)getBufferedImagePeer((BufferedImage)img);
Packit 5e46da
        } else {
Packit 5e46da
            logger.unimplemented("drawImageN: unsupported image type " + img.getClass().getName());
Packit 5e46da
            return false;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (bdImage instanceof BDImageConsumer) {
Packit 5e46da
            BDImageConsumer consumer = (BDImageConsumer)bdImage;
Packit 5e46da
            if (!consumer.isComplete(observer)) {
Packit 5e46da
                return false;
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (sw < 0) sw = bdImage.width;
Packit 5e46da
        if (sh < 0) sh = bdImage.height;
Packit 5e46da
        if (dw < 0) dw = bdImage.width;
Packit 5e46da
        if (dh < 0) dh = bdImage.height;
Packit 5e46da
Packit 5e46da
        int   stride   = bdImage.width;
Packit 5e46da
        int[] rgbArray = bdImage.getBdBackBuffer();
Packit 5e46da
        int   bgColor  = 0;
Packit 5e46da
Packit 5e46da
        if (bg != null) {
Packit 5e46da
            bgColor = bg.getRGB();
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // draw background colour
Packit 5e46da
        for (int i = 0; i < dh && bg != null; i++) {
Packit 5e46da
            drawSpan(dx, dy + i, dw, bgColor);
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // resize if needed
Packit 5e46da
        if (dw != sw || dh != sh) {
Packit 5e46da
            drawResizeBilinear(rgbArray, (sy * stride) + sx, stride, sw, sh,
Packit 5e46da
                               dx, dy, dw, dh, flipX, flipY);
Packit 5e46da
            return true;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // draw actual colour array
Packit 5e46da
        if (flipY) {
Packit 5e46da
            for (int i = 0; i < dh; i++) {
Packit 5e46da
                drawSpan(dx, dy + dh - 1 - i, dw, rgbArray, (stride * (i + sy)) + sx, flipX);
Packit 5e46da
            }
Packit 5e46da
        } else {
Packit 5e46da
            for (int i = 0; i < dh; i++) {
Packit 5e46da
                drawSpan(dx, dy + i, dw, rgbArray, (stride * (i + sy)) + sx, flipX);
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        return true;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    /**
Packit 5e46da
     * Bilinear resize ARGB image.
Packit 5e46da
     *
Packit 5e46da
     * @param pixels Source image pixels.
Packit 5e46da
     * @param sw Source image width.
Packit 5e46da
     * @param sh Source image height.
Packit 5e46da
     * @param dw New width.
Packit 5e46da
     * @param dh New height.
Packit 5e46da
     * @return New array with size dw * dh.
Packit 5e46da
     */
Packit 5e46da
    private int[] tmpLine = null;
Packit 5e46da
    private void drawResizeBilinear(int[] pixels, int offset, int scansize, int sw, int sh,
Packit 5e46da
                                    int dx, int dy, int dw, int dh, boolean flipX, boolean flipY) {
Packit 5e46da
Packit 5e46da
        if (sh == 1) {
Packit 5e46da
            // crop source width if needed for 1d arrays
Packit 5e46da
            if (offset + sw > pixels.length) {
Packit 5e46da
                sw = (pixels.length - offset);
Packit 5e46da
            }
Packit 5e46da
        } else {
Packit 5e46da
            // crop source height to prevent possible over reads
Packit 5e46da
            if (offset + (scansize*sh) > pixels.length) {
Packit 5e46da
                sh = (pixels.length - offset) / scansize;
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
        if (sw < 1 || sh < 1 || pixels.length < 1) {
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (sw == 1 && sh == 1) {
Packit 5e46da
            for (int Y = dy; Y < (dy + dh); Y++)
Packit 5e46da
                drawSpan(dx, Y, dw, pixels[offset]);
Packit 5e46da
            return;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        // a quick hack for 1D arrays, stretch them to make them 2D
Packit 5e46da
        if (sw == 1) {
Packit 5e46da
            int[] temp = new int[2 * sh];
Packit 5e46da
Packit 5e46da
            for (int i = 0; i < sw * sh; i++) {
Packit 5e46da
                temp[(i * 2) + 0] = pixels[offset + i];
Packit 5e46da
                temp[(i * 2) + 1] = pixels[offset + i];
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            scansize = 2;
Packit 5e46da
            pixels = temp;
Packit 5e46da
            offset = 0;
Packit 5e46da
            sw = 2;
Packit 5e46da
Packit 5e46da
        } else if (sh == 1) {
Packit 5e46da
            int[] temp = new int[sw * 2];
Packit 5e46da
Packit 5e46da
            System.arraycopy(pixels, offset, temp,  0, sw);
Packit 5e46da
            System.arraycopy(pixels, offset, temp, sw, sw);
Packit 5e46da
Packit 5e46da
            scansize = sw;
Packit 5e46da
            pixels = temp;
Packit 5e46da
            offset = 0;
Packit 5e46da
            sh = 2;
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (tmpLine == null || tmpLine.length < dw + 1) {
Packit 5e46da
            tmpLine = new int[Math.max(1920, dw + 1)];
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        int a, b, c, d, x, y, index;
Packit 5e46da
        float x_ratio = ((float)(sw - 1)) / dw;
Packit 5e46da
        float y_ratio = ((float)(sh - 1)) / dh;
Packit 5e46da
        float x_diff, y_diff, blue, red, green, alpha;
Packit 5e46da
        int position = 0;
Packit 5e46da
        for (int i = 0; i < dh; i++) {
Packit 5e46da
            for (int j = 0; j < dw; j++) {
Packit 5e46da
                x      = (int)(x_ratio * j);
Packit 5e46da
                y      = (int)(y_ratio * i);
Packit 5e46da
                x_diff = (x_ratio * j) - x;
Packit 5e46da
                y_diff = (y_ratio * i) - y;
Packit 5e46da
                index  = (y * scansize + x);
Packit 5e46da
                index += offset;
Packit 5e46da
Packit 5e46da
                a = pixels[index];
Packit 5e46da
                b = pixels[index + 1];
Packit 5e46da
                c = pixels[index + scansize];
Packit 5e46da
                d = pixels[index + scansize + 1];
Packit 5e46da
Packit 5e46da
                int aA = a >>> 24;
Packit 5e46da
                int bA = b >>> 24;
Packit 5e46da
                int cA = c >>> 24;
Packit 5e46da
                int dA = d >>> 24;
Packit 5e46da
Packit 5e46da
                if (aA + bA + cA + dA < 1) {
Packit 5e46da
                    tmpLine[position++] = 0;
Packit 5e46da
                    continue;
Packit 5e46da
                }
Packit 5e46da
Packit 5e46da
                /* calculate areas, weighted with alpha */
Packit 5e46da
                float aFactor = (1-x_diff) * (1-y_diff) * aA;
Packit 5e46da
                float bFactor = x_diff     * (1-y_diff) * bA;
Packit 5e46da
                float cFactor = (1-x_diff) * y_diff     * cA;
Packit 5e46da
                float dFactor = x_diff     * y_diff     * dA;
Packit 5e46da
Packit 5e46da
                // alpha element
Packit 5e46da
                // Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
Packit 5e46da
                alpha = aFactor + bFactor + cFactor + dFactor;
Packit 5e46da
Packit 5e46da
                // blue element
Packit 5e46da
                // Yb = Ab(1-w)(1-h) + Bb(w)(1-h) + Cb(h)(1-w) + Db(wh)
Packit 5e46da
                blue = (a & 0xff) * aFactor +
Packit 5e46da
                       (b & 0xff) * bFactor +
Packit 5e46da
                       (c & 0xff) * cFactor +
Packit 5e46da
                       (d & 0xff) * dFactor;
Packit 5e46da
Packit 5e46da
                // green element
Packit 5e46da
                // Yg = Ag(1-w)(1-h) + Bg(w)(1-h) + Cg(h)(1-w) + Dg(wh)
Packit 5e46da
                green = ((a >> 8) & 0xff) * aFactor +
Packit 5e46da
                        ((b >> 8) & 0xff) * bFactor +
Packit 5e46da
                        ((c >> 8) & 0xff) * cFactor +
Packit 5e46da
                        ((d >> 8) & 0xff) * dFactor;
Packit 5e46da
Packit 5e46da
                // red element
Packit 5e46da
                // Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
Packit 5e46da
                red = ((a >> 16) & 0xff) * aFactor +
Packit 5e46da
                      ((b >> 16) & 0xff) * bFactor +
Packit 5e46da
                      ((c >> 16) & 0xff) * cFactor +
Packit 5e46da
                      ((d >> 16) & 0xff) * dFactor;
Packit 5e46da
Packit 5e46da
                blue  /= alpha;
Packit 5e46da
                green /= alpha;
Packit 5e46da
                red   /= alpha;
Packit 5e46da
Packit 5e46da
                tmpLine[position++] =
Packit 5e46da
                    ((((int)alpha) << 24) & 0xff000000) |
Packit 5e46da
                    ((((int)red  ) << 16) & 0x00ff0000) |
Packit 5e46da
                    ((((int)green) << 8 ) & 0x0000ff00) |
Packit 5e46da
                    ((((int)blue )      ) & 0x000000ff);
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            if (flipY) {
Packit 5e46da
                drawSpan(dx, dy + dh - 1 - i, dw, tmpLine, 0, flipX);
Packit 5e46da
            } else {
Packit 5e46da
                drawSpan(dx, dy + i, dw, tmpLine, 0, flipX);
Packit 5e46da
            }
Packit 5e46da
Packit 5e46da
            position = 0;
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public Stroke getStroke() {
Packit 5e46da
        logger.unimplemented("getStroke");
Packit 5e46da
        throw new Error();
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void setStroke(Stroke stroke) {
Packit 5e46da
        logger.unimplemented("setStroke");
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public void dispose() {
Packit 5e46da
        tmpLine = null;
Packit 5e46da
        font = null;
Packit 5e46da
        fontMetrics = null;
Packit 5e46da
        gc = null;
Packit 5e46da
        backBuffer = null;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    public String toString() {
Packit 5e46da
        return getClass().getName() + "[" + originX + "," + originY + "]";
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private static Image getBufferedImagePeer(BufferedImage image) {
Packit 5e46da
        try {
Packit 5e46da
            return (Image)bufferedImagePeer.get(image);
Packit 5e46da
        } catch (IllegalArgumentException e) {
Packit 5e46da
            logger.error("Failed getting buffered image peer: " + e + "\n" +
Packit 5e46da
                         Logger.dumpStack(e));
Packit 5e46da
        } catch (IllegalAccessException e) {
Packit 5e46da
            logger.error("Failed getting buffered image peer: " + e + "\n" +
Packit 5e46da
                         Logger.dumpStack(e));
Packit 5e46da
        }
Packit 5e46da
        return null;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private static Field bufferedImagePeer;
Packit 5e46da
Packit 5e46da
    static {
Packit 5e46da
        try {
Packit 5e46da
            Class c = Class.forName("java.awt.image.BufferedImage");
Packit 5e46da
            bufferedImagePeer = c.getDeclaredField("peer");
Packit 5e46da
            bufferedImagePeer.setAccessible(true);
Packit 5e46da
        } catch (ClassNotFoundException e) {
Packit 5e46da
            throw new AWTError("java.awt.image.BufferedImage not found");
Packit 5e46da
        } catch (SecurityException e) {
Packit 5e46da
            throw new AWTError("java.awt.image.BufferedImage.peer not accessible");
Packit 5e46da
        } catch (NoSuchFieldException e) {
Packit 5e46da
            throw new AWTError("java.awt.image.BufferedImage.peer not found");
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    private static final Logger logger = Logger.getLogger(BDGraphics.class.getName());
Packit 5e46da
}