Mercurial > hg > Applications > TreeVNC
diff src/main/java/com/glavsoft/drawing/Renderer.java @ 0:4689cc86d6cb
create TreeViewer2 Repository
author | Yu Taninari <you@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 03 Jul 2012 13:20:49 +0900 |
parents | |
children | 0c08cdc4b572 17b702648079 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/com/glavsoft/drawing/Renderer.java Tue Jul 03 13:20:49 2012 +0900 @@ -0,0 +1,328 @@ +// Copyright (C) 2010, 2011 GlavSoft LLC. +// All rights reserved. +// +//------------------------------------------------------------------------- +// This file is part of the TightVNC software. Please visit our Web site: +// +// http://www.tightvnc.com/ +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//------------------------------------------------------------------------- +// + +package com.glavsoft.drawing; + +import com.glavsoft.exceptions.TransportException; +import com.glavsoft.rfb.encoding.PixelFormat; +import com.glavsoft.rfb.encoding.decoder.FramebufferUpdateRectangle; +import com.glavsoft.transport.Reader; + +import java.util.Arrays; + +/** + * Render bitmap data + * + * @author dime @ tightvnc.com + */ +public abstract class Renderer { + + protected Reader reader; + + public abstract void drawJpegImage(byte[] bytes, int offset, + int jpegBufferLength, FramebufferUpdateRectangle rect); + + protected int width; + protected int height; + protected int bytesPerPixel; + protected int bytesPerPixelSignificant; + protected int[] pixels; + protected SoftCursor cursor; + protected PixelFormat pixelFormat; + private ColorDecoder colorDecoder; + + protected void init(Reader reader, int width, int height, PixelFormat pixelFormat) { + this.reader = reader; + this.width = width; + this.height = height; + initPixelFormat(pixelFormat); + pixels = new int[width * height]; + Arrays.fill(pixels, 0); + } + + public synchronized void initPixelFormat(PixelFormat pixelFormat) { + this.pixelFormat = pixelFormat; + bytesPerPixel = pixelFormat.bitsPerPixel / 8; + bytesPerPixelSignificant = + 24 == pixelFormat.depth && 32 == pixelFormat.bitsPerPixel ? 3 : bytesPerPixel; + colorDecoder = new ColorDecoder(pixelFormat); + } + + /** + * Draw byte array bitmap data + * + * @param bytes bitmap data + * @param x bitmap x position + * @param y bitmap y position + * @param width bitmap width + * @param height bitmap height + */ + public void drawBytes(byte[] bytes, int x, int y, int width, int height) { + int i = 0; + for (int ly = y; ly < y + height; ++ly) { + int end = ly * this.width + x + width; + for (int pixelsOffset = ly * this.width + x; pixelsOffset < end; ++pixelsOffset) { + pixels[pixelsOffset] = getPixelColor(bytes, i); + i += bytesPerPixel; + } + } + } + + /** + * Draw byte array bitmap data (for ZRLE) + */ + public synchronized int drawCompactBytes(byte[] bytes, int offset, int x, int y, int width, int height) { + int i = offset; + for (int ly = y; ly < y + height; ++ly) { + int end = ly * this.width + x + width; + for (int pixelsOffset = ly * this.width + x; pixelsOffset < end; ++pixelsOffset) { + pixels[pixelsOffset] = getCompactPixelColor(bytes, i); + i += bytesPerPixelSignificant; + } + } + return i - offset; + } + + /** + * Draw int (colors) array bitmap data (for ZRLE) + */ + public synchronized void drawColoredBitmap(int[] colors, int x, int y, int width, int height) { + int i = 0; + for (int ly = y; ly < y + height; ++ly) { + int end = ly * this.width + x + width; + for (int pixelsOffset = ly * this.width + x; pixelsOffset < end; ++pixelsOffset) { + pixels[pixelsOffset] = colors[i++]; + } + } + } + + /** + * Draw byte array bitmap data (for Tight) + */ + public synchronized int drawTightBytes(byte[] bytes, int offset, int x, int y, int width, int height) { + int i = offset; + for (int ly = y; ly < y + height; ++ly) { + int end = ly * this.width + x + width; + for (int pixelsOffset = ly * this.width + x; pixelsOffset < end; ++pixelsOffset) { + pixels[pixelsOffset] = colorDecoder.getTightColor(bytes, i); + i += bytesPerPixelSignificant; + } + } + return i - offset; + } + + /** + * Draw byte array bitmap data (from array with plain RGB color components. Assumed: rrrrrrrr gggggggg bbbbbbbb) + */ + public synchronized void drawUncaliberedRGBLine(byte[] bytes, int x, int y, int width) { + int end = y * this.width + x + width; + for (int i=3, pixelsOffset = y * this.width + x; pixelsOffset < end; ++pixelsOffset) { + pixels[pixelsOffset] = +// (0xff & bytes[i++]) << 16 | +// (0xff & bytes[i++]) << 8 | +// 0xff & bytes[i++]; + (0xff & 255 * (colorDecoder.redMax & bytes[i++]) / colorDecoder.redMax) << 16 | + (0xff & 255 * (colorDecoder.greenMax & bytes[i++]) / colorDecoder.greenMax) << 8 | + 0xff & 255 * (colorDecoder.blueMax & bytes[i++]) / colorDecoder.blueMax; + } + } + + /** + * Draw paletted byte array bitmap data + * + * @param buffer bitmap data + * @param rect bitmap location and dimensions + * @param palette colour palette + */ + public synchronized void drawBytesWithPalette(byte[] buffer, FramebufferUpdateRectangle rect, + int[] palette) { + // 2 colors + if (palette.length == 2) { + int dx, dy, n; + int i = rect.y * this.width + rect.x; + int rowBytes = (rect.width + 7) / 8; + byte b; + + for (dy = 0; dy < rect.height; dy++) { + for (dx = 0; dx < rect.width / 8; dx++) { + b = buffer[dy * rowBytes + dx]; + for (n = 7; n >= 0; n--) { + pixels[i++] = palette[b >> n & 1]; + } + } + for (n = 7; n >= 8 - rect.width % 8; n--) { + pixels[i++] = palette[buffer[dy * rowBytes + dx] >> n & 1]; + } + i += this.width- rect.width; + } + } else { + // 3..255 colors (assuming bytesPixel == 4). + int i = 0; + for (int ly = rect.y; ly < rect.y + rect.height; ++ly) { + for (int lx = rect.x; lx < rect.x + rect.width; ++lx) { + int pixelsOffset = ly * this.width + lx; + pixels[pixelsOffset] = palette[buffer[i++] & 0xFF]; + } + } + } + + } + + /** + * Copy rectangle region from one position to another. Regions may be overlapped. + * + * @param srcX source rectangle x position + * @param srcY source rectangle y position + * @param dstRect destination rectangle + */ + public synchronized void copyRect(int srcX, int srcY, FramebufferUpdateRectangle dstRect) { + int startSrcY, endSrcY, dstY, deltaY; + if (srcY > dstRect.y) { + startSrcY = srcY; + endSrcY = srcY + dstRect.height; + dstY = dstRect.y; + deltaY = +1; + } else { + startSrcY = srcY + dstRect.height - 1; + endSrcY = srcY -1; + dstY = dstRect.y + dstRect.height - 1; + deltaY = -1; + } + for (int y = startSrcY; y != endSrcY; y += deltaY) { + System.arraycopy(pixels, y * width + srcX, + pixels, dstY * width + dstRect.x, dstRect.width); + dstY += deltaY; + } + } + + /** + * Fill rectangle region with specified colour + * + * @param color colour to fill with + * @param rect rectangle region posions and dimensions + */ + public void fillRect(int color, FramebufferUpdateRectangle rect) { + fillRect(color, rect.x, rect.y, rect.width, rect.height); + } + + /** + * Fill rectangle region with specified colour + * + * @param color colour to fill with + * @param x rectangle x position + * @param y rectangle y position + * @param width rectangle width + * @param height rectangle height + */ + public synchronized void fillRect(int color, int x, int y, int width, int height) { + int sy = y * this.width + x; + int ey = sy + height * this.width; + for (int i = sy; i < ey; i += this.width) { + Arrays.fill(pixels, i, i + width, color); + } + } + + /** + * Reads color bytes (PIXEL) from reader, returns int combined RGB + * value consisting of the red component in bits 16-23, the green component + * in bits 8-15, and the blue component in bits 0-7. May be used directly for + * creation awt.Color object + */ + public int readPixelColor(Reader reader) throws TransportException { + return colorDecoder.readColor(reader); + } + + public int readTightPixelColor(Reader reader) throws TransportException { + return colorDecoder.readTightColor(reader); + } + + public ColorDecoder getColorDecoder() { + return colorDecoder; + } + + public int getCompactPixelColor(byte[] bytes, int offset) { + return colorDecoder.getCompactColor(bytes, offset); + } + + public int getPixelColor(byte[] bytes, int offset) { + return colorDecoder.getColor(bytes, offset); + } + + public int getBytesPerPixel() { + return bytesPerPixel; + } + + public int getBytesPerPixelSignificant() { + return bytesPerPixelSignificant; + } + + public void fillColorBitmapWithColor(int[] bitmapData, int decodedOffset, int rlength, int color) { + while (rlength-- > 0) { + bitmapData[decodedOffset++] = color; + } + } + + /** + * Width of rendered image + * + * @return width + */ + public int getWidth() { + return width; + } + + /** + * Height of rendered image + * + * @return height + */ + public int getHeight() { + return height; + } + + /** + * Read and decode cursor image + * + * @param rect new cursor hot point position and cursor dimensions + * @throws TransportException + */ + public void createCursor(int[] cursorPixels, FramebufferUpdateRectangle rect) + throws TransportException { + synchronized (cursor) { + cursor.createCursor(cursorPixels, rect.x, rect.y, rect.width, rect.height); + } + } + + /** + * Read and decode new cursor position + * + * @param rect cursor position + */ + public void decodeCursorPosition(FramebufferUpdateRectangle rect) { + synchronized (cursor) { + cursor.updatePosition(rect.x, rect.y); + } + } + +} \ No newline at end of file