/*
* $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.driver.video.vga;
import java.awt.Rectangle;
import java.awt.image.Raster;
import org.jnode.awt.util.AbstractBitmapGraphics;
/**
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class VGABitmapGraphics extends AbstractBitmapGraphics {
private final StandardVGAIO vgaIO;
/**
* @param vga
* @param vgaIO
* @param width
* @param height
* @param offset
* @param bytesPerLine
*/
public VGABitmapGraphics(StandardVGA vga, StandardVGAIO vgaIO, int width, int height,
int offset, int bytesPerLine) {
super(vga.getVgaMem(), width, height, offset, bytesPerLine);
this.vgaIO = vgaIO;
}
protected void doCopyArea(int x, int y, int width, int height, int dx, int dy) {
// TODO Implement me
}
protected void doDrawImage(Raster src, int srcX, int srcY, int dstX, int dstY, int width,
int height) {
vgaIO.setGRAF(1, 0);
vgaIO.setGRAF(8, 0xFF);
// round up the result of width/8
int pWidth = width >> 3; // (width >> 3) == (width / 8)
if ((width & 7) != 0) { // (width & 7) == (width % 8)
pWidth++;
}
final byte[] plane0 = new byte[pWidth];
final byte[] plane1 = new byte[pWidth];
final byte[] plane2 = new byte[pWidth];
final byte[] plane3 = new byte[pWidth];
final byte[] buf = new byte[width];
for (int row = 0; row < height; row++) {
final int y = dstY + row;
src.getDataElements(srcX, srcY + row, width, 1, buf);
for (int col = 0; col < width; col++) {
final int bit = getBit(dstX + col);
final int pixel = buf[col];
final int i = (col >> 3);
if ((pixel & 0x01) != 0) {
plane0[i] |= bit;
}
if ((pixel & 0x02) != 0) {
plane1[i] |= bit;
}
if ((pixel & 0x04) != 0) {
plane2[i] |= bit;
}
if ((pixel & 0x08) != 0) {
plane3[i] |= bit;
}
}
final int dstOfs = getOffset(dstX, y);
vgaIO.setSEQ(2, 1); // plane 0
vgaIO.setGRAF(4, 0);
mem.setBytes(plane0, 0, dstOfs, pWidth);
vgaIO.setSEQ(2, 2); // plane 1
vgaIO.setGRAF(4, 1);
mem.setBytes(plane1, 0, dstOfs, pWidth);
vgaIO.setSEQ(2, 4); // plane 2
vgaIO.setGRAF(4, 2);
mem.setBytes(plane2, 0, dstOfs, pWidth);
vgaIO.setSEQ(2, 8); // plane 3
vgaIO.setGRAF(4, 3);
mem.setBytes(plane3, 0, dstOfs, pWidth);
for (int col = 0; col < pWidth; col++) {
plane0[col] = 0;
plane1[col] = 0;
plane2[col] = 0;
plane3[col] = 0;
}
}
vgaIO.setSEQ(2, 0x0F); // restore
vgaIO.setGRAF(1, 0x0F);
}
protected void doDrawImage(Raster src, int srcX, int srcY, int dstX, int dstY, int width,
int height, int bgColor) {
//TODO use bgColor parameter
doDrawImage(src, srcX, srcY, dstX, dstY, width, height);
}
protected void doDrawLine(int x, int y, int lineWidth, int color, int mode) {
final int ofsY = y * 80;
lineWidth = Math.min(this.width - x, lineWidth);
while (lineWidth > 0) {
if (((x & 7) == 0) && (lineWidth >= 8)) {
final int count = lineWidth >> 3;
final int bits = count << 3;
final int offset = ofsY + (x >> 3);
vgaIO.setGRAF(8, 0xFF);
mem.orByte(offset, (byte) 0xFF, count);
lineWidth -= bits;
x += bits;
} else {
final int offset = ofsY + (x >> 3);
vgaIO.setGRAF(8, getBit(x));
mem.orByte(offset, (byte) 0xFF, 1);
lineWidth--;
x++;
}
}
}
protected void doDrawPixels(int x, int y, int count, int color, int mode) {
//TODO (do)DrawLine/(do)doDrawPixels appear to be duplicates at higher level => remove one
doDrawLine(x, y, count, color, mode);
}
protected void doDrawAlphaRaster(Raster raster, int srcX, int srcY, int dstX, int dstY,
int width, int height, int color) {
//TODO should we support alpha with only a fixed set of 16 colors ?
doDrawImage(raster, srcX, srcY, dstX, dstY, width, height, color);
}
public int doGetPixel(int x, int y) {
// TODO Implement me
return 0;
}
public int[] doGetPixels(Rectangle r) {
final int[] result = new int[r.width * r.height];
final int xmax = r.x + r.width;
final int ymax = r.y + r.height;
int i = 0;
for (int y = r.y; y < ymax; y++) {
for (int x = r.x; x < xmax; x++) {
result[i++] = doGetPixel(x, y);
}
}
return result;
}
@Override
protected int getBytesForWidth(int width) {
return (width * bytesPerLine) / this.width;
}
@Override
protected int getOffset(int x, int y) {
return y * 80 + (x >> 3);
}
private int getBit(int x) {
return 0x80 >> (x & 7);
}
}