1 /* Copyright (C) 2001-2019 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
gx_compute_char_matrix(const gs_matrix * char_tm,const gs_log2_scale_point * log2_scale,float * mxx,float * mxy,float * myx,float * myy)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 {
52     int scale_x = 1 << log2_scale->x;
53     int scale_y = 1 << log2_scale->y;
54 
55     *mxx = char_tm->xx * scale_x;
56     *mxy = char_tm->xy * scale_x;
57     *myx = char_tm->yx * scale_y;
58     *myy = char_tm->yy * scale_y;
59 }
60 
61 void
gx_compute_ccache_key(gs_font * pfont,const gs_matrix * char_tm,const gs_log2_scale_point * log2_scale,bool design_grid,float * mxx,float * mxy,float * myx,float * myy)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 {
66     if (design_grid &&
67             (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         *mxx = *mxy = *myx = *myy = 0;
77     } else
78         gx_compute_char_matrix(char_tm, log2_scale, mxx, mxy, myx, myy);
79 }
80 
81 /* Look up, and if necessary add, a font/matrix pair in the cache */
82 int
gx_lookup_fm_pair(gs_font * pfont,const gs_matrix * char_tm,const gs_log2_scale_point * log2_scale,bool design_grid,cached_fm_pair ** ppair)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 {
86     float mxx, mxy, myx, myy;
87     gs_font *font = pfont;
88     register gs_font_dir *dir = font->dir;
89     register cached_fm_pair *pair = dir->fmcache.mdata + dir->fmcache.used;
90     int count = dir->fmcache.msize;
91     gs_uid uid;
92 
93     gx_compute_ccache_key(pfont, char_tm, log2_scale, design_grid,
94                             &mxx, &mxy, &myx, &myy);
95     if (font->FontType == ft_composite || font->PaintType != 0) {	/* We can't cache by UID alone. */
96         uid_set_invalid(&uid);
97     } else {
98         uid = ((gs_font_base *) font)->UID;
99         if (uid_is_valid(&uid))
100             font = 0;
101     }
102     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         if (font != 0) {
108             if (pair->font != font)
109                 continue;
110         } else {
111             if (!uid_equal(&pair->UID, &uid) ||
112                 pair->FontType != pfont->FontType
113                 )
114                 continue;
115         }
116         if (pair->mxx == mxx && pair->mxy == mxy &&
117             pair->myx == myx && pair->myy == myy
118             && pair->design_grid == design_grid) {
119             int code;
120 
121             if (pair->font == 0) {
122                 pair->font = pfont;
123                 if_debug2m('k', pfont->memory, "[k]updating pair 0x%lx with font 0x%lx\n",
124                            (ulong) pair, (ulong) pfont);
125             } else {
126                 if_debug2m('k', pfont->memory, "[k]found pair 0x%lx: font=0x%lx\n",
127                            (ulong) pair, (ulong) pair->font);
128             }
129             code = gx_touch_fm_pair(dir, pair);
130             if (code < 0)
131                 return code;
132             code = gx_provide_fm_pair_attributes(dir, pfont, pair,
133                                 char_tm, log2_scale, design_grid);
134             if (code < 0)
135                 return code;
136             *ppair = pair;
137             return 0;
138         }
139     }
140     return gx_add_fm_pair(dir, pfont, &uid, char_tm, log2_scale, design_grid, ppair);
141 }
142 
143 /* Look up a glyph with the right depth in the cache. */
144 /* Return the cached_char or 0. */
145 cached_char *
gx_lookup_cached_char(const gs_font * pfont,const cached_fm_pair * pair,gs_glyph glyph,int wmode,int depth,gs_fixed_point * subpix_origin)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 {
150     gs_font_dir *dir = pfont->dir;
151     uint chi = chars_head_index(glyph, pair);
152     register cached_char *cc;
153 
154     while ((cc = dir->ccache.table[chi & dir->ccache.table_mask]) != 0) {
155         if (cc->code == glyph && cc_pair(cc) == pair &&
156             cc->subpix_origin.x == subpix_origin->x &&
157             cc->subpix_origin.y == subpix_origin->y &&
158             cc->wmode == wmode && cc_depth(cc) == depth
159             ) {
160             if_debug4m('K', pfont->memory,
161                        "[K]found 0x%lx (depth=%d) for glyph=0x%lx, wmode=%d\n",
162                        (ulong) cc, cc_depth(cc), (ulong) glyph, wmode);
163             return cc;
164         }
165         chi++;
166     }
167     if_debug3m('K', pfont->memory, "[K]not found: glyph=0x%lx, wmode=%d, depth=%d\n",
168               (ulong) glyph, wmode, depth);
169     return 0;
170 }
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
gx_image_cached_char(register gs_show_enum * penum,register cached_char * cc)177 gx_image_cached_char(register gs_show_enum * penum, register cached_char * cc)
178 {
179     register gs_gstate *pgs = penum->pgs;
180     gx_device_color *pdevc = gs_currentdevicecolor_inline(pgs);
181     int x, y, w, h, depth;
182     int code;
183     gs_fixed_point pt;
184     gx_device *dev = penum->dev;
185     gx_device *imaging_dev = penum->imaging_dev ? penum->imaging_dev : dev;
186     gx_device *orig_dev = imaging_dev;
187     gx_device_clip cdev;
188     gx_xglyph xg = cc->xglyph;
189     gx_xfont *xf;
190     byte *bits;
191 
192   top:code = gx_path_current_point_inline(pgs, &pt);
193     if (code < 0)
194         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     pt.x -= cc->offset.x + cc->subpix_origin.x;
202     x = fixed2int_var_rounded(pt.x) + penum->ftx;
203     pt.y -= cc->offset.y + cc->subpix_origin.y;
204     y = fixed2int_var_rounded(pt.y) + penum->fty;
205     w = cc->width;
206     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 0x%lx, offset=(%g,%g)\n", (ulong) cc,
215                    fixed2float(-cc->offset.x),
216                    fixed2float(-cc->offset.y));
217         dmlprintf6(penum->memory, "   at (%g,%g)+(%d,%d)->(%d,%d)\n",
218                    fixed2float(pt.x), fixed2float(pt.y),
219                    penum->ftx, penum->fty, x, y);
220     }
221 #endif
222     if ((x < penum->ibox.p.x || x + w > penum->ibox.q.x ||
223          y < penum->ibox.p.y || y + h > penum->ibox.q.y) &&
224         imaging_dev != (gx_device *) & cdev	/* might be 2nd time around */
225         ) {			/* Check for the character falling entirely outside */
226         /* the clipping region. */
227         gx_clip_path *pcpath;
228 
229         if (x >= penum->obox.q.x || x + w <= penum->obox.p.x ||
230             y >= penum->obox.q.y || y + h <= penum->obox.p.y
231             )
232             return 0;		/* nothing to do */
233         code = gx_effective_clip_path(pgs, &pcpath);
234         if (code < 0)
235             return code;
236         gx_make_clip_device_on_stack(&cdev, pcpath, imaging_dev);
237         imaging_dev = (gx_device *) & cdev;
238         if_debug0m('K', penum->memory, "[K](clipping)\n");
239     }
240     code = gx_set_dev_color(pgs);
241     if (code != 0)
242         return code;
243     /* If an xfont can render this character, use it. */
244     if (xg != gx_no_xglyph && (xf = cc_pair(cc)->xfont) != 0) {
245         int cx = x + fixed2int(cc->offset.x);
246         int cy = y + fixed2int(cc->offset.y);
247 
248         /*
249          * Note that we prefer a 1-bit xfont implementation over
250          * a multi-bit cached bitmap.  Eventually we should change
251          * the xfont interface so it can deliver multi-bit bitmaps,
252          * or else implement oversampling for xfonts.
253          */
254         if (gs_color_writes_pure(pgs)) {
255             code = (*xf->common.procs->render_char) (xf, xg,
256                                         imaging_dev, cx, cy,
257                                         pdevc->colors.pure, 0);
258             if_debug8m('K', penum->memory,
259                        "[K]render_char display: xfont=0x%lx, glyph=0x%lx\n\tdev=0x%lx(%s) x,y=%d,%d, color=0x%lx => %d\n",
260                        (ulong) xf, (ulong) xg, (ulong) imaging_dev,
261                        imaging_dev->dname, cx, cy,
262                        (ulong) pdevc->colors.pure, code);
263             if (code == 0)
264                 return_check_interrupt(penum->memory, 0);
265         }
266         /* Can't render directly.  If we don't have a bitmap yet, */
267         /* get it from the xfont now. */
268         if (!cc_has_bits(cc)) {
269             gx_device_memory mdev;
270 
271             gs_make_mem_mono_device(&mdev, dev->memory, imaging_dev);
272             gx_open_cache_device(&mdev, cc);
273             code = (*xf->common.procs->render_char) (xf, xg,
274                                        (gx_device *) & mdev, cx - x, cy - y,
275                                                      (gx_color_index) 1, 1);
276             if_debug7m('K', penum->memory,
277                        "[K]render_char to bits: xfont=0x%lx, glyph=0x%lx\n\tdev=0x%lx(%s) x,y=%d,%d => %d\n",
278                       (ulong) xf, (ulong) xg, (ulong) & mdev,
279                       mdev.dname, cx - x, cy - y, code);
280             if (code != 0)
281                 return_check_interrupt(penum->memory, 1);
282             gx_add_char_bits(cc_pair(cc)->font->dir,
283                              cc, &scale_log2_1);
284             /* gx_add_char_bits may change width, height, */
285             /* raster, and/or offset.  It's easiest to */
286             /* start over from the top.  Clear xg so that */
287             /* we don't waste time trying render_char again. */
288             xg = gx_no_xglyph;
289             goto top;
290         }
291     }
292     /*
293      * No xfont.  Render from the cached bits.  If the cached bits
294      * have more than 1 bit of alpha, and the color isn't pure or
295      * the copy_alpha operation fails, construct a single-bit mask
296      * by taking the high-order alpha bit.
297      */
298     bits = cc_bits(cc);
299     /* With 4x2 scale, depth == 3.
300      * An example is -dTextAlphaBits=4 comparefiles/fonttest.pdf .
301      * We need to map 4 bitmap bits to 2 alpha bits.
302      */
303     depth = (cc_depth(cc) == 3 ? 2 : cc_depth(cc));
304     if ((dev_proc(orig_dev, fill_mask) != gx_default_fill_mask ||
305         !lop_no_S_is_T(pgs->log_op))) {
306 
307         gx_clip_path *pcpath;
308 
309         penum->use_wxy_float = false;
310         penum->wxy_float.x = penum->wxy_float.y = 0.0;
311         penum->wxy = cc->wxy;
312 
313         code = gx_effective_clip_path(pgs, &pcpath);
314         if (code >= 0) {
315             code = gx_image_fill_masked
316                 (orig_dev, bits, 0, cc_raster(cc), cc->id,
317                  x, y, w, h, pdevc, depth, pgs->log_op, pcpath);
318             if (code >= 0)
319                 goto done;
320         }
321     } else if (gs_color_writes_pure(pgs)) {
322         gx_color_index color = pdevc->colors.pure;
323 
324         if (depth > 1) {
325             code = (*dev_proc(imaging_dev, copy_alpha))
326                 (imaging_dev, bits, 0, cc_raster(cc), cc->id,
327                  x, y, w, h, color, depth);
328             if (code >= 0)
329                 return_check_interrupt(penum->memory, 0);
330             /* copy_alpha failed, construct a monobit mask. */
331             bits = compress_alpha_bits(cc, penum->memory->non_gc_memory);
332             if (bits == 0)
333                 return 1;	/* VMerror, but recoverable */
334         }
335         code = (*dev_proc(imaging_dev, copy_mono))
336             (imaging_dev, bits, 0, bitmap_raster(w), gs_no_id,
337              x, y, w, h, gx_no_color_index, color);
338         goto done;
339     }
340     if (depth > 1) {		/* Complex color or fill_mask / copy_alpha failed, */
341         /* construct a monobit mask. */
342         bits = compress_alpha_bits(cc, penum->memory->non_gc_memory);
343         if (bits == 0)
344             return 1;		/* VMerror, but recoverable */
345 
346     } {				/* Use imagemask to render the character. */
347         gs_memory_t *mem = penum->memory->non_gc_memory;
348         gs_image_enum *pie =
349             gs_image_enum_alloc(mem, "image_char(image_enum)");
350         gs_image_t image;
351         int iy;
352         uint used, raster = (bits == cc_bits(cc) ? cc_raster(cc)
353                              : bitmap_raster(cc->width) );
354         int code1;
355 
356         if (pie == 0) {
357             if (bits != cc_bits(cc))
358                 gs_free_object(mem, bits,
359                                "compress_alpha_bits");
360             return 1;		/* VMerror, but recoverable */
361         }
362         /* Make a matrix that will place the image */
363         /* at (x,y) with no transformation. */
364         gs_image_t_init_mask(&image, true);
365         gs_make_translation((double) - x, (double) - y, &image.ImageMatrix);
366         gs_matrix_multiply(&ctm_only(pgs), &image.ImageMatrix, &image.ImageMatrix);
367         image.Width = w;
368         image.Height = h;
369         image.adjust = false;
370         code = gs_image_init(pie, &image, false, true, pgs);
371         switch (code) {
372             case 1:		/* empty image */
373                 code = 0;
374             default:
375                 break;
376             case 0:
377                 for (iy = 0; iy < h && code >= 0; iy++)
378                     code = gs_image_next(pie, bits + iy * raster,
379                                          (w + 7) >> 3, &used);
380         }
381         code1 = gs_image_cleanup_and_free_enum(pie, pgs);
382         if (code >= 0 && code1 < 0)
383             code = code1;
384     }
385   done:if (bits != cc_bits(cc))
386         gs_free_object(penum->memory->non_gc_memory, bits, "compress_alpha_bits");
387     if (code > 0)
388         code = 0;
389     return_check_interrupt(penum->memory, code);
390 }
391 
392 /* ------ Image manipulation ------ */
393 
394 /*
395  * Compress a mask with 2 or 4 bits of alpha to a monobit mask.
396  * Allocate and return the address of the monobit mask.
397  */
398 static byte *
compress_alpha_bits(const cached_char * cc,gs_memory_t * mem)399 compress_alpha_bits(const cached_char * cc, gs_memory_t * mem)
400 {
401     const byte *data = cc_const_bits(cc);
402     uint width = cc->width;
403     uint height = cc->height;
404     /* With 4x2 scale, depth == 3.
405      * An example is -dTextAlphaBits=4 comparefiles/fonttest.pdf .
406      * We need to map 4 bitmap bits to 2 alpha bits.
407      */
408     int depth = (cc_depth(cc) == 3 ? 2 : cc_depth(cc));
409     uint sraster = cc_raster(cc);
410     uint sskip = sraster - ((width * depth + 7) >> 3);
411     uint draster = bitmap_raster(width);
412     uint dskip = draster - ((width + 7) >> 3);
413     byte *mask = gs_alloc_bytes(mem, draster * height,
414                                 "compress_alpha_bits");
415     const byte *sptr = data;
416     byte *dptr = mask;
417     uint h;
418 
419     if (mask == 0)
420         return 0;
421     for (h = height; h; --h) {
422         byte sbit = 0x80;
423         byte d = 0;
424         byte dbit = 0x80;
425         uint w;
426 
427         for (w = width; w; --w) {
428             if (*sptr & sbit)
429                 d += dbit;
430             if (!(sbit >>= depth))
431                 sbit = 0x80, sptr++;
432             if (!(dbit >>= 1)) {
433                 *dptr++ = d;
434                 dbit = 0x80, d = 0;
435             }
436         }
437         if (dbit != 0x80)
438             *dptr++ = d;
439         for (w = dskip; w != 0; --w)
440             *dptr++ = 0;
441         if (sbit != 0x80)
442             ++sptr;
443         sptr += sskip;
444     }
445     return mask;
446 }
447