// Path: src/org/emdev/utils/MathUtils.java
// public class MathUtils {
// 
//     public static int adjust(final int value, final int min, final int max) {
//         return Math.min(Math.max(min, value), max);
//     }
// 
//     public static float adjust(final float value, final float min, final float max) {
//         return Math.min(Math.max(min, value), max);
//     }
// 
//     public static Rect rect(final RectF rect) {
//         return new Rect((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom);
//     }
// 
//     public static Rect rect(final float left, final float top, final float right, final float bottom) {
//         return new Rect((int) left, (int) top, (int) right, (int) bottom);
//     }
// 
//     public static RectF zoom(final RectF rect, final float zoom) {
//         return new RectF(zoom * rect.left, zoom * rect.top, zoom * rect.right, zoom * rect.bottom);
//     }
// 
//     public static void zoom(final RectF rect, final float zoom, final RectF target) {
//         target.left = rect.left * zoom;
//         target.right = rect.right * zoom;
//         target.top = rect.top * zoom;
//         target.bottom = rect.bottom * zoom;
//     }
// 
//     public static RectF zoom(final Rect rect, final float zoom) {
//         return new RectF(zoom * rect.left, zoom * rect.top, zoom * rect.right, zoom * rect.bottom);
//     }
// 
//     public static Rect zoom(final float left, final float top, final float right, final float bottom, final float zoom) {
//         return new Rect((int) (zoom * left), (int) (zoom * top), (int) (zoom * right), (int) (zoom * bottom));
//     }
// 
//     public static int min(final int... values) {
//         int min = Integer.MAX_VALUE;
//         for (final int v : values) {
//             min = Math.min(v, min);
//         }
//         return min;
//     }
// 
//     public static int max(final int... values) {
//         int max = Integer.MIN_VALUE;
//         for (final int v : values) {
//             max = Math.max(v, max);
//         }
//         return max;
//     }
// 
//     public static float fmin(final float... values) {
//         float min = Float.MAX_VALUE;
//         for (final float v : values) {
//             min = Math.min(v, min);
//         }
//         return min;
//     }
// 
//     public static float fmax(final float... values) {
//         float max = Float.MIN_VALUE;
//         for (final float v : values) {
//             max = Math.max(v, max);
//         }
//         return max;
//     }
// 
//     public static float round(final float value, final float share) {
//         return (float) Math.floor(value * share) / share;
//     }
// 
//     public static RectF round(final RectF rect, final float share) {
//         rect.left = (float) Math.floor(rect.left * share) / share;
//         rect.top = (float) Math.floor(rect.top * share) / share;
//         rect.right = (float) Math.floor(rect.right * share) / share;
//         rect.bottom = (float) Math.floor(rect.bottom * share) / share;
//         return rect;
//     }
// 
//     public static RectF floor(final RectF rect) {
//         rect.left = (float) Math.floor(rect.left);
//         rect.top = (float) Math.floor(rect.top);
//         rect.right = (float) Math.floor(rect.right);
//         rect.bottom = (float) Math.floor(rect.bottom);
//         return rect;
//     }
// 
//     public static RectF ceil(final RectF rect) {
//         rect.left = (float) Math.ceil(rect.left);
//         rect.top = (float) Math.ceil(rect.top);
//         rect.right = (float) Math.ceil(rect.right);
//         rect.bottom = (float) Math.ceil(rect.bottom);
//         return rect;
//     }
// 
//     public static RectF round(final RectF rect) {
//         rect.left = (float) Math.floor(rect.left);
//         rect.top = (float) Math.floor(rect.top);
//         rect.right = (float) Math.ceil(rect.right);
//         rect.bottom = (float) Math.ceil(rect.bottom);
//         return rect;
//     }
// 
//     public static int nextPowerOf2(int n) {
//         if (n <= 0 || n > (1 << 30)) {
//             throw new IllegalArgumentException();
//         }
//         n -= 1;
//         n |= n >> 16;
//         n |= n >> 8;
//         n |= n >> 4;
//         n |= n >> 2;
//         n |= n >> 1;
//         return n + 1;
//     }
// 
//     public static int prevPowerOf2(final int n) {
//         if (n <= 0) {
//             throw new IllegalArgumentException();
//         }
//         return Integer.highestOneBit(n);
//     }
// 
//     public static boolean isOpaque(final int color) {
//         return color >>> 24 == 0xFF;
//     }
// }


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;
                }
            }
        }
    }

    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);
