Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gxccache.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Fast case character cache routines for Ghostscript library */
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gpcheck.h"
21
#include "gserrors.h"
22
#include "gsstruct.h"
23
#include "gscencs.h"
24
#include "gxfixed.h"
25
#include "gxmatrix.h"
26
#include "gzstate.h"
27
#include "gzpath.h"
28
#include "gxdevice.h"
29
#include "gxdevmem.h"
30
#include "gzcpath.h"
31
#include "gxchar.h"
32
#include "gxfont.h"
33
#include "gxfcache.h"
34
#include "gxxfont.h"
35
#include "gximask.h"
36
#include "gscspace.h"   /* for gsimage.h */
37
#include "gsimage.h"
38
#include "gxhttile.h"
39
#include "gsptype1.h"       /* for gx_dc_is_pattern1_color_with_trans */
40
41
/* Forward references */
42
static byte *compress_alpha_bits(const cached_char *, gs_memory_t *);
43
44
/* Define a scale factor of 1. */
45
static const gs_log2_scale_point scale_log2_1 =
46
{0, 0};
47
48
void
49
gx_compute_char_matrix(const gs_matrix *char_tm, const gs_log2_scale_point *log2_scale,
50
    float *mxx, float *mxy, float *myx, float *myy)
51
9.29M
{
52
9.29M
    int scale_x = 1 << log2_scale->x;
53
9.29M
    int scale_y = 1 << log2_scale->y;
54
55
9.29M
    *mxx = char_tm->xx * scale_x;
56
9.29M
    *mxy = char_tm->xy * scale_x;
57
9.29M
    *myx = char_tm->yx * scale_y;
58
9.29M
    *myy = char_tm->yy * scale_y;
59
9.29M
}
60
61
void
62
gx_compute_ccache_key(gs_font * pfont, const gs_matrix *char_tm,
63
    const gs_log2_scale_point *log2_scale, bool design_grid,
64
    float *mxx, float *mxy, float *myx, float *myy)
65
9.42M
{
66
9.42M
    if (design_grid &&
67
9.42M
            (pfont->FontType == ft_TrueType || pfont->FontType == ft_CID_TrueType)) {
68
        /*
69
         * We need a special face for this case, because the TT interpreter
70
         * can't generate both grid_fitted and non-grid-fitted outlines
71
         * with a same face instance. This happens due to control
72
         * values in 'cvt' must be different.
73
         * Since a single face satisfies all font sizes,
74
         * we use a zero matrix as the cache entry key.
75
         */
76
195k
        *mxx = *mxy = *myx = *myy = 0;
77
195k
    } else
78
9.23M
        gx_compute_char_matrix(char_tm, log2_scale, mxx, mxy, myx, myy);
79
9.42M
}
80
81
/* Look up, and if necessary add, a font/matrix pair in the cache */
82
int
83
gx_lookup_fm_pair(gs_font * pfont, const gs_matrix *char_tm,
84
    const gs_log2_scale_point *log2_scale, bool design_grid, cached_fm_pair **ppair)
