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