SquirrelJME/SquirrelJME

View on GitHub
modules/midp-lcdui/src/main/java/cc/squirreljme/runtime/lcdui/gfx/ProxyGraphics.java

Summary

Maintainability
A
1 hr
Test Coverage
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the Mozilla Public License Version 2.0.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.lcdui.gfx;

import cc.squirreljme.runtime.cldc.debug.Debugging;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Text;

/**
 * This is a proxy version of {@link Graphics} where each instance can
 * refer to a single graphics instance. When a draw operation occurs, the
 * parameters of this current graphics will be set on the target.
 *
 * @see ProxyGraphicsTarget
 * @since 2022/02/25
 */
public final class ProxyGraphics
    extends Graphics
{
    /** The target graphics to draw into. */
    protected final ProxyGraphicsTarget target;
    
    /** The current alpha color. */
    private int _argbColor;
    
    /** The current blending mode. */
    private int _blendingMode;
    
    /** The clip height. */
    private int _clipHeight;
    
    /** The clip width. */
    private int _clipWidth;
    
    /** The clip X position. */
    private int _clipX;
    
    /** The clip Y position. */
    private int _clipY;
    
    /** The current font used. */
    private Font _font;
    
    /** The current stroke style. */
    private int _strokeStyle;
    
    /** The current X translation. */
    private int _transX;
    
    /** The current Y translation. */
    private int _transY;
    
    /**
     * Initializes the proxy graphics with the given target.
     * 
     * @param __target The target graphics proxy.
     * @param __width The graphics width.
     * @param __height The graphics height.
     * @throws NullPointerException On null arguments.
     * @since 2022/02/25
     */
    public ProxyGraphics(ProxyGraphicsTarget __target, int __width,
        int __height)
        throws NullPointerException
    {
        if (__target == null)
            throw new NullPointerException("NARG");
        
        this.target = __target;
        this._clipWidth = __width;
        this._clipHeight = __height;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void clipRect(int __a, int __b, int __c, int __d)
    {
        throw Debugging.todo();
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void copyArea(int __a, int __b, int __c, int __d, int __e,
        int __f, int __g)
    {
        this.__graphics().copyArea(__a, __b, __c, __d, __e, __f, __g);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawArc(int __a, int __b, int __c, int __d, int __e,
        int __f)
    {
        this.__graphics().drawArc(__a, __b, __c, __d, __e, __f);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawARGB16(short[] __data, int __off, int __scanlen,
        int __x, int __y, int __w, int __h)
    {
        this.__graphics().drawARGB16(__data, __off, __scanlen, __x, __y, __w,
            __h);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawChar(char __a, int __b, int __c, int __d)
    {
        this.__graphics().drawChar(__a, __b, __c, __d);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawChars(char[] __a, int __b, int __c, int __d,
        int __e, int __f)
    {
        this.__graphics().drawChars(__a, __b, __c, __d, __e, __f);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawImage(Image __a, int __b, int __c, int __d)
    {
        this.__graphics().drawImage(__a, __b, __c, __d);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawLine(int __a, int __b, int __c, int __d)
    {
        this.__graphics().drawLine(__a, __b, __c, __d);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawRGB(int[] __a, int __b, int __c, int __d, int __e,
        int __f, int __g, boolean __h)
    {
        this.__graphics().drawRGB(__a, __b, __c, __d, __e, __f, __g, __h);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawRGB16(short[] __data, int __off, int __scanlen,
        int __x, int __y, int __w, int __h)
    {
        this.__graphics().drawRGB16(__data, __off, __scanlen, __x, __y, __w, __h);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawRect(int __a, int __b, int __c, int __d)
    {
        this.__graphics().drawRect(__a, __b, __c, __d);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawRegion(Image __a, int __b, int __c, int __d,
        int __e, int __f, int __g, int __h, int __i)
    {
        this.__graphics().drawRegion(__a, __b, __c, __d, __e, __f, __g, __h,
            __i);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawRegion(Image __src, int __xsrc, int __ysrc,
        int __w, int __h, int __trans, int __xdest, int __ydest, int __anch,
        int __wdest, int __hdest)
    {
        this.__graphics().drawRegion(__src, __xsrc, __ysrc, __w, __h, __trans,
            __xdest, __ydest, __anch, __wdest, __hdest);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawRoundRect(int __a, int __b, int __c, int __d,
        int __e,  int __f)
    {
        this.__graphics().drawRoundRect(__a, __b, __c, __d, __e, __f);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawString(String __a, int __b, int __c, int __d)
    {
        this.__graphics().drawString(__a, __b, __c, __d);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawSubstring(String __a, int __b, int __c, int __d,
        int __e, int __f)
    {
        this.__graphics().drawSubstring(__a, __b, __c, __d, __e, __f);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void drawText(Text __t, int __x, int __y)
    {
        this.__graphics().drawText(__t, __x, __y);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void fillArc(int __a, int __b, int __c, int __d, int __e,
        int __f)
    {
        this.__graphics().fillArc(__a, __b, __c, __d, __e, __f);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void fillRect(int __x, int __y, int __w, int __h)
    {
        this.__graphics().fillRect(__x, __y, __w, __h);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void fillRoundRect(int __a, int __b, int __c, int __d,
        int __e, int __f)
    {
        this.__graphics().fillRoundRect(__a, __b, __c, __d, __e, __f);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void fillTriangle(int __a, int __b, int __c, int __d,
        int __e, int __f)
    {
        this.__graphics().fillTriangle(__a, __b, __c, __d, __e, __f);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getAlpha()
    {
        return (this._argbColor >> 24) & 0xFF;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/02/10
     */
    @Override
    public int getAlphaColor()
    {
        return this._argbColor;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getBlendingMode()
    {
        return this._blendingMode;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getBlueComponent()
    {
        return (this._argbColor) & 0xFF;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getClipHeight()
    {
        return this._clipHeight;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getClipWidth()
    {
        return this._clipWidth;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getClipX()
    {
        return this._clipX - this._transX;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getClipY()
    {
        return this._clipY - this._transY;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getColor()
    {
        return this._argbColor & 0xFFFFFF;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getDisplayColor(int __a)
    {
        return this.__graphics().getDisplayColor(__a);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public Font getFont()
    {
        return this.__font();
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getGrayScale()
    {
        return (((this._argbColor >> 16) & 0xFF) +
            ((this._argbColor >> 8) & 0xFF) +
            ((this._argbColor) & 0xFF)) / 3;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getGreenComponent()
    {
        return (this._argbColor >> 8) & 0xFF;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getRedComponent()
    {
        return (this._argbColor >> 16) & 0xFF;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getStrokeStyle()
    {
        return this._strokeStyle;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getTranslateX()
    {
        return this._transX;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public int getTranslateY()
    {
        return this._transY;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void setAlpha(int __a)
    {
        this.setAlphaColor(__a,
            this.getRedComponent(),
            this.getGreenComponent(),
            this.getBlueComponent());
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void setAlphaColor(int __argb)
    {
        this._argbColor = __argb;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void setAlphaColor(int __a, int __r, int __g, int __b)
    {
        /* {@squirreljme.error EB2y Color out of range. (Alpha; Red; Green;
        Blue)} */
        if (__a < 0 || __a > 255 || __r < 0 || __r > 255 ||
            __g < 0 || __g > 255 || __b < 0 || __b > 255)
            throw new IllegalArgumentException(String.format(
                "EB2y %d %d %d %d", __a, __r, __g, __b));
        
        // Set
        this.setAlphaColor((__a << 24) | (__r << 16) | (__g << 8) | __b);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void setBlendingMode(int __m)
    {
        /* {@squirreljme.error EB2x Invalid blending mode. (The mode)} */
        if (__m != Graphics.SRC && __m != Graphics.SRC_OVER)
            throw new IllegalArgumentException("EB2x " + __m);
        
        // Cache locally
        this._blendingMode = __m;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void setClip(int __x, int __y, int __w, int __h)
    {
        // Calculate the base clip coordinates
        int startX = __x + this._transX;
        int startY = __y + this._transY;
        int endX = startX + __w;
        int endY = startY + __h;
        
        // Normalize X
        if (endX < startX)
        {
            int temp = endX;
            endX = startX;
            startX = temp;
        }
        
        // Normalize Y
        if (endY < startY)
        {
            int temp = endY;
            endY = startY;
            startY = temp;
        }
        
        // Determine the bounds of all of these
        int clipX = Math.max(0, startX);
        int clipY = Math.max(0, startY);
        int clipEndX = Math.max(0, endX);
        int clipEndY = Math.max(0, endY);
        
        // Record internally
        this._clipX = clipX;
        this._clipY = clipY;
        this._clipWidth = clipEndX - clipX;
        this._clipHeight = clipEndY - clipY;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void setColor(int __rgb)
    {
        this.setAlphaColor((this.getAlphaColor() & 0xFF_000000) |
            (__rgb & 0x00_FFFFFF));
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void setColor(int __r, int __g, int __b)
    {
        this.setAlphaColor(this.getAlpha(), __r, __g, __b);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void setFont(Font __font)
    {
        this.__graphics().setFont(__font);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void setGrayScale(int __v)
    {
        this.setAlphaColor(this.getAlpha(), __v, __v, __v);
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     * @param __style
     */
    @Override
    public void setStrokeStyle(int __style)
    {
        /* {@squirreljme.error EB2z Illegal stroke style.} */
        if (__style != Graphics.SOLID && __style != Graphics.DOTTED)
            throw new IllegalArgumentException("EB2z");
        
        // Set
        this._strokeStyle = __style;
    }
    
    /**
     * {@inheritDoc}
     * @since 2022/02/25
     */
    @Override
    public void translate(int __x, int __y)
    {
        // Cache locally
        this._transX += __x;
        this._transY += __y;
    }
    
    /**
     * Returns the font that should be used.
     * 
     * @return The font used.
     * @since 2022/02/25
     */
    private Font __font()
    {
        Font rv = this._font;
        if (rv == null)
            rv = Font.getDefaultFont();
        return rv;
    }
    
    /**
     * Initializes and returns the target graphics accordingly.
     * 
     * @return The resultant graphics object.
     * @since 2022/02/25
     */
    private Graphics __graphics()
    {
        // This is the graphics we are drawing into
        Graphics target = this.target._target;
        
        // Pass all the adjustable parameters to the target
        target.setAlphaColor(this._argbColor);
        target.setBlendingMode(this._blendingMode);
        target.setFont(this.__font());
        target.setStrokeStyle(this._strokeStyle);
        
        // Translation that is needed for clipping and translation
        int targetTransX = target.getTranslateX();
        int targetTransY = target.getTranslateY();
        
        // Set absolute clipping area
        target.setClip(
            this._clipX - targetTransX, this._clipY - targetTransY,
            this._clipWidth, this._clipHeight);
        target.translate(this._transX - targetTransX,
            this._transY - targetTransY);
        
        // Return the graphics we are drawing into
        return target;
    }
}