1 /* Copyright (C) 2000 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: zcid.c,v 1.9 2004/08/04 19:36:13 stefan Exp $ */
18 /* CMap and CID-keyed font services */
19 #include "ghost.h"
20 #include "ierrors.h"
21 #include "gxcid.h"
22 #include "icid.h" /* for checking prototype */
23 #include "idict.h"
24 #include "idparam.h"
25 #include "store.h"
26 #include "oper.h"
27
28 /* Get the information from a CIDSystemInfo dictionary. */
29 int
cid_system_info_param(gs_cid_system_info_t * pcidsi,const ref * prcidsi)30 cid_system_info_param(gs_cid_system_info_t *pcidsi, const ref *prcidsi)
31 {
32 ref *pregistry;
33 ref *pordering;
34 int code;
35
36 if (!r_has_type(prcidsi, t_dictionary))
37 return_error(e_typecheck);
38 if (dict_find_string(prcidsi, "Registry", &pregistry) <= 0 ||
39 dict_find_string(prcidsi, "Ordering", &pordering) <= 0
40 )
41 return_error(e_rangecheck);
42 check_read_type_only(*pregistry, t_string);
43 check_read_type_only(*pordering, t_string);
44 pcidsi->Registry.data = pregistry->value.const_bytes;
45 pcidsi->Registry.size = r_size(pregistry);
46 pcidsi->Ordering.data = pordering->value.const_bytes;
47 pcidsi->Ordering.size = r_size(pordering);
48 code = dict_int_param(prcidsi, "Supplement", 0, max_int, -1,
49 &pcidsi->Supplement);
50 return (code < 0 ? code : 0);
51 }
52
53 /* Convert a CID into TT char code or to TT glyph index. */
54 private bool
TT_char_code_from_CID_no_subst(const gs_memory_t * mem,const ref * Decoding,const ref * TT_cmap,uint nCID,uint * c)55 TT_char_code_from_CID_no_subst(const gs_memory_t *mem,
56 const ref *Decoding, const ref *TT_cmap, uint nCID, uint *c)
57 { ref *DecodingArray, char_code, ih, glyph_index;
58
59 make_int(&ih, nCID / 256);
60 if (dict_find(Decoding, &ih, &DecodingArray) <= 0 ||
61 !r_has_type(DecodingArray, t_array) ||
62 array_get(mem, DecodingArray, nCID % 256, &char_code) < 0 ||
63 !r_has_type(&char_code, t_integer)) {
64 /* fixme : Generally, a single char_code can be insufficient.
65 It could be an array. Fix lib/gs_ciddc.ps as well. */
66 return false;
67 }
68 if (TT_cmap == NULL) {
69 *c = char_code.value.intval;
70 return true;
71 }
72 if (array_get(mem, TT_cmap, char_code.value.intval, &glyph_index) < 0 ||
73 !r_has_type(&glyph_index, t_integer))
74 return false;
75 *c = glyph_index.value.intval;
76 return true;
77 }
78
79 /* Convert a CID into a TT char code or into a TT glyph index, using SubstNWP. */
80 /* Returns 1 if a glyph presents, 0 if not, <0 if error. */
81 int
cid_to_TT_charcode(const gs_memory_t * mem,const ref * Decoding,const ref * TT_cmap,const ref * SubstNWP,uint nCID,uint * c,ref * src_type,ref * dst_type)82 cid_to_TT_charcode(const gs_memory_t *mem,
83 const ref *Decoding, const ref *TT_cmap, const ref *SubstNWP,
84 uint nCID, uint *c, ref *src_type, ref *dst_type)
85 {
86 int SubstNWP_length = r_size(SubstNWP), i, code;
87
88 if (TT_char_code_from_CID_no_subst(mem, Decoding, TT_cmap, nCID, c)) {
89 make_null(src_type);
90 /* Leaving dst_type uninitialized. */
91 return 1;
92 }
93 for (i = 0; i < SubstNWP_length; i += 5) {
94 ref rb, re, rs;
95 int nb, ne, ns;
96
97 if ((code = array_get(mem, SubstNWP, i + 1, &rb)) < 0)
98 return code;
99 if ((code = array_get(mem, SubstNWP, i + 2, &re)) < 0)
100 return code;
101 if ((code = array_get(mem, SubstNWP, i + 3, &rs)) < 0)
102 return code;
103 nb = rb.value.intval;
104 ne = re.value.intval;
105 ns = rs.value.intval;
106 if (nCID >= nb && nCID <= ne)
107 if (TT_char_code_from_CID_no_subst(mem, Decoding, TT_cmap, ns + (nCID - nb), c)) {
108 if ((code = array_get(mem, SubstNWP, i + 0, src_type)) < 0)
109 return code;
110 if ((code = array_get(mem, SubstNWP, i + 4, dst_type)) < 0)
111 return code;
112 return 1;
113 }
114 if (nCID >= ns && nCID <= ns + (ne - nb))
115 if (TT_char_code_from_CID_no_subst(mem, Decoding, TT_cmap, nb + (nCID - ns), c)) {
116 if ((code = array_get(mem, SubstNWP, i + 0, dst_type)) < 0)
117 return code;
118 if ((code = array_get(mem, SubstNWP, i + 4, src_type)) < 0)
119 return code;
120 return 1;
121 }
122 }
123 *c = 0;
124 return 0;
125 }
126
127 /* Set a CIDMap element. */
128 private int
set_CIDMap_element(const gs_memory_t * mem,ref * CIDMap,uint cid,uint glyph_index)129 set_CIDMap_element(const gs_memory_t *mem, ref *CIDMap, uint cid, uint glyph_index)
130 { /* Assuming the CIDMap is already type-checked. */
131 /* Assuming GDBytes == 2. */
132 int offset = cid * 2;
133 int count = r_size(CIDMap), size, i;
134 ref s;
135 uchar *c;
136
137 if (glyph_index >= 65536)
138 return_error(e_rangecheck); /* Can't store with GDBytes == 2. */
139 for (i = 0; i < count; i++) {
140 array_get(mem, CIDMap, i, &s);
141 size = r_size(&s) & ~1;
142 if (offset < size) {
143 c = s.value.bytes + offset;
144 c[0] = (uchar)(glyph_index >> 8);
145 c[1] = (uchar)(glyph_index & 255);
146 break;
147 }
148 offset -= size;
149 }
150 /* We ignore the substitution if it goes out the CIDMap range.
151 It must not happen, except for empty Decoding elements */
152 return 0;
153 }
154
155 /* Create a CIDMap from a True Type cmap array, Decoding and SubstNWP. */
156 int
cid_fill_CIDMap(const gs_memory_t * mem,const ref * Decoding,const ref * TT_cmap,const ref * SubstNWP,int GDBytes,ref * CIDMap)157 cid_fill_CIDMap(const gs_memory_t *mem,
158 const ref *Decoding, const ref *TT_cmap, const ref *SubstNWP, int GDBytes,
159 ref *CIDMap)
160 { int dict_enum;
161 ref el[2];
162 int count, i;
163
164 if (GDBytes != 2)
165 return_error(e_unregistered); /* Unimplemented. */
166 if (r_type(CIDMap) != t_array)
167 return_error(e_unregistered); /* Unimplemented. It could be a single string. */
168 count = r_size(CIDMap);
169 /* Checking the CIDMap structure correctness : */
170 for (i = 0; i < count; i++) {
171 ref s;
172 int code = array_get(mem, CIDMap, i, &s);
173
174 if (code < 0)
175 return code;
176 check_type(s, t_string); /* fixme : optimize with moving to TT_char_code_from_CID. */
177 }
178 /* Compute the CIDMap : */
179 dict_enum = dict_first(Decoding);
180 for (;;) {
181 int index, count, i;
182
183 if ((dict_enum = dict_next(Decoding, dict_enum, el)) == -1)
184 break;
185 if (!r_has_type(&el[0], t_integer))
186 continue;
187 if (!r_has_type(&el[1], t_array))
188 return_error(e_typecheck);
189 index = el[0].value.intval;
190 count = r_size(&el[1]);
191 for (i = 0; i < count; i++) {
192 uint cid = index * 256 + i, glyph_index;
193 ref src_type, dst_type;
194 int code = cid_to_TT_charcode(mem, Decoding, TT_cmap, SubstNWP,
195 cid, &glyph_index, &src_type, &dst_type);
196
197 if (code < 0)
198 return code;
199 if (code > 0) {
200 code = set_CIDMap_element(mem, CIDMap, cid, glyph_index);
201 if (code < 0)
202 return code;
203 }
204 }
205 }
206 return 0;
207 }
208