diff options
-rw-r--r-- | include/mupdf/fitz/document.h | 17 | ||||
-rw-r--r-- | include/mupdf/html.h | 2 | ||||
-rw-r--r-- | platform/java/example/Viewer.java | 4 | ||||
-rw-r--r-- | platform/java/mupdf_native.c | 36 | ||||
-rw-r--r-- | platform/java/mupdf_native.h | 16 | ||||
-rw-r--r-- | platform/java/src/com/artifex/mupdf/fitz/Document.java | 3 | ||||
-rw-r--r-- | source/fitz/document.c | 14 | ||||
-rw-r--r-- | source/html/epub-doc.c | 35 | ||||
-rw-r--r-- | source/html/html-doc.c | 18 | ||||
-rw-r--r-- | source/html/html-layout.c | 85 |
10 files changed, 227 insertions, 3 deletions
diff --git a/include/mupdf/fitz/document.h b/include/mupdf/fitz/document.h index d7dbd447..c66dc2ca 100644 --- a/include/mupdf/fitz/document.h +++ b/include/mupdf/fitz/document.h @@ -16,6 +16,7 @@ typedef struct fz_document_s fz_document; typedef struct fz_document_handler_s fz_document_handler; typedef struct fz_page_s fz_page; typedef struct fz_annot_s fz_annot; +typedef intptr_t fz_bookmark; typedef enum { @@ -36,6 +37,8 @@ typedef int (fz_document_resolve_link_fn)(fz_context *ctx, fz_document *doc, con typedef int (fz_document_count_pages_fn)(fz_context *ctx, fz_document *doc); typedef fz_page *(fz_document_load_page_fn)(fz_context *ctx, fz_document *doc, int number); typedef int (fz_document_lookup_metadata_fn)(fz_context *ctx, fz_document *doc, const char *key, char *buf, int size); +typedef fz_bookmark (fz_document_make_bookmark_fn)(fz_context *ctx, fz_document *doc, int page); +typedef int (fz_document_lookup_bookmark_fn)(fz_context *ctx, fz_document *doc, fz_bookmark mark); typedef fz_link *(fz_page_load_links_fn)(fz_context *ctx, fz_page *page); typedef fz_rect *(fz_page_bound_page_fn)(fz_context *ctx, fz_page *page, fz_rect *); @@ -100,6 +103,8 @@ struct fz_document_s fz_document_has_permission_fn *has_permission; fz_document_load_outline_fn *load_outline; fz_document_layout_fn *layout; + fz_document_make_bookmark_fn *make_bookmark; + fz_document_lookup_bookmark_fn *lookup_bookmark; fz_document_resolve_link_fn *resolve_link; fz_document_count_pages_fn *count_pages; fz_document_load_page_fn *load_page; @@ -217,6 +222,18 @@ int fz_is_document_reflowable(fz_context *ctx, fz_document *doc); void fz_layout_document(fz_context *ctx, fz_document *doc, float w, float h, float em); /* + Create a bookmark for the given page, which can be used to find the + same location after the document has been laid out with different + parameters. +*/ +fz_bookmark fz_make_bookmark(fz_context *ctx, fz_document *doc, int page); + +/* + Find a bookmark and return its page number. +*/ +int fz_lookup_bookmark(fz_context *ctx, fz_document *doc, fz_bookmark mark); + +/* fz_count_pages: Return the number of pages in document May return 0 for documents with no pages. diff --git a/include/mupdf/html.h b/include/mupdf/html.h index be0808d1..e23a606d 100644 --- a/include/mupdf/html.h +++ b/include/mupdf/html.h @@ -283,5 +283,7 @@ void fz_draw_html(fz_context *ctx, fz_device *dev, const fz_matrix *ctm, fz_html float fz_find_html_target(fz_context *ctx, fz_html *html, const char *id); fz_link *fz_load_html_links(fz_context *ctx, fz_html *html, int page, const char *base_uri); void fz_drop_html(fz_context *ctx, fz_html *html); +fz_bookmark fz_make_html_bookmark(fz_context *ctx, fz_html *html, int page); +int fz_lookup_html_bookmark(fz_context *ctx, fz_html *html, fz_bookmark mark); #endif diff --git a/platform/java/example/Viewer.java b/platform/java/example/Viewer.java index 1361a538..a924cf4b 100644 --- a/platform/java/example/Viewer.java +++ b/platform/java/example/Viewer.java @@ -383,12 +383,12 @@ public class Viewer extends Frame implements WindowListener, ActionListener, Ite } if (layoutEm != oldLayoutEm) { - float oldPos = (pageNumber + 0.5f) / (float)pageCount; + long mark = doc.makeBookmark(pageNumber); doc.layout(layoutWidth, layoutHeight, layoutEm); updateOutline(); pageCount = doc.countPages(); pageLabel.setText("/ " + pageCount); - pageNumber = (int)(oldPos * pageCount); + pageNumber = doc.findBookmark(mark); } if (zoomLevel != oldZoomLevel || pageNumber != oldPageNumber || layoutEm != oldLayoutEm || searchHits != oldSearchHits) diff --git a/platform/java/mupdf_native.c b/platform/java/mupdf_native.c index cbb3dd7a..aec932c4 100644 --- a/platform/java/mupdf_native.c +++ b/platform/java/mupdf_native.c @@ -4222,6 +4222,42 @@ FUN(Document_loadOutline)(JNIEnv *env, jobject self) return joutline; } +JNIEXPORT jlong JNICALL +FUN(Document_makeBookmark)(JNIEnv *env, jobject self, jint page) +{ + fz_context *ctx = get_context(env); + fz_document *doc = from_Document(env, self); + fz_bookmark mark = 0; + + fz_try(ctx) + mark = fz_make_bookmark(ctx, doc, page); + fz_catch(ctx) + { + jni_rethrow(env, ctx); + return 0; + } + + return mark; +} + +JNIEXPORT jint JNICALL +FUN(Document_findBookmark)(JNIEnv *env, jobject self, jlong mark) +{ + fz_context *ctx = get_context(env); + fz_document *doc = from_Document(env, self); + int page = -1; + + fz_try(ctx) + page = fz_lookup_bookmark(ctx, doc, mark); + fz_catch(ctx) + { + jni_rethrow(env, ctx); + return -1; + } + + return page; +} + JNIEXPORT jobject JNICALL FUN(Document_toPDFDocument)(JNIEnv *env, jobject self) { diff --git a/platform/java/mupdf_native.h b/platform/java/mupdf_native.h index 3e6c51b3..8b0b2fe3 100644 --- a/platform/java/mupdf_native.h +++ b/platform/java/mupdf_native.h @@ -683,6 +683,22 @@ JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Document_layout /* * Class: com_artifex_mupdf_fitz_Document + * Method: makeBookmark + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_com_artifex_mupdf_fitz_Document_makeBookmark + (JNIEnv *, jobject, jint); + +/* + * Class: com_artifex_mupdf_fitz_Document + * Method: findBookmark + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_com_artifex_mupdf_fitz_Document_findBookmark + (JNIEnv *, jobject, jlong); + +/* + * Class: com_artifex_mupdf_fitz_Document * Method: isUnencryptedPDF * Signature: ()Z */ diff --git a/platform/java/src/com/artifex/mupdf/fitz/Document.java b/platform/java/src/com/artifex/mupdf/fitz/Document.java index 29cad4db..1fc21c13 100644 --- a/platform/java/src/com/artifex/mupdf/fitz/Document.java +++ b/platform/java/src/com/artifex/mupdf/fitz/Document.java @@ -49,6 +49,9 @@ public class Document public native boolean isReflowable(); public native void layout(float width, float height, float em); + public native long makeBookmark(int page); + public native int findBookmark(long mark); + public native boolean isUnencryptedPDF(); public native PDFDocument toPDFDocument(); diff --git a/source/fitz/document.c b/source/fitz/document.c index 684c8523..41abb736 100644 --- a/source/fitz/document.c +++ b/source/fitz/document.c @@ -182,6 +182,20 @@ fz_is_document_reflowable(fz_context *ctx, fz_document *doc) return doc ? doc->is_reflowable : 0; } +fz_bookmark fz_make_bookmark(fz_context *ctx, fz_document *doc, int page) +{ + if (doc && doc->make_bookmark) + return doc->make_bookmark(ctx, doc, page); + return (fz_bookmark)page; +} + +int fz_lookup_bookmark(fz_context *ctx, fz_document *doc, fz_bookmark mark) +{ + if (doc && doc->lookup_bookmark) + return doc->lookup_bookmark(ctx, doc, mark); + return (int)mark; +} + int fz_needs_password(fz_context *ctx, fz_document *doc) { diff --git a/source/html/epub-doc.c b/source/html/epub-doc.c index d220816d..3cfa3f06 100644 --- a/source/html/epub-doc.c +++ b/source/html/epub-doc.c @@ -178,6 +178,39 @@ epub_load_links(fz_context *ctx, fz_page *page_) return NULL; } +static fz_bookmark +epub_make_bookmark(fz_context *ctx, fz_document *doc_, int n) +{ + epub_document *doc = (epub_document*)doc_; + epub_chapter *ch; + int count = 0; + + for (ch = doc->spine; ch; ch = ch->next) + { + int cn = ceilf(ch->html->root->h / ch->html->page_h); + if (n < count + cn) + return fz_make_html_bookmark(ctx, ch->html, n - count); + count += cn; + } + + return 0; +} + +static int +epub_lookup_bookmark(fz_context *ctx, fz_document *doc_, fz_bookmark mark) +{ + epub_document *doc = (epub_document*)doc_; + epub_chapter *ch; + + for (ch = doc->spine; ch; ch = ch->next) + { + int p = fz_lookup_html_bookmark(ctx, ch->html, mark); + if (p != -1) + return ch->start + p; + } + return -1; +} + static fz_page * epub_load_page(fz_context *ctx, fz_document *doc_, int number) { @@ -440,6 +473,8 @@ epub_init(fz_context *ctx, fz_archive *zip) doc->super.layout = epub_layout; doc->super.load_outline = epub_load_outline; doc->super.resolve_link = epub_resolve_link; + doc->super.make_bookmark = epub_make_bookmark; + doc->super.lookup_bookmark = epub_lookup_bookmark; doc->super.count_pages = epub_count_pages; doc->super.load_page = epub_load_page; doc->super.lookup_metadata = epub_lookup_metadata; diff --git a/source/html/html-doc.c b/source/html/html-doc.c index c19d5049..47225c06 100644 --- a/source/html/html-doc.c +++ b/source/html/html-doc.c @@ -97,6 +97,20 @@ htdoc_load_links(fz_context *ctx, fz_page *page_) return fz_load_html_links(ctx, doc->html, page->number, ""); } +static fz_bookmark +htdoc_make_bookmark(fz_context *ctx, fz_document *doc_, int page) +{ + html_document *doc = (html_document*)doc_; + return fz_make_html_bookmark(ctx, doc->html, page); +} + +static int +htdoc_lookup_bookmark(fz_context *ctx, fz_document *doc_, fz_bookmark mark) +{ + html_document *doc = (html_document*)doc_; + return fz_lookup_html_bookmark(ctx, doc->html, mark); +} + static fz_page * htdoc_load_page(fz_context *ctx, fz_document *doc_, int number) { @@ -111,7 +125,7 @@ htdoc_load_page(fz_context *ctx, fz_document *doc_, int number) return (fz_page*)page; } -int +static int htdoc_lookup_metadata(fz_context *ctx, fz_document *doc_, const char *key, char *buf, int size) { if (!strcmp(key, "format")) @@ -162,6 +176,8 @@ htdoc_open_document(fz_context *ctx, const char *filename) doc->super.drop_document = htdoc_drop_document; doc->super.layout = htdoc_layout; doc->super.resolve_link = htdoc_resolve_link; + doc->super.make_bookmark = htdoc_make_bookmark; + doc->super.lookup_bookmark = htdoc_lookup_bookmark; doc->super.count_pages = htdoc_count_pages; doc->super.load_page = htdoc_load_page; doc->super.lookup_metadata = htdoc_lookup_metadata; diff --git a/source/html/html-layout.c b/source/html/html-layout.c index f06e6cbd..1cac935b 100644 --- a/source/html/html-layout.c +++ b/source/html/html-layout.c @@ -2101,6 +2101,91 @@ fz_find_html_target(fz_context *ctx, fz_html *html, const char *id) return find_box_target(html->root, id); } +static fz_html_flow * +make_flow_bookmark(fz_context *ctx, fz_html_flow *flow, float y) +{ + while (flow) + { + if (flow->y >= y) + return flow; + flow = flow->next; + } + return NULL; +} + +static fz_html_flow * +make_box_bookmark(fz_context *ctx, fz_html_box *box, float y) +{ + fz_html_flow *mark; + while (box) + { + if (box->type == BOX_FLOW) + { + if (box->y >= y) + { + mark = make_flow_bookmark(ctx, box->flow_head, y); + if (mark) + return mark; + } + } + else + { + mark = make_box_bookmark(ctx, box->down, y); + if (mark) + return mark; + } + box = box->next; + } + return NULL; +} + +fz_bookmark +fz_make_html_bookmark(fz_context *ctx, fz_html *html, int page) +{ + return (fz_bookmark)make_box_bookmark(ctx, html->root, page * html->page_h); +} + +static int +lookup_flow_bookmark(fz_context *ctx, fz_html_flow *flow, fz_html_flow *mark) +{ + while (flow) + { + if (flow == mark) + return 1; + flow = flow->next; + } + return 0; +} + +static int +lookup_box_bookmark(fz_context *ctx, fz_html_box *box, fz_html_flow *mark) +{ + while (box) + { + if (box->type == BOX_FLOW) + { + if (lookup_flow_bookmark(ctx, box->flow_head, mark)) + return 1; + } + else + { + if (lookup_box_bookmark(ctx, box->down, mark)) + return 1; + } + box = box->next; + } + return 0; +} + +int +fz_lookup_html_bookmark(fz_context *ctx, fz_html *html, fz_bookmark mark) +{ + fz_html_flow *flow = (fz_html_flow*)mark; + if (flow && lookup_box_bookmark(ctx, html->root, flow)) + return (int)(flow->y / html->page_h); + return -1; +} + static char *concat_text(fz_context *ctx, fz_xml *root) { fz_xml *node; |