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