1 /* Copyright (C) 2001-2006 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, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /* $Id: gxccache.c 9253 2008-12-05 04:44:51Z alexcher $ */
15 /* Fast case character cache routines for Ghostscript library */
16 #include "memory_.h"
17 #include "gx.h"
18 #include "gpcheck.h"
19 #include "gserrors.h"
20 #include "gsstruct.h"
21 #include "gscencs.h"
22 #include "gxfixed.h"
23 #include "gxmatrix.h"
24 #include "gzstate.h"
25 #include "gzpath.h"
26 #include "gxdevice.h"
27 #include "gxdevmem.h"
28 #include "gzcpath.h"
29 #include "gxchar.h"
30 #include "gxfont.h"
31 #include "gxfcache.h"
32 #include "gxxfont.h"
33 #include "gximask.h"
34 #include "gscspace.h"		/* for gsimage.h */
35 #include "gsimage.h"
36 #include "gxhttile.h"
37 
38 /* Forward references */
39 static byte *compress_alpha_bits(const cached_char *, gs_memory_t *);
40 
41 /* Define a scale factor of 1. */
42 static const gs_log2_scale_point scale_log2_1 =
43 {0, 0};
44 
45 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)46 gx_compute_char_matrix(const gs_matrix *char_tm, const gs_log2_scale_point *log2_scale,
47     float *mxx, float *mxy, float *myx, float *myy)
48 {
49     int scale_x = 1 << log2_scale->x;
50     int scale_y = 1 << log2_scale->y;
51 
52     *mxx = char_tm->xx * scale_x;
53     *mxy = char_tm->xy * scale_x;
54     *myx = char_tm->yx * scale_y;
55     *myy = char_tm->yy * scale_y;
56 }
57 
58 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)59 gx_compute_ccache_key(gs_font * pfont, const gs_matrix *char_tm,
60     const gs_log2_scale_point *log2_scale, bool design_grid,
61     float *mxx, float *mxy, float *myx, float *myy)
62 {
63     if (design_grid &&
64 	    (pfont->FontType == ft_TrueType || pfont->FontType == ft_CID_TrueType)) {
65 	/*
66 	 * We need a special face for this case, because the TT interpreter
67 	 * can't generate both grid_fitted and non-grid-fitted outlines
68 	 * with a same face instance. This happens due to control
69 	 * values in 'cvt' must be different.
70 	 * Since a single face satisfies all font sizes,
71 	 * we use a zero matrix as the cache entry key.
72 	 */
73 	*mxx = *mxy = *myx = *myy = 0;
74     } else
75 	gx_compute_char_matrix(char_tm, log2_scale, mxx, mxy, myx, myy);
76 }
77 
78 /* Look up, and if necessary add, a font/matrix pair in the cache */
79 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)80 gx_lookup_fm_pair(gs_font * pfont, const gs_matrix *char_tm,
81     const gs_log2_scale_point *log2_scale, bool design_grid, cached_fm_pair **ppair)
82 {
83     float mxx, mxy, myx, myy;
84     gs_font *font = pfont;
85     register gs_font_dir *dir = font->dir;
86     register cached_fm_pair *pair = dir->fmcache.mdata + dir->fmcache.used;
87     int count = dir->fmcache.msize;
88     gs_uid uid;
89 
90     gx_compute_ccache_key(pfont, char_tm, log2_scale, design_grid,
91 			    &mxx, &mxy, &myx, &myy);
92     if (font->FontType == ft_composite || font->PaintType != 0) {	/* We can't cache by UID alone. */
93 	uid_set_invalid(&uid);
94     } else {
95 	uid = ((gs_font_base *) font)->UID;
96 	if (uid_is_valid(&uid))
97 	    font = 0;
98     }
99     for (;count--; pair = dir->fmcache.mdata + pair->next) {
100 	/* We have either a non-zero font and an invalid UID, */
101 	/* or a zero font and a valid UID. */
102 	/* We have to break up the test */
103 	/* because of a bug in the Zortech compiler. */
104 	if (font != 0) {
105 	    if (pair->font != font)
106 		continue;
107 	} else {
108 	    if (!uid_equal(&pair->UID, &uid) ||
109 		pair->FontType != pfont->FontType
110 		)
111 		continue;
112 	}
113 	if (pair->mxx == mxx && pair->mxy == mxy &&
114 	    pair->myx == myx && pair->myy == myy
115 	    && pair->design_grid == design_grid) {
116 	    int code;
117 
118 	    if (pair->font == 0) {
119 		pair->font = pfont;
120 		if_debug2('k', "[k]updating pair 0x%lx with font 0x%lx\n",
121 			  (ulong) pair, (ulong) pfont);
122 	    } else {
123 		if_debug2('k', "[k]found pair 0x%lx: font=0x%lx\n",
124 			  (ulong) pair, (ulong) pair->font);
125 	    }
126 	    code = gx_touch_fm_pair(dir, pair);
127 	    if (code < 0)
128 		return code;
129 	    code = gx_provide_fm_pair_attributes(dir, pfont, pair,
130 				char_tm, log2_scale, design_grid);
131 	    if (code < 0)
132 		return code;
133 	    *ppair = pair;
134 	    return 0;
135 	}
136     }
137     return gx_add_fm_pair(dir, pfont, &uid, char_tm, log2_scale, design_grid, ppair);
138 }
139 
140 /* Look up a glyph with the right depth in the cache. */
141 /* Return the cached_char or 0. */
142 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)143 gx_lookup_cached_char(const gs_font * pfont, const cached_fm_pair * pair,
144 		      gs_glyph glyph, int wmode, int depth,
145 		      gs_fixed_point *subpix_origin)
146 {
147     gs_font_dir *dir = pfont->dir;
148     uint chi = chars_head_index(glyph, pair);
149     register cached_char *cc;
150 
151     while ((cc = dir->ccache.table[chi & dir->ccache.table_mask]) != 0) {
152 	if (cc->code == glyph && cc_pair(cc) == pair &&
153 	    cc->subpix_origin.x == subpix_origin->x &&
154 	    cc->subpix_origin.y == subpix_origin->y &&
155 	    cc->wmode == wmode && cc_depth(cc) == depth
156 	    ) {
157 	    if_debug4('K', "[K]found 0x%lx (depth=%d) for glyph=0x%lx, wmode=%d\n",
158 		      (ulong) cc, cc_depth(cc), (ulong) glyph, wmode);
159 	    return cc;
160 	}
161 	chi++;
162     }
163     if_debug3('K', "[K]not found: glyph=0x%lx, wmode=%d, depth=%d\n",
164 	      (ulong) glyph, wmode, depth);
165     return 0;
166 }
167 
168 /* Look up a character in an external font. */
169 /* If found, stores a pointer to the cached_char into *pcc and returns 1 */
170 /* Otherwise stores NULL into *pcc and returns 0 or error. */
171 /* Note it must initialise *pcc in any case. */
172 int
gx_lookup_xfont_char(const gs_state * pgs,cached_fm_pair * pair,gs_char chr,gs_glyph glyph,int wmode,cached_char ** pcc)173 gx_lookup_xfont_char(const gs_state * pgs, cached_fm_pair * pair,
174 		     gs_char chr, gs_glyph glyph, int wmode, cached_char **pcc)
175 {
176     gs_font *font = pair->font;
177     int enc_index;
178     gx_xfont *xf;
179     gx_xglyph xg;
180     gs_log2_scale_point log2_scale;
181     gs_point wxy;
182     gs_int_rect bbox;
183     cached_char *cc;
184     int code;
185 
186     *pcc = NULL;
187     if (font == 0)
188 	return 0;
189     enc_index =
190 	(font->FontType == ft_composite ? -1 :
191 	 ((gs_font_base *) font)->nearest_encoding_index);
192     if (!pair->xfont_tried) {	/* Look for an xfont now. */
193 	gx_lookup_xfont(pgs, pair, enc_index);
194 	pair->xfont_tried = true;
195     }
196     xf = pair->xfont;
197     if (xf == 0)
198 	return 0;
199     {
200 	const gx_xfont_procs *procs = xf->common.procs;
201 	gs_const_string gstr;
202 	int code = font->procs.glyph_name(font, glyph, &gstr);
203 
204 	if (code < 0)
205 	    return 0;
206 	if (enc_index >= 0 && ((gs_font_base *)font)->encoding_index < 0) {
207 	    /*
208 	     * Use the registered encoding only if this glyph
209 	     * is the same as the one in the registered encoding.
210 	     */
211 	    gs_const_string kstr;
212 
213 	    if (gs_c_glyph_name(gs_c_known_encode(chr, enc_index), &kstr) < 0 ||
214 		kstr.size != gstr.size ||
215 		memcmp(kstr.data, gstr.data, kstr.size)
216 		)
217 		enc_index = -1;
218 	}
219 	xg = procs->char_xglyph(xf, chr, enc_index, glyph, &gstr);
220 	if (xg == gx_no_xglyph)
221 	    return 0;
222 	if ((*procs->char_metrics) (xf, xg, wmode, &wxy, &bbox) < 0)
223 	    return 0;
224     }
225     log2_scale.x = log2_scale.y = 1;
226     code = gx_alloc_char_bits(font->dir, NULL, NULL,
227 		(ushort)(bbox.q.x - bbox.p.x), (ushort)(bbox.q.y - bbox.p.y),
228 		&log2_scale, 1, &cc);
229     if (code < 0)
230 	return code;
231     if (cc == 0)
232 	return 0;
233     /* Success.  Make the cache entry. */
234     cc->code = glyph;
235     cc->wmode = wmode;
236     cc->xglyph = xg;
237     cc->wxy.x = float2fixed(wxy.x);
238     cc->wxy.y = float2fixed(wxy.y);
239     cc->offset.x = int2fixed(-bbox.p.x);
240     cc->offset.y = int2fixed(-bbox.p.y);
241     cc_set_pair(cc, pair);
242     if_debug5('k', "[k]xfont %s char %d/0x%x#0x%lx=>0x%lx\n",
243 	      font->font_name.chars, enc_index, (int)chr,
244 	      (ulong) glyph, (ulong) xg);
245     if_debug6('k', "     wxy=(%g,%g) bbox=(%d,%d),(%d,%d)\n",
246 	      wxy.x, wxy.y, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
247     code = gx_add_cached_char(font->dir, NULL, cc, pair, &scale_log2_1);
248     if (code < 0)
249 	return code;
250     *pcc = cc;
251     return 1;
252 }
253 
254 /* Copy a cached character to the screen. */
255 /* Assume the caller has already done gx_color_load. */
256 /* Return 0 if OK, 1 if we couldn't do the operation but no error */
257 /* should be signalled, or a negative error code. */
258 int
gx_image_cached_char(register gs_show_enum * penum,register cached_char * cc)259 gx_image_cached_char(register gs_show_enum * penum, register cached_char * cc)
260 {
261     register gs_state *pgs = penum->pgs;
262     gx_device_color *pdevc = pgs->dev_color;
263     int x, y, w, h, depth;
264     int code;
265     gs_fixed_point pt;
266     gx_device *dev = penum->dev;
267     gx_device *imaging_dev = penum->imaging_dev ? penum->imaging_dev : dev;
268     gx_device *orig_dev = imaging_dev;
269     gx_device_clip cdev;
270     gx_xglyph xg = cc->xglyph;
271     gx_xfont *xf;
272     byte *bits;
273 
274   top:code = gx_path_current_point_inline(pgs->path, &pt);
275     if (code < 0)
276 	return code;
277     /*
278      * If the character doesn't lie entirely within the inner
279      * clipping rectangle, we set up an intermediate clipping device.
280      * Note that if the original device implements fill_mask, we may
281      * never actually use the clipping device.
282      */
283     pt.x -= cc->offset.x + cc->subpix_origin.x;
284     x = fixed2int_var_rounded(pt.x) + penum->ftx;
285     pt.y -= cc->offset.y + cc->subpix_origin.y;
286     y = fixed2int_var_rounded(pt.y) + penum->fty;
287     w = cc->width;
288     h = cc->height;
289 #ifdef DEBUG
290     if (gs_debug_c('K')) {
291 	if (cc_has_bits(cc))
292 	    debug_dump_bitmap(cc_bits(cc), cc_raster(cc), h,
293 			      "[K]bits");
294 	else
295 	    dputs("[K]no bits\n");
296 	dlprintf3("[K]copying 0x%lx, offset=(%g,%g)\n", (ulong) cc,
297 		  fixed2float(-cc->offset.x),
298 		  fixed2float(-cc->offset.y));
299 	dlprintf6("   at (%g,%g)+(%d,%d)->(%d,%d)\n",
300 		  fixed2float(pt.x), fixed2float(pt.y),
301 		  penum->ftx, penum->fty, x, y);
302     }
303 #endif
304     if ((x < penum->ibox.p.x || x + w > penum->ibox.q.x ||
305 	 y < penum->ibox.p.y || y + h > penum->ibox.q.y) &&
306 	imaging_dev != (gx_device *) & cdev	/* might be 2nd time around */
307 	) {			/* Check for the character falling entirely outside */
308 	/* the clipping region. */
309 	gx_clip_path *pcpath;
310 
311 	if (x >= penum->obox.q.x || x + w <= penum->obox.p.x ||
312 	    y >= penum->obox.q.y || y + h <= penum->obox.p.y
313 	    )
314 	    return 0;		/* nothing to do */
315 	code = gx_effective_clip_path(pgs, &pcpath);
316 	if (code < 0)
317 	    return code;
318 	gx_make_clip_device_on_stack(&cdev, pcpath, imaging_dev);
319 	imaging_dev = (gx_device *) & cdev;
320 	if_debug0('K', "[K](clipping)\n");
321     }
322     gx_set_dev_color(pgs);
323     /* If an xfont can render this character, use it. */
324     if (xg != gx_no_xglyph && (xf = cc_pair(cc)->xfont) != 0) {
325 	int cx = x + fixed2int(cc->offset.x);
326 	int cy = y + fixed2int(cc->offset.y);
327 
328 	/*
329 	 * Note that we prefer a 1-bit xfont implementation over
330 	 * a multi-bit cached bitmap.  Eventually we should change
331 	 * the xfont interface so it can deliver multi-bit bitmaps,
332 	 * or else implement oversampling for xfonts.
333 	 */
334 	if (gs_color_writes_pure(pgs)) {
335 	    code = (*xf->common.procs->render_char) (xf, xg,
336 					imaging_dev, cx, cy,
337 					pdevc->colors.pure, 0);
338 	    if_debug8('K', "[K]render_char display: xfont=0x%lx, glyph=0x%lx\n\tdev=0x%lx(%s) x,y=%d,%d, color=0x%lx => %d\n",
339 		      (ulong) xf, (ulong) xg, (ulong) imaging_dev,
340 		      imaging_dev->dname, cx, cy,
341 		      (ulong) pdevc->colors.pure, code);
342 	    if (code == 0)
343 		return_check_interrupt(penum->memory, 0);
344 	}
345 	/* Can't render directly.  If we don't have a bitmap yet, */
346 	/* get it from the xfont now. */
347 	if (!cc_has_bits(cc)) {
348 	    gx_device_memory mdev;
349 
350 	    gs_make_mem_mono_device(&mdev, dev->memory, imaging_dev);
351 	    gx_open_cache_device(&mdev, cc);
352 	    code = (*xf->common.procs->render_char) (xf, xg,
353 				       (gx_device *) & mdev, cx - x, cy - y,
354 						     (gx_color_index) 1, 1);
355 	    if_debug7('K', "[K]render_char to bits: xfont=0x%lx, glyph=0x%lx\n\tdev=0x%lx(%s) x,y=%d,%d => %d\n",
356 		      (ulong) xf, (ulong) xg, (ulong) & mdev,
357 		      mdev.dname, cx - x, cy - y, code);
358 	    if (code != 0)
359 		return_check_interrupt(penum->memory, 1);
360 	    gx_add_char_bits(cc_pair(cc)->font->dir,
361 			     cc, &scale_log2_1);
362 	    /* gx_add_char_bits may change width, height, */
363 	    /* raster, and/or offset.  It's easiest to */
364 	    /* start over from the top.  Clear xg so that */
365 	    /* we don't waste time trying render_char again. */
366 	    xg = gx_no_xglyph;
367 	    goto top;
368 	}
369     }
370     /*
371      * No xfont.  Render from the cached bits.  If the cached bits
372      * have more than 1 bit of alpha, and the color isn't pure or
373      * the copy_alpha operation fails, construct a single-bit mask
374      * by taking the high-order alpha bit.
375      */
376     bits = cc_bits(cc);
377     /* With 4x2 scale, depth == 3.
378      * An example is -dTextAlphaBits=4 comparefiles/fonttest.pdf .
379      * We need to map 4 bitmap bits to 2 alpha bits.
380      */
381     depth = (cc_depth(cc) == 3 ? 2 : cc_depth(cc));
382     if (dev_proc(orig_dev, fill_mask) != gx_default_fill_mask ||
383 	!lop_no_S_is_T(pgs->log_op)
384 	) {
385 	gx_clip_path *pcpath;
386 
387 	code = gx_effective_clip_path(pgs, &pcpath);
388 	if (code >= 0) {
389 	    code = gx_image_fill_masked
390 		(orig_dev, bits, 0, cc_raster(cc), cc->id,
391 		 x, y, w, h, pdevc, depth, pgs->log_op, pcpath);
392 	    if (code >= 0)
393 		goto done;
394 	}
395     } else if (gs_color_writes_pure(pgs)) {
396 	gx_color_index color = pdevc->colors.pure;
397 
398 	if (depth > 1) {
399 	    code = (*dev_proc(imaging_dev, copy_alpha))
400 		(imaging_dev, bits, 0, cc_raster(cc), cc->id,
401 		 x, y, w, h, color, depth);
402 	    if (code >= 0)
403 		return_check_interrupt(penum->memory, 0);
404 	    /* copy_alpha failed, construct a monobit mask. */
405 	    bits = compress_alpha_bits(cc, penum->memory->non_gc_memory);
406 	    if (bits == 0)
407 		return 1;	/* VMerror, but recoverable */
408 	}
409 	code = (*dev_proc(imaging_dev, copy_mono))
410 	    (imaging_dev, bits, 0, bitmap_raster(w), gs_no_id,
411 	     x, y, w, h, gx_no_color_index, color);
412 	goto done;
413     }
414     if (depth > 1) {		/* Complex color or fill_mask / copy_alpha failed, */
415 	/* construct a monobit mask. */
416 	bits = compress_alpha_bits(cc, penum->memory->non_gc_memory);
417 	if (bits == 0)
418 	    return 1;		/* VMerror, but recoverable */
419 
420     } {				/* Use imagemask to render the character. */
421 	gs_memory_t *mem = penum->memory->non_gc_memory;
422 	gs_image_enum *pie =
423 	    gs_image_enum_alloc(mem, "image_char(image_enum)");
424 	gs_image_t image;
425 	int iy;
426 	uint used, raster = (bits == cc_bits(cc) ? cc_raster(cc)
427 			     : bitmap_raster(cc->width) );
428 	int code1;
429 
430 	if (pie == 0) {
431 	    if (bits != cc_bits(cc))
432 		gs_free_object(mem, bits,
433 			       "compress_alpha_bits");
434 	    return 1;		/* VMerror, but recoverable */
435 	}
436 	/* Make a matrix that will place the image */
437 	/* at (x,y) with no transformation. */
438 	gs_image_t_init_mask(&image, true);
439 	gs_make_translation((floatp) - x, (floatp) - y, &image.ImageMatrix);
440 	gs_matrix_multiply(&ctm_only(pgs), &image.ImageMatrix, &image.ImageMatrix);
441 	image.Width = w;
442 	image.Height = h;
443 	image.adjust = false;
444 	code = gs_image_init(pie, &image, false, pgs);
445 	switch (code) {
446 	    case 1:		/* empty image */
447 		code = 0;
448 	    default:
449 		break;
450 	    case 0:
451 		for (iy = 0; iy < h && code >= 0; iy++)
452 		    code = gs_image_next(pie, bits + iy * raster,
453 					 (w + 7) >> 3, &used);
454 	}
455 	code1 = gs_image_cleanup_and_free_enum(pie, pgs);
456 	if (code >= 0 && code1 < 0)
457 	    code = code1;
458     }
459   done:if (bits != cc_bits(cc))
460 	gs_free_object(penum->memory->non_gc_memory, bits, "compress_alpha_bits");
461     if (code > 0)
462 	code = 0;
463     return_check_interrupt(penum->memory, code);
464 }
465 
466 /* ------ Image manipulation ------ */
467 
468 /*
469  * Compress a mask with 2 or 4 bits of alpha to a monobit mask.
470  * Allocate and return the address of the monobit mask.
471  */
472 static byte *
compress_alpha_bits(const cached_char * cc,gs_memory_t * mem)473 compress_alpha_bits(const cached_char * cc, gs_memory_t * mem)
474 {
475     const byte *data = cc_const_bits(cc);
476     uint width = cc->width;
477     uint height = cc->height;
478     /* With 4x2 scale, depth == 3.
479      * An example is -dTextAlphaBits=4 comparefiles/fonttest.pdf .
480      * We need to map 4 bitmap bits to 2 alpha bits.
481      */
482     int depth = (cc_depth(cc) == 3 ? 2 : cc_depth(cc));
483     uint sraster = cc_raster(cc);
484     uint sskip = sraster - ((width * depth + 7) >> 3);
485     uint draster = bitmap_raster(width);
486     uint dskip = draster - ((width + 7) >> 3);
487     byte *mask = gs_alloc_bytes(mem, draster * height,
488 				"compress_alpha_bits");
489     const byte *sptr = data;
490     byte *dptr = mask;
491     uint h;
492 
493     if (mask == 0)
494 	return 0;
495     for (h = height; h; --h) {
496 	byte sbit = 0x80;
497 	byte d = 0;
498 	byte dbit = 0x80;
499 	uint w;
500 
501 	for (w = width; w; --w) {
502 	    if (*sptr & sbit)
503 		d += dbit;
504 	    if (!(sbit >>= depth))
505 		sbit = 0x80, sptr++;
506 	    if (!(dbit >>= 1)) {
507 		*dptr++ = d;
508 		dbit = 0x80, d = 0;
509 	    }
510 	}
511 	if (dbit != 0x80)
512 	    *dptr++ = d;
513 	for (w = dskip; w != 0; --w)
514 	    *dptr++ = 0;
515 	if (sbit != 0x80)
516 	    ++sptr;
517 	sptr += sskip;
518     }
519     return mask;
520 }
521