85
8.44M
{
86
8.44M
    float mxx, mxy, myx, myy;
87
8.44M
    gs_font *font = pfont;
88
8.44M
    register gs_font_dir *dir = font->dir;
89
8.44M
    register cached_fm_pair *pair = dir->fmcache.mdata + dir->fmcache.used;
90
8.44M
    int count = dir->fmcache.msize;
91
8.44M
    gs_uid uid;
92
93
8.44M
    gx_compute_ccache_key(pfont, char_tm, log2_scale, design_grid,
94
8.44M
                            &mxx, &mxy, &myx, &myy);
95
8.44M
    if (font->FontType == ft_composite || font->PaintType != 0) { /* We can't cache by UID alone. */
96
0
        uid_set_invalid(&uid);
97
8.44M
    } else {
98
8.44M
        uid = ((gs_font_base *) font)->UID;
99
8.44M
        if (uid_is_valid(&uid))
100
17
            font = 0;
101
8.44M
    }
102
164M
    for (;count--; pair = dir->fmcache.mdata + pair->next) {
103
        /* We have either a non-zero font and an invalid UID, */
104
        /* or a zero font and a valid UID. */
105
        /* We have to break up the test */
106
        /* because of a bug in the Zortech compiler. */
107
163M
        if (font != 0) {
108
163M
            if (pair->font != font)
109
2.69M
                continue;
110
163M
        } else {
111
57
            if (!uid_equal(&pair->UID, &uid) ||
112
57
                pair->FontType != pfont->FontType
113
57
                )
114
22
                continue;
115
57
        }
116
160M
        if (pair->mxx == mxx && pair->mxy == mxy &&
117
160M
            pair->myx == myx && pair->myy == myy
118
160M
            && pair->design_grid == design_grid) {
119
7.45M
            int code;
120
121
7.45M
            if (pair->font == 0) {
122
0
                pair->font = pfont;
123
0
                if_debug2m('k', pfont->memory, "[k]updating pair "PRI_INTPTR" with font "PRI_INTPTR"\n",
124
0
                           (intptr_t)pair, (intptr_t)pfont);
125
7.45M
            } else {
126
7.45M
                if_debug2m('k', pfont->memory, "[k]found pair "PRI_INTPTR": font="PRI_INTPTR"\n",
127
7.45M
                           (intptr_t)pair, (intptr_t)pair->font);
128
7.45M
            }
129
7.45M
            code = gx_touch_fm_pair(dir, pair);
130
7.45M
            if (code < 0)
131
0
                return code;
132
7.45M
            code = gx_provide_fm_pair_attributes(dir, pfont, pair,
133
7.45M
                                char_tm, log2_scale, design_grid);
134
7.45M
            if (code < 0)
135
0
                return code;
136
7.45M
            *ppair = pair;
137
7.45M
            return 0;
138
7.45M
        }
139
160M
    }
140
983k
    return gx_add_fm_pair(dir, pfont, &uid, char_tm, log2_scale, design_grid, ppair);
141
8.44M
}
142
143
/* Look up a glyph with the right depth in the cache. */
144
/* Return the cached_char or 0. */
145
cached_char *
146
gx_lookup_cached_char(const gs_font * pfont, const cached_fm_pair * pair,
147
                      gs_glyph glyph, int wmode, int depth,
148
                      gs_fixed_point *subpix_origin)
