1 #include "mupdf/fitz.h"
2 
3 typedef struct
4 {
5 	fz_device super;
6 	fz_output *out;
7 	int depth;
8 } fz_trace_device;
9 
fz_trace_indent(fz_context * ctx,fz_output * out,int depth)10 static void fz_trace_indent(fz_context *ctx, fz_output *out, int depth)
11 {
12 	while (depth-- > 0)
13 		fz_write_string(ctx, out, "    ");
14 }
15 
16 static void
fz_trace_matrix(fz_context * ctx,fz_output * out,fz_matrix ctm)17 fz_trace_matrix(fz_context *ctx, fz_output *out, fz_matrix ctm)
18 {
19 	fz_write_printf(ctx, out, " transform=\"%g %g %g %g %g %g\"", ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f);
20 }
21 
22 static void
fz_trace_color(fz_context * ctx,fz_output * out,fz_colorspace * colorspace,const float * color,float alpha)23 fz_trace_color(fz_context *ctx, fz_output *out, fz_colorspace *colorspace, const float *color, float alpha)
24 {
25 	int i, n;
26 	if (colorspace)
27 	{
28 		n = fz_colorspace_n(ctx, colorspace);
29 		fz_write_printf(ctx, out, " colorspace=\"%s\" color=\"", fz_colorspace_name(ctx, colorspace));
30 		for (i = 0; i < n; i++)
31 			fz_write_printf(ctx, out, "%s%g", i == 0 ? "" : " ", color[i]);
32 		fz_write_printf(ctx, out, "\"");
33 	}
34 	if (alpha < 1)
35 		fz_write_printf(ctx, out, " alpha=\"%g\"", alpha);
36 }
37 
38 static void
fz_trace_text_span(fz_context * ctx,fz_output * out,fz_text_span * span,int depth)39 fz_trace_text_span(fz_context *ctx, fz_output *out, fz_text_span *span, int depth)
40 {
41 	int i;
42 	fz_trace_indent(ctx, out, depth);
43 	fz_write_printf(ctx, out, "<span font=\"%s\" wmode=\"%d\" bidi=\"%d\"", fz_font_name(ctx, span->font), span->wmode, span->bidi_level);
44 	fz_write_printf(ctx, out, " trm=\"%g %g %g %g\">\n", span->trm.a, span->trm.b, span->trm.c, span->trm.d);
45 	for (i = 0; i < span->len; i++)
46 	{
47 		int ucs = span->items[i].ucs;
48 		float adv = 0;
49 		if (span->items[i].gid >= 0) {
50 			adv = fz_advance_glyph(ctx, span->font, span->items[i].gid, span->wmode);
51 		}
52 
53 		fz_trace_indent(ctx, out, depth+1);
54 		fz_write_string(ctx, out, "<g");
55 		if (span->items[i].ucs >= 0)
56 		{
57 			fz_write_string(ctx, out, " unicode=\"");
58 			switch (ucs)
59 			{
60 			default:
61 				if (ucs < 32)
62 					fz_write_printf(ctx, out, "&#x%x;", ucs);
63 				else
64 					fz_write_rune(ctx, out, ucs);
65 				break;
66 			case '&': fz_write_string(ctx, out, "&amp;"); break;
67 			case '\'': fz_write_string(ctx, out, "&apos;"); break;
68 			case '"': fz_write_string(ctx, out, "&quot;"); break;
69 			case '<': fz_write_string(ctx, out, "&lt;"); break;
70 			case '>': fz_write_string(ctx, out, "&gt;"); break;
71 			}
72 			fz_write_string(ctx, out, "\"");
73 		}
74 		if (span->items[i].gid >= 0)
75 		{
76 			char name[32];
77 			fz_get_glyph_name(ctx, span->font, span->items[i].gid, name, sizeof name);
78 			fz_write_printf(ctx, out, " glyph=\"%s\"", name);
79 		}
80 
81 		fz_write_printf(ctx, out, " x=\"%g\" y=\"%g\" adv=\"%g\"/>\n", span->items[i].x, span->items[i].y, adv);
82 	}
83 	fz_trace_indent(ctx, out, depth);
84 	fz_write_string(ctx, out, "</span>\n");
85 }
86 
87 static void
fz_trace_text(fz_context * ctx,fz_output * out,const fz_text * text,int depth)88 fz_trace_text(fz_context *ctx, fz_output *out, const fz_text *text, int depth)
89 {
90 	fz_text_span *span;
91 	for (span = text->head; span; span = span->next)
92 		fz_trace_text_span(ctx, out, span, depth);
93 }
94 
95 static void
trace_moveto(fz_context * ctx,void * dev_,float x,float y)96 trace_moveto(fz_context *ctx, void *dev_, float x, float y)
97 {
98 	fz_trace_device *dev = (fz_trace_device*)dev_;
99 	fz_output *out = dev->out;
100 	fz_trace_indent(ctx, out, dev->depth);
101 	fz_write_printf(ctx, out, "<moveto x=\"%g\" y=\"%g\"/>\n", x, y);
102 }
103 
104 static void
trace_lineto(fz_context * ctx,void * dev_,float x,float y)105 trace_lineto(fz_context *ctx, void *dev_, float x, float y)
106 {
107 	fz_trace_device *dev = (fz_trace_device*)dev_;
108 	fz_output *out = dev->out;
109 	fz_trace_indent(ctx, out, dev->depth);
110 	fz_write_printf(ctx, out, "<lineto x=\"%g\" y=\"%g\"/>\n", x, y);
111 }
112 
113 static void
trace_curveto(fz_context * ctx,void * dev_,float x1,float y1,float x2,float y2,float x3,float y3)114 trace_curveto(fz_context *ctx, void *dev_, float x1, float y1, float x2, float y2, float x3, float y3)
115 {
116 	fz_trace_device *dev = (fz_trace_device*)dev_;
117 	fz_output *out = dev->out;
118 	fz_trace_indent(ctx, out, dev->depth);
119 	fz_write_printf(ctx, out, "<curveto x1=\"%g\" y1=\"%g\" x2=\"%g\" y2=\"%g\" x3=\"%g\" y3=\"%g\"/>\n", x1, y1, x2, y2, x3, y3);
120 }
121 
122 static void
trace_close(fz_context * ctx,void * dev_)123 trace_close(fz_context *ctx, void *dev_)
124 {
125 	fz_trace_device *dev = (fz_trace_device*)dev_;
126 	fz_output *out = dev->out;
127 	fz_trace_indent(ctx, out, dev->depth);
128 	fz_write_printf(ctx, out, "<closepath/>\n");
129 }
130 
131 static const fz_path_walker trace_path_walker =
132 {
133 	trace_moveto,
134 	trace_lineto,
135 	trace_curveto,
136 	trace_close
137 };
138 
139 static void
fz_trace_path(fz_context * ctx,fz_trace_device * dev,const fz_path * path)140 fz_trace_path(fz_context *ctx, fz_trace_device *dev, const fz_path *path)
141 {
142 	dev->depth++;
143 	fz_walk_path(ctx, path, &trace_path_walker, dev);
144 	dev->depth--;
145 }
146 
147 static void
fz_trace_fill_path(fz_context * ctx,fz_device * dev_,const fz_path * path,int even_odd,fz_matrix ctm,fz_colorspace * colorspace,const float * color,float alpha,fz_color_params color_params)148 fz_trace_fill_path(fz_context *ctx, fz_device *dev_, const fz_path *path, int even_odd, fz_matrix ctm,
149 	fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
150 {
151 	fz_trace_device *dev = (fz_trace_device*)dev_;
152 	fz_output *out = dev->out;
153 	fz_trace_indent(ctx, out, dev->depth);
154 	fz_write_printf(ctx, out, "<fill_path");
155 	if (even_odd)
156 		fz_write_printf(ctx, out, " winding=\"eofill\"");
157 	else
158 		fz_write_printf(ctx, out, " winding=\"nonzero\"");
159 	fz_trace_color(ctx, out, colorspace, color, alpha);
160 	fz_trace_matrix(ctx, out, ctm);
161 	fz_write_printf(ctx, out, ">\n");
162 	fz_trace_path(ctx, dev, path);
163 	fz_trace_indent(ctx, out, dev->depth);
164 	fz_write_printf(ctx, out, "</fill_path>\n");
165 }
166 
167 static void
fz_trace_stroke_path(fz_context * ctx,fz_device * dev_,const fz_path * path,const fz_stroke_state * stroke,fz_matrix ctm,fz_colorspace * colorspace,const float * color,float alpha,fz_color_params color_params)168 fz_trace_stroke_path(fz_context *ctx, fz_device *dev_, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm,
169 	fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
170 {
171 	fz_trace_device *dev = (fz_trace_device*)dev_;
172 	fz_output *out = dev->out;
173 	int i;
174 
175 	fz_trace_indent(ctx, out, dev->depth);
176 	fz_write_printf(ctx, out, "<stroke_path");
177 	fz_write_printf(ctx, out, " linewidth=\"%g\"", stroke->linewidth);
178 	fz_write_printf(ctx, out, " miterlimit=\"%g\"", stroke->miterlimit);
179 	fz_write_printf(ctx, out, " linecap=\"%d,%d,%d\"", stroke->start_cap, stroke->dash_cap, stroke->end_cap);
180 	fz_write_printf(ctx, out, " linejoin=\"%d\"", stroke->linejoin);
181 
182 	if (stroke->dash_len)
183 	{
184 		fz_write_printf(ctx, out, " dash_phase=\"%g\" dash=\"", stroke->dash_phase);
185 		for (i = 0; i < stroke->dash_len; i++)
186 			fz_write_printf(ctx, out, "%s%g", i > 0 ? " " : "", stroke->dash_list[i]);
187 		fz_write_printf(ctx, out, "\"");
188 	}
189 
190 	fz_trace_color(ctx, out, colorspace, color, alpha);
191 	fz_trace_matrix(ctx, out, ctm);
192 	fz_write_printf(ctx, out, ">\n");
193 
194 	fz_trace_path(ctx, dev, path);
195 
196 	fz_trace_indent(ctx, out, dev->depth);
197 	fz_write_printf(ctx, out, "</stroke_path>\n");
198 }
199 
200 static void
fz_trace_clip_path(fz_context * ctx,fz_device * dev_,const fz_path * path,int even_odd,fz_matrix ctm,fz_rect scissor)201 fz_trace_clip_path(fz_context *ctx, fz_device *dev_, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor)
202 {
203 	fz_trace_device *dev = (fz_trace_device*)dev_;
204 	fz_output *out = dev->out;
205 	fz_trace_indent(ctx, out, dev->depth);
206 	fz_write_printf(ctx, out, "<clip_path");
207 	if (even_odd)
208 		fz_write_printf(ctx, out, " winding=\"eofill\"");
209 	else
210 		fz_write_printf(ctx, out, " winding=\"nonzero\"");
211 	fz_trace_matrix(ctx, out, ctm);
212 	fz_write_printf(ctx, out, ">\n");
213 	fz_trace_path(ctx, dev, path);
214 	fz_trace_indent(ctx, out, dev->depth);
215 	fz_write_printf(ctx, out, "</clip_path>\n");
216 	dev->depth++;
217 }
218 
219 static void
fz_trace_clip_stroke_path(fz_context * ctx,fz_device * dev_,const fz_path * path,const fz_stroke_state * stroke,fz_matrix ctm,fz_rect scissor)220 fz_trace_clip_stroke_path(fz_context *ctx, fz_device *dev_, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
221 {
222 	fz_trace_device *dev = (fz_trace_device*)dev_;
223 	fz_output *out = dev->out;
224 	fz_trace_indent(ctx, out, dev->depth);
225 	fz_write_printf(ctx, out, "<clip_stroke_path");
226 	fz_trace_matrix(ctx, out, ctm);
227 	fz_write_printf(ctx, out, ">\n");
228 	fz_trace_path(ctx, dev, path);
229 	fz_trace_indent(ctx, out, dev->depth);
230 	fz_write_printf(ctx, out, "</clip_stroke_path>\n");
231 	dev->depth++;
232 }
233 
234 static void
fz_trace_fill_text(fz_context * ctx,fz_device * dev_,const fz_text * text,fz_matrix ctm,fz_colorspace * colorspace,const float * color,float alpha,fz_color_params color_params)235 fz_trace_fill_text(fz_context *ctx, fz_device *dev_, const fz_text *text, fz_matrix ctm,
236 	fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
237 {
238 	fz_trace_device *dev = (fz_trace_device*)dev_;
239 	fz_output *out = dev->out;
240 	fz_trace_indent(ctx, out, dev->depth);
241 	fz_write_printf(ctx, out, "<fill_text");
242 	fz_trace_color(ctx, out, colorspace, color, alpha);
243 	fz_trace_matrix(ctx, out, ctm);
244 	fz_write_printf(ctx, out, ">\n");
245 	fz_trace_text(ctx, out, text, dev->depth+1);
246 	fz_trace_indent(ctx, out, dev->depth);
247 	fz_write_printf(ctx, out, "</fill_text>\n");
248 }
249 
250 static void
fz_trace_stroke_text(fz_context * ctx,fz_device * dev_,const fz_text * text,const fz_stroke_state * stroke,fz_matrix ctm,fz_colorspace * colorspace,const float * color,float alpha,fz_color_params color_params)251 fz_trace_stroke_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm,
252 	fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
253 {
254 	fz_trace_device *dev = (fz_trace_device*)dev_;
255 	fz_output *out = dev->out;
256 	fz_trace_indent(ctx, out, dev->depth);
257 	fz_write_printf(ctx, out, "<stroke_text");
258 	fz_trace_color(ctx, out, colorspace, color, alpha);
259 	fz_trace_matrix(ctx, out, ctm);
260 	fz_write_printf(ctx, out, ">\n");
261 	fz_trace_text(ctx, out, text, dev->depth+1);
262 	fz_trace_indent(ctx, out, dev->depth);
263 	fz_write_printf(ctx, out, "</stroke_text>\n");
264 }
265 
266 static void
fz_trace_clip_text(fz_context * ctx,fz_device * dev_,const fz_text * text,fz_matrix ctm,fz_rect scissor)267 fz_trace_clip_text(fz_context *ctx, fz_device *dev_, const fz_text *text, fz_matrix ctm, fz_rect scissor)
268 {
269 	fz_trace_device *dev = (fz_trace_device*)dev_;
270 	fz_output *out = dev->out;
271 	fz_trace_indent(ctx, out, dev->depth);
272 	fz_write_printf(ctx, out, "<clip_text");
273 	fz_trace_matrix(ctx, out, ctm);
274 	fz_write_printf(ctx, out, ">\n");
275 	fz_trace_text(ctx, out, text, dev->depth+1);
276 	fz_trace_indent(ctx, out, dev->depth);
277 	fz_write_printf(ctx, out, "</clip_text>\n");
278 	dev->depth++;
279 }
280 
281 static void
fz_trace_clip_stroke_text(fz_context * ctx,fz_device * dev_,const fz_text * text,const fz_stroke_state * stroke,fz_matrix ctm,fz_rect scissor)282 fz_trace_clip_stroke_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
283 {
284 	fz_trace_device *dev = (fz_trace_device*)dev_;
285 	fz_output *out = dev->out;
286 	fz_trace_indent(ctx, out, dev->depth);
287 	fz_write_printf(ctx, out, "<clip_stroke_text");
288 	fz_trace_matrix(ctx, out, ctm);
289 	fz_write_printf(ctx, out, ">\n");
290 	fz_trace_text(ctx, out, text, dev->depth+1);
291 	fz_trace_indent(ctx, out, dev->depth);
292 	fz_write_printf(ctx, out, "</clip_stroke_text>\n");
293 	dev->depth++;
294 }
295 
296 static void
fz_trace_ignore_text(fz_context * ctx,fz_device * dev_,const fz_text * text,fz_matrix ctm)297 fz_trace_ignore_text(fz_context *ctx, fz_device *dev_, const fz_text *text, fz_matrix ctm)
298 {
299 	fz_trace_device *dev = (fz_trace_device*)dev_;
300 	fz_output *out = dev->out;
301 	fz_trace_indent(ctx, out, dev->depth);
302 	fz_write_printf(ctx, out, "<ignore_text");
303 	fz_trace_matrix(ctx, out, ctm);
304 	fz_write_printf(ctx, out, ">\n");
305 	fz_trace_text(ctx, out, text, dev->depth+1);
306 	fz_trace_indent(ctx, out, dev->depth);
307 	fz_write_printf(ctx, out, "</ignore_text>\n");
308 }
309 
310 static void
fz_trace_fill_image(fz_context * ctx,fz_device * dev_,fz_image * image,fz_matrix ctm,float alpha,fz_color_params color_params)311 fz_trace_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params)
312 {
313 	fz_trace_device *dev = (fz_trace_device*)dev_;
314 	fz_output *out = dev->out;
315 	fz_trace_indent(ctx, out, dev->depth);
316 	fz_write_printf(ctx, out, "<fill_image alpha=\"%g\"", alpha);
317 	if (image->colorspace)
318 		fz_write_printf(ctx, out, " colorspace=\"%s\"", fz_colorspace_name(ctx, image->colorspace));
319 	fz_trace_matrix(ctx, out, ctm);
320 	fz_write_printf(ctx, out, " width=\"%d\" height=\"%d\"", image->w, image->h);
321 	fz_write_printf(ctx, out, "/>\n");
322 }
323 
324 static void
fz_trace_fill_shade(fz_context * ctx,fz_device * dev_,fz_shade * shade,fz_matrix ctm,float alpha,fz_color_params color_params)325 fz_trace_fill_shade(fz_context *ctx, fz_device *dev_, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params)
326 {
327 	fz_trace_device *dev = (fz_trace_device*)dev_;
328 	fz_output *out = dev->out;
329 	fz_trace_indent(ctx, out, dev->depth);
330 	fz_write_printf(ctx, out, "<fill_shade alpha=\"%g\"", alpha);
331 	fz_trace_matrix(ctx, out, ctm);
332 	fz_write_printf(ctx, out, " pattern_matrix=\"%g %g %g %g %g %g\"",
333 		shade->matrix.a,
334 		shade->matrix.b,
335 		shade->matrix.c,
336 		shade->matrix.d,
337 		shade->matrix.e,
338 		shade->matrix.f);
339 	fz_write_printf(ctx, out, " colorspace=\"%s\"", fz_colorspace_name(ctx, shade->colorspace));
340 	// TODO: use_background and background
341 	// TODO: use_function and function
342 	switch (shade->type)
343 	{
344 	case FZ_FUNCTION_BASED:
345 		fz_write_printf(ctx, out, " type=\"function\"");
346 		fz_write_printf(ctx, out, " function_matrix=\"%g %g %g %g %g %g\"",
347 			shade->u.f.matrix.a,
348 			shade->u.f.matrix.b,
349 			shade->u.f.matrix.c,
350 			shade->u.f.matrix.d,
351 			shade->u.f.matrix.e,
352 			shade->u.f.matrix.f);
353 		fz_write_printf(ctx, out, " domain=\"%g %g %g %g\"",
354 			shade->u.f.domain[0][0],
355 			shade->u.f.domain[0][1],
356 			shade->u.f.domain[1][0],
357 			shade->u.f.domain[1][1]);
358 		fz_write_printf(ctx, out, " samples=\"%d %d\"",
359 			shade->u.f.xdivs,
360 			shade->u.f.ydivs);
361 		fz_write_printf(ctx, out, "/>\n");
362 		break;
363 	case FZ_LINEAR:
364 		fz_write_printf(ctx, out, " type=\"linear\"");
365 		fz_write_printf(ctx, out, " extend=\"%d %d\"",
366 			shade->u.l_or_r.extend[0],
367 			shade->u.l_or_r.extend[1]);
368 		fz_write_printf(ctx, out, " start=\"%g %g\"",
369 			shade->u.l_or_r.coords[0][0],
370 			shade->u.l_or_r.coords[0][1]);
371 		fz_write_printf(ctx, out, " end=\"%g %g\"",
372 			shade->u.l_or_r.coords[1][0],
373 			shade->u.l_or_r.coords[1][1]);
374 		fz_write_printf(ctx, out, "/>\n");
375 		break;
376 	case FZ_RADIAL:
377 		fz_write_printf(ctx, out, " type=\"radial\"");
378 		fz_write_printf(ctx, out, " extend=\"%d %d\"",
379 			shade->u.l_or_r.extend[0],
380 			shade->u.l_or_r.extend[1]);
381 		fz_write_printf(ctx, out, " inner=\"%g %g %g\"",
382 			shade->u.l_or_r.coords[0][0],
383 			shade->u.l_or_r.coords[0][1],
384 			shade->u.l_or_r.coords[0][2]);
385 		fz_write_printf(ctx, out, " outer=\"%g %g %g\"",
386 			shade->u.l_or_r.coords[1][0],
387 			shade->u.l_or_r.coords[1][1],
388 			shade->u.l_or_r.coords[1][2]);
389 		fz_write_printf(ctx, out, "/>\n");
390 		break;
391 	default:
392 		fz_write_printf(ctx, out, " type=\"mesh\"/>\n");
393 		break;
394 	}
395 }
396 
397 static void
fz_trace_fill_image_mask(fz_context * ctx,fz_device * dev_,fz_image * image,fz_matrix ctm,fz_colorspace * colorspace,const float * color,float alpha,fz_color_params color_params)398 fz_trace_fill_image_mask(fz_context *ctx, fz_device *dev_, fz_image *image, fz_matrix ctm,
399 	fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
400 {
401 	fz_trace_device *dev = (fz_trace_device*)dev_;
402 	fz_output *out = dev->out;
403 	fz_trace_indent(ctx, out, dev->depth);
404 	fz_write_printf(ctx, out, "<fill_image_mask");
405 	fz_trace_matrix(ctx, out, ctm);
406 	fz_trace_color(ctx, out, colorspace, color, alpha);
407 	fz_write_printf(ctx, out, " width=\"%d\" height=\"%d\"", image->w, image->h);
408 	fz_write_printf(ctx, out, "/>\n");
409 }
410 
411 static void
fz_trace_clip_image_mask(fz_context * ctx,fz_device * dev_,fz_image * image,fz_matrix ctm,fz_rect scissor)412 fz_trace_clip_image_mask(fz_context *ctx, fz_device *dev_, fz_image *image, fz_matrix ctm, fz_rect scissor)
413 {
414 	fz_trace_device *dev = (fz_trace_device*)dev_;
415 	fz_output *out = dev->out;
416 	fz_trace_indent(ctx, out, dev->depth);
417 	fz_write_printf(ctx, out, "<clip_image_mask");
418 	fz_trace_matrix(ctx, out, ctm);
419 	fz_write_printf(ctx, out, " width=\"%d\" height=\"%d\"", image->w, image->h);
420 	fz_write_printf(ctx, out, "/>\n");
421 	dev->depth++;
422 }
423 
424 static void
fz_trace_pop_clip(fz_context * ctx,fz_device * dev_)425 fz_trace_pop_clip(fz_context *ctx, fz_device *dev_)
426 {
427 	fz_trace_device *dev = (fz_trace_device*)dev_;
428 	fz_output *out = dev->out;
429 	dev->depth--;
430 	fz_trace_indent(ctx, out, dev->depth);
431 	fz_write_printf(ctx, out, "<pop_clip/>\n");
432 }
433 
434 static void
fz_trace_begin_mask(fz_context * ctx,fz_device * dev_,fz_rect bbox,int luminosity,fz_colorspace * colorspace,const float * color,fz_color_params color_params)435 fz_trace_begin_mask(fz_context *ctx, fz_device *dev_, fz_rect bbox, int luminosity, fz_colorspace *colorspace, const float *color, fz_color_params color_params)
436 {
437 	fz_trace_device *dev = (fz_trace_device*)dev_;
438 	fz_output *out = dev->out;
439 	fz_trace_indent(ctx, out, dev->depth);
440 	fz_write_printf(ctx, out, "<clip_mask bbox=\"%g %g %g %g\" s=\"%s\"",
441 		bbox.x0, bbox.y0, bbox.x1, bbox.y1,
442 		luminosity ? "luminosity" : "alpha");
443 	fz_write_printf(ctx, out, ">\n");
444 	dev->depth++;
445 }
446 
447 static void
fz_trace_end_mask(fz_context * ctx,fz_device * dev_)448 fz_trace_end_mask(fz_context *ctx, fz_device *dev_)
449 {
450 	fz_trace_device *dev = (fz_trace_device*)dev_;
451 	fz_output *out = dev->out;
452 	dev->depth--;
453 	fz_trace_indent(ctx, out, dev->depth);
454 	fz_write_printf(ctx, out, "</clip_mask>\n");
455 	dev->depth++;
456 }
457 
458 static void
fz_trace_begin_group(fz_context * ctx,fz_device * dev_,fz_rect bbox,fz_colorspace * cs,int isolated,int knockout,int blendmode,float alpha)459 fz_trace_begin_group(fz_context *ctx, fz_device *dev_, fz_rect bbox, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
460 {
461 	fz_trace_device *dev = (fz_trace_device*)dev_;
462 	fz_output *out = dev->out;
463 	fz_trace_indent(ctx, out, dev->depth);
464 	fz_write_printf(ctx, out, "<group bbox=\"%g %g %g %g\" isolated=\"%d\" knockout=\"%d\" blendmode=\"%s\" alpha=\"%g\">\n",
465 		bbox.x0, bbox.y0, bbox.x1, bbox.y1,
466 		isolated, knockout, fz_blendmode_name(blendmode), alpha);
467 	dev->depth++;
468 }
469 
470 static void
fz_trace_end_group(fz_context * ctx,fz_device * dev_)471 fz_trace_end_group(fz_context *ctx, fz_device *dev_)
472 {
473 	fz_trace_device *dev = (fz_trace_device*)dev_;
474 	fz_output *out = dev->out;
475 	dev->depth--;
476 	fz_trace_indent(ctx, out, dev->depth);
477 	fz_write_printf(ctx, out, "</group>\n");
478 }
479 
480 static int
fz_trace_begin_tile(fz_context * ctx,fz_device * dev_,fz_rect area,fz_rect view,float xstep,float ystep,fz_matrix ctm,int id)481 fz_trace_begin_tile(fz_context *ctx, fz_device *dev_, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id)
482 {
483 	fz_trace_device *dev = (fz_trace_device*)dev_;
484 	fz_output *out = dev->out;
485 	fz_trace_indent(ctx, out, dev->depth);
486 	fz_write_printf(ctx, out, "<tile id=\"%d\"", id);
487 	fz_write_printf(ctx, out, " area=\"%g %g %g %g\"", area.x0, area.y0, area.x1, area.y1);
488 	fz_write_printf(ctx, out, " view=\"%g %g %g %g\"", view.x0, view.y0, view.x1, view.y1);
489 	fz_write_printf(ctx, out, " xstep=\"%g\" ystep=\"%g\"", xstep, ystep);
490 	fz_trace_matrix(ctx, out, ctm);
491 	fz_write_printf(ctx, out, ">\n");
492 	dev->depth++;
493 	return 0;
494 }
495 
496 static void
fz_trace_end_tile(fz_context * ctx,fz_device * dev_)497 fz_trace_end_tile(fz_context *ctx, fz_device *dev_)
498 {
499 	fz_trace_device *dev = (fz_trace_device*)dev_;
500 	fz_output *out = dev->out;
501 	dev->depth--;
502 	fz_trace_indent(ctx, out, dev->depth);
503 	fz_write_printf(ctx, out, "</tile>\n");
504 }
505 
506 static void
fz_trace_begin_layer(fz_context * ctx,fz_device * dev_,const char * name)507 fz_trace_begin_layer(fz_context *ctx, fz_device *dev_, const char *name)
508 {
509 	fz_trace_device *dev = (fz_trace_device*)dev_;
510 	fz_output *out = dev->out;
511 	fz_trace_indent(ctx, out, dev->depth);
512 	fz_write_printf(ctx, out, "<layer name=\"%s\"/>\n", name);
513 }
514 
515 static void
fz_trace_end_layer(fz_context * ctx,fz_device * dev_)516 fz_trace_end_layer(fz_context *ctx, fz_device *dev_)
517 {
518 	fz_trace_device *dev = (fz_trace_device*)dev_;
519 	fz_output *out = dev->out;
520 	fz_trace_indent(ctx, out, dev->depth);
521 	fz_write_printf(ctx, out, "<end_layer/>\n");
522 }
523 
524 static void
fz_trace_render_flags(fz_context * ctx,fz_device * dev_,int set,int clear)525 fz_trace_render_flags(fz_context *ctx, fz_device *dev_, int set, int clear)
526 {
527 	fz_trace_device *dev = (fz_trace_device*)dev_;
528 	fz_output *out = dev->out;
529 	fz_trace_indent(ctx, out, dev->depth);
530 	fz_write_printf(ctx, out, "<render_flags set=\"0x%x\" clear=\"0x%x\"/>\n", set, clear);
531 }
532 
533 static void
fz_trace_set_default_colorspaces(fz_context * ctx,fz_device * dev_,fz_default_colorspaces * dcs)534 fz_trace_set_default_colorspaces(fz_context *ctx, fz_device *dev_, fz_default_colorspaces *dcs)
535 {
536 	fz_trace_device *dev = (fz_trace_device*)dev_;
537 	fz_output *out = dev->out;
538 	fz_trace_indent(ctx, out, dev->depth);
539 	fz_write_printf(ctx, out, "<set_default_colorspaces");
540 	fz_write_printf(ctx, out, " gray=\"%s\"", fz_colorspace_name(ctx, fz_default_gray(ctx, dcs)));
541 	fz_write_printf(ctx, out, " rgb=\"%s\"", fz_colorspace_name(ctx, fz_default_rgb(ctx, dcs)));
542 	fz_write_printf(ctx, out, " cmyk=\"%s\"", fz_colorspace_name(ctx, fz_default_cmyk(ctx, dcs)));
543 	fz_write_printf(ctx, out, " oi=\"%s\"/>\n",fz_colorspace_name(ctx, fz_default_output_intent(ctx, dcs)));
544 }
545 
fz_new_trace_device(fz_context * ctx,fz_output * out)546 fz_device *fz_new_trace_device(fz_context *ctx, fz_output *out)
547 {
548 	fz_trace_device *dev = fz_new_derived_device(ctx, fz_trace_device);
549 
550 	dev->super.fill_path = fz_trace_fill_path;
551 	dev->super.stroke_path = fz_trace_stroke_path;
552 	dev->super.clip_path = fz_trace_clip_path;
553 	dev->super.clip_stroke_path = fz_trace_clip_stroke_path;
554 
555 	dev->super.fill_text = fz_trace_fill_text;
556 	dev->super.stroke_text = fz_trace_stroke_text;
557 	dev->super.clip_text = fz_trace_clip_text;
558 	dev->super.clip_stroke_text = fz_trace_clip_stroke_text;
559 	dev->super.ignore_text = fz_trace_ignore_text;
560 
561 	dev->super.fill_shade = fz_trace_fill_shade;
562 	dev->super.fill_image = fz_trace_fill_image;
563 	dev->super.fill_image_mask = fz_trace_fill_image_mask;
564 	dev->super.clip_image_mask = fz_trace_clip_image_mask;
565 
566 	dev->super.pop_clip = fz_trace_pop_clip;
567 
568 	dev->super.begin_mask = fz_trace_begin_mask;
569 	dev->super.end_mask = fz_trace_end_mask;
570 	dev->super.begin_group = fz_trace_begin_group;
571 	dev->super.end_group = fz_trace_end_group;
572 
573 	dev->super.begin_tile = fz_trace_begin_tile;
574 	dev->super.end_tile = fz_trace_end_tile;
575 
576 	dev->super.begin_layer = fz_trace_begin_layer;
577 	dev->super.end_layer = fz_trace_end_layer;
578 
579 	dev->super.render_flags = fz_trace_render_flags;
580 	dev->super.set_default_colorspaces = fz_trace_set_default_colorspaces;
581 
582 	dev->out = out;
583 
584 	return (fz_device*)dev;
585 }
586