summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2020-06-27 22:12:55 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2020-06-27 22:12:55 +0000
commit89512d1f7c29187e836317d91edd4f189d2f2296 (patch)
treefae937be9bd5d2f7341904e54753a618fabed614
parente9f99c166c22a7382f45b1ce1415159345ea4747 (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/ChangeLog12
-rw-r--r--Build/source/texk/dvipdfm-x/dvi.c56
-rw-r--r--Build/source/texk/dvipdfm-x/dvi.h11
-rw-r--r--Build/source/texk/dvipdfm-x/spc_dvipdfmx.c35
-rw-r--r--Build/source/texk/dvipdfm-x/spc_pdfm.c160
-rw-r--r--Build/source/texk/dvipdfm-x/specials.c17
-rw-r--r--Build/source/texk/dvipdfm-x/specials.h7
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);