1 package org.coolreader.crengine;
2 
3 
4 import android.graphics.Bitmap;
5 
6 import java.io.ByteArrayOutputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 
10 public class DocView {
11 
12 	public static final Logger log = L.create("dv");
13 
14 	public static final int SWAP_DONE = 0;
15 	public static final int SWAP_TIMEOUT = 1;
16 	public static final int SWAP_ERROR = 2;
17 
18 	private final Object mutex;
19 
DocView(Object mutex)20 	public DocView(Object mutex) {
21 		log.i("DocView()");
22 		this.mutex = mutex;
23 	}
24 
25 	/**
26 	 * Create native object.
27 	 */
create()28 	public void create() {
29 		synchronized(mutex) {
30 			createInternal();
31 		}
32 	}
33 
34 	/**
35 	 * Destroy native object.
36 	 */
destroy()37 	public void destroy() {
38 		synchronized(mutex) {
39 			destroyInternal();
40 		}
41 	}
42 
43 	/**
44 	 * Set document callback.
45 	 * @param readerCallback is callback to set
46 	 */
setReaderCallback(ReaderCallback readerCallback)47 	public void setReaderCallback(ReaderCallback readerCallback) {
48 		this.readerCallback = readerCallback;
49 	}
50 
51 	/**
52 	 * If document uses cache file, swap all unsaved data to it.
53 	 * @return either SWAP_DONE, SWAP_TIMEOUT, SWAP_ERROR
54 	 */
swapToCache()55 	public int swapToCache() {
56 
57 		synchronized(mutex) {
58 			return swapToCacheInternal();
59 		}
60 	}
61 
62 	/**
63 	 * Follow link.
64 	 * @param link
65 	 * @return
66 	 */
goLink(String link)67 	public int goLink(String link) {
68 		synchronized(mutex) {
69 			return goLinkInternal(link);
70 		}
71 	}
72 
73 	/**
74 	 * Find a link near to specified window coordinates.
75 	 * @param x
76 	 * @param y
77 	 * @param delta
78 	 * @return
79 	 */
checkLink(int x, int y, int delta)80 	public String checkLink(int x, int y, int delta) {
81 		synchronized(mutex) {
82 			return checkLinkInternal(x, y, delta);
83 		}
84 	}
85 
86 	/**
87 	 * Set selection range.
88 	 * @param sel
89 	 */
updateSelection(Selection sel)90 	public void updateSelection(Selection sel) {
91 		synchronized(mutex) {
92 			updateSelectionInternal(sel);
93 		}
94 	}
95 
96 	/**
97 	 * Move selection.
98 	 * @param sel
99 	 * @param moveCmd
100 	 * @param params
101 	 * @return
102 	 */
moveSelection(Selection sel, int moveCmd, int params)103 	public boolean moveSelection(Selection sel,
104 			int moveCmd, int params) {
105 		synchronized(mutex) {
106 			return moveSelectionInternal(sel, moveCmd, params);
107 		}
108 	}
109 
110 	/**
111 	 * Send battery state to native object.
112 	 * @param state
113 	 */
setBatteryState(int state)114 	public void setBatteryState(int state) {
115 		synchronized(mutex) {
116 			setBatteryStateInternal(state);
117 		}
118 	}
119 
120 	/**
121 	 * Get current book coverpage data bytes.
122 	 * @return
123 	 */
getCoverPageData()124 	public byte[] getCoverPageData() {
125 		synchronized(mutex) {
126 			return getCoverPageDataInternal();
127 		}
128 	}
129 
130 	/**
131 	 * Set texture for page background.
132 	 * @param imageBytes
133 	 * @param tileFlags
134 	 */
setPageBackgroundTexture( byte[] imageBytes, int tileFlags)135 	public void setPageBackgroundTexture(
136 			byte[] imageBytes, int tileFlags) {
137 		synchronized(mutex) {
138 			setPageBackgroundTextureInternal(imageBytes, tileFlags);
139 		}
140 	}
141 
142 	/**
143 	 * create empty document with specified message (e.g. to show errors)
144 	 * @param title
145 	 * @param message
146 	 * @return
147 	 */
createDefaultDocument(String title, String message)148 	public void createDefaultDocument(String title, String message)
149 	{
150 		synchronized(mutex) {
151 			createDefaultDocumentInternal(title, message);
152 		}
153 	}
154 
155 	/**
156 	 * Load document from file.
157 	 * @param fileName
158 	 * @return
159 	 */
loadDocument(String fileName)160 	public boolean loadDocument(String fileName) {
161 		synchronized(mutex) {
162 			return loadDocumentInternal(fileName);
163 		}
164 	}
165 
166 	/**
167 	 * Load document from input stream.
168 	 * @param inputStream
169 	 * @param contentPath
170 	 * @return
171 	 */
loadDocumentFromStream(InputStream inputStream, String contentPath)172 	public boolean loadDocumentFromStream(InputStream inputStream, String contentPath) {
173 		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
174 		int errorCode = 0;
175 		try {
176 			byte [] buf = new byte [4096];
177 			int readBytes;
178 			while (true) {
179 				readBytes = inputStream.read(buf);
180 				if (readBytes > 0)
181 					outputStream.write(buf, 0, readBytes);
182 				else
183 					break;
184 			}
185 		} catch (IOException e1) {
186 			errorCode = 1;
187 		} catch (OutOfMemoryError e2) {
188 			errorCode = 2;
189 		}
190 		if (0 == errorCode) {
191 			synchronized (mutex) {
192 				return loadDocumentFromMemoryInternal(outputStream.toByteArray(), contentPath);
193 			}
194 		}
195 		// TODO: pass error code to caller to show message for user.
196 		return false;
197 	}
198 
199 	/**
200 	 * Get settings from native object.
201 	 * @return
202 	 */
getSettings()203 	public java.util.Properties getSettings() {
204 		synchronized(mutex) {
205 			return getSettingsInternal();
206 		}
207 	}
208 
209 	/**
210 	 * Apply settings.
211 	 * @param settings
212 	 * @return
213 	 */
applySettings(java.util.Properties settings)214 	public boolean applySettings(java.util.Properties settings) {
215 		synchronized(mutex) {
216 			return applySettingsInternal(settings);
217 		}
218 	}
219 
getDocProps()220 	public java.util.Properties getDocProps() {
221 		synchronized (mutex) {
222 			return getDocPropsInternal();
223 		}
224 	}
225 
226 	/**
227 	 * Set stylesheet for document.
228 	 * @param stylesheet
229 	 */
setStylesheet(String stylesheet)230 	public void setStylesheet(String stylesheet) {
231 		synchronized(mutex) {
232 			setStylesheetInternal(stylesheet);
233 		}
234 	}
235 
requestRender()236 	public void requestRender() {
237 		doCommand(ReaderCommand.DCMD_REQUEST_RENDER.getNativeId(), 0);
238 	}
239 
240 	/**
241 	 * Change window size.
242 	 * @param dx
243 	 * @param dy
244 	 */
resize(int dx, int dy)245 	public void resize(int dx, int dy) {
246 		synchronized(mutex) {
247 			log.d("DocView.resize(" + dx + ", "+ dy + ")");
248 			resizeInternal(dx, dy);
249 		}
250 	}
251 
252 	/**
253 	 * Execute command by native object.
254 	 * @param command
255 	 * @param param
256 	 * @return
257 	 */
doCommand(int command, int param)258 	public boolean doCommand(int command, int param) {
259 		synchronized(mutex) {
260 			return doCommandInternal(command, param);
261 		}
262 	}
263 
264 	/**
265 	 * Get current page bookmark info.
266 	 * @return
267 	 */
getCurrentPageBookmark()268 	public Bookmark getCurrentPageBookmark() {
269 		synchronized(mutex) {
270 			return getCurrentPageBookmarkInternal();
271 		}
272 	}
273 
274 	/**
275 	 * Get current page bookmark info, returning null if document is not yet rendered (to avoid long call).
276 	 * @return bookmark for current page, null if cannot be determined fast
277 	 */
getCurrentPageBookmarkNoRender()278 	public Bookmark getCurrentPageBookmarkNoRender() {
279 		if (!isRenderedInternal())
280 			return null;
281 		synchronized(mutex) {
282 			return getCurrentPageBookmarkInternal();
283 		}
284 	}
285 
286 	/**
287 	 * Check whether document is formatted/rendered.
288 	 * @return true if document is rendered, and e.g. retrieving of page image will not cause long activity (formatting etc.)
289 	 */
isRendered()290 	public boolean isRendered() {
291 		// thread safe
292 		return isRenderedInternal();
293 	}
294 
295 	/**
296 	 * Move reading position to specified xPath.
297 	 * @param xPath
298 	 * @return
299 	 */
goToPosition(String xPath, boolean saveToHistory)300 	public boolean goToPosition(String xPath, boolean saveToHistory) {
301 		synchronized(mutex) {
302 			return goToPositionInternal(xPath, saveToHistory);
303 		}
304 	}
305 
306 	/**
307 	 * Get position properties by xPath.
308 	 * @param xPath
309 	 * @return
310 	 */
getPositionProps(String xPath, boolean precise)311 	public PositionProperties getPositionProps(String xPath, boolean precise) {
312 		synchronized(mutex) {
313 			return getPositionPropsInternal(xPath, precise);
314 		}
315 	}
316 
317 	/**
318 	 * Fill book info fields using metadata from current book.
319 	 * @param info
320 	 */
updateBookInfo(BookInfo info)321 	public void updateBookInfo(BookInfo info) {
322 		synchronized(mutex) {
323 			updateBookInfoInternal(info);
324 		}
325 	}
326 
327 	/**
328 	 * Get TOC tree from current book.
329 	 * @return
330 	 */
getTOC()331 	public TOCItem getTOC() {
332 		synchronized(mutex) {
333 			return getTOCInternal();
334 		}
335 	}
336 
337 	/**
338 	 * Clear selection.
339 	 */
clearSelection()340 	public void clearSelection() {
341 		synchronized(mutex) {
342 			clearSelectionInternal();
343 		}
344 	}
345 
346 	/**
347 	 * Find text in book.
348 	 * @param pattern
349 	 * @param origin
350 	 * @param reverse
351 	 * @param caseInsensitive
352 	 * @return
353 	 */
findText(String pattern, int origin, int reverse, int caseInsensitive)354 	public boolean findText(String pattern, int origin,
355 			int reverse, int caseInsensitive) {
356 		synchronized(mutex) {
357 			return findTextInternal(pattern, origin, reverse, caseInsensitive);
358 		}
359 	}
360 
361 	/**
362 	 * Get current page image.
363 	 * @param bitmap is buffer to put data to.
364 	 */
getPageImage(Bitmap bitmap)365 	public void getPageImage(Bitmap bitmap) {
366 		synchronized(mutex) {
367 			getPageImageInternal(bitmap, DeviceInfo.EINK_SCREEN ? 4 : 32);
368 		}
369 	}
370 
371 	/**
372 	 * Check whether point of current document contains image.
373 	 * If image is found, image becomes current image to be drawn by drawImage(), dstImage fields are set to image dimension.
374 	 *
375 	 * @param x is X coordinate in document window
376 	 * @param y is Y coordinate in document window
377 	 * @param dstImage is to place found image dimensions to
378 	 * @return true if point belongs to image
379 	 */
checkImage(int x, int y, ImageInfo dstImage)380 	public boolean checkImage(int x, int y, ImageInfo dstImage) {
381 		synchronized(mutex) {
382 			return checkImageInternal(x, y, dstImage);
383 		}
384 	}
385 
386 	/**
387 	 * Check whether point of current document belongs to bookmark.
388 	 *
389 	 * @param x is X coordinate in document window
390 	 * @param y is Y coordinate in document window
391 	 * @return bookmark if point belongs to bookmark, null otherwise
392 	 */
checkBookmark(int x, int y)393 	public Bookmark checkBookmark(int x, int y) {
394 		synchronized(mutex) {
395 			Bookmark dstBookmark = new Bookmark();
396 			if (checkBookmarkInternal(x, y, dstBookmark)) {
397 				return dstBookmark;
398 			}
399 			return null;
400 		}
401 	}
402 
403 
404 	/**
405 	 * Draws currently opened image to bitmap.
406 	 * @param bitmap is destination bitmap
407 	 * @param imageInfo contains image position and scaling parameters.
408 	 * @return true if current image is drawn successfully.
409 	 */
drawImage(Bitmap bitmap, ImageInfo imageInfo)410 	public boolean drawImage(Bitmap bitmap, ImageInfo imageInfo) {
411 		synchronized(mutex) {
412 			return drawImageInternal(bitmap, DeviceInfo.EINK_SCREEN ? 4 : 32, imageInfo);
413 		}
414 	}
415 
416 	/**
417 	 * Close currently opened image, free resources.
418 	 * @return true if there was opened current image, and it's now closed
419 	 */
closeImage()420 	public boolean closeImage() {
421 		synchronized(mutex) {
422 			return closeImageInternal();
423 		}
424 	}
425 
426 	/**
427 	 * Highlight bookmarks.
428 	 * Remove highlight using clearSelection().
429 	 * @params bookmarks is array of bookmarks to highlight
430 	 */
hilightBookmarks(Bookmark[] bookmarks)431 	public void hilightBookmarks(Bookmark[] bookmarks) {
432 		synchronized(mutex) {
433 			hilightBookmarksInternal(bookmarks);
434 		}
435 	}
436 
437 	//========================================================================================
438 	// Native functions
439 	/* implementend by libcr3engine.so */
440 	//========================================================================================
getPageImageInternal(Bitmap bitmap, int bpp)441 	private native void getPageImageInternal(Bitmap bitmap, int bpp);
442 
createInternal()443 	private native void createInternal();
444 
destroyInternal()445 	private native void destroyInternal();
446 
createDefaultDocumentInternal(String title, String message)447 	private native void createDefaultDocumentInternal(String title, String message);
448 
loadDocumentInternal(String fileName)449 	private native boolean loadDocumentInternal(String fileName);
450 
loadDocumentFromMemoryInternal(byte [] buf, String contentPath)451 	private native boolean loadDocumentFromMemoryInternal(byte [] buf, String contentPath);
452 
getSettingsInternal()453 	private native java.util.Properties getSettingsInternal();
454 
applySettingsInternal( java.util.Properties settings)455 	private native boolean applySettingsInternal(
456 			java.util.Properties settings);
457 
getDocPropsInternal()458 	private native java.util.Properties getDocPropsInternal();
459 
setStylesheetInternal(String stylesheet)460 	private native void setStylesheetInternal(String stylesheet);
461 
resizeInternal(int dx, int dy)462 	private native void resizeInternal(int dx, int dy);
463 
doCommandInternal(int command, int param)464 	private native boolean doCommandInternal(int command, int param);
465 
getCurrentPageBookmarkInternal()466 	private native Bookmark getCurrentPageBookmarkInternal();
467 
goToPositionInternal(String xPath, boolean saveToHistory)468 	private native boolean goToPositionInternal(String xPath, boolean saveToHistory);
469 
getPositionPropsInternal(String xPath, boolean precise)470 	private native PositionProperties getPositionPropsInternal(String xPath, boolean precise);
471 
updateBookInfoInternal(BookInfo info)472 	private native void updateBookInfoInternal(BookInfo info);
473 
getTOCInternal()474 	private native TOCItem getTOCInternal();
475 
clearSelectionInternal()476 	private native void clearSelectionInternal();
477 
findTextInternal(String pattern, int origin, int reverse, int caseInsensitive)478 	private native boolean findTextInternal(String pattern, int origin,
479 			int reverse, int caseInsensitive);
480 
setBatteryStateInternal(int state)481 	private native void setBatteryStateInternal(int state);
482 
getCoverPageDataInternal()483 	private native byte[] getCoverPageDataInternal();
484 
setPageBackgroundTextureInternal( byte[] imageBytes, int tileFlags)485 	private native void setPageBackgroundTextureInternal(
486 			byte[] imageBytes, int tileFlags);
487 
updateSelectionInternal(Selection sel)488 	private native void updateSelectionInternal(Selection sel);
489 
moveSelectionInternal(Selection sel, int moveCmd, int params)490 	private native boolean moveSelectionInternal(Selection sel,
491 			int moveCmd, int params);
492 
checkLinkInternal(int x, int y, int delta)493 	private native String checkLinkInternal(int x, int y, int delta);
494 
checkImageInternal(int x, int y, ImageInfo dstImage)495 	private native boolean checkImageInternal(int x, int y, ImageInfo dstImage);
496 
checkBookmarkInternal(int x, int y, Bookmark dstBookmark)497 	private native boolean checkBookmarkInternal(int x, int y, Bookmark dstBookmark);
498 
drawImageInternal(Bitmap bitmap, int bpp, ImageInfo dstImage)499 	private native boolean drawImageInternal(Bitmap bitmap, int bpp, ImageInfo dstImage);
500 
closeImageInternal()501 	private native boolean closeImageInternal();
502 
isRenderedInternal()503 	private native boolean isRenderedInternal();
504 
goLinkInternal(String link)505 	private native int goLinkInternal(String link);
506 
hilightBookmarksInternal(Bookmark[] bookmarks)507 	private native void hilightBookmarksInternal(Bookmark[] bookmarks);
508 
509 	// / returns either SWAP_DONE, SWAP_TIMEOUT or SWAP_ERROR
swapToCacheInternal()510 	private native int swapToCacheInternal();
511 
512 	private long mNativeObject; // used from JNI
513 
514 	private ReaderCallback readerCallback;  // used from JNI
515 
516 
517 }
518