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