texlive[43807] Build/source/texk/dvipdfm-x: dvipdfm-x: Final patch

commits+kakuto at tug.org commits+kakuto at tug.org
Sat Apr 15 22:19:40 CEST 2017


Revision: 43807
          http://tug.org/svn/texlive?view=revision&revision=43807
Author:   kakuto
Date:     2017-04-15 22:19:40 +0200 (Sat, 15 Apr 2017)
Log Message:
-----------
dvipdfm-x: Final patch for TL 2017 by the author, S. Hirata

Modified Paths:
--------------
    trunk/Build/source/texk/dvipdfm-x/ChangeLog
    trunk/Build/source/texk/dvipdfm-x/fontmap.c
    trunk/Build/source/texk/dvipdfm-x/pdffont.c
    trunk/Build/source/texk/dvipdfm-x/tt_cmap.c
    trunk/Build/source/texk/dvipdfm-x/tt_gsub.c
    trunk/Build/source/texk/dvipdfm-x/tt_gsub.h

Modified: trunk/Build/source/texk/dvipdfm-x/ChangeLog
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/ChangeLog	2017-04-15 13:58:58 UTC (rev 43806)
+++ trunk/Build/source/texk/dvipdfm-x/ChangeLog	2017-04-15 20:19:40 UTC (rev 43807)
@@ -1,3 +1,12 @@
+2017-04-15  Shunsaku Hirata  <shunsaku.hirata74 at gmail.com>
+
+	* fontmap.c, tt_cmap.c, tt_gsub.c, tt_gsub.h, pdffont.c: Removed
+	undocumented OpenType Layout GSUB support.  Added simplified version of
+	OpenType Layout GSUB support. Fontmap option "-l otl_tags" enables
+	OpenType GSUB features specified by otl_tags, where otl_tags is a ":"
+	separated list of OpenType Layout feature tags
+	(or strings of script.language.feature form).
+	
 2017-04-12  Akira Kakuto  <kakuto at fuk.kindai.ac.jp>
 
 	* dvipdfmx.c: Fix a bug in static const char *optstrig.

Modified: trunk/Build/source/texk/dvipdfm-x/fontmap.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/fontmap.c	2017-04-15 13:58:58 UTC (rev 43806)
+++ trunk/Build/source/texk/dvipdfm-x/fontmap.c	2017-04-15 20:19:40 UTC (rev 43807)
@@ -71,7 +71,7 @@
   mrec->opt.design_size = -1.0;
 
   mrec->opt.tounicode = NULL;
-  mrec->opt.otl_tags  = NULL; /* deactivated */
+  mrec->opt.otl_tags  = NULL;
   mrec->opt.index     = 0;
   mrec->opt.charcoll  = NULL;
   mrec->opt.style     = FONTMAP_STYLE_NONE;
@@ -453,6 +453,17 @@
       RELEASE(q);
       break;
 
+    /* 2017.4.15 back again */
+    case 'l':
+      q = parse_string_value(&p, endptr);
+      if (q)
+        mrec->opt.otl_tags = q;
+      else {
+        WARN("Missing string value for option 'l'.");
+        return -1;
+      }
+      break;
+
     /* Omega uses both single-byte and double-byte set_char command
      * even for double-byte OFMs. This confuses CMap decoder.
      */

Modified: trunk/Build/source/texk/dvipdfm-x/pdffont.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdffont.c	2017-04-15 13:58:58 UTC (rev 43806)
+++ trunk/Build/source/texk/dvipdfm-x/pdffont.c	2017-04-15 20:19:40 UTC (rev 43807)
@@ -50,7 +50,6 @@
 #include "type0.h"
 #include "tt_cmap.h"
 #include "cidtype0.h"
-#include "otl_conf.h"
 
 #include "pdffont.h"
 
@@ -67,7 +66,6 @@
   CIDFont_set_verbose  ();
   pdf_encoding_set_verbose();
   agl_set_verbose();
-  otl_conf_set_verbose();
   otf_cmap_set_verbose ();
 }
 
@@ -308,7 +306,6 @@
   ASSERT(font_cache.fonts == NULL);  
 
   agl_init_map();
-  otl_init_conf();
 
   CMap_cache_init();
   pdf_init_encodings();
@@ -600,7 +597,6 @@
   CMap_cache_close();
   pdf_close_encodings();
 
-  otl_close_conf();
   agl_close_map (); /* After encoding */
 
   return;

Modified: trunk/Build/source/texk/dvipdfm-x/tt_cmap.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/tt_cmap.c	2017-04-15 13:58:58 UTC (rev 43806)
+++ trunk/Build/source/texk/dvipdfm-x/tt_cmap.c	2017-04-15 20:19:40 UTC (rev 43807)
@@ -45,12 +45,9 @@
 
 #include "unicode.h"
 #include "agl.h"
-#include "pdfparse.h"
+
 #include "pdfresource.h"
-#include "otl_conf.h"
-
 #include "dpxfile.h"
