Mercurial > hg > Applications > TreeVNC
view 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 source
// 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); } } }