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