149
23.0M
{
150
23.0M
    gs_font_dir *dir = pfont->dir;
151
23.0M
    uint chi = chars_head_index(glyph, pair);
152
23.0M
    register cached_char *cc;
153
154
23.0M
    while ((cc = dir->ccache.table[chi & dir->ccache.table_mask]) != 0) {
155
19.9M
        if (cc->code == glyph && cc_pair(cc) == pair &&
156
19.9M
            cc->subpix_origin.x == subpix_origin->x &&
157
19.9M
            cc->subpix_origin.y == subpix_origin->y &&
158
19.9M
            cc->wmode == wmode && cc_depth(cc) == depth
159
19.9M
            ) {
160
19.8M
            if_debug4m('K', pfont->memory,
161
19.8M
                       "[K]found "PRI_INTPTR" (depth=%d) for glyph=0x%lx, wmode=%d\n",
162
19.8M
                       (intptr_t)cc, cc_depth(cc), (ulong)glyph, wmode);
163
19.8M
            return cc;
164
19.8M
        }
165
46.2k
        chi++;
166
46.2k
    }
167
23.0M
    if_debug3m('K', pfont->memory, "[K]not found: glyph=0x%lx, wmode=%d, depth=%d\n",
168
3.17M
              (ulong) glyph, wmode, depth);
169
3.17M
    return 0;
170
23.0M
}
171
172
/* Copy a cached character to the screen. */
173
/* Assume the caller has already done gx_color_load. */
174
/* Return 0 if OK, 1 if we couldn't do the operation but no error */
175
/* should be signalled, or a negative error code. */
176
int
177
gx_image_cached_char(register gs_show_enum * penum, register cached_char * cc)
178
21.7M
{
179
21.7M
    register gs_gstate *pgs = penum->pgs;
180
21.7M
    gx_device_color *pdevc = gs_currentdevicecolor_inline(pgs);
181
21.7M
    int x, y, w, h, depth;
182
21.7M
    int code;
183
21.7M
    gs_fixed_point pt;
184
21.7M
    gx_device *dev = penum->dev;
185
21.7M
    gx_device *imaging_dev = penum->imaging_dev ? penum->imaging_dev : dev;
186
21.7M
    gx_device *orig_dev = imaging_dev;
187
21.7M
    gx_device_clip cdev;
188
21.7M
    gx_xglyph xg = cc->xglyph;
189
21.7M
    gx_xfont *xf;
190
21.7M
    byte *bits;
191
192
21.7M
  top:code = gx_path_current_point_inline(pgs, &pt);
193
21.7M
    if (code < 0)
194
0
        return code;
195
    /*
196
     * If the character doesn't lie entirely within the inner
197
     * clipping rectangle, we set up an intermediate clipping device.
198
     * Note that if the original device implements fill_mask, we may
199
     * never actually use the clipping device.
200
     */
201
21.7M
    pt.x -= cc->offset.x + cc->subpix_origin.x;
202
21.7M
    x = fixed2int_var_rounded(pt.x) + penum->ftx;
203
21.7M
    pt.y -= cc->offset.y + cc->subpix_origin.y;
204
21.7M
    y = fixed2int_var_rounded(pt.y) + penum->fty;
205
21.7M
    w = cc->width;
206
21.7M
    h = cc->height;
207
#ifdef DEBUG
208
    if (gs_debug_c('K')) {
209
        if (cc_has_bits(cc))
210
            debug_dump_bitmap(penum->memory, cc_bits(cc), cc_raster(cc), h,
211
                              "[K]bits");
212
        else
213
            dmputs(penum->memory, "[K]no bits\n");
214
        dmlprintf3(penum->memory, "[K]copying "PRI_INTPTR", offset=(%g,%g)\n",
215
                   (intptr_t) cc,
216
                   fixed2float(-cc->offset.x),
217
                   fixed2float(-cc->offset.y));
218
        dmlprintf6(penum->memory, "   at (%g,%g)+(%d,%d)->(%d,%d)\n",
219
                   fixed2float(pt.x), fixed2float(pt.y),
220
                   penum->ftx, penum->fty, x, y);
221
    }
222
#endif
223
21.7M
    if ((x < penum->ibox.p.x || x + w > penum->ibox.q.x ||
224
21.7M
         y < penum->ibox.p.y || y + h > penum->ibox.q.y) &&
225
21.7M
        imaging_dev != (gx_device *) & cdev  /* might be 2nd time around */
226
21.7M
        ) {     /* Check for the character falling entirely outside */
227
        /* the clipping region. */
228
4.51M
        gx_clip_path *pcpath;
229
230
4.51M
        if (x >= penum->obox.q.x || x + w <= penum->obox.p.x ||
231
4.51M
            y >= penum->obox.q.y || y + h <= penum->obox.p.y
232
4.51M
            )
233
4.42M
            return 0;    /* nothing to do */
234
97.8k
        code = gx_effective_clip_path(pgs, &pcpath);
235
97.8k
        if (code < 0)
236
0
            return code;
237
97.8k
        gx_make_clip_device_on_stack(&cdev, pcpath, imaging_dev);
238
97.8k
        imaging_dev = (gx_device *) & cdev;
239
97.8k
        if_debug0m('K', penum->memory, "[K](clipping)\n");
240
97.8k
    }
241
17.3M
    code = gx_set_dev_color(pgs);
242
17.3M
    if (code != 0)
243
0
        return code;
244
    /* If an xfont can render this character, use it. */
245
17.3M
    if (xg != gx_no_xglyph && (xf = cc_pair(cc)->xfont) != 0) {
246
0
        int cx = x + fixed2int(cc->offset.x);
247
0
        int cy = y + fixed2int(cc->offset.y);
248
249
        /*
250
         * Note that we prefer a 1-bit xfont implementation over
251
         * a multi-bit cached bitmap.  Eventually we should change
252
         * the xfont interface so it can deliver multi-bit bitmaps,
253
         * or else implement oversampling for xfonts.
254
         */
255
0
        if (gs_color_writes_pure(pgs)) {
256
0
            code = (*xf->common.procs->render_char) (xf, xg,
257
0
                                        imaging_dev, cx, cy,
258
0
                                        pdevc->colors.pure, 0);
259
0
            if_debug8m('K', penum->memory,
260
0
                       "[K]render_char display: xfont="PRI_INTPTR", glyph=0x%lx\n\tdev="PRI_INTPTR"(%s) x,y=%d,%d, color=0x%lx => %d\n",
261
0
                       (intptr_t)xf, (ulong)xg, (intptr_t)imaging_dev,
262
0
                       imaging_dev->dname, cx, cy,
263
0
                       (ulong) pdevc->colors.pure, code);
264
0
            if (code == 0)
265
0
                return_check_interrupt(penum->memory, 0);
266
0
        }
267
        /* Can't render directly.  If we don't have a bitmap yet, */
268
        /* get it from the xfont now. */
269
0
        if (!cc_has_bits(cc)) {
270
0
            gx_device_memory mdev;
271
272
0
            gs_make_mem_mono_device(&mdev, dev->memory, imaging_dev);
273
0
            gx_open_cache_device(&mdev, cc);
274
0
            code = (*xf->common.procs->render_char) (xf, xg,
275
0
                                       (gx_device *) & mdev, cx - x, cy - y,
276
0
                                                     (gx_color_index) 1, 1);
277
0
            if_debug7m('K', penum->memory,
278
0
                       "[K]render_char to bits: xfont="PRI_INTPTR", glyph=0x%lx\n\tdev="PRI_INTPTR"(%s) x,y=%d,%d => %d\n",
279
0
                      (intptr_t)xf, (ulong) xg, (intptr_t)&mdev,
280
0
                      mdev.dname, cx - x, cy - y, code);
281
0
            if (code != 0)
282
0
                return_check_interrupt(penum->memory, 1);
283
0
            gx_add_char_bits(cc_pair(cc)->font->dir,
284
0
                             cc, &scale_log2_1);
285
            /* gx_add_char_bits may change width, height, */
286
            /* raster, and/or offset.  It's easiest to */
287
            /* start over from the top.  Clear xg so that */
288
            /* we don't waste time trying render_char again. */
289
0
            xg = gx_no_xglyph;
290
0
            goto top;
291
0
        }
292
0
    }
293
    /*
294
     * No xfont.  Render from the cached bits.  If the cached bits
295
     * have more than 1 bit of alpha, and the color isn't pure or
296
     * the copy_alpha operation fails, construct a single-bit mask
297
     * by taking the high-order alpha bit.
298
     */
299
17.3M
    bits = cc_bits(cc);
300
    /* With 4x2 scale, depth == 3.
301
     * An example is -dTextAlphaBits=4 comparefiles/fonttest.pdf .
302
     * We need to map 4 bitmap bits to 2 alpha bits.
303
     */
304
17.3M
    depth = (cc_depth(cc) == 3 ? 2 : cc_depth(cc));
305
17.3M
    if ((dev_proc(orig_dev, fill_mask) != gx_default_fill_mask ||
306
17.3M
        !lop_no_S_is_T(pgs->log_op))) {
307
308
16.2M
        gx_clip_path *pcpath;
309
310
16.2M
        penum->use_wxy_float = false;
311
16.2M
        penum->wxy_float.x = penum->wxy_float.y = 0.0;
312
16.2M
        penum->wxy = cc->wxy;
313
314
16.2M
        code = gx_effective_clip_path(pgs, &pcpath);
315
16.2M
        if (code >= 0) {
316
16.2M
            code = gx_image_fill_masked
317
16.2M
                (orig_dev, bits, 0, cc_raster(cc), cc->id,
318
16.2M
                 x, y, w, h, pdevc, depth, pgs->log_op, pcpath);
319
16.2M
            if (code >= 0)
320
16.2M
                goto done;
321
16.2M
        }
322
16.2M
    } else if (gs_color_writes_pure(pgs)) {
323
1.09M
        gx_color_index color = pdevc->colors.pure;
324
325
1.09M
        if (depth > 1) {
326
0
            code = (*dev_proc(imaging_dev, copy_alpha))
327
0
                (imaging_dev, bits, 0, cc_raster(cc), cc->id,
328
0
                 x, y, w, h, color, depth);
329
0
            if (code >= 0)
330
0
                return_check_interrupt(penum->memory, 0);
331
            /* copy_alpha failed, construct a monobit mask. */
332
0
            bits = compress_alpha_bits(cc, penum->memory->non_gc_memory);
333
0
            if (bits == 0)
334
0
                return 1; /* VMerror, but recoverable */
335
0
        }
336
1.09M
        code = (*dev_proc(imaging_dev, copy_mono))
337
1.09M
            (imaging_dev, bits, 0, bitmap_raster(w), gs_no_id,
338
1.09M
             x, y, w, h, gx_no_color_index, color);
339
1.09M
        goto done;
340
1.09M
    }
341
148
    if (depth > 1) {   /* Complex color or fill_mask / copy_alpha failed, */
342
        /* construct a monobit mask. */
343
0
        bits = compress_alpha_bits(cc, penum->memory->non_gc_memory);
344
0
        if (bits == 0)
345
0
            return 1;   /* VMerror, but recoverable */
346
347
148
    } {       /* Use imagemask to render the character. */
348
148
        gs_memory_t *mem = penum->memory->non_gc_memory;
349
148
        gs_image_enum *pie =
350
148
            gs_image_enum_alloc(mem, "image_char(image_enum)");
351
148
        gs_image_t image;
352
148
        int iy;
353
148
        uint used, raster = (bits == cc_bits(cc) ? cc_raster(cc)
354
148
                             : bitmap_raster(cc->width) );
355
148
        int code1;
356
357
148
        if (pie == 0) {
358
0
            if (bits != cc_bits(cc))
359
0
                gs_free_object(mem, bits,
360
0
                               "compress_alpha_bits");
361
0
            return 1;   /* VMerror, but recoverable */
362
0
        }
363
        /* Make a matrix that will place the image */
364
        /* at (x,y) with no transformation. */
365
148
        gs_image_t_init_mask(&image, true);
366
148
        gs_make_translation((double) - x, (double) - y, &image.ImageMatrix);
367
148
        gs_matrix_multiply(&ctm_only(pgs), &image.ImageMatrix, &image.ImageMatrix);
368
148
        image.Width = w;
369
148
        image.Height = h;
370
148
        image.adjust = false;
371
148
        code = gs_image_init(pie, &image, false, true, pgs);
372
148
        switch (code) {
373
14
            case 1:   /* empty image */
374
14
                code = 0;
375
14
            default:
376
14
                break;
377
134
            case 0:
378
9.53k
                for (iy = 0; iy < h && code >= 0; iy++)
379
9.39k
                    code = gs_image_next(pie, bits + iy * raster,
380
9.39k
                                         (w + 7) >> 3, &used);
381
148
        }
382
148
        code1 = gs_image_cleanup_and_free_enum(pie, pgs);
383
148
        if (code >= 0 && code1 < 0)
384
4
            code = code1;
385
148
    }
386
17.3M
  done:if (bits != cc_bits(cc))
387
0
        gs_free_object(penum->memory->non_gc_memory, bits, "compress_alpha_bits");
388
17.3M
    if (code > 0)
389
130
        code = 0;
390
17.3M
    return_check_interrupt(penum->memory, code);
391
148
}
392
393
/* ------ Image manipulation ------ */
394
395
/*
396
 * Compress a mask with 2 or 4 bits of alpha to a monobit mask.
397
 * Allocate and return the address of the monobit mask.
398
 */
