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 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 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 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 * 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 * 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 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 * 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