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