399
static byte *
400
compress_alpha_bits(const cached_char * cc, gs_memory_t * mem)
401
0
{
402
0
    const byte *data = cc_const_bits(cc);
403
0
    uint width = cc->width;
404
0
    uint height = cc->height;
405
    /* With 4x2 scale, depth == 3.
406
     * An example is -dTextAlphaBits=4 comparefiles/fonttest.pdf .
407
     * We need to map 4 bitmap bits to 2 alpha bits.
408
     */
409
0
    int depth = (cc_depth(cc) == 3 ? 2 : cc_depth(cc));
410
0
    uint sraster = cc_raster(cc);
411
0
    uint sskip = sraster - ((width * depth + 7) >> 3);
412
0
    uint draster = bitmap_raster(width);
413
0
    uint dskip = draster - ((width + 7) >> 3);
414
0
    byte *mask = gs_alloc_bytes(mem, (size_t)draster * height,
415
0
                                "compress_alpha_bits");
416
0
    const byte *sptr = data;
417
0
    byte *dptr = mask;
418
0
    uint h;
419
420
0
    if (mask == 0)
421
0
        return 0;
422
0
    for (h = height; h; --h) {
423
0
        byte sbit = 0x80;
424
0
        byte d = 0;
425
0
        byte dbit = 0x80;
426
0
        uint w;
427
428
0
        for (w = width; w; --w) {
429
0
            if (*sptr & sbit)
430
0
                d += dbit;
431
0
            if (!(sbit >>= depth))
432
0
                sbit = 0x80, sptr++;
433
0
            if (!(dbit >>= 1)) {
434
0
                *dptr++ = d;
435
0
                dbit = 0x80, d = 0;
436
0
            }
437
0
        }
438
0
        if (dbit != 0x80)
439
0
            *dptr++ = d;
440
0
        for (w = dskip; w != 0; --w)
441
0
            *dptr++ = 0;
442
0
        if (sbit != 0x80)
443
0
            ++sptr;
444
0
        sptr += sskip;
445
0
    }
446
0
    return mask;
447
0
}