Coverage Report

Created: 2026-07-24 07:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pcl/pcl/pgfont.c
Line
Count
Source
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
/* pgfont.c */
18
/* HP-GL/2 stick and arc font */
19
#include "math_.h"
20
#include "gstypes.h"
21
#include "gsccode.h"
22
#include "gsmemory.h"           /* for gsstate.h */
23
#include "gsstate.h"            /* for gscoord.h, gspath.h */
24
#include "gsmatrix.h"
25
#include "gscoord.h"
26
#include "gspaint.h"
27
#include "gspath.h"
28
#include "gxfixed.h"            /* for gxchar.h */
29
#include "gxchar.h"
30
#include "gxfarith.h"
31
#include "gxfont.h"
32
#include "plfont.h"
33
#include "pgfdata.h"
34
#include "pgfont.h"
35
36
/* The client always asks for a Unicode indexed chr.
37
 * The stick/arc fonts themselves use Roman-8 (8U) indexing.
38
 */
39
extern const pl_symbol_map_t map_8U_unicode;
40
41
static gs_glyph
42
hpgl_stick_arc_encode_char(gs_font * pfont, gs_char chr,
43
                           gs_glyph_space_t not_used)
44
760k
{
45
760k
    int i;
46
47
    /* reverse map unicode back to roman 8 */
48
60.3M
    for (i = 0; i < countof(map_8U_unicode.codes); i++) {
49
60.3M
        if (chr == map_8U_unicode.codes[i])
50
760k
            return (gs_glyph) i;
51
60.3M
    }
52
0
    return (gs_glyph) 0xffff;
53
760k
}
54
55
/* The stick font is fixed-pitch.
56
 */
57
static int
58
hpgl_stick_char_width(const pl_font_t * plfont, const void *pgs,
59
                      gs_char uni_code, gs_point * pwidth)
60
228k
{
61
    /* first map unicode to roman-8 */
62
228k
    gs_glyph g = hpgl_stick_arc_encode_char(NULL, uni_code, 0);
63
64
    /* NB need an interface function call to verify the character exists */
65
228k
    if ((g >= 0x20) && (g <= 0xff))
66
220k
        pwidth->x = hpgl_stick_arc_width(uni_code, HPGL_STICK_FONT);
67
8.08k
    else
68
        /* doesn't exist */
69
8.08k
        return 1;
70
220k
    return 0;
71
228k
}
72
73
static int
74
hpgl_stick_char_metrics(const pl_font_t * plfont, const void *pgs,
75
                        gs_char uni_code, float metrics[4])
76
228k
{
77
228k
    gs_point width;
78
79
    /* never a vertical substitute */
80
228k
    metrics[1] = metrics[3] = 0;
81
    /* no lsb */
82
228k
    metrics[0] = 0;
83
    /* just get the width */
84
228k
    if ((hpgl_stick_char_width(plfont, pgs, uni_code, &width)) == 1)
85
        /* doesn't exist */
86
8.08k
        return 1;
87
220k
    metrics[2] = width.x;
88
220k
    return 0;
89
228k
}
90
91
/* The arc font is proportionally spaced. */
92
static int
93
hpgl_arc_char_width(const pl_font_t * plfont, const void *pgs,
94
                    gs_char uni_code, gs_point * pwidth)
95
190k
{
96
    /* first map uni_code to roman-8 */
97
190k
    gs_glyph g = hpgl_stick_arc_encode_char(NULL, uni_code, 0);
98
99
    /* NB need an interface function call to verify the character exists */
100
190k
    if ((g >= 0x20) && (g <= 0xff)) {
101
135k
        pwidth->x = hpgl_stick_arc_width(uni_code, HPGL_ARC_FONT)
102
135k
            / 1024.0            /* convert to ratio of cell size to be multiplied by point size */
103
135k
            * 0.667;            /* TRM 23-18 cell is 2/3 of point size */
104
135k
    } else
105
        /* doesn't exist */
106
55.0k
        return 1;
107
135k
    return 0;
108
190k
}
109
110
static int
111
hpgl_arc_char_metrics(const pl_font_t * plfont, const void *pgs,
112
                      gs_char uni_code, float metrics[4])
