/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.awt.util;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.Raster;
import org.apache.log4j.Logger;
import org.jnode.system.resource.MemoryResource;
import org.jnode.system.resource.MultiMediaMemoryResource;
public abstract class AbstractBitmapGraphics extends BitmapGraphics {
protected final int bytesPerLine;
protected final int height;
/**
* My logger
*/
protected static final Logger log = Logger.getLogger(AbstractBitmapGraphics.class);
protected final MultiMediaMemoryResource mem;
/**
* Offset of first pixel in mem (in bytes)
*/
protected final int offset;
protected final int width;
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
/**
* Create a new instance
*
* @param mem
* @param width
* @param height
* @param offset
* @param bytesPerLine
*/
protected AbstractBitmapGraphics(MemoryResource mem, int width, int height,
int offset, int bytesPerLine) {
this.mem = mem.asMultiMediaMemoryResource();
this.offset = offset;
this.bytesPerLine = bytesPerLine;
this.width = width;
this.height = height;
}
protected abstract int getOffset(int x, int y);
/**
* @see org.jnode.driver.video.Surface#copyArea(int, int, int, int, int,
* int)
*/
public final void copyArea(final int srcX, final int srcY, final int w, final int h,
final int deltaX, final int deltaY) {
if (w < 1 || h < 1)
return;
final int dstX = srcX + deltaX;
final int dstY = srcY + deltaY;
final int bytesForWidth = getBytesForWidth(w);
if (deltaY < 0) {
int srcOfs = getOffset(srcX, srcY);
int dstOfs = getOffset(dstX, dstY);
for (int row = 0; row < h; row++) {
mem.copy(srcOfs, dstOfs, bytesForWidth);
srcOfs += bytesPerLine;
dstOfs += bytesPerLine;
}
} else {
int srcOfs = getOffset(srcX, srcY + h - 1);
int dstOfs = getOffset(dstX, dstY + h - 1);
for (int row = 0; row < h; row++) {
mem.copy(srcOfs, dstOfs, bytesForWidth);
srcOfs -= bytesPerLine;
dstOfs -= bytesPerLine;
}
}
/*
if ((dstY < this.height) && (dstX < this.width)) {
if (dstX < 0) {
srcX -= dstX;
w += dstX;
dstX = 0;
}
if (dstY < 0) {
srcY -= dstY;
h += dstY;
dstY = 0;
}
w = Math.min(w, width - dstX);
h = Math.min(h, height - dstY);
if ((w > 0) && (h > 0)) {
doCopyArea(srcX, srcY, w, h, dstX, dstY);
}
}
*/
}
/**
* Draw an image to this surface
*
* @param src
* @param srcX The upper left x coordinate of the source
* @param srcY The upper left y coordinate of the source
* @param dstX The upper left x coordinate of the destination
* @param dstY The upper left y coordinate of the destination
* @param w
* @param h
*/
public final void drawImage(Raster src, int srcX, int srcY, int dstX,
int dstY, int w, int h) {
if ((dstY < this.height) && (dstX < this.width)) {
if (dstX < 0) {
srcX -= dstX;
w += dstX;
dstX = 0;
}
if (dstY < 0) {
srcY -= dstY;
h += dstY;
dstY = 0;
}
w = Math.min(w, width - dstX);
h = Math.min(h, height - dstY);
if ((w > 0) && (h > 0)) {
doDrawImage(src, srcX, srcY, dstX, dstY, w, h);
}
}
}
/**
* Draw an image to this surface
*
* @param src
* @param srcX The upper left x coordinate of the source
* @param srcY The upper left y coordinate of the source
* @param dstX The upper left x coordinate of the destination
* @param dstY The upper left y coordinate of the destination
* @param w
* @param h
* @param bgColor The color to use for transparent pixels
*/
public final void drawImage(Raster src, int srcX, int srcY, int dstX,
int dstY, int w, int h, int bgColor) {
if ((dstY < this.height) && (dstX < this.width)) {
if (dstX < 0) {
srcX -= dstX;
w += dstX;
dstX = 0;
}
if (dstY < 0) {
srcY -= dstY;
h += dstY;
dstY = 0;
}
w = Math.min(w, width - dstX);
h = Math.min(h, height - dstY);
if ((w > 0) && (h > 0)) {
doDrawImage(src, srcX, srcY, dstX, dstY, w, h, bgColor);
}
}
}
/**
* Draw an raster of alpha values using a given color onto to this surface.
* The given raster is a 1 band gray type raster.
*
* @param raster
* @param srcX The upper left x coordinate within the raster
* @param srcY The upper left y coordinate within the raster
* @param dstX The upper left destination x coordinate
* @param dstY The upper left destination y coordinate
* @param w
* @param h
* @param color The color to use.
*/
public void drawAlphaRaster(Raster raster, AffineTransform tx, int srcX,
int srcY, int dstX, int dstY, int w, int h, int color) {
if (tx != null) {
Point2D dst = tx.transform(new Point2D.Float(dstX, dstY), null);
dstX = (int) dst.getX();
dstY = (int) dst.getY();
}
if ((dstY < this.height) && (dstX < this.width)) {
if (dstX < 0) {
srcX -= dstX;
w += dstX;
dstX = 0;
}
if (dstY < 0) {
srcY -= dstY;
h += dstY;
dstY = 0;
}
w = Math.min(w, width - dstX);
h = Math.min(h, height - dstY);
if ((w > 0) && (h > 0)) {
doDrawAlphaRaster(raster, srcX, srcY, dstX, dstY, w, h, color);
}
}
}
/**
* Draw a line at location x,y that is w long using the given color.
*
* @param x
* @param y
* @param w
* @param color
* @param mode
* @see org.jnode.driver.video.Surface#PAINT_MODE
* @see org.jnode.driver.video.Surface#XOR_MODE
*/
public final void drawLine(int x, int y, int w, int color, int mode) {
try {
if ((y >= 0) && (y < height) && (x < width)) {
if (x < 0) {
w += x;
x = 0;
}
w = Math.min(w, width - x);
if (w > 0) {
doDrawLine(x, y, w, color, mode);
}
}
} catch (IndexOutOfBoundsException ex) {
log.error("Index out of bounds: x=" + x + ", y=" + y + ", w=" + w +
", width=" + width + ", height=" + height);
}
}
/**
* Draw a pixel at location x,y using the given color.
*
* @param x
* @param y
* @param color
* @param mode
* @see org.jnode.driver.video.Surface#PAINT_MODE
* @see org.jnode.driver.video.Surface#XOR_MODE
*/
public final void drawPixels(int x, int y, int count, int color, int mode) {
try {
if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
doDrawPixels(x, y, count, color, mode);
}
} catch (IndexOutOfBoundsException ex) {
log.error("Index out of bounds: x=" + x + ", y=" + y + ", width=" +
width + ", height=" + height);
}
}
@Override
public void fillRect(int x, int y, int width, int height, int color, int mode) {
if ((x >= 0) && (x < this.width) && (y >= 0) && (y < this.height) &&
(x + width >= 0) && (x + width < this.width) && (y + height >= 0) && (y + height < this.height)) {
for (int i = 0; i < height; i++)
doDrawPixels(x, y + i, width, color, mode);
} else {
// super.fillRect(x, y, width, height, color, mode);
}
}
/**
* @see org.jnode.driver.video.Surface#copyArea(int, int, int, int, int,
* int)
*/
protected void doCopyArea(int srcX, int srcY, int width, int height,
int dstX, int dstY) {
int srcOfs = getOffset(srcX, srcY);
int dstOfs = getOffset(dstX, dstY);
final int bytesForWidth = getBytesForWidth(width);
for (int row = 0; row < height; row++) {
mem.copy(srcOfs, dstOfs, bytesForWidth);
srcOfs += bytesPerLine;
dstOfs += bytesPerLine;
}
}
protected abstract int getBytesForWidth(int width);
protected abstract void doDrawAlphaRaster(Raster raster, int srcX,
int srcY, int dstX, int dstY, int width, int height, int color);
/**
* Draw an image to this surface
*
* @param src
* @param srcX The upper left x coordinate of the source
* @param srcY The upper left y coordinate of the source
* @param dstX The upper left x coordinate of the destination
* @param dstY The upper left y coordinate of the destination
* @param width
* @param height
*/
protected abstract void doDrawImage(Raster src, int srcX, int srcY,
int dstX, int dstY, int width, int height);
/**
* Draw an image to this surface
*
* @param src
* @param srcX The upper left x coordinate of the source
* @param srcY The upper left y coordinate of the source
* @param dstX The upper left x coordinate of the destination
* @param dstY The upper left y coordinate of the destination
* @param width
* @param height
* @param bgColor The color to use for transparent pixels
*/
protected abstract void doDrawImage(Raster src, int srcX, int srcY,
int dstX, int dstY, int width, int height, int bgColor);
/**
* Draw a line at location x,y that is w long using the given color.
*
* @param x
* @param y
* @param w
* @param color
* @param mode
* @see org.jnode.driver.video.Surface#PAINT_MODE
* @see org.jnode.driver.video.Surface#XOR_MODE
*/
protected abstract void doDrawLine(int x, int y, int w, int color, int mode);
/**
* Draw a number of pixels at location x,y using the given color.
*
* @param x
* @param y
* @param count
* @param color
* @param mode
* @see org.jnode.driver.video.Surface#PAINT_MODE
* @see org.jnode.driver.video.Surface#XOR_MODE
*/
protected abstract void doDrawPixels(int x, int y, int count, int color,
int mode);
}