diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2018-06-18 16:55:30 +0200 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2018-06-22 16:48:50 +0100 |
commit | 66a23e616670fe19e966c833ac4c0db5edf57c7c (patch) | |
tree | b682ae17bbc253c13a36b70100d4c548d1f7ac61 | |
parent | a69f71e89bc9c325bc91fc0ec69f3ca231c83efe (diff) | |
download | mupdf-66a23e616670fe19e966c833ac4c0db5edf57c7c.tar.xz |
Use fz_quad type in structured text and selection/highlighting.
-rw-r--r-- | include/mupdf/fitz/structured-text.h | 10 | ||||
-rw-r--r-- | include/mupdf/fitz/util.h | 6 | ||||
-rw-r--r-- | include/mupdf/pdf/annot.h | 2 | ||||
-rw-r--r-- | platform/gl/gl-annotate.c | 13 | ||||
-rw-r--r-- | platform/gl/gl-main.c | 33 | ||||
-rw-r--r-- | platform/java/mupdf_native.c | 76 | ||||
-rw-r--r-- | platform/java/mupdf_native.h | 15 | ||||
-rw-r--r-- | platform/java/src/com/artifex/mupdf/fitz/Quad.java | 74 | ||||
-rw-r--r-- | platform/java/src/com/artifex/mupdf/fitz/StructuredText.java | 6 | ||||
-rw-r--r-- | platform/x11/pdfapp.c | 5 | ||||
-rw-r--r-- | platform/x11/pdfapp.h | 2 | ||||
-rw-r--r-- | source/fitz/stext-device.c | 23 | ||||
-rw-r--r-- | source/fitz/stext-output.c | 8 | ||||
-rw-r--r-- | source/fitz/stext-search.c | 107 | ||||
-rw-r--r-- | source/fitz/util.c | 6 | ||||
-rw-r--r-- | source/pdf/pdf-annot.c | 20 | ||||
-rw-r--r-- | source/tools/murun.c | 29 |
17 files changed, 267 insertions, 168 deletions
diff --git a/include/mupdf/fitz/structured-text.h b/include/mupdf/fitz/structured-text.h index 0ad6cd3c..44219f4d 100644 --- a/include/mupdf/fitz/structured-text.h +++ b/include/mupdf/fitz/structured-text.h @@ -95,7 +95,7 @@ struct fz_stext_char_s { int c; fz_point origin; - fz_rect bbox; + fz_quad quad; float size; fz_font *font; fz_stext_char *next; @@ -141,16 +141,16 @@ void fz_print_stext_page_as_text(fz_context *ctx, fz_output *out, fz_stext_page /* fz_search_stext_page: Search for occurrence of 'needle' in text page. - Return the number of hits and store hit bboxes in the passed in array. + Return the number of hits and store hit quads in the passed in array. NOTE: This is an experimental interface and subject to change without notice. */ -int fz_search_stext_page(fz_context *ctx, fz_stext_page *text, const char *needle, fz_rect *hit_bbox, int hit_max); +int fz_search_stext_page(fz_context *ctx, fz_stext_page *text, const char *needle, fz_quad *quads, int max_quads); /* - fz_highlight_selection: Return a list of rectangles to highlight lines inside the selection points. + fz_highlight_selection: Return a list of quads to highlight lines inside the selection points. */ -int fz_highlight_selection(fz_context *ctx, fz_stext_page *page, fz_point a, fz_point b, fz_rect *hit_bbox, int hit_max); +int fz_highlight_selection(fz_context *ctx, fz_stext_page *page, fz_point a, fz_point b, fz_quad *quads, int max_quads); /* fz_copy_selection: Return a newly allocated UTF-8 string with the text for a given selection. diff --git a/include/mupdf/fitz/util.h b/include/mupdf/fitz/util.h index 49409cbb..05119fd5 100644 --- a/include/mupdf/fitz/util.h +++ b/include/mupdf/fitz/util.h @@ -55,9 +55,9 @@ fz_buffer *fz_new_buffer_from_display_list(fz_context *ctx, fz_display_list *lis Record the hits in the hit_bbox array and return the number of hits. Will stop looking once it has filled hit_max rectangles. */ -int fz_search_page(fz_context *ctx, fz_page *page, const char *needle, fz_rect *hit_bbox, int hit_max); -int fz_search_page_number(fz_context *ctx, fz_document *doc, int number, const char *needle, fz_rect *hit_bbox, int hit_max); -int fz_search_display_list(fz_context *ctx, fz_display_list *list, const char *needle, fz_rect *hit_bbox, int hit_max); +int fz_search_page(fz_context *ctx, fz_page *page, const char *needle, fz_quad *hit_bbox, int hit_max); +int fz_search_page_number(fz_context *ctx, fz_document *doc, int number, const char *needle, fz_quad *hit_bbox, int hit_max); +int fz_search_display_list(fz_context *ctx, fz_display_list *list, const char *needle, fz_quad *hit_bbox, int hit_max); /* Parse an SVG document into a display-list. diff --git a/include/mupdf/pdf/annot.h b/include/mupdf/pdf/annot.h index d616436c..869678c0 100644 --- a/include/mupdf/pdf/annot.h +++ b/include/mupdf/pdf/annot.h @@ -184,7 +184,7 @@ void pdf_set_annot_quadding(fz_context *ctx, pdf_annot *annot, int q); void pdf_set_annot_quad_points(fz_context *ctx, pdf_annot *annot, int n, const float *v); void pdf_clear_annot_quad_points(fz_context *ctx, pdf_annot *annot); -void pdf_add_annot_quad_point(fz_context *ctx, pdf_annot *annot, fz_rect bbox); +void pdf_add_annot_quad_point(fz_context *ctx, pdf_annot *annot, fz_quad quad); void pdf_set_annot_ink_list(fz_context *ctx, pdf_annot *annot, int n, const int *count, const fz_point *v); void pdf_clear_annot_ink_list(fz_context *ctx, pdf_annot *annot); diff --git a/platform/gl/gl-annotate.c b/platform/gl/gl-annotate.c index 9d88dabc..873612c7 100644 --- a/platform/gl/gl-annotate.c +++ b/platform/gl/gl-annotate.c @@ -1040,7 +1040,7 @@ static void do_edit_quad_points(void) { static fz_point pt = { 0, 0 }; static int marking = 0; - fz_rect hits[1000]; + fz_quad hits[1000]; int i, n; if (ui_mouse_inside(&view_page_area)) @@ -1071,12 +1071,17 @@ static void do_edit_quad_points(void) glEnable(GL_BLEND); glColor4f(1, 1, 1, 1); + glBegin(GL_QUADS); for (i = 0; i < n; ++i) { - fz_rect thit = hits[i]; - fz_transform_rect(&thit, &view_page_ctm); - glRectf(thit.x0, thit.y0, thit.x1 + 1, thit.y1 + 1); + fz_quad thit = hits[i]; + fz_transform_quad(&thit, &view_page_ctm); + glVertex2f(thit.ul.x, thit.ul.y); + glVertex2f(thit.ur.x, thit.ur.y); + glVertex2f(thit.lr.x, thit.lr.y); + glVertex2f(thit.ll.x, thit.ll.y); } + glEnd(); glDisable(GL_BLEND); diff --git a/platform/gl/gl-main.c b/platform/gl/gl-main.c index ce63c4d2..726de1c0 100644 --- a/platform/gl/gl-main.c +++ b/platform/gl/gl-main.c @@ -142,7 +142,7 @@ static int search_dir = 1; static int search_page = -1; static int search_hit_page = -1; static int search_hit_count = 0; -static fz_rect search_hit_bbox[5000]; +static fz_quad search_hit_quads[5000]; static char error_message[256]; static void error_dialog(void) @@ -467,7 +467,7 @@ static void do_links(fz_link *link) static void do_page_selection(void) { static fz_point pt = { 0, 0 }; - fz_rect hits[1000]; + fz_quad hits[1000]; int i, n; if (ui_mouse_inside(&view_page_area)) @@ -495,11 +495,17 @@ static void do_page_selection(void) glEnable(GL_BLEND); glColor4f(1, 1, 1, 1); + glBegin(GL_QUADS); for (i = 0; i < n; ++i) { - fz_transform_rect(&hits[i], &view_page_ctm); - glRectf(hits[i].x0, hits[i].y0, hits[i].x1 + 1, hits[i].y1 + 1); + fz_quad thit = hits[i]; + fz_transform_quad(&thit, &view_page_ctm); + glVertex2f(thit.ul.x, thit.ul.y); + glVertex2f(thit.ur.x, thit.ur.y); + glVertex2f(thit.lr.x, thit.lr.y); + glVertex2f(thit.ll.x, thit.ll.y); } + glEnd(); glDisable(GL_BLEND); @@ -519,23 +525,24 @@ static void do_page_selection(void) static void do_search_hits(void) { - fz_rect bounds; - fz_irect area; int i; glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); + glColor4f(1, 0, 0, 0.4f); + glBegin(GL_QUADS); for (i = 0; i < search_hit_count; ++i) { - bounds = search_hit_bbox[i]; - fz_transform_rect(&bounds, &view_page_ctm); - fz_irect_from_rect(&area, &bounds); - - glColor4f(1, 0, 0, 0.4f); - glRectf(area.x0, area.y0, area.x1, area.y1); + fz_quad thit = search_hit_quads[i]; + fz_transform_quad(&thit, &view_page_ctm); + glVertex2f(thit.ul.x, thit.ul.y); + glVertex2f(thit.ur.x, thit.ur.y); + glVertex2f(thit.lr.x, thit.lr.y); + glVertex2f(thit.ll.x, thit.ll.y); } + glEnd(); glDisable(GL_BLEND); } @@ -1192,7 +1199,7 @@ void do_main(void) while (glutGet(GLUT_ELAPSED_TIME) < start_time + 200) { search_hit_count = fz_search_page_number(ctx, doc, search_page, search_needle, - search_hit_bbox, nelem(search_hit_bbox)); + search_hit_quads, nelem(search_hit_quads)); if (search_hit_count) { search_active = 0; diff --git a/platform/java/mupdf_native.c b/platform/java/mupdf_native.c index 8e9e9f3f..5a1b0cb7 100644 --- a/platform/java/mupdf_native.c +++ b/platform/java/mupdf_native.c @@ -86,6 +86,7 @@ static jclass cls_Path; static jclass cls_PathWalker; static jclass cls_Pixmap; static jclass cls_Point; +static jclass cls_Quad; static jclass cls_Rect; static jclass cls_RuntimeException; static jclass cls_SeekableInputStream; @@ -133,6 +134,14 @@ static jfieldID fid_Path_pointer; static jfieldID fid_Pixmap_pointer; static jfieldID fid_Point_x; static jfieldID fid_Point_y; +static jfieldID fid_Quad_ul_x; +static jfieldID fid_Quad_ul_y; +static jfieldID fid_Quad_ur_x; +static jfieldID fid_Quad_ur_y; +static jfieldID fid_Quad_ll_x; +static jfieldID fid_Quad_ll_y; +static jfieldID fid_Quad_lr_x; +static jfieldID fid_Quad_lr_y; static jfieldID fid_Rect_x0; static jfieldID fid_Rect_x1; static jfieldID fid_Rect_y0; @@ -142,7 +151,7 @@ static jfieldID fid_StrokeState_pointer; static jfieldID fid_StructuredText_pointer; static jfieldID fid_TextBlock_bbox; static jfieldID fid_TextBlock_lines; -static jfieldID fid_TextChar_bbox; +static jfieldID fid_TextChar_quad; static jfieldID fid_TextChar_c; static jfieldID fid_TextLine_bbox; static jfieldID fid_TextLine_chars; @@ -195,6 +204,7 @@ static jmethodID mid_PathWalker_moveTo; static jmethodID mid_Path_init; static jmethodID mid_Pixmap_init; static jmethodID mid_Point_init; +static jmethodID mid_Quad_init; static jmethodID mid_Rect_init; static jmethodID mid_SeekableInputStream_read; static jmethodID mid_SeekableOutputStream_write; @@ -556,6 +566,17 @@ static int find_fids(JNIEnv *env) fid_Point_x = get_field(&err, env, "x", "F"); fid_Point_y = get_field(&err, env, "y", "F"); + cls_Quad = get_class(&err, env, PKG"Quad"); + fid_Quad_ul_x = get_field(&err, env, "ul_x", "F"); + fid_Quad_ul_y = get_field(&err, env, "ul_y", "F"); + fid_Quad_ur_x = get_field(&err, env, "ur_x", "F"); + fid_Quad_ur_y = get_field(&err, env, "ur_y", "F"); + fid_Quad_ll_x = get_field(&err, env, "ll_x", "F"); + fid_Quad_ll_y = get_field(&err, env, "ll_y", "F"); + fid_Quad_lr_x = get_field(&err, env, "lr_x", "F"); + fid_Quad_lr_y = get_field(&err, env, "lr_y", "F"); + mid_Quad_init = get_method(&err, env, "<init>", "(FFFFFFFF)V"); + cls_Rect = get_class(&err, env, PKG"Rect"); fid_Rect_x0 = get_field(&err, env, "x0", "F"); fid_Rect_x1 = get_field(&err, env, "x1", "F"); @@ -596,7 +617,7 @@ static int find_fids(JNIEnv *env) cls_TextChar = get_class(&err, env, PKG"StructuredText$TextChar"); mid_TextChar_init = get_method(&err, env, "<init>", "(L"PKG"StructuredText;)V"); - fid_TextChar_bbox = get_field(&err, env, "bbox", "L"PKG"Rect;"); + fid_TextChar_quad = get_field(&err, env, "bbox", "L"PKG"Quad;"); fid_TextChar_c = get_field(&err, env, "c", "I"); cls_TextLine = get_class(&err, env, PKG"StructuredText$TextLine"); @@ -702,6 +723,7 @@ static void lose_fids(JNIEnv *env) (*env)->DeleteGlobalRef(env, cls_PDFObject); (*env)->DeleteGlobalRef(env, cls_Pixmap); (*env)->DeleteGlobalRef(env, cls_Point); + (*env)->DeleteGlobalRef(env, cls_Quad); (*env)->DeleteGlobalRef(env, cls_Rect); (*env)->DeleteGlobalRef(env, cls_RuntimeException); (*env)->DeleteGlobalRef(env, cls_SeekableStream); @@ -1447,25 +1469,36 @@ static inline jobject to_Rect_safe(fz_context *ctx, JNIEnv *env, const fz_rect * return (*env)->NewObject(env, cls_Rect, mid_Rect_init, rect->x0, rect->y0, rect->x1, rect->y1); } -static inline jobjectArray to_jRectArray_safe(fz_context *ctx, JNIEnv *env, const fz_rect *rects, jint n) +static inline jobject to_Quad_safe(fz_context *ctx, JNIEnv *env, const fz_quad *quad) +{ + if (!ctx || !quad) return NULL; + + return (*env)->NewObject(env, cls_Quad, mid_Quad_init, + quad->ul.x, quad->ul.y, + quad->ur.x, quad->ur.y, + quad->ll.x, quad->ll.y, + quad->lr.x, quad->lr.y); +} + +static inline jobjectArray to_jQuadArray_safe(fz_context *ctx, JNIEnv *env, const fz_quad *quads, jint n) { jobjectArray arr; int i; - if (!ctx || !rects) return NULL; + if (!ctx || !quads) return NULL; - arr = (*env)->NewObjectArray(env, n, cls_Rect, NULL); + arr = (*env)->NewObjectArray(env, n, cls_Quad, NULL); if (!arr) return NULL; for (i = 0; i < n; i++) { - jobject jrect = to_Rect_safe(ctx, env, &rects[i]); - if (!jrect) return NULL; + jobject jquad = to_Quad_safe(ctx, env, &quads[i]); + if (!jquad) return NULL; - (*env)->SetObjectArrayElement(env, arr, i, jrect); + (*env)->SetObjectArrayElement(env, arr, i, jquad); if ((*env)->ExceptionCheck(env)) return NULL; - (*env)->DeleteLocalRef(env, jrect); + (*env)->DeleteLocalRef(env, jquad); } return arr; @@ -5554,7 +5587,7 @@ FUN(Page_search)(JNIEnv *env, jobject self, jstring jneedle) { fz_context *ctx = get_context(env); fz_page *page = from_Page(env, self); - fz_rect hits[256]; + fz_quad hits[256]; const char *needle = NULL; int n = 0; @@ -5574,7 +5607,7 @@ FUN(Page_search)(JNIEnv *env, jobject self, jstring jneedle) return NULL; } - return to_jRectArray_safe(ctx, env, hits, n); + return to_jQuadArray_safe(ctx, env, hits, n); } JNIEXPORT jobject JNICALL @@ -5872,7 +5905,7 @@ FUN(DisplayList_search)(JNIEnv *env, jobject self, jstring jneedle) { fz_context *ctx = get_context(env); fz_display_list *list = from_DisplayList(env, self); - fz_rect hits[256]; + fz_quad hits[256]; const char *needle = NULL; int n = 0; @@ -5892,7 +5925,7 @@ FUN(DisplayList_search)(JNIEnv *env, jobject self, jstring jneedle) return NULL; } - return to_jRectArray_safe(ctx, env, hits, n); + return to_jQuadArray_safe(ctx, env, hits, n); } /* Buffer interface */ @@ -6359,7 +6392,7 @@ FUN(StructuredText_search)(JNIEnv *env, jobject self, jstring jneedle) { fz_context *ctx = get_context(env); fz_stext_page *text = from_StructuredText(env, self); - fz_rect hits[256]; + fz_quad hits[256]; const char *needle = NULL; int n = 0; @@ -6379,7 +6412,7 @@ FUN(StructuredText_search)(JNIEnv *env, jobject self, jstring jneedle) return NULL; } - return to_jRectArray_safe(ctx, env, hits, n); + return to_jQuadArray_safe(ctx, env, hits, n); } JNIEXPORT jobject JNICALL @@ -6389,7 +6422,7 @@ FUN(StructuredText_highlight)(JNIEnv *env, jobject self, jobject jpt1, jobject j fz_stext_page *text = from_StructuredText(env, self); fz_point pt1 = from_Point(env, jpt1); fz_point pt2 = from_Point(env, jpt2); - fz_rect hits[1000]; + fz_quad hits[1000]; int n = 0; if (!ctx || !text) return NULL; @@ -6402,7 +6435,7 @@ FUN(StructuredText_highlight)(JNIEnv *env, jobject self, jobject jpt1, jobject j return NULL; } - return to_jRectArray_safe(ctx, env, hits, n); + return to_jQuadArray_safe(ctx, env, hits, n); } JNIEXPORT jobject JNICALL @@ -6443,6 +6476,7 @@ FUN(StructuredText_getBlocks)(JNIEnv *env, jobject self) jobject larr = NULL; jobject carr = NULL; jobject jrect = NULL; + jobject jquad = NULL; int len; int b; @@ -6522,11 +6556,11 @@ FUN(StructuredText_getBlocks)(JNIEnv *env, jobject self) if (!jchar) return NULL; /* set the char's bbox */ - jrect = to_Rect_safe(ctx, env, &(ch->bbox)); - if (!jrect) return NULL; + jquad = to_Quad_safe(ctx, env, &ch->quad); + if (!jquad) return NULL; - (*env)->SetObjectField(env, jchar, fid_TextChar_bbox, jrect); - (*env)->DeleteLocalRef(env, jrect); + (*env)->SetObjectField(env, jchar, fid_TextChar_quad, jquad); + (*env)->DeleteLocalRef(env, jquad); /* set the char's value */ (*env)->SetIntField(env, jchar, fid_TextChar_c, ch->c); diff --git a/platform/java/mupdf_native.h b/platform/java/mupdf_native.h index 1813aa18..3f223a13 100644 --- a/platform/java/mupdf_native.h +++ b/platform/java/mupdf_native.h @@ -2896,6 +2896,17 @@ extern "C" { } #endif #endif +/* Header for class com_artifex_mupdf_fitz_Quad */ + +#ifndef _Included_com_artifex_mupdf_fitz_Quad +#define _Included_com_artifex_mupdf_fitz_Quad +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif /* Header for class com_artifex_mupdf_fitz_Rect */ #ifndef _Included_com_artifex_mupdf_fitz_Rect @@ -3185,7 +3196,7 @@ JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_StructuredText_finalize /* * Class: com_artifex_mupdf_fitz_StructuredText * Method: search - * Signature: (Ljava/lang/String;)[Lcom/artifex/mupdf/fitz/Rect; + * Signature: (Ljava/lang/String;)[Lcom/artifex/mupdf/fitz/Quad; */ JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_StructuredText_search (JNIEnv *, jobject, jstring); @@ -3193,7 +3204,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_StructuredText_search /* * Class: com_artifex_mupdf_fitz_StructuredText * Method: highlight - * Signature: (Lcom/artifex/mupdf/fitz/Point;Lcom/artifex/mupdf/fitz/Point;)[Lcom/artifex/mupdf/fitz/Rect; + * Signature: (Lcom/artifex/mupdf/fitz/Point;Lcom/artifex/mupdf/fitz/Point;)[Lcom/artifex/mupdf/fitz/Quad; */ JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_StructuredText_highlight (JNIEnv *, jobject, jobject, jobject); diff --git a/platform/java/src/com/artifex/mupdf/fitz/Quad.java b/platform/java/src/com/artifex/mupdf/fitz/Quad.java new file mode 100644 index 00000000..6e69a7b1 --- /dev/null +++ b/platform/java/src/com/artifex/mupdf/fitz/Quad.java @@ -0,0 +1,74 @@ +package com.artifex.mupdf.fitz; + +public class Quad +{ + public float ul_x, ul_y; + public float ur_x, ur_y; + public float ll_x, ll_y; + public float lr_x, lr_y; + + public Quad(float ul_x, float ul_y, float ur_x, float ur_y, float ll_x, float ll_y, float lr_x, float lr_y) { + this.ul_x = ul_x; + this.ul_y = ul_y; + this.ur_x = ur_x; + this.ur_y = ur_y; + this.ll_x = ll_x; + this.ll_y = ll_y; + this.lr_x = lr_x; + this.lr_y = lr_y; + } + + public Rect toRect() { + float x0 = Math.min(Math.min(ul_x, ur_x), Math.min(ll_x, lr_x)); + float y0 = Math.min(Math.min(ul_y, ur_y), Math.min(ll_y, lr_y)); + float x1 = Math.max(Math.max(ul_x, ur_x), Math.max(ll_x, lr_x)); + float y1 = Math.max(Math.max(ul_y, ur_y), Math.max(ll_y, lr_y)); + return new Rect(x0, y0, x1, y1); + } + + public Quad transformed(Matrix m) { + float t_ul_x = ul_x * m.a + ul_y * m.c + m.e; + float t_ul_y = ul_x * m.b + ul_y * m.d + m.f; + float t_ur_x = ur_x * m.a + ur_y * m.c + m.e; + float t_ur_y = ur_x * m.b + ur_y * m.d + m.f; + float t_ll_x = ll_x * m.a + ll_y * m.c + m.e; + float t_ll_y = ll_x * m.b + ll_y * m.d + m.f; + float t_lr_x = lr_x * m.a + lr_y * m.c + m.e; + float t_lr_y = lr_x * m.b + lr_y * m.d + m.f; + return new Quad( + t_ul_x, t_ul_y, + t_ur_x, t_ur_y, + t_ll_x, t_ll_y, + t_lr_x, t_lr_y + ); + } + + public Quad transform(Matrix m) { + float t_ul_x = ul_x * m.a + ul_y * m.c + m.e; + float t_ul_y = ul_x * m.b + ul_y * m.d + m.f; + float t_ur_x = ur_x * m.a + ur_y * m.c + m.e; + float t_ur_y = ur_x * m.b + ur_y * m.d + m.f; + float t_ll_x = ll_x * m.a + ll_y * m.c + m.e; + float t_ll_y = ll_x * m.b + ll_y * m.d + m.f; + float t_lr_x = lr_x * m.a + lr_y * m.c + m.e; + float t_lr_y = lr_x * m.b + lr_y * m.d + m.f; + ul_x = t_ul_x; + ul_y = t_ul_y; + ur_x = t_ur_x; + ur_y = t_ur_y; + ll_x = t_ll_x; + ll_y = t_ll_y; + lr_x = t_lr_x; + lr_y = t_lr_y; + return this; + } + + public String toString() { + return "[" + + ul_x + " " + ul_y + " " + + ur_x + " " + ur_y + " " + + ll_x + " " + ll_y + " " + + lr_x + " " + lr_y + + "]"; + } +} diff --git a/platform/java/src/com/artifex/mupdf/fitz/StructuredText.java b/platform/java/src/com/artifex/mupdf/fitz/StructuredText.java index 12ec5be3..82aa55ea 100644 --- a/platform/java/src/com/artifex/mupdf/fitz/StructuredText.java +++ b/platform/java/src/com/artifex/mupdf/fitz/StructuredText.java @@ -19,8 +19,8 @@ public class StructuredText pointer = p; } - public native Rect[] search(String needle); - public native Rect[] highlight(Point a, Point b); + public native Quad[] search(String needle); + public native Quad[] highlight(Point a, Point b); public native String copy(Point a, Point b); public native TextBlock[] getBlocks(); @@ -37,7 +37,7 @@ public class StructuredText public class TextChar { public int c; - public Rect bbox; + public Quad quad; public boolean isWhitespace() { return Character.isWhitespace(c); } diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c index 1c5ae45d..17af3d0f 100644 --- a/platform/x11/pdfapp.c +++ b/platform/x11/pdfapp.c @@ -1050,7 +1050,7 @@ void pdfapp_inverthit(pdfapp_t *app) for (i = 0; i < app->hit_count; i++) { - bbox = app->hit_bbox[i]; + bbox = fz_rect_from_quad(app->hit_bbox[i]); pdfapp_invert(app, fz_transform_rect(&bbox, &ctm)); } } @@ -1938,10 +1938,11 @@ void pdfapp_oncopy(pdfapp_t *app, unsigned short *ucsbuf, int ucslen) int saw_text = 0; for (ch = line->first_char; ch; ch = ch->next) { + fz_rect bbox = fz_rect_from_quad(ch->quad); int c = ch->c; if (c < 32) c = 0xFFFD; - if (ch->bbox.x1 >= sel.x0 && ch->bbox.x0 <= sel.x1 && ch->bbox.y1 >= sel.y0 && ch->bbox.y0 <= sel.y1) + if (bbox.x1 >= sel.x0 && bbox.x0 <= sel.x1 && bbox.y1 >= sel.y0 && bbox.y0 <= sel.y1) { saw_text = 1; if (need_newline) diff --git a/platform/x11/pdfapp.h b/platform/x11/pdfapp.h index b6c2127c..0315bfd0 100644 --- a/platform/x11/pdfapp.h +++ b/platform/x11/pdfapp.h @@ -131,7 +131,7 @@ struct pdfapp_s int searchdir; char search[512]; int searchpage; - fz_rect hit_bbox[512]; + fz_quad hit_bbox[512]; int hit_count; /* client context storage */ diff --git a/source/fitz/stext-device.c b/source/fitz/stext-device.c index 40b203b3..ffff886a 100644 --- a/source/fitz/stext-device.c +++ b/source/fitz/stext-device.c @@ -124,16 +124,6 @@ add_line_to_block(fz_context *ctx, fz_stext_page *page, fz_stext_block *block, c return line; } -static float min4(float a, float b, float c, float d) -{ - return fz_min(fz_min(a, b), fz_min(c, d)); -} - -static float max4(float a, float b, float c, float d) -{ - return fz_max(fz_max(a, b), fz_max(c, d)); -} - static fz_stext_char * add_char_to_line(fz_context *ctx, fz_stext_page *page, fz_stext_line *line, const fz_matrix *trm, fz_font *font, float size, int c, fz_point *p, fz_point *q) { @@ -171,10 +161,10 @@ add_char_to_line(fz_context *ctx, fz_stext_page *page, fz_stext_line *line, cons fz_transform_vector(&a, trm); fz_transform_vector(&d, trm); - ch->bbox.x0 = min4(p->x + a.x, q->x + a.x, p->x + d.x, q->x + d.x); - ch->bbox.x1 = max4(p->x + a.x, q->x + a.x, p->x + d.x, q->x + d.x); - ch->bbox.y0 = min4(p->y + a.y, q->y + a.y, p->y + d.y, q->y + d.y); - ch->bbox.y1 = max4(p->y + a.y, q->y + a.y, p->y + d.y, q->y + d.y); + ch->quad.ll = fz_make_point(p->x + d.x, p->y + d.y); + ch->quad.ul = fz_make_point(p->x + a.x, p->y + a.y); + ch->quad.lr = fz_make_point(q->x + d.x, q->y + d.y); + ch->quad.ur = fz_make_point(q->x + a.x, q->y + a.y); return ch; } @@ -648,7 +638,10 @@ fz_stext_close_device(fz_context *ctx, fz_device *dev) for (line = block->u.t.first_line; line; line = line->next) { for (ch = line->first_char; ch; ch = ch->next) - fz_union_rect(&line->bbox, &ch->bbox); + { + fz_rect bbox = fz_rect_from_quad(ch->quad); + fz_union_rect(&line->bbox, &bbox); + } fz_union_rect(&block->bbox, &line->bbox); } } diff --git a/source/fitz/stext-output.c b/source/fitz/stext-output.c index 492885cb..66433489 100644 --- a/source/fitz/stext-output.c +++ b/source/fitz/stext-output.c @@ -364,8 +364,12 @@ fz_print_stext_page_as_xml(fz_context *ctx, fz_output *out, fz_stext_page *page) name = font_full_name(ctx, font); fz_write_printf(ctx, out, "<font name=\"%s\" size=\"%g\">\n", name, size); } - fz_write_printf(ctx, out, "<char bbox=\"%g %g %g %g\" x=\"%g\" y=\"%g\" c=\"", - ch->bbox.x0, ch->bbox.y0, ch->bbox.x1, ch->bbox.y1, ch->origin.x, ch->origin.y); + fz_write_printf(ctx, out, "<char quad=\"%g %g %g %g %g %g %g %g\" x=\"%g\" y=\"%g\" c=\"", + ch->quad.ul.x, ch->quad.ul.y, + ch->quad.ur.x, ch->quad.ur.y, + ch->quad.ll.x, ch->quad.ll.y, + ch->quad.lr.x, ch->quad.lr.y, + ch->origin.x, ch->origin.y); switch (ch->c) { case '<': fz_write_string(ctx, out, "<"); break; diff --git a/source/fitz/stext-search.c b/source/fitz/stext-search.c index b73296e3..0805d3dc 100644 --- a/source/fitz/stext-search.c +++ b/source/fitz/stext-search.c @@ -11,6 +11,20 @@ static float dist2(float a, float b) return a * a + b * b; } +static float hdist(fz_point *dir, fz_point *a, fz_point *b) +{ + float dx = b->x - a->x; + float dy = b->y - a->y; + return fz_abs(dx * dir->x + dy * dir->y); +} + +static float vdist(fz_point *dir, fz_point *a, fz_point *b) +{ + float dx = b->x - a->x; + float dy = b->y - a->y; + return fz_abs(dx * dir->y + dy * dir->x); +} + static int line_length(fz_stext_line *line) { fz_stext_char *ch; @@ -43,8 +57,8 @@ static int find_closest_in_line(fz_stext_line *line, int idx, fz_point p) for (ch = line->first_char; ch; ch = ch->next) { - float mid_x = (ch->bbox.x0 + ch->bbox.x1) / 2; - float mid_y = (ch->bbox.y0 + ch->bbox.y1) / 2; + float mid_x = (ch->quad.ul.x + ch->quad.ur.x + ch->quad.ll.x + ch->quad.lr.x) / 4; + float mid_y = (ch->quad.ul.y + ch->quad.ur.y + ch->quad.ll.y + ch->quad.lr.y) / 4; float this_dist = dist2(p.x - mid_x, p.y - mid_y); if (this_dist < closest_dist) { @@ -171,7 +185,7 @@ fz_enumerate_selection(fz_context *ctx, fz_stext_page *page, fz_point a, fz_poin struct highlight { int len, cap; - fz_rect *box; + fz_quad *box; float hfuzz, vfuzz; }; @@ -180,80 +194,23 @@ static void on_highlight_char(fz_context *ctx, void *arg, fz_stext_line *line, f struct highlight *hits = arg; float vfuzz = ch->size * hits->vfuzz; float hfuzz = ch->size * hits->hfuzz; - fz_rect bbox; - - if (line->dir.x > line->dir.y) - { - bbox.x0 = ch->bbox.x0; - bbox.x1 = ch->bbox.x1; - bbox.y0 = line->bbox.y0; - bbox.y1 = line->bbox.y1; - } - else - { - bbox.x0 = line->bbox.x0; - bbox.x1 = line->bbox.x1; - bbox.y0 = ch->bbox.y0; - bbox.y1 = ch->bbox.y1; - } if (hits->len > 0) { - fz_rect *end = &hits->box[hits->len-1]; - if (fz_abs(bbox.y0 - end->y0) < vfuzz && fz_abs(bbox.y1 - end->y1) < vfuzz) + fz_quad *end = &hits->box[hits->len-1]; + if (hdist(&line->dir, &end->lr, &ch->quad.ll) < hfuzz + && vdist(&line->dir, &end->lr, &ch->quad.ll) < vfuzz + && hdist(&line->dir, &end->ur, &ch->quad.ul) < hfuzz + && vdist(&line->dir, &end->ur, &ch->quad.ul) < vfuzz) { - if (bbox.x1 < end->x0) - { - if (end->x0 - bbox.x1 < hfuzz) - { - end->x0 = bbox.x0; - return; - } - } - else if (bbox.x0 > end->x1) - { - if (bbox.x0 - end->x1 < hfuzz) - { - end->x1 = bbox.x1; - return; - } - } - else - { - end->x0 = fz_min(bbox.x0, end->x0); - end->x1 = fz_max(bbox.x1, end->x1); - return; - } - } - if (fz_abs(bbox.x0 - end->x0) < vfuzz && fz_abs(bbox.x1 - end->x1) < vfuzz) - { - if (bbox.y1 < end->y0) - { - if (end->y0 - bbox.y1 < hfuzz) - { - end->y0 = bbox.y0; - return; - } - } - else if (bbox.y0 > end->y1) - { - if (bbox.y0 - end->y1 < hfuzz) - { - end->y1 = bbox.y1; - return; - } - } - else - { - end->y0 = fz_min(bbox.y0, end->y0); - end->y1 = fz_max(bbox.y1, end->y1); - return; - } + end->ur = ch->quad.ur; + end->lr = ch->quad.lr; + return; } } if (hits->len < hits->cap) - hits->box[hits->len++] = bbox; + hits->box[hits->len++] = ch->quad; } static void on_highlight_line(fz_context *ctx, void *arg, fz_stext_line *line) @@ -261,14 +218,14 @@ static void on_highlight_line(fz_context *ctx, void *arg, fz_stext_line *line) } int -fz_highlight_selection(fz_context *ctx, fz_stext_page *page, fz_point a, fz_point b, fz_rect *hit_bbox, int hit_max) +fz_highlight_selection(fz_context *ctx, fz_stext_page *page, fz_point a, fz_point b, fz_quad *quads, int max_quads) { struct callbacks cb; struct highlight hits; hits.len = 0; - hits.cap = hit_max; - hits.box = hit_bbox; + hits.cap = max_quads; + hits.box = quads; hits.hfuzz = 0.5f; hits.vfuzz = 0.1f; @@ -387,7 +344,7 @@ static const char *find_string(const char *s, const char *needle, const char **e } int -fz_search_stext_page(fz_context *ctx, fz_stext_page *page, const char *needle, fz_rect *hit_bbox, int hit_max) +fz_search_stext_page(fz_context *ctx, fz_stext_page *page, const char *needle, fz_quad *quads, int max_quads) { struct highlight hits; fz_stext_block *block; @@ -401,8 +358,8 @@ fz_search_stext_page(fz_context *ctx, fz_stext_page *page, const char *needle, f return 0; hits.len = 0; - hits.cap = hit_max; - hits.box = hit_bbox; + hits.cap = max_quads; + hits.box = quads; hits.hfuzz = 0.1f; hits.vfuzz = 0.1f; diff --git a/source/fitz/util.c b/source/fitz/util.c index 85ee1e45..0f935e53 100644 --- a/source/fitz/util.c +++ b/source/fitz/util.c @@ -343,7 +343,7 @@ fz_new_stext_page_from_page_number(fz_context *ctx, fz_document *doc, int number } int -fz_search_display_list(fz_context *ctx, fz_display_list *list, const char *needle, fz_rect *hit_bbox, int hit_max) +fz_search_display_list(fz_context *ctx, fz_display_list *list, const char *needle, fz_quad *hit_bbox, int hit_max) { fz_stext_page *text; int count = 0; @@ -359,7 +359,7 @@ fz_search_display_list(fz_context *ctx, fz_display_list *list, const char *needl } int -fz_search_page(fz_context *ctx, fz_page *page, const char *needle, fz_rect *hit_bbox, int hit_max) +fz_search_page(fz_context *ctx, fz_page *page, const char *needle, fz_quad *hit_bbox, int hit_max) { fz_stext_page *text; int count = 0; @@ -375,7 +375,7 @@ fz_search_page(fz_context *ctx, fz_page *page, const char *needle, fz_rect *hit_ } int -fz_search_page_number(fz_context *ctx, fz_document *doc, int number, const char *needle, fz_rect *hit_bbox, int hit_max) +fz_search_page_number(fz_context *ctx, fz_document *doc, int number, const char *needle, fz_quad *hit_bbox, int hit_max) { fz_page *page; int count = 0; diff --git a/source/pdf/pdf-annot.c b/source/pdf/pdf-annot.c index ba92b7ef..cf072c60 100644 --- a/source/pdf/pdf-annot.c +++ b/source/pdf/pdf-annot.c @@ -1058,7 +1058,7 @@ pdf_clear_annot_quad_points(fz_context *ctx, pdf_annot *annot) } void -pdf_add_annot_quad_point(fz_context *ctx, pdf_annot *annot, fz_rect bbox) +pdf_add_annot_quad_point(fz_context *ctx, pdf_annot *annot, fz_quad quad) { pdf_document *doc = annot->page->doc; fz_matrix page_ctm, inv_page_ctm; @@ -1080,15 +1080,15 @@ pdf_add_annot_quad_point(fz_context *ctx, pdf_annot *annot, fz_rect bbox) * in a counterclockwise fashion. Experiments with Adobe's implementation * indicates a cross-wise ordering is intended: ul, ur, ll, lr. */ - fz_transform_rect(&bbox, &inv_page_ctm); - pdf_array_push_real(ctx, quad_points, bbox.x0); /* ul */ - pdf_array_push_real(ctx, quad_points, bbox.y1); - pdf_array_push_real(ctx, quad_points, bbox.x1); /* ur */ - pdf_array_push_real(ctx, quad_points, bbox.y1); - pdf_array_push_real(ctx, quad_points, bbox.x0); /* ll */ - pdf_array_push_real(ctx, quad_points, bbox.y0); - pdf_array_push_real(ctx, quad_points, bbox.x1); /* lr */ - pdf_array_push_real(ctx, quad_points, bbox.y0); + fz_transform_quad(&quad, &inv_page_ctm); + pdf_array_push_real(ctx, quad_points, quad.ul.x); + pdf_array_push_real(ctx, quad_points, quad.ul.y); + pdf_array_push_real(ctx, quad_points, quad.ur.x); + pdf_array_push_real(ctx, quad_points, quad.ur.y); + pdf_array_push_real(ctx, quad_points, quad.ll.x); + pdf_array_push_real(ctx, quad_points, quad.ll.y); + pdf_array_push_real(ctx, quad_points, quad.lr.x); + pdf_array_push_real(ctx, quad_points, quad.lr.y); pdf_dirty_annot(ctx, annot); } diff --git a/source/tools/murun.c b/source/tools/murun.c index c74e4bbc..f7a890b2 100644 --- a/source/tools/murun.c +++ b/source/tools/murun.c @@ -489,6 +489,19 @@ static void ffi_pushrect(js_State *J, fz_rect rect) js_pushnumber(J, rect.y1); js_setindex(J, -2, 3); } +static void ffi_pushquad(js_State *J, fz_quad quad) +{ + js_newarray(J); + js_pushnumber(J, quad.ul.x); js_setindex(J, -2, 0); + js_pushnumber(J, quad.ul.y); js_setindex(J, -2, 1); + js_pushnumber(J, quad.ur.x); js_setindex(J, -2, 0); + js_pushnumber(J, quad.ur.y); js_setindex(J, -2, 1); + js_pushnumber(J, quad.ll.x); js_setindex(J, -2, 0); + js_pushnumber(J, quad.ll.y); js_setindex(J, -2, 1); + js_pushnumber(J, quad.lr.x); js_setindex(J, -2, 0); + js_pushnumber(J, quad.lr.y); js_setindex(J, -2, 1); +} + static fz_irect ffi_toirect(js_State *J, int idx) { fz_irect irect; @@ -1922,7 +1935,7 @@ static void ffi_Page_search(js_State *J) fz_context *ctx = js_getcontext(J); fz_page *page = ffi_topage(J, 0); const char *needle = js_tostring(J, 1); - fz_rect hits[256]; + fz_quad hits[256]; int i, n = 0; fz_try(ctx) @@ -1932,7 +1945,7 @@ static void ffi_Page_search(js_State *J) js_newarray(J); for (i = 0; i < n; ++i) { - ffi_pushrect(J, hits[i]); + ffi_pushquad(J, hits[i]); js_setindex(J, -2, i); } } @@ -2777,7 +2790,7 @@ static void ffi_DisplayList_search(js_State *J) fz_context *ctx = js_getcontext(J); fz_display_list *list = js_touserdata(J, 0, "fz_display_list"); const char *needle = js_tostring(J, 1); - fz_rect hits[256]; + fz_quad hits[256]; int i, n = 0; fz_try(ctx) @@ -2787,7 +2800,7 @@ static void ffi_DisplayList_search(js_State *J) js_newarray(J); for (i = 0; i < n; ++i) { - ffi_pushrect(J, hits[i]); + ffi_pushquad(J, hits[i]); js_setindex(J, -2, i); } } @@ -2797,7 +2810,7 @@ static void ffi_StructuredText_search(js_State *J) fz_context *ctx = js_getcontext(J); fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page"); const char *needle = js_tostring(J, 1); - fz_rect hits[256]; + fz_quad hits[256]; int i, n = 0; fz_try(ctx) @@ -2807,7 +2820,7 @@ static void ffi_StructuredText_search(js_State *J) js_newarray(J); for (i = 0; i < n; ++i) { - ffi_pushrect(J, hits[i]); + ffi_pushquad(J, hits[i]); js_setindex(J, -2, i); } } @@ -2818,7 +2831,7 @@ static void ffi_StructuredText_highlight(js_State *J) fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page"); fz_point a = ffi_topoint(J, 1); fz_point b = ffi_topoint(J, 2); - fz_rect hits[256]; + fz_quad hits[256]; int i, n = 0; fz_try(ctx) @@ -2828,7 +2841,7 @@ static void ffi_StructuredText_highlight(js_State *J) js_newarray(J); for (i = 0; i < n; ++i) { - ffi_pushrect(J, hits[i]); + ffi_pushquad(J, hits[i]); js_setindex(J, -2, i); } } |