package org.ebookdroid.droids.fb2.codec;
import org.ebookdroid.common.bitmaps.BitmapManager;
import org.ebookdroid.common.bitmaps.ByteBufferBitmap;
import org.ebookdroid.common.bitmaps.IBitmapRef;
import org.ebookdroid.core.ViewState;
import org.ebookdroid.core.codec.AbstractCodecPage;
import org.ebookdroid.core.codec.CodecPageInfo;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import java.util.ArrayList;
import java.util.List;
import org.emdev.common.textmarkup.JustificationMode;
import org.emdev.common.textmarkup.TextStyle;
import org.emdev.common.textmarkup.line.AbstractLineElement;
import org.emdev.common.textmarkup.line.Line;
import org.emdev.common.textmarkup.line.LineFixedWhiteSpace;
import org.emdev.common.textmarkup.line.LineWhiteSpace;
import org.emdev.common.textmarkup.line.TextElement;
import org.emdev.utils.LengthUtils;
import org.emdev.utils.MatrixUtils;
public class FB2Page extends AbstractCodecPage {
public static final int PAGE_WIDTH = 800;
public static final int PAGE_HEIGHT = 1280;
public static final CodecPageInfo CPI = new CodecPageInfo(PAGE_WIDTH, PAGE_HEIGHT);
public static final int MARGIN_X = 20;
public static final int MARGIN_Y = 20;
static final RectF PAGE_RECT = new RectF(0, 0, PAGE_WIDTH, PAGE_HEIGHT);
final ArrayList<Line> lines = new ArrayList<Line>(PAGE_HEIGHT / TextStyle.TEXT.getFontSize());
final ArrayList<Line> noteLines = new ArrayList<Line>(PAGE_HEIGHT / TextStyle.FOOTNOTE.getFontSize());
boolean committed = false;
int contentHeight = 0;
@Override
public int getHeight() {
return PAGE_HEIGHT;
}
@Override
public int getWidth() {
return PAGE_WIDTH;
}
@Override
public List<? extends RectF> searchText(final String pattern) {
final List<RectF> rects = new ArrayList<RectF>();
final char[] charArray = pattern.toCharArray();
final float y = searchText(lines, charArray, rects, FB2Page.MARGIN_Y);
searchText(noteLines, charArray, rects, y);
return rects;
}
private float searchText(final ArrayList<Line> lines, final char[] pattern, final List<RectF> rects, float y) {
for (int i = 0, n = lines.size(); i < n; i++) {
final Line line = lines.get(i);
final float bottom = y + line.getHeight();
line.ensureJustification();
float x = FB2Page.MARGIN_X;
for (int i1 = 0, n1 = line.elements.size(); i1 < n1; i1++) {
final AbstractLineElement e = line.elements.get(i1);
final float w = e.width + (e instanceof LineWhiteSpace ? line.spaceWidth : 0);
if (e instanceof TextElement) {
final TextElement textElement = (TextElement) e;
if (textElement.indexOfIgnoreCases(pattern) != -1) {
final Rect bounds = new Rect();
textElement.getTextBounds(bounds);
rects.add(new RectF((x - 3) / FB2Page.PAGE_WIDTH, (bottom + bounds.top - 3)
/ FB2Page.PAGE_HEIGHT, (x + w + 3) / FB2Page.PAGE_WIDTH, (bottom + bounds.bottom + 3)
/ FB2Page.PAGE_HEIGHT));
}
}
x += w;
}
y = bottom;
}
return y;
}
@Override
public void recycle() {
}
void finalRecycle() {
for (final Line l : lines) {
l.recycle();
}
lines.clear();
for (final Line l : noteLines) {
l.recycle();
}
}
@Override
public ByteBufferBitmap renderBitmap(final ViewState viewState, final int width, final int height,
final RectF pageSliceBounds) {
final int nightmode = viewState != null && viewState.nightMode && viewState.positiveImagesInNightMode ? 1 : 0;
final Matrix matrix = MatrixUtils.get();
matrix.postScale((float) width / PAGE_WIDTH, (float) height / PAGE_HEIGHT);
matrix.postTranslate(-pageSliceBounds.left * width, -pageSliceBounds.top * height);
matrix.postScale(1 / pageSliceBounds.width(), 1 / pageSliceBounds.height());
final IBitmapRef bmp = BitmapManager.getBitmap("FB2 page", width, height, Bitmap.Config.ARGB_8888);
final Canvas c = bmp.getCanvas();
c.setMatrix(matrix);
final Paint paint1 = new Paint();
paint1.setColor(Color.WHITE);
c.drawRect(PAGE_RECT, paint1);
final RectF bounds = new RectF(pageSliceBounds.left * PAGE_WIDTH, pageSliceBounds.top * PAGE_HEIGHT,
pageSliceBounds.right * PAGE_WIDTH, pageSliceBounds.bottom * PAGE_HEIGHT);
int y = MARGIN_Y;
for (int i = 0, n = lines.size(); i < n; i++) {
final Line line = lines.get(i);
final int top = y;
final int bottom = y + line.getHeight();
if (bounds.top < bottom && top < bounds.bottom) {
line.render(c, FB2Page.MARGIN_X, bottom, bounds.left, bounds.right, nightmode);
}
y = bottom;
}
for (int i = 0, n = noteLines.size(); i < n; i++) {
final Line line = noteLines.get(i);
final int top = y;
final int bottom = y + line.getHeight();
if (bounds.top < bottom && top < bounds.bottom) {
line.render(c, FB2Page.MARGIN_X, bottom, bounds.left, bounds.right, nightmode);
}
y = bottom;
}
final ByteBufferBitmap buffer = ByteBufferBitmap.get(bmp.getBitmap());
BitmapManager.release(bmp);
return buffer;
}
public void appendLine(final Line line) {
if (committed || !line.appendable()) {
return;
}
lines.add(line);
contentHeight += line.getHeight();
}
public void appendNoteLine(final Line line) {
noteLines.add(line);
contentHeight += line.getHeight();
}
public void commit(final ParsedContent content) {
if (committed) {
return;
}
final int h = FB2Page.PAGE_HEIGHT - contentHeight - 2 * FB2Page.MARGIN_Y;
if (h > 0) {
lines.add(new Line(content, 0, JustificationMode.Center).append(new LineFixedWhiteSpace(0, h)));
contentHeight += h;
}
for (final Line line : noteLines) {
lines.add(line);
}
noteLines.clear();
committed = true;
}
@Override
public boolean isRecycled() {
return false;
}
public boolean isEmpty() {
if (LengthUtils.isEmpty(lines) && LengthUtils.isEmpty(noteLines)) {
return true;
}
for (final Line l : lines) {
if (!l.isEmpty()) {
return false;
}
}
for (final Line l : noteLines) {
if (!l.isEmpty()) {
return false;
}
}
return true;
}
}