package org.ebookdroid.core;
import org.ebookdroid.common.bitmaps.GLBitmaps;
import android.graphics.RectF;
import java.util.List;
public class PageTree {
// private static final LogContext LCTX = Page.LCTX;
static RectF[] splitMasks = {
// Left Top
new RectF(0, 0, 0.5f, 0.5f),
// Right top
new RectF(0.5f, 0, 1.0f, 0.5f),
// Left Bottom
new RectF(0, 0.5f, 0.5f, 1.0f),
// Right Bottom
new RectF(0.5f, 0.5f, 1.0f, 1.0f), };
final Page owner;
public final PageTreeNode root;
private PageTreeNode[] treeNodes;
private volatile int maxNodeId;
public PageTree(final Page owner) {
this.owner = owner;
this.root = new PageTreeNode(owner);
this.maxNodeId = 1;
}
private synchronized PageTreeNode[] getNodes() {
if (this.treeNodes == null) {
this.treeNodes = new PageTreeNode[PageTreeLevel.NODES];
this.treeNodes[0] = root;
}
return this.treeNodes;
}
public boolean process(final IEvent event, final PageTreeLevel level, final boolean createNodes) {
boolean res = false;
if (createNodes || level.start < maxNodeId) {
final PageTreeNode[] nodes = getNodes();
for (int nodeIndex = level.start; nodeIndex < level.end; nodeIndex++) {
if (nodes[nodeIndex] == null) {
createChildren(getParent(nodeIndex, true));
}
res |= event.process(nodes[nodeIndex]);
}
}
return res;
}
public boolean paintChildren(final EventGLDraw event, final PageTreeNode node, final RectF nodeRect) {
boolean res = false;
int childId = PageTree.getFirstChildId(node.id);
if (childId < maxNodeId) {
final PageTreeNode[] nodes = getNodes();
for (final int end = Math.min(nodes.length, childId + PageTree.splitMasks.length); childId < end; childId++) {
final PageTreeNode child = nodes[childId];
if (child != null) {
res |= event.paintChild(node, child, nodeRect);
}
}
}
return res;
}
public boolean createChildren(final PageTreeNode parent) {
final PageTreeNode[] nodes = getNodes();
int childId = getFirstChildId(parent.id);
for (int i = 0; i < splitMasks.length; i++, childId++) {
if (nodes[childId] == null) {
nodes[childId] = new PageTreeNode(owner, parent, childId, splitMasks[i]);
}
}
maxNodeId = Math.max(maxNodeId, childId);
return true;
}
public PageTreeNode getParent(final int nodeIndex, final boolean create) {
if (nodeIndex == 0) {
return null;
}
if (nodeIndex >= maxNodeId && !create) {
return null;
}
final PageTreeNode[] nodes = getNodes();
final int parentIndex = (nodeIndex - 1) / 4;
if (nodes[parentIndex] == null && create) {
createChildren(getParent(parentIndex, true));
}
return nodes[parentIndex];
}
public boolean recycleAll(final List<GLBitmaps> bitmapsToRecycle, final boolean includeRoot) {
boolean res = false;
if (includeRoot) {
res |= root.recycle(bitmapsToRecycle);
}
if (maxNodeId > 1) {
final PageTreeNode[] nodes = getNodes();
for (int index = 1; index < maxNodeId; index++) {
if (nodes[index] != null) {
res |= nodes[index].recycle(bitmapsToRecycle);
nodes[index] = null;
}
}
}
maxNodeId = 1;
return res;
}
public boolean recycleParents(final PageTreeNode child, final List<GLBitmaps> bitmapsToRecycle) {
if (child.id == 0) {
return false;
}
boolean res = false;
int childId = child.id;
for (PageTreeNode p = getParent(childId, false); p != null; p = getParent(childId, false)) {
res |= p.recycle(bitmapsToRecycle);
childId = p.id;
if (child.id == 0) {
break;
}
}
return res;
}
public boolean recycleChildren(final PageTreeNode node, final List<GLBitmaps> bitmapsToRecycle) {
boolean res = false;
int childId = getFirstChildId(node.id);
if (childId >= maxNodeId) {
return res;
}
final PageTreeNode[] nodes = getNodes();
for (final int end = Math.min(nodes.length, childId + splitMasks.length); childId < end; childId++) {
if (nodes[childId] != null) {
res |= nodes[childId].recycle(bitmapsToRecycle);
nodes[childId] = null;
}
}
if (childId >= maxNodeId) {
if (childId >= nodes.length) {
maxNodeId = nodes.length - 1;
}
while (maxNodeId > 0 && nodes[maxNodeId] == null) {
maxNodeId--;
}
maxNodeId++;
}
return res;
}
public void recycleNodes(final PageTreeLevel level, final List<GLBitmaps> bitmapsToRecycle) {
if (level.start >= maxNodeId) {
return;
}
final PageTreeNode[] nodes = getNodes();
for (int i = level.start; i < maxNodeId; i++) {
if (nodes[i] != null) {
nodes[i].recycle(bitmapsToRecycle);
nodes[i] = null;
}
}
maxNodeId = level.start;
while (maxNodeId > 0 && nodes[maxNodeId] == null) {
maxNodeId--;
}
maxNodeId++;
}
public boolean isHiddenByChildren(final PageTreeNode parent, final ViewState viewState, final RectF pageBounds) {
int childId = getFirstChildId(parent.id);
if (childId >= maxNodeId) {
return false;
}
final PageTreeNode[] nodes = getNodes();
for (final int end = Math.min(nodes.length, childId + splitMasks.length); childId < end; childId++) {
final PageTreeNode child = nodes[childId];
if (child == null) {
return false;
}
if (viewState.isNodeKeptInMemory(child, pageBounds) && !child.holder.hasBitmaps()) {
return false;
}
}
return true;
}
static int getFirstChildId(final long parentId) {
return (int) (parentId * splitMasks.length + 1);
}
}