-
 /* Hash */
 #include "dpxutil.h"
 
@@ -612,7 +609,8 @@
 
 static void
 load_cmap4 (struct cmap4 *map,
-	    unsigned char *GIDToCIDMap, otl_gsub *gsub_list, CMap *cmap)
+	    unsigned char *GIDToCIDMap,
+      otl_gsub *gsub_vert, otl_gsub *gsub_list, CMap *cmap)
 {
   USHORT  c0, c1, gid, cid;
   USHORT  j, d, segCount;
@@ -637,7 +635,9 @@
       }
       if (gid != 0 && gid != 0xffff) {
         if (gsub_list)
-          otl_gsub_apply(gsub_list, &gid);
+          otl_gsub_apply_chain(gsub_list, &gid);
+        if (gsub_vert)
+          otl_gsub_apply(gsub_vert, &gid);
 	if (GIDToCIDMap) {
 	  cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]);
 	  if (cid == 0)
@@ -659,7 +659,8 @@
 
 static void
 load_cmap12 (struct cmap12 *map,
-	     unsigned char *GIDToCIDMap, otl_gsub *gsub_list, CMap *cmap)
+	     unsigned char *GIDToCIDMap,
+       otl_gsub *gsub_vert, otl_gsub *gsub_list, CMap *cmap)
 {
   ULONG   i, ch;  /* LONG ? */
   USHORT  gid, cid;
@@ -671,7 +672,9 @@
       int  d = ch - map->groups[i].startCharCode;
       gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff);
       if (gsub_list)
-        otl_gsub_apply(gsub_list, &gid);
+        otl_gsub_apply_chain(gsub_list, &gid);
+      if (gsub_vert)
+        otl_gsub_apply(gsub_vert, &gid);
       if (GIDToCIDMap) {
 	cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]);
 	if (cid == 0)
@@ -1304,300 +1307,10 @@
   return cmap_ref;
 }
 
