1 /* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved. 2 3 This file is part of AFPL Ghostscript. 4 5 AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or 6 distributor accepts any responsibility for the consequences of using it, or 7 for whether it serves any particular purpose or works at all, unless he or 8 she says so in writing. Refer to the Aladdin Free Public License (the 9 "License") for full details. 10 11 Every copy of AFPL Ghostscript must include a copy of the License, normally 12 in a plain ASCII text file named PUBLIC. The License grants you the right 13 to copy, modify and redistribute AFPL Ghostscript, but only under certain 14 conditions described in the License. Among other things, the License 15 requires that the copyright notice and this notice be preserved on all 16 copies. 17 */ 18 19 /*$Id: gxccache.c,v 1.5 2001/07/05 20:36:55 raph Exp $ */ 20 /* Fast case character cache routines for Ghostscript library */ 21 #include "gx.h" 22 #include "gpcheck.h" 23 #include "gserrors.h" 24 #include "gsstruct.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(P2(const cached_char *, gs_memory_t *)); 42 43 /* Define a scale factor of 1. */ 44 static const gs_log2_scale_point scale_log2_1 = 45 {0, 0}; 46 47 /* Look up, and if necessary add, a font/matrix pair in the cache */ 48 cached_fm_pair * 49 gx_lookup_fm_pair(gs_font * pfont, register const gs_state * pgs) 50 { 51 float mxx = pgs->char_tm.xx, mxy = pgs->char_tm.xy, myx = pgs->char_tm.yx, 52 myy = pgs->char_tm.yy; 53 gs_font *font = pfont; 54 register gs_font_dir *dir = font->dir; 55 register cached_fm_pair *pair = 56 dir->fmcache.mdata + dir->fmcache.mnext; 57 int count = dir->fmcache.mmax; 58 gs_uid uid; 59 60 if (font->FontType == ft_composite || font->PaintType != 0) { /* We can't cache by UID alone. */ 61 uid_set_invalid(&uid); 62 } else { 63 uid = ((gs_font_base *) font)->UID; 64 if (uid_is_valid(&uid)) 65 font = 0; 66 } 67 while (count--) { 68 if (pair == dir->fmcache.mdata) 69 pair += dir->fmcache.mmax; 70 pair--; 71 /* We have either a non-zero font and an invalid UID, */ 72 /* or a zero font and a valid UID. */ 73 /* We have to break up the test */ 74 /* because of a bug in the Zortech compiler. */ 75 if (font != 0) { 76 if (pair->font != font) 77 continue; 78 } else { 79 if (!uid_equal(&pair->UID, &uid) || 80 pair->FontType != pfont->FontType 81 ) 82 continue; 83 } 84 if (pair->mxx == mxx && pair->mxy == mxy && 85 pair->myx == myx && pair->myy == myy 86 ) { 87 if (pair->font == 0) { 88 pair->font = pfont; 89 if_debug2('k', "[k]updating pair 0x%lx with font 0x%lx\n", 90 (ulong) pair, (ulong) pfont); 91 } else { 92 if_debug2('k', "[k]found pair 0x%lx: font=0x%lx\n", 93 (ulong) pair, (ulong) pair->font); 94 } 95 return pair; 96 } 97 } 98 return gx_add_fm_pair(dir, pfont, &uid, pgs); 99 } 100 101 /* Look up a glyph in the cache. */ 102 /* The character depth must be either 1 or alt_depth. */ 103 /* Return the cached_char or 0. */ 104 cached_char * 105 gx_lookup_cached_char(const gs_font * pfont, const cached_fm_pair * pair, 106 gs_glyph glyph, int wmode, int alt_depth) 107 { 108 gs_font_dir *dir = pfont->dir; 109 uint chi = chars_head_index(glyph, pair); 110 register cached_char *cc; 111 112 while ((cc = dir->ccache.table[chi & dir->ccache.table_mask]) != 0) { 113 if (cc->code == glyph && cc_pair(cc) == pair && 114 cc->wmode == wmode && (cc_depth(cc) == 1 || cc_depth(cc) == alt_depth) 115 ) { 116 if_debug4('K', "[K]found 0x%lx (depth=%d) for glyph=0x%lx, wmode=%d\n", 117 (ulong) cc, cc_depth(cc), (ulong) glyph, wmode); 118 return cc; 119 } 120 chi++; 121 } 122 if_debug3('K', "[K]not found: glyph=0x%lx, wmode=%d, alt_depth=%d\n", 123 (ulong) glyph, wmode, alt_depth); 124 return 0; 125 } 126 127 /* Look up a character in an external font. */ 128 /* Return the cached_char or 0. */ 129 cached_char * 130 gx_lookup_xfont_char(const gs_state * pgs, cached_fm_pair * pair, 131 gs_char chr, gs_glyph glyph, const gx_xfont_callbacks * callbacks, int wmode) 132 { 133 gs_font *font = pair->font; 134 int enc_index; 135 gx_xfont *xf; 136 gx_xglyph xg; 137 gs_log2_scale_point log2_scale; 138 gs_point wxy; 139 gs_int_rect bbox; 140 cached_char *cc; 141 142 if (font == 0) 143 return NULL; 144 enc_index = 145 (font->FontType == ft_composite ? -1 : 146 ((gs_font_base *) font)->nearest_encoding_index); 147 if (!pair->xfont_tried) { /* Look for an xfont now. */ 148 gx_lookup_xfont(pgs, pair, enc_index); 149 pair->xfont_tried = true; 150 } 151 xf = pair->xfont; 152 if (xf == 0) 153 return NULL; 154 { 155 const gx_xfont_procs *procs = xf->common.procs; 156 157 if (procs->char_xglyph2 == 0) { /* The xfont can't recognize reencoded fonts. */ 158 /* Use the registered encoding only if this glyph */ 159 /* is the same as the one in the registered encoding. */ 160 if (enc_index >= 0 && 161 (*callbacks->known_encode) (chr, enc_index) != glyph 162 ) 163 enc_index = -1; 164 xg = (*procs->char_xglyph) (xf, chr, enc_index, glyph, 165 callbacks->glyph_name); 166 } else { /* The xfont can recognize reencoded fonts. */ 167 xg = (*procs->char_xglyph2) (xf, chr, enc_index, glyph, 168 callbacks); 169 } 170 if (xg == gx_no_xglyph) 171 return NULL; 172 if ((*procs->char_metrics) (xf, xg, wmode, &wxy, &bbox) < 0) 173 return NULL; 174 } 175 log2_scale.x = log2_scale.y = 1; 176 cc = gx_alloc_char_bits(font->dir, NULL, NULL, bbox.q.x - bbox.p.x, 177 bbox.q.y - bbox.p.y, &log2_scale, 1); 178 if (cc == 0) 179 return NULL; 180 /* Success. Make the cache entry. */ 181 cc->code = glyph; 182 cc->wmode = wmode; 183 cc->xglyph = xg; 184 cc->wxy.x = float2fixed(wxy.x); 185 cc->wxy.y = float2fixed(wxy.y); 186 cc->offset.x = int2fixed(-bbox.p.x); 187 cc->offset.y = int2fixed(-bbox.p.y); 188 if_debug5('k', "[k]xfont %s char %d/0x%x#0x%lx=>0x%lx\n", 189 font->font_name.chars, enc_index, (int)chr, 190 (ulong) glyph, (ulong) xg); 191 if_debug6('k', " wxy=(%g,%g) bbox=(%d,%d),(%d,%d)\n", 192 wxy.x, wxy.y, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y); 193 gx_add_cached_char(font->dir, NULL, cc, pair, &scale_log2_1); 194 return cc; 195 } 196 197 /* Copy a cached character to the screen. */ 198 /* Assume the caller has already done gx_color_load. */ 199 /* Return 0 if OK, 1 if we couldn't do the operation but no error */ 200 /* should be signalled, or a negative error code. */ 201 int 202 gx_image_cached_char(register gs_show_enum * penum, register cached_char * cc) 203 { 204 register gs_state *pgs = penum->pgs; 205 gx_device_color *pdevc = pgs->dev_color; 206 int x, y, w, h, depth; 207 int code; 208 gs_fixed_point pt; 209 gx_device *dev = penum->dev; 210 gx_device *imaging_dev = penum->imaging_dev ? penum->imaging_dev : dev; 211 gx_device *orig_dev = imaging_dev; 212 gx_device_clip cdev; 213 gx_xglyph xg = cc->xglyph; 214 gx_xfont *xf; 215 byte *bits; 216 217 top:code = gx_path_current_point_inline(pgs->path, &pt); 218 if (code < 0) 219 return code; 220 /* 221 * If the character doesn't lie entirely within the inner 222 * clipping rectangle, we set up an intermediate clipping device. 223 * Note that if the original device implements fill_mask, we may 224 * never actually use the clipping device. 225 */ 226 pt.x -= cc->offset.x; 227 x = fixed2int_var_rounded(pt.x) + penum->ftx; 228 pt.y -= cc->offset.y; 229 y = fixed2int_var_rounded(pt.y) + penum->fty; 230 w = cc->width; 231 h = cc->height; 232 #ifdef DEBUG 233 if (gs_debug_c('K')) { 234 if (cc_has_bits(cc)) 235 debug_dump_bitmap(cc_bits(cc), cc_raster(cc), h, 236 "[K]bits"); 237 else 238 dputs("[K]no bits\n"); 239 dlprintf3("[K]copying 0x%lx, offset=(%g,%g)\n", (ulong) cc, 240 fixed2float(-cc->offset.x), 241 fixed2float(-cc->offset.y)); 242 dlprintf6(" at (%g,%g)+(%d,%d)->(%d,%d)\n", 243 fixed2float(pt.x), fixed2float(pt.y), 244 penum->ftx, penum->fty, x, y); 245 } 246 #endif 247 if ((x < penum->ibox.p.x || x + w > penum->ibox.q.x || 248 y < penum->ibox.p.y || y + h > penum->ibox.q.y) && 249 imaging_dev != (gx_device *) & cdev /* might be 2nd time around */ 250 ) { /* Check for the character falling entirely outside */ 251 /* the clipping region. */ 252 gx_clip_path *pcpath; 253 254 if (x >= penum->obox.q.x || x + w <= penum->obox.p.x || 255 y >= penum->obox.q.y || y + h <= penum->obox.p.y 256 ) 257 return 0; /* nothing to do */ 258 code = gx_effective_clip_path(pgs, &pcpath); 259 if (code < 0) 260 return code; 261 gx_make_clip_device(&cdev, gx_cpath_list(pcpath)); 262 cdev.target = imaging_dev; 263 imaging_dev = (gx_device *) & cdev; 264 (*dev_proc(imaging_dev, open_device)) (imaging_dev); 265 if_debug0('K', "[K](clipping)\n"); 266 } 267 /* If an xfont can render this character, use it. */ 268 if (xg != gx_no_xglyph && (xf = cc_pair(cc)->xfont) != 0) { 269 int cx = x + fixed2int(cc->offset.x); 270 int cy = y + fixed2int(cc->offset.y); 271 272 /* 273 * Note that we prefer a 1-bit xfont implementation over 274 * a multi-bit cached bitmap. Eventually we should change 275 * the xfont interface so it can deliver multi-bit bitmaps, 276 * or else implement oversampling for xfonts. 277 */ 278 if (gs_color_writes_pure(pgs)) { 279 code = (*xf->common.procs->render_char) (xf, xg, 280 imaging_dev, cx, cy, 281 pdevc->colors.pure, 0); 282 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", 283 (ulong) xf, (ulong) xg, (ulong) imaging_dev, 284 imaging_dev->dname, cx, cy, 285 (ulong) pdevc->colors.pure, code); 286 if (code == 0) 287 return_check_interrupt(0); 288 } 289 /* Can't render directly. If we don't have a bitmap yet, */ 290 /* get it from the xfont now. */ 291 if (!cc_has_bits(cc)) { 292 gx_device_memory mdev; 293 294 gs_make_mem_mono_device(&mdev, 0, imaging_dev); 295 gx_open_cache_device(&mdev, cc); 296 code = (*xf->common.procs->render_char) (xf, xg, 297 (gx_device *) & mdev, cx - x, cy - y, 298 (gx_color_index) 1, 1); 299 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", 300 (ulong) xf, (ulong) xg, (ulong) & mdev, 301 mdev.dname, cx - x, cy - y, code); 302 if (code != 0) 303 return_check_interrupt(1); 304 gx_add_char_bits(cc_pair(cc)->font->dir, 305 cc, &scale_log2_1); 306 /* gx_add_char_bits may change width, height, */ 307 /* raster, and/or offset. It's easiest to */ 308 /* start over from the top. Clear xg so that */ 309 /* we don't waste time trying render_char again. */ 310 xg = gx_no_xglyph; 311 goto top; 312 } 313 } 314 /* 315 * No xfont. Render from the cached bits. If the cached bits 316 * have more than 1 bit of alpha, and the color isn't pure or 317 * the copy_alpha operation fails, construct a single-bit mask 318 * by taking the high-order alpha bit. 319 */ 320 bits = cc_bits(cc); 321 depth = cc_depth(cc); 322 if (dev_proc(orig_dev, fill_mask) != gx_default_fill_mask || 323 !lop_no_S_is_T(pgs->log_op) 324 ) { 325 gx_clip_path *pcpath; 326 327 code = gx_effective_clip_path(pgs, &pcpath); 328 if (code >= 0) { 329 code = (*dev_proc(orig_dev, fill_mask)) 330 (orig_dev, bits, 0, cc_raster(cc), cc->id, 331 x, y, w, h, pdevc, depth, pgs->log_op, pcpath); 332 if (code >= 0) 333 goto done; 334 } 335 } else if (gs_color_writes_pure(pgs)) { 336 gx_color_index color = pdevc->colors.pure; 337 338 if (depth > 1) { 339 code = (*dev_proc(imaging_dev, copy_alpha)) 340 (imaging_dev, bits, 0, cc_raster(cc), cc->id, 341 x, y, w, h, color, depth); 342 if (code >= 0) 343 return_check_interrupt(0); 344 /* copy_alpha failed, construct a monobit mask. */ 345 bits = compress_alpha_bits(cc, &gs_memory_default); 346 if (bits == 0) 347 return 1; /* VMerror, but recoverable */ 348 } 349 code = (*dev_proc(imaging_dev, copy_mono)) 350 (imaging_dev, bits, 0, cc_raster(cc), cc->id, 351 x, y, w, h, gx_no_color_index, pdevc->colors.pure); 352 goto done; 353 } 354 if (depth > 1) { /* Complex color or fill_mask / copy_alpha failed, */ 355 /* construct a monobit mask. */ 356 bits = compress_alpha_bits(cc, &gs_memory_default); 357 if (bits == 0) 358 return 1; /* VMerror, but recoverable */ 359 360 } { /* Use imagemask to render the character. */ 361 gs_memory_t *mem = &gs_memory_default; 362 gs_image_enum *pie = 363 gs_image_enum_alloc(mem, "image_char(image_enum)"); 364 gs_image_t image; 365 int iy; 366 uint used; 367 368 if (pie == 0) { 369 if (bits != cc_bits(cc)) 370 gs_free_object(&gs_memory_default, bits, 371 "compress_alpha_bits"); 372 return 1; /* VMerror, but recoverable */ 373 } 374 /* Make a matrix that will place the image */ 375 /* at (x,y) with no transformation. */ 376 gs_image_t_init_mask(&image, true); 377 #define mat image.ImageMatrix 378 gs_make_translation((floatp) - x, (floatp) - y, &mat); 379 gs_matrix_multiply(&ctm_only(pgs), &mat, &mat); 380 #undef mat 381 image.Width = w; 382 image.Height = h; 383 image.adjust = false; 384 code = gs_image_init(pie, &image, false, pgs); 385 switch (code) { 386 case 1: /* empty image */ 387 code = 0; 388 default: 389 break; 390 case 0: 391 for (iy = 0; iy < h && code >= 0; iy++) 392 code = gs_image_next(pie, bits + iy * cc_raster(cc), 393 (w + 7) >> 3, &used); 394 gs_image_cleanup(pie); 395 } 396 gs_free_object(mem, pie, "image_char(image_enum)"); 397 } 398 done:if (bits != cc_bits(cc)) 399 gs_free_object(&gs_memory_default, bits, "compress_alpha_bits"); 400 if (code > 0) 401 code = 0; 402 return_check_interrupt(code); 403 } 404 405 /* ------ Image manipulation ------ */ 406 407 /* 408 * Compress a mask with 2 or 4 bits of alpha to a monobit mask. 409 * Allocate and return the address of the monobit mask. 410 */ 411 private byte * 412 compress_alpha_bits(const cached_char * cc, gs_memory_t * mem) 413 { 414 const byte *data = cc_const_bits(cc); 415 uint width = cc->width; 416 uint height = cc->height; 417 int log2_scale = cc_depth(cc); 418 int scale = 1 << log2_scale; 419 uint sraster = cc_raster(cc); 420 uint sskip = sraster - ((width * scale + 7) >> 3); 421 uint draster = bitmap_raster(width); 422 uint dskip = draster - ((width + 7) >> 3); 423 byte *mask = gs_alloc_bytes(mem, draster * height, 424 "compress_alpha_bits"); 425 const byte *sptr = data; 426 byte *dptr = mask; 427 uint h; 428 429 if (mask == 0) 430 return 0; 431 for (h = height; h; --h) { 432 byte sbit = 0x80; 433 byte d = 0; 434 byte dbit = 0x80; 435 uint w; 436 437 for (w = width; w; --w) { 438 if (*sptr & sbit) 439 d += dbit; 440 if (!(sbit >>= log2_scale)) 441 sbit = 0x80, sptr++; 442 if (!(dbit >>= 1)) 443 dbit = 0x80, dptr++, d = 0; 444 } 445 if (dbit != 0x80) 446 *dptr++ = d; 447 for (w = dskip; w != 0; --w) 448 *dptr++ = 0; 449 sptr += sskip; 450 } 451 return mask; 452 } 453