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