/*
* $Id$
*
* Copyright (C) 2003-2014 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.textscreen.fb;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import org.jnode.driver.textscreen.TextScreen;
import org.jnode.driver.textscreen.x86.AbstractPcTextScreen;
import org.jnode.driver.video.Surface;
class FbTextScreen extends AbstractPcTextScreen {
private final Font font;
private final char[] buffer;
private int cursorOffset;
private boolean cursorVisible = true;
private FbScreenPainter painter;
private final Surface surface;
private final Background background;
private final BufferedImage bufferedImage;
private final Graphics graphics;
private final int xOffset;
private final int yOffset;
/**
*
* @param g
* @param width in pixels
* @param height in pixels
*/
public FbTextScreen(Surface g, BufferedImage bufferedImage, Graphics graphics, Font font, int nbColumns,
int nbRows, int xOffset, int yOffset) {
super(nbColumns, nbRows);
buffer = new char[getWidth() * getHeight()];
Arrays.fill(buffer, ' ');
this.xOffset = xOffset;
this.yOffset = yOffset;
//this.background = new DefaultBackground(Color.BLACK);
this.background = new GradientBackground(bufferedImage.getWidth(), bufferedImage.getHeight());
this.surface = g;
this.bufferedImage = bufferedImage;
this.graphics = graphics;
this.font = font;
open();
}
public char getChar(int offset) {
return buffer[offset];
}
public int getColor(int offset) {
return 0;
}
public void set(int offset, char ch, int count, int color) {
char c = (char) (ch & 0xFF);
buffer[offset] = c == 0 ? ' ' : c;
sync(offset, count);
}
public void set(int offset, char[] ch, int chOfs, int length, int color) {
char[] cha = new char[ch.length];
for (int i = 0; i < cha.length; i++) {
char c = (char) (ch[i] & 0xFF);
cha[i] = c == 0 ? ' ' : c;
}
System.arraycopy(cha, chOfs, buffer, offset, length);
sync(offset, length);
}
public void set(int offset, char[] ch, int chOfs, int length, int[] colors, int colorsOfs) {
char[] cha = new char[ch.length];
for (int i = 0; i < cha.length; i++) {
char c = (char) (ch[i] & 0xFF);
cha[i] = c == 0 ? ' ' : c;
}
System.arraycopy(cha, chOfs, buffer, offset, length);
sync(offset, length);
}
public void copyContent(int srcOffset, int destOffset, int length) {
System.arraycopy(buffer, srcOffset * 2, buffer, destOffset * 2, length * 2);
sync(destOffset, length);
}
public void copyTo(TextScreen dst, int offset, int length) {
}
public int setCursor(int x, int y) {
cursorOffset = getOffset(x, y);
sync(cursorOffset, 1);
return cursorOffset;
}
public int setCursorVisible(boolean visible) {
cursorVisible = visible;
sync(cursorOffset, 1);
return cursorOffset;
}
@Override
public void sync(int offset, int length) {
if (painter != null) {
painter.repaint();
}
}
/**
* Copy the content of the given rawData into this screen.
*
* @param rawData the data as a char array
* @param rawDataOffset the offset in the data array
*/
@Override
public void copyFrom(char[] rawData, int rawDataOffset) {
char[] cha = new char[rawData.length];
for (int i = 0; i < cha.length; i++) {
char c = (char) (rawData[i] & 0xFF);
cha[i] = c == 0 ? ' ' : c;
}
final int length = getWidth() * getHeight();
System.arraycopy(cha, rawDataOffset, buffer, 0, length);
sync(0, length);
}
class FbScreenPainter {
private final Thread painterThread;
private boolean stop = false;
private boolean update = true;
public FbScreenPainter() {
painterThread = new Thread(new Runnable() {
public void run() {
while (!stop) {
try {
paintComponent();
synchronized (FbScreenPainter.this) {
if (update) {
update = false;
FbScreenPainter.this.wait();
}
}
} catch (InterruptedException x) {
break;
}
}
}
}, "FbScreenPainter");
painterThread.start();
}
private void stop() {
this.stop = true;
}
protected void paintComponent() {
// first draw the background
background.paint(graphics);
graphics.setColor(Color.WHITE);
graphics.setFont(font);
final FontMetrics fm = graphics.getFontMetrics();
final int fontHeight = fm.getHeight();
final char[] textBuffer = buffer;
final int length = getWidth();
int offset = 0;
int y = fontHeight;
// draw the text of the console
for (int i = 0; i < getHeight(); i++) {
graphics.drawChars(textBuffer, offset, length, 0, y);
// draw the cursor
if (cursorVisible && (cursorOffset >= offset) && (cursorOffset < (offset + length))) {
final int x1 = fm.charsWidth(buffer, offset, cursorOffset - offset);
final char charUnderCursor = buffer[cursorOffset];
final int width = fm.charWidth(charUnderCursor);
graphics.fillRect(x1, y - fontHeight + 1, width, fontHeight);
if (charUnderCursor >= ' ') {
graphics.setColor(Color.BLACK);
graphics.drawChars(textBuffer, cursorOffset, 1, x1, y);
graphics.setColor(Color.WHITE);
}
}
offset += length;
y += fontHeight;
}
surface.drawCompatibleRaster(bufferedImage.getRaster(), 0, 0, xOffset, yOffset, bufferedImage.getWidth(),
bufferedImage.getHeight(), Color.BLACK);
}
public synchronized void repaint() {
if (!update) {
update = true;
notifyAll();
}
}
}
void close() {
if (painter != null) {
painter.stop();
painter = null;
}
}
void open() {
if (painter == null) {
painter = new FbScreenPainter();
}
}
}