-/* Must be smaller than (WBUF_SIZE-2)/8 */
-#define MAX_UNICODES 16
-
-struct gent
-{
-  USHORT gid;
-  int32_t ucv; /* assigned PUA unicode */
-
-  int     num_unicodes;
-  int32_t unicodes[MAX_UNICODES];
-};
-
-static void
-create_cmaps (CMap *cmap, CMap *tounicode,
-	      struct ht_table *unencoded, unsigned char *GIDToCIDMap)
-{
-  struct ht_iter iter;
-
-  ASSERT(cmap && unencoded);
-
-  if (ht_set_iter(unencoded, &iter) < 0)
-    return;
-
-  CMap_set_silent(1); /* many warnings without this... */
-
-  do {
-    struct gent   *glyph;
-    unsigned char *ucv;
-    int            i, len;
-    unsigned char  *p, *endptr;
-    CID            cid;
-
-    glyph = (struct gent *)   ht_iter_getval(&iter);
-    ucv   = (unsigned char *) ht_iter_getkey(&iter, &len);
-
-    if (GIDToCIDMap) {
-      cid = ((GIDToCIDMap[2 * glyph->gid] << 8)|GIDToCIDMap[2 * glyph->gid + 1]);
-      if (cid == 0)
-	WARN("Glyph gid=%u does not have corresponding CID.", glyph->gid);
-    } else {
-      cid = glyph->gid;
-    }
-
-    CMap_add_cidchar(cmap, ucv, 4, cid);
-
-    if (tounicode) {
-      wbuf[0] = (cid >> 8) & 0xff;
-      wbuf[1] = cid & 0xff;
-      p       = wbuf + 2;
-      endptr  = wbuf + WBUF_SIZE;
-      len     = 0;
-      for (i = 0; i < glyph->num_unicodes; i++) {
-	      len += UC_UTF16BE_encode_char(glyph->unicodes[i], &p, endptr);
-      }
-      CMap_add_bfchar(tounicode, wbuf, 2, wbuf + 2, len);
-    }
-  } while (ht_iter_next(&iter) >= 0);
-
-  CMap_set_silent(0);
-
-  ht_clear_iter(&iter);
-}
-
-static void
-add_glyph (struct ht_table *unencoded,
-	   USHORT gid, int32_t ucv, int num_unicodes, int32_t *unicodes)
-{
-  struct gent *glyph;
-  int i;
-
-  ASSERT(unencoded);
-
-  if (gid == 0 || num_unicodes < 1) {
-    return;
-  }
-
-  wbuf[0] = (ucv >> 24) & 0xff;
-  wbuf[1] = (ucv >> 16) & 0xff;
-  wbuf[2] = (ucv >>  8) & 0xff;
-  wbuf[3] =  ucv & 0xff;
-
-  glyph = NEW(1, struct gent);
-  glyph->gid = gid;
-  glyph->num_unicodes = num_unicodes;
-  for (i = 0;
-       i < num_unicodes && i < MAX_UNICODES; i++) {
-    glyph->unicodes[i] = unicodes[i];
-  }
-
-  ht_append_table(unencoded, wbuf, 4, glyph);
-}
-
-/* This seriously affects speed... */
-static struct gent *
-find_glyph (struct ht_table *unencoded, int32_t ucv)
-{
-  ASSERT(unencoded);
-
-  wbuf[0] = (ucv >> 24) & 0xff;
-  wbuf[1] = (ucv >> 16) & 0xff;
-  wbuf[2] = (ucv >>  8) & 0xff;
-  wbuf[3] =  ucv & 0xff;
-
-  return (struct gent *) ht_lookup_table(unencoded, wbuf, 4);
-}
-
-static void
-handle_subst (pdf_obj *dst_obj, pdf_obj *src_obj, int flag,
-	      otl_gsub *gsub_list, tt_cmap *ttcmap,
-	      struct ht_table *unencoded)
-{
-  pdf_obj *tmp;
-  int32_t     i, j, src_size, dst_size;
-  int32_t     src, dst;
-  int32_t     src_start, src_end, dst_start, dst_end;
-
-  src_size = pdf_array_length(src_obj);
-  dst_size = pdf_array_length(dst_obj);
-
-  dst_start = dst_end = -1; dst = 0;
-  src_start = src_end = -1; src = 0;
-  for (i = 0, j = 0;
-       i < src_size && j < dst_size; i++) {
-    USHORT       gid;
-    int          rv;
-    struct gent *glyph;
-
-    tmp = pdf_get_array(src_obj, i);
-    if (PDF_OBJ_ARRAYTYPE(tmp)) {
-      src_start = (int32_t) pdf_number_value(pdf_get_array(tmp, 0));
-      src_end   = (int32_t) pdf_number_value(pdf_get_array(tmp, 1));
-    } else {
-      src_start = src_end = (int32_t) pdf_number_value(tmp);
-    }
-    for (src = src_start; src <= src_end; src++) {
-      glyph = find_glyph(unencoded, src);
-      if (glyph)
-	gid = glyph->gid;
-      else {
- 	gid = tt_cmap_lookup(ttcmap, src);
-      }
-      dst++;
-      if (dst > dst_end) {
-	tmp = pdf_get_array(dst_obj, j++);
-	if (PDF_OBJ_ARRAYTYPE(tmp)) {
-	  dst_start = (int32_t) pdf_number_value(pdf_get_array(tmp, 0));
-	  dst_end   = (int32_t) pdf_number_value(pdf_get_array(tmp, 1));
-	} else {
-	  dst_start = dst_end = (int32_t) pdf_number_value(tmp);
-	}
-	dst = dst_start;
-      }
-      if (gid == 0) {
-	if (flag == 'r' || flag == 'p') {
-	  if (src < 0x10000) {
-	    WARN("Font does not have glyph for U+%04X.", src);
-	  } else {
-	    WARN("Font does not have glyph for U+%06X.", src);
-	  }
-	}
-	if (flag == 'r') {
-	  ERROR("Missing glyph found...");
-	}
-	continue;
-      }
-      rv = otl_gsub_apply(gsub_list, &gid);
-      if (rv < 0) {
-	if (flag == 'p' || flag == 'r') {
-	  if (src < 0x10000) {
-	    WARN("No substituted glyph for U+%04X.", src);
-	  } else {
-	    WARN("No substituted glyph for U+%06X.", src);
-	  }
-	}
-	if (flag == 'r') {
-	  ERROR("Missing glyph found...");
-	}
-	continue;
-      }
-
-      if (glyph) {
-	glyph->gid = gid;
-      } else {
-	add_glyph(unencoded, gid, dst, 1, &src);
-      }
-
-      if (verbose > VERBOSE_LEVEL_MIN) {
-	if (dst < 0x10000) {
-	  MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%04X\n",
-	       gid, dst);
-	} else {
-	  MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%06X\n",
-	       gid, dst);
-	}
-      }
-
-    }
-  }
-
-  if (dst < dst_end || src < src_end ||
-      i < src_size  || j < dst_size) {
-    WARN("Number of glyphs in left-side and right-side not equal...");
-    WARN("Please check .otl file...");
-  }
-}
-
-static void
-handle_assign (pdf_obj *dst, pdf_obj *src, int flag,
-	       otl_gsub *gsub_list, tt_cmap *ttcmap,
-	       struct ht_table *unencoded)
-{
-  int32_t  unicodes[MAX_UNICODES], ucv;
-  int      i, n_unicodes, rv;
-  USHORT   gid_in[MAX_UNICODES], lig;
-
-  n_unicodes = pdf_array_length(src); /* FIXME */
-  ucv = (int32_t) pdf_number_value(pdf_get_array(dst, 0)); /* FIXME */
-  if (!UC_is_valid(ucv)) {
-    if (flag == 'r' || flag == 'p') {
-      if (ucv < 0x10000) {
-	WARN("Invalid Unicode in: %04X", ucv);
-      } else {
-	WARN("Invalid Unicode in: %06X", ucv);
-      }
-    }
-    if (flag == 'r') {
-      ERROR("Invalid Unicode code specified.");
-    }
-    return;
-  }
-
-  if (verbose > VERBOSE_LEVEL_MIN) {
-    MESG("otf_cmap>> Ligature component:");
-  }
-
-  for (i = 0; i < n_unicodes; i++) {
-    unicodes[i] =
-      (int32_t) pdf_number_value(pdf_get_array(src, i));
-    gid_in[i] = tt_cmap_lookup(ttcmap, unicodes[i]);
-
-    if (verbose > VERBOSE_LEVEL_MIN) {
-      if (unicodes[i] < 0x10000) {
-	MESG(" U+%04X (gid=%u)", unicodes[i], gid_in[i]);
-      } else {
-	MESG(" U+%06X (gid=%u)", unicodes[i], gid_in[i]);
-      }
-    }
-
-    if (gid_in[i] == 0) {
-      if (flag == 'r' || flag == 'p') {
-	if (unicodes[i] < 0x10000) {
-	  WARN("Unicode char U+%04X not exist in font...", unicodes[i]);
-	} else {
-	  WARN("Unicode char U+%06X not exist in font...", unicodes[i]);
-	}
-      }
-      if (flag == 'r') {
-	ERROR("Missing glyph found...");
-      }
-      return;
-    }
-
-  }
- 
-  if (verbose > VERBOSE_LEVEL_MIN) {
-    MESG("\n");
-  }
-
-  rv = otl_gsub_apply_lig(gsub_list,
-			  gid_in, (USHORT)n_unicodes, &lig);
-  if (rv < 0) {
-    if (flag == 'p')
-      WARN("No ligature found...");
-    else if (flag == 'r')
-      ERROR("No ligature found...");
-    return;
-  }
-
-  add_glyph(unencoded, lig, ucv, n_unicodes, unicodes);
-
-  if (verbose > VERBOSE_LEVEL_MIN) {
-    if (ucv < 0x10000) {
-      MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%04X\n", lig, ucv);
-    } else {
-      MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%06X\n", lig, ucv);
-    }
-  }
-
-  return;
-}
-
 static int
 load_base_CMap (const char *cmap_name, int wmode,
-		CIDSysInfo *csi, unsigned char *GIDToCIDMap, otl_gsub *gsub_list,
+		CIDSysInfo *csi, unsigned char *GIDToCIDMap,
+    otl_gsub *gsub_vert, otl_gsub *gsub_list,
 		tt_cmap *ttcmap)
 {
   int cmap_id;
@@ -1619,9 +1332,9 @@
     }
 
     if (ttcmap->format == 12) {
-      load_cmap12(ttcmap->map, GIDToCIDMap, gsub_list, cmap);
+      load_cmap12(ttcmap->map, GIDToCIDMap, gsub_vert, gsub_list, cmap);
     } else if (ttcmap->format == 4) {
-      load_cmap4(ttcmap->map, GIDToCIDMap, gsub_list, cmap);
+      load_cmap4(ttcmap->map, GIDToCIDMap, gsub_vert, gsub_list, cmap);
     }
 
     cmap_id = CMap_cache_add(cmap);