113
138k
{
114
138k
    gs_point width;
115
116
    /* never a vertical substitute */
117
138k
    metrics[1] = metrics[3] = 0;
118
    /* no lsb */
119
138k
    metrics[0] = 0;
120
    /* just get the width */
121
138k
    if ((hpgl_arc_char_width(plfont, pgs, uni_code, &width)) == 1)
122
        /* doesn't exist */
123
25.6k
        return 1;
124
113k
    metrics[2] = width.x;
125
113k
    return 0;
126
138k
}
127
128
static int
129
hpgl_dl_char_width(const pl_font_t * plfont, const void *pgs,
130
                   gs_char uni_code, gs_point * pwidth)
131
0
{
132
    /* just the width of the cell */
133
0
    pwidth->x = 1024;
134
0
    pwidth->y = 0;
135
0
    return 0;
136
0
}
137
138
static int
139
hpgl_dl_char_metrics(const pl_font_t * plfont, const void *pgs,
140
                     gs_char uni_code, float metrics[4])
141
0
{
142
    /* never a vertical substitute */
143
0
    metrics[1] = metrics[3] = 0;
144
    /* no lsb */
145
0
    metrics[0] = 0;
146
0
    metrics[2] = 1024;
147
0
    return 0;
148
0
}
149
150
/* Add a symbol to the path. */
151
static int
152
hpgl_stick_arc_build_char(gs_show_enum * penum, gs_gstate * pgs,
153
                          gs_font * pfont, gs_glyph uni_code,
154
                          hpgl_font_type_t font_type)
155
341k
{
156
341k
    int width;
157
341k
    gs_matrix save_ctm;
158
341k
    int code;
159
160
    /* we assert the font is present at this point */
161
341k
    width = hpgl_stick_arc_width(uni_code, font_type);
162
163
341k
    code = gs_setcharwidth(penum, pgs, width / 1024.0 * 0.667, 0.0);
164
341k
    if (code < 0)
165
0
        return code;
166
341k
    gs_currentmatrix(pgs, &save_ctm);
167
341k
    gs_scale(pgs, 1.0 / 1024.0 * .667, 1.0 / 1024.0 * .667);
168
341k
    code = gs_moveto(pgs, 0.0, 0.0);
169
341k
    if (code < 0)
170
0
        return code;
171
341k
    code =
172
341k
        hpgl_stick_arc_segments(pfont->memory, (void *)pgs, uni_code,
173
341k
                                font_type);
174
341k
    if (code < 0)
175
0
        return code;
176
341k
    gs_setdefaultmatrix(pgs, NULL);
177
341k
    gs_initmatrix(pgs);
178
    /* Set predictable join and cap styles. */
179
341k
    code = gs_setlinejoin(pgs, gs_join_round);
180
341k
    if (code < 0)
181
0
        return code;
182
341k
    code = gs_setmiterlimit(pgs, 2.61);        /* start beveling at 45 degrees */
183
341k
    if (code < 0)
184
0
        return code;
185
341k
    code = gs_setlinecap(pgs, gs_cap_round);
186
341k
    if (code < 0)
187
0
        return code;
188
341k
    {
189
341k
        float pattern[1];
190
191
341k
        code = gs_setdash(pgs, pattern, 0, 0);
192
341k
        if (code < 0)
193
0
            return code;
194
341k
    }
195
341k
    code = gs_stroke(pgs);
196
341k
    if (code < 0)
197
0
        return code;
198
341k
    gs_setmatrix(pgs, &save_ctm);
199
341k
    return 0;
200
341k
}
201
202
static int
203
hpgl_stick_build_char(gs_show_enum * penum, gs_gstate * pgs, gs_font * pfont,
204
                      gs_char ignore_chr, gs_glyph uni_code)
205
228k
{
206
228k
    return hpgl_stick_arc_build_char(penum, pgs, pfont, uni_code,
207
228k
                                     HPGL_STICK_FONT);
208
228k
}
209
static int
210
hpgl_arc_build_char(gs_show_enum * penum, gs_gstate * pgs, gs_font * pfont,
211
                    gs_char ignore_chr, gs_glyph uni_code)
