package org.ebookdroid.common.bitmaps;
import org.ebookdroid.core.PagePaint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.FloatMath;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.emdev.common.log.LogContext;
import org.emdev.common.log.LogManager;
import org.emdev.ui.gl.GLCanvas;
import org.emdev.utils.MathUtils;
public class GLBitmaps {
protected static final LogContext LCTX = LogManager.root().lctx("Bitmaps", false);
protected static final ThreadLocal<ByteBufferBitmap> threadSlices = new ThreadLocal<ByteBufferBitmap>();
protected final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public final int width;
public final int height;
public final String nodeId;
public final int partSize;
public final int columns;
public final int rows;
private ByteBufferBitmap[] bitmaps;
private ByteBufferTexture[] textures;
public GLBitmaps(final String nodeId, final ByteBufferBitmap orig, final PagePaint paint) {
this.nodeId = nodeId;
this.width = orig.width;
this.height = orig.height;
this.partSize = ByteBufferManager.partSize;
this.columns = getPartCount(width, partSize);
this.rows = getPartCount(height, partSize);
this.bitmaps = ByteBufferManager.getParts(partSize, rows, columns);
final int color = paint.fillPaint.getColor();
int top = 0;
for (int row = 0; row < rows; row++, top += partSize) {
int left = 0;
for (int col = 0; col < columns; col++, left += partSize) {
final int index = row * columns + col;
try {
if (row == rows - 1 || col == columns - 1) {
final int right = Math.min(left + partSize, orig.width);
final int bottom = Math.min(top + partSize, orig.height);
bitmaps[index].eraseColor(color);
bitmaps[index].copyPixelsFrom(orig, left, top, right - left, bottom - top);
} else {
bitmaps[index].copyPixelsFrom(orig, left, top, partSize, partSize);
}
} catch (final IllegalArgumentException ex) {
LCTX.e("Cannot create part: " + row + "/" + rows + ", " + col + "/" + columns + ": "
+ ex.getMessage());
}
}
}
}
private static int getPartCount(final int size, final int partSize) {
if (size % partSize == 0) {
return size / partSize;
}
return (int) Math.ceil(size / (float) partSize);
}
public boolean drawGL(final GLCanvas canvas, final PagePaint paint, final PointF vb, final RectF tr, final RectF cr) {
lock.writeLock().lock();
try {
if (textures == null) {
if (this.bitmaps == null) {
return false;
}
textures = new ByteBufferTexture[columns * rows];
for (int i = 0; i < textures.length; i++) {
textures[i] = new ByteBufferTexture(bitmaps[i]);
}
}
if (LCTX.isDebugEnabled()) {
LCTX.d(nodeId + ".drawGL(): >>>>");
}
final RectF actual = new RectF(cr.left - vb.x, cr.top - vb.y, cr.right - vb.x, cr.bottom - vb.y);
MathUtils.round(actual);
canvas.setClipRect(actual);
final boolean res = draw(canvas, vb, tr, actual);
if (res && bitmaps != null) {
ByteBufferManager.release(bitmaps);
bitmaps = null;
}
if (LCTX.isDebugEnabled()) {
LCTX.d(nodeId + ".drawGL(): <<<<<");
}
canvas.clearClipRect();
return res;
} finally {
lock.writeLock().unlock();
}
}
protected boolean draw(final GLCanvas canvas, final PointF vb, final RectF tr, final RectF actual) {
final float offsetX = tr.left - vb.x;
final float offsetY = tr.top - vb.y;
final float scaleX = tr.width() / width;
final float scaleY = tr.height() / height;
final float sizeX = partSize * scaleX;
final float sizeY = partSize * scaleY;
final RectF src = new RectF();
final RectF rect = new RectF(offsetX, offsetY, offsetX + sizeX, offsetY + sizeY);
final RectF r = new RectF();
boolean res = true;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < columns; col++) {
final int index = row * columns + col;
res &= draw(canvas, row, col, this.textures[index], actual, src, rect, r);
rect.left += sizeX;
rect.right += sizeX;
}
rect.left = offsetX;
rect.right = offsetX + sizeX;
rect.top += sizeY;
rect.bottom += sizeY;
}
return res;
}
protected boolean draw(final GLCanvas canvas, final int row, final int col, final ByteBufferTexture t,
final RectF actual, final RectF src, final RectF rect, final RectF r) {
boolean tres = false;
if (t != null) {
r.set(rect);
src.set(0, 0, t.getWidth(), t.getHeight());
if (!(r.right < actual.left || r.left > actual.right || r.bottom < actual.top || r.top > actual.bottom)) {
tres = canvas.drawTexture(t, src, r);
if (LCTX.isDebugEnabled()) {
LCTX.d(nodeId + ": " + row + "." + col + " : " + t.getId() + " = " + tres);
}
}
}
return tres;
}
ByteBufferBitmap[] clear() {
lock.writeLock().lock();
try {
if (textures != null) {
for (int i = 0; i < textures.length; i++) {
textures[i].recycle();
}
textures = null;
}
final ByteBufferBitmap[] ref = this.bitmaps;
this.bitmaps = null;
return ref;
} finally {
lock.writeLock().unlock();
}
}
public boolean hasBitmaps() {
lock.readLock().lock();
try {
return textures != null || bitmaps != null;
} finally {
lock.readLock().unlock();
}
}
}