@@ -1630,156 +1343,18 @@
   return cmap_id;
 }
 
-static void
-load_gsub (pdf_obj *conf, otl_gsub *gsub_list, sfnt *sfont)
-{
-  pdf_obj  *rule;
-  char     *script, *language, *feature;
-  int       i, size;
-
-  rule = otl_conf_get_rule(conf);
-  if (!rule)
-    return;
-
-  script   = otl_conf_get_script  (conf);
-  language = otl_conf_get_language(conf);
-
-  size     = pdf_array_length(rule);
-  for (i = 0; i < size; i += 2) {
-    pdf_obj   *tmp, *commands;
-    int        flag;
-    int        j, num_comms;
-
-    tmp  = pdf_get_array(rule, i);
-    flag = (int) pdf_number_value(tmp);
-
-    commands  = pdf_get_array(rule, i+1);
-    num_comms = pdf_array_length(commands);
-
-    /* (assign|substitute) tag dst src */
-    for (j = 0 ; j < num_comms; j += 4) {
-      tmp = pdf_get_array(commands, 1);
-      if (PDF_OBJ_STRINGTYPE(tmp)) {
-	feature = pdf_string_value(tmp);
-	if (otl_gsub_add_feat(gsub_list,
-			      script, language, feature, sfont) < 0) {
-	  if (flag == 'p')
-	    WARN("No OTL feature matches \"%s.%s.%s\" found.",
-		 script, language, feature);
-	  else if (flag == 'r')
-	    ERROR("No OTL feature matches \"%s.%s.%s\" found.",
-		  script, language, feature);
-	}
-      }
-
-    }
-  }
-
-}
-
-static void
-handle_gsub (pdf_obj *conf,
-	     tt_cmap *ttcmap, otl_gsub *gsub_list,
-	     struct ht_table *unencoded)
-{
-  pdf_obj *rule;
-  char    *script, *language, *feature;
-  int      i, size;
-
-  if (!conf)
-    return;
-
-  rule = otl_conf_get_rule(conf);
-  if (!rule) {
-    return;
-  }
-
-  if (!PDF_OBJ_ARRAYTYPE(rule)) {
-    WARN("Not arraytype?");
-    return;
-  }
-  script   = otl_conf_get_script  (conf);
-  language = otl_conf_get_language(conf);
-
-  size = pdf_array_length(rule);
-  for (i = 0; i < size; i += 2) {
-    pdf_obj  *tmp, *commands;
-    int       j, num_comms;
-    int       flag;
-
-    tmp  = pdf_get_array(rule, i);
-    flag = (int) pdf_number_value(tmp);
-
-    commands  = pdf_get_array   (rule, i+1);
-    num_comms = pdf_array_length(commands);
-
-    for (j = 0; j < num_comms; j += 4) {
-      pdf_obj *operator;
-      pdf_obj *src, *dst, *feat;
-      int      rv;
-
-      /* (assing|substitute) tag dst src */
-      operator = pdf_get_array(commands, j);
-
-      feat     = pdf_get_array(commands, j+1);
-      if (PDF_OBJ_STRINGTYPE(feat))
-	feature = pdf_string_value(feat);
-      else
-	feature = NULL;
-
-      dst  = pdf_get_array(commands, j+2);
-      src  = pdf_get_array(commands, j+3);
-
-      rv = otl_gsub_select(gsub_list, script, language, feature);
-      if (rv < 0) {
-	if (flag == 'p') {
-	  WARN("No GSUB feature %s.%s.%s loaded...",
-	       script, language, feature);
-	} else if (flag == 'r') {
-	  ERROR("No GSUB feature %s.%s.%s loaded...",
-		script, language, feature);
-	}
-      } else {
-
-	if (verbose > VERBOSE_LEVEL_MIN) {
-	  MESG("otf_cmap>> %s:\n", pdf_name_value(operator));
-	}
-
-	if (!strcmp(pdf_name_value(operator), "assign")) {
-	  handle_assign(dst, src, flag,
-			gsub_list, ttcmap, unencoded);
-	} else if (!strcmp(pdf_name_value(operator), "substitute")) {
-	  handle_subst(dst, src, flag,
-		       gsub_list, ttcmap, unencoded);
-	}
-      }
-
-    }
-
-  }
-
-}
-
-static inline void
-hval_free (void *hval)
-{
-  RELEASE(hval);
-}
-
 int
 otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC font */
 		       const char *otl_tags, int wmode)
 {
   int    cmap_id = -1;
-  int    tounicode_id = -1, is_cidfont = 0;
+  int    is_cidfont = 0;
   sfnt  *sfont;
   ULONG  offset = 0;
   char  *base_name = NULL, *cmap_name = NULL;
-  char  *tounicode_name = NULL;
   FILE  *fp = NULL;
-  otl_gsub      *gsub_list = NULL;
+  otl_gsub      *gsub_vert = NULL, *gsub_list = NULL;
   tt_cmap       *ttcmap;
-  CMap          *cmap, *base, *tounicode = NULL;
   CIDSysInfo     csi = {NULL, NULL, 0};
   unsigned char *GIDToCIDMap = NULL;
 
@@ -1851,19 +1426,11 @@
     is_cidfont = 0;
   }
 
