diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2013-06-19 15:29:44 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2013-06-20 16:45:35 +0200 |
commit | 0a927854a10e1e6b9770a81e2e1d9f3093631757 (patch) | |
tree | 3d65d820d9fdba2d0d394d99c36290c851b78ca0 /android/src/com/artifex/mupdfdemo/PageView.java | |
parent | 1ae8f19179c5f0f8c6352b3c7855465325d5449a (diff) | |
download | mupdf-0a927854a10e1e6b9770a81e2e1d9f3093631757.tar.xz |
Rearrange source files.
Diffstat (limited to 'android/src/com/artifex/mupdfdemo/PageView.java')
-rw-r--r-- | android/src/com/artifex/mupdfdemo/PageView.java | 704 |
1 files changed, 0 insertions, 704 deletions
diff --git a/android/src/com/artifex/mupdfdemo/PageView.java b/android/src/com/artifex/mupdfdemo/PageView.java deleted file mode 100644 index 200821dd..00000000 --- a/android/src/com/artifex/mupdfdemo/PageView.java +++ /dev/null @@ -1,704 +0,0 @@ -package com.artifex.mupdfdemo; - -import java.util.ArrayList; -import java.util.Iterator; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Point; -import android.graphics.PointF; -import android.graphics.Rect; -import android.graphics.RectF; -import android.os.Handler; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.ProgressBar; - -class PatchInfo { - public BitmapHolder bmh; - public Bitmap bm; - public Point patchViewSize; - public Rect patchArea; - public boolean completeRedraw; - - public PatchInfo(Point aPatchViewSize, Rect aPatchArea, BitmapHolder aBmh, boolean aCompleteRedraw) { - bmh = aBmh; - bm = null; - patchViewSize = aPatchViewSize; - patchArea = aPatchArea; - completeRedraw = aCompleteRedraw; - } -} - -// Make our ImageViews opaque to optimize redraw -class OpaqueImageView extends ImageView { - - public OpaqueImageView(Context context) { - super(context); - } - - @Override - public boolean isOpaque() { - return true; - } -} - -interface TextProcessor { - void onStartLine(); - void onWord(TextWord word); - void onEndLine(); -} - -class TextSelector { - final private TextWord[][] mText; - final private RectF mSelectBox; - - public TextSelector(TextWord[][] text, RectF selectBox) { - mText = text; - mSelectBox = selectBox; - } - - public void select(TextProcessor tp) { - if (mText == null || mSelectBox == null) - return; - - ArrayList<TextWord[]> lines = new ArrayList<TextWord[]>(); - for (TextWord[] line : mText) - if (line[0].bottom > mSelectBox.top && line[0].top < mSelectBox.bottom) - lines.add(line); - - Iterator<TextWord[]> it = lines.iterator(); - while (it.hasNext()) { - TextWord[] line = it.next(); - boolean firstLine = line[0].top < mSelectBox.top; - boolean lastLine = line[0].bottom > mSelectBox.bottom; - float start = Float.NEGATIVE_INFINITY; - float end = Float.POSITIVE_INFINITY; - - if (firstLine && lastLine) { - start = Math.min(mSelectBox.left, mSelectBox.right); - end = Math.max(mSelectBox.left, mSelectBox.right); - } else if (firstLine) { - start = mSelectBox.left; - } else if (lastLine) { - end = mSelectBox.right; - } - - tp.onStartLine(); - - for (TextWord word : line) - if (word.right > start && word.left < end) - tp.onWord(word); - - tp.onEndLine(); - } - } -} - -public abstract class PageView extends ViewGroup { - private static final int HIGHLIGHT_COLOR = 0x802572AC; - private static final int LINK_COLOR = 0x80AC7225; - private static final int BOX_COLOR = 0xFF4444FF; - private static final int INK_COLOR = 0xFFFF0000; - private static final float INK_THICKNESS = 10.0f; - private static final int BACKGROUND_COLOR = 0xFFFFFFFF; - private static final int PROGRESS_DIALOG_DELAY = 200; - protected final Context mContext; - protected int mPageNumber; - private Point mParentSize; - protected Point mSize; // Size of page at minimum zoom - protected float mSourceScale; - - private ImageView mEntire; // Image rendered at minimum zoom - private BitmapHolder mEntireBmh; - private AsyncTask<Void,Void,TextWord[][]> mGetText; - private AsyncTask<Void,Void,LinkInfo[]> mGetLinkInfo; - private AsyncTask<Void,Void,Bitmap> mDrawEntire; - - private Point mPatchViewSize; // View size on the basis of which the patch was created - private Rect mPatchArea; - private ImageView mPatch; - private BitmapHolder mPatchBmh; - private AsyncTask<PatchInfo,Void,PatchInfo> mDrawPatch; - private RectF mSearchBoxes[]; - protected LinkInfo mLinks[]; - private RectF mSelectBox; - private TextWord mText[][]; - private RectF mItemSelectBox; - protected ArrayList<ArrayList<PointF>> mDrawing; - private View mSearchView; - private boolean mIsBlank; - private boolean mHighlightLinks; - - private ProgressBar mBusyIndicator; - private final Handler mHandler = new Handler(); - - public PageView(Context c, Point parentSize) { - super(c); - mContext = c; - mParentSize = parentSize; - setBackgroundColor(BACKGROUND_COLOR); - mEntireBmh = new BitmapHolder(); - mPatchBmh = new BitmapHolder(); - } - - protected abstract Bitmap drawPage(int sizeX, int sizeY, int patchX, int patchY, int patchWidth, int patchHeight); - protected abstract Bitmap updatePage(BitmapHolder h, int sizeX, int sizeY, int patchX, int patchY, int patchWidth, int patchHeight); - protected abstract LinkInfo[] getLinkInfo(); - protected abstract TextWord[][] getText(); - protected abstract void addMarkup(PointF[] quadPoints, Annotation.Type type); - - private void reinit() { - // Cancel pending render task - if (mDrawEntire != null) { - mDrawEntire.cancel(true); - mDrawEntire = null; - } - - if (mDrawPatch != null) { - mDrawPatch.cancel(true); - mDrawPatch = null; - } - - if (mGetLinkInfo != null) { - mGetLinkInfo.cancel(true); - mGetLinkInfo = null; - } - - if (mGetText != null) { - mGetText.cancel(true); - mGetText = null; - } - - mIsBlank = true; - mPageNumber = 0; - - if (mSize == null) - mSize = mParentSize; - - if (mEntire != null) { - mEntire.setImageBitmap(null); - mEntireBmh.setBm(null); - } - - if (mPatch != null) { - mPatch.setImageBitmap(null); - mPatchBmh.setBm(null); - } - - mPatchViewSize = null; - mPatchArea = null; - - mSearchBoxes = null; - mLinks = null; - mSelectBox = null; - mText = null; - mItemSelectBox = null; - } - - public void releaseResources() { - reinit(); - - if (mBusyIndicator != null) { - removeView(mBusyIndicator); - mBusyIndicator = null; - } - } - - public void blank(int page) { - reinit(); - mPageNumber = page; - - if (mBusyIndicator == null) { - mBusyIndicator = new ProgressBar(mContext); - mBusyIndicator.setIndeterminate(true); - mBusyIndicator.setBackgroundResource(R.drawable.busy); - addView(mBusyIndicator); - } - - setBackgroundColor(BACKGROUND_COLOR); - } - - public void setPage(int page, PointF size) { - // Cancel pending render task - if (mDrawEntire != null) { - mDrawEntire.cancel(true); - mDrawEntire = null; - } - - mIsBlank = false; - // Highlights may be missing because mIsBlank was true on last draw - if (mSearchView != null) - mSearchView.invalidate(); - - mPageNumber = page; - if (mEntire == null) { - mEntire = new OpaqueImageView(mContext); - mEntire.setScaleType(ImageView.ScaleType.FIT_CENTER); - addView(mEntire); - } - - // Calculate scaled size that fits within the screen limits - // This is the size at minimum zoom - mSourceScale = Math.min(mParentSize.x/size.x, mParentSize.y/size.y); - Point newSize = new Point((int)(size.x*mSourceScale), (int)(size.y*mSourceScale)); - mSize = newSize; - - mEntire.setImageBitmap(null); - mEntireBmh.setBm(null); - - // Get the link info in the background - mGetLinkInfo = new AsyncTask<Void,Void,LinkInfo[]>() { - protected LinkInfo[] doInBackground(Void... v) { - return getLinkInfo(); - } - - protected void onPostExecute(LinkInfo[] v) { - mLinks = v; - invalidate(); - } - }; - - mGetLinkInfo.execute(); - - // Render the page in the background - mDrawEntire = new AsyncTask<Void,Void,Bitmap>() { - protected Bitmap doInBackground(Void... v) { - return drawPage(mSize.x, mSize.y, 0, 0, mSize.x, mSize.y); - } - - protected void onPreExecute() { - setBackgroundColor(BACKGROUND_COLOR); - mEntire.setImageBitmap(null); - mEntireBmh.setBm(null); - - if (mBusyIndicator == null) { - mBusyIndicator = new ProgressBar(mContext); - mBusyIndicator.setIndeterminate(true); - mBusyIndicator.setBackgroundResource(R.drawable.busy); - addView(mBusyIndicator); - mBusyIndicator.setVisibility(INVISIBLE); - mHandler.postDelayed(new Runnable() { - public void run() { - if (mBusyIndicator != null) - mBusyIndicator.setVisibility(VISIBLE); - } - }, PROGRESS_DIALOG_DELAY); - } - } - - protected void onPostExecute(Bitmap bm) { - removeView(mBusyIndicator); - mBusyIndicator = null; - mEntire.setImageBitmap(bm); - mEntireBmh.setBm(bm); - setBackgroundColor(Color.TRANSPARENT); - } - }; - - mDrawEntire.execute(); - - if (mSearchView == null) { - mSearchView = new View(mContext) { - @Override - protected void onDraw(final Canvas canvas) { - super.onDraw(canvas); - // Work out current total scale factor - // from source to view - final float scale = mSourceScale*(float)getWidth()/(float)mSize.x; - final Paint paint = new Paint(); - - if (!mIsBlank && mSearchBoxes != null) { - paint.setColor(HIGHLIGHT_COLOR); - for (RectF rect : mSearchBoxes) - canvas.drawRect(rect.left*scale, rect.top*scale, - rect.right*scale, rect.bottom*scale, - paint); - } - - if (!mIsBlank && mLinks != null && mHighlightLinks) { - paint.setColor(LINK_COLOR); - for (LinkInfo link : mLinks) - canvas.drawRect(link.rect.left*scale, link.rect.top*scale, - link.rect.right*scale, link.rect.bottom*scale, - paint); - } - - if (mSelectBox != null && mText != null) { - paint.setColor(HIGHLIGHT_COLOR); - processSelectedText(new TextProcessor() { - RectF rect; - - public void onStartLine() { - rect = new RectF(); - } - - public void onWord(TextWord word) { - rect.union(word); - } - - public void onEndLine() { - if (!rect.isEmpty()) - canvas.drawRect(rect.left*scale, rect.top*scale, rect.right*scale, rect.bottom*scale, paint); - } - }); - } - - if (mItemSelectBox != null) { - paint.setStyle(Paint.Style.STROKE); - paint.setColor(BOX_COLOR); - canvas.drawRect(mItemSelectBox.left*scale, mItemSelectBox.top*scale, mItemSelectBox.right*scale, mItemSelectBox.bottom*scale, paint); - } - - if (mDrawing != null) { - Path path = new Path(); - PointF p; - Iterator<ArrayList<PointF>> it = mDrawing.iterator(); - while (it.hasNext()) { - ArrayList<PointF> arc = it.next(); - if (arc.size() >= 2) { - Iterator<PointF> iit = arc.iterator(); - p = iit.next(); - float mX = p.x * scale; - float mY = p.y * scale; - path.moveTo(mX, mY); - while (iit.hasNext()) { - p = iit.next(); - float x = p.x * scale; - float y = p.y * scale; - path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); - mX = x; - mY = y; - } - path.lineTo(mX, mY); - } - } - - paint.setAntiAlias(true); - paint.setDither(true); - paint.setStrokeJoin(Paint.Join.ROUND); - paint.setStrokeCap(Paint.Cap.ROUND); - - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(INK_THICKNESS * scale); - paint.setColor(INK_COLOR); - - canvas.drawPath(path, paint); - } - } - }; - - addView(mSearchView); - } - requestLayout(); - } - - public void setSearchBoxes(RectF searchBoxes[]) { - mSearchBoxes = searchBoxes; - if (mSearchView != null) - mSearchView.invalidate(); - } - - public void setLinkHighlighting(boolean f) { - mHighlightLinks = f; - if (mSearchView != null) - mSearchView.invalidate(); - } - - public void deselectText() { - mSelectBox = null; - mSearchView.invalidate(); - } - - public void selectText(float x0, float y0, float x1, float y1) { - float scale = mSourceScale*(float)getWidth()/(float)mSize.x; - float docRelX0 = (x0 - getLeft())/scale; - float docRelY0 = (y0 - getTop())/scale; - float docRelX1 = (x1 - getLeft())/scale; - float docRelY1 = (y1 - getTop())/scale; - // Order on Y but maintain the point grouping - if (docRelY0 <= docRelY1) - mSelectBox = new RectF(docRelX0, docRelY0, docRelX1, docRelY1); - else - mSelectBox = new RectF(docRelX1, docRelY1, docRelX0, docRelY0); - - mSearchView.invalidate(); - - if (mGetText == null) { - mGetText = new AsyncTask<Void,Void,TextWord[][]>() { - @Override - protected TextWord[][] doInBackground(Void... params) { - return getText(); - } - @Override - protected void onPostExecute(TextWord[][] result) { - mText = result; - mSearchView.invalidate(); - } - }; - - mGetText.execute(); - } - } - - public void startDraw(float x, float y) { - float scale = mSourceScale*(float)getWidth()/(float)mSize.x; - float docRelX = (x - getLeft())/scale; - float docRelY = (y - getTop())/scale; - if (mDrawing == null) - mDrawing = new ArrayList<ArrayList<PointF>>(); - - ArrayList<PointF> arc = new ArrayList<PointF>(); - arc.add(new PointF(docRelX, docRelY)); - mDrawing.add(arc); - } - - public void continueDraw(float x, float y) { - float scale = mSourceScale*(float)getWidth()/(float)mSize.x; - float docRelX = (x - getLeft())/scale; - float docRelY = (y - getTop())/scale; - - if (mDrawing != null && mDrawing.size() > 0) { - ArrayList<PointF> arc = mDrawing.get(mDrawing.size() - 1); - arc.add(new PointF(docRelX, docRelY)); - mSearchView.invalidate(); - } - } - - public void cancelDraw() { - mDrawing = null; - mSearchView.invalidate(); - } - - protected PointF[][] getDraw() { - if (mDrawing == null) - return null; - - PointF[][] path = new PointF[mDrawing.size()][]; - - for (int i = 0; i < mDrawing.size(); i++) { - ArrayList<PointF> arc = mDrawing.get(i); - path[i] = arc.toArray(new PointF[arc.size()]); - } - - return path; - } - - protected void processSelectedText(TextProcessor tp) { - (new TextSelector(mText, mSelectBox)).select(tp); - } - - public void setItemSelectBox(RectF rect) { - mItemSelectBox = rect; - if (mSearchView != null) - mSearchView.invalidate(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int x, y; - switch(View.MeasureSpec.getMode(widthMeasureSpec)) { - case View.MeasureSpec.UNSPECIFIED: - x = mSize.x; - break; - default: - x = View.MeasureSpec.getSize(widthMeasureSpec); - } - switch(View.MeasureSpec.getMode(heightMeasureSpec)) { - case View.MeasureSpec.UNSPECIFIED: - y = mSize.y; - break; - default: - y = View.MeasureSpec.getSize(heightMeasureSpec); - } - - setMeasuredDimension(x, y); - - if (mBusyIndicator != null) { - int limit = Math.min(mParentSize.x, mParentSize.y)/2; - mBusyIndicator.measure(View.MeasureSpec.AT_MOST | limit, View.MeasureSpec.AT_MOST | limit); - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - int w = right-left; - int h = bottom-top; - - if (mEntire != null) { - mEntire.layout(0, 0, w, h); - } - - if (mSearchView != null) { - mSearchView.layout(0, 0, w, h); - } - - if (mPatchViewSize != null) { - if (mPatchViewSize.x != w || mPatchViewSize.y != h) { - // Zoomed since patch was created - mPatchViewSize = null; - mPatchArea = null; - if (mPatch != null) { - mPatch.setImageBitmap(null); - mPatchBmh.setBm(null); - } - } else { - mPatch.layout(mPatchArea.left, mPatchArea.top, mPatchArea.right, mPatchArea.bottom); - } - } - - if (mBusyIndicator != null) { - int bw = mBusyIndicator.getMeasuredWidth(); - int bh = mBusyIndicator.getMeasuredHeight(); - - mBusyIndicator.layout((w-bw)/2, (h-bh)/2, (w+bw)/2, (h+bh)/2); - } - } - - public void addHq(boolean update) { - Rect viewArea = new Rect(getLeft(),getTop(),getRight(),getBottom()); - // If the viewArea's size matches the unzoomed size, there is no need for an hq patch - if (viewArea.width() != mSize.x || viewArea.height() != mSize.y) { - Point patchViewSize = new Point(viewArea.width(), viewArea.height()); - Rect patchArea = new Rect(0, 0, mParentSize.x, mParentSize.y); - - // Intersect and test that there is an intersection - if (!patchArea.intersect(viewArea)) - return; - - // Offset patch area to be relative to the view top left - patchArea.offset(-viewArea.left, -viewArea.top); - - boolean area_unchanged = patchArea.equals(mPatchArea) && patchViewSize.equals(mPatchViewSize); - - // If being asked for the same area as last time and not because of an update then nothing to do - if (area_unchanged && !update) - return; - - boolean completeRedraw = !(area_unchanged && update); - - // Stop the drawing of previous patch if still going - if (mDrawPatch != null) { - mDrawPatch.cancel(true); - mDrawPatch = null; - } - - if (completeRedraw) { - // The bitmap holder mPatchBm may still be rendered to by a - // previously invoked task, and possibly for a different - // area, so we cannot risk the bitmap generated by this task - // being passed to it - mPatchBmh.drop(); - mPatchBmh = new BitmapHolder(); - } - - // Create and add the image view if not already done - if (mPatch == null) { - mPatch = new OpaqueImageView(mContext); - mPatch.setScaleType(ImageView.ScaleType.FIT_CENTER); - addView(mPatch); - mSearchView.bringToFront(); - } - - mDrawPatch = new AsyncTask<PatchInfo,Void,PatchInfo>() { - protected PatchInfo doInBackground(PatchInfo... v) { - if (v[0].completeRedraw) { - v[0].bm = drawPage(v[0].patchViewSize.x, v[0].patchViewSize.y, - v[0].patchArea.left, v[0].patchArea.top, - v[0].patchArea.width(), v[0].patchArea.height()); - } else { - v[0].bm = updatePage(v[0].bmh, v[0].patchViewSize.x, v[0].patchViewSize.y, - v[0].patchArea.left, v[0].patchArea.top, - v[0].patchArea.width(), v[0].patchArea.height()); - } - - return v[0]; - } - - protected void onPostExecute(PatchInfo v) { - if (mPatchBmh == v.bmh) { - mPatchViewSize = v.patchViewSize; - mPatchArea = v.patchArea; - if (v.bm != null) { - mPatch.setImageBitmap(v.bm); - v.bmh.setBm(v.bm); - v.bm = null; - } - //requestLayout(); - // Calling requestLayout here doesn't lead to a later call to layout. No idea - // why, but apparently others have run into the problem. - mPatch.layout(mPatchArea.left, mPatchArea.top, mPatchArea.right, mPatchArea.bottom); - invalidate(); - } - } - }; - - mDrawPatch.execute(new PatchInfo(patchViewSize, patchArea, mPatchBmh, completeRedraw)); - } - } - - public void update() { - // Cancel pending render task - if (mDrawEntire != null) { - mDrawEntire.cancel(true); - mDrawEntire = null; - } - - if (mDrawPatch != null) { - mDrawPatch.cancel(true); - mDrawPatch = null; - } - - // Render the page in the background - mDrawEntire = new AsyncTask<Void,Void,Bitmap>() { - protected Bitmap doInBackground(Void... v) { - // Pass the current bitmap as a basis for the update, but use a bitmap - // holder so that the held bitmap will be nulled and not hold on to - // memory, should this view become redundant. - return updatePage(mEntireBmh, mSize.x, mSize.y, 0, 0, mSize.x, mSize.y); - } - - protected void onPostExecute(Bitmap bm) { - if (bm != null) { - mEntire.setImageBitmap(bm); - mEntireBmh.setBm(bm); - } - invalidate(); - } - }; - - mDrawEntire.execute(); - - addHq(true); - } - - public void removeHq() { - // Stop the drawing of the patch if still going - if (mDrawPatch != null) { - mDrawPatch.cancel(true); - mDrawPatch = null; - } - - // And get rid of it - mPatchViewSize = null; - mPatchArea = null; - if (mPatch != null) { - mPatch.setImageBitmap(null); - mPatchBmh.setBm(null); - } - } - - public int getPage() { - return mPageNumber; - } - - @Override - public boolean isOpaque() { - return true; - } -} |