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