[Gs-devel] refined MDRC patch (still including "relpos")
mpsuzuki at hiroshima-u.ac.jp
mpsuzuki at hiroshima-u.ac.jp
Mon May 28 03:35:24 PDT 2001
Dear Mr. Melichev,
Sorry for lated posting, I had a network trouble,
took 2 hours to sync the patch to the current CVS tree.
Following the revised MDRC patch. In gs_cmap.ps, there's
comment on "relpos" feature, and a sample of "relpos"
disabler is included.
# I send a tarball of modified files to you in another mail.
# For gs-devel mailing list, a patch would be better.
Regards,
suzuki toshiya
diff -Nur gs-CVS/src.orig/gdebug.h gs-CVS/src/gdebug.h
--- gs-CVS/src.orig/gdebug.h Wed Sep 20 04:00:11 2000
+++ gs-CVS/src/gdebug.h Mon May 28 18:53:24 2001
@@ -122,5 +122,6 @@
void debug_dump_bitmap(P4(const byte * from, uint raster, uint height,
const char *msg));
void debug_print_string(P2(const byte * str, uint len));
+void debug_print_string_hex(P2(const byte * str, uint len));
#endif /* gdebug_INCLUDED */
diff -Nur gs-CVS/src.orig/gsmisc.c gs-CVS/src/gsmisc.c
--- gs-CVS/src.orig/gsmisc.c Mon Apr 9 17:35:51 2001
+++ gs-CVS/src/gsmisc.c Mon May 28 18:53:24 2001
@@ -440,6 +440,17 @@
dflush();
}
+/* Print a string in hexdump format. */
+void
+debug_print_string_hex(const byte * chrs, uint len)
+{
+ uint i;
+
+ for (i = 0; i < len; i++)
+ dprintf1("%02x", chrs[i]);
+ dflush();
+}
+
/*
* The following code prints a hex stack backtrace on Linux/Intel systems.
* It is here to be patched into places where we need to print such a trace
diff -Nur gs-CVS/src.orig/gxfcmap.h gs-CVS/src/gxfcmap.h
--- gs-CVS/src.orig/gxfcmap.h Wed Nov 29 14:50:03 2000
+++ gs-CVS/src/gxfcmap.h Mon May 28 18:53:24 2001
@@ -69,8 +69,9 @@
typedef enum {
CODE_VALUE_CID, /* CIDs */
CODE_VALUE_GLYPH, /* glyphs */
- CODE_VALUE_CHARS /* character(s) */
-#define CODE_VALUE_MAX CODE_VALUE_CHARS
+ CODE_VALUE_CHARS, /* character(s) */
+ CODE_VALUE_UNDEF, /* CID - for notdef(char|range) dst */
+#define CODE_VALUE_MAX CODE_VALUE_UNDEF
} gx_code_value_type_t;
/* The strings in this structure are all const after initialization. */
typedef struct gx_code_lookup_range_s {
diff -Nur gs-CVS/src.orig/gsfcmap.c gs-CVS/src/gsfcmap.c
--- gs-CVS/src.orig/gsfcmap.c Tue Dec 19 06:58:03 2000
+++ gs-CVS/src/gsfcmap.c Mon May 28 18:53:24 2001
@@ -147,6 +147,142 @@
return 0;
}
+/*
+ * multi-dimentional range comparator
+ */
+#define if_debug_print_string_hex(c, str, len)\
+ if (gs_debug_c(c)) debug_print_string_hex((str), (len))
+
+#define if_debug_print_msg_str_in_range(c, str)\
+BEGIN\
+ if_debug_print_string_hex(c, str, prefix_size + key_size);\
+ if_debug0(c, " in ");\
+ if_debug_print_string_hex(c, prefix, prefix_size);\
+ if_debug_print_string_hex(c, key_lo, key_size);\
+ if_debug0(c, " - ");\
+ if_debug_print_string_hex(c, prefix, prefix_size);\
+ if_debug_print_string_hex(c, key_hi, key_size);\
+END
+
+private int
+gs_cmap_get_shortest_chr(const gx_code_map_t * pcmap, uint *pfidx)
+{
+ int i;
+ int len_shortest = MAX_CMAP_CODE_SIZE;
+ uint fidx_shortest = 0; /* font index for this fallback */
+
+ for (i = pcmap->num_lookup - 1; i >= 0; --i) {
+ const gx_code_lookup_range_t *pclr = &pcmap->lookup[i];
+ if ((pclr->key_prefix_size + pclr->key_size) <= len_shortest) {
+ len_shortest = (pclr->key_prefix_size + pclr->key_size);
+ fidx_shortest = pclr->font_index;
+ }
+ }
+
+ if (NULL != pfidx)
+ *pfidx = fidx_shortest;
+ return len_shortest;
+}
+
+private int
+gs_multidim_cmp_range(const byte *str,
+ const byte *prefix,
+ const byte *key_lo, const byte *key_hi,
+ int prefix_size, int key_size)
+{
+ int i;
+ if_debug0('J', "\n[J]gmcr() checks");
+ if_debug_print_msg_str_in_range('J', str);
+ if_debug0('J', "\n");
+
+ if (0 < prefix_size) {
+ for (i = 0; i < prefix_size; i++)
+ if (memcmp(prefix, str, i))
+ break;
+
+ if (0 == i) /* prefix No match */
+ return 0;
+ else if (i < prefix_size) /* prefix partial match */
+ return i;
+ else if (0 == key_size) /* prefix full match, and no key */
+ return prefix_size;
+ /* completely matched, and key (with finite length) */
+ str = str + prefix_size;
+ }
+
+ for (i = 0; i < key_size; i++)
+ if (str[i] < key_lo[i] || key_hi[i] < str[i])
+ break;
+
+ if (0 == prefix_size && 0 == i) /* key no match */
+ return 0;
+ else if (i < key_size) /* key partial match */
+ return (prefix_size + i);
+
+ /* (prefix full patched, and) key full matched */
+ return (prefix_size + key_size);
+}
+
+
+/*
+ * multi-dimentional relative position calculator
+ */
+private int
+gs_multidim_calc_relpos(const byte *str,
+ const byte *prefix,
+ const byte *key_lo, const byte *key_hi,
+ int prefix_size, int key_size)
+{
+ /*
+ * +---------------+ (L * M * N)
+ * /| /|
+ * / | / |
+ * / | / |
+ * +---------------+ |
+ * | +---------- |---+ (L * M)
+ * N | / | /
+ * | / | /M
+ * |/1 2 3 . . . . |/
+ * +---------------+
+ * 0 L
+ *
+ * L: 1st dimension
+ * M: 2nd dimension
+ * N: 3rd dimension
+ *
+ * "relpos" calculates the number how many blocks are needed to fill
+ * the region from [0,0,0] to [l,m,n].
+ *
+ * To increment for the 1st dimension ([l-1, m, n] to [l, m, n]),
+ * 1 block is consumed.
+ *
+ * To increment for the 2nd dimension ([l, m-1, n] to [l, m, n]),
+ * L blocks are consumed.
+ *
+ * To increment for the 3rd dimension ([l, m, n-1] to [l, m, n]),
+ * (L*M) blocks are consumed.
+ *
+ * The calculation starts low dimension (l, then m, then n), and
+ * the number of blocks to increment current dimension is stored in
+ * variable "j".
+ */
+
+ int i; /* index for current dimension */
+ int j = 1; /* how many # is required to increment current "1" */
+ int rel_pos = 0;
+
+ if_debug0('J', "[J]gmcrp() calc rel_pos for 0x");
+ if_debug_print_msg_str_in_range('J', str);
+ if_debug0('J', "\n");
+
+ for (i = key_size - 1; 0 <= i; i--) {
+ rel_pos = rel_pos
+ + j * (str[prefix_size + i] - key_lo[i]);
+ j = j * (key_hi[i] - key_lo[i] + 1);
+ }
+ return rel_pos;
+}
+
/* Get a big-endian integer. */
private uint
bytes2int(const byte *p, int n)
@@ -180,7 +316,11 @@
*/
int i;
- for (i = pcmap->num_lookup - 1; i >= 0; --i) { /* reverse scan order due to 'usecmap' */
+ /* old implementation initialized *pchr out of CMDN() */
+ *pchr = 0;
+
+ /* reverse scan order due to 'usecmap' */
+ for (i = pcmap->num_lookup - 1; i >= 0; --i) {
const gx_code_lookup_range_t *pclr = &pcmap->lookup[i];
int pre_size = pclr->key_prefix_size, key_size = pclr->key_size,
chr_size = pre_size + key_size;
@@ -221,6 +361,10 @@
bytes2int(str + pre_size, key_size) -
bytes2int(key, key_size);
return 0;
+ case CODE_VALUE_UNDEF:
+ *pglyph = gs_min_cid_glyph +
+ bytes2int(pvalue, pclr->value_size);
+ return 0;
case CODE_VALUE_GLYPH:
*pglyph = bytes2int(pvalue, pclr->value_size);
return 0;
@@ -240,9 +384,187 @@
return 0;
}
+private int
+code_map_decode_next_mdrc(const gx_code_map_t * pcmap, const gs_const_string * pstr,
+ uint * pindex, uint * pfidx,
+ gs_char * pchr, gs_glyph * pglyph)
+{
+ /*
+ * one "range" is specified by
+ * (prefix + key(lo-end)) and (prefix + key(hi-end)).
+ *
+ * pclr is a collection of range"s"
+ * which have same prefix, and keys with same length.
+ *
+ * number of ranges = pclr->num_keys
+ * prefix = pclr->key_prefix
+ * prefix length = pclr->key_prefix_size
+ * key = pclr->key.data
+ * key length = pclr->key_size
+ * +-----------+-----------------------+
+ * | *(prefix) | *(key) |
+ * |...MATCHED...
+ * | *(prefix) | *(key + key_size) |
+ * +-----------+-----------------------+
+ * / / / / / / / / / / / / / / / / /
+ * |...NOT MATCHED |
+ * / / / / / / / / / / / / / / / / /
+ * +-----------+-----------------------+
+ * | *(prefix) | *(key + 2 * key_size) |
+ * |...MATCHED
+ * | *(prefix) | *(key + 3 * key_size) |
+ * +-----------+-----------------------+
+ *
+ * ...
+ *
+ * pcmap is a collection of pclr.
+ * number of pclr = pcmap->num_lookup
+ * pclr = pcmap->lookup[i]
+ *
+ */
+
+ const byte *str = pstr->data + *pindex;
+ uint ssize = pstr->size - *pindex;
+ /*
+ * The keys are not sorted due to 'usecmap'. Possible optimization :
+ * merge and sort keys in 'zbuildcmap', then use binary search here.
+ * This would be valuable for UniJIS-UTF8-H, which contains about 7000
+ * keys.
+ */
+ int i;
+
+ /*
+ * In the fallback of CMap decoding procedure, there is "partial matching".
+ * For detail, refer PostScript Ref. Manual v3 at the end of Fonts chapter.
+ */
+
+ /* partial match parameters, temporal use, NOT pointer !!! */
+ int pm_maxlen = 0; /* partial match: max length */
+ int pm_index = *pindex; /* partial match: ptr index (in str) */
+ uint pm_fidx = *pfidx; /* partial match: ptr font index */
+ gs_char pm_chr = *pchr; /* partial match: ptr character */
+ /* pm_pvalue is not needed, because
+ partial match is used for notdef */
+
+ *pchr = 0; /* originally, pchr is initialized out of CMDN() */
+
+ if_debug1('J', "[J]CMDN() is called: str=0x%lx (", str);
+ if_debug0('J', " (");
+ if_debug_print_string_hex('J', str, ssize);
+ if_debug1('J', ") ssize=%d\n", ssize);
+ if_debug1('J', "[J]CMDN() checks %d ranges\n", pcmap->num_lookup);
+
+ for (i = pcmap->num_lookup - 1; i >= 0; --i) {
+ /* main loop - scan the map passed via pcmap */
+ /* reverse scan order due to 'usecmap' */
+
+ const gx_code_lookup_range_t *pclr = &pcmap->lookup[i];
+ int pre_size = pclr->key_prefix_size, key_size = pclr->key_size,
+ chr_size = pre_size + key_size;
+
+ /* length of the given byte stream is shorter than
+ * chr-length of current range, no need for further check,
+ * skip to the next range.
+ */
+ if (ssize < chr_size)
+ continue;
+
+ /* If the first byte of current range prefix does not match
+ * with the given string, there will be no match
+ * (exact nor partial), so skip to the next range.
+ */
+ if (0 < pclr->key_prefix && str[0] != pclr->key_prefix[0])
+ continue;
+
+ /* The first byte of current range matches with given string,
+ * progress to the real comparison.
+ */
+
+ /* Search the lookup range. We could use binary search. */
+ {
+ const byte *key = pclr->keys.data;
+ int step = key_size;
+ int k;
+ const byte *pvalue = NULL;
+
+ if_debug3('J', "[J]CMDN() lookup range: key=0x%lx pvalue=%lx step=%d\n", key, pvalue, step);
+
+ /* when range is "range", 2 keys for lo-end and hi-end
+ * are stacked. So twice the step. */
+ if (pclr->key_is_range)
+ step <<=1; /* step = step * 2; */
+
+ for (k = 0; k < pclr->num_keys; ++k, key += step) {
+ int ret_gmcr;
+ ret_gmcr = gs_multidim_cmp_range(str,
+ pclr->key_prefix, key, key + key_size,
+ pre_size, key_size);
+ if (0 < ret_gmcr && pm_maxlen < chr_size)
+ pm_maxlen = chr_size;
+ pm_chr = (*pchr << (chr_size * 8)) + bytes2int(str, chr_size);
+ pm_index = (*pindex) + chr_size;
+ pm_fidx = pclr->font_index;
+ if (ret_gmcr == pre_size + key_size)
+ break;
+ }
+
+ /* all keys are tried, but found no match. */
+ /* go to next prefix. */
+ if (k == pclr->num_keys)
+ continue;
+
+ /* We have a match. Return the result. */
+ *pchr = (*pchr << (chr_size * 8)) + bytes2int(str, chr_size);
+ *pindex += chr_size;
+ *pfidx = pclr->font_index;
+ pvalue = pclr->values.data + k * pclr->value_size;
+ switch (pclr->value_type) {
+ case CODE_VALUE_CID:
+ {
+ int ret_gmcrp;
+ ret_gmcrp = gs_multidim_calc_relpos(str,
+ pclr->key_prefix, key, key + key_size,
+ pre_size, key_size);
+ *pglyph = gs_min_cid_glyph +
+ bytes2int(pvalue, pclr->value_size) +
+ ret_gmcrp;
+ }
+ return 0;
+ case CODE_VALUE_UNDEF:
+ *pglyph = gs_min_cid_glyph +
+ bytes2int(pvalue, pclr->value_size);
+ return 0;
+ case CODE_VALUE_GLYPH:
+ *pglyph = bytes2int(pvalue, pclr->value_size);
+ return 0;
+ case CODE_VALUE_CHARS:
+ *pglyph =
+ bytes2int(pvalue, pclr->value_size) +
+ bytes2int(str + pre_size, key_size) -
+ bytes2int(key, key_size);
+ return pclr->value_size;
+ default: /* shouldn't happen */
+ return_error(gs_error_rangecheck);
+ }
+ }
+ }
+ /* No mapping. */
+ *pchr = pm_chr;
+ *pindex = pm_index;
+ *pfidx = pm_fidx;
+ *pglyph = gs_no_glyph;
+ return 0;
+}
+#undef if_debug_print_string_hex(c, str, len)
+#undef if_debug_print_msg_str_in_range(c, str)
+
/*
* Decode a character from a string using a CMap.
* Return like code_map_decode_next.
+ * At present, the range specification by (begin|end)codespacerange
+ * is not used in this function. Therefore, this function accepts
+ * some invalid CMap which def & undef maps exceed the codespacerange.
+ * It should be checked in this function, or some procedure in gs_cmap.ps.
*/
int
gs_cmap_decode_next(const gs_cmap_t * pcmap, const gs_const_string * pstr,
@@ -252,14 +574,74 @@
uint save_index = *pindex;
int code;
- *pchr = 0;
+ uint pm_index;
+ uint pm_fidx;
+ gs_char pm_chr;
+
+ /* For first, check defined map */
code =
- code_map_decode_next(&pcmap->def, pstr, pindex, pfidx, pchr, pglyph);
+ code_map_decode_next_mdrc(&pcmap->def, pstr, pindex, pfidx, pchr, pglyph);
+
+ /* This is defined character */
if (code != 0 || *pglyph != gs_no_glyph)
return code;
- /* This is an undefined character. Use the notdef map. */
+
+ /* In here, this is NOT defined character */
+ /* save partially matched results */
+ pm_index = *pindex;
+ pm_fidx = *pfidx;
+ pm_chr = *pchr;
+
+ /* check notdef map. */
*pindex = save_index;
- *pchr = 0;
- return code_map_decode_next(&pcmap->notdef, pstr, pindex, pfidx,
- pchr, pglyph);
+ code =
+ code_map_decode_next_mdrc(&pcmap->notdef, pstr, pindex, pfidx, pchr, pglyph);
+
+ /* This is defined "notdef" character. */
+ if (code != 0 || *pglyph != gs_no_glyph)
+ return code;
+
+ /*
+ * This is undefined in def & undef maps,
+ * use partially matched result with default notdef (CID = 0).
+ */
+ if (save_index < pm_index) {
+
+ /* there was some partially matched */
+
+ *pglyph = gs_min_cid_glyph; /* CID = 0 */
+ *pindex = pm_index;
+ *pfidx = pm_fidx;
+ *pchr = '\0';
+ return 0; /* should return some error for partial matched .notdef? */
+ }
+ else {
+ /* no match */
+
+ /* Even partial match is failed.
+ * Getting the shortest length from defined characters,
+ * and cut a .notdef with same length, from undecodable string.
+ * Also this procedure is specified in PS Ref. Manual v3,
+ * at the end of Fonts chapter.
+ */
+
+ const byte *str = pstr->data + save_index;
+ uint ssize = pstr->size - save_index;
+ int chr_size_shortest =
+ gs_cmap_get_shortest_chr(&pcmap->def, pfidx);
+
+ if (chr_size_shortest <= ssize) {
+ *pglyph = gs_min_cid_glyph; /* CID = 0, this is CMap fallback */
+ *pindex = save_index + chr_size_shortest;
+ *pchr = '\0';
+ return 0; /* should return some error for fallback .notdef? */
+ }
+ else {
+ /* Undecodable string is shorter than the shortest character,
+ * there's no way except to return error.
+ */
+ *pglyph = gs_no_glyph;
+ return -1;
+ }
+ }
}
diff -Nur gs-CVS/src.orig/zfcid0.c gs-CVS/src/zfcid0.c
--- gs-CVS/src.orig/zfcid0.c Wed Mar 14 04:57:06 2001
+++ gs-CVS/src/zfcid0.c Mon May 28 18:53:24 2001
@@ -484,8 +484,21 @@
code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
(gs_glyph)(gs_min_cid_glyph + op->value.intval),
&gstr, &fidx);
- if (code < 0)
- return code;
+
+ /* return code; original error-sensitive & fragile code */
+ if (code < 0) { /* failed to load glyph data, put CID 0 */
+ int default_fallback_CID = 0 ;
+
+ if_debug2('J', "[J]ztype9cidmap() use CID %d instead of glyph-missing CID %d\n", default_fallback_CID, op->value.intval);
+
+ op->value.intval = default_fallback_CID;
+
+ /* reload glyph for default_fallback_CID */
+
+ code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
+ (gs_glyph)(gs_min_cid_glyph + op->value.intval),
+ &gstr, &fidx);
+ }
make_const_string(op - 1,
a_readonly | imemory_space((gs_ref_memory_t *)pfont->memory),
diff -Nur gs-CVS/lib.orig/gs_cmap.ps gs-CVS/lib/gs_cmap.ps
--- gs-CVS/lib.orig/gs_cmap.ps Wed Nov 29 16:10:27 2000
+++ gs-CVS/lib/gs_cmap.ps Mon May 28 18:53:24 2001
@@ -23,6 +23,22 @@
% ---------------- Public operators ---------------- %
+/.rewriteTempMapsNotDef {
+ DEBUG { (rewriting TempMapsNotDef\n) print flush } if
+ .TempMaps 2 get
+ dup length 0 gt {
+ 0 get
+ DEBUG { (...original...\n) print flush } if
+ 1 5 2 index length 1 sub {
+ { 1 index exch get 2 3 put } stopped
+ { DEBUG { (cannot rewrite\n) print flush } if }
+ { DEBUG { (rewrite\n) print flush } if } ifelse
+ } for
+ } if
+ pop
+ DEBUG { (...FINISHED...\n) print } if
+} bind def
+
% composefont doesn't appear in CMap files -- it's documented in
% the "PostScript Language Reference Manual Supplement".
/composefont { % <name> <cmap|cmapname> <fonts> composefont <font>
@@ -89,11 +105,19 @@
/CodeMap null def % for .buildcmap
} bind def
/endcmap { % - endcmap -
+ .rewriteTempMapsNotDef
+ DEBUG {
+ (*** defined charmap ***\n) print
+ .TempMaps 1 get {exch == (\t) print ==} forall
+ (*** undefined charmap ***\n) print
+ .TempMaps 2 get {exch == (\t) print ==} forall
+ } if
10 dict begin 0 1 2 {
/i exch def
% Append data from .TempMaps to .CodeMapData.
/t .TempMaps i get def
.CodeMapData i get length t { exch pop length add } forall
+ DEBUG { (requested array size ) print dup == } if
array /a exch def
a 0 .CodeMapData i get .putmore
0 1 t length 1 sub {
@@ -273,44 +297,99 @@
counttomark 3 idiv {
counttomark -3 roll % process in correct order
% Construct prefix, params, key_lo, key_hi, value, font_index
- 3 1 roll dup length 1 eq {
- () 3 1 roll % prefix
- <01 01 00 02> % params
- 3 1 roll % keys
- concatstrings 4 -1 roll .endmapvalue
- } {
- % Stack: cid_base code_lo code_hi
- % Hack: handle 16-bit single-range mappings specially.
- counttomark 3 eq 1 index length 2 eq and {
- () 3 1 roll % prefix
- <02 01 00 02> % params
- 3 1 roll % keys
- concatstrings 4 -1 roll .endmapvalue
- } {
- exch dup dup length 1 sub 0 exch getinterval % prefix
- % Stack: cid_base code_hi code_lo prefix
- <01 01 00 02> % params
- 3 -1 roll dup length 1 sub 1 getinterval % key_lo
- 4 -1 roll dup length 1 sub 1 getinterval % key_hi
- concatstrings
- 4 -1 roll .endmapvalue
+ 3 1 roll % <cid_base> <code_lo> <code_hi>
+ % prefix key
+ % 1-byte code: () .
+ % 1-byte range: () .
+ % N-byte code: . (*)
+ % N-byte range: (*) (*)
+ dup 1 index eq { % <code_lo> == <code_hi>
+ % 0: prefix_len for 1-byte code
+ % 1: prefix_len for N-byte code
+ dup length 1 eq { 0 } { 1 } ifelse
+ } { % <code_lo> != <code_hi>
+ % calculate prefix_len for *-byte range
+ 0 % initial value for N
+ { % <cid_base> <code_lo> <code_hi> (code_len-1) N
+ dup 2 index le { exit } if
+ 2 index 1 index get % N-th byte of code_lo
+ 2 index 2 index get % N-th byte of code_hi
+ eq { 1 add } { exit } ifelse
+ } loop
+ } ifelse
+ % cid_base code_lo code_hi prefix_len
+
+ % Althogh Adobe CPSI with native CID/CMap support accept
+ % multi-dimensional range specification in notdef & cidrange
+ % (and CID is calculated as relative position in multi-dimensional
+ % range), but older CPSI & ATM cannot handle it.
+ %
+ % GS accepts such specification, but it's recommended to keep
+ % from using this feature for notdef & cidrange.
+ % Following is a disabler of this feature.
+ % -------------------------------------------------------------
+ % counttomark 1 add index % get map#
+ % 0 ne { % if not codespacerange
+ % 1 index length % get code length
+ % 1 index % get prefix length
+ % sub % calculate key length
+ % 1 gt { % if (key_len > 1),
+ % (.endmapranges error) = flush
+ % (multi-dimensional range specification is used out of codespacerange)
+ % = flush
+ % (/) =only
+ % CMapName CMapName length string cvs =only
+ % (: <) =only
+ % 2 index (%stdout) (w) file exch writehexstring
+ % (> <) =only
+ % 1 index (%stdout) (w) file exch writehexstring
+ % (>\n) =only flush
+ % quit
+ % } if
+ % } if
+ % -------------------------------------------------------------
+
+ 1 index exch 0 exch getinterval
+ % cid_base code_lo code_hi prefix
+ dup length 3 index length exch sub
+ % cid_base code_lo code_hi prefix range_len
+ dup 255 gt {
+ (too long coderange specification for current GS\n) print stop
+ } if
+ <00 01 00 02> 4 string copy % create initialized param
+ dup 0 4 -1 roll put % put range_len into param
+
+ % get key_hi
+ 3 -1 roll dup length 3 index length dup 3 1 roll sub getinterval
+
+ % get key_lo
+ 4 -1 roll dup length 4 index length dup 3 1 roll sub getinterval
+
+ % make "keys" (concatenated key_lo + key_hi)
+ exch concatstrings
+
+ %
+ 4 -1 roll
+ .endmapvalue
+
% See if we can merge with the previous value.
% The prefix, params, and font index must match.
- % Stack: prefix params keys value fontindex
- 4 index 10 index eq % prefix
- 4 index 10 index eq and % params
- 1 index 7 index eq and % fontindex
+ % prefix params keys value fontindex
+ counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item)
+ 4 index 10 index eq % compare prefix
+ 4 index 10 index eq and % compare params
+ 1 index 7 index eq and % compare fontindex
{
+ DEBUG { (merge!\n) print } if
pop 4 2 roll pop pop
- % Stack: prefix params keys value fontindex keys2 value2
+ % prefix params keys value fontindex keys2 value2
5 -1 roll 3 -1 roll concatstrings
- % Stack: prefix params value fontindex value2 keys'
+ % prefix params value fontindex value2 keys'
4 -1 roll 3 -1 roll concatstrings
- % Stack: prefix params fontindex keys' values'
+ % prefix params fontindex keys' values'
3 -1 roll
} if
- } ifelse
- } ifelse
+ } if % end of 2 (or more) ranges
} repeat
counttomark 2 add -1 roll .appendmap
} bind def
More information about the gs-devel
mailing list