2 |
- |
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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 |
}
|