// Path: src/org/emdev/utils/MathUtils.java
// public class MathUtils {
// 
//     public static int adjust(final int value, final int min, final int max) {
//         return Math.min(Math.max(min, value), max);
//     }
// 
//     public static float adjust(final float value, final float min, final float max) {
//         return Math.min(Math.max(min, value), max);
//     }
// 
//     public static Rect rect(final RectF rect) {
//         return new Rect((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom);
//     }
// 
//     public static Rect rect(final float left, final float top, final float right, final float bottom) {
//         return new Rect((int) left, (int) top, (int) right, (int) bottom);
//     }
// 
//     public static RectF zoom(final RectF rect, final float zoom) {
//         return new RectF(zoom * rect.left, zoom * rect.top, zoom * rect.right, zoom * rect.bottom);
//     }
// 
//     public static void zoom(final RectF rect, final float zoom, final RectF target) {
//         target.left = rect.left * zoom;
//         target.right = rect.right * zoom;
//         target.top = rect.top * zoom;
//         target.bottom = rect.bottom * zoom;
//     }
// 
//     public static RectF zoom(final Rect rect, final float zoom) {
//         return new RectF(zoom * rect.left, zoom * rect.top, zoom * rect.right, zoom * rect.bottom);
//     }
// 
//     public static Rect zoom(final float left, final float top, final float right, final float bottom, final float zoom) {
//         return new Rect((int) (zoom * left), (int) (zoom * top), (int) (zoom * right), (int) (zoom * bottom));
//     }
// 
//     public static int min(final int... values) {
//         int min = Integer.MAX_VALUE;
//         for (final int v : values) {
//             min = Math.min(v, min);
//         }
//         return min;
//     }
// 
//     public static int max(final int... values) {
//         int max = Integer.MIN_VALUE;
//         for (final int v : values) {
//             max = Math.max(v, max);
//         }
//         return max;
//     }
// 
//     public static float fmin(final float... values) {
//         float min = Float.MAX_VALUE;
//         for (final float v : values) {
//             min = Math.min(v, min);
//         }
//         return min;
//     }
// 
//     public static float fmax(final float... values) {
//         float max = Float.MIN_VALUE;
//         for (final float v : values) {
//             max = Math.max(v, max);
//         }
//         return max;
//     }
// 
//     public static float round(final float value, final float share) {
//         return (float) Math.floor(value * share) / share;
//     }
// 
//     public static RectF round(final RectF rect, final float share) {
//         rect.left = (float) Math.floor(rect.left * share) / share;
//         rect.top = (float) Math.floor(rect.top * share) / share;
//         rect.right = (float) Math.floor(rect.right * share) / share;
//         rect.bottom = (float) Math.floor(rect.bottom * share) / share;
//         return rect;
//     }
// 
//     public static RectF floor(final RectF rect) {
//         rect.left = (float) Math.floor(rect.left);
//         rect.top = (float) Math.floor(rect.top);
//         rect.right = (float) Math.floor(rect.right);
//         rect.bottom = (float) Math.floor(rect.bottom);
//         return rect;
//     }
// 
//     public static RectF ceil(final RectF rect) {
//         rect.left = (float) Math.ceil(rect.left);
//         rect.top = (float) Math.ceil(rect.top);
//         rect.right = (float) Math.ceil(rect.right);
//         rect.bottom = (float) Math.ceil(rect.bottom);
//         return rect;
//     }
// 
//     public static RectF round(final RectF rect) {
//         rect.left = (float) Math.floor(rect.left);
//         rect.top = (float) Math.floor(rect.top);
//         rect.right = (float) Math.ceil(rect.right);
//         rect.bottom = (float) Math.ceil(rect.bottom);
//         return rect;
//     }
// 
//     public static int nextPowerOf2(int n) {
//         if (n <= 0 || n > (1 << 30)) {
//             throw new IllegalArgumentException();
//         }
//         n -= 1;
//         n |= n >> 16;
//         n |= n >> 8;
//         n |= n >> 4;
//         n |= n >> 2;
//         n |= n >> 1;
//         return n + 1;
//     }
// 
//     public static int prevPowerOf2(final int n) {
//         if (n <= 0) {
//             throw new IllegalArgumentException();
//         }
//         return Integer.highestOneBit(n);
//     }
// 
//     public static boolean isOpaque(final int color) {
//         return color >>> 24 == 0xFF;
//     }
// }


// Path: src/org/ebookdroid/common/bitmaps/GLBitmaps.java
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;

                }
            }
        }
    }

    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);