-  if (is_cidfont) {
-    tounicode_name = NULL;
-  } else {
-    tounicode_name = NEW(strlen(map_name)+strlen("-UTF16")+5, char);
-    sprintf(tounicode_name, "%s,%03d-UTF16", map_name, ttc_index);
-  }
-
   if (verbose > VERBOSE_LEVEL_MIN) {
     MESG("\n");
     MESG("otf_cmap>> Unicode charmap for font=\"%s\" layout=\"%s\"\n",
 	 map_name, (otl_tags ? otl_tags : "none"));
   }
-
   cmap_id = CMap_cache_find(cmap_name);
   if (cmap_id >= 0) {
     RELEASE(cmap_name);
@@ -1870,9 +1437,6 @@
     RELEASE(base_name);
     if (GIDToCIDMap)
       RELEASE(GIDToCIDMap);
-    if (tounicode_name)
-      RELEASE(tounicode_name);
-
     sfnt_close(sfont);
     DPXFCLOSE(fp);
 
@@ -1897,37 +1461,47 @@
     }
   }
   if (wmode == 1) {
-    gsub_list = otl_gsub_new();
-    if (otl_gsub_add_feat(gsub_list, "*", "*", "vrt2", sfont) < 0) {
-      if (otl_gsub_add_feat(gsub_list, "*", "*", "vert", sfont) < 0) {
+    gsub_vert = otl_gsub_new();
+    if (otl_gsub_add_feat(gsub_vert, "*", "*", "vrt2", sfont) < 0) {
+      if (otl_gsub_add_feat(gsub_vert, "*", "*", "vert", sfont) < 0) {
         WARN("GSUB feature vrt2/vert not found.");
-        otl_gsub_release(gsub_list);
-        gsub_list = NULL;
+        otl_gsub_release(gsub_vert);
+        gsub_vert = NULL;
       } else {
-        otl_gsub_select(gsub_list, "*", "*", "vert");
+        otl_gsub_select(gsub_vert, "*", "*", "vert");
       }
     } else {
-      otl_gsub_select(gsub_list, "*", "*", "vrt2");
+      otl_gsub_select(gsub_vert, "*", "*", "vrt2");
     }
   } else {
+    gsub_vert = NULL;
+  }
+  if (otl_tags) {
+    gsub_list = otl_gsub_new();
+    if (otl_gsub_add_feat_list(gsub_list, otl_tags, sfont) < 0) {
+      WARN("Readin GSUB feature table(s) failed for \"%s\"", otl_tags);
+    } else {
+      otl_gsub_set_chain(gsub_list, otl_tags);
+    }
+  } else {
     gsub_list = NULL;
   }
   cmap_id = load_base_CMap(base_name, wmode,
                            (is_cidfont ? &csi : NULL), GIDToCIDMap,
-                           gsub_list, ttcmap);
+                           gsub_vert, gsub_list, ttcmap);
   if (cmap_id < 0)
     ERROR("Failed to read OpenType/TrueType cmap table.");
+  if (gsub_vert)
+    otl_gsub_release(gsub_vert);
+  gsub_vert = NULL;
   if (gsub_list)
     otl_gsub_release(gsub_list);
   gsub_list = NULL;
 
-  if (!otl_tags) {
     RELEASE(cmap_name);
     RELEASE(base_name);
     if (GIDToCIDMap)
       RELEASE(GIDToCIDMap);
-    if (tounicode_name)
-      RELEASE(tounicode_name);
     if (is_cidfont) {
       if (csi.registry)
 	RELEASE(csi.registry);
@@ -1938,125 +1512,5 @@
     sfnt_close(sfont);
     DPXFCLOSE(fp);
 
-    return cmap_id;
-  }
-
-  base = CMap_cache_get(cmap_id);
-
-  cmap = CMap_new();
-  CMap_set_name (cmap, cmap_name);
-  CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID);
-  CMap_set_wmode(cmap, wmode);
-  /* CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4); */
-  CMap_set_usecmap(cmap, base);
-  CMap_add_cidchar(cmap, lrange_max, 4, 0); /* FIXME */
-
-  if (is_cidfont) {
-    CMap_set_CIDSysInfo(cmap, &csi);
-    if (csi.registry)
-      RELEASE(csi.registry);
-    if (csi.ordering)
-      RELEASE(csi.ordering);
-  } else {
-    CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY);
-  }
-
-  gsub_list = otl_gsub_new();
-
-  {
-    struct ht_table unencoded;
-    char    *conf_name, *opt_tag;
-    pdf_obj *conf, *opt_conf;
-
-    conf_name = NEW(strlen(otl_tags)+1, char);
-    memset (conf_name, 0, strlen(otl_tags)+1);
-    opt_tag  = strchr(otl_tags, ':');
-    if (opt_tag) {
-      opt_tag++;
-      strncpy(conf_name, otl_tags,
-	      strlen(otl_tags) - strlen(opt_tag) - 1);
-    } else {
-      strcpy(conf_name, otl_tags);
-    }
-
-    if (verbose > VERBOSE_LEVEL_MIN) {
-      MESG("otf_cmap>> Read layout config. \"%s\"\n", conf_name);
-    }
-
-    conf = otl_find_conf(conf_name);
-    if (!conf)
-      ERROR("Layout file \"%s\" not found...", conf_name);
-
-    load_gsub(conf, gsub_list, sfont);
-    if (opt_tag) {
-      if (verbose > VERBOSE_LEVEL_MIN) {
-	MESG("otf_cmap>> Layout option \"%s\" enabled\n", opt_tag);
-      }
-      opt_conf = otl_conf_find_opt(conf, opt_tag);
-      if (!opt_conf)
-	ERROR("There is no option \"%s\" in \"%s\".",
-	      opt_tag, conf_name);
-      load_gsub(opt_conf, gsub_list, sfont);
-    }
-
-    ht_init_table(&unencoded, hval_free);
-
-    handle_gsub(conf, ttcmap, gsub_list, &unencoded);
-    if (opt_tag) {
-      opt_conf = otl_conf_find_opt(conf, opt_tag);
-      if (!opt_conf)
-	ERROR("There is no option \"%s\" in \"%s\".",
-	      opt_tag, conf_name);
-      handle_gsub(opt_conf, ttcmap, gsub_list, &unencoded);
-    }
-    if (is_cidfont) {
-      tounicode_id = -1;
-      tounicode    = NULL;
-    } else {
-      tounicode_id = CMap_cache_find(tounicode_name);
-      if (tounicode_id >= 0)
-	tounicode  = CMap_cache_get(tounicode_id);
-      else {
-	tounicode = CMap_new();
-	CMap_set_name (tounicode, tounicode_name);
-	CMap_set_type (tounicode, CMAP_TYPE_TO_UNICODE);
-	CMap_set_wmode(tounicode, 0);
-	CMap_add_codespacerange(tounicode, srange_min, srange_max, 2);
-	CMap_set_CIDSysInfo(tounicode, &CSI_UNICODE);
-	/* FIXME */
-	CMap_add_bfchar(tounicode, srange_min, 2, srange_max, 2);
-      }
-    }
-    create_cmaps(cmap, tounicode, &unencoded, GIDToCIDMap);
-
-    ht_clear_table(&unencoded);
-    RELEASE(conf_name);
-  }
-
-  cmap_id = CMap_cache_add(cmap);
-  if (!is_cidfont && tounicode_id < 0) /* New */
-    CMap_cache_add(tounicode);
-
-  tt_cmap_release(ttcmap);
-  if (gsub_list)
-    otl_gsub_release(gsub_list);
-
-  if (verbose > VERBOSE_LEVEL_MIN) {
-    MESG("otf_cmap>> Overwrite CMap \"%s\" by \"%s\" with usecmap\n",
-	 base_name, cmap_name);
-  }
-
-  if (GIDToCIDMap)
-    RELEASE(GIDToCIDMap);
-  if (base_name)
-    RELEASE(base_name);
-  if (cmap_name)
-    RELEASE(cmap_name);
-  if (tounicode_name)
-    RELEASE(tounicode_name);
-
-  sfnt_close(sfont);
-  DPXFCLOSE(fp);
-
   return cmap_id;
 }

