texlive[55681] Build/source/texk/dvipdfm-x: Workaround for \phantom

commits+kakuto at tug.org commits+kakuto at tug.org
Sun Jun 28 00:12:56 CEST 2020


Revision: 55681
          http://tug.org/svn/texlive?view=revision&revision=55681
Author:   kakuto
Date:     2020-06-28 00:12:55 +0200 (Sun, 28 Jun 2020)
Log Message:
-----------
Workaround for \phantom text annot issue (S. Hirata).

Modified Paths:
--------------
    trunk/Build/source/texk/dvipdfm-x/ChangeLog
    trunk/Build/source/texk/dvipdfm-x/dvi.c
    trunk/Build/source/texk/dvipdfm-x/dvi.h
    trunk/Build/source/texk/dvipdfm-x/spc_dvipdfmx.c
    trunk/Build/source/texk/dvipdfm-x/spc_pdfm.c
    trunk/Build/source/texk/dvipdfm-x/specials.c
    trunk/Build/source/texk/dvipdfm-x/specials.h

Modified: trunk/Build/source/texk/dvipdfm-x/ChangeLog
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/ChangeLog	2020-06-27 21:23:32 UTC (rev 55680)
+++ trunk/Build/source/texk/dvipdfm-x/ChangeLog	2020-06-27 22:12:55 UTC (rev 55681)
@@ -1,3 +1,15 @@
+2020-06-28  Shunsaku Hirata  <shunsaku.hirata74 at 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 at gmail.com>
 
 	* pdfcolor.[ch], pdfdoc.c, pdfdraw.c, spc_util.c: An extension

Modified: trunk/Build/source/texk/dvipdfm-x/dvi.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/dvi.c	2020-06-27 21:23:32 UTC (rev 55680)
+++ trunk/Build/source/texk/dvipdfm-x/dvi.c	2020-06-27 22:12:55 UTC (rev 55681)
@@ -204,6 +204,17 @@
 
 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 @@
 }
 
 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 @@
   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 @@
   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 @@
   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)

Modified: trunk/Build/source/texk/dvipdfm-x/dvi.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/dvi.h	2020-06-27 21:23:32 UTC (rev 55680)
+++ trunk/Build/source/texk/dvipdfm-x/dvi.h	2020-06-27 22:12:55 UTC (rev 55681)
@@ -82,6 +82,17 @@
  * 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.

Modified: trunk/Build/source/texk/dvipdfm-x/spc_dvipdfmx.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/spc_dvipdfmx.c	2020-06-27 21:23:32 UTC (rev 55680)
+++ trunk/Build/source/texk/dvipdfm-x/spc_dvipdfmx.c	2020-06-27 22:12:55 UTC (rev 55681)
@@ -44,8 +44,41 @@
   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

Modified: trunk/Build/source/texk/dvipdfm-x/spc_pdfm.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/spc_pdfm.c	2020-06-27 21:23:32 UTC (rev 55680)
+++ trunk/Build/source/texk/dvipdfm-x/spc_pdfm.c	2020-06-27 22:12:55 UTC (rev 55681)
@@ -57,6 +57,7 @@
 
 #include "dvipdfmx.h"
 
+#define SPC_PDFM_SUPPORT_ANNOT_TRANS 1
 
 /* PLEASE REMOVE THIS */
 struct resource_map {
@@ -641,7 +642,39 @@
   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 @@
     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,7 +847,97 @@
   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
 spc_handler_pdfm_bcolor (struct spc_env *spe, struct spc_arg *ap)
@@ -2219,6 +2315,10 @@
 
   {"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[] = {

Modified: trunk/Build/source/texk/dvipdfm-x/specials.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/specials.c	2020-06-27 21:23:32 UTC (rev 55680)
+++ trunk/Build/source/texk/dvipdfm-x/specials.c	2020-06-27 22:12:55 UTC (rev 55681)
@@ -104,8 +104,25 @@
   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;
 
 /* reserved keys */

Modified: trunk/Build/source/texk/dvipdfm-x/specials.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/specials.h	2020-06-27 21:23:32 UTC (rev 55680)
+++ trunk/Build/source/texk/dvipdfm-x/specials.h	2020-06-27 22:12:55 UTC (rev 55681)
@@ -59,6 +59,13 @@
 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);



More information about the tex-live-commits mailing list.