trace-device.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. // Copyright (C) 2004-2024 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/fitz.h"
  23. typedef struct
  24. {
  25. fz_device super;
  26. fz_output *out;
  27. int depth;
  28. } fz_trace_device;
  29. static void fz_trace_indent(fz_context *ctx, fz_output *out, int depth)
  30. {
  31. while (depth-- > 0)
  32. fz_write_string(ctx, out, " ");
  33. }
  34. static void
  35. fz_trace_matrix(fz_context *ctx, fz_output *out, fz_matrix ctm)
  36. {
  37. fz_write_printf(ctx, out, " transform=\"%g %g %g %g %g %g\"", ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f);
  38. }
  39. static void
  40. fz_trace_color(fz_context *ctx, fz_output *out, fz_colorspace *colorspace, const float *color, float alpha)
  41. {
  42. int i, n;
  43. if (colorspace)
  44. {
  45. n = fz_colorspace_n(ctx, colorspace);
  46. fz_write_printf(ctx, out, " colorspace=\"%s\" color=\"", fz_colorspace_name(ctx, colorspace));
  47. for (i = 0; i < n; i++)
  48. fz_write_printf(ctx, out, "%s%g", i == 0 ? "" : " ", color[i]);
  49. fz_write_printf(ctx, out, "\"");
  50. }
  51. if (alpha < 1)
  52. fz_write_printf(ctx, out, " alpha=\"%g\"", alpha);
  53. }
  54. static void
  55. fz_trace_color_params(fz_context *ctx, fz_output *out, fz_color_params color_params)
  56. {
  57. fz_write_printf(ctx, out, " ri=\"%d\" bp=\"%d\" op=\"%d\" opm=\"%d\"",
  58. color_params.ri, color_params.bp, color_params.op, color_params.opm);
  59. }
  60. static void
  61. fz_trace_text_span(fz_context *ctx, fz_output *out, fz_text_span *span, int depth)
  62. {
  63. int i;
  64. fz_trace_indent(ctx, out, depth);
  65. fz_write_printf(ctx, out, "<span font=\"%s\" wmode=\"%d\" bidi=\"%d\"", fz_font_name(ctx, span->font), span->wmode, span->bidi_level);
  66. if (span->language != FZ_LANG_UNSET)
  67. {
  68. char text[8];
  69. fz_string_from_text_language(text, span->language);
  70. fz_write_printf(ctx, out, " lang=\"%s\"", text);
  71. }
  72. fz_write_printf(ctx, out, " trm=\"%g %g %g %g\">\n", span->trm.a, span->trm.b, span->trm.c, span->trm.d);
  73. for (i = 0; i < span->len; i++)
  74. {
  75. int ucs = span->items[i].ucs;
  76. fz_trace_indent(ctx, out, depth+1);
  77. fz_write_string(ctx, out, "<g");
  78. if (span->items[i].ucs >= 0)
  79. {
  80. fz_write_string(ctx, out, " unicode=\"");
  81. switch (ucs)
  82. {
  83. default:
  84. if (ucs < 32)
  85. fz_write_printf(ctx, out, "&#x%x;", ucs);
  86. else
  87. fz_write_rune(ctx, out, ucs);
  88. break;
  89. case '&': fz_write_string(ctx, out, "&amp;"); break;
  90. case '\'': fz_write_string(ctx, out, "&apos;"); break;
  91. case '"': fz_write_string(ctx, out, "&quot;"); break;
  92. case '<': fz_write_string(ctx, out, "&lt;"); break;
  93. case '>': fz_write_string(ctx, out, "&gt;"); break;
  94. }
  95. fz_write_string(ctx, out, "\"");
  96. }
  97. if (span->items[i].gid >= 0)
  98. {
  99. char name[32];
  100. fz_get_glyph_name(ctx, span->font, span->items[i].gid, name, sizeof name);
  101. fz_write_printf(ctx, out, " glyph=\"%s\"", name);
  102. }
  103. fz_write_printf(ctx, out, " x=\"%g\" y=\"%g\" adv=\"%g\"/>\n", span->items[i].x, span->items[i].y, span->items[i].adv);
  104. }
  105. fz_trace_indent(ctx, out, depth);
  106. fz_write_string(ctx, out, "</span>\n");
  107. }
  108. static void
  109. fz_trace_text(fz_context *ctx, fz_output *out, const fz_text *text, int depth)
  110. {
  111. fz_text_span *span;
  112. for (span = text->head; span; span = span->next)
  113. fz_trace_text_span(ctx, out, span, depth);
  114. }
  115. static void
  116. trace_moveto(fz_context *ctx, void *dev_, float x, float y)
  117. {
  118. fz_trace_device *dev = (fz_trace_device*)dev_;
  119. fz_output *out = dev->out;
  120. fz_trace_indent(ctx, out, dev->depth);
  121. fz_write_printf(ctx, out, "<moveto x=\"%g\" y=\"%g\"/>\n", x, y);
  122. }
  123. static void
  124. trace_lineto(fz_context *ctx, void *dev_, float x, float y)
  125. {
  126. fz_trace_device *dev = (fz_trace_device*)dev_;
  127. fz_output *out = dev->out;
  128. fz_trace_indent(ctx, out, dev->depth);
  129. fz_write_printf(ctx, out, "<lineto x=\"%g\" y=\"%g\"/>\n", x, y);
  130. }
  131. static void
  132. trace_curveto(fz_context *ctx, void *dev_, float x1, float y1, float x2, float y2, float x3, float y3)
  133. {
  134. fz_trace_device *dev = (fz_trace_device*)dev_;
  135. fz_output *out = dev->out;
  136. fz_trace_indent(ctx, out, dev->depth);
  137. 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);
  138. }
  139. static void
  140. trace_close(fz_context *ctx, void *dev_)
  141. {
  142. fz_trace_device *dev = (fz_trace_device*)dev_;
  143. fz_output *out = dev->out;
  144. fz_trace_indent(ctx, out, dev->depth);
  145. fz_write_printf(ctx, out, "<closepath/>\n");
  146. }
  147. static const fz_path_walker trace_path_walker =
  148. {
  149. trace_moveto,
  150. trace_lineto,
  151. trace_curveto,
  152. trace_close
  153. };
  154. static void
  155. fz_trace_path(fz_context *ctx, fz_trace_device *dev, const fz_path *path)
  156. {
  157. dev->depth++;
  158. fz_walk_path(ctx, path, &trace_path_walker, dev);
  159. dev->depth--;
  160. }
  161. static void
  162. fz_trace_fill_path(fz_context *ctx, fz_device *dev_, const fz_path *path, int even_odd, fz_matrix ctm,
  163. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  164. {
  165. fz_trace_device *dev = (fz_trace_device*)dev_;
  166. fz_output *out = dev->out;
  167. fz_trace_indent(ctx, out, dev->depth);
  168. fz_write_printf(ctx, out, "<fill_path");
  169. if (even_odd)
  170. fz_write_printf(ctx, out, " winding=\"eofill\"");
  171. else
  172. fz_write_printf(ctx, out, " winding=\"nonzero\"");
  173. fz_trace_color(ctx, out, colorspace, color, alpha);
  174. fz_trace_color_params(ctx, out, color_params);
  175. fz_trace_matrix(ctx, out, ctm);
  176. fz_write_printf(ctx, out, ">\n");
  177. fz_trace_path(ctx, dev, path);
  178. fz_trace_indent(ctx, out, dev->depth);
  179. fz_write_printf(ctx, out, "</fill_path>\n");
  180. }
  181. static void
  182. fz_trace_stroke_path(fz_context *ctx, fz_device *dev_, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm,
  183. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  184. {
  185. fz_trace_device *dev = (fz_trace_device*)dev_;
  186. fz_output *out = dev->out;
  187. int i;
  188. fz_trace_indent(ctx, out, dev->depth);
  189. fz_write_printf(ctx, out, "<stroke_path");
  190. fz_write_printf(ctx, out, " linewidth=\"%g\"", stroke->linewidth);
  191. fz_write_printf(ctx, out, " miterlimit=\"%g\"", stroke->miterlimit);
  192. fz_write_printf(ctx, out, " linecap=\"%d,%d,%d\"", stroke->start_cap, stroke->dash_cap, stroke->end_cap);
  193. fz_write_printf(ctx, out, " linejoin=\"%d\"", stroke->linejoin);
  194. if (stroke->dash_len)
  195. {
  196. fz_write_printf(ctx, out, " dash_phase=\"%g\" dash=\"", stroke->dash_phase);
  197. for (i = 0; i < stroke->dash_len; i++)
  198. fz_write_printf(ctx, out, "%s%g", i > 0 ? " " : "", stroke->dash_list[i]);
  199. fz_write_printf(ctx, out, "\"");
  200. }
  201. fz_trace_color(ctx, out, colorspace, color, alpha);
  202. fz_trace_color_params(ctx, out, color_params);
  203. fz_trace_matrix(ctx, out, ctm);
  204. fz_write_printf(ctx, out, ">\n");
  205. fz_trace_path(ctx, dev, path);
  206. fz_trace_indent(ctx, out, dev->depth);
  207. fz_write_printf(ctx, out, "</stroke_path>\n");
  208. }
  209. static void
  210. fz_trace_clip_path(fz_context *ctx, fz_device *dev_, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor)
  211. {
  212. fz_trace_device *dev = (fz_trace_device*)dev_;
  213. fz_output *out = dev->out;
  214. fz_trace_indent(ctx, out, dev->depth);
  215. fz_write_printf(ctx, out, "<clip_path");
  216. if (even_odd)
  217. fz_write_printf(ctx, out, " winding=\"eofill\"");
  218. else
  219. fz_write_printf(ctx, out, " winding=\"nonzero\"");
  220. fz_trace_matrix(ctx, out, ctm);
  221. fz_write_printf(ctx, out, ">\n");
  222. fz_trace_path(ctx, dev, path);
  223. fz_trace_indent(ctx, out, dev->depth);
  224. fz_write_printf(ctx, out, "</clip_path>\n");
  225. dev->depth++;
  226. }
  227. static void
  228. 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)
  229. {
  230. fz_trace_device *dev = (fz_trace_device*)dev_;
  231. fz_output *out = dev->out;
  232. fz_trace_indent(ctx, out, dev->depth);
  233. fz_write_printf(ctx, out, "<clip_stroke_path");
  234. fz_trace_matrix(ctx, out, ctm);
  235. fz_write_printf(ctx, out, ">\n");
  236. fz_trace_path(ctx, dev, path);
  237. fz_trace_indent(ctx, out, dev->depth);
  238. fz_write_printf(ctx, out, "</clip_stroke_path>\n");
  239. dev->depth++;
  240. }
  241. static void
  242. fz_trace_fill_text(fz_context *ctx, fz_device *dev_, const fz_text *text, fz_matrix ctm,
  243. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  244. {
  245. fz_trace_device *dev = (fz_trace_device*)dev_;
  246. fz_output *out = dev->out;
  247. fz_trace_indent(ctx, out, dev->depth);
  248. fz_write_printf(ctx, out, "<fill_text");
  249. fz_trace_color(ctx, out, colorspace, color, alpha);
  250. fz_trace_color_params(ctx, out, color_params);
  251. fz_trace_matrix(ctx, out, ctm);
  252. fz_write_printf(ctx, out, ">\n");
  253. fz_trace_text(ctx, out, text, dev->depth+1);
  254. fz_trace_indent(ctx, out, dev->depth);
  255. fz_write_printf(ctx, out, "</fill_text>\n");
  256. }
  257. static void
  258. fz_trace_stroke_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm,
  259. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  260. {
  261. fz_trace_device *dev = (fz_trace_device*)dev_;
  262. fz_output *out = dev->out;
  263. fz_trace_indent(ctx, out, dev->depth);
  264. fz_write_printf(ctx, out, "<stroke_text");
  265. fz_trace_color(ctx, out, colorspace, color, alpha);
  266. fz_trace_color_params(ctx, out, color_params);
  267. fz_trace_matrix(ctx, out, ctm);
  268. fz_write_printf(ctx, out, ">\n");
  269. fz_trace_text(ctx, out, text, dev->depth+1);
  270. fz_trace_indent(ctx, out, dev->depth);
  271. fz_write_printf(ctx, out, "</stroke_text>\n");
  272. }
  273. static void
  274. fz_trace_clip_text(fz_context *ctx, fz_device *dev_, const fz_text *text, fz_matrix ctm, fz_rect scissor)
  275. {
  276. fz_trace_device *dev = (fz_trace_device*)dev_;
  277. fz_output *out = dev->out;
  278. fz_trace_indent(ctx, out, dev->depth);
  279. fz_write_printf(ctx, out, "<clip_text");
  280. fz_trace_matrix(ctx, out, ctm);
  281. fz_write_printf(ctx, out, ">\n");
  282. fz_trace_text(ctx, out, text, dev->depth+1);
  283. fz_trace_indent(ctx, out, dev->depth);
  284. fz_write_printf(ctx, out, "</clip_text>\n");
  285. dev->depth++;
  286. }
  287. static void
  288. 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)
  289. {
  290. fz_trace_device *dev = (fz_trace_device*)dev_;
  291. fz_output *out = dev->out;
  292. fz_trace_indent(ctx, out, dev->depth);
  293. fz_write_printf(ctx, out, "<clip_stroke_text");
  294. fz_trace_matrix(ctx, out, ctm);
  295. fz_write_printf(ctx, out, ">\n");
  296. fz_trace_text(ctx, out, text, dev->depth+1);
  297. fz_trace_indent(ctx, out, dev->depth);
  298. fz_write_printf(ctx, out, "</clip_stroke_text>\n");
  299. dev->depth++;
  300. }
  301. static void
  302. fz_trace_ignore_text(fz_context *ctx, fz_device *dev_, const fz_text *text, fz_matrix ctm)
  303. {
  304. fz_trace_device *dev = (fz_trace_device*)dev_;
  305. fz_output *out = dev->out;
  306. fz_trace_indent(ctx, out, dev->depth);
  307. fz_write_printf(ctx, out, "<ignore_text");
  308. fz_trace_matrix(ctx, out, ctm);
  309. fz_write_printf(ctx, out, ">\n");
  310. fz_trace_text(ctx, out, text, dev->depth+1);
  311. fz_trace_indent(ctx, out, dev->depth);
  312. fz_write_printf(ctx, out, "</ignore_text>\n");
  313. }
  314. static void
  315. fz_trace_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params)
  316. {
  317. fz_trace_device *dev = (fz_trace_device*)dev_;
  318. fz_output *out = dev->out;
  319. fz_trace_indent(ctx, out, dev->depth);
  320. fz_write_printf(ctx, out, "<fill_image alpha=\"%g\"", alpha);
  321. if (image->colorspace)
  322. fz_write_printf(ctx, out, " colorspace=\"%s\"", fz_colorspace_name(ctx, image->colorspace));
  323. fz_trace_color_params(ctx, out, color_params);
  324. fz_trace_matrix(ctx, out, ctm);
  325. fz_write_printf(ctx, out, " width=\"%d\" height=\"%d\"", image->w, image->h);
  326. fz_write_printf(ctx, out, "/>\n");
  327. }
  328. static void
  329. fz_trace_fill_shade(fz_context *ctx, fz_device *dev_, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params)
  330. {
  331. fz_trace_device *dev = (fz_trace_device*)dev_;
  332. fz_output *out = dev->out;
  333. fz_trace_indent(ctx, out, dev->depth);
  334. fz_write_printf(ctx, out, "<fill_shade alpha=\"%g\"", alpha);
  335. fz_trace_matrix(ctx, out, ctm);
  336. fz_write_printf(ctx, out, " pattern_matrix=\"%g %g %g %g %g %g\"",
  337. shade->matrix.a,
  338. shade->matrix.b,
  339. shade->matrix.c,
  340. shade->matrix.d,
  341. shade->matrix.e,
  342. shade->matrix.f);
  343. fz_write_printf(ctx, out, " colorspace=\"%s\"", fz_colorspace_name(ctx, shade->colorspace));
  344. fz_trace_color_params(ctx, out, color_params);
  345. // TODO: use_background and background
  346. // TODO: use_function and function
  347. switch (shade->type)
  348. {
  349. case FZ_FUNCTION_BASED:
  350. fz_write_printf(ctx, out, " type=\"function\"");
  351. fz_write_printf(ctx, out, " function_matrix=\"%g %g %g %g %g %g\"",
  352. shade->u.f.matrix.a,
  353. shade->u.f.matrix.b,
  354. shade->u.f.matrix.c,
  355. shade->u.f.matrix.d,
  356. shade->u.f.matrix.e,
  357. shade->u.f.matrix.f);
  358. fz_write_printf(ctx, out, " domain=\"%g %g %g %g\"",
  359. shade->u.f.domain[0][0],
  360. shade->u.f.domain[0][1],
  361. shade->u.f.domain[1][0],
  362. shade->u.f.domain[1][1]);
  363. fz_write_printf(ctx, out, " samples=\"%d %d\"",
  364. shade->u.f.xdivs,
  365. shade->u.f.ydivs);
  366. fz_write_printf(ctx, out, "/>\n");
  367. break;
  368. case FZ_LINEAR:
  369. fz_write_printf(ctx, out, " type=\"linear\"");
  370. fz_write_printf(ctx, out, " extend=\"%d %d\"",
  371. shade->u.l_or_r.extend[0],
  372. shade->u.l_or_r.extend[1]);
  373. fz_write_printf(ctx, out, " start=\"%g %g\"",
  374. shade->u.l_or_r.coords[0][0],
  375. shade->u.l_or_r.coords[0][1]);
  376. fz_write_printf(ctx, out, " end=\"%g %g\"",
  377. shade->u.l_or_r.coords[1][0],
  378. shade->u.l_or_r.coords[1][1]);
  379. fz_write_printf(ctx, out, "/>\n");
  380. break;
  381. case FZ_RADIAL:
  382. fz_write_printf(ctx, out, " type=\"radial\"");
  383. fz_write_printf(ctx, out, " extend=\"%d %d\"",
  384. shade->u.l_or_r.extend[0],
  385. shade->u.l_or_r.extend[1]);
  386. fz_write_printf(ctx, out, " inner=\"%g %g %g\"",
  387. shade->u.l_or_r.coords[0][0],
  388. shade->u.l_or_r.coords[0][1],
  389. shade->u.l_or_r.coords[0][2]);
  390. fz_write_printf(ctx, out, " outer=\"%g %g %g\"",
  391. shade->u.l_or_r.coords[1][0],
  392. shade->u.l_or_r.coords[1][1],
  393. shade->u.l_or_r.coords[1][2]);
  394. fz_write_printf(ctx, out, "/>\n");
  395. break;
  396. default:
  397. fz_write_printf(ctx, out, " type=\"mesh\"/>\n");
  398. break;
  399. }
  400. }
  401. static void
  402. fz_trace_fill_image_mask(fz_context *ctx, fz_device *dev_, fz_image *image, fz_matrix ctm,
  403. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  404. {
  405. fz_trace_device *dev = (fz_trace_device*)dev_;
  406. fz_output *out = dev->out;
  407. fz_trace_indent(ctx, out, dev->depth);
  408. fz_write_printf(ctx, out, "<fill_image_mask");
  409. fz_trace_matrix(ctx, out, ctm);
  410. fz_trace_color(ctx, out, colorspace, color, alpha);
  411. fz_trace_color_params(ctx, out, color_params);
  412. fz_write_printf(ctx, out, " width=\"%d\" height=\"%d\"", image->w, image->h);
  413. fz_write_printf(ctx, out, "/>\n");
  414. }
  415. static void
  416. fz_trace_clip_image_mask(fz_context *ctx, fz_device *dev_, fz_image *image, fz_matrix ctm, fz_rect scissor)
  417. {
  418. fz_trace_device *dev = (fz_trace_device*)dev_;
  419. fz_output *out = dev->out;
  420. fz_trace_indent(ctx, out, dev->depth);
  421. fz_write_printf(ctx, out, "<clip_image_mask");
  422. fz_trace_matrix(ctx, out, ctm);
  423. fz_write_printf(ctx, out, " width=\"%d\" height=\"%d\"", image->w, image->h);
  424. fz_write_printf(ctx, out, "/>\n");
  425. dev->depth++;
  426. }
  427. static void
  428. fz_trace_pop_clip(fz_context *ctx, fz_device *dev_)
  429. {
  430. fz_trace_device *dev = (fz_trace_device*)dev_;
  431. fz_output *out = dev->out;
  432. dev->depth--;
  433. fz_trace_indent(ctx, out, dev->depth);
  434. fz_write_printf(ctx, out, "<pop_clip/>\n");
  435. }
  436. static void
  437. 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)
  438. {
  439. fz_trace_device *dev = (fz_trace_device*)dev_;
  440. fz_output *out = dev->out;
  441. fz_trace_indent(ctx, out, dev->depth);
  442. fz_write_printf(ctx, out, "<clip_mask bbox=\"%g %g %g %g\" s=\"%s\"",
  443. bbox.x0, bbox.y0, bbox.x1, bbox.y1,
  444. luminosity ? "luminosity" : "alpha");
  445. fz_trace_color_params(ctx, out, color_params);
  446. fz_write_printf(ctx, out, ">\n");
  447. dev->depth++;
  448. }
  449. static void
  450. fz_trace_end_mask(fz_context *ctx, fz_device *dev_, fz_function *tr)
  451. {
  452. fz_trace_device *dev = (fz_trace_device*)dev_;
  453. fz_output *out = dev->out;
  454. dev->depth--;
  455. fz_trace_indent(ctx, out, dev->depth);
  456. fz_write_printf(ctx, out, "</clip_mask%s>\n", tr ? " (with TR)" : "");
  457. dev->depth++;
  458. }
  459. static void
  460. fz_trace_begin_group(fz_context *ctx, fz_device *dev_, fz_rect bbox, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
  461. {
  462. fz_trace_device *dev = (fz_trace_device*)dev_;
  463. fz_output *out = dev->out;
  464. fz_trace_indent(ctx, out, dev->depth);
  465. fz_write_printf(ctx, out, "<group bbox=\"%g %g %g %g\" isolated=\"%d\" knockout=\"%d\" blendmode=\"%s\" alpha=\"%g\">\n",
  466. bbox.x0, bbox.y0, bbox.x1, bbox.y1,
  467. isolated, knockout, fz_blendmode_name(blendmode), alpha);
  468. dev->depth++;
  469. }
  470. static void
  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. static int
  480. 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. {
  482. fz_trace_device *dev = (fz_trace_device*)dev_;
  483. fz_output *out = dev->out;
  484. fz_trace_indent(ctx, out, dev->depth);
  485. fz_write_printf(ctx, out, "<tile id=\"%d\"", id);
  486. fz_write_printf(ctx, out, " area=\"%g %g %g %g\"", area.x0, area.y0, area.x1, area.y1);
  487. fz_write_printf(ctx, out, " view=\"%g %g %g %g\"", view.x0, view.y0, view.x1, view.y1);
  488. fz_write_printf(ctx, out, " xstep=\"%g\" ystep=\"%g\"", xstep, ystep);
  489. fz_trace_matrix(ctx, out, ctm);
  490. fz_write_printf(ctx, out, ">\n");
  491. dev->depth++;
  492. return 0;
  493. }
  494. static void
  495. fz_trace_end_tile(fz_context *ctx, fz_device *dev_)
  496. {
  497. fz_trace_device *dev = (fz_trace_device*)dev_;
  498. fz_output *out = dev->out;
  499. dev->depth--;
  500. fz_trace_indent(ctx, out, dev->depth);
  501. fz_write_printf(ctx, out, "</tile>\n");
  502. }
  503. static void
  504. fz_trace_begin_layer(fz_context *ctx, fz_device *dev_, const char *name)
  505. {
  506. fz_trace_device *dev = (fz_trace_device*)dev_;
  507. fz_output *out = dev->out;
  508. fz_trace_indent(ctx, out, dev->depth);
  509. fz_write_printf(ctx, out, "<layer name=\"%s\">\n", name ? name : "");
  510. dev->depth++;
  511. }
  512. static void
  513. fz_trace_end_layer(fz_context *ctx, fz_device *dev_)
  514. {
  515. fz_trace_device *dev = (fz_trace_device*)dev_;
  516. fz_output *out = dev->out;
  517. dev->depth--;
  518. fz_trace_indent(ctx, out, dev->depth);
  519. fz_write_printf(ctx, out, "</layer>\n");
  520. }
  521. static void
  522. fz_trace_begin_structure(fz_context *ctx, fz_device *dev_, fz_structure standard, const char *raw, int idx)
  523. {
  524. fz_trace_device *dev = (fz_trace_device*)dev_;
  525. fz_output *out = dev->out;
  526. const char *str = fz_structure_to_string(standard);
  527. fz_trace_indent(ctx, out, dev->depth);
  528. fz_write_printf(ctx, out, "<structure standard=\"%s\"", str);
  529. if (raw && strcmp(str, raw))
  530. fz_write_printf(ctx, out, " raw=\"%s\"", raw);
  531. if (idx != 0)
  532. fz_write_printf(ctx, out, " idx=\"%d\"", idx);
  533. fz_write_printf(ctx, out, ">\n");
  534. dev->depth++;
  535. }
  536. static void
  537. fz_trace_end_structure(fz_context *ctx, fz_device *dev_)
  538. {
  539. fz_trace_device *dev = (fz_trace_device*)dev_;
  540. fz_output *out = dev->out;
  541. dev->depth--;
  542. fz_trace_indent(ctx, out, dev->depth);
  543. fz_write_printf(ctx, out, "</structure>\n");
  544. }
  545. static const char *
  546. metatext_type(fz_metatext meta)
  547. {
  548. switch (meta)
  549. {
  550. case FZ_METATEXT_ABBREVIATION:
  551. return "abbreviation";
  552. case FZ_METATEXT_ACTUALTEXT:
  553. return "actualtext";
  554. case FZ_METATEXT_ALT:
  555. return "alt";
  556. case FZ_METATEXT_TITLE:
  557. return "title";
  558. }
  559. return "????";
  560. }
  561. static void
  562. fz_trace_begin_metatext(fz_context *ctx, fz_device *dev_, fz_metatext meta, const char *txt)
  563. {
  564. fz_trace_device *dev = (fz_trace_device*)dev_;
  565. fz_output *out = dev->out;
  566. const char *type = metatext_type(meta);
  567. fz_trace_indent(ctx, out, dev->depth);
  568. fz_write_printf(ctx, out, "<metatext type=\"%s\" txt=\"%s\">\n", type, txt ? txt : "");
  569. dev->depth++;
  570. }
  571. static void
  572. fz_trace_end_metatext(fz_context *ctx, fz_device *dev_)
  573. {
  574. fz_trace_device *dev = (fz_trace_device*)dev_;
  575. fz_output *out = dev->out;
  576. dev->depth--;
  577. fz_trace_indent(ctx, out, dev->depth);
  578. fz_write_printf(ctx, out, "</metatext>\n");
  579. }
  580. static void
  581. fz_trace_render_flags(fz_context *ctx, fz_device *dev_, int set, int clear)
  582. {
  583. fz_trace_device *dev = (fz_trace_device*)dev_;
  584. fz_output *out = dev->out;
  585. fz_trace_indent(ctx, out, dev->depth);
  586. fz_write_printf(ctx, out, "<render_flags set=\"0x%x\" clear=\"0x%x\"/>\n", set, clear);
  587. }
  588. static void
  589. fz_trace_set_default_colorspaces(fz_context *ctx, fz_device *dev_, fz_default_colorspaces *dcs)
  590. {
  591. fz_trace_device *dev = (fz_trace_device*)dev_;
  592. fz_output *out = dev->out;
  593. fz_trace_indent(ctx, out, dev->depth);
  594. fz_write_printf(ctx, out, "<set_default_colorspaces");
  595. fz_write_printf(ctx, out, " gray=\"%s\"", fz_colorspace_name(ctx, fz_default_gray(ctx, dcs)));
  596. fz_write_printf(ctx, out, " rgb=\"%s\"", fz_colorspace_name(ctx, fz_default_rgb(ctx, dcs)));
  597. fz_write_printf(ctx, out, " cmyk=\"%s\"", fz_colorspace_name(ctx, fz_default_cmyk(ctx, dcs)));
  598. fz_write_printf(ctx, out, " oi=\"%s\"/>\n",fz_colorspace_name(ctx, fz_default_output_intent(ctx, dcs)));
  599. }
  600. fz_device *fz_new_trace_device(fz_context *ctx, fz_output *out)
  601. {
  602. fz_trace_device *dev = fz_new_derived_device(ctx, fz_trace_device);
  603. dev->super.fill_path = fz_trace_fill_path;
  604. dev->super.stroke_path = fz_trace_stroke_path;
  605. dev->super.clip_path = fz_trace_clip_path;
  606. dev->super.clip_stroke_path = fz_trace_clip_stroke_path;
  607. dev->super.fill_text = fz_trace_fill_text;
  608. dev->super.stroke_text = fz_trace_stroke_text;
  609. dev->super.clip_text = fz_trace_clip_text;
  610. dev->super.clip_stroke_text = fz_trace_clip_stroke_text;
  611. dev->super.ignore_text = fz_trace_ignore_text;
  612. dev->super.fill_shade = fz_trace_fill_shade;
  613. dev->super.fill_image = fz_trace_fill_image;
  614. dev->super.fill_image_mask = fz_trace_fill_image_mask;
  615. dev->super.clip_image_mask = fz_trace_clip_image_mask;
  616. dev->super.pop_clip = fz_trace_pop_clip;
  617. dev->super.begin_mask = fz_trace_begin_mask;
  618. dev->super.end_mask = fz_trace_end_mask;
  619. dev->super.begin_group = fz_trace_begin_group;
  620. dev->super.end_group = fz_trace_end_group;
  621. dev->super.begin_tile = fz_trace_begin_tile;
  622. dev->super.end_tile = fz_trace_end_tile;
  623. dev->super.begin_layer = fz_trace_begin_layer;
  624. dev->super.end_layer = fz_trace_end_layer;
  625. dev->super.begin_structure = fz_trace_begin_structure;
  626. dev->super.end_structure = fz_trace_end_structure;
  627. dev->super.begin_metatext = fz_trace_begin_metatext;
  628. dev->super.end_metatext = fz_trace_end_metatext;
  629. dev->super.render_flags = fz_trace_render_flags;
  630. dev->super.set_default_colorspaces = fz_trace_set_default_colorspaces;
  631. dev->out = out;
  632. return (fz_device*)dev;
  633. }