Modified: trunk/Build/source/texk/dvipdfm-x/tt_gsub.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/tt_gsub.c	2017-04-15 13:58:58 UTC (rev 43806)
+++ trunk/Build/source/texk/dvipdfm-x/tt_gsub.c	2017-04-15 20:19:40 UTC (rev 43807)
@@ -1269,10 +1269,16 @@
 }
 
 #define GSUB_LIST_MAX 32
+struct gsub_entry {
+  int                index;
+  struct gsub_entry *next;
+};
+
 struct otl_gsub
 {
   int num_gsubs;
   int select;
+  struct gsub_entry   *first;
   struct otl_gsub_tab gsubs[GSUB_LIST_MAX];
 };
 
@@ -1284,10 +1290,21 @@
   gsub_list = NEW(1, struct otl_gsub);
   gsub_list->num_gsubs = 0;
   gsub_list->select    = -1;
+  gsub_list->first     = NULL;
 
   return (otl_gsub *) gsub_list;
 }
 
+static void
+clear_chain (otl_gsub *gsub_list) {
+  struct gsub_entry *entry, *next;
+  for (entry = gsub_list->first; entry != NULL; entry = next) {
+    next = entry->next;
+    RELEASE(entry);
+  }
+  gsub_list->first = NULL;
+}
+
 int
 otl_gsub_add_feat (otl_gsub *gsub_list,
                    const char *script,
@@ -1342,6 +1359,56 @@
   return retval;
 }
 
