Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/psi/zcid.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* CMap and CID-keyed font services */
18
#include "ghost.h"
19
#include "ierrors.h"
20
#include "gxcid.h"
21
#include "icid.h"   /* for checking prototype */
22
#include "idict.h"
23
#include "idparam.h"
24
#include "store.h"
25
#include "oper.h"
26
#include "gserrors.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
1
{
32
1
    ref *pregistry;
33
1
    ref *pordering;
34
1
    int code;
35
36
1
    if (!r_has_type(prcidsi, t_dictionary))
37
0
        return_error(gs_error_typecheck);
38
1
    if (dict_find_string(prcidsi, "Registry", &pregistry) <= 0 ||
39
1
        dict_find_string(prcidsi, "Ordering", &pordering) <= 0
40
1
        )
41
0
        return_error(gs_error_rangecheck);
42
1
    check_read_type_only(*pregistry, t_string);
43
1
    check_read_type_only(*pordering, t_string);
44
1
    pcidsi->Registry.data = pregistry->value.const_bytes;
45
1
    pcidsi->Registry.size = r_size(pregistry);
46
1
    pcidsi->Ordering.data = pordering->value.const_bytes;
47
1
    pcidsi->Ordering.size = r_size(pordering);
48
1
    code = dict_int_param(prcidsi, "Supplement", 0, max_int, -1,
49
1
                          &pcidsi->Supplement);
50
1
    return (code < 0 ? code : 0);
51
1
}
52
53
/* Convert a CID into TT char code or to TT glyph index. */
54
static 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
0
{   ref *DecodingArray, char_code, char_code1, ih, *glyph_index;
58
0
    bool found = false;
59
0
    int i = nCID % 256, n;
60
61
0
    make_int(&ih, nCID / 256);
62
0
    if (dict_find(Decoding, &ih, &DecodingArray) <= 0 ||
63
0
            !r_has_type(DecodingArray, t_array) ||
64
0
            array_get(mem, DecodingArray, i, &char_code) < 0)
65
0
        return false;
66
0
    if (r_has_type(&char_code, t_integer))
67
0
        n = 1;
68
0
    else if (r_has_type(&char_code, t_array)) {
69
0
        DecodingArray = &char_code;
70
0
        i = 0;
71
0
        n = r_size(DecodingArray);
72
0
    } else
73
0
        return false; /* Must not happen. */
74
0
    for (;n--; i++) {
75
0
        int code;
76
77
0
        if (array_get(mem, DecodingArray, i, &char_code1) < 0 ||
78
0
            !r_has_type(&char_code1, t_integer))
79
0
            return false; /* Must not happen. */
80
0
        code = dict_find(TT_cmap, &char_code1, &glyph_index);
81
0
        if (code > 0 && r_has_type(glyph_index, t_integer)) {
82
0
            *c = glyph_index->value.intval;
83
0
            found = true;
84
0
            if (*c != 0)
85
0
                return true;
86
0
        }
87
0
    }
88
0
    return found;
89
0
}
90
91
/* Convert a CID into a TT char code or into a TT glyph index, using SubstNWP. */
92
/* Returns 1 if a glyph presents, 0 if not, <0 if error. */
93
int
94
cid_to_TT_charcode(const gs_memory_t *mem,
95
                   const ref *Decoding, const ref *TT_cmap, const ref *SubstNWP,
96
                   uint nCID, uint *c, ref *src_type, ref *dst_type)
