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