+static const char *
+scan_otl_tag (const char *otl_tags, const char *endptr,
+              char *script, char *language, char *feature)
+{
+  const char *p, *period;
+
+  ASSERT(script && language && feature);
+  ASSERT(otl_tags < endptr);
+
+  if (!otl_tags)
+    return NULL;
+
+  memset(script, ' ', 4);   script[4]   = 0;
+  memset(language, ' ', 4); language[4] = 0;
+  memset(feature, ' ', 4);  feature[4]  = 0;
+
+  /* First parse otl_tags variable */
+  p = otl_tags;
+  period = strchr(p, '.');
+  if (period && period < endptr) {
+    /* Format scrp.lang.feat */
+    if (period < p + 5) {
+      strncpy(script, p, period - p);
+    } else {
+      WARN("Invalid OTL script tag found: %s", p);
+    }
+    p = period + 1;
+    period = strchr(p, '.');
+    if (period && period < endptr) {
+      /* Now lang part */
+      if (period < p + 5) {
+        strncpy(language, p, period - p);
+      } else {
+        WARN("Invalid OTL lanuage tag found: %s", p);
+      }
+      p = period + 1;
+    }
+  } else {
+    strcpy(script, "*");
+    strcpy(language, "*");
+  }
+  /* Finally feature */
+  if (p < endptr) {
+    strncpy(feature, p, endptr - p);
+    p = endptr;
+  }
+
+  return p;
+}
+
 void
 otl_gsub_release (otl_gsub *gsub_list)
 {
@@ -1381,7 +1448,7 @@
     }
     RELEASE(gsub->subtables);
   }
-
+  clear_chain(gsub_list);
   RELEASE(gsub_list);
 }
 
