/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package javax.microedition.lcdui;
import com.nokia.mid.ui.*;
import javax.microedition.lcdui.game.*;
import malik.emulator.media.graphics.*;
public class Graphics extends Object implements DirectGraphics
{
private static class Line extends Object implements Drawable
{
public final int x1;
public final int y1;
public final int x2;
public final int y2;
public Line(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public void draw(PrimitiveRender render) {
Graphics.drawLine(render, x1, y1, x2, y2, true);
}
}
private static abstract class Triangle extends Line
{
public final int x3;
public final int y3;
public Triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
super(x1, y1, x2, y2);
this.x3 = x3;
this.y3 = y3;
}
public abstract void draw(PrimitiveRender render);
}
private static abstract class Polygon extends Object implements Drawable
{
public final int length;
public final int xOffset;
public final int yOffset;
public final int[] xCoords;
public final int[] yCoords;
public Polygon(int[] xCoords, int xOffset, int[] yCoords, int yOffset, int length) {
this.length = length;
this.xOffset = xOffset;
this.yOffset = yOffset;
this.xCoords = xCoords;
this.yCoords = yCoords;
}
public abstract void draw(PrimitiveRender render);
}
private static abstract class Rectangle extends Object implements Drawable
{
public final int width;
public final int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public abstract void draw(PrimitiveRender render);
}
private static abstract class RoundRect extends Rectangle
{
public final int arcWidth;
public final int arcHeight;
public RoundRect(int width, int height, int arcWidth, int arcHeight) {
super(width, height);
width >>= 1;
height >>= 1;
this.arcWidth = arcWidth < 0 ? 0 : arcWidth > width ? width : arcWidth;
this.arcHeight = arcHeight < 0 ? 0 : arcHeight > height ? height : arcHeight;
}
public abstract void draw(PrimitiveRender render);
}
private static class FilledTriangle extends Triangle
{
public FilledTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
super(x1, y1, x2, y2, x3, y3);
}
public void draw(PrimitiveRender render) {
int x1 = this.x1;
int x2 = this.x2;
int x3 = this.x3;
int y1 = this.y1;
int y2 = this.y2;
int y3 = this.y3;
int ix;
int id;
int idx;
int idy;
int ixerr;
int iyerr;
int iincx;
int iincy;
int jx;
int jd;
int jdx;
int jdy;
int jxerr;
int jyerr;
int jincx;
int jincy;
int tmp;
if(y1 > y3)
{
tmp = y1;
y1 = y3;
y3 = tmp;
tmp = x1;
x1 = x3;
x3 = tmp;
}
if(y1 > y2)
{
tmp = y1;
y1 = y2;
y2 = tmp;
tmp = x1;
x1 = x2;
x2 = tmp;
}
if(y2 > y3)
{
tmp = y2;
y2 = y3;
y3 = tmp;
tmp = x2;
x2 = x3;
x3 = tmp;
}
ix = x1;
ixerr = 0;
iyerr = 0;
iincx = (idx = x2 - x1) == 0 ? 0 : (idx < 0 ? -1 : 1);
iincy = (idy = y2 - y1) == 0 ? 0 : (idy < 0 ? -1 : 1);
id = (idx = idx < 0 ? -idx : idx) >= (idy = idy < 0 ? -idy : idy) ? idx : idy;
jx = x1;
jxerr = 0;
jyerr = 0;
jincx = (jdx = x3 - x1) == 0 ? 0 : (jdx < 0 ? -1 : 1);
jincy = (jdy = y3 - y1) == 0 ? 0 : (jdy < 0 ? -1 : 1);
jd = (jdx = jdx < 0 ? -jdx : jdx) >= (jdy = jdy < 0 ? -jdy : jdy) ? jdx : jdy;
for(int y = y1; ; )
{
if(y == y2)
{
ix = x2;
ixerr = 0;
iyerr = 0;
iincx = (idx = x3 - x2) == 0 ? 0 : (idx < 0 ? -1 : 1);
iincy = (idy = y3 - y2) == 0 ? 0 : (idy < 0 ? -1 : 1);
id = (idx = idx < 0 ? -idx : idx) >= (idy = idy < 0 ? -idy : idy) ? idx : idy;
}
if(ix <= jx)
{
render.drawHorizontalLine(ix, y, jx - ix + 1);
} else
{
render.drawHorizontalLine(jx, y, ix - jx + 1);
}
if(++y > y3) break;
while(iincy > 0)
{
ixerr += idx;
iyerr += idy;
if(ixerr > id)
{
ixerr -= id;
ix += iincx;
}
if(iyerr > id)
{
iyerr -= id;
break;
}
}
while(jincy > 0)
{
jxerr += jdx;
jyerr += jdy;
if(jxerr > jd)
{
jxerr -= jd;
jx += jincx;
}
if(jyerr > jd)
{
jyerr -= jd;
break;
}
}
}
}
}
private static class FilledPolygon extends Polygon
{
public FilledPolygon(int[] xCoords, int xOffset, int[] yCoords, int yOffset, int length) {
super(xCoords, xOffset, yCoords, yOffset, length);
}
public void draw(PrimitiveRender render) {
int ymin;
int ymax;
int length;
int xStart;
int yStart = (xStart = (length = this.length) & (-2)) + length;
int[] coords = new int[yStart + length];
Array.copy(xCoords, xOffset, coords, xStart, length);
Array.copy(yCoords, yOffset, coords, yStart, length);
ymin = ymax = coords[yStart];
for(int i = length; i-- > 1; )
{
int yi = coords[yStart + i];
if(ymin > yi) ymin = yi;
if(ymax < yi) ymax = yi;
}
for(int y = ymin; y < ymax; y++)
{
int ixsize = 0;
for(int x1 = coords[xStart], y1 = coords[yStart], i = length; i-- > 0; )
{
int x;
int x0;
int x2 = x1;
int y2 = y1;
x1 = coords[xStart + i];
y1 = coords[yStart + i];
if(y < (y1 <= y2 ? y1 : y2) || y >= (y1 >= y2 ? y1 : y2)) continue;
x = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
switch(ixsize)
{
default:
if(x >= coords[ixsize - 1])
{
coords[ixsize++] = x;
break;
}
for(int j = 0; j < ixsize; j++) if(x <= coords[j])
{
Array.copy(coords, j, coords, j + 1, ixsize++ - j);
coords[j] = x;
break;
}
break;
case 1:
if(x < (x0 = coords[0]))
{
coords[ixsize++] = x0;
coords[0] = x;
break;
}
/* fall through */
case 0:
coords[ixsize++] = x;
break;
}
}
for(int x1, x2, j = ixsize; (j -= 2) >= 0; ) if((x1 = coords[j]) < (x2 = coords[j + 1])) render.drawHorizontalLine(x1, y, x2 - x1);
}
}
}
private static class FilledRoundRect extends RoundRect
{
public FilledRoundRect(int width, int height, int arcWidth, int arcHeight) {
super(width, height, arcWidth, arcHeight);
}
public strictfp void draw(PrimitiveRender render) {
double ratio;
int w = width;
int h = height;
int aw = arcWidth;
int ah = arcHeight;
long square;
if(aw <= 0 || ah <= 0)
{
render.fillRectangle(0, 0, w, h);
return;
}
render.fillRectangle(0, ah, w, --h - (ah << 1) + 1);
ratio = (double) aw / (double) ah;
square = (long) ah * (long) ah;
for(int y = ah, i = 0; i < ah; h--, y--, i++)
{
int j = (int) Math.round((double) aw - ratio * Math.sqrt((double) (square - (long) y * (long) y))) + (i != 0 ? 1 : 0);
int tmp1 = w - (j << 1);
render.drawHorizontalLine(j, i, tmp1);
render.drawHorizontalLine(j, h, tmp1);
}
}
}
private static class ClosedPolygon extends Polygon
{
public ClosedPolygon(int[] xCoords, int xOffset, int[] yCoords, int yOffset, int length) {
super(xCoords, xOffset, yCoords, yOffset, length);
}
public void draw(PrimitiveRender render) {
int length = this.length;
int xStart = xOffset;
int yStart = yOffset;
int[] cx = xCoords;
int[] cy = yCoords;
for(int x1 = cx[xStart], y1 = cy[yStart], i = length; i-- > 0; )
{
int x2 = x1;
int y2 = y1;
x1 = cx[xStart + i];
y1 = cy[yStart + i];
Graphics.drawLine(render, x1, y1, x2, y2, true);
}
}
}
private static class OpenedPolygon extends Polygon
{
public OpenedPolygon(int[] xCoords, int xOffset, int[] yCoords, int yOffset, int length) {
super(xCoords, xOffset, yCoords, yOffset, length);
}
public void draw(PrimitiveRender render) {
int length = this.length;
int xStart = xOffset;
int yStart = yOffset;
int[] cx = xCoords;
int[] cy = yCoords;
for(int x2 = cx[xStart], y2 = cy[yStart], i = 1; i < length; i++)
{
int x1 = x2;
int y1 = y2;
x2 = cx[xStart + i];
y2 = cy[yStart + i];
Graphics.drawLine(render, x1, y1, x2, y2, false);
}
}
}
private static class OutlinedTriangle extends Triangle
{
public OutlinedTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
super(x1, y1, x2, y2, x3, y3);
}
public void draw(PrimitiveRender render) {
int x1 = this.x1;
int y1 = this.y1;
int x2 = this.x2;
int y2 = this.y2;
int x3 = this.x3;
int y3 = this.y3;
Graphics.drawLine(render, x1, y1, x2, y2, true);
Graphics.drawLine(render, x2, y2, x3, y3, true);
Graphics.drawLine(render, x3, y3, x1, y1, true);
}
}
private static class OutlinedRectangle extends Rectangle
{
public OutlinedRectangle(int width, int height) {
super(width, height);
}
public void draw(PrimitiveRender render) {
int w = width;
int h = height;
render.drawHorizontalLine(0, 0, w + 1);
if(h > 0) render.drawHorizontalLine(0, h, w + 1);
if(h > 1)
{
render.drawVerticalLine(0, 1, h - 1);
if(w > 0) render.drawVerticalLine(w, 1, h - 1);
}
}
}
private static class OutlinedRoundRect extends RoundRect
{
public OutlinedRoundRect(int width, int height, int arcWidth, int arcHeight) {
super(width, height, arcWidth, arcHeight);
}
public strictfp void draw(PrimitiveRender render) {
double ratio;
int w = width;
int h = height;
int aw = arcWidth;
int ah = arcHeight;
int tmp1;
int tmp2;
long square;
if(aw <= 0 || ah <= 0)
{
render.drawHorizontalLine(0, 0, w + 1);
if(h > 0) render.drawHorizontalLine(0, h, w + 1);
if(h > 1)
{
render.drawVerticalLine(0, 1, h - 1);
if(w > 0) render.drawVerticalLine(w, 1, h - 1);
}
return;
}
tmp1 = w - (aw << 1) + 1;
tmp2 = h - (ah << 1) + 1;
render.drawHorizontalLine(aw, 0, tmp1);
render.drawHorizontalLine(aw, h, tmp1);
render.drawVerticalLine(0, ah, tmp2);
render.drawVerticalLine(w, ah, tmp2);
ratio = (double) aw / (double) ah;
square = (long) ah * (long) ah;
for(int x = aw, y = ah, l, k, j, i = 1; i < ah; x = j, i++)
{
y--;
j = (int) Math.intPart((double) aw - ratio * Math.sqrt((double) (square - (long) y * (long) y))) + 1;
tmp1 = x == j ? 1 : x - j;
k = h - i;
l = w - j - tmp1 + 1;
render.drawHorizontalLine(j, i, tmp1);
render.drawHorizontalLine(j, k, tmp1);
render.drawHorizontalLine(l, i, tmp1);
render.drawHorizontalLine(l, k, tmp1);
}
}
}
public static final int SOLID = 0;
public static final int DOTTED = 1;
public static final int HCENTER = 0x01;
public static final int VCENTER = 0x02;
public static final int LEFT = 0x04;
public static final int RIGHT = 0x08;
public static final int TOP = 0x10;
public static final int BOTTOM = 0x20;
public static final int BASELINE = 0x40;
private static final short[] XTABLE;
private static final short[] YTABLE;
static {
short[] x = new short[360];
short[] y = new short[360];
init(x, y);
XTABLE = x;
YTABLE = y;
}
static void drawLine(PrimitiveRender render, int x1, int y1, int x2, int y2, boolean inclusive) {
int x;
int y;
int d;
int dx;
int dy;
int xerr;
int yerr;
int incx;
int incy;
int prevx;
int prevy;
xerr = 0;
yerr = 0;
prevx = x = x1;
prevy = y = y1;
incx = (dx = x2 - x1) == 0 ? 0 : (dx < 0 ? -1 : 1);
incy = (dy = y2 - y1) == 0 ? 0 : (dy < 0 ? -1 : 1);
d = (dx = dx < 0 ? -dx : dx) >= (dy = dy < 0 ? -dy : dy) ? dx : dy;
if(inclusive)
{
dx++;
dy++;
d++;
}
for(int i = 0; i <= d; i++)
{
xerr += dx;
yerr += dy;
if(xerr > d)
{
xerr -= d;
x += incx;
}
if(yerr > d)
{
yerr -= d;
y += incy;
}
if(dx >= dy)
{
if(y != prevy || i == d)
{
if(prevx <= x)
{
render.drawHorizontalLine(prevx, prevy, x - prevx);
} else
{
render.drawHorizontalLine(x + 1, prevy, prevx - x);
}
prevx = x;
prevy = y;
}
} else
{
if(x != prevx || i == d)
{
if(prevy <= y)
{
render.drawVerticalLine(prevx, prevy, y - prevy);
} else
{
render.drawVerticalLine(prevx, y + 1, prevy - y);
}
prevx = x;
prevy = y;
}
}
}
}
private static void init(short[] x, short[] y) {
short[] sin = new short[] {
0x0000, 0x011e, 0x023c, 0x0359, 0x0477, 0x0594, 0x06b1, 0x07cd, 0x08e8, 0x0a03, 0x0b1d, 0x0c36, 0x0d4e, 0x0e66, 0x0f7c, 0x1090, 0x11a4, 0x12b6, 0x13c7, 0x14d6,
0x15e4, 0x16f0, 0x17f9, 0x1902, 0x1a08, 0x1b0c, 0x1c0e, 0x1d0e, 0x1e0c, 0x1f07, 0x2000, 0x20f6, 0x21ea, 0x22db, 0x23ca, 0x24b5, 0x259e, 0x2684, 0x2767, 0x2847,
0x2923, 0x29fd, 0x2ad3, 0x2ba6, 0x2c75, 0x2d41, 0x2e0a, 0x2ece, 0x2f90, 0x304d, 0x3107, 0x31bd, 0x326f, 0x331d, 0x33c7, 0x346d, 0x350f, 0x35ad, 0x3646, 0x36dc,
0x376d, 0x37fa, 0x3882, 0x3906, 0x3986, 0x3a01, 0x3a78, 0x3aea, 0x3b57, 0x3bc0, 0x3c24, 0x3c83, 0x3cde, 0x3d34, 0x3d85, 0x3dd2, 0x3e19, 0x3e5c, 0x3e9a, 0x3ed3,
0x3f07, 0x3f36, 0x3f61, 0x3f86, 0x3fa6, 0x3fc2, 0x3fd8, 0x3fea, 0x3ff6, 0x3ffe, 0x4000
};
for(int a = 90; a-- > 0; )
{
x[a] = (short) sin[90 - a];
x[a + 90] = (short) -sin[a];
x[a + 180] = (short) -sin[90 - a];
x[a + 270] = (short) sin[a];
y[a] = (short) -sin[a];
y[a + 90] = (short) -sin[90 - a];
y[a + 180] = (short) sin[a];
y[a + 270] = (short) sin[90 - a];
}
}
private static int directGraphicsToRasterCanvasTransform(int transform) {
switch(transform)
{
case 0:
case FLIP_HORIZONTAL | FLIP_VERTICAL | ROTATE_180:
return RasterCanvas.TRANSFORM_NONE;
case ROTATE_270:
case FLIP_HORIZONTAL | FLIP_VERTICAL | ROTATE_90:
return RasterCanvas.TRANSFORM_ROTATE_90;
case ROTATE_180:
case FLIP_HORIZONTAL | FLIP_VERTICAL | 0:
return RasterCanvas.TRANSFORM_ROTATE_180;
case ROTATE_90:
case FLIP_HORIZONTAL | FLIP_VERTICAL | ROTATE_270:
return RasterCanvas.TRANSFORM_ROTATE_270;
case FLIP_HORIZONTAL | 0:
case FLIP_VERTICAL | ROTATE_180:
return RasterCanvas.TRANSFORM_MIRROR;
case FLIP_HORIZONTAL | ROTATE_90:
case FLIP_VERTICAL | ROTATE_270:
return RasterCanvas.TRANSFORM_MIRROR_ROTATE_90;
case FLIP_HORIZONTAL | ROTATE_180:
case FLIP_VERTICAL | 0:
return RasterCanvas.TRANSFORM_MIRROR_ROTATE_180;
case FLIP_HORIZONTAL | ROTATE_270:
case FLIP_VERTICAL | ROTATE_90:
return RasterCanvas.TRANSFORM_MIRROR_ROTATE_270;
default:
return -1;
}
}
private static int spriteToRasterCanvasTransform(int transform) {
switch(transform)
{
case Sprite.TRANS_NONE:
return RasterCanvas.TRANSFORM_NONE;
case Sprite.TRANS_ROT90:
return RasterCanvas.TRANSFORM_ROTATE_90;
case Sprite.TRANS_ROT180:
return RasterCanvas.TRANSFORM_ROTATE_180;
case Sprite.TRANS_ROT270:
return RasterCanvas.TRANSFORM_ROTATE_270;
case Sprite.TRANS_MIRROR:
return RasterCanvas.TRANSFORM_MIRROR;
case Sprite.TRANS_MIRROR_ROT90:
return RasterCanvas.TRANSFORM_MIRROR_ROTATE_90;
case Sprite.TRANS_MIRROR_ROT180:
return RasterCanvas.TRANSFORM_MIRROR_ROTATE_180;
case Sprite.TRANS_MIRROR_ROT270:
return RasterCanvas.TRANSFORM_MIRROR_ROTATE_270;
default:
return -1;
}
}
final int width;
final int height;
private int stroke;
private Font font;
private final TextPaint paint;
private final RasterBuffer buffer;
private final RasterCanvas canvas;
Graphics(RasterBuffer buffer) {
int width;
int height;
Font font;
this.width = width = buffer.getWidth();
this.height = height = buffer.getHeight();
this.font = font = Font.getDefaultFont();
this.paint = new TextPaint(width, height, 0xff000000, true, font.getSystemFont(), font.isUnderlined(), false);
this.buffer = buffer;
this.canvas = new RasterCanvas(buffer);
}
public void drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int colorARGB) {
Paint p;
if((p = paint).getColor() != colorARGB)
{
int tx;
int ty;
p = new Paint(tx = p.getTranslateX(), ty = p.getTranslateY(), p.getLeft() - tx, p.getTop() - ty, p.getWidth(), p.getHeight(), colorARGB, true);
}
canvas.drawCustom(new OutlinedTriangle(x1, y1, x2, y2, x3, y3), 0, 0, p);
}
public void drawPolygon(int[] xCoords, int xOffset, int[] yCoords, int yOffset, int length, int colorARGB) {
Paint p;
if(xCoords == null)
{
throw new NullPointerException("DirectGraphics.drawPolygon: аргумент xCoords равен нулевой ссылке.");
}
if(yCoords == null)
{
throw new NullPointerException("DirectGraphics.drawPolygon: аргумент yCoords равен нулевой ссылке.");
}
Array.checkBound("DirectGraphics.drawPolygon", xCoords.length, xOffset, length);
Array.checkBound("DirectGraphics.drawPolygon", yCoords.length, yOffset, length);
if(length > 0)
{
if((p = paint).getColor() != colorARGB)
{
int tx;
int ty;
p = new Paint(tx = p.getTranslateX(), ty = p.getTranslateY(), p.getLeft() - tx, p.getTop() - ty, p.getWidth(), p.getHeight(), colorARGB, true);
}
canvas.drawCustom(new ClosedPolygon(xCoords, xOffset, yCoords, yOffset, length), 0, 0, p);
}
}
public void drawPixels(byte[] pixels, byte[] mask, int offset, int scanlength, int left, int top, int width, int height, int transform, int format) {
int pixelsOffset;
int pixelsLength;
int[] pixelsNative;
RasterBuffer buffer;
switch(format)
{
case TYPE_BYTE_8_GRAY:
case TYPE_BYTE_332_RGB:
if(scanlength >= 0)
{
pixelsOffset = offset;
pixelsLength = width + (height - 1) * scanlength;
} else
{
pixelsOffset = offset + (height - 1) * scanlength;
pixelsLength = width + offset - pixelsOffset;
}
break;
case TYPE_BYTE_1_GRAY_VERTICAL:
case TYPE_BYTE_1_GRAY:
case TYPE_BYTE_2_GRAY:
case TYPE_BYTE_4_GRAY:
throw new IllegalArgumentException("DirectGraphics.drawPixels: форматы, у которых меньше 8 бит на пиксел, не поддерживаются.");
default:
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент format имеет недопустимое значение.");
}
if((transform = directGraphicsToRasterCanvasTransform(transform)) < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент transform имеет недопустимое значение.");
}
if(width < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент width не может быть отрицательным.");
}
if(height < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент height не может быть отрицательным.");
}
if(width == 0 || height == 0) return;
if(pixels == null)
{
throw new NullPointerException("DirectGraphics.drawPixels: аргумент pixels равен нулевой ссылке.");
}
Array.checkBound("DirectGraphics.drawPixels", pixels.length, pixelsOffset, pixelsLength);
if(mask != null) Array.checkBound("DirectGraphics.drawPixels", mask.length, pixelsOffset, pixelsLength);
buffer = RasterBuffer.create(pixelsNative = new int[width * height], 0, width, width, height, false);
switch(format)
{
case TYPE_BYTE_8_GRAY:
/* pixel : yyyy|yyyy */
/* mask : aaaa|aaaa */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
for(int i = 0, j = offset, dj = scanlength - width, cy = height; cy-- > 0; j += dj) for(int cx = width; cx-- > 0; i++, j++)
{
int y = pixels[j] & 0xff;
int a = mask != null ? mask[j] & 0xff : 0xff;
pixelsNative[i] = a << 24 | y << 16 | y << 8 | y;
}
break;
case TYPE_BYTE_332_RGB:
/* pixel : rrrg|ggbb */
/* mask : aaaa|aaaa */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
for(int i = 0, j = offset, dj = scanlength - width, cy = height; cy-- > 0; j += dj) for(int cx = width; cx-- > 0; i++, j++)
{
int p = pixels[j];
int a = mask != null ? mask[j] & 0xff : 0xff;
int r = 0xe0 & p;
int g = 0x1c & p;
int b = 0x03 & p;
pixelsNative[i] = a << 24 | r << 16 | r << 13 | (r & 0xc0) << 10 | g << 11 | g << 8 | (g & 0x18) << 5 | b << 6 | b << 4 | b << 2 | b;
}
break;
}
if((transform & 1) != 0)
{
canvas.drawPixels(buffer, transform, left, top, height, width, paint);
return;
}
canvas.drawPixels(buffer, transform, left, top, width, height, paint);
}
public void drawPixels(short[] pixels, boolean transparency, int offset, int scanlength, int left, int top, int width, int height, int transform, int format) {
int pixelsOffset;
int pixelsLength;
int[] pixelsNative;
RasterBuffer buffer;
switch(format)
{
case TYPE_USHORT_444_RGB:
case TYPE_USHORT_555_RGB:
case TYPE_USHORT_565_RGB:
case TYPE_USHORT_1555_ARGB:
case TYPE_USHORT_4444_ARGB:
if(scanlength >= 0)
{
pixelsOffset = offset;
pixelsLength = width + (height - 1) * scanlength;
} else
{
pixelsOffset = offset + (height - 1) * scanlength;
pixelsLength = width + offset - pixelsOffset;
}
break;
default:
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент format имеет недопустимое значение.");
}
if((transform = directGraphicsToRasterCanvasTransform(transform)) < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент transform имеет недопустимое значение.");
}
if(width < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент width не может быть отрицательным.");
}
if(height < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент height не может быть отрицательным.");
}
if(width == 0 || height == 0) return;
if(pixels == null)
{
throw new NullPointerException("DirectGraphics.drawPixels: аргумент pixels равен нулевой ссылке.");
}
Array.checkBound("DirectGraphics.drawPixels", pixels.length, pixelsOffset, pixelsLength);
buffer = RasterBuffer.create(pixelsNative = new int[width * height], 0, width, width, height, false);
switch(format)
{
case TYPE_USHORT_444_RGB:
/* pixel : ****|rrrr|gggg|bbbb */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
for(int i = 0, j = offset, dj = scanlength - width, cy = height; cy-- > 0; j += dj) for(int cx = width; cx-- > 0; i++, j++)
{
int p = pixels[j];
int r = 0x0f00 & p;
int g = 0x00f0 & p;
int b = 0x000f & p;
pixelsNative[i] = 0xff000000 | r << 12 | r << 8 | g << 8 | g << 4 | b << 4 | b;
}
break;
case TYPE_USHORT_555_RGB:
/* pixel : *rrr|rrgg|gggb|bbbb */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
for(int i = 0, j = offset, dj = scanlength - width, cy = height; cy-- > 0; j += dj) for(int cx = width; cx-- > 0; i++, j++)
{
int p = pixels[j];
int r = 0x7c00 & p;
int g = 0x03e0 & p;
int b = 0x001f & p;
pixelsNative[i] = 0xff000000 | r << 9 | (r & 0x7000) << 4 | g << 6 | (g & 0x0380) << 1 | b << 3 | (b & 0x001c) >> 2;
}
break;
case TYPE_USHORT_565_RGB:
/* pixel : rrrr|rggg|gggb|bbbb */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
for(int i = 0, j = offset, dj = scanlength - width, cy = height; cy-- > 0; j += dj) for(int cx = width; cx-- > 0; i++, j++)
{
int p = pixels[j];
int r = 0xf800 & p;
int g = 0x07e0 & p;
int b = 0x001f & p;
pixelsNative[i] = 0xff000000 | r << 8 | (r & 0xe000) << 3 | g << 5 | (g & 0x0600) >> 1 | b << 3 | (b & 0x001c) >> 2;
}
break;
case TYPE_USHORT_1555_ARGB:
/* pixel : arrr|rrgg|gggb|bbbb */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
for(int i = 0, j = offset, dj = scanlength - width, cy = height; cy-- > 0; j += dj) for(int cx = width; cx-- > 0; i++, j++)
{
int p = pixels[j];
int a = 0x8000 & p;
int r = 0x7c00 & p;
int g = 0x03e0 & p;
int b = 0x001f & p;
pixelsNative[i] = a << 16 >> 7 | r << 9 | (r & 0x7000) << 4 | g << 6 | (g & 0x0380) << 1 | b << 3 | (b & 0x001c) >> 2;
}
break;
case TYPE_USHORT_4444_ARGB:
/* pixel : aaaa|rrrr|gggg|bbbb */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
for(int i = 0, j = offset, dj = scanlength - width, cy = height; cy-- > 0; j += dj) for(int cx = width; cx-- > 0; i++, j++)
{
int p = pixels[j];
int a = 0xf000 & p;
int r = 0x0f00 & p;
int g = 0x00f0 & p;
int b = 0x000f & p;
pixelsNative[i] = a << 16 | a << 12 | r << 12 | r << 8 | g << 8 | g << 4 | b << 4 | b;
}
break;
}
if((transform & 1) != 0)
{
if(transparency)
{
canvas.drawPixels(buffer, transform, left, top, height, width, paint);
return;
}
canvas.copyPixels(buffer, transform, left, top, height, width, paint);
return;
}
if(transparency)
{
canvas.drawPixels(buffer, transform, left, top, width, height, paint);
return;
}
canvas.copyPixels(buffer, transform, left, top, width, height, paint);
}
public void drawPixels(int[] pixels, boolean transparency, int offset, int scanlength, int left, int top, int width, int height, int transform, int format) {
int pixelsOffset;
int pixelsLength;
RasterBuffer buffer;
switch(format)
{
case TYPE_INT_888_RGB:
case TYPE_INT_8888_ARGB:
if(scanlength >= 0)
{
pixelsOffset = offset;
pixelsLength = width + (height - 1) * scanlength;
} else
{
pixelsOffset = offset + (height - 1) * scanlength;
pixelsLength = width + offset - pixelsOffset;
}
break;
default:
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент format имеет недопустимое значение.");
}
if((transform = directGraphicsToRasterCanvasTransform(transform)) < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент transform имеет недопустимое значение.");
}
if(width < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент width не может быть отрицательным.");
}
if(height < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawPixels: аргумент height не может быть отрицательным.");
}
if(width == 0 || height == 0) return;
if(pixels == null)
{
throw new NullPointerException("DirectGraphics.drawPixels: аргумент pixels равен нулевой ссылке.");
}
Array.checkBound("DirectGraphics.drawPixels", pixels.length, pixelsOffset, pixelsLength);
buffer = RasterBuffer.create(pixels, offset, scanlength, width, height, format == TYPE_INT_888_RGB);
if((transform & 1) != 0)
{
if(transparency)
{
canvas.drawPixels(buffer, transform, left, top, height, width, paint);
return;
}
canvas.copyPixels(buffer, transform, left, top, height, width, paint);
return;
}
if(transparency)
{
canvas.drawPixels(buffer, transform, left, top, width, height, paint);
return;
}
canvas.copyPixels(buffer, transform, left, top, width, height, paint);
}
public void drawImage(Image image, int x, int y, int anchor, int transform) {
int width;
int height;
if(image == null)
{
throw new NullPointerException("DirectGraphics.drawImage: аргумент image равен нулевой ссылке.");
}
if((transform = directGraphicsToRasterCanvasTransform(transform)) < 0)
{
throw new IllegalArgumentException("DirectGraphics.drawImage: аргумент transform имеет недопустимое значение.");
}
if((transform & 1) != 0)
{
width = image.height;
height = image.width;
} else
{
width = image.width;
height = image.height;
}
switch(anchor)
{
case 0:
case TOP | LEFT:
break;
case TOP | HCENTER:
x -= width >> 1;
break;
case TOP | RIGHT:
x -= width;
break;
case VCENTER | LEFT:
y -= height >> 1;
break;
case VCENTER | HCENTER:
x -= width >> 1;
y -= height >> 1;
break;
case VCENTER | RIGHT:
x -= width;
y -= height >> 1;
break;
case BOTTOM | LEFT:
y -= height;
break;
case BOTTOM | HCENTER:
x -= width >> 1;
y -= height;
break;
case BOTTOM | RIGHT:
x -= width;
y -= height;
break;
default:
throw new IllegalArgumentException("DirectGraphics.drawImage: аргумент anchor имеет недопустимое значение.");
}
canvas.drawPixels(image.buffer, transform, x, y, width, height, paint);
}
public void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int colorARGB) {
Paint p;
if((p = paint).getColor() != colorARGB)
{
int tx;
int ty;
p = new Paint(tx = p.getTranslateX(), ty = p.getTranslateY(), p.getLeft() - tx, p.getTop() - ty, p.getWidth(), p.getHeight(), colorARGB, true);
}
canvas.drawCustom(new FilledTriangle(x1, y1, x2, y2, x3, y3), 0, 0, p);
}
public void fillPolygon(int[] xCoords, int xOffset, int[] yCoords, int yOffset, int length, int colorARGB) {
Paint p;
if(xCoords == null)
{
throw new NullPointerException("DirectGraphics.fillPolygon: аргумент xCoords равен нулевой ссылке.");
}
if(yCoords == null)
{
throw new NullPointerException("DirectGraphics.fillPolygon: аргумент yCoords равен нулевой ссылке.");
}
Array.checkBound("DirectGraphics.fillPolygon", xCoords.length, xOffset, length);
Array.checkBound("DirectGraphics.fillPolygon", yCoords.length, yOffset, length);
if(length > 0)
{
if((p = paint).getColor() != colorARGB)
{
int tx;
int ty;
p = new Paint(tx = p.getTranslateX(), ty = p.getTranslateY(), p.getLeft() - tx, p.getTop() - ty, p.getWidth(), p.getHeight(), colorARGB, true);
}
canvas.drawCustom(new FilledPolygon(xCoords, xOffset, yCoords, yOffset, length), 0, 0, p);
}
}
public void setARGBColor(int colorARGB) {
paint.setColor(colorARGB);
}
public void getPixels(byte[] pixels, byte[] mask, int offset, int scanlength, int left, int top, int width, int height, int format) {
boolean srcOpaque;
int pixelsOffset;
int pixelsLength;
int srcOffset;
int srcScanln;
int[] srcPixels;
RasterBuffer srcBuffer;
Clip clip;
switch(format)
{
case TYPE_BYTE_8_GRAY:
case TYPE_BYTE_332_RGB:
if(scanlength >= 0)
{
pixelsOffset = offset;
pixelsLength = width + (height - 1) * scanlength;
} else
{
pixelsOffset = offset + (height - 1) * scanlength;
pixelsLength = width + offset - pixelsOffset;
}
break;
case TYPE_BYTE_1_GRAY_VERTICAL:
case TYPE_BYTE_1_GRAY:
case TYPE_BYTE_2_GRAY:
case TYPE_BYTE_4_GRAY:
throw new IllegalArgumentException("DirectGraphics.getPixels: форматы, у которых меньше 8 бит на пиксел, не поддерживаются.");
default:
throw new IllegalArgumentException("DirectGraphics.getPixels: аргумент format имеет недопустимое значение.");
}
if(width < 0)
{
throw new IllegalArgumentException("DirectGraphics.getPixels: аргумент width не может быть отрицательным.");
}
if(height < 0)
{
throw new IllegalArgumentException("DirectGraphics.getPixels: аргумент height не может быть отрицательным.");
}
if(width == 0 || height == 0) return;
if(pixels == null)
{
throw new NullPointerException("DirectGraphics.getPixels: аргумент pixels равен нулевой ссылке.");
}
Array.checkBound("DirectGraphics.getPixels", pixels.length, pixelsOffset, pixelsLength);
if(mask != null) Array.checkBound("DirectGraphics.getPixels", mask.length, pixelsOffset, pixelsLength);
check("DirectGraphics.getPixels", left += (clip = paint).getTranslateX(), top += clip.getTranslateY(), width, height);
srcBuffer = buffer;
srcOpaque = srcBuffer.isOpaque();
srcPixels = srcBuffer.getPixels();
srcOffset = srcBuffer.getOffset();
srcScanln = srcBuffer.getScanlength();
switch(format)
{
case TYPE_BYTE_8_GRAY:
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* pixel : yyyy|yyyy */
/* mask : aaaa|aaaa */
for(int i = offset, di = scanlength - width, j = srcOffset + left + top * srcScanln, dj = srcScanln - width, cy = height; cy-- > 0; i += di, j += dj)
{
for(int cx = width; cx-- > 0; i++, j++)
{
int p = srcPixels[j];
pixels[i] = (byte) ((76 * ((p >> 16) & 0xff) + 152 * ((p >> 8) & 0xff) + 28 * (p & 0xff)) >> 8);
if(mask != null) mask[i] = srcOpaque ? (byte) 0xff : (byte) (p >> 24);
}
}
break;
case TYPE_BYTE_332_RGB:
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* pixel : rrrg|ggbb */
/* mask : aaaa|aaaa */
for(int i = offset, di = scanlength - width, j = srcOffset + left + top * srcScanln, dj = srcScanln - width, cy = height; cy-- > 0; i += di, j += dj)
{
for(int cx = width; cx-- > 0; i++, j++)
{
int p = srcPixels[j];
pixels[i] = (byte) ((p >> 16) & 0xe0 | (p >> 11) & 0x1c | (p >> 6) & 0x03);
if(mask != null) mask[i] = srcOpaque ? (byte) 0xff : (byte) (p >> 24);
}
}
break;
}
}
public void getPixels(short[] pixels, int offset, int scanlength, int left, int top, int width, int height, int format) {
boolean srcOpaque;
int pixelsOffset;
int pixelsLength;
int srcOffset;
int srcScanln;
int[] srcPixels;
RasterBuffer srcBuffer;
Clip clip;
switch(format)
{
case TYPE_USHORT_444_RGB:
case TYPE_USHORT_555_RGB:
case TYPE_USHORT_565_RGB:
case TYPE_USHORT_1555_ARGB:
case TYPE_USHORT_4444_ARGB:
if(scanlength >= 0)
{
pixelsOffset = offset;
pixelsLength = width + (height - 1) * scanlength;
} else
{
pixelsOffset = offset + (height - 1) * scanlength;
pixelsLength = width + offset - pixelsOffset;
}
break;
default:
throw new IllegalArgumentException("DirectGraphics.getPixels: аргумент format имеет недопустимое значение.");
}
if(width < 0)
{
throw new IllegalArgumentException("DirectGraphics.getPixels: аргумент width не может быть отрицательным.");
}
if(height < 0)
{
throw new IllegalArgumentException("DirectGraphics.getPixels: аргумент height не может быть отрицательным.");
}
if(width == 0 || height == 0) return;
if(pixels == null)
{
throw new NullPointerException("DirectGraphics.getPixels: аргумент pixels равен нулевой ссылке.");
}
Array.checkBound("DirectGraphics.getPixels", pixels.length, pixelsOffset, pixelsLength);
check("DirectGraphics.getPixels", left += (clip = paint).getTranslateX(), top += clip.getTranslateY(), width, height);
srcBuffer = buffer;
srcOpaque = srcBuffer.isOpaque();
srcPixels = srcBuffer.getPixels();
srcOffset = srcBuffer.getOffset();
srcScanln = srcBuffer.getScanlength();
switch(format)
{
case TYPE_USHORT_444_RGB:
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* pixel : 0000|rrrr|gggg|bbbb */
for(int i = offset, di = scanlength - width, j = srcOffset + left + top * srcScanln, dj = srcScanln - width, cy = height; cy-- > 0; i += di, j += dj)
{
for(int cx = width; cx-- > 0; i++, j++)
{
int p = srcPixels[j];
pixels[i] = (short) ((p >> 12) & 0x0f00 | (p >> 8) & 0x00f0 | (p >> 4) & 0x000f);
}
}
break;
case TYPE_USHORT_555_RGB:
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* pixel : 0rrr|rrgg|gggb|bbbb */
for(int i = offset, di = scanlength - width, j = srcOffset + left + top * srcScanln, dj = srcScanln - width, cy = height; cy-- > 0; i += di, j += dj)
{
for(int cx = width; cx-- > 0; i++, j++)
{
int p = srcPixels[j];
pixels[i] = (short) ((p >> 9) & 0x7c00 | (p >> 6) & 0x03e0 | (p >> 3) & 0x001f);
}
}
break;
case TYPE_USHORT_565_RGB:
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* pixel : rrrr|rggg|gggb|bbbb */
for(int i = offset, di = scanlength - width, j = srcOffset + left + top * srcScanln, dj = srcScanln - width, cy = height; cy-- > 0; i += di, j += dj)
{
for(int cx = width; cx-- > 0; i++, j++)
{
int p = srcPixels[j];
pixels[i] = (short) ((p >> 8) & 0xf800 | (p >> 5) & 0x07e0 | (p >> 3) & 0x001f);
}
}
break;
case TYPE_USHORT_1555_ARGB:
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* pixel : arrr|rrgg|gggb|bbbb */
for(int i = offset, di = scanlength - width, j = srcOffset + left + top * srcScanln, dj = srcScanln - width, cy = height; cy-- > 0; i += di, j += dj)
{
for(int cx = width; cx-- > 0; i++, j++)
{
int p = srcPixels[j];
pixels[i] = (short) ((srcOpaque ? 0x8000 : (p >> 16) & 0x8000) | (p >> 9) & 0x7c00 | (p >> 6) & 0x03e0 | (p >> 3) & 0x001f);
}
}
break;
case TYPE_USHORT_4444_ARGB:
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* pixel : aaaa|rrrr|gggg|bbbb */
for(int i = offset, di = scanlength - width, j = srcOffset + left + top * srcScanln, dj = srcScanln - width, cy = height; cy-- > 0; i += di, j += dj)
{
for(int cx = width; cx-- > 0; i++, j++)
{
int p = srcPixels[j];
pixels[i] = (short) ((srcOpaque ? 0xf000 : (p >> 16) & 0xf000) | (p >> 12) & 0x0f00 | (p >> 8) & 0x00f0 | (p >> 4) & 0x000f);
}
}
break;
}
}
public void getPixels(int[] pixels, int offset, int scanlength, int left, int top, int width, int height, int format) {
boolean srcOpaque;
int pixelsOffset;
int pixelsLength;
int srcOffset;
int srcScanln;
int[] srcPixels;
RasterBuffer srcBuffer;
Clip clip;
switch(format)
{
case TYPE_INT_888_RGB:
case TYPE_INT_8888_ARGB:
if(scanlength >= 0)
{
pixelsOffset = offset;
pixelsLength = width + (height - 1) * scanlength;
} else
{
pixelsOffset = offset + (height - 1) * scanlength;
pixelsLength = width + offset - pixelsOffset;
}
break;
default:
throw new IllegalArgumentException("DirectGraphics.getPixels: аргумент format имеет недопустимое значение.");
}
if(width < 0)
{
throw new IllegalArgumentException("DirectGraphics.getPixels: аргумент width не может быть отрицательным.");
}
if(height < 0)
{
throw new IllegalArgumentException("DirectGraphics.getPixels: аргумент height не может быть отрицательным.");
}
if(width == 0 || height == 0) return;
if(pixels == null)
{
throw new NullPointerException("DirectGraphics.getPixels: аргумент pixels равен нулевой ссылке.");
}
Array.checkBound("DirectGraphics.getPixels", pixels.length, pixelsOffset, pixelsLength);
check("DirectGraphics.getPixels", left += (clip = paint).getTranslateX(), top += clip.getTranslateY(), width, height);
srcBuffer = buffer;
srcOpaque = srcBuffer.isOpaque();
srcPixels = srcBuffer.getPixels();
srcOffset = srcBuffer.getOffset();
srcScanln = srcBuffer.getScanlength();
switch(format)
{
case TYPE_INT_888_RGB:
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* pixel : 0000|0000|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
for(int i = offset, di = scanlength - width, j = srcOffset + left + top * srcScanln, dj = srcScanln - width, cy = height; cy-- > 0; i += di, j += dj)
{
for(int cx = width; cx-- > 0; i++, j++)
{
int p = srcPixels[j];
pixels[i] = p & 0x00ffffff;
}
}
break;
case TYPE_INT_8888_ARGB:
/* bits : 28| 24| 20| 16| 12| 8| 4| 0 */
/* native : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
/* pixel : aaaa|aaaa|rrrr|rrrr|gggg|gggg|bbbb|bbbb */
for(int i = offset, di = scanlength - width, j = srcOffset + left + top * srcScanln, dj = srcScanln - width, cy = height; cy-- > 0; i += di, j += dj)
{
for(int cx = width; cx-- > 0; i++, j++)
{
int p = srcPixels[j];
pixels[i] = srcOpaque ? p | 0xff000000 : p;
}
}
break;
}
}
public int getAlphaComponent() {
return paint.getAlphaComponent();
}
public int getNativePixelFormat() {
return buffer.isOpaque() ? TYPE_INT_888_RGB : TYPE_INT_8888_ARGB;
}
public void copyArea(int left, int top, int width, int height, int x, int y, int anchor) {
Clip clip;
check("Graphics.copyArea", left += (clip = paint).getTranslateX(), top += clip.getTranslateY(), width, height);
switch(anchor)
{
case 0:
case TOP | LEFT:
break;
case TOP | HCENTER:
x -= width >> 1;
break;
case TOP | RIGHT:
x -= width;
break;
case VCENTER | LEFT:
y -= height >> 1;
break;
case VCENTER | HCENTER:
x -= width >> 1;
y -= height >> 1;
break;
case VCENTER | RIGHT:
x -= width;
y -= height >> 1;
break;
case BOTTOM | LEFT:
y -= height;
break;
case BOTTOM | HCENTER:
x -= width >> 1;
y -= height;
break;
case BOTTOM | RIGHT:
x -= width;
y -= height;
break;
default:
throw new IllegalArgumentException("Graphics.copyArea: аргумент anchor имеет недопустимое значение.");
}
canvas.copyPixels(RasterBuffer.create(buffer, left, top, width, height), RasterCanvas.TRANSFORM_NONE, x, y, width, height, clip);
}
public void drawElement(int type, int subtype, int state, int left, int top, int width, int height) {
canvas.drawGUIElement(type, subtype, state, left, top, width, height, paint);
}
public void drawLine(int x1, int y1, int x2, int y2) {
if(x1 == x2 && y1 == y2)
{
canvas.drawPixel(x1, y1, paint);
return;
}
canvas.drawCustom(new Line(x1, y1, x2, y2), 0, 0, paint);
}
public void drawArc(int left, int top, int width, int height, int startAngle, int arcAngle) {
int angle;
int stepAngle;
int length;
int yStart;
long xnSize;
long ynSize;
long xmSize;
long ymSize;
int[] coords;
if(width < 0 || height < 0) return;
if(startAngle < 0) startAngle += 360 * (startAngle / (-360) + 1);
startAngle %= 360;
if(arcAngle > 360) arcAngle = 360;
if(arcAngle < -360) arcAngle = -360;
if(arcAngle < 0)
{
startAngle = (startAngle + arcAngle + 360) % 360;
arcAngle = -arcAngle;
}
angle = startAngle;
stepAngle = (stepAngle = width < height ? height + 1 : width + 1) >= 180 || stepAngle == Integer.MIN_VALUE ? 1 : 180 / stepAngle;
length = arcAngle / stepAngle + 1;
xnSize = (long) width;
ynSize = (long) height;
xmSize = xnSize << 14;
ymSize = ynSize << 14;
coords = new int[(yStart = length + 1) << 1];
for(int x = 0, y = yStart; x < length; angle += stepAngle, x++, y++)
{
coords[x] = (int) (xmSize + xnSize * (long) XTABLE[angle % 360] + 0x4000L >> 15);
coords[y] = (int) (ymSize + ynSize * (long) YTABLE[angle % 360] + 0x4000L >> 15);
}
if((angle - stepAngle) < (angle = startAngle + arcAngle))
{
coords[length] = (int) (xmSize + xnSize * (long) XTABLE[angle % 360] + 0x4000L >> 15);
coords[length++ + yStart] = (int) (ymSize + ynSize * (long) YTABLE[angle % 360] + 0x4000L >> 15);
}
canvas.drawCustom(new OpenedPolygon(coords, 0, coords, yStart, length), left, top, paint);
}
public void drawRect(int left, int top, int width, int height) {
if(width >= 0 && height >= 0) canvas.drawCustom(new OutlinedRectangle(width, height), left, top, paint);
}
public void drawRoundRect(int left, int top, int width, int height, int arcWidth, int arcHeight) {
if(width >= 0 && height >= 0) canvas.drawCustom(new OutlinedRoundRect(width, height, arcWidth, arcHeight), left, top, paint);
}
public void drawRGB(int[] pixels, int offset, int scanlength, int left, int top, int width, int height, boolean alpha) {
int pixelsOffset;
int pixelsLength;
RasterBuffer buffer;
if(scanlength >= 0)
{
pixelsOffset = offset;
pixelsLength = width + (height - 1) * scanlength;
} else
{
pixelsOffset = offset + (height - 1) * scanlength;
pixelsLength = width + offset - pixelsOffset;
}
if(width <= 0 || height <= 0) return;
if(pixels == null)
{
throw new NullPointerException("Graphics.drawRGB: аргумент pixels равен нулевой ссылке.");
}
Array.checkBound("Graphics.drawRGB", pixels.length, pixelsOffset, pixelsLength);
buffer = RasterBuffer.create(pixels, offset, scanlength, width, height, !alpha);
canvas.drawPixels(buffer, RasterCanvas.TRANSFORM_NONE, left, top, width, height, paint);
}
public void drawImage(Image image, int x, int y, int anchor) {
int width;
int height;
if(image == null)
{
throw new NullPointerException("Graphics.drawImage: аргумент image равен нулевой ссылке.");
}
width = image.width;
height = image.height;
switch(anchor)
{
case 0:
case TOP | LEFT:
break;
case TOP | HCENTER:
x -= width >> 1;
break;
case TOP | RIGHT:
x -= width;
break;
case VCENTER | LEFT:
y -= height >> 1;
break;
case VCENTER | HCENTER:
x -= width >> 1;
y -= height >> 1;
break;
case VCENTER | RIGHT:
x -= width;
y -= height >> 1;
break;
case BOTTOM | LEFT:
y -= height;
break;
case BOTTOM | HCENTER:
x -= width >> 1;
y -= height;
break;
case BOTTOM | RIGHT:
x -= width;
y -= height;
break;
default:
throw new IllegalArgumentException("Graphics.drawImage: аргумент anchor имеет недопустимое значение.");
}
canvas.drawPixels(image.buffer, RasterCanvas.TRANSFORM_NONE, x, y, width, height, paint);
}
public void drawStretch(Image image, int x, int y, int width, int height, int anchor) {
if(image == null)
{
throw new NullPointerException("Graphics.drawStretch: аргумент image равен нулевой ссылке.");
}
if(width <= 0 || height <= 0) return;
switch(anchor)
{
case 0:
case TOP | LEFT:
break;
case TOP | HCENTER:
x -= width >> 1;
break;
case TOP | RIGHT:
x -= width;
break;
case VCENTER | LEFT:
y -= height >> 1;
break;
case VCENTER | HCENTER:
x -= width >> 1;
y -= height >> 1;
break;
case VCENTER | RIGHT:
x -= width;
y -= height >> 1;
break;
case BOTTOM | LEFT:
y -= height;
break;
case BOTTOM | HCENTER:
x -= width >> 1;
y -= height;
break;
case BOTTOM | RIGHT:
x -= width;
y -= height;
break;
default:
throw new IllegalArgumentException("Graphics.drawStretch: аргумент anchor имеет недопустимое значение.");
}
canvas.drawPixels(image.buffer, RasterCanvas.TRANSFORM_NONE, x, y, width, height, paint);
}
public void drawRegion(Image image, int left, int top, int width, int height, int transform, int x, int y, int anchor) {
int w;
int h;
int lim;
int len;
if(image == null)
{
throw new NullPointerException("Graphics.drawRegion: аргумент image равен нулевой ссылке.");
}
if((lim = left + width) > (len = image.width) || lim < left || left > len || left < 0 || (lim = top + height) > (len = image.height) || lim < top || top > len || top < 0)
{
throw new IllegalArgumentException("Graphics.drawRegion: заданный регион выходит за пределы изображения.");
}
if((transform = spriteToRasterCanvasTransform(transform)) < 0)
{
throw new IllegalArgumentException("Graphics.drawRegion: аргумент transform имеет недопустимое значение.");
}
if((transform & 1) != 0)
{
w = height;
h = width;
} else
{
w = width;
h = height;
}
switch(anchor)
{
case 0:
case TOP | LEFT:
break;
case TOP | HCENTER:
x -= w >> 1;
break;
case TOP | RIGHT:
x -= w;
break;
case VCENTER | LEFT:
y -= h >> 1;
break;
case VCENTER | HCENTER:
x -= w >> 1;
y -= h >> 1;
break;
case VCENTER | RIGHT:
x -= w;
y -= h >> 1;
break;
case BOTTOM | LEFT:
y -= h;
break;
case BOTTOM | HCENTER:
x -= w >> 1;
y -= h;
break;
case BOTTOM | RIGHT:
x -= w;
y -= h;
break;
default:
throw new IllegalArgumentException("Graphics.drawRegion: аргумент anchor имеет недопустимое значение.");
}
if(w > 0 && h > 0) canvas.drawPixels(image.buffer, left, top, width, height, transform, x, y, w, h, paint);
}
public void drawChar(char character, int x, int y, int anchor) {
int width;
TextPaint p;
SystemFont font;
width = (font = (p = paint).getFont()).characterWidth(character);
switch(anchor)
{
case BASELINE | LEFT:
break;
case BASELINE | HCENTER:
x -= width >> 1;
break;
case BASELINE | RIGHT:
x -= width;
break;
case 0:
case TOP | LEFT:
y += font.getBaselinePosition();
break;
case TOP | HCENTER:
x -= width >> 1;
y += font.getBaselinePosition();
break;
case TOP | RIGHT:
x -= width;
y += font.getBaselinePosition();
break;
case BOTTOM | LEFT:
y -= font.getBaselineHeight();
break;
case BOTTOM | HCENTER:
x -= width >> 1;
y -= font.getBaselineHeight();
break;
case BOTTOM | RIGHT:
x -= width;
y -= font.getBaselineHeight();
break;
default:
throw new IllegalArgumentException("Graphics.drawChar: аргумент anchor имеет недопустимое значение.");
}
canvas.drawCharacter(character, x, y, p);
}
public void drawChars(char[] src, int offset, int length, int x, int y, int anchor) {
int width;
TextPaint p;
SystemFont font;
width = (font = (p = paint).getFont()).charactersWidth(src, offset, length);
switch(anchor)
{
case BASELINE | LEFT:
break;
case BASELINE | HCENTER:
x -= width >> 1;
break;
case BASELINE | RIGHT:
x -= width;
break;
case 0:
case TOP | LEFT:
y += font.getBaselinePosition();
break;
case TOP | HCENTER:
x -= width >> 1;
y += font.getBaselinePosition();
break;
case TOP | RIGHT:
x -= width;
y += font.getBaselinePosition();
break;
case BOTTOM | LEFT:
y -= font.getBaselineHeight();
break;
case BOTTOM | HCENTER:
x -= width >> 1;
y -= font.getBaselineHeight();
break;
case BOTTOM | RIGHT:
x -= width;
y -= font.getBaselineHeight();
break;
default:
throw new IllegalArgumentException("Graphics.drawChars: аргумент anchor имеет недопустимое значение.");
}
canvas.drawCharacters(src, offset, length, x, y, p);
}
public void drawString(String string, int x, int y, int anchor) {
int width;
TextPaint p;
SystemFont font;
width = (font = (p = paint).getFont()).stringWidth(string);
switch(anchor)
{
case BASELINE | LEFT:
break;
case BASELINE | HCENTER:
x -= width >> 1;
break;
case BASELINE | RIGHT:
x -= width;
break;
case 0:
case TOP | LEFT:
y += font.getBaselinePosition();
break;
case TOP | HCENTER:
x -= width >> 1;
y += font.getBaselinePosition();
break;
case TOP | RIGHT:
x -= width;
y += font.getBaselinePosition();
break;
case BOTTOM | LEFT:
y -= font.getBaselineHeight();
break;
case BOTTOM | HCENTER:
x -= width >> 1;
y -= font.getBaselineHeight();
break;
case BOTTOM | RIGHT:
x -= width;
y -= font.getBaselineHeight();
break;
default:
throw new IllegalArgumentException("Graphics.drawString: аргумент anchor имеет недопустимое значение.");
}
canvas.drawString(string, x, y, p);
}
public void drawSubstring(String string, int offset, int length, int x, int y, int anchor) {
int width;
TextPaint p;
SystemFont font;
width = (font = (p = paint).getFont()).substringWidth(string, offset, length);
switch(anchor)
{
case BASELINE | LEFT:
break;
case BASELINE | HCENTER:
x -= width >> 1;
break;
case BASELINE | RIGHT:
x -= width;
break;
case 0:
case TOP | LEFT:
y += font.getBaselinePosition();
break;
case TOP | HCENTER:
x -= width >> 1;
y += font.getBaselinePosition();
break;
case TOP | RIGHT:
x -= width;
y += font.getBaselinePosition();
break;
case BOTTOM | LEFT:
y -= font.getBaselineHeight();
break;
case BOTTOM | HCENTER:
x -= width >> 1;
y -= font.getBaselineHeight();
break;
case BOTTOM | RIGHT:
x -= width;
y -= font.getBaselineHeight();
break;
default:
throw new IllegalArgumentException("Graphics.drawSubstring: аргумент anchor имеет недопустимое значение.");
}
canvas.drawSubstring(string, offset, length, x, y, p);
}
public void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
canvas.drawCustom(new FilledTriangle(x1, y1, x2, y2, x3, y3), 0, 0, paint);
}
public void fillArc(int left, int top, int width, int height, int startAngle, int arcAngle) {
int stepAngle;
int length;
int yStart;
long xnSize;
long ynSize;
long xmSize;
long ymSize;
int[] coords;
if(width <= 0 || height <= 0) return;
if(startAngle < 0) startAngle += 360 * (startAngle / (-360) + 1);
startAngle %= 360;
if(arcAngle > 360) arcAngle = 360;
if(arcAngle < -360) arcAngle = -360;
if(arcAngle < 0)
{
startAngle = (startAngle + arcAngle + 360) % 360;
arcAngle = -arcAngle;
}
stepAngle = (stepAngle = width < height ? height : width) >= 180 ? 1 : 180 / stepAngle;
length = arcAngle / stepAngle + 2;
xnSize = (long) width;
ynSize = (long) height;
xmSize = xnSize << 14;
ymSize = ynSize << 14;
coords = new int[length << 1];
for(int a = startAngle, x = 0, y = yStart = length--; x < length; a = (a + stepAngle) % 360, x++, y++)
{
coords[x] = (int) (xmSize + xnSize * (long) XTABLE[a] + 0x4000L >> 15);
coords[y] = (int) (ymSize + ynSize * (long) YTABLE[a] + 0x4000L >> 15);
}
if(arcAngle < 360)
{
coords[length] = (int) (xmSize + 0x4000L >> 15);
coords[length++ + yStart] = (int) (ymSize + 0x4000L >> 15);
}
canvas.drawCustom(new FilledPolygon(coords, 0, coords, yStart, length), left, top, paint);
}
public void fillRect(int left, int top, int width, int height) {
if(width > 0 && height > 0) canvas.fillRectangle(left, top, width, height, paint);
}
public void fillRoundRect(int left, int top, int width, int height, int arcWidth, int arcHeight) {
if(width > 0 && height > 0) canvas.drawCustom(new FilledRoundRect(width, height, arcWidth, arcHeight), left, top, paint);
}
public void translate(int deltaX, int deltaY) {
Clip c;
synchronized(c = paint)
{
c.translate(deltaX, deltaY);
}
}
public void clipRect(int left, int top, int width, int height) {
Clip c;
synchronized(c = paint)
{
c.clipRect(left, top, width, height);
}
}
public void setClip(int left, int top, int width, int height) {
Clip c;
synchronized(c = paint)
{
c.setClip(left, top, width, height);
bound(c);
}
}
public void setColor(int colorRGB) {
paint.setColor(colorRGB | 0xff000000);
}
public void setColor(int red, int green, int blue) {
if((red & 0xffffff00) != 0)
{
throw new IllegalArgumentException("Graphics.setColor: аргумент red имеет недопустимое значение.");
}
if((green & 0xffffff00) != 0)
{
throw new IllegalArgumentException("Graphics.setColor: аргумент green имеет недопустимое значение.");
}
if((blue & 0xffffff00) != 0)
{
throw new IllegalArgumentException("Graphics.setColor: аргумент blue имеет недопустимое значение.");
}
paint.setColor(red << 0x10 | green << 0x08 | blue | 0xff000000);
}
public void setGrayScale(int gray) {
if((gray & 0xffffff00) != 0)
{
throw new IllegalArgumentException("Graphics.setGrayScale: аргумент gray имеет недопустимое значение.");
}
paint.setColor(gray << 0x10 | gray << 0x08 | gray | 0xff000000);
}
public void setStrokeStyle(int stroke) {
if(stroke < 0 || stroke > 1)
{
throw new IllegalArgumentException("Graphics.setStrokeStyle: аргумент stroke имеет недопустимое значение.");
}
this.stroke = stroke;
}
public void setFont(Font font) {
if(font == null) font = Font.getDefaultFont();
this.font = font;
paint.setFont(font.getSystemFont(), font.isUnderlined(), false);
}
public int getTranslateX() {
return paint.getTranslateX();
}
public int getTranslateY() {
return paint.getTranslateY();
}
public int getClipX() {
return paint.getClipLeft();
}
public int getClipY() {
return paint.getClipTop();
}
public int getClipWidth() {
return paint.getClipWidth();
}
public int getClipHeight() {
return paint.getClipHeight();
}
public int getColor() {
return paint.getColor() & 0x00ffffff;
}
public int getDisplayColor(int colorRGB) {
return colorRGB & 0x00ffffff;
}
public int getRedComponent() {
return paint.getRedComponent();
}
public int getGreenComponent() {
return paint.getGreenComponent();
}
public int getBlueComponent() {
return paint.getBlueComponent();
}
public int getGrayScale() {
int c = paint.getColor();
return (76 * ((c >> 0x10) & 0xff) + 152 * ((c >> 0x08) & 0xff) + 28 * (c & 0xff)) >> 8;
}
public int getStrokeStyle() {
return stroke;
}
public Font getFont() {
return font;
}
void reset() {
Font f;
TextPaint p = paint;
stroke = SOLID;
font = f = Font.getDefaultFont();
p.setFont(f.getSystemFont(), f.isUnderlined(), false);
p.setColor(0xff000000);
synchronized(p)
{
p.translateReset();
p.setClip(0, 0, width, height);
}
}
void bound(Clip clip) {
clip.clipRect(-clip.getTranslateX(), -clip.getTranslateY(), width, height);
}
void check(String method, int left, int top, int width, int height) throws IllegalArgumentException {
int lim;
int len;
if((lim = left + width) > (len = this.width) || lim < left || left > len || left < 0 || (lim = top + height) > (len = this.height) || lim < top || top > len || top < 0)
{
throw new IllegalArgumentException(method.concat(": заданный регион выходит за пределы канвы."));
}
}
}
final class ScreenGraphics extends Graphics
{
private int left;
private int top;
private int width;
private int height;
private int startX;
private int startY;
ScreenGraphics(RasterBuffer buffer) {
super(buffer);
}
public void copyArea(int left, int top, int width, int height, int x, int y, int anchor) {
throw new IllegalStateException("Graphics.copyArea: эта канва представляет собой экран устройства.");
}
public void reset() {
left = 0;
top = 0;
width = super.width;
height = super.height;
startX = 0;
startY = 0;
super.reset();
}
public int getTranslateX() {
return super.getTranslateX() - startX;
}
public int getTranslateY() {
return super.getTranslateY() - startY;
}
public void restricts(int left, int top, int width, int height) {
this.left = left;
this.top = top;
this.width = width;
this.height = height;
}
public void setStartPoint(int startX, int startY) {
this.startX = startX;
this.startY = startY;
}
public int getRestrictedLeft() {
return left;
}
public int getRestrictedTop() {
return top;
}
public int getRestrictedWidth() {
return width;
}
public int getRestrictedHeight() {
return height;
}
public int getStartPointX() {
return startX;
}
public int getStartPointY() {
return startY;
}
void bound(Clip clip) {
clip.clipRect(left - clip.getTranslateX(), top - clip.getTranslateY(), width, height);
}
void check(String method, int left, int top, int width, int height) throws IllegalArgumentException {
int lim;
int len;
int min;
if(
(lim = left + width) > (len = (min = this.left) + this.width) || lim < left || left > len || left < min ||
(lim = top + height) > (len = (min = this.top) + this.height) || lim < top || top > len || top < min
)
{
throw new IllegalArgumentException(method.concat(": заданный регион выходит за пределы канвы."));
}
}
}