diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-06-27 22:12:55 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-06-27 22:12:55 +0000 |
commit | 89512d1f7c29187e836317d91edd4f189d2f2296 (patch) | |
tree | fae937be9bd5d2f7341904e54753a618fabed614 | |
parent | e9f99c166c22a7382f45b1ce1415159345ea4747 (diff) |
Workaround for \phantom text annot issue (S. Hirata).
git-svn-id: svn://tug.org/texlive/trunk@55681 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Build/source/texk/dvipdfm-x/ChangeLog | 12 | ||||
-rw-r--r-- | Build/source/texk/dvipdfm-x/dvi.c | 56 | ||||
-rw-r--r-- | Build/source/texk/dvipdfm-x/dvi.h | 11 | ||||
-rw-r--r-- | Build/source/texk/dvipdfm-x/spc_dvipdfmx.c | 35 | ||||
-rw-r--r-- | Build/source/texk/dvipdfm-x/spc_pdfm.c | 160 | ||||
-rw-r--r-- | Build/source/texk/dvipdfm-x/specials.c | 17 | ||||
-rw-r--r-- | Build/source/texk/dvipdfm-x/specials.h | 7 |
7 files changed, 266 insertions, 32 deletions
diff --git a/Build/source/texk/dvipdfm-x/ChangeLog b/Build/source/texk/dvipdfm-x/ChangeLog index b9f81c190b8..dadfe8a719b 100644 --- a/Build/source/texk/dvipdfm-x/ChangeLog +++ b/Build/source/texk/dvipdfm-x/ChangeLog @@ -1,3 +1,15 @@ +2020-06-28 Shunsaku Hirata <shunsaku.hirata74@gmail.com> + + * dvi.[ch], spc_dvipdfmx.c, spc_pdfm.c, specials.[ch]: Two new + special commands added as workarounds for \phantom text issue + in creating annotation (link). "pdf:xann" which extends the + current annotation area by a specified amount. + "dvipdfmx:catch_phantom" to control the behavior of dvipdfmx, + when this is set to true, then dvipdfmx extends the annotation + area when it encounters "horizontal movement" such as DVI + "right". Optionally height and depth of such area can be + specified (default: current font size for height and depth 0). + 2020-06-27 Shunsaku Hirata <shunsaku.hirata74@gmail.com> * pdfcolor.[ch], pdfdoc.c, pdfdraw.c, spc_util.c: An extension diff --git a/Build/source/texk/dvipdfm-x/dvi.c b/Build/source/texk/dvipdfm-x/dvi.c index e85a98a3924..5317bfb8182 100644 --- a/Build/source/texk/dvipdfm-x/dvi.c +++ b/Build/source/texk/dvipdfm-x/dvi.c @@ -204,6 +204,17 @@ static struct font_def static int num_def_fonts = 0, max_def_fonts = 0; static int compute_boxes = 0, link_annot = 1; +/* If "catch_phantom" is non-zero, dvipdfmx try to catch phantom texts. + * Dvipdfmx treats DVI horizontal movement instructions (x, w, right) differently + * when "catch_phantom" is non-zero. Amount of horizontal move will be added to + * the current annotation rectangle with "height" and "depth" estimated as, + * + * catch_phantom=1: with current font size + * catch_phantom=2: with specified height and depth + */ +static int catch_phantom = 0; +static double phantom_height = 0.0; +static double phantom_depth = 0.0; #define DVI_PAGE_BUF_CHUNK 0x10000U /* 64K should be plenty for most pages */ @@ -782,6 +793,20 @@ dvi_is_tracking_boxes(void) } void +dvi_set_linkmode (int mode) +{ + catch_phantom = mode != 0 ? 1 : 0; +} + +void +dvi_set_phantom_height (double height, double depth) +{ + phantom_height = height; + phantom_depth = depth; + catch_phantom = 2; +} + +void dvi_do_special (const void *buffer, int32_t size) { double x_user, y_user, mag; @@ -1104,9 +1129,10 @@ static void do_moveto (int32_t x, int32_t y) dvi_state.v = y; } -/* FIXME: dvi_forward() might be a better name */ void dvi_right (int32_t x) { + spt_t save_h, save_v; + if (lr_mode >= SKIMMING) { lr_width += x; return; @@ -1115,6 +1141,9 @@ void dvi_right (int32_t x) if (lr_mode == RTYPESETTING) x = -x; + save_h = dvi_state.h; + save_v = dvi_state.v; + switch (dvi_state.d) { case 0: dvi_state.h += x; break; @@ -1123,6 +1152,31 @@ void dvi_right (int32_t x) case 3: dvi_state.v -= x; break; } + + if (dvi_is_tracking_boxes() && catch_phantom > 0) { + pdf_rect rect; + spt_t width, height, depth; + if (catch_phantom == 1) { + height = loaded_fonts[current_font].size; + depth = 0.0; + } else { + height = phantom_height / dvi2pts; + depth = phantom_depth / dvi2pts; + } + switch (dvi_state.d) { + case 0: + width = dvi_state.h - save_h; + break; + case 1: + case 2: + width = dvi_state.v - save_v; + break; + default: + width = dvi_state.h - save_h; + } + pdf_dev_set_rect (&rect, save_h, -save_v, width, height, depth); + pdf_doc_expand_box(&rect); + } } void dvi_down (int32_t y) diff --git a/Build/source/texk/dvipdfm-x/dvi.h b/Build/source/texk/dvipdfm-x/dvi.h index 720db74b841..ab29f3b6a46 100644 --- a/Build/source/texk/dvipdfm-x/dvi.h +++ b/Build/source/texk/dvipdfm-x/dvi.h @@ -82,6 +82,17 @@ extern int dvi_locate_font (const char *name, spt_t ptsize); * footnote and page number in link annotation. */ extern void dvi_link_annot (int flag); + +/* linkmode + * To capture \phantom's, DVI "right" instructions are also taken into + * account in calculation of annotaion rectangle. + * Mode 1 for catching phantoms. + * dvi_set_phantom_height() specifies the height of phantom box (default + * is the current font size). + */ +extern void dvi_set_linkmode (int mode); +extern void dvi_set_phantom_height (double height, double depth); + /* The followings are for calculating bounding box of text for annotation. * DVI uses push/pop to do line-feed-carriage-return. So line breaking is * handled by inspecting current depth of DVI register stack. diff --git a/Build/source/texk/dvipdfm-x/spc_dvipdfmx.c b/Build/source/texk/dvipdfm-x/spc_dvipdfmx.c index 456d0fc4361..277c4014f90 100644 --- a/Build/source/texk/dvipdfm-x/spc_dvipdfmx.c +++ b/Build/source/texk/dvipdfm-x/spc_dvipdfmx.c @@ -44,8 +44,41 @@ spc_handler_null (struct spc_env *spe, struct spc_arg *args) return 0; } +static int +spc_handler_dvipdfmx_catch_phantom (struct spc_env *spe, struct spc_arg *args) +{ + int mode, error; + + skip_white(&args->curptr, args->endptr); + { + pdf_obj *b = parse_pdf_boolean(&args->curptr, args->endptr); + if (!b) { + WARN("A boolean value expected but not found..."); + return -1; + } + mode = pdf_boolean_value(b); + pdf_release_obj(b); + } + spc_set_linkmode(spe, mode); + + skip_white(&args->curptr, args->endptr); + if (mode == 1 && args->curptr < args->endptr) { + transform_info ti; + error = spc_util_read_dimtrns(spe, &ti, args, 0); + if (error) + return -1; + if (ti.flags & INFO_HAS_HEIGHT) { + spc_set_phantom(spe, ti.height, ti.depth); + } + skip_white(&args->curptr, args->endptr); + } + + return 0; +} + static struct spc_handler dvipdfmx_handlers[] = { - {"config", spc_handler_null}, /* handled at bop */ + {"config", spc_handler_null}, /* handled at bop */ + {"catch_phantom", spc_handler_dvipdfmx_catch_phantom}, }; int diff --git a/Build/source/texk/dvipdfm-x/spc_pdfm.c b/Build/source/texk/dvipdfm-x/spc_pdfm.c index d7f16add83c..00971def266 100644 --- a/Build/source/texk/dvipdfm-x/spc_pdfm.c +++ b/Build/source/texk/dvipdfm-x/spc_pdfm.c @@ -57,6 +57,7 @@ #include "dvipdfmx.h" +#define SPC_PDFM_SUPPORT_ANNOT_TRANS 1 /* PLEASE REMOVE THIS */ struct resource_map { @@ -641,7 +642,39 @@ parse_pdf_dict_with_tounicode (const char **pp, const char *endptr, struct touni return dict; } -#define SPC_PDFM_SUPPORT_ANNOT_TRANS 1 +static void +set_rect (pdf_rect *rect, pdf_coord cp1, pdf_coord cp2, pdf_coord cp3, pdf_coord cp4) +{ + rect->llx = cp1.x; + if (cp2.x < rect->llx) + rect->llx = cp2.x; + if (cp3.x < rect->llx) + rect->llx = cp3.x; + if (cp4.x < rect->llx) + rect->llx = cp4.x; + rect->urx = cp1.x; + if (cp2.x > rect->urx) + rect->urx = cp2.x; + if (cp3.x > rect->urx) + rect->urx = cp3.x; + if (cp4.x > rect->urx) + rect->urx = cp4.x; + rect->lly = cp1.y; + if (cp2.y < rect->lly) + rect->lly = cp2.y; + if (cp3.y < rect->lly) + rect->lly = cp3.y; + if (cp4.y < rect->lly) + rect->lly = cp4.y; + rect->ury = cp1.y; + if (cp2.y > rect->ury) + rect->ury = cp2.y; + if (cp3.y > rect->ury) + rect->ury = cp3.y; + if (cp4.y > rect->ury) + rect->ury = cp4.y; +} + static int spc_handler_pdfm_annot (struct spc_env *spe, struct spc_arg *args) { @@ -715,35 +748,8 @@ spc_handler_pdfm_annot (struct spc_env *spe, struct spc_arg *args) pdf_dev_transform(&cp1, NULL); pdf_dev_transform(&cp2, NULL); pdf_dev_transform(&cp3, NULL); - pdf_dev_transform(&cp4, NULL); - rect.llx = cp1.x; - if (cp2.x < rect.llx) - rect.llx = cp2.x; - if (cp3.x < rect.llx) - rect.llx = cp3.x; - if (cp4.x < rect.llx) - rect.llx = cp4.x; - rect.urx = cp1.x; - if (cp2.x > rect.urx) - rect.urx = cp2.x; - if (cp3.x > rect.urx) - rect.urx = cp3.x; - if (cp4.x > rect.urx) - rect.urx = cp4.x; - rect.lly = cp1.y; - if (cp2.y < rect.lly) - rect.lly = cp2.y; - if (cp3.y < rect.lly) - rect.lly = cp3.y; - if (cp4.y < rect.lly) - rect.lly = cp4.y; - rect.ury = cp1.y; - if (cp2.y > rect.ury) - rect.ury = cp2.y; - if (cp3.y > rect.ury) - rect.ury = cp3.y; - if (cp4.y > rect.ury) - rect.ury = cp4.y; + pdf_dev_transform(&cp4, NULL); + set_rect(&rect, cp1, cp2, cp3, cp4); #ifdef USE_QUADPOINTS qpoints = pdf_new_array(); pdf_add_array(qpoints, pdf_new_number(ROUND(cp1.x, 0.01))); @@ -841,6 +847,96 @@ spc_handler_pdfm_eann (struct spc_env *spe, struct spc_arg *args) return error; } +/* For supporting \phantom within bann-eann. + * + * \special{pdf:xann width 50pt height 8pt depth 1pt} + * + * tells dvipdfmx to extend the current annotation rectangle + * by the amount specified (witdh 50pt, height 8pt, depth 1pt) + * This was introduced since in the following situation + * + * \special{pdf:bann ...}\phantom{Some texts}\special{pdf:eann} + * + * annotation is not created since there is no annotation + * rectangle calculated due to no object being put. + */ +static int +spc_handler_pdfm_xann (struct spc_env *spe, struct spc_arg *args) +{ + pdf_rect rect; + transform_info ti; + + if (!spc_is_tracking_boxes(spe)) { + /* Silently ignore */ + args->curptr = args->endptr; + return 0; + } + + skip_white(&args->curptr, args->endptr); + + transform_info_clear(&ti); + if (spc_util_read_dimtrns(spe, &ti, args, 0) < 0) { + return -1; + } + + if ((ti.flags & INFO_HAS_USER_BBOX) && + ((ti.flags & INFO_HAS_WIDTH) || (ti.flags & INFO_HAS_HEIGHT))) { + spc_warn(spe, "You can't specify both bbox and width/height."); + return -1; + } + +#ifdef SPC_PDFM_SUPPORT_ANNOT_TRANS + { + pdf_coord cp1, cp2, cp3, cp4; + + if (ti.flags & INFO_HAS_USER_BBOX) { + cp1.x = spe->x_user + ti.bbox.llx; + cp1.y = spe->y_user + ti.bbox.lly; + cp2.x = spe->x_user + ti.bbox.urx; + cp2.y = spe->y_user + ti.bbox.lly; + cp3.x = spe->x_user + ti.bbox.urx; + cp3.y = spe->y_user + ti.bbox.ury; + cp4.x = spe->x_user + ti.bbox.llx; + cp4.y = spe->y_user + ti.bbox.ury; + } else { + cp1.x = spe->x_user; + cp1.y = spe->y_user - spe->mag * ti.depth; + cp2.x = spe->x_user + spe->mag * ti.width; + cp2.y = spe->y_user - spe->mag * ti.depth; + cp3.x = spe->x_user + spe->mag * ti.width; + cp3.y = spe->y_user + spe->mag * ti.height; + cp4.x = spe->x_user; + cp4.y = spe->y_user + spe->mag * ti.height; + } + pdf_dev_transform(&cp1, NULL); + pdf_dev_transform(&cp2, NULL); + pdf_dev_transform(&cp3, NULL); + pdf_dev_transform(&cp4, NULL); + set_rect(&rect, cp1, cp2, cp3, cp4); + } +#else + { + pdf_coord cp; + + cp.x = spe->x_user; cp.y = spe->y_user; + pdf_dev_transform(&cp, NULL); + if (ti.flags & INFO_HAS_USER_BBOX) { + rect.llx = ti.bbox.llx + cp.x; + rect.lly = ti.bbox.lly + cp.y; + rect.urx = ti.bbox.urx + cp.x; + rect.ury = ti.bbox.ury + cp.y; + } else { + rect.llx = cp.x; + rect.lly = cp.y - spe->mag * ti.depth; + rect.urx = cp.x + spe->mag * ti.width; + rect.ury = cp.y + spe->mag * ti.height; + } + } +#endif + pdf_doc_expand_box(&rect); + + return 0; +} /* Color:.... */ static int @@ -2219,6 +2315,10 @@ static struct spc_handler pdfm_handlers[] = { {"pageresources", spc_handler_pdfm_pageresources}, {"trailerid", spc_handler_pdfm_do_nothing}, + + {"xannot", spc_handler_pdfm_xann}, + {"extendann", spc_handler_pdfm_xann}, + {"xann", spc_handler_pdfm_xann}, }; static struct spc_handler pdft_compat_handlers[] = { diff --git a/Build/source/texk/dvipdfm-x/specials.c b/Build/source/texk/dvipdfm-x/specials.c index 15f0d1706f4..735e51e6f32 100644 --- a/Build/source/texk/dvipdfm-x/specials.c +++ b/Build/source/texk/dvipdfm-x/specials.c @@ -104,7 +104,24 @@ spc_suspend_annot (struct spc_env *spe) return 0; } +/* Added this for supporting bann-eann erea only with \phantom text */ +int +spc_is_tracking_boxes (struct spc_env *spe) +{ + return dvi_is_tracking_boxes(); +} + +void +spc_set_linkmode (struct spc_env *spe, int mode) +{ + dvi_set_linkmode(mode); +} +void +spc_set_phantom (struct spc_env *spe, double height, double depth) +{ + dvi_set_phantom_height(height, depth); +} static struct ht_table *named_objects = NULL; diff --git a/Build/source/texk/dvipdfm-x/specials.h b/Build/source/texk/dvipdfm-x/specials.h index 0ce9785a314..ee94d53e6a6 100644 --- a/Build/source/texk/dvipdfm-x/specials.h +++ b/Build/source/texk/dvipdfm-x/specials.h @@ -59,6 +59,13 @@ extern int spc_end_annot (struct spc_env *spe); extern int spc_resume_annot (struct spc_env *spe); extern int spc_suspend_annot (struct spc_env *spe); +extern int spc_is_tracking_boxes (struct spc_env *spe); + +/* linkmode 0: normal, 1: capture phantom texts */ +extern void spc_set_linkmode (struct spc_env *spe, int mode); +/* set default height of phantom texts */ +extern void spc_set_phantom (struct spc_env *spe, double height, double depth); + extern void spc_push_object (const char *key, pdf_obj *value); extern void spc_flush_object (const char *key); extern void spc_clear_objects (void); |