212
112k
{
213
112k
    return hpgl_stick_arc_build_char(penum, pgs, pfont, uni_code,
214
112k
                                     HPGL_ARC_FONT);
215
216
112k
}
217
218
/* Fill in stick/arc font boilerplate. */
219
static void
220
hpgl_fill_in_stick_arc_font(gs_font_base * pfont, long unique_id)
221
61.3k
{                               /* The way the code is written requires FontMatrix = identity. */
222
61.3k
    gs_make_identity(&pfont->FontMatrix);
223
61.3k
    pfont->FontType = ft_GL2_stick_user_defined;
224
61.3k
    pfont->PaintType = 1;       /* stroked fonts */
225
61.3k
    pfont->BitmapWidths = false;
226
61.3k
    pfont->ExactSize = fbit_use_outlines;
227
61.3k
    pfont->InBetweenSize = fbit_use_outlines;
228
61.3k
    pfont->TransformedChar = fbit_use_outlines;
229
61.3k
    pfont->procs.encode_char = hpgl_stick_arc_encode_char;      /* FIX ME (void *) */
230
    /* p.y of the FontBBox is a guess, because of descenders. */
231
    /* Because of descenders, we have no real idea what the */
232
    /* FontBBox should be. */
233
61.3k
    pfont->FontBBox.p.x = 0;
234
61.3k
    pfont->FontBBox.p.y = -0.333;
235
61.3k
    pfont->FontBBox.q.x = 0.667;
236
61.3k
    pfont->FontBBox.q.y = 0.667;
237
61.3k
    uid_set_UniqueID(&pfont->UID, unique_id);
238
61.3k
    pfont->encoding_index = 1;          /****** WRONG ******/
239
61.3k
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
240
61.3k
}
241
242
static int
243
hpgl_531_build_char(gs_show_enum * penum, gs_gstate * pgs, gs_font * pfont,
244
                    gs_char ignore_chr, gs_glyph ccode)
