/**
* Copyright (C) 2012 Iordan Iordanov
* Copyright (C) 2009 Michael A. MacDonald
*
* This 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 software 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 software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
package com.iiordanov.bVNC;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.widget.ImageView;
import android.util.Log;
/**
* Abstract interface between the VncCanvas and the bitmap and pixel data buffers that actually contain
* the data.
* This allows for implementations that use smaller bitmaps or buffers to save memory.
* @author Michael A. MacDonald
*
*/
abstract public class AbstractBitmapData {
int framebufferwidth;
int framebufferheight;
int bitmapwidth;
int bitmapheight;
RfbConnectable rfb;
Bitmap mbitmap;
int bitmapPixels[];
Canvas memGraphics;
boolean waitingForInput;
RemoteCanvas vncCanvas;
public AbstractBitmapDrawable drawable;
private Paint paint;
int xoffset = 0;
int yoffset = 0;
AbstractBitmapData(RfbConnectable p, RemoteCanvas c)
{
rfb = p;
vncCanvas = c;
framebufferwidth = rfb.framebufferWidth();
framebufferheight = rfb.framebufferHeight();
drawable = createDrawable();
paint = new Paint();
}
synchronized void doneWaiting() {
waitingForInput = false;
}
void setCursorRect(int x, int y, int w, int h, int hX, int hY) {
if (drawable != null)
drawable.setCursorRect(x, y, w, h, hX, hY);
}
void moveCursorRect(int x, int y) {
if (drawable != null)
drawable.moveCursorRect(x, y);
}
void setSoftCursor (int[] newSoftCursorPixels) {
if (drawable != null)
drawable.setSoftCursor (newSoftCursorPixels);
}
RectF getCursorRect () {
if (drawable != null)
return drawable.cursorRect;
else // Return an empty new rectangle if drawable is null.
return new RectF();
}
boolean isNotInitSoftCursor() {
if (drawable != null)
return (drawable.softCursorInit == false);
else
return false;
}
/**
*
* @return The smallest scale supported by the implementation; the scale at which
* the bitmap would be smaller than the screen
*/
float getMinimumScale() {
return Math.min((float)vncCanvas.getWidth()/bitmapwidth, (float)vncCanvas.getHeight()/bitmapheight);
}
/**
* Send a request through the protocol to get the data for the currently held bitmap
* @param incremental True if we want incremental update; false for full update
*/
public void prepareFullUpdateRequest(boolean incremental) {};
/**
* Determine if a rectangle in full-frame coordinates can be drawn in the existing buffer
* @param x Top left x
* @param y Top left y
* @param w width (pixels)
* @param h height (pixels)
* @return True if entire rectangle fits into current screen buffer, false otherwise
*/
public abstract boolean validDraw(int x, int y, int w, int h);
/**
* Return an offset in the bitmapPixels array of a point in full-frame coordinates
* @param x
* @param y
* @return Offset in bitmapPixels array of color data for that point
*/
public abstract int offset(int x, int y);
/**
* Update pixels in the bitmap with data from the bitmapPixels array, positioned
* in full-frame coordinates
* @param x Top left x
* @param y Top left y
* @param w width (pixels)
* @param h height (pixels)
*/
public abstract void updateBitmap(int x, int y, int w, int h);
/**
* Update pixels in the bitmap with data from the given bitmap, positioned
* in full-frame coordinates
* @param b The bitmap to copy from.
* @param x Top left x
* @param y Top left y
* @param w width (pixels)
* @param h height (pixels)
*/
public abstract void updateBitmap(Bitmap b, int x, int y, int w, int h);
/**
* Create drawable appropriate for this data
* @return drawable
*/
abstract AbstractBitmapDrawable createDrawable();
/**
* Sets the canvas's drawable
* @param v ImageView displaying bitmap data
*/
void setImageDrawable(ImageView v)
{
v.setImageDrawable(drawable);
}
/**
* Call in UI thread; tell ImageView we've changed
* @param v ImageView displaying bitmap data
*/
void updateView(ImageView v)
{
v.invalidate();
}
/**
* Copy a rectangle from one part of the bitmap to another
* @param src Rectangle in full-frame coordinates to be copied
* @param dest Destination rectangle in full-frame coordinates
* @param paint Paint specifier
*/
public abstract void copyRect(int sx, int sy, int dx, int dy, int w, int h);
public void fillRect(int x, int y, int w, int h, int pix) {
paint.setColor(pix);
drawRect(x, y, w, h, paint);
}
public void imageRect(int x, int y, int w, int h, int[] pix) {
for (int j = 0; j < h; j++) {
try {
synchronized (mbitmap) {
System.arraycopy(pix, (w * j), bitmapPixels, offset(x, y+j), w);
}
//System.arraycopy(pix, (w * j), bitmapPixels, bitmapwidth * (y + j) + x, w);
} catch (ArrayIndexOutOfBoundsException e) {
// An index is out of bounds for some reason, but we try to continue.
e.printStackTrace();
}
}
updateBitmap(x, y, w, h);
}
/**
* Draw a rectangle in the bitmap with coordinates given in full frame
* @param x Top left x
* @param y Top left y
* @param w width (pixels)
* @param h height (pixels)
* @param paint How to draw
*/
abstract void drawRect( int x, int y, int w, int h, Paint paint);
/**
* Scroll position has changed.
* <p>
* This method is called in the UI thread-- it updates internal status, but does
* not change the bitmap data or send a network request until syncScroll is called
* @param newx Position of left edge of visible part in full-frame coordinates
* @param newy Position of top edge of visible part in full-frame coordinates
*/
abstract void scrollChanged( int newx, int newy);
/**
* Remote framebuffer size has changed.
* <p>
* This method is called when the framebuffer has changed size and reinitializes the
* necessary data structures to support that change.
*/
public abstract void frameBufferSizeChanged ();
/**
* Sync scroll -- called from network thread; copies scroll changes from UI to network state
*/
abstract void syncScroll();
/**
* Release resources
*/
void dispose() {
if (drawable != null)
drawable.dispose();
drawable = null;
if (mbitmap != null)
mbitmap.recycle();
mbitmap = null;
memGraphics = null;
bitmapPixels = null;
}
public int fbWidth () {
return framebufferwidth;
}
public int fbHeight () {
return framebufferheight;
}
public int bmWidth () {
return bitmapwidth;
}
public int bmHeight () {
return bitmapheight;
}
public int getXoffset () {
return xoffset;
}
public int getYoffset () {
return yoffset;
}
}