modules/midp-lcdui/src/main/java/cc/squirreljme/runtime/lcdui/mle/PencilGraphics.java
// -*- 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.mle;
import cc.squirreljme.jvm.mle.PencilShelf;
import cc.squirreljme.jvm.mle.brackets.PencilBracket;
import cc.squirreljme.jvm.mle.constants.PencilCapabilities;
import cc.squirreljme.jvm.mle.constants.PencilShelfError;
import cc.squirreljme.jvm.mle.constants.UIPixelFormat;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;
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;
import javax.microedition.lcdui.game.Sprite;
/**
* This delegates drawing operations to either the hardware graphics layer
* or the software graphics layer.
*
* This utilizes both {@link PencilShelf} and {@link PencilBracket} for native
* graphics.
*
* @since 2020/09/25
*/
public final class PencilGraphics
extends Graphics
{
/**
* {@squirreljme.property cc.squirreljme.lcdui.software=boolean
* If set to {@code true} then software graphics will be forced to be
* used.}
*/
private static final String _FORCE_SOFTWARE_PROPERTY =
"cc.squirreljme.lcdui.software";
/** Forcing software rasterization */
private static final boolean _IS_FORCE_SOFTWARE;
/** Software graphics backend. */
protected final Graphics software;
/** The hardware bracket reference. */
protected final PencilBracket hardware;
/** The capabilities of the graphics hardware. */
protected final int capabilities;
/** Surface width. */
protected final int surfaceW;
/** Surface height. */
protected final int surfaceH;
/** Does this have alpha channel support? */
protected final boolean hasAlpha;
/** Single character. */
private final char[] _singleChar =
new char[1];
/** 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;
static
{
_IS_FORCE_SOFTWARE =
Boolean.getBoolean(PencilGraphics._FORCE_SOFTWARE_PROPERTY);
}
/**
* Initializes the pencil graphics system.
*
* @param __caps Capabilities of the hardware, this determines the
* functions that are available.
* @param __software The fallback software graphics rasterizer.
* @param __sw The surface width.
* @param __sh The surface height.
* @param __hardware The hardware bracket reference for drawing.
* @param __pf The pixel format used.
* @throws IllegalArgumentException If hardware graphics are not capable
* enough to be used at all.
* @throws NullPointerException On null arguments.
* @since 2020/09/25
*/
private PencilGraphics(int __caps, Graphics __software, int __sw, int __sh,
PencilBracket __hardware, int __pf)
throws IllegalArgumentException, NullPointerException
{
if (__software == null || __hardware == null)
throw new NullPointerException("NARG");
/* {@squirreljme.error EB3g Hardware graphics not capable enough.} */
if ((__caps & PencilCapabilities.MINIMUM) == 0)
throw new IllegalArgumentException("EB3g " + __caps);
this.software = __software;
this.hardware = __hardware;
this.capabilities = __caps;
// These are used to manage the clip
this.surfaceW = __sw;
this.surfaceH = __sh;
// Does this use alpha?
this.hasAlpha = (__pf == UIPixelFormat.INT_RGBA8888 ||
__pf == UIPixelFormat.SHORT_ABGR1555 ||
__pf == UIPixelFormat.SHORT_RGBA4444);
// Set initial parameters for the graphics and make sure they are
// properly forwarded as well
this.setAlphaColor(0xFF000000);
this.setBlendingMode(Graphics.SRC_OVER);
this.setStrokeStyle(Graphics.SOLID);
this.setFont(null);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void clipRect(int __x, int __y, int __w, int __h)
{
throw Debugging.todo();
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void copyArea(int __sx, int __sy, int __w, int __h, int __dx,
int __dy, int __anchor)
throws IllegalArgumentException, IllegalStateException
{
if (0 == (this.capabilities & PencilCapabilities.COPY_AREA))
{
this.software.copyArea(__sx, __sy, __w, __h, __dx, __dy, __anchor);
return;
}
// Forward to native call
try
{
PencilShelf.hardwareCopyArea(this.hardware,
__sx, __sy, __w, __h, __dx, __dy, __anchor);
}
// Unwrap any potential errors.
catch (MLECallError e)
{
switch (e.distinction)
{
case PencilShelfError.ILLEGAL_ARGUMENT:
throw new IllegalArgumentException(e.getMessage(), e);
case PencilShelfError.ILLEGAL_STATE:
throw new IllegalStateException(e.getMessage(), e);
}
// No distinction
throw e;
}
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawArc(int __x, int __y, int __w, int __h, int __startAngle,
int __arcAngle)
{
if (0 == (this.capabilities & PencilCapabilities.DRAW_ARC))
{
this.software.drawArc(__x, __y, __w, __h, __startAngle, __arcAngle);
return;
}
throw Debugging.todo();
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawARGB16(short[] __data, int __off, int __scanlen,
int __x, int __y, int __w, int __h)
throws NullPointerException
{
if (0 == (this.capabilities & PencilCapabilities.DRAW_XRGB16_SIMPLE))
{
this.software.drawARGB16(__data, __off, __scanlen, __x, __y, __w,
__h);
return;
}
throw Debugging.todo();
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawChar(char __s, int __x, int __y, int __anchor)
{
if (0 == (this.capabilities & PencilCapabilities.TEXT_BASIC))
{
this.software.drawChar(__s, __x, __y, __anchor);
return;
}
// Fill single character first
char[] singleChar = this._singleChar;
singleChar[0] = __s;
// Forward
try
{
PencilShelf.hardwareDrawChars(this.hardware,
singleChar, 0, 1, __x, __y, __anchor);
}
catch (MLECallError e)
{
RuntimeException x;
switch (e.distinction)
{
case PencilShelfError.ILLEGAL_ARGUMENT:
throw new IllegalArgumentException(e.getMessage(), e);
}
throw e;
}
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawChars(char[] __s, int __o, int __l, int __x, int __y,
int __anchor)
throws IllegalArgumentException, IndexOutOfBoundsException,
NullPointerException
{
// Check
if (__s == null)
throw new NullPointerException("NARG");
if (__o < 0 || __l < 0 || (__o + __l) > __s.length)
throw new IndexOutOfBoundsException("IOOB");
if (0 == (this.capabilities & PencilCapabilities.TEXT_BASIC))
{
this.software.drawChars(__s, __o, __l, __x, __y, __anchor);
return;
}
// Forward
try
{
PencilShelf.hardwareDrawChars(this.hardware,
__s, __o, __l, __x, __y, __anchor);
}
catch (MLECallError e)
{
RuntimeException x;
switch (e.distinction)
{
case PencilShelfError.INDEX_OUT_OF_BOUNDS:
x = new IndexOutOfBoundsException(e.getMessage());
x.initCause(e);
throw x;
case PencilShelfError.ILLEGAL_ARGUMENT:
throw new IllegalArgumentException(e.getMessage(), e);
}
throw e;
}
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawImage(Image __i, int __x, int __y, int __anchor)
throws IllegalArgumentException, NullPointerException
{
// This is a duplicate function, so it gets forwarded
this.drawRegion(__i, 0, 0,
__i.getWidth(), __i.getHeight(), 0,
__x, __y, __anchor);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawLine(int __x1, int __y1, int __x2, int __y2)
{
if (0 == (this.capabilities & PencilCapabilities.DRAW_LINE))
{
this.software.drawLine(__x1, __y1, __x2, __y2);
return;
}
PencilShelf.hardwareDrawLine(this.hardware, __x1, __y1, __x2, __y2);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawRGB(int[] __data, int __off, int __scanlen, int __x,
int __y, int __w, int __h, boolean __alpha)
throws NullPointerException
{
if (0 == (this.capabilities & PencilCapabilities.DRAW_XRGB32_REGION))
{
this.software.drawRGB(__data, __off, __scanlen, __x, __y, __w,
__h, __alpha);
return;
}
// Forward Call
this.__drawRegion(__data, __off, __scanlen, __alpha,
0, 0, __w, __h, Sprite.TRANS_NONE,
__x, __y, Graphics.TOP | Graphics.LEFT, __w, __h,
__scanlen, (__data.length - __off) / __scanlen);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawRGB16(short[] __data, int __off, int __scanlen,
int __x, int __y, int __w, int __h)
throws NullPointerException
{
if (0 == (this.capabilities & PencilCapabilities.DRAW_XRGB16_SIMPLE))
{
this.software.drawRGB16(__data, __off, __scanlen, __x, __y,
__w, __h);
return;
}
throw Debugging.todo();
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawRect(int __x, int __y, int __w, int __h)
{
if (0 == (this.capabilities & PencilCapabilities.DRAW_RECT))
{
this.software.drawRect(__x, __y, __w, __h);
return;
}
// Forward to hardware
PencilShelf.hardwareDrawRect(this.hardware, __x, __y, __w, __h);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawRegion(Image __src, int __xsrc, int __ysrc,
int __wsrc, int __hsrc, int __trans, int __xdest, int __ydest,
int __anch)
throws IllegalArgumentException, NullPointerException
{
// Forward call
this.drawRegion(__src, __xsrc, __ysrc, __wsrc, __hsrc,
__trans, __xdest, __ydest, __anch, __wsrc, __hsrc);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawRegion(Image __src, int __xsrc, int __ysrc,
int __wsrc, int __hsrc, int __trans, int __xdest, int __ydest,
int __anch, int __wdest, int __hdest)
throws IllegalArgumentException, NullPointerException
{
if (__src == null)
throw new NullPointerException("NARG");
if (0 == (this.capabilities & PencilCapabilities.DRAW_XRGB32_REGION))
{
this.software.drawRegion(__src, __xsrc, __ysrc, __wsrc, __hsrc,
__trans, __xdest, __ydest, __anch, __wdest, __hdest);
return;
}
// If the image is direct, use the buffer that is inside rather than
// a copy, so we do not waste time copying from it!
int[] buf;
int offset;
int scanLen;
if (__src.squirreljmeIsDirect())
{
buf = __src.squirreljmeDirectRGBInt();
offset = __src.squirreljmeDirectOffset();
scanLen = __src.squirreljmeDirectScanLen();
}
// Image is not directly accessible, so get a copy of it
else
{
// Obtain image properties
int iW = __src.getWidth();
int iH = __src.getHeight();
int totalPixels = iW * iH;
// Read RGB data
buf = new int[totalPixels];
offset = 0;
scanLen = iW;
__src.getRGB(buf, offset, scanLen, 0, 0, iW, iH);
}
// Perform the internal draw
this.__drawRegion(buf, offset, scanLen, __src.hasAlpha(),
__xsrc, __ysrc, __wsrc, __hsrc, __trans,
__xdest, __ydest, __anch,
__wdest, __hdest, __src.getWidth(), __src.getHeight());
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawRoundRect(int __x, int __y, int __w, int __h,
int __aw, int __ah)
{
if (0 == (this.capabilities & PencilCapabilities.DRAW_ROUND_RECT))
{
this.software.drawRoundRect(__x, __y, __w, __h, __aw, __ah);
return;
}
throw Debugging.todo();
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawString(String __s, int __x, int __y, int __anchor)
throws NullPointerException
{
if (__s == null)
throw new NullPointerException("NARG");
if (0 == (this.capabilities & PencilCapabilities.TEXT_BASIC))
{
this.software.drawString(__s, __x, __y, __anchor);
return;
}
// Forward
try
{
PencilShelf.hardwareDrawSubstring(this.hardware,
__s, 0, __s.length(), __x, __y, __anchor);
}
catch (MLECallError e)
{
RuntimeException x;
switch (e.distinction)
{
case PencilShelfError.ILLEGAL_ARGUMENT:
throw new IllegalArgumentException(e.getMessage(), e);
}
throw e;
}
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawSubstring(String __s, int __o, int __l,
int __x, int __y, int __anchor)
throws NullPointerException, StringIndexOutOfBoundsException
{
if (__s == null)
throw new NullPointerException("NARG");
if (__o < 0 || __l < 0 || (__o + __l) > __s.length())
throw new StringIndexOutOfBoundsException("IOOB");
if (0 == (this.capabilities & PencilCapabilities.TEXT_BASIC))
{
this.software.drawSubstring(__s, __o, __l, __x, __y, __anchor);
return;
}
// Forward
try
{
PencilShelf.hardwareDrawSubstring(this.hardware,
__s, __o, __l, __x, __y, __anchor);
}
catch (MLECallError e)
{
RuntimeException x;
switch (e.distinction)
{
case PencilShelfError.ILLEGAL_ARGUMENT:
throw new IllegalArgumentException(e.getMessage(), e);
}
throw e;
}
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void drawText(Text __t, int __x, int __y)
{
if (0 == (this.capabilities & PencilCapabilities.TEXT_ADVANCED))
{
this.software.drawText(__t, __x, __y);
return;
}
throw Debugging.todo();
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void fillArc(int __x, int __y, int __w, int __h, int __startAngle,
int __arcAngle)
{
if (0 == (this.capabilities & PencilCapabilities.FILL_ARC))
{
this.software.fillArc(__x, __y, __w, __h, __startAngle, __arcAngle);
return;
}
throw Debugging.todo();
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void fillRect(int __x, int __y, int __w, int __h)
{
if (0 == (this.capabilities & PencilCapabilities.FILL_RECT))
{
this.software.fillRect(__x, __y, __w, __h);
return;
}
// Forward to hardware
PencilShelf.hardwareFillRect(this.hardware, __x, __y, __w, __h);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void fillRoundRect(int __x, int __y, int __w, int __h,
int __aw, int __ah)
{
if (0 == (this.capabilities & PencilCapabilities.FILL_ROUND_RECT))
{
this.software.fillRoundRect(__x, __y, __w, __h, __aw, __ah);
return;
}
throw Debugging.todo();
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void fillTriangle(int __x1, int __y1, int __x2, int __y2,
int __x3, int __y3)
{
if (0 == (this.capabilities & PencilCapabilities.FILL_TRIANGLE))
{
this.software.fillTriangle(__x1, __y1, __x2, __y2, __x3, __y3);
return;
}
// Forward to hardware
PencilShelf.hardwareFillTriangle(this.hardware, __x1, __y1, __x2, __y2,
__x3, __y3);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getAlpha()
{
return (this._argbColor >> 24) & 0xFF;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getAlphaColor()
{
return this._argbColor;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getBlendingMode()
{
return this._blendingMode;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getBlueComponent()
{
return (this._argbColor) & 0xFF;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getClipHeight()
{
return this._clipHeight;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getClipWidth()
{
return this._clipWidth;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getClipX()
{
return this._clipX - this._transX;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getClipY()
{
return this._clipY - this._transY;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getColor()
{
return this._argbColor & 0xFFFFFF;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getDisplayColor(int __rgb)
{
// We can just ask the software graphics for the color we are using
// since it should hopefully match the hardware one.
return this.software.getDisplayColor(__rgb);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public Font getFont()
{
if (0 == (this.capabilities & PencilCapabilities.TEXT_BASIC))
return this.software.getFont();
return this._font;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getGrayScale()
{
return (((this._argbColor >> 16) & 0xFF) +
((this._argbColor >> 8) & 0xFF) +
((this._argbColor) & 0xFF)) / 3;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getGreenComponent()
{
return (this._argbColor >> 8) & 0xFF;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getRedComponent()
{
return (this._argbColor >> 16) & 0xFF;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getStrokeStyle()
{
return this._strokeStyle;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getTranslateX()
{
return this._transX;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public int getTranslateY()
{
return this._transY;
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void setAlpha(int __a)
throws IllegalArgumentException
{
this.setAlphaColor(__a,
this.getRedComponent(),
this.getGreenComponent(),
this.getBlueComponent());
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void setAlphaColor(int __argb)
{
// Mirror locally
this._argbColor = __argb;
// Set on the remote software and hardware graphics
this.software.setAlphaColor(__argb);
PencilShelf.hardwareSetAlphaColor(this.hardware, __argb);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void setAlphaColor(int __a, int __r, int __g, int __b)
throws IllegalArgumentException
{
/* {@squirreljme.error EB3t 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(
"EB3t %d %d %d %d", __a, __r, __g, __b));
// Set
this.setAlphaColor((__a << 24) | (__r << 16) | (__g << 8) | __b);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void setBlendingMode(int __m)
throws IllegalArgumentException
{
/* {@squirreljme.error EB3u Invalid blending mode. (The mode)} */
if ((__m != Graphics.SRC && __m != Graphics.SRC_OVER) ||
(__m == Graphics.SRC && !this.hasAlpha))
throw new IllegalArgumentException("EB3u " + __m);
// Cache locally
this._blendingMode = __m;
// Forward to both software and hardware graphics
this.software.setBlendingMode(__m);
PencilShelf.hardwareSetBlendingMode(this.hardware, __m);
}
/**
* {@inheritDoc}
* @since 2020/09/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.min(this.surfaceW, Math.max(0, startX));
int clipY = Math.min(this.surfaceH, Math.max(0, startY));
int clipEndX = Math.min(this.surfaceW, Math.max(0, endX));
int clipEndY = Math.min(this.surfaceH, Math.max(0, endY));
// Record internally
this._clipX = clipX;
this._clipY = clipY;
this._clipWidth = clipEndX - clipX;
this._clipHeight = clipEndY - clipY;
// Forward to both software and hardware graphics
this.software.setClip(__x, __y, __w, __h);
PencilShelf.hardwareSetClip(this.hardware, __x, __y, __w, __h);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@SuppressWarnings("MagicNumber")
@Override
public void setColor(int __rgb)
{
this.setAlphaColor((this.getAlphaColor() & 0xFF_000000) |
(__rgb & 0x00_FFFFFF));
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void setColor(int __r, int __g, int __b)
throws IllegalArgumentException
{
this.setAlphaColor(this.getAlpha(), __r, __g, __b);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void setFont(Font __font)
{
// Cache locally
this._font = __font;
// This is always set in software
this.software.setFont(__font);
// If supported by hardware, set it here
if (0 != (this.capabilities & PencilCapabilities.TEXT_BASIC))
{
// Clearing the font?
if (__font == null)
PencilShelf.hardwareSetDefaultFont(this.hardware);
// Set font natively from the font details
else
PencilShelf.hardwareSetFont(this.hardware,
__font.getFontName(), __font.getStyle(),
__font.getPixelSize());
}
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void setGrayScale(int __v)
{
this.setAlphaColor(this.getAlpha(), __v, __v, __v);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void setStrokeStyle(int __style)
throws IllegalArgumentException
{
/* {@squirreljme.error EB3v Illegal stroke style.} */
if (__style != Graphics.SOLID && __style != Graphics.DOTTED)
throw new IllegalArgumentException("EB3v");
// Set
this._strokeStyle = __style;
// Forward to both software and hardware graphics
this.software.setStrokeStyle(__style);
PencilShelf.hardwareSetStrokeStyle(this.hardware, __style);
}
/**
* {@inheritDoc}
* @since 2020/09/25
*/
@Override
public void translate(int __x, int __y)
{
// Set locally
this._transX += __x;
this._transY += __y;
// Forward to both software and hardware graphics
this.software.translate(__x, __y);
PencilShelf.hardwareTranslate(this.hardware, __x, __y);
}
/**
* Draws a direct RGB region of an image.
*
* @param __data The source buffer.
* @param __off The offset into the buffer.
* @param __scanlen The scanline length.
* @param __alpha Drawing with the alpha channel?
* @param __xsrc The source X position.
* @param __ysrc The source Y position.
* @param __wsrc The width of the source region.
* @param __hsrc The height of the source region.
* @param __trans Sprite translation and/or rotation, see {@link Sprite}.
* @param __xdest The destination X position, is translated.
* @param __ydest The destination Y position, is translated.
* @param __anch The anchor point.
* @param __wdest The destination width.
* @param __hdest The destination height.
* @param __origImgWidth Original image width.
* @param __origImgHeight Original image height.
* @throws NullPointerException On null arguments.
* @since 2022/01/26
*/
private void __drawRegion(int[] __data, int __off, int __scanlen,
boolean __alpha, int __xsrc, int __ysrc, int __wsrc, int __hsrc,
int __trans, int __xdest, int __ydest, int __anch, int __wdest,
int __hdest, int __origImgWidth, int __origImgHeight)
throws NullPointerException
{
if (__data == null)
throw new NullPointerException("NARG");
// Forward to the native region drawing method
PencilShelf.hardwareDrawXRGB32Region(this.hardware,
__data, __off, __scanlen,
__alpha, __xsrc, __ysrc, __wsrc, __hsrc,
__trans, __xdest, __ydest, __anch,
__wdest, __hdest, __origImgWidth, __origImgHeight);
}
/**
* Creates a graphics that is capable of drawing on hardware if it is
* supported, but falling back to software level graphics.
*
* @param __pf The {@link UIPixelFormat} used for the draw.
* @param __bw The buffer width, this is the scanline width of the buffer.
* @param __bh The buffer height.
* @param __buf The target buffer to draw to, this is cast to the correct
* buffer format.
* @param __offset The offset to the start of the buffer.
* @param __pal The color palette, may be {@code null}.
* @param __sx Starting surface X coordinate.
* @param __sy Starting surface Y coordinate.
* @param __sw Surface width.
* @param __sh Surface height.
* @throws NullPointerException On null arguments.
* @since 2020/09/25
*/
public static Graphics hardwareGraphics(int __pf, int __bw,
int __bh, Object __buf, int __offset, int[] __pal, int __sx, int __sy,
int __sw, int __sh)
throws NullPointerException
{
// Setup software graphics
Graphics software = SoftwareGraphicsFactory.softwareGraphics(__pf,
__bw, __bh, __buf, __offset, __pal, __sx, __sy, __sw, __sh);
// Get the capabilities of the native system, if it is not supported
// then operations will purely be implemented in software
// It can also be disabled via a system property
int caps = PencilShelf.capabilities(__pf);
if (PencilGraphics._IS_FORCE_SOFTWARE ||
(caps & PencilCapabilities.MINIMUM) == 0)
return software;
return new PencilGraphics(caps, software, __sw, __sh,
PencilShelf.hardwareGraphics(__pf,
__bw, __bh, __buf, __offset, __pal, __sx, __sy, __sw, __sh), __pf);
}
}