package org.ebookdroid.core;
import org.sufficientlysecure.viewer.R;
import org.ebookdroid.common.settings.AppSettings;
import org.ebookdroid.core.codec.PageLink;
import org.ebookdroid.core.models.SearchModel;
import org.ebookdroid.core.models.SearchModel.Matches;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.RectF;
import android.text.TextPaint;
import java.util.List;
import java.util.Queue;
import org.emdev.BaseDroidApp;
import org.emdev.common.log.LogContext;
import org.emdev.common.log.LogManager;
import org.emdev.ui.gl.GLCanvas;
import org.emdev.ui.gl.StringTexture;
import org.emdev.utils.LengthUtils;
public class EventGLDraw implements IEvent {
public final static LogContext LCTX = LogManager.root().lctx("EventDraw", false);
private static final Paint LINK_PAINT = new Paint();
private static final Paint BRIGHTNESS_FILTER = new Paint();
private static final StringTexture t = new StringTexture(256, 128);
private final Queue<EventGLDraw> eventQueue;
public ViewState viewState;
public PageTreeLevel level;
public GLCanvas canvas;
Paint brightnessFilter;
RectF pageBounds;
final RectF fixedPageBounds = new RectF();
EventGLDraw(final Queue<EventGLDraw> eventQueue) {
this.eventQueue = eventQueue;
}
void init(final ViewState viewState, final GLCanvas canvas) {
this.viewState = viewState;
this.level = PageTreeLevel.getLevel(viewState.zoom);
this.canvas = canvas;
}
void init(final EventGLDraw event, final GLCanvas canvas) {
this.viewState = event.viewState;
this.level = event.level;
this.canvas = canvas;
}
void release() {
this.canvas = null;
this.level = null;
this.pageBounds = null;
this.viewState = null;
eventQueue.offer(this);
}
@Override
public ViewState process() {
try {
if (canvas == null || viewState == null) {
return viewState;
}
canvas.clearBuffer(viewState.paint.backgroundFillPaint);
viewState.ctrl.drawView(this);
return viewState;
} finally {
release();
}
}
@Override
public boolean process(final Page page) {
pageBounds = viewState.getBounds(page);
fixedPageBounds.set(pageBounds);
fixedPageBounds.offset(-viewState.viewBase.x, -viewState.viewBase.y);
canvas.setClipRect(fixedPageBounds);
try {
if (LCTX.isDebugEnabled()) {
LCTX.d("process(" + page.index + "): view=" + viewState.viewRect + ", page=" + pageBounds);
}
drawPageBackground(page);
final boolean res = page.nodes.process(this, level, false);
if (res) {
drawPageLinks(page);
drawHighlights(page);
}
return res;
} finally {
canvas.clearClipRect();
}
}
@Override
public boolean process(final PageTree nodes) {
return process(nodes, level);
}
@Override
public boolean process(final PageTree nodes, final PageTreeLevel level) {
return nodes.process(this, level, false);
}
@Override
public boolean process(final PageTreeNode node) {
final RectF nodeRect = node.getTargetRect(pageBounds);
if (LCTX.isDebugEnabled()) {
LCTX.d("process(" + node.fullId + "): view=" + viewState.viewRect + ", page=" + pageBounds + ", node="
+ nodeRect);
}
if (!viewState.isNodeVisible(nodeRect)) {
return false;
}
try {
if (node.holder.drawBitmap(canvas, viewState.paint, viewState.viewBase, nodeRect, nodeRect)) {
return true;
}
if (node.parent != null) {
final RectF parentRect = node.parent.getTargetRect(pageBounds);
if (node.parent.holder.drawBitmap(canvas, viewState.paint, viewState.viewBase, parentRect, nodeRect)) {
return true;
}
}
return node.page.nodes.paintChildren(this, node, nodeRect);
} finally {
drawBrightnessFilter(nodeRect);
}
}
public boolean paintChild(final PageTreeNode node, final PageTreeNode child, final RectF nodeRect) {
final RectF childRect = child.getTargetRect(pageBounds);
return child.holder.drawBitmap(canvas, viewState.paint, viewState.viewBase, childRect, nodeRect);
}
protected void drawPageBackground(final Page page) {
canvas.fillRect(fixedPageBounds, viewState.paint.fillPaint);
}
protected void drawPageNumber(final Page page) {
final TextPaint textPaint = viewState.paint.textPaint;
textPaint.setTextSize(24 * viewState.zoom);
textPaint.setTextAlign(Align.LEFT);
final int offset = viewState.book != null ? viewState.book.firstPageOffset : 1;
final String text = BaseDroidApp.context.getString(R.string.text_page) + " " + (page.index.viewIndex + offset);
t.setText(text, textPaint);
final int w = t.getTextWidth();
final int h = t.getTextHeight();
t.draw(canvas, (int) fixedPageBounds.centerX() - w / 2, (int) fixedPageBounds.centerY() - h / 2);
}
private void drawPageLinks(final Page page) {
if (LengthUtils.isEmpty(page.links)) {
return;
}
for (final PageLink link : page.links) {
final RectF rect = page.getLinkSourceRect(pageBounds, link);
if (rect != null) {
rect.offset(-viewState.viewBase.x, -viewState.viewBase.y);
LINK_PAINT.setColor(AppSettings.current().linkHighlightColor);
canvas.fillRect(rect, LINK_PAINT);
}
}
}
private void drawHighlights(final Page page) {
final SearchModel sm = viewState.ctrl.getBase().getSearchModel();
final Matches matches = sm.getMatches(page);
final List<? extends RectF> mm = matches != null ? matches.getMatches() : null;
if (LengthUtils.isEmpty(mm)) {
return;
}
final AppSettings app = AppSettings.current();
final Paint p = new Paint();
final Page cp = sm.getCurrentPage();
final int cmi = sm.getCurrentMatchIndex();
for (int i = 0; i < mm.size(); i++) {
final boolean current = page == cp && i == cmi;
final RectF link = mm.get(i);
final RectF rect = page.getPageRegion(pageBounds, new RectF(link));
rect.offset(-viewState.viewBase.x, -viewState.viewBase.y);
p.setColor(current ? app.currentSearchHighlightColor : app.searchHighlightColor);
canvas.fillRect(rect, p);
}
}
protected void drawBrightnessFilter(final RectF nodeRect) {
if (viewState.app.brightnessInNightModeOnly && !viewState.nightMode) {
return;
}
if (viewState.app.brightness >= 100) {
return;
}
final int alpha = 255 - viewState.app.brightness * 255 / 100;
BRIGHTNESS_FILTER.setColor(Color.BLACK);
BRIGHTNESS_FILTER.setAlpha(alpha);
canvas.fillRect(fixedPageBounds, BRIGHTNESS_FILTER);
}
}