@@ -1487,7 +1554,7 @@
 }
 
 int
-otl_gsub_select (otl_gsub *gsub_list,
+gsub_find (otl_gsub *gsub_list,
                  const char *script,
                  const char *language,
                  const char *feature)
@@ -1500,16 +1567,116 @@
     if (!strcmp(gsub->script,   script)   &&
         !strcmp(gsub->language, language) &&
         !strcmp(gsub->feature,  feature)) {
-      gsub_list->select = i;
       return i;
     }
   }
 
-  gsub_list->select = -1;
+  return -1;
+}
 
+int
+otl_gsub_select (otl_gsub *gsub_list,
+                 const char *script,
+                 const char *language,
+                 const char *feature)
+{
+  gsub_list->select = gsub_find(gsub_list, script, language, feature);
+  return gsub_list->select;
+}
+
+int
+otl_gsub_set_chain (otl_gsub *gsub_list, const char *otl_tags) {
+  struct gsub_entry *prev = NULL;
+  const char *p, *nextptr, *endptr;
+  char script[5], language[5], feature[5];
+  int  idx;
+
+  clear_chain(gsub_list);
+
+  endptr = otl_tags + strlen(otl_tags);
+  for (p = otl_tags; p < endptr; p = nextptr) {
+    nextptr = strchr(p, ':');
+    if (!nextptr)
+      nextptr = endptr;
+    scan_otl_tag(p, nextptr, script, language, feature);
+    idx = gsub_find(gsub_list, script, language, feature);
+    if (idx >= 0 && idx <= gsub_list->num_gsubs) {
+      struct gsub_entry *entry;
+      entry = NEW(1, struct gsub_entry);
+      if (prev)
+        prev->next = entry;
+      entry->index = idx;
+      prev = entry;
+    }
+    nextptr++;
+  }
+  if (prev)
+    prev->next = NULL;
+  gsub_list->first = prev;
+
+  return 0;
+}
+
+int
+otl_gsub_add_feat_list (otl_gsub *gsub_list, const char *otl_tags, sfnt *sfont)
+{
+  const char *p, *nextptr, *endptr;
+  char script[5], language[5], feature[5];
+  int  idx;
+
+  if (!gsub_list || !otl_tags || !sfont)
   return -1;
+
+  clear_chain(gsub_list);
+  endptr = otl_tags + strlen(otl_tags);
+  for (p = otl_tags; p < endptr; p = nextptr) {
+    nextptr = strchr(p, ':');
+    if (!nextptr)
+      nextptr = endptr;
+    scan_otl_tag(p, nextptr, script, language, feature);
+    idx = gsub_find(gsub_list, script, language, feature);
+    if (idx < 0) {
+      otl_gsub_add_feat(gsub_list, script, language, feature, sfont);
+    }
+    nextptr++;
+  }
+
+  return 0;
 }
 
+int
+otl_gsub_apply_chain (otl_gsub *gsub_list, USHORT *gid) {
+  int    retval = -1;
+  struct otl_gsub_tab    *gsub;
+  struct otl_gsub_subtab *subtab;
+  struct gsub_entry      *entry;
+  int    i, idx;
+
+  if (!gsub_list || !gid)
+    return retval;
+
+  for (entry = gsub_list->first;
+       entry != NULL; entry = entry->next) {
+    idx = entry->index;
+    if (idx < 0 || idx >= gsub_list->num_gsubs)
+      continue;
+    gsub = &(gsub_list->gsubs[idx]);
+    for (i = 0, retval = -1;
+         retval < 0 && i < gsub->num_subtables; i++) {
+      subtab = &(gsub->subtables[i]);
+      switch ((int) subtab->LookupType){
+      case OTL_GSUB_TYPE_SINGLE:
+        retval = otl_gsub_apply_single(subtab, gid);
+        break;
+      default:
+        break;
+      }
+    }
+  }
+
+  return retval;
+}
+
 #if  0
 static int
 otl_gsub_dump_single (struct otl_gsub_subtab *subtab)

Modified: trunk/Build/source/texk/dvipdfm-x/tt_gsub.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/tt_gsub.h	2017-04-15 13:58:58 UTC (rev 43806)
+++ trunk/Build/source/texk/dvipdfm-x/tt_gsub.h	2017-04-15 20:19:40 UTC (rev 43807)
@@ -55,6 +55,12 @@
                                 USHORT *gid_in, USHORT num_gids,
                                 USHORT *gid_out);
 
+/* Handle a list of OTL features */
+extern int  otl_gsub_add_feat_list (otl_gsub *gsub_list,
+                                    const char *otl_tags, sfnt *sfont);
+extern int  otl_gsub_set_chain   (otl_gsub *gsub_list, const char *otl_tags);
+extern int  otl_gsub_apply_chain (otl_gsub *gsub_list, USHORT *gid);
+
 #if  0  
 extern int  otl_gsub_dump      (otl_gsub *gsub_list,
                                 const char *script,



More information about the tex-live-commits mailing list