245
0
{
246
0
    gs_matrix save_ctm;
247
0
    int code;
248
0
    pcl_id_t ckey;
249
0
    hpgl_dl_cdata_t *cdata;
250
0
    gs_point width;
251
0
    pl_font_t *plfont = (pl_font_t *) pfont->client_data;
252
0
    pl_dict_t *dl_dict = (pl_dict_t *) plfont->header;
253
254
0
    id_set_value(ckey, (ushort) ccode);
255
0
    if (!pl_dict_find(dl_dict, id_key(ckey), 2, (void **)&cdata))
256
        /* this should be a failed assertion */
257
0
        return -1;
258
259
    /* we assert the font is present at this point */
260
0
    if (((plfont)->char_width) (plfont, pgs, ccode, &width) < 0)
261
0
        return -1;
262
263
    /* This certainly is wrong but the advance is always explicit */
264
0
    code = gs_setcharwidth(penum, pgs, width.x / 1024.0 * 0.667, 0.0);
265
0
    if (code < 0)
266
0
        return code;
267
0
    gs_currentmatrix(pgs, &save_ctm);
268
269
    /* the DL fonts are defined on a 32x32 grid */
270
0
    gs_scale(pgs, 1.0 / 32.0, 1.0 / 32.0);
271
272
0
    code = gs_moveto(pgs, 0.0, 0.0);
273
0
    if (code < 0)
274
0
        return code;
275
0
    code = hpgl_531_segments(pfont->memory, (void *)pgs, cdata);
276
0
    if (code < 0)
277
0
        return code;
278
0
    gs_setdefaultmatrix(pgs, NULL);
279
0
    gs_initmatrix(pgs);
280
    /* Set predictable join and cap styles. */
281
0
    code = gs_setlinejoin(pgs, gs_join_round);
282
0
    if (code < 0)
283
0
        return code;
284
0
    code = gs_setmiterlimit(pgs, 2.61);        /* start beveling at 45 degrees */
285
0
    if (code < 0)
286
0
        return code;
287
0
    code = gs_setlinecap(pgs, gs_cap_round);
288
0
    if (code < 0)
289
0
        return code;
290
0
    {
291
0
        float pattern[1];
292
293
0
        code = gs_setdash(pgs, pattern, 0, 0);
294
0
        if (code < 0)
295
0
            return code;
296
0
    }
297
0
    code = gs_stroke(pgs);
298
0
    if (code < 0)
299
0
        return code;
300
0
    gs_setmatrix(pgs, &save_ctm);
301
0
    return 0;
302
0
}
303
304
void
305
hpgl_fill_in_531_font(gs_font_base * pfont, long unique_id)
306
0
{
307
0
    gs_make_identity(&pfont->FontMatrix);
308
    /* we'll just make this look like a stick font to the graphics
309
       library */
310
0
    pfont->FontType = ft_GL2_531;
311
0
    pfont->PaintType = 1;       /* stroked fonts */
312
0
    pfont->BitmapWidths = false;
313
0
    pfont->ExactSize = fbit_use_outlines;
314
0
    pfont->InBetweenSize = fbit_use_outlines;
315
0
    pfont->TransformedChar = fbit_use_outlines;
316
0
    pfont->procs.encode_char = hpgl_stick_arc_encode_char;      /* FIX ME (void *) */
317
    /* p.y of the FontBBox is a guess, because of descenders. */
318
    /* Because of descenders, we have no real idea what the */
319
    /* FontBBox should be. */
320
0
    pfont->FontBBox.p.x = 0;
321
0
    pfont->FontBBox.p.y = -0.333;
322
0
    pfont->FontBBox.q.x = 0.667;
323
0
    pfont->FontBBox.q.y = 0.667;
324
0
    uid_set_UniqueID(&pfont->UID, unique_id);
325
0
    pfont->encoding_index = 1;  /****** WRONG ******/
326
0
    pfont->nearest_encoding_index = 1;  /****** WRONG ******/
327
328
0
#define plfont ((pl_font_t *)pfont->client_data)
329
0
    pfont->procs.build_char = hpgl_531_build_char;      /* FIX ME (void *) */
330
0
    plfont->char_width = hpgl_dl_char_width;
331
0
    plfont->char_metrics = hpgl_dl_char_metrics;
332
0
#undef plfont
333
0
}
334
335
void
336
hpgl_fill_in_stick_font(gs_font_base * pfont, long unique_id)
337
50.2k
{
338
50.2k
    hpgl_fill_in_stick_arc_font(pfont, unique_id);
339
100k
#define plfont ((pl_font_t *)pfont->client_data)
340
50.2k
    pfont->procs.build_char = hpgl_stick_build_char;    /* FIX ME (void *) */
341
50.2k
    plfont->char_width = hpgl_stick_char_width;
342
50.2k
    plfont->char_metrics = hpgl_stick_char_metrics;
343
50.2k
#undef plfont
344
50.2k
}
345
void
346
hpgl_fill_in_arc_font(gs_font_base * pfont, long unique_id)
347
11.0k
{
348
11.0k
    hpgl_fill_in_stick_arc_font(pfont, unique_id);
349
22.1k
#define plfont ((pl_font_t *)pfont->client_data)
350
11.0k
    pfont->procs.build_char = hpgl_arc_build_char;      /* FIX ME (void *) */
351
11.0k
    plfont->char_width = hpgl_arc_char_width;
352
11.0k
    plfont->char_metrics = hpgl_arc_char_metrics;
353
11.0k
#undef plfont
354
11.0k
}
355
356
void
357
hpgl_initialize_stick_fonts(hpgl_state_t * pcs)
358
48.9k
{
359
48.9k
    pcs->g.stick_font[0][0].pfont =
360
48.9k
        pcs->g.stick_font[0][1].pfont =
361
48.9k
        pcs->g.stick_font[1][0].pfont = pcs->g.stick_font[1][1].pfont = 0;
362
363
    /* NB most of the pl_font structure is uninitialized! */
364
48.9k
    pcs->g.stick_font[0][0].font_file =
365
48.9k
        pcs->g.stick_font[0][1].font_file =
366
48.9k
        pcs->g.stick_font[1][0].font_file =
367
48.9k
        pcs->g.stick_font[1][1].font_file = 0;
368
369
48.9k
    pcs->g.dl_531_font[0].pfont = pcs->g.dl_531_font[1].pfont = 0;
370
371
48.9k
    pcs->g.dl_531_font[0].font_file = pcs->g.dl_531_font[1].font_file = 0;
372
48.9k
}