]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/glass/src/main/java/cz/cvut/fel/dce/qrscanner/pdfviewer/PdfPageView.java
Reimplemented the preview by using the pdfview widget
[hornmich/skoda-qr-demo.git] / QRScanner / glass / src / main / java / cz / cvut / fel / dce / qrscanner / pdfviewer / PdfPageView.java
1 package cz.cvut.fel.dce.qrscanner.pdfviewer;
2
3 import android.content.Context;
4 import android.graphics.Bitmap;
5 import android.graphics.Canvas;
6 import android.graphics.Paint;
7 import android.util.Log;
8 import android.view.View;
9
10 import java.io.File;
11 import java.sql.Time;
12
13 import cz.cvut.fel.dce.qrscanner.mupdf.MuPDFCore;
14
15 /**
16  * Created by Michal Horn on 16.2.15.
17  */
18 public class PdfPageView  extends View {
19         /**
20          * Value with some allowed minimum and maximum.
21          * @author Michal Horn
22          *
23          * @param <T> some comparable numeric data type
24          */
25         class IntervalValue<T extends Number & Comparable<? super T>> {
26                 /**
27                  * Stored value
28                  */
29                 private T mValue;
30                 /**
31                  * The lowest allowed value. All values stored in the object are
32                  * higher or equal this minimum.
33                  */
34                 private T mMinimum;
35                 /**
36                  * The highest allowed value. All values stored in the object are
37                  * lower or equal this maximum.
38                  */
39                 private T mMaximum;
40
41                 /**
42                  * Class constructor.
43                  * Creates object that represents a value in range <minimum; maximum>.
44                  *
45                  * @param defValue      Value to be stored in the object. Must be in the allowed range specified by other two parameters.
46                  * @param minimum       The lowes allowed value to be stored in the object.
47                  * @param maximum       The highest allowed value to be stored in the object.
48                  * @throws Exception Throwed when minimal, maximal or inserted value were rejected.
49                  */
50                 public IntervalValue(T defValue, T minimum, T maximum) throws Exception {
51                         setMinimum(minimum);
52                         setMaximum(maximum);
53                         if (!setValue(defValue)) {
54                                 throw new Exception("Provided value is not in the range.");
55                         }
56                 }
57
58                 /**
59                  * Store value in the object. The value must lie between the minimum and maximum
60                  * defined for the object.
61                  * @param value value to be stored in the object
62                  * @return true - vale was stored successfully,<br>false - value could not be inserted because it was out of range.
63                  */
64                 public boolean setValue(T value) {
65                         if (value.compareTo(mMinimum) >= 0 && value.compareTo(mMaximum) <= 0) {
66                                 mValue = value;
67                                 return true;
68                         }
69                         else {
70                                 return false;
71                         }
72                 }
73
74                 /**
75                  * Set minimum for values in the object.
76                  * Last inserted value is not changed even if it is lower then the new minimum.
77                  * @param min new allowed minimum for the values stored to the object.
78                  * @throws Exception throwed when new minimum is higher than old maximum.
79                  */
80                 public void setMinimum(T min) throws Exception {
81                         if (mMaximum != null && mMinimum != null &&  mMinimum.compareTo(mMaximum) > 0) {
82                                 throw new Exception("Minimum is higher then maximum.");
83                         }
84                         mMinimum = min;
85                 }
86
87                 /**
88                  * Set maximum for values in the object.
89                  * Last inserted value is not changed even if it is higher then the new maximum.
90                  * @param max new allowed maximum for the values stored to the object.
91                  * @throws Exception throwed when new maximum is lower than old minimum.
92                  */
93                 public void setMaximum(T max) throws Exception {
94                         if (mMinimum != null && mMaximum != null &&  mMaximum.compareTo(mMinimum) < 0) {
95                                 throw new Exception("Maximum is lower then minimum.");
96                         }
97                         mMaximum = max;
98                 }
99
100                 /**
101                  * Get value stored in the object
102                  * @return value stored in the object.
103                  */
104                 public T getValue() {
105                         return mValue;
106                 }
107
108                 /**
109                  * Get the lowest allowed value that can be stored in the object.
110                  * @return minimal value
111                  */
112                 public T getMinimum() {
113                         return mMinimum;
114                 }
115
116                 /**
117                  * Get the highest allowed value that can be stored in the object.
118                  * @return maximal value
119                  */
120                 public T getMaximum() {
121                         return mMaximum;
122                 }
123         }
124
125         /**
126          * Interface for events generated by the view
127          * @author Michal Horn
128          *
129          */
130         public interface SceneChange {
131                 /**
132                  * Invoked every time when the scene should be redrawed.
133                  * @param source
134                  */
135                 public void onViewChanged(PdfPageView source);
136
137                 /**
138                  * Invoked once the PDF page is loaded and prepared as a bitmap to be shown
139                  * @param source
140                  */
141                 public void onPageLoaded(PdfPageView source);
142         }
143
144         public static final String TAG = "PdfPageView";
145         protected Paint mPaint;
146         protected IntervalValue<Float> mZoom;
147         protected IntervalValue<Float> mXPosition;
148         protected IntervalValue<Float> mYPosition;
149         protected SceneChange mListener;
150         protected float mSceneHeight;
151         protected float mSceneWidth;
152         protected Bitmap mPdfBitmap;
153         protected File mPdfFile;
154         protected Boolean mPageLoaded;
155         private MuPDFCore mPdfCore;
156         private IntervalValue<Integer> mPage;
157         private MuPDFCore.Cookie mPdfCookie;
158
159         public PdfPageView(Context context, String filePath) throws Exception {
160                 super(context);
161                 mPageLoaded = false;
162                 mPdfFile = new File(filePath);
163                 if (!mPdfFile.exists()) {
164                         throw new PdfViewerException("File " + filePath + " does not exist.");
165                 }
166                 mPaint = new Paint();
167                 mPdfCore = new MuPDFCore(context, mPdfFile.getAbsolutePath());
168                 mPdfCookie = mPdfCore.new Cookie();
169                 if (mPdfCore == null) {
170                         throw new PdfViewerException("The PDF file could not be loaded.");
171                 }
172                 mPage = new IntervalValue<>(0, 0, mPdfCore.countPages()-1);
173                 Log.i(TAG, "Pages: " + mPage.toString());
174         }
175
176         public int getActualPage() {
177                 return mPage.getValue();
178         }
179
180         public int getLastPage() {
181                 return mPage.getMaximum();
182         }
183
184         public boolean setPage(int page) {
185                 return mPage.setValue(page);
186         }
187
188         public void loadPage() {
189                 long startTime = System.currentTimeMillis();
190                 try {
191                         Log.i(TAG, "Loading PDF page " + getActualPage());
192                         mSceneWidth = mPdfCore.getPageSize(getActualPage()).x;
193                         mSceneHeight = mPdfCore.getPageSize(getActualPage()).y;
194                         Log.i(TAG, "Page size: " + mSceneWidth + "x" + mSceneHeight);
195                         Bitmap.Config mPdfBitmapConf = Bitmap.Config.ARGB_8888;
196                         mPdfBitmap = Bitmap.createBitmap((int)mSceneWidth, (int)mSceneHeight, mPdfBitmapConf);
197                         mPdfCore.drawPage(mPdfBitmap, 0, (int) mSceneWidth, (int) mSceneHeight, 0, 0, (int) mSceneWidth, (int) mSceneHeight, mPdfCookie);
198
199                         mXPosition = new IntervalValue<>(0.0f, -mSceneWidth, mSceneWidth);
200                         mYPosition = new IntervalValue<>(0.0f, -mSceneHeight, mSceneHeight);
201                         mZoom = new IntervalValue<>(0.2f, 0.2f, 10.0f);
202                 } catch (Exception e) {
203                         Log.e(TAG, "Error in setting page dimensions.");
204                         e.printStackTrace();
205                 }
206                 long endTime = System.currentTimeMillis();
207                 mPageLoaded = true;
208                 Log.i(TAG, "PDF page loaded in " + Long.toString(endTime - startTime) + "ms.");
209                 if (mListener != null) {
210                         mListener.onPageLoaded(this);
211                 }
212         }
213
214         public Bitmap getPageBitmap() {
215                 return mPdfBitmap;
216         }
217
218
219
220         /**
221          * Set a listener of the events
222          * @param listener listener of the events
223          */
224         public void setListener(SceneChange listener) {
225                 mListener = listener;
226         }
227
228         public void clearListener() {
229                 mListener = null;
230         }
231
232         /**
233          * Zoom scene function. The scene can be zoomed in or out only in limits
234          * defined in constructor.
235          * @param deltaRatio when > 0 - zoom in,<br> when < 0 - zoom out
236          */
237         public  void zoom(float deltaRatio) {
238                 if (!mPageLoaded) return;
239                 float ratio = mZoom.getValue();
240                 ratio += deltaRatio;
241                 if (mZoom.setValue(ratio) == true && mListener != null) {
242                         mListener.onViewChanged(this);
243                 }
244         }
245
246         /**
247          * Move scene function. The scene can be moved only in the rectangle specified
248          * by limits defined in constructor.
249          * @param x change of the x coordinate relatively to the actual position
250          * @param y change of the y coordinate relatively to the actual position
251          */
252         public void move(float x, float y) {
253                 if (!mPageLoaded) return;
254                 boolean xWasSet = mXPosition.setValue(mXPosition.getValue() + x/mZoom.getValue()*2.2f);
255                 boolean yWasSet = mYPosition.setValue(mYPosition.getValue() + y/mZoom.getValue()*2.2f);
256
257                 if ((xWasSet || yWasSet) && mListener != null) {
258                         mListener.onViewChanged(this);
259                 }
260         }
261         /**
262          * @return actual scene zoom ratio
263          */
264         public float getZoomRatio() {
265                 return mZoom.getValue();
266         }
267
268         /**
269          * @return actual scene position on X axis
270          */
271         public float getXPosition() {
272                 return mXPosition.getValue();
273         }
274
275         /**
276          * @return actual scene positoin on Y axis
277          */
278         public float getYPosition() {
279                 return mYPosition.getValue();
280         }
281
282         /**
283          * @return how tall the scene is
284          */
285         public float getSceneHeight() {
286                 return mSceneHeight;
287         }
288
289         /**
290          * @return how wide the scene is
291          */
292         public float getSceneWidth() {
293                 return mSceneWidth;
294         }
295
296         @Override
297         protected void onDraw(Canvas c) {
298                 if (!mPageLoaded) return;
299                 draw(c);
300                 super.onDraw(c);
301         }
302
303         @Override
304         public void draw(Canvas c) {
305                 if (!mPageLoaded) return;
306                 c.translate(c.getWidth()/2, c.getHeight()/2);
307                 c.scale(mZoom.getValue(), mZoom.getValue());
308                 c.translate(-mXPosition.getValue(), -mYPosition.getValue());
309                 c.drawBitmap(mPdfBitmap, 0, 0, mPaint);
310         }
311 }