/**
* Copyright (C) 2012 Iordan Iordanov
* Copyright (C) 2010 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 java.util.Arrays;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
class FullBufferBitmapData extends AbstractBitmapData {
/**
* Multiply this times total number of pixels to get estimate of process size with all buffers plus
* safety factor
*/
static final int CAPACITY_MULTIPLIER = 6;
int xoffset;
int yoffset;
int dataWidth;
int dataHeight;
class Drawable extends AbstractBitmapDrawable {
private final static String TAG = "Drawable";
int drawWidth;
int drawHeight;
int xo, yo;
/**
* @param data
*/
public Drawable(AbstractBitmapData data) {
super(data);
}
/* (non-Javadoc)
* @see android.graphics.drawable.DrawableContainer#draw(android.graphics.Canvas)
*/
@Override
public void draw(Canvas canvas) {
toDraw = canvas.getClipBounds();
// To avoid artifacts, we need to enlarge the box by one pixel in all directions.
toDraw.set(toDraw.left-1, toDraw.top-1, toDraw.right+1, toDraw.bottom+1);
drawWidth = toDraw.width();
drawHeight = toDraw.height();
if (toDraw.left < 0)
xo = 0;
else if (toDraw.left >= data.framebufferwidth)
return;
else
xo = toDraw.left;
if (toDraw.top < 0)
yo = 0;
else if (toDraw.top >= data.framebufferheight)
return;
else
yo = toDraw.top;
if (xo + drawWidth >= data.framebufferwidth)
drawWidth = data.framebufferwidth - xo;
if (yo + drawHeight >= data.framebufferheight)
drawHeight = data.framebufferheight - yo;
try {
canvas.drawBitmap(data.bitmapPixels, offset(xo, yo), data.framebufferwidth,
xo, yo, drawWidth, drawHeight, false, _defaultPaint);
canvas.drawBitmap(softCursor, cursorRect.left, cursorRect.top, _defaultPaint);
} catch (Throwable e) { }
}
}
/**
* @param p
* @param c
*/
public FullBufferBitmapData(RfbConnectable p, RemoteCanvas c, int capacity) {
super(p, c);
framebufferwidth=rfb.framebufferWidth();
framebufferheight=rfb.framebufferHeight();
bitmapwidth=framebufferwidth;
bitmapheight=framebufferheight;
dataWidth=framebufferwidth;
dataHeight=framebufferheight;
android.util.Log.i("FBBM", "bitmapsize = ("+bitmapwidth+","+bitmapheight+")");
bitmapPixels = new int[framebufferwidth * framebufferheight];
drawable.startDrawing();
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#copyRect(android.graphics.Rect, android.graphics.Rect, android.graphics.Paint)
*/
@Override
public void copyRect(int sx, int sy, int dx, int dy, int w, int h) {
int srcOffset, dstOffset;
int dstH = h;
int dstW = w;
int startSrcY, endSrcY, dstY, deltaY;
if (sy > dy) {
startSrcY = sy;
endSrcY = sy + dstH;
dstY = dy;
deltaY = +1;
} else {
startSrcY = sy + dstH - 1;
endSrcY = sy - 1;
dstY = dy + dstH - 1;
deltaY = -1;
}
for (int y = startSrcY; y != endSrcY; y += deltaY) {
srcOffset = offset(sx, y);
dstOffset = offset(dx, dstY);
try {
System.arraycopy(bitmapPixels, srcOffset, bitmapPixels, dstOffset, dstW);
} catch (Exception e) {
// There was an index out of bounds exception, but we continue copying what we can.
e.printStackTrace();
}
dstY += deltaY;
}
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#createDrawable()
*/
@Override
AbstractBitmapDrawable createDrawable() {
return new Drawable(this);
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#drawRect(int, int, int, int, android.graphics.Paint)
*/
@Override
void drawRect(int x, int y, int w, int h, Paint paint) {
int color = paint.getColor();
int offset = offset(x,y);
if (w > 10)
{
for (int j = 0; j < h; j++, offset += framebufferwidth)
{
Arrays.fill(bitmapPixels, offset, offset + w, color);
}
}
else
{
for (int j = 0; j < h; j++, offset += framebufferwidth - w)
{
for (int k = 0; k < w; k++, offset++)
{
bitmapPixels[offset] = color;
}
}
}
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#offset(int, int)
*/
@Override
public int offset(int x, int y) {
return x + y * framebufferwidth;
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#scrollChanged(int, int)
*/
@Override
void scrollChanged(int newx, int newy) {
xoffset = newx;
yoffset = newy;
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#frameBufferSizeChanged(RfbProto)
*/
@Override
public void frameBufferSizeChanged () {
framebufferwidth = rfb.framebufferWidth();
framebufferheight = rfb.framebufferHeight();
bitmapwidth = framebufferwidth;
bitmapheight = framebufferheight;
android.util.Log.i("FBBM", "bitmapsize changed = ("+bitmapwidth+","+bitmapheight+")");
if ( dataWidth < framebufferwidth || dataHeight < framebufferheight ) {
dispose();
// Try to free up some memory.
System.gc();
dataWidth = framebufferwidth;
dataHeight = framebufferheight;
bitmapPixels = new int[framebufferwidth * framebufferheight];
drawable = createDrawable();
drawable.startDrawing();
}
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#syncScroll()
*/
@Override
void syncScroll() {
// Don't need to do anything here
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#updateBitmap(int, int, int, int)
*/
@Override
public void updateBitmap(int x, int y, int w, int h) {
// Don't need to do anything here
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#updateBitmap(Bitmap, int, int, int, int)
*/
@Override
public void updateBitmap(Bitmap b, int x, int y, int w, int h) {
b.getPixels(bitmapPixels, offset(x, y), bitmapwidth, 0, 0, w, h);
}
/* (non-Javadoc)
* @see com.iiordanov.bVNC.AbstractBitmapData#validDraw(int, int, int, int)
*/
@Override
public boolean validDraw(int x, int y, int w, int h) {
if (x + w > bitmapwidth || y + h > bitmapheight)
return false;
return true;
}
}