diff options
author | Paul Gardiner <paulg.artifex@glidos.net> | 2013-02-26 16:13:51 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-02-26 19:02:01 +0000 |
commit | 5bf497485a597a866bb5c149ef02f2b10b74e1ea (patch) | |
tree | 3fbe1e53eba034f300e718db52c31ad06abf5d9f | |
parent | df1f7eb75709a95fdf3838976ebdf49a46430c3b (diff) | |
download | mupdf-5bf497485a597a866bb5c149ef02f2b10b74e1ea.tar.xz |
Include required quadPoints entry in created markup annotations.
Also change the way we pass the text rectangles so that
non-axis-aligned ones can be permitted, and relocate the code that
calculates the strike-out lines from the bounding boxes
-rw-r--r-- | android/jni/mupdf.c | 87 | ||||
-rw-r--r-- | android/src/com/artifex/mupdfdemo/MuPDFCore.java | 6 | ||||
-rw-r--r-- | android/src/com/artifex/mupdfdemo/MuPDFPageView.java | 25 | ||||
-rw-r--r-- | android/src/com/artifex/mupdfdemo/PageView.java | 2 | ||||
-rw-r--r-- | fitz/doc_interactive.c | 5 | ||||
-rw-r--r-- | fitz/fitz-internal.h | 5 | ||||
-rw-r--r-- | pdf/mupdf-internal.h | 1 | ||||
-rw-r--r-- | pdf/pdf_annot.c | 25 |
8 files changed, 99 insertions, 57 deletions
diff --git a/android/jni/mupdf.c b/android/jni/mupdf.c index 88c7a8c6..f5abf328 100644 --- a/android/jni/mupdf.c +++ b/android/jni/mupdf.c @@ -32,6 +32,9 @@ #define MAX_SEARCH_HITS (500) #define NUM_CACHE (3) +#define STRIKE_HEIGHT (0.375f) +#define LINE_THICKNESS (0.07f) +#define SMALL_FLOAT (0.00001) enum { @@ -1360,16 +1363,17 @@ JNI_FN(MuPDFCore_textAsHtml)(JNIEnv * env, jobject thiz) } JNIEXPORT void JNICALL -JNI_FN(MuPDFCore_addStrikeOutAnnotationInternal)(JNIEnv * env, jobject thiz, jobjectArray lines) +JNI_FN(MuPDFCore_addStrikeOutAnnotationInternal)(JNIEnv * env, jobject thiz, jobjectArray points) { globals *glo = get_globals(env, thiz); fz_context *ctx = glo->ctx; fz_document *doc = glo->doc; fz_interactive *idoc = fz_interact(doc); page_cache *pc = &glo->pages[glo->current]; - jclass rect_cls; - jfieldID x0_fid, y0_fid, x1_fid, y1_fid; + jclass pt_cls; + jfieldID x_fid, y_fid; int i, n; + fz_point *pts = NULL; fz_path *path = NULL; fz_stroke_state *stroke = NULL; fz_device *dev = NULL; @@ -1380,6 +1384,7 @@ JNI_FN(MuPDFCore_addStrikeOutAnnotationInternal)(JNIEnv * env, jobject thiz, job strike_list = fz_new_display_list(ctx); + fz_var(pts); fz_var(path); fz_var(stroke); fz_var(dev); @@ -1392,45 +1397,53 @@ JNI_FN(MuPDFCore_addStrikeOutAnnotationInternal)(JNIEnv * env, jobject thiz, job float zoom = glo->resolution / 72; zoom = 1.0 / zoom; fz_scale(&ctm, zoom, zoom); - LOGI("P1 %f", zoom); - rect_cls = (*env)->FindClass(env, "android.graphics.RectF"); - if (rect_cls == NULL) fz_throw(ctx, "FindClass"); - LOGI("P2"); - x0_fid = (*env)->GetFieldID(env, rect_cls, "left", "F"); - if (x0_fid == NULL) fz_throw(ctx, "GetFieldID(left)"); - LOGI("P3"); - y0_fid = (*env)->GetFieldID(env, rect_cls, "top", "F"); - if (y0_fid == NULL) fz_throw(ctx, "GetFieldID(top)"); - LOGI("P4"); - x1_fid = (*env)->GetFieldID(env, rect_cls, "right", "F"); - if (x1_fid == NULL) fz_throw(ctx, "GetFieldID(right)"); - LOGI("P5"); - y1_fid = (*env)->GetFieldID(env, rect_cls, "bottom", "F"); - if (y1_fid == NULL) fz_throw(ctx, "GetFieldID(bottom)"); - LOGI("P6"); - - n = (*env)->GetArrayLength(env, lines); - LOGI("nlines=%d", n); + pt_cls = (*env)->FindClass(env, "android.graphics.PointF"); + if (pt_cls == NULL) fz_throw(ctx, "FindClass"); + x_fid = (*env)->GetFieldID(env, pt_cls, "x", "F"); + if (x_fid == NULL) fz_throw(ctx, "GetFieldID(x)"); + y_fid = (*env)->GetFieldID(env, pt_cls, "y", "F"); + if (y_fid == NULL) fz_throw(ctx, "GetFieldID(y)"); + + n = (*env)->GetArrayLength(env, points); + + pts = fz_malloc_array(ctx, n, sizeof(fz_point)); dev = fz_new_list_device(ctx, strike_list); for (i = 0; i < n; i++) { - jobject line = (*env)->GetObjectArrayElement(env, lines, i); - float x0 = (*env)->GetFloatField(env, line, x0_fid); - float y0 = (*env)->GetFloatField(env, line, y0_fid); - float x1 = (*env)->GetFloatField(env, line, x1_fid); - float y1 = (*env)->GetFloatField(env, line, y1_fid); - float vcenter = (y0 + y1)/2; - float thickness = y1 - y0; - - if (!stroke || stroke->linewidth != thickness) + jobject opt = (*env)->GetObjectArrayElement(env, points, i); + pts[i].x = opt ? (*env)->GetFloatField(env, opt, x_fid) : 0.0f; + pts[i].y = opt ? (*env)->GetFloatField(env, opt, y_fid) : 0.0f; + } + + annot = fz_create_annot(idoc, pc->page, FZ_ANNOT_STRIKEOUT); + + fz_set_markup_annot_quadpoints(idoc, annot, pts, n); + + for (i = 0; i < n; i += 4) + { + fz_point pt0 = pts[i]; + fz_point pt1 = pts[i+1]; + fz_point up; + float thickness; + + up.x = pts[i+2].x - pts[i+1].x; + up.y = pts[i+2].y - pts[i+1].y; + + pt0.x += STRIKE_HEIGHT * up.x; + pt0.y += STRIKE_HEIGHT * up.y; + pt1.x += STRIKE_HEIGHT * up.x; + pt1.y += STRIKE_HEIGHT * up.y; + + thickness = sqrtf(up.x * up.x + up.y * up.y) * LINE_THICKNESS; + + if (!stroke || fz_abs(stroke->linewidth - thickness) < SMALL_FLOAT) { if (stroke) { // assert(path) fz_stroke_path(dev, path, stroke, &ctm, fz_device_rgb, color, 1.0); - LOGI("Path stroked"); fz_drop_stroke_state(ctx, stroke); stroke = NULL; fz_free_path(ctx, path); @@ -1438,29 +1451,25 @@ JNI_FN(MuPDFCore_addStrikeOutAnnotationInternal)(JNIEnv * env, jobject thiz, job } stroke = fz_new_stroke_state(ctx); - LOGI("thickness(%f)", thickness); stroke->linewidth = thickness; path = fz_new_path(ctx); } - fz_moveto(ctx, path, x0, vcenter); - LOGI("moveto(%f,%f)", x0, vcenter); - fz_lineto(ctx, path, x1, vcenter); - LOGI("lineto(%f,%f)", x1, vcenter); + fz_moveto(ctx, path, pt0.x, pt0.y); + fz_lineto(ctx, path, pt1.x, pt1.y); } if (stroke) { fz_stroke_path(dev, path, stroke, &ctm, fz_device_rgb, color, 1.0); - LOGI("Path stroked"); } - annot = fz_create_annot(idoc, pc->page, FZ_ANNOT_STRIKEOUT); fz_set_annot_appearance(idoc, annot, strike_list); dump_annotation_display_lists(glo); } fz_always(ctx) { + fz_free(ctx, pts); fz_free_device(dev); fz_drop_stroke_state(ctx, stroke); fz_free_path(ctx, path); diff --git a/android/src/com/artifex/mupdfdemo/MuPDFCore.java b/android/src/com/artifex/mupdfdemo/MuPDFCore.java index f9b5f779..bfcb3582 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFCore.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFCore.java @@ -39,7 +39,7 @@ public class MuPDFCore private native RectF[] searchPage(String text); private native TextChar[][][][] text(); private native byte[] textAsHtml(); - private native void addStrikeOutAnnotationInternal(RectF[] lines); + private native void addStrikeOutAnnotationInternal(PointF[] quadPoints); private native void deleteAnnotationInternal(int annot_index); private native int passClickEventInternal(int page, float x, float y); private native void setFocusedWidgetChoiceSelectedInternal(String [] selected); @@ -248,9 +248,9 @@ public class MuPDFCore return lns.toArray(new TextWord[lns.size()][]); } - public synchronized void addStrikeOutAnnotation(int page, RectF[] lines) { + public synchronized void addStrikeOutAnnotation(int page, PointF[] quadPoints) { gotoPage(page); - addStrikeOutAnnotationInternal(lines); + addStrikeOutAnnotationInternal(quadPoints); } public synchronized void deleteAnnotation(int page, int annot_index) { diff --git a/android/src/com/artifex/mupdfdemo/MuPDFPageView.java b/android/src/com/artifex/mupdfdemo/MuPDFPageView.java index 63531ec8..d82b2d0a 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFPageView.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFPageView.java @@ -74,7 +74,7 @@ public class MuPDFPageView extends PageView implements MuPDFView { private EditText mEditText; private AsyncTask<String,Void,Boolean> mSetWidgetText; private AsyncTask<String,Void,Void> mSetWidgetChoice; - private AsyncTask<RectF[],Void,Void> mAddStrikeOut; + private AsyncTask<PointF[],Void,Void> mAddStrikeOut; private AsyncTask<Integer,Void,Void> mDeleteAnnotation; private Runnable changeReporter; @@ -280,7 +280,7 @@ public class MuPDFPageView extends PageView implements MuPDFView { } public void strikeOutSelection() { - final ArrayList<RectF> lines = new ArrayList<RectF>(); + final ArrayList<PointF> quadPoints = new ArrayList<PointF>(); processSelectedText(new TextProcessor() { RectF rect; @@ -294,20 +294,17 @@ public class MuPDFPageView extends PageView implements MuPDFView { public void onEndLine() { if (!rect.isEmpty()) { - // These are vertical lines so we can specify - // both position and thickness with a RectF - float vcenter = rect.bottom - (rect.bottom - rect.top)*STRIKE_HEIGHT; - float thickness = (rect.bottom - rect.top)*LINE_THICKNESS; - rect.top = vcenter - thickness/2; - rect.bottom = vcenter + thickness/2; - lines.add(rect); + quadPoints.add(new PointF(rect.left, rect.bottom)); + quadPoints.add(new PointF(rect.right, rect.bottom)); + quadPoints.add(new PointF(rect.right, rect.top)); + quadPoints.add(new PointF(rect.left, rect.top)); } } }); - mAddStrikeOut = new AsyncTask<RectF[],Void,Void>() { + mAddStrikeOut = new AsyncTask<PointF[],Void,Void>() { @Override - protected Void doInBackground(RectF[]... params) { + protected Void doInBackground(PointF[]... params) { addStrikeOut(params[0]); return null; } @@ -319,7 +316,7 @@ public class MuPDFPageView extends PageView implements MuPDFView { } }; - mAddStrikeOut.execute(lines.toArray(new RectF[lines.size()])); + mAddStrikeOut.execute(quadPoints.toArray(new PointF[quadPoints.size()])); deselectText(); } @@ -378,8 +375,8 @@ public class MuPDFPageView extends PageView implements MuPDFView { } @Override - protected void addStrikeOut(RectF[] lines) { - mCore.addStrikeOutAnnotation(mPageNumber, lines); + protected void addStrikeOut(PointF[] quadPoints) { + mCore.addStrikeOutAnnotation(mPageNumber, quadPoints); } private void loadAnnotations() { diff --git a/android/src/com/artifex/mupdfdemo/PageView.java b/android/src/com/artifex/mupdfdemo/PageView.java index 849dbc1f..2412253f 100644 --- a/android/src/com/artifex/mupdfdemo/PageView.java +++ b/android/src/com/artifex/mupdfdemo/PageView.java @@ -146,7 +146,7 @@ public abstract class PageView extends ViewGroup { 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 addStrikeOut(RectF[] lines); + protected abstract void addStrikeOut(PointF[] quadPoints); private void reinit() { // Cancel pending render task diff --git a/fitz/doc_interactive.c b/fitz/doc_interactive.c index bf08690a..c39cf05d 100644 --- a/fitz/doc_interactive.c +++ b/fitz/doc_interactive.c @@ -101,6 +101,11 @@ void fz_set_annot_appearance(fz_interactive *idoc, fz_annot *annot, fz_display_l pdf_set_annot_appearance((pdf_document *)idoc, (pdf_annot *)annot, disp_list); } +void fz_set_markup_annot_quadpoints(fz_interactive *idoc, fz_annot *annot, fz_point *qp, int n) +{ + pdf_set_markup_annot_quadpoints((pdf_document *)idoc, (pdf_annot *)annot, qp, n); +} + void fz_set_doc_event_callback(fz_interactive *idoc, fz_doc_event_cb *event_cb, void *data) { pdf_set_doc_event_callback((pdf_document *)idoc, event_cb, data); diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 7f9beace..c1751fe9 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -1212,6 +1212,11 @@ void fz_delete_annot(fz_interactive *idoc, fz_page *page, fz_annot *annot); void fz_set_annot_appearance(fz_interactive *idoc, fz_annot *annot, fz_display_list *disp_list); /* + fz_set_markup_annot_quadpoints: set the quadpoints for a text-markup annotation. +*/ +void fz_set_markup_annot_quadpoints(fz_interactive *idoc, fz_annot *annot, fz_point *qp, int n); + +/* * Text buffer. * * The trm field contains the a, b, c and d coefficients. diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h index 4b58f911..a4e34a8f 100644 --- a/pdf/mupdf-internal.h +++ b/pdf/mupdf-internal.h @@ -590,6 +590,7 @@ void pdf_choice_widget_set_value(pdf_document *doc, fz_widget *tw, int n, char * pdf_annot *pdf_create_annot(pdf_document *doc, pdf_page *page, fz_annot_type type); void pdf_delete_annot(pdf_document *doc, pdf_page *page, pdf_annot *annot); void pdf_set_annot_appearance(pdf_document *doc, pdf_annot *annot, fz_display_list *disp_list); +void pdf_set_markup_annot_quadpoints(pdf_document *doc, pdf_annot *annot, fz_point *qp, int n); void pdf_set_doc_event_callback(pdf_document *doc, fz_doc_event_cb *event_cb, void *data); void pdf_event_issue_alert(pdf_document *doc, fz_alert_event *event); diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c index aa56e056..ccc7c24c 100644 --- a/pdf/pdf_annot.c +++ b/pdf/pdf_annot.c @@ -741,6 +741,31 @@ pdf_delete_annot(pdf_document *doc, pdf_page *page, pdf_annot *annot) } void +pdf_set_markup_annot_quadpoints(pdf_document *doc, pdf_annot *annot, fz_point *qp, int n) +{ + fz_context *ctx = doc->ctx; + fz_matrix ctm; + pdf_obj *arr = pdf_new_array(ctx, n*2); + int i; + + fz_invert_matrix(&ctm, &annot->page->ctm); + + pdf_dict_puts_drop(annot->obj, "QuadPoints", arr); + + for (i = 0; i < n; i++) + { + fz_point pt = qp[i]; + pdf_obj *r; + + fz_transform_point(&pt, &ctm); + r = pdf_new_real(ctx, pt.x); + pdf_array_push_drop(arr, r); + r = pdf_new_real(ctx, pt.y); + pdf_array_push_drop(arr, r); + } +} + +void pdf_set_annot_appearance(pdf_document *doc, pdf_annot *annot, fz_display_list *disp_list) { fz_context *ctx = doc->ctx; |