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 /* Tracing device (including sample high-level implementation) */
18 #include "gx.h"
19 #include "gserrors.h"
20 #include "gscspace.h"
21 #include "gxdevice.h"
22 #include "gxtmap.h"		/* for gxdht.h */
23 #include "gxdht.h"
24 #include "gxfont.h"
25 #include "gxiparam.h"
26 #include "gxistate.h"
27 #include "gxpaint.h"
28 #include "gzpath.h"
29 #include "gzcpath.h"
30 
31 /* Define the default resolution. */
32 #ifndef X_DPI
33 #  define X_DPI 720
34 #endif
35 #ifndef Y_DPI
36 #  define Y_DPI 720
37 #endif
38 
39 extern_st(st_gs_text_enum);
40 extern_st(st_gx_image_enum_common);
41 
42 /* ---------------- Internal utilities ---------------- */
43 
44 static void
trace_drawing_color(const char * prefix,const gx_drawing_color * pdcolor)45 trace_drawing_color(const char *prefix, const gx_drawing_color *pdcolor)
46 {
47     dprintf1("%scolor=", prefix);
48     if (pdcolor->type == gx_dc_type_none)
49         dputs("none");
50     else if (pdcolor->type == gx_dc_type_null)
51         dputs("null");
52     else if (pdcolor->type == gx_dc_type_pure)
53         dprintf1("0x%lx", (ulong)pdcolor->colors.pure);
54     else if (pdcolor->type == gx_dc_type_ht_binary) {
55         int ci = pdcolor->colors.binary.b_index;
56 
57         dprintf5("binary(0x%lx, 0x%lx, %d/%d, index=%d)",
58                  (ulong)pdcolor->colors.binary.color[0],
59                  (ulong)pdcolor->colors.binary.color[1],
60                  pdcolor->colors.binary.b_level,
61                  (ci < 0 ? pdcolor->colors.binary.b_ht->order.num_bits :
62                   pdcolor->colors.binary.b_ht->components[ci].corder.num_bits),
63                  ci);
64     } else if (pdcolor->type == gx_dc_type_ht_colored) {
65         ulong plane_mask = pdcolor->colors.colored.plane_mask;
66         int ci;
67 
68         dprintf1("colored(mask=%lu", plane_mask);
69         for (ci = 0; plane_mask != 0; ++ci, plane_mask >>= 1)
70             if (plane_mask & 1) {
71                 dprintf2(", (base=%u, level=%u)",
72                          pdcolor->colors.colored.c_base[ci],
73                          pdcolor->colors.colored.c_level[ci]);
74             } else
75                 dputs(", -");
76     } else {
77         dputs("**unknown**");
78     }
79 }
80 
81 static void
trace_lop(gs_logical_operation_t lop)82 trace_lop(gs_logical_operation_t lop)
83 {
84     dprintf1(", lop=0x%x", (uint)lop);
85 }
86 
87 static void
trace_path(const gx_path * path)88 trace_path(const gx_path *path)
89 {
90     gs_path_enum penum;
91 
92     gx_path_enum_init(&penum, path);
93     for (;;) {
94         gs_fixed_point pts[3];
95 
96         switch (gx_path_enum_next(&penum, pts)) {
97         case gs_pe_moveto:
98             dprintf2("    %g %g moveto\n", fixed2float(pts[0].x),
99                      fixed2float(pts[0].y));
100             continue;
101         case gs_pe_lineto:
102             dprintf2("    %g %g lineto\n", fixed2float(pts[0].x),
103                      fixed2float(pts[0].y));
104             continue;
105         case gs_pe_gapto:
106             dprintf2("    %g %g gapto\n", fixed2float(pts[0].x),
107                      fixed2float(pts[0].y));
108             continue;
109         case gs_pe_curveto:
110             dprintf6("    %g %g %g %g %g %g curveto\n", fixed2float(pts[0].x),
111                      fixed2float(pts[0].y), fixed2float(pts[1].x),
112                      fixed2float(pts[1].y), fixed2float(pts[2].x),
113                      fixed2float(pts[2].y));
114             continue;
115         case gs_pe_closepath:
116             dputs("    closepath\n");
117             continue;
118         default:
119             break;
120         }
121         break;
122     }
123 }
124 
125 static void
trace_clip(gx_device * dev,const gx_clip_path * pcpath)126 trace_clip(gx_device *dev, const gx_clip_path *pcpath)
127 {
128     if (pcpath == 0)
129         return;
130     if (gx_cpath_includes_rectangle(pcpath, fixed_0, fixed_0,
131                                     int2fixed(dev->width),
132                                     int2fixed(dev->height))
133         )
134         return;
135     dputs(", clip={");
136     if (pcpath->path_valid)
137         trace_path(&pcpath->path);
138     else
139         dputs("NO PATH");
140     dputs("}");
141 }
142 
143 /* ---------------- Low-level driver procedures ---------------- */
144 
145 static int
trace_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)146 trace_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
147                      gx_color_index color)
148 {
149     dprintf5("fill_rectangle(%d, %d, %d, %d, 0x%lx)\n",
150              x, y, w, h, (ulong)color);
151     return 0;
152 }
153 
154 static int
trace_copy_mono(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)155 trace_copy_mono(gx_device * dev, const byte * data,
156                 int dx, int raster, gx_bitmap_id id,
157                 int x, int y, int w, int h,
158                 gx_color_index zero, gx_color_index one)
159 {
160     dprintf7("copy_mono(x=%d, y=%d, w=%d, h=%d, dx=%d, raster=%d, id=0x%lx,\n",
161              x, y, w, h, dx, raster, (ulong)id);
162     dprintf2("    colors=(0x%lx,0x%lx))\n", (ulong)zero, (ulong)one);
163     return 0;
164 }
165 
166 static int
trace_copy_color(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h)167 trace_copy_color(gx_device * dev, const byte * data,
168                  int dx, int raster, gx_bitmap_id id,
169                  int x, int y, int w, int h)
170 {
171     dprintf7("copy_color(x=%d, y=%d, w=%d, h=%d, dx=%d, raster=%d, id=0x%lx)\n",
172              x, y, w, h, dx, raster, (ulong)id);
173     return 0;
174 }
175 
176 static int
trace_copy_alpha(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index color,int depth)177 trace_copy_alpha(gx_device * dev, const byte * data, int dx, int raster,
178                  gx_bitmap_id id, int x, int y, int w, int h,
179                  gx_color_index color, int depth)
180 {
181     dprintf7("copy_alpha(x=%d, y=%d, w=%d, h=%d, dx=%d, raster=%d, id=0x%lx,\n",
182              x, y, w, h, dx, raster, (ulong)id);
183     dprintf2("    color=0x%lx, depth=%d)\n", (ulong)color, depth);
184     return 0;
185 }
186 
187 static int
trace_fill_mask(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,const gx_drawing_color * pdcolor,int depth,gs_logical_operation_t lop,const gx_clip_path * pcpath)188 trace_fill_mask(gx_device * dev,
189                 const byte * data, int dx, int raster, gx_bitmap_id id,
190                 int x, int y, int w, int h,
191                 const gx_drawing_color * pdcolor, int depth,
192                 gs_logical_operation_t lop, const gx_clip_path * pcpath)
193 {
194     dprintf7("fill_mask(x=%d, y=%d, w=%d, h=%d, dx=%d, raster=%d, id=0x%lx,\n",
195              x, y, w, h, dx, raster, (ulong)id);
196     trace_drawing_color("    ", pdcolor);
197     dprintf1(", depth=%d", depth);
198     trace_lop(lop);
199     trace_clip(dev, pcpath);
200     dputs(")\n");
201     return 0;
202 }
203 
204 static int
trace_fill_trapezoid(gx_device * dev,const gs_fixed_edge * left,const gs_fixed_edge * right,fixed ybot,fixed ytop,bool swap_axes,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)205 trace_fill_trapezoid(gx_device * dev,
206                      const gs_fixed_edge * left,
207                      const gs_fixed_edge * right,
208                      fixed ybot, fixed ytop, bool swap_axes,
209                      const gx_drawing_color * pdcolor,
210                      gs_logical_operation_t lop)
211 {
212     dputs("**fill_trapezoid**\n");
213     return 0;
214 }
215 
216 static int
trace_fill_parallelogram(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)217 trace_fill_parallelogram(gx_device * dev,
218                          fixed px, fixed py, fixed ax, fixed ay,
219                          fixed bx, fixed by, const gx_drawing_color * pdcolor,
220                          gs_logical_operation_t lop)
221 {
222     dprintf6("fill_parallelogram((%g,%g), (%g,%g), (%g,%g)",
223              fixed2float(px), fixed2float(py), fixed2float(ax),
224              fixed2float(ay), fixed2float(bx), fixed2float(by));
225     trace_drawing_color(", ", pdcolor);
226     trace_lop(lop);
227     dputs(")\n");
228     return 0;
229 }
230 
231 static int
trace_fill_triangle(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)232 trace_fill_triangle(gx_device * dev,
233                     fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
234                     const gx_drawing_color * pdcolor,
235                     gs_logical_operation_t lop)
236 {
237     dprintf6("fill_triangle((%g,%g), (%g,%g), (%g,%g)",
238              fixed2float(px), fixed2float(py), fixed2float(ax),
239              fixed2float(ay), fixed2float(bx), fixed2float(by));
240     trace_drawing_color(", ", pdcolor);
241     trace_lop(lop);
242     dputs(")\n");
243     return 0;
244 }
245 
246 static int
trace_draw_thin_line(gx_device * dev,fixed fx0,fixed fy0,fixed fx1,fixed fy1,const gx_drawing_color * pdcolor,gs_logical_operation_t lop,fixed adjustx,fixed adjusty)247 trace_draw_thin_line(gx_device * dev,
248                      fixed fx0, fixed fy0, fixed fx1, fixed fy1,
249                      const gx_drawing_color * pdcolor,
250                      gs_logical_operation_t lop,
251                      fixed adjustx, fixed adjusty)
252 {
253     dprintf4("draw_thin_line((%g,%g), (%g,%g)",
254              fixed2float(fx0), fixed2float(fy0), fixed2float(fx1),
255              fixed2float(fy1));
256     trace_drawing_color(", ", pdcolor);
257     trace_lop(lop);
258     dputs(")\n");
259     return 0;
260 }
261 
262 static int
trace_strip_tile_rectangle(gx_device * dev,const gx_strip_bitmap * tiles,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int px,int py)263 trace_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
264                            int x, int y, int w, int h,
265                            gx_color_index color0, gx_color_index color1,
266                            int px, int py)
267 {
268     dprintf6("strip_tile_rectangle(x=%d, y=%d, w=%d, h=%d, colors=(0x%lx,0x%lx),\n",
269              x, y, w, h, (ulong)color0, (ulong)color1);
270     dprintf8("    size=(%d,%d) shift %u, rep=(%u,%u) shift %u, phase=(%d,%d))\n",
271              tiles->size.x, tiles->size.y, tiles->shift,
272              tiles->rep_width, tiles->rep_height, tiles->rep_shift, px, py);
273     return 0;
274 }
275 
276 static int
trace_strip_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)277 trace_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex,
278                      uint sraster, gx_bitmap_id id,
279                      const gx_color_index * scolors,
280                      const gx_strip_bitmap * textures,
281                      const gx_color_index * tcolors,
282                      int x, int y, int width, int height,
283                      int phase_x, int phase_y, gs_logical_operation_t lop)
284 {
285     dputs("**strip_copy_rop**\n");
286     return 0;
287 }
288 
289 static int
trace_strip_copy_rop2(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop,uint plane_height)290 trace_strip_copy_rop2(gx_device * dev, const byte * sdata, int sourcex,
291                       uint sraster, gx_bitmap_id id,
292                       const gx_color_index * scolors,
293                       const gx_strip_bitmap * textures,
294                       const gx_color_index * tcolors,
295                       int x, int y, int width, int height,
296                       int phase_x, int phase_y, gs_logical_operation_t lop,
297                       uint plane_height)
298 {
299     dputs("**strip_copy_rop2**\n");
300     return 0;
301 }
302 
303 /* ---------------- High-level driver procedures ---------------- */
304 
305 static int
trace_fill_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)306 trace_fill_path(gx_device * dev, const gs_imager_state * pis,
307                 gx_path * ppath, const gx_fill_params * params,
308                 const gx_drawing_color * pdcolor,
309                 const gx_clip_path * pcpath)
310 {
311     dputs("fill_path({\n");
312     trace_path(ppath);
313     trace_drawing_color("}, ", pdcolor);
314     dprintf4(", rule=%d, adjust=(%g,%g), flatness=%g",
315              params->rule, fixed2float(params->adjust.x),
316              fixed2float(params->adjust.y), params->flatness);
317     trace_clip(dev, pcpath);
318     /****** pis ******/
319     dputs(")\n");
320     return 0;
321 }
322 
323 static int
trace_stroke_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)324 trace_stroke_path(gx_device * dev, const gs_imager_state * pis,
325                   gx_path * ppath, const gx_stroke_params * params,
326                   const gx_drawing_color * pdcolor,
327                   const gx_clip_path * pcpath)
328 {
329     dputs("stroke_path({\n");
330     trace_path(ppath);
331     trace_drawing_color("}, ", pdcolor);
332     dprintf1(", flatness=%g", params->flatness);
333     trace_clip(dev, pcpath);
334     /****** pis ******/
335     dputs(")\n");
336     return 0;
337 }
338 
339 typedef struct trace_image_enum_s {
340     gx_image_enum_common;
341     int rows_left;
342 } trace_image_enum_t;
343 gs_private_st_suffix_add0(st_trace_image_enum, trace_image_enum_t,
344                           "trace_image_enum_t", trace_image_enum_enum_ptrs,
345                           trace_image_enum_reloc_ptrs,
346                           st_gx_image_enum_common);
347 static int
trace_plane_data(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * rows_used)348 trace_plane_data(gx_image_enum_common_t * info,
349                  const gx_image_plane_t * planes, int height,
350                  int *rows_used)
351 {
352     trace_image_enum_t *pie = (trace_image_enum_t *)info;
353     int i;
354 
355     dprintf1("image_plane_data(height=%d", height);
356     for (i = 0; i < pie->num_planes; ++i) {
357         if (planes[i].data)
358             dprintf4(", {depth=%d, width=%d, dx=%d, raster=%u}",
359                      pie->plane_depths[i], pie->plane_widths[i],
360                      planes[i].data_x, planes[i].raster);
361         else
362             dputs(", -");
363     }
364     dputs(")\n");
365     *rows_used = height;
366     return (pie->rows_left -= height) <= 0;
367 }
368 static int
trace_end_image(gx_image_enum_common_t * info,bool draw_last)369 trace_end_image(gx_image_enum_common_t * info, bool draw_last)
370 {
371     trace_image_enum_t *pie = (trace_image_enum_t *)info;
372 
373     gx_image_free_enum(&info);
374     return 0;
375 }
376 static const gx_image_enum_procs_t trace_image_enum_procs = {
377     trace_plane_data, trace_end_image
378 };
379 static int
trace_begin_typed_image(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pim,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gx_image_enum_common_t ** pinfo)380 trace_begin_typed_image(gx_device * dev, const gs_imager_state * pis,
381                         const gs_matrix * pmat,
382                         const gs_image_common_t * pim,
383                         const gs_int_rect * prect,
384                         const gx_drawing_color * pdcolor,
385                         const gx_clip_path * pcpath,
386                         gs_memory_t * memory,
387                         gx_image_enum_common_t ** pinfo)
388 {
389     trace_image_enum_t *pie;
390     const gs_pixel_image_t *ppi = (const gs_pixel_image_t *)pim;
391     int ncomp;
392 
393     dprintf7("begin_typed_image(type=%d, ImageMatrix=[%g %g %g %g %g %g]",
394              pim->type->index, pim->ImageMatrix.xx, pim->ImageMatrix.xy,
395              pim->ImageMatrix.yx, pim->ImageMatrix.yy,
396              pim->ImageMatrix.tx, pim->ImageMatrix.ty);
397     switch (pim->type->index) {
398     case 1:
399         if (((const gs_image1_t *)ppi)->ImageMask) {
400             ncomp = 1;
401             break;
402         }
403         /* falls through */
404     case 4:
405         ncomp = gs_color_space_num_components(ppi->ColorSpace);
406         break;
407     case 3:
408         ncomp = gs_color_space_num_components(ppi->ColorSpace) + 1;
409         break;
410     case 2:			/* no data */
411         dputs(")\n");
412         return 1;
413     default:
414         goto dflt;
415     }
416     pie = gs_alloc_struct(memory, trace_image_enum_t, &st_trace_image_enum,
417                           "trace_begin_typed_image");
418     if (pie == 0)
419         goto dflt;
420     if (gx_image_enum_common_init((gx_image_enum_common_t *)pie,
421                                   (const gs_data_image_t *)pim,
422                                   &trace_image_enum_procs, dev, ncomp,
423                                   ppi->format) < 0
424         )
425         goto dflt;
426     dprintf4("\n    Width=%d, Height=%d, BPC=%d, num_components=%d)\n",
427              ppi->Width, ppi->Height, ppi->BitsPerComponent, ncomp);
428     pie->memory = memory;
429     pie->rows_left = ppi->Height;
430     *pinfo = (gx_image_enum_common_t *)pie;
431     return 0;
432  dflt:
433     dputs(") DEFAULTED\n");
434     return gx_default_begin_typed_image(dev, pis, pmat, pim, prect, pdcolor,
435                                         pcpath, memory, pinfo);
436 }
437 
438 static int
trace_text_process(gs_text_enum_t * pte)439 trace_text_process(gs_text_enum_t *pte)
440 {
441     return 0;
442 }
443 static const gs_text_enum_procs_t trace_text_procs = {
444     NULL, trace_text_process, NULL, NULL, NULL, NULL,
445     gx_default_text_release
446 };
447 static int
trace_text_begin(gx_device * dev,gs_imager_state * pis,const gs_text_params_t * text,gs_font * font,gx_path * path,const gx_device_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gs_text_enum_t ** ppenum)448 trace_text_begin(gx_device * dev, gs_imager_state * pis,
449                  const gs_text_params_t * text, gs_font * font,
450                  gx_path * path, const gx_device_color * pdcolor,
451                  const gx_clip_path * pcpath, gs_memory_t * memory,
452                  gs_text_enum_t ** ppenum)
453 {
454     static const char *const tags[sizeof(text->operation) * 8] = {
455         "FROM_STRING", "FROM_BYTES", "FROM_CHARS", "FROM_GLYPHS",
456         "FROM_SINGLE_CHAR", "FROM_SINGLE_GLYPH",
457         "ADD_TO_ALL_WIDTHS", "ADD_TO_SPACE_WIDTH",
458         "REPLACE_WIDTHS", "DO_NONE", "DO_DRAW", "DO_CHARWIDTH",
459         "DO_FALSE_CHARPATH", "DO_TRUE_CHARPATH",
460         "DO_FALSE_CHARBOXPATH", "DO_TRUE_CHARBOXPATH",
461         "INTERVENE", "RETURN_WIDTH"
462     };
463     int i;
464     gs_text_enum_t *pte;
465     int code;
466 
467     dputs("text_begin(");
468     for (i = 0; i < countof(tags); ++i)
469         if (text->operation & (1 << i)) {
470             if (tags[i])
471                 dprintf1("%s ", tags[i]);
472             else
473                 dprintf1("%d? ", i);
474         }
475     dprintf1("font=%s\n           text=(", font->font_name.chars);
476     if (text->operation & TEXT_FROM_SINGLE_CHAR)
477         dprintf1("0x%lx", (ulong)text->data.d_char);
478     else if (text->operation & TEXT_FROM_SINGLE_GLYPH)
479         dprintf1("0x%lx", (ulong)text->data.d_glyph);
480     else
481         for (i = 0; i < text->size; ++i) {
482             if (text->operation & TEXT_FROM_STRING)
483                 dputc(text->data.bytes[i]);
484             else
485                 dprintf1("0x%lx ",
486                          (text->operation & TEXT_FROM_GLYPHS ?
487                           (ulong)text->data.glyphs[i] :
488                           (ulong)text->data.chars[i]));
489     }
490     dprintf1(")\n           size=%u", text->size);
491     if (text->operation & TEXT_ADD_TO_ALL_WIDTHS)
492         dprintf2(", delta_all=(%g,%g)", text->delta_all.x, text->delta_all.y);
493     if (text->operation & TEXT_ADD_TO_SPACE_WIDTH) {
494         dprintf3(", space=0x%lx, delta_space=(%g,%g)",
495                  (text->operation & TEXT_FROM_GLYPHS ?
496                   (ulong)text->space.s_glyph : (ulong)text->space.s_char),
497                  text->delta_space.x, text->delta_space.y);
498     }
499     if (text->operation & TEXT_REPLACE_WIDTHS) {
500         dputs("\n           widths=");
501         for (i = 0; i < text->widths_size; ++i) {
502             if (text->x_widths)
503                 dprintf1("(%g,", text->x_widths[i]);
504             else
505                 dputs("(,");
506             if (text->y_widths)
507                 dprintf1("%g)",
508                          (text->y_widths == text->x_widths ?
509                           text->y_widths[++i] : text->y_widths[i]));
510             else
511                 dputs(")");
512         }
513     }
514     if (text->operation & TEXT_DO_DRAW)
515         trace_drawing_color(", ", pdcolor);
516     /*
517      * We can't do it if CHAR*PATH or INTERVENE, or if (RETURN_WIDTH and not
518      * REPLACE_WIDTHS and we can't get the widths from the font).
519      */
520     if (text->operation &
521         (TEXT_DO_FALSE_CHARPATH | TEXT_DO_TRUE_CHARPATH |
522          TEXT_DO_FALSE_CHARBOXPATH | TEXT_DO_TRUE_CHARBOXPATH |
523          TEXT_INTERVENE)
524         )
525         goto dflt;
526     rc_alloc_struct_1(pte, gs_text_enum_t, &st_gs_text_enum, memory,
527                       goto dflt, "trace_text_begin");
528     code = gs_text_enum_init(pte, &trace_text_procs, dev, pis, text, font,
529                              path, pdcolor, pcpath, memory);
530     if (code < 0)
531         goto dfree;
532     if ((text->operation & (TEXT_DO_CHARWIDTH | TEXT_RETURN_WIDTH)) &&
533         !(text->operation & TEXT_REPLACE_WIDTHS)
534         ) {
535         /*
536          * Get the widths from the font.  This code is mostly copied from
537          * the pdfwrite driver, and should probably be shared with it.
538          * ****** WRONG IF Type 0 FONT ******
539          */
540         int i;
541         gs_point w;
542         double scale = (font->FontType == ft_TrueType ? 0.001 : 1.0);
543         gs_fixed_point origin;
544         gs_point dpt;
545         int num_spaces = 0;
546 
547         if (!(text->operation & TEXT_FROM_STRING))
548             goto dfree;		/* can't handle yet */
549         if (gx_path_current_point(path, &origin) < 0)
550             goto dfree;
551         w.x = 0, w.y = 0;
552         for (i = 0; i < text->size; ++i) {
553             gs_char ch = text->data.bytes[i];
554             int wmode = font->WMode;
555             gs_glyph glyph =
556                 ((gs_font_base *)font)->procs.encode_char(font, ch,
557                                                           GLYPH_SPACE_NAME);
558             gs_glyph_info_t info;
559 
560             if (glyph != gs_no_glyph &&
561                 (code = font->procs.glyph_info(font, glyph, NULL,
562                                                GLYPH_INFO_WIDTH0 << wmode,
563                                                &info)) >= 0
564             ) {
565                 w.x += info.width[wmode].x;
566                 w.y += info.width[wmode].y;
567             } else
568                 goto dfree;
569             if (ch == text->space.s_char)
570                 ++num_spaces;
571         }
572         gs_distance_transform(w.x * scale, w.y * scale,
573                               &font->FontMatrix, &dpt);
574         if (text->operation & TEXT_ADD_TO_ALL_WIDTHS) {
575             int num_chars = text->size;
576 
577             dpt.x += text->delta_all.x * num_chars;
578             dpt.y += text->delta_all.y * num_chars;
579         }
580         if (text->operation & TEXT_ADD_TO_SPACE_WIDTH) {
581             dpt.x += text->delta_space.x * num_spaces;
582             dpt.y += text->delta_space.y * num_spaces;
583         }
584         pte->returned.total_width = dpt;
585         gs_distance_transform(dpt.x, dpt.y, &ctm_only(pis), &dpt);
586         code = gx_path_add_point(path,
587                                  origin.x + float2fixed(dpt.x),
588                                  origin.y + float2fixed(dpt.y));
589         if (code < 0)
590             goto dfree;
591     }
592     dputs(")\n");
593     *ppenum = pte;
594     return 0;
595  dfree:
596     gs_free_object(memory, pte, "trace_text_begin");
597  dflt:
598     dputs(") DEFAULTED\n");
599     return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
600                                  pcpath, memory, ppenum);
601 }
602 
603 /* ---------------- The device definition ---------------- */
604 
605 #define TRACE_DEVICE_BODY(dname, ncomp, depth, map_rgb_color, map_color_rgb, map_cmyk_color, map_rgb_alpha_color)\
606     std_device_dci_body(gx_device, 0, dname,\
607                         DEFAULT_WIDTH_10THS * X_DPI / 10,\
608                         DEFAULT_HEIGHT_10THS * Y_DPI / 10,\
609                         X_DPI, Y_DPI, ncomp, depth,\
610                         (1 << (depth / ncomp)) - 1,\
611                         (ncomp > 1 ? (1 << (depth / ncomp)) - 1 : 0),\
612                         1 << (depth / ncomp),\
613                         (ncomp > 1 ? 1 << (depth / ncomp) : 1)),\
614 {\
615      NULL,			/* open_device */\
616      NULL,			/* get_initial_matrix */\
617      NULL,			/* sync_output */\
618      NULL,			/* output_page */\
619      NULL,			/* close_device */\
620      map_rgb_color,		/* differs */\
621      map_color_rgb,		/* differs */\
622      trace_fill_rectangle,\
623      NULL,			/* tile_rectangle */\
624      trace_copy_mono,\
625      trace_copy_color,\
626      NULL,			/* draw_line */\
627      NULL,			/* get_bits */\
628      NULL,			/* get_params */\
629      NULL,			/* put_params */\
630      map_cmyk_color,		/* differs */\
631      NULL,			/* get_xfont_procs */\
632      NULL,			/* get_xfont_device */\
633      map_rgb_alpha_color,	/* differs */\
634      gx_page_device_get_page_device,\
635      NULL,			/* get_alpha_bits */\
636      trace_copy_alpha,\
637      NULL,			/* get_band */\
638      NULL,			/* copy_rop */\
639      trace_fill_path,\
640      trace_stroke_path,\
641      trace_fill_mask,\
642      trace_fill_trapezoid,\
643      trace_fill_parallelogram,\
644      trace_fill_triangle,\
645      trace_draw_thin_line,\
646      NULL,			/* begin_image */\
647      NULL,			/* image_data */\
648      NULL,			/* end_image */\
649      trace_strip_tile_rectangle,\
650      trace_strip_copy_rop,\
651      NULL,			/* get_clipping_box */\
652      trace_begin_typed_image,\
653      NULL,			/* get_bits_rectangle */\
654      NULL,			/* map_color_rgb_alpha */\
655      NULL,			/* create_compositor */\
656      NULL,			/* get_hardware_params */\
657      trace_text_begin,\
658      NULL,			/* finish_copydevice */\
659      NULL,			/* begin_transparency_group */\
660      NULL,			/* end_transparency_group */\
661      NULL,			/* begin_transparency_mask */\
662      NULL,			/* end_transparency_mask */\
663      NULL,			/* discard_transparency_layer */\
664      NULL,			/* get_color_mapping_procs */\
665      NULL,			/* get_color_comp_index */\
666      NULL,			/* encode_color */\
667      NULL,			/* decode_color */\
668      NULL,			/* pattern_manage */\
669      NULL,			/* fill_rectangle_hl_color */\
670      NULL,			/* include_color_space */\
671      NULL,			/* fill_linear_color_scanline */\
672      NULL,			/* fill_linear_color_trapezoid */\
673      NULL,			/* fill_linear_color_triangle */\
674      NULL,			/* update_spot_equivalent_colors */\
675      NULL,			/* ret_devn_params */\
676      NULL,			/* fillpage */\
677      NULL,			/* push_transparency_state */\
678      NULL,			/* pop_transparency_state */\
679      NULL,			/* put_image */\
680      NULL,			/* dev_spec_op */\
681      NULL,			/* copy_planes */\
682      NULL,			/* get_profile */\
683      NULL,			/* set_graphics_type_tag */\
684      trace_strip_copy_rop2\
685 }
686 
687 const gx_device gs_tr_mono_device = {
688     TRACE_DEVICE_BODY("tr_mono", 1, 1,
689                       gx_default_b_w_map_rgb_color,
690                       gx_default_b_w_map_color_rgb, NULL, NULL)
691 };
692 
693 const gx_device gs_tr_rgb_device = {
694     TRACE_DEVICE_BODY("tr_rgb", 3, 24,
695                       gx_default_rgb_map_rgb_color,
696                       gx_default_rgb_map_color_rgb, NULL, NULL)
697 };
698 
699 const gx_device gs_tr_cmyk_device = {
700     TRACE_DEVICE_BODY("tr_cmyk", 4, 4,
701                       NULL, cmyk_1bit_map_color_rgb,
702                       cmyk_1bit_map_cmyk_color, NULL)
703 };
704