97
0
{
98
0
    int SubstNWP_length = r_size(SubstNWP), i, code;
99
100
0
    if (TT_char_code_from_CID_no_subst(mem, Decoding, TT_cmap, nCID, c)) {
101
0
        make_null(src_type);
102
        /* Leaving dst_type uninitialized. */
103
0
        return 1;
104
0
    }
105
0
    for (i = 0; i < SubstNWP_length; i += 5) {
106
0
        ref rb, re, rs;
107
0
        int nb, ne, ns;
108
109
0
        if ((code = array_get(mem, SubstNWP, i + 1, &rb)) < 0)
110
0
            return code;
111
0
        if ((code = array_get(mem, SubstNWP, i + 2, &re)) < 0)
112
0
            return code;
113
0
        if ((code = array_get(mem, SubstNWP, i + 3, &rs)) < 0)
114
0
            return code;
115
0
        nb = rb.value.intval;
116
0
        ne = re.value.intval;
117
0
        ns = rs.value.intval;
118
0
        if (nCID >= nb && nCID <= ne)
119
0
            if (TT_char_code_from_CID_no_subst(mem, Decoding, TT_cmap, ns + (nCID - nb), c)) {
120
0
                if ((code = array_get(mem, SubstNWP, i + 0, src_type)) < 0)
121
0
                    return code;
122
0
                if ((code = array_get(mem, SubstNWP, i + 4, dst_type)) < 0)
123
0
                    return code;
124
0
                return 1;
125
0
            }
126
0
        if (nCID >= ns && nCID <= ns + (ne - nb))
127
0
            if (TT_char_code_from_CID_no_subst(mem, Decoding, TT_cmap, nb + (nCID - ns), c)) {
128
0
                if ((code = array_get(mem, SubstNWP, i + 0, dst_type)) < 0)
129
0
                    return code;
130
0
                if ((code = array_get(mem, SubstNWP, i + 4, src_type)) < 0)
131
0
                    return code;
132
0
                return 1;
133
0
            }
134
0
    }
135
0
    *c = 0;
136
0
    return 0;
137
0
}
138
139
/* Set a CIDMap element. */
140
static int
141
set_CIDMap_element(const gs_memory_t *mem, ref *CIDMap, uint cid, uint glyph_index)
142
0
{   /* Assuming the CIDMap is already type-checked. */
143
    /* Assuming GDBytes == 2. */
144
0
    uint offset = cid * 2;
145
0
    uint count = r_size(CIDMap), size, i;
146
0
    ref s;
147
0
    uchar *c;
148
149
0
    if (glyph_index >= 65536 || cid > max_uint / 2)
150
0
        return_error(gs_error_rangecheck); /* Can't store with GDBytes == 2. */
151
0
    for (i = 0; i < count; i++) {
152
0
        array_get(mem, CIDMap, i, &s);
153
0
        size = r_size(&s) & ~1;
154
0
        if (offset < size) {
155
0
            c = s.value.bytes + offset;
156
0
            c[0] = (uchar)(glyph_index >> 8);
157
0
            c[1] = (uchar)(glyph_index & 255);
158
0
            break;
159
0
        }
160
0
        offset -= size;
161
0
    }
162
    /* We ignore the substitution if it goes out the CIDMap range.
163
       It must not happen, except for empty Decoding elements */
164
0
    return 0;
165
0
}
166
167
/* Create a CIDMap from a True Type cmap array, Decoding and SubstNWP. */
168
int
169
cid_fill_CIDMap(const gs_memory_t *mem,
170
                const ref *Decoding, const ref *TT_cmap, const ref *SubstNWP, int GDBytes,
171
                ref *CIDMap)
172
0
{   int dict_enum;
173
0
    ref el[2];
174
0
    int count, i;
175
176
0
    if (GDBytes != 2)
177
0
        return_error(gs_error_unregistered); /* Unimplemented. */
178
0
    if (r_type(CIDMap) != t_array)
179
0
        return_error(gs_error_unregistered); /* Unimplemented. It could be a single string. */
180
0
    count = r_size(CIDMap);
181
    /* Checking the CIDMap structure correctness : */
182
0
    for (i = 0; i < count; i++) {
183
0
        ref s;
184
0
        int code = array_get(mem, CIDMap, i, &s);
185
186
0
        if (code < 0)
187
0
            return code;
188
0
        check_type(s, t_string); /* fixme : optimize with moving to TT_char_code_from_CID. */
189
0
    }
190
    /* Compute the CIDMap : */
191
0
    dict_enum = dict_first(Decoding);
192
0
    for (;;) {
193
0
        int index, count, i;
194
195
0
        if ((dict_enum = dict_next(Decoding, dict_enum, el)) == -1)
196
0
            break;
197
0
        if (!r_has_type(&el[0], t_integer))
198
0
            continue;
199
0
        if (!r_has_type(&el[1], t_array))
200
0
            return_error(gs_error_typecheck);
201
0
        index = el[0].value.intval;
202
0
        count = r_size(&el[1]);
203
0
        for (i = 0; i < count; i++) {
204
0
            uint cid = index * 256 + i, glyph_index;
205
0
            ref src_type, dst_type;
206
0
            int code = cid_to_TT_charcode(mem, Decoding, TT_cmap, SubstNWP,
207
0
                                cid, &glyph_index, &src_type, &dst_type);
208
209
0
            if (code < 0)
210
0
                return code;
211
0
            if (code > 0) {
212
0
                code = set_CIDMap_element(mem, CIDMap, cid, glyph_index);
213
0
                if (code < 0)
214
0
                    return code;
215
0
            }
216
0
        }
217
0
    }
218
0
    return 0;
219
0
}
220
221
int
222
cid_fill_Identity_CIDMap(const gs_memory_t *mem,
223
                ref *CIDMap)
224
0
{   int count, i;
225
226
0
    count = r_size(CIDMap);
227
0
    if (count != 3)
228
0
        return_error(gs_error_rangecheck);
229
230
    /* Checking the CIDMap structure correctness : */
231
0
    for (i = 0; i < count; i++) {
232
0
        ref s;
233
0
        int code = array_get(mem, CIDMap, i, &s);
234
235
0
        if (code < 0)
236
0
            return code;
237
0
        check_type(s, t_string); /* fixme : optimize with moving to TT_char_code_from_CID. */
238
0
    }
239
0
    for (i=0; i < 255*255; i++) {
240
0
        int code;
241
242
0
        code = set_CIDMap_element(mem, CIDMap, i, i);
243
0
        if (code < 0)
244
0
            return code;
245
0
    }
246
0
    return 0;
247
0
}