list-device.c 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124
  1. // Copyright (C) 2004-2025 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. #include <assert.h>
  24. #include <string.h>
  25. #define STACK_SIZE 96
  26. typedef enum
  27. {
  28. FZ_CMD_FILL_PATH,
  29. FZ_CMD_STROKE_PATH,
  30. FZ_CMD_CLIP_PATH,
  31. FZ_CMD_CLIP_STROKE_PATH,
  32. FZ_CMD_FILL_TEXT,
  33. FZ_CMD_STROKE_TEXT,
  34. FZ_CMD_CLIP_TEXT,
  35. FZ_CMD_CLIP_STROKE_TEXT,
  36. FZ_CMD_IGNORE_TEXT,
  37. FZ_CMD_FILL_SHADE,
  38. FZ_CMD_FILL_IMAGE,
  39. FZ_CMD_FILL_IMAGE_MASK,
  40. FZ_CMD_CLIP_IMAGE_MASK,
  41. FZ_CMD_POP_CLIP,
  42. FZ_CMD_BEGIN_MASK,
  43. FZ_CMD_END_MASK,
  44. FZ_CMD_BEGIN_GROUP,
  45. FZ_CMD_END_GROUP,
  46. FZ_CMD_BEGIN_TILE,
  47. FZ_CMD_END_TILE,
  48. FZ_CMD_RENDER_FLAGS,
  49. FZ_CMD_DEFAULT_COLORSPACES,
  50. FZ_CMD_BEGIN_LAYER,
  51. FZ_CMD_END_LAYER,
  52. FZ_CMD_BEGIN_STRUCTURE,
  53. FZ_CMD_END_STRUCTURE,
  54. FZ_CMD_BEGIN_METATEXT,
  55. FZ_CMD_END_METATEXT
  56. } fz_display_command;
  57. /* The display list is a list of nodes.
  58. * Each node is a structure consisting of a bitfield (that packs into a
  59. * 32 bit word).
  60. * The different fields in the bitfield identify what information is
  61. * present in the node.
  62. *
  63. * cmd: What type of node this is.
  64. *
  65. * size: The number of sizeof(fz_display_node) bytes that this node's
  66. * data occupies. (i.e. &node[size] = the next node in the
  67. * chain; 0 for end of list).
  68. *
  69. * At 9 bits for this field, and 4 bytes for a node, this means
  70. * the largest node can span 511*4 bytes. We therefore reserve
  71. * 511 as a special value to mean that the actual size for the
  72. * node is given in an (unaligned!) size_t following the node
  73. * before the rest of the data.
  74. *
  75. * rect: 0 for unchanged, 1 for present.
  76. *
  77. * path: 0 for unchanged, 1 for present.
  78. *
  79. * cs: 0 for unchanged
  80. * 1 for devicegray (color defaults to 0)
  81. * 2 for devicegray (color defaults to 1)
  82. * 3 for devicergb (color defaults to 0,0,0)
  83. * 4 for devicergb (color defaults to 1,1,1)
  84. * 5 for devicecmyk (color defaults to 0,0,0,0)
  85. * 6 for devicecmyk (color defaults to 0,0,0,1)
  86. * 7 for present (color defaults to 0)
  87. *
  88. * color: 0 for unchanged color, 1 for present.
  89. *
  90. * alpha: 0 for unchanged, 1 for solid, 2 for transparent, 3
  91. * for alpha value present.
  92. *
  93. * ctm: 0 for unchanged,
  94. * 1 for change ad
  95. * 2 for change bc
  96. * 4 for change ef.
  97. *
  98. * stroke: 0 for unchanged, 1 for present.
  99. *
  100. * flags: Flags (node specific meanings)
  101. *
  102. * Nodes are packed in the order:
  103. * header, rect, colorspace, color, alpha, ctm, stroke_state, path, private data.
  104. */
  105. typedef struct
  106. {
  107. unsigned int cmd : 5;
  108. unsigned int size : 9;
  109. unsigned int rect : 1;
  110. unsigned int path : 1;
  111. unsigned int cs : 3;
  112. unsigned int color : 1;
  113. unsigned int alpha : 2;
  114. unsigned int ctm : 3;
  115. unsigned int stroke : 1;
  116. unsigned int flags : 6;
  117. } fz_display_node;
  118. enum {
  119. CS_UNCHANGED = 0,
  120. CS_GRAY_0 = 1,
  121. CS_GRAY_1 = 2,
  122. CS_RGB_0 = 3,
  123. CS_RGB_1 = 4,
  124. CS_CMYK_0 = 5,
  125. CS_CMYK_1 = 6,
  126. CS_OTHER_0 = 7,
  127. ALPHA_UNCHANGED = 0,
  128. ALPHA_1 = 1,
  129. ALPHA_0 = 2,
  130. ALPHA_PRESENT = 3,
  131. CTM_UNCHANGED = 0,
  132. CTM_CHANGE_AD = 1,
  133. CTM_CHANGE_BC = 2,
  134. CTM_CHANGE_EF = 4,
  135. INDIRECT_NODE_THRESHOLD = (1<<9)-1
  136. };
  137. struct fz_display_list
  138. {
  139. fz_storable storable;
  140. fz_display_node *list;
  141. fz_rect mediabox;
  142. size_t max;
  143. size_t len;
  144. };
  145. typedef struct
  146. {
  147. fz_device super;
  148. fz_display_list *list;
  149. fz_path *path;
  150. float alpha;
  151. fz_matrix ctm;
  152. fz_stroke_state *stroke;
  153. fz_colorspace *colorspace;
  154. fz_color_params *color_params;
  155. float color[FZ_MAX_COLORS];
  156. fz_rect rect;
  157. int top;
  158. struct {
  159. fz_rect *update;
  160. fz_rect rect;
  161. } stack[STACK_SIZE];
  162. int tiled;
  163. } fz_list_device;
  164. enum { ISOLATED = 1, KNOCKOUT = 2 };
  165. enum { OPM = 1, OP = 2, BP = 3, RI = 4};
  166. #define SIZE_IN_NODES(t) \
  167. ((t + sizeof(fz_display_node) - 1) / sizeof(fz_display_node))
  168. /* The display list node are 32bit aligned. For some architectures we
  169. * need to pad to 64bit for pointers. We allow for that here. */
  170. static void pad_size_for_pointer(const fz_display_list *list, size_t *size)
  171. {
  172. /* list->len and size are both counting in nodes, not bytes.
  173. * Nodes are consistently 32bit things, hence we are looking
  174. * for even/odd for "8 byte aligned or not". */
  175. if (FZ_POINTER_ALIGN_MOD <= 4)
  176. return;
  177. /* Otherwise, ensure we're on an even boundary. */
  178. if (FZ_POINTER_ALIGN_MOD == 8)
  179. {
  180. if ((list->len + (*size)) & 1)
  181. (*size)++;
  182. } else
  183. (*size) = ((list->len + (*size) + (FZ_POINTER_ALIGN_MOD>>2) - 1) & ~((FZ_POINTER_ALIGN_MOD>>2)-1)) - list->len;
  184. }
  185. static void align_node_for_pointer(fz_display_node **node)
  186. {
  187. intptr_t ptr;
  188. if (FZ_POINTER_ALIGN_MOD <= 4)
  189. return;
  190. ptr = (intptr_t)*node;
  191. if (FZ_POINTER_ALIGN_MOD == 8)
  192. {
  193. if (ptr & 4)
  194. (*node) = (fz_display_node *)(ptr+4);
  195. }
  196. else
  197. (*node) = (fz_display_node *)((ptr + FZ_POINTER_ALIGN_MOD - 1) & ~(FZ_POINTER_ALIGN_MOD-1));
  198. }
  199. static int
  200. cmd_needs_alignment(fz_display_command cmd)
  201. {
  202. return (cmd == FZ_CMD_FILL_TEXT ||
  203. cmd == FZ_CMD_STROKE_TEXT ||
  204. cmd == FZ_CMD_CLIP_TEXT ||
  205. cmd == FZ_CMD_CLIP_STROKE_TEXT ||
  206. cmd == FZ_CMD_IGNORE_TEXT ||
  207. cmd == FZ_CMD_FILL_SHADE ||
  208. cmd == FZ_CMD_FILL_IMAGE ||
  209. cmd == FZ_CMD_FILL_IMAGE_MASK ||
  210. cmd == FZ_CMD_CLIP_IMAGE_MASK ||
  211. cmd == FZ_CMD_END_MASK ||
  212. cmd == FZ_CMD_DEFAULT_COLORSPACES);
  213. }
  214. static unsigned char *
  215. fz_append_display_node(
  216. fz_context *ctx,
  217. fz_device *dev,
  218. fz_display_command cmd,
  219. int flags,
  220. const fz_rect *rect,
  221. const fz_path *path,
  222. const float *color,
  223. fz_colorspace *colorspace,
  224. const float *alpha,
  225. const fz_matrix *ctm,
  226. const fz_stroke_state *stroke,
  227. const void *private_data,
  228. size_t private_data_len)
  229. {
  230. fz_display_node node = { 0 };
  231. fz_display_node *node_ptr;
  232. fz_list_device *writer = (fz_list_device *)dev;
  233. fz_display_list *list = writer->list;
  234. size_t size;
  235. size_t rect_off = 0;
  236. size_t path_off = 0;
  237. size_t color_off = 0;
  238. size_t colorspace_off = 0;
  239. size_t alpha_off = 0;
  240. size_t ctm_off = 0;
  241. size_t stroke_off = 0;
  242. int rect_for_updates = 0;
  243. size_t private_off = 0;
  244. fz_path *my_path = NULL;
  245. fz_stroke_state *my_stroke = NULL;
  246. fz_rect local_rect;
  247. size_t path_size = 0;
  248. unsigned char *out_private = NULL;
  249. switch (cmd)
  250. {
  251. case FZ_CMD_CLIP_PATH:
  252. case FZ_CMD_CLIP_STROKE_PATH:
  253. case FZ_CMD_CLIP_TEXT:
  254. case FZ_CMD_CLIP_STROKE_TEXT:
  255. case FZ_CMD_CLIP_IMAGE_MASK:
  256. if (writer->top < STACK_SIZE)
  257. {
  258. rect_for_updates = 1;
  259. writer->stack[writer->top].rect = fz_empty_rect;
  260. }
  261. writer->top++;
  262. break;
  263. case FZ_CMD_END_MASK:
  264. if (writer->top < STACK_SIZE)
  265. {
  266. writer->stack[writer->top].update = NULL;
  267. writer->stack[writer->top].rect = fz_empty_rect;
  268. }
  269. writer->top++;
  270. break;
  271. case FZ_CMD_BEGIN_TILE:
  272. writer->tiled++;
  273. if (writer->top > 0 && writer->top <= STACK_SIZE)
  274. {
  275. writer->stack[writer->top-1].rect = fz_infinite_rect;
  276. }
  277. break;
  278. case FZ_CMD_END_TILE:
  279. writer->tiled--;
  280. break;
  281. case FZ_CMD_END_GROUP:
  282. break;
  283. case FZ_CMD_POP_CLIP:
  284. if (writer->top > STACK_SIZE)
  285. {
  286. writer->top--;
  287. rect = &fz_infinite_rect;
  288. }
  289. else if (writer->top > 0)
  290. {
  291. fz_rect *update;
  292. writer->top--;
  293. update = writer->stack[writer->top].update;
  294. if (writer->tiled == 0)
  295. {
  296. if (update)
  297. {
  298. *update = fz_intersect_rect(*update, writer->stack[writer->top].rect);
  299. local_rect = *update;
  300. rect = &local_rect;
  301. }
  302. else
  303. rect = &writer->stack[writer->top].rect;
  304. }
  305. else
  306. rect = &fz_infinite_rect;
  307. }
  308. /* fallthrough */
  309. default:
  310. if (writer->top > 0 && writer->tiled == 0 && writer->top <= STACK_SIZE && rect)
  311. writer->stack[writer->top-1].rect = fz_union_rect(writer->stack[writer->top-1].rect, *rect);
  312. break;
  313. }
  314. size = 1; /* 1 for the fz_display_node */
  315. node.cmd = cmd;
  316. /* Figure out what we need to write, and the offsets at which we will
  317. * write it. */
  318. if (rect_for_updates || (rect != NULL && (writer->rect.x0 != rect->x0 || writer->rect.y0 != rect->y0 || writer->rect.x1 != rect->x1 || writer->rect.y1 != rect->y1)))
  319. {
  320. node.rect = 1;
  321. rect_off = size;
  322. size += SIZE_IN_NODES(sizeof(fz_rect));
  323. }
  324. if (color == NULL)
  325. {
  326. if (colorspace)
  327. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Colorspace cannot be specified without color.");
  328. }
  329. else
  330. {
  331. if (colorspace != writer->colorspace)
  332. {
  333. if (colorspace == fz_device_gray(ctx))
  334. {
  335. if (color[0] == 0.0f)
  336. node.cs = CS_GRAY_0, color = NULL;
  337. else
  338. {
  339. node.cs = CS_GRAY_1;
  340. if (color[0] == 1.0f)
  341. color = NULL;
  342. }
  343. }
  344. else if (colorspace == fz_device_rgb(ctx))
  345. {
  346. if (color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f)
  347. node.cs = CS_RGB_0, color = NULL;
  348. else
  349. {
  350. node.cs = CS_RGB_1;
  351. if (color[0] == 1.0f && color[1] == 1.0f && color[2] == 1.0f)
  352. color = NULL;
  353. }
  354. }
  355. else if (colorspace == fz_device_cmyk(ctx))
  356. {
  357. node.cs = CS_CMYK_0;
  358. if (color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f)
  359. {
  360. if (color[3] == 0.0f)
  361. color = NULL;
  362. else
  363. {
  364. node.cs = CS_CMYK_1;
  365. if (color[3] == 1.0f)
  366. color = NULL;
  367. }
  368. }
  369. }
  370. else
  371. {
  372. int i;
  373. int n = fz_colorspace_n(ctx, colorspace);
  374. pad_size_for_pointer(list, &size);
  375. colorspace_off = size;
  376. size += SIZE_IN_NODES(sizeof(fz_colorspace *));
  377. node.cs = CS_OTHER_0;
  378. for (i = 0; i < n; i++)
  379. if (color[i] != 0.0f)
  380. break;
  381. if (i == n)
  382. color = NULL;
  383. memset(writer->color, 0, sizeof(float)*n);
  384. }
  385. }
  386. else
  387. {
  388. /* Colorspace is unchanged, but color may have changed
  389. * to something best coded as a colorspace change */
  390. if (colorspace == fz_device_gray(ctx))
  391. {
  392. if (writer->color[0] != color[0])
  393. {
  394. if (color[0] == 0.0f)
  395. {
  396. node.cs = CS_GRAY_0;
  397. color = NULL;
  398. }
  399. else if (color[0] == 1.0f)
  400. {
  401. node.cs = CS_GRAY_1;
  402. color = NULL;
  403. }
  404. }
  405. }
  406. else if (colorspace == fz_device_rgb(ctx))
  407. {
  408. if (writer->color[0] != color[0] || writer->color[1] != color[1] || writer->color[2] != color[2])
  409. {
  410. if (color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f)
  411. {
  412. node.cs = CS_RGB_0;
  413. color = NULL;
  414. }
  415. else if (color[0] == 1.0f && color[1] == 1.0f && color[2] == 1.0f)
  416. {
  417. node.cs = CS_RGB_1;
  418. color = NULL;
  419. }
  420. }
  421. }
  422. else if (colorspace == fz_device_cmyk(ctx))
  423. {
  424. if (writer->color[0] != color[0] || writer->color[1] != color[1] || writer->color[2] != color[2] || writer->color[3] != color[3])
  425. {
  426. if (color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f)
  427. {
  428. if (color[3] == 0.0f)
  429. {
  430. node.cs = CS_CMYK_0;
  431. color = NULL;
  432. }
  433. else if (color[3] == 1.0f)
  434. {
  435. node.cs = CS_CMYK_1;
  436. color = NULL;
  437. }
  438. }
  439. }
  440. }
  441. else
  442. {
  443. int i;
  444. int n = fz_colorspace_n(ctx, colorspace);
  445. for (i=0; i < n; i++)
  446. if (color[i] != 0.0f)
  447. break;
  448. if (i == n)
  449. {
  450. node.cs = CS_OTHER_0;
  451. pad_size_for_pointer(list, &size);
  452. colorspace_off = size;
  453. size += SIZE_IN_NODES(sizeof(fz_colorspace *));
  454. color = NULL;
  455. }
  456. }
  457. }
  458. }
  459. if (color)
  460. {
  461. int i, n;
  462. const float *wc = &writer->color[0];
  463. assert(colorspace != NULL);
  464. n = fz_colorspace_n(ctx, colorspace);
  465. i = 0;
  466. /* Only check colors if the colorspace is unchanged. If the
  467. * colorspace *has* changed and the colors are implicit then
  468. * this will have been caught above. */
  469. if (colorspace == writer->colorspace)
  470. for (; i < n; i++)
  471. if (color[i] != wc[i])
  472. break;
  473. if (i != n)
  474. {
  475. node.color = 1;
  476. color_off = size;
  477. size += n * SIZE_IN_NODES(sizeof(float));
  478. }
  479. }
  480. if (alpha && (*alpha != writer->alpha))
  481. {
  482. if (*alpha >= 1.0f)
  483. node.alpha = ALPHA_1;
  484. else if (*alpha <= 0.0f)
  485. node.alpha = ALPHA_0;
  486. else
  487. {
  488. alpha_off = size;
  489. size += SIZE_IN_NODES(sizeof(float));
  490. node.alpha = ALPHA_PRESENT;
  491. }
  492. }
  493. if (ctm && (ctm->a != writer->ctm.a || ctm->b != writer->ctm.b || ctm->c != writer->ctm.c || ctm->d != writer->ctm.d || ctm->e != writer->ctm.e || ctm->f != writer->ctm.f))
  494. {
  495. int ctm_flags;
  496. ctm_off = size;
  497. ctm_flags = CTM_UNCHANGED;
  498. if (ctm->a != writer->ctm.a || ctm->d != writer->ctm.d)
  499. ctm_flags = CTM_CHANGE_AD, size += SIZE_IN_NODES(2*sizeof(float));
  500. if (ctm->b != writer->ctm.b || ctm->c != writer->ctm.c)
  501. ctm_flags |= CTM_CHANGE_BC, size += SIZE_IN_NODES(2*sizeof(float));
  502. if (ctm->e != writer->ctm.e || ctm->f != writer->ctm.f)
  503. ctm_flags |= CTM_CHANGE_EF, size += SIZE_IN_NODES(2*sizeof(float));
  504. node.ctm = ctm_flags;
  505. }
  506. if (stroke && (writer->stroke == NULL || !fz_stroke_state_eq(ctx, stroke, writer->stroke)))
  507. {
  508. pad_size_for_pointer(list, &size);
  509. stroke_off = size;
  510. size += SIZE_IN_NODES(sizeof(fz_stroke_state *));
  511. node.stroke = 1;
  512. }
  513. if (path && (writer->path == NULL || path != writer->path))
  514. {
  515. pad_size_for_pointer(list, &size);
  516. path_size = SIZE_IN_NODES(fz_pack_path(ctx, NULL, path));
  517. node.path = 1;
  518. path_off = size;
  519. size += path_size;
  520. }
  521. if (private_data_len)
  522. {
  523. if (cmd_needs_alignment(cmd))
  524. pad_size_for_pointer(list, &size);
  525. private_off = size;
  526. size += SIZE_IN_NODES(private_data_len);
  527. }
  528. /* If the size is more than 511, then we can't signal that in 9 bits,
  529. * so we'll send it as 511, and then put an extra size_t with the
  530. * size in. */
  531. if (size >= INDIRECT_NODE_THRESHOLD)
  532. size += SIZE_IN_NODES(sizeof(size_t));
  533. while (list->len + size > list->max)
  534. {
  535. size_t newsize = list->max * 2;
  536. fz_display_node *old = list->list;
  537. ptrdiff_t diff;
  538. int i, n;
  539. if (newsize < 256)
  540. newsize = 256;
  541. list->list = fz_realloc_array(ctx, list->list, newsize, fz_display_node);
  542. list->max = newsize;
  543. diff = (char *)(list->list) - (char *)old;
  544. n = (writer->top < STACK_SIZE ? writer->top : STACK_SIZE);
  545. for (i = 0; i < n; i++)
  546. {
  547. if (writer->stack[i].update != NULL)
  548. writer->stack[i].update = (fz_rect *)(((char *)writer->stack[i].update) + diff);
  549. }
  550. if (writer->path)
  551. writer->path = (fz_path *)(((char *)writer->path) + diff);
  552. }
  553. /* Write the node to the list */
  554. if (size >= INDIRECT_NODE_THRESHOLD)
  555. node.size = INDIRECT_NODE_THRESHOLD;
  556. else
  557. node.size = (unsigned int)size;
  558. node.flags = flags;
  559. node_ptr = &list->list[list->len];
  560. *node_ptr = node;
  561. /* Insert the explicit size (unaligned) if required. */
  562. if (size >= INDIRECT_NODE_THRESHOLD)
  563. {
  564. memcpy(&node_ptr[1], &size, sizeof(size));
  565. node_ptr += SIZE_IN_NODES(sizeof(size_t));
  566. }
  567. /* Path is the most frequent one, so try to avoid the try/catch in
  568. * this case */
  569. if (path_off)
  570. {
  571. my_path = (void *)(&node_ptr[path_off]);
  572. (void)fz_pack_path(ctx, (void *)my_path, path);
  573. }
  574. if (stroke_off)
  575. {
  576. fz_try(ctx)
  577. {
  578. my_stroke = fz_clone_stroke_state(ctx, stroke);
  579. }
  580. fz_catch(ctx)
  581. {
  582. fz_drop_path(ctx, my_path);
  583. fz_rethrow(ctx);
  584. }
  585. }
  586. if (rect_off)
  587. {
  588. fz_rect *out_rect = (fz_rect *)(void *)(&node_ptr[rect_off]);
  589. writer->rect = *rect;
  590. *out_rect = *rect;
  591. if (rect_for_updates)
  592. writer->stack[writer->top-1].update = out_rect;
  593. }
  594. if (path_off)
  595. {
  596. fz_drop_path(ctx, writer->path);
  597. writer->path = fz_keep_path(ctx, my_path); /* Can never fail */
  598. }
  599. if (node.cs)
  600. {
  601. fz_drop_colorspace(ctx, writer->colorspace);
  602. switch(node.cs)
  603. {
  604. case CS_GRAY_0:
  605. writer->colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
  606. writer->color[0] = 0;
  607. break;
  608. case CS_GRAY_1:
  609. writer->colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
  610. writer->color[0] = 1;
  611. break;
  612. case CS_RGB_0:
  613. writer->color[0] = 0;
  614. writer->color[1] = 0;
  615. writer->color[2] = 0;
  616. writer->colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
  617. break;
  618. case CS_RGB_1:
  619. writer->color[0] = 1;
  620. writer->color[1] = 1;
  621. writer->color[2] = 1;
  622. writer->colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
  623. break;
  624. case CS_CMYK_0:
  625. writer->color[0] = 0;
  626. writer->color[1] = 0;
  627. writer->color[2] = 0;
  628. writer->color[3] = 0;
  629. writer->colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
  630. break;
  631. case CS_CMYK_1:
  632. writer->color[0] = 0;
  633. writer->color[1] = 0;
  634. writer->color[2] = 0;
  635. writer->color[3] = 1;
  636. writer->colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
  637. break;
  638. default:
  639. {
  640. fz_colorspace **out_colorspace = (fz_colorspace **)(void *)(&node_ptr[colorspace_off]);
  641. int i, n;
  642. n = fz_colorspace_n(ctx, colorspace);
  643. *out_colorspace = fz_keep_colorspace(ctx, colorspace);
  644. writer->colorspace = fz_keep_colorspace(ctx, colorspace);
  645. for (i = 0; i < n; i++)
  646. writer->color[i] = 0;
  647. break;
  648. }
  649. }
  650. }
  651. if (color_off)
  652. {
  653. int n = fz_colorspace_n(ctx, colorspace);
  654. float *out_color = (float *)(void *)(&node_ptr[color_off]);
  655. memcpy(writer->color, color, n * sizeof(float));
  656. memcpy(out_color, color, n * sizeof(float));
  657. }
  658. if (node.alpha)
  659. {
  660. writer->alpha = *alpha;
  661. if (alpha_off)
  662. {
  663. float *out_alpha = (float *)(void *)(&node_ptr[alpha_off]);
  664. *out_alpha = *alpha;
  665. }
  666. }
  667. if (ctm_off)
  668. {
  669. float *out_ctm = (float *)(void *)(&node_ptr[ctm_off]);
  670. if (node.ctm & CTM_CHANGE_AD)
  671. {
  672. writer->ctm.a = *out_ctm++ = ctm->a;
  673. writer->ctm.d = *out_ctm++ = ctm->d;
  674. }
  675. if (node.ctm & CTM_CHANGE_BC)
  676. {
  677. writer->ctm.b = *out_ctm++ = ctm->b;
  678. writer->ctm.c = *out_ctm++ = ctm->c;
  679. }
  680. if (node.ctm & CTM_CHANGE_EF)
  681. {
  682. writer->ctm.e = *out_ctm++ = ctm->e;
  683. writer->ctm.f = *out_ctm = ctm->f;
  684. }
  685. }
  686. if (stroke_off)
  687. {
  688. fz_stroke_state **out_stroke = (fz_stroke_state **)(void *)(&node_ptr[stroke_off]);
  689. *out_stroke = my_stroke;
  690. fz_drop_stroke_state(ctx, writer->stroke);
  691. /* Can never fail as my_stroke was cloned above */
  692. writer->stroke = fz_keep_stroke_state(ctx, my_stroke);
  693. }
  694. if (private_data_len)
  695. {
  696. out_private = (unsigned char *)(void *)(&node_ptr[private_off]);
  697. if (private_data)
  698. memcpy(out_private, private_data, private_data_len);
  699. }
  700. list->len += size;
  701. return out_private;
  702. }
  703. /* Pack ri, op, opm, bp into flags upper bits, even/odd in lower bit */
  704. static int
  705. fz_pack_color_params(fz_color_params color_params)
  706. {
  707. int flags = 0;
  708. flags |= color_params.ri << RI; /* 2 bits */
  709. flags |= color_params.bp << BP;
  710. flags |= color_params.op << OP;
  711. flags |= color_params.opm << OPM;
  712. return flags;
  713. }
  714. /* unpack ri, op, opm, bp from flags, even/odd in lower bit */
  715. static void
  716. fz_unpack_color_params(fz_color_params *color_params, int flags)
  717. {
  718. color_params->ri = (flags >> RI) & 3;
  719. color_params->bp = (flags >> BP) & 1;
  720. color_params->op = (flags >> OP) & 1;
  721. color_params->opm = (flags >> OPM) & 1;
  722. }
  723. static void
  724. fz_list_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm,
  725. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  726. {
  727. fz_rect rect = fz_bound_path(ctx, path, NULL, ctm);
  728. fz_append_display_node(
  729. ctx,
  730. dev,
  731. FZ_CMD_FILL_PATH,
  732. even_odd | fz_pack_color_params(color_params), /* flags */
  733. &rect,
  734. path, /* path */
  735. color,
  736. colorspace,
  737. &alpha, /* alpha */
  738. &ctm,
  739. NULL, /* stroke_state */
  740. NULL, /* private_data */
  741. 0); /* private_data_len */
  742. }
  743. static void
  744. fz_list_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke,
  745. fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  746. {
  747. fz_rect rect = fz_bound_path(ctx, path, stroke, ctm);
  748. fz_append_display_node(
  749. ctx,
  750. dev,
  751. FZ_CMD_STROKE_PATH,
  752. fz_pack_color_params(color_params), /* flags */
  753. &rect,
  754. path, /* path */
  755. color,
  756. colorspace,
  757. &alpha, /* alpha */
  758. &ctm, /* ctm */
  759. stroke,
  760. NULL, /* private_data */
  761. 0); /* private_data_len */
  762. }
  763. static void
  764. fz_list_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor)
  765. {
  766. fz_rect rect = fz_bound_path(ctx, path, NULL, ctm);
  767. rect = fz_intersect_rect(rect, scissor);
  768. fz_append_display_node(
  769. ctx,
  770. dev,
  771. FZ_CMD_CLIP_PATH,
  772. even_odd, /* flags */
  773. &rect,
  774. path, /* path */
  775. NULL, /* color */
  776. NULL, /* colorspace */
  777. NULL, /* alpha */
  778. &ctm, /* ctm */
  779. NULL, /* stroke */
  780. NULL, /* private_data */
  781. 0); /* private_data_len */
  782. }
  783. static void
  784. fz_list_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
  785. {
  786. fz_rect rect = fz_bound_path(ctx, path, stroke, ctm);
  787. rect = fz_intersect_rect(rect, scissor);
  788. fz_append_display_node(
  789. ctx,
  790. dev,
  791. FZ_CMD_CLIP_STROKE_PATH,
  792. 0, /* flags */
  793. &rect,
  794. path, /* path */
  795. NULL, /* color */
  796. NULL, /* colorspace */
  797. NULL, /* alpha */
  798. &ctm, /* ctm */
  799. stroke, /* stroke */
  800. NULL, /* private_data */
  801. 0); /* private_data_len */
  802. }
  803. static void
  804. fz_list_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm,
  805. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  806. {
  807. fz_text *cloned_text = fz_keep_text(ctx, text);
  808. fz_try(ctx)
  809. {
  810. fz_rect rect = fz_bound_text(ctx, text, NULL, ctm);
  811. fz_append_display_node(
  812. ctx,
  813. dev,
  814. FZ_CMD_FILL_TEXT,
  815. fz_pack_color_params(color_params), /* flags */
  816. &rect,
  817. NULL, /* path */
  818. color, /* color */
  819. colorspace, /* colorspace */
  820. &alpha, /* alpha */
  821. &ctm, /* ctm */
  822. NULL, /* stroke */
  823. &cloned_text, /* private_data */
  824. sizeof(cloned_text)); /* private_data_len */
  825. }
  826. fz_catch(ctx)
  827. {
  828. fz_drop_text(ctx, cloned_text);
  829. fz_rethrow(ctx);
  830. }
  831. }
  832. static void
  833. fz_list_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm,
  834. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  835. {
  836. fz_text *cloned_text = fz_keep_text(ctx, text);
  837. fz_try(ctx)
  838. {
  839. fz_rect rect = fz_bound_text(ctx, text, stroke, ctm);
  840. fz_append_display_node(
  841. ctx,
  842. dev,
  843. FZ_CMD_STROKE_TEXT,
  844. fz_pack_color_params(color_params), /* flags */
  845. &rect,
  846. NULL, /* path */
  847. color, /* color */
  848. colorspace, /* colorspace */
  849. &alpha, /* alpha */
  850. &ctm, /* ctm */
  851. stroke,
  852. &cloned_text, /* private_data */
  853. sizeof(cloned_text)); /* private_data_len */
  854. }
  855. fz_catch(ctx)
  856. {
  857. fz_drop_text(ctx, cloned_text);
  858. fz_rethrow(ctx);
  859. }
  860. }
  861. static void
  862. fz_list_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor)
  863. {
  864. fz_text *cloned_text = fz_keep_text(ctx, text);
  865. fz_try(ctx)
  866. {
  867. fz_rect rect = fz_bound_text(ctx, text, NULL, ctm);
  868. rect = fz_intersect_rect(rect, scissor);
  869. fz_append_display_node(
  870. ctx,
  871. dev,
  872. FZ_CMD_CLIP_TEXT,
  873. 0, /* flags */
  874. &rect,
  875. NULL, /* path */
  876. NULL, /* color */
  877. NULL, /* colorspace */
  878. NULL, /* alpha */
  879. &ctm, /* ctm */
  880. NULL, /* stroke */
  881. &cloned_text, /* private_data */
  882. sizeof(cloned_text)); /* private_data_len */
  883. }
  884. fz_catch(ctx)
  885. {
  886. fz_drop_text(ctx, cloned_text);
  887. fz_rethrow(ctx);
  888. }
  889. }
  890. static void
  891. fz_list_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
  892. {
  893. fz_text *cloned_text = fz_keep_text(ctx, text);
  894. fz_try(ctx)
  895. {
  896. fz_rect rect = fz_bound_text(ctx, text, stroke, ctm);
  897. rect = fz_intersect_rect(rect, scissor);
  898. fz_append_display_node(
  899. ctx,
  900. dev,
  901. FZ_CMD_CLIP_STROKE_TEXT,
  902. 0, /* flags */
  903. &rect,
  904. NULL, /* path */
  905. NULL, /* color */
  906. NULL, /* colorspace */
  907. NULL, /* alpha */
  908. &ctm, /* ctm */
  909. stroke, /* stroke */
  910. &cloned_text, /* private_data */
  911. sizeof(cloned_text)); /* private_data_len */
  912. }
  913. fz_catch(ctx)
  914. {
  915. fz_drop_text(ctx, cloned_text);
  916. fz_rethrow(ctx);
  917. }
  918. }
  919. static void
  920. fz_list_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm)
  921. {
  922. fz_text *cloned_text = fz_keep_text(ctx, text);
  923. fz_try(ctx)
  924. {
  925. fz_rect rect = fz_bound_text(ctx, text, NULL, ctm);
  926. fz_append_display_node(
  927. ctx,
  928. dev,
  929. FZ_CMD_IGNORE_TEXT,
  930. 0, /* flags */
  931. &rect,
  932. NULL, /* path */
  933. NULL, /* color */
  934. NULL, /* colorspace */
  935. NULL, /* alpha */
  936. &ctm, /* ctm */
  937. NULL, /* stroke */
  938. &cloned_text, /* private_data */
  939. sizeof(cloned_text)); /* private_data_len */
  940. }
  941. fz_catch(ctx)
  942. {
  943. fz_drop_text(ctx, cloned_text);
  944. fz_rethrow(ctx);
  945. }
  946. }
  947. static void
  948. fz_list_pop_clip(fz_context *ctx, fz_device *dev)
  949. {
  950. fz_append_display_node(
  951. ctx,
  952. dev,
  953. FZ_CMD_POP_CLIP,
  954. 0, /* flags */
  955. NULL, /* rect */
  956. NULL, /* path */
  957. NULL, /* color */
  958. NULL, /* colorspace */
  959. NULL, /* alpha */
  960. NULL, /* ctm */
  961. NULL, /* stroke */
  962. NULL, /* private_data */
  963. 0); /* private_data_len */
  964. }
  965. static void
  966. fz_list_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params)
  967. {
  968. fz_shade *shade2 = fz_keep_shade(ctx, shade);
  969. fz_try(ctx)
  970. {
  971. fz_rect rect = fz_bound_shade(ctx, shade, ctm);
  972. fz_append_display_node(
  973. ctx,
  974. dev,
  975. FZ_CMD_FILL_SHADE,
  976. fz_pack_color_params(color_params), /* flags */
  977. &rect,
  978. NULL, /* path */
  979. NULL, /* color */
  980. NULL, /* colorspace */
  981. &alpha, /* alpha */
  982. &ctm, /* ctm */
  983. NULL, /* stroke */
  984. &shade2, /* private_data */
  985. sizeof(shade2)); /* private_data_len */
  986. }
  987. fz_catch(ctx)
  988. {
  989. fz_drop_shade(ctx, shade2);
  990. fz_rethrow(ctx);
  991. }
  992. }
  993. static void
  994. fz_list_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params)
  995. {
  996. fz_image *image2 = fz_keep_image(ctx, image);
  997. fz_try(ctx)
  998. {
  999. fz_rect rect = fz_transform_rect(fz_unit_rect, ctm);
  1000. fz_append_display_node(
  1001. ctx,
  1002. dev,
  1003. FZ_CMD_FILL_IMAGE,
  1004. fz_pack_color_params(color_params), /* flags */
  1005. &rect,
  1006. NULL, /* path */
  1007. NULL, /* color */
  1008. NULL, /* colorspace */
  1009. &alpha, /* alpha */
  1010. &ctm, /* ctm */
  1011. NULL, /* stroke */
  1012. &image2, /* private_data */
  1013. sizeof(image2)); /* private_data_len */
  1014. }
  1015. fz_catch(ctx)
  1016. {
  1017. fz_drop_image(ctx, image2);
  1018. fz_rethrow(ctx);
  1019. }
  1020. }
  1021. static void
  1022. fz_list_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm,
  1023. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  1024. {
  1025. fz_image *image2 = fz_keep_image(ctx, image);
  1026. fz_try(ctx)
  1027. {
  1028. fz_rect rect = fz_transform_rect(fz_unit_rect, ctm);
  1029. fz_append_display_node(
  1030. ctx,
  1031. dev,
  1032. FZ_CMD_FILL_IMAGE_MASK,
  1033. fz_pack_color_params(color_params), /* flags */
  1034. &rect,
  1035. NULL, /* path */
  1036. color,
  1037. colorspace,
  1038. &alpha, /* alpha */
  1039. &ctm, /* ctm */
  1040. NULL, /* stroke */
  1041. &image2, /* private_data */
  1042. sizeof(image2)); /* private_data_len */
  1043. }
  1044. fz_catch(ctx)
  1045. {
  1046. fz_drop_image(ctx, image2);
  1047. fz_rethrow(ctx);
  1048. }
  1049. }
  1050. static void
  1051. fz_list_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor)
  1052. {
  1053. fz_image *image2 = fz_keep_image(ctx, image);
  1054. fz_try(ctx)
  1055. {
  1056. fz_rect rect = fz_transform_rect(fz_unit_rect, ctm);
  1057. rect = fz_intersect_rect(rect, scissor);
  1058. fz_append_display_node(
  1059. ctx,
  1060. dev,
  1061. FZ_CMD_CLIP_IMAGE_MASK,
  1062. 0, /* flags */
  1063. &rect,
  1064. NULL, /* path */
  1065. NULL, /* color */
  1066. NULL, /* colorspace */
  1067. NULL, /* alpha */
  1068. &ctm, /* ctm */
  1069. NULL, /* stroke */
  1070. &image2, /* private_data */
  1071. sizeof(image2)); /* private_data_len */
  1072. }
  1073. fz_catch(ctx)
  1074. {
  1075. fz_drop_image(ctx, image2);
  1076. fz_rethrow(ctx);
  1077. }
  1078. }
  1079. static void
  1080. fz_list_begin_mask(fz_context *ctx, fz_device *dev, fz_rect rect, int luminosity, fz_colorspace *colorspace, const float *color, fz_color_params color_params)
  1081. {
  1082. fz_append_display_node(
  1083. ctx,
  1084. dev,
  1085. FZ_CMD_BEGIN_MASK,
  1086. (!!luminosity) | fz_pack_color_params(color_params), /* flags */
  1087. &rect,
  1088. NULL, /* path */
  1089. color,
  1090. colorspace,
  1091. NULL, /* alpha */
  1092. NULL, /* ctm */
  1093. NULL, /* stroke */
  1094. NULL, /* private_data */
  1095. 0); /* private_data_len */
  1096. }
  1097. static void
  1098. fz_list_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
  1099. {
  1100. fz_function *tr2 = fz_keep_function(ctx, tr);
  1101. fz_try(ctx)
  1102. fz_append_display_node(
  1103. ctx,
  1104. dev,
  1105. FZ_CMD_END_MASK,
  1106. 0, /* flags */
  1107. NULL, /* rect */
  1108. NULL, /* path */
  1109. NULL, /* color */
  1110. NULL, /* colorspace */
  1111. NULL, /* alpha */
  1112. NULL, /* ctm */
  1113. NULL, /* stroke */
  1114. &tr2, /* private_data */
  1115. sizeof(tr2)); /* private_data_len */
  1116. fz_catch(ctx)
  1117. {
  1118. fz_drop_function(ctx, tr);
  1119. fz_rethrow(ctx);
  1120. }
  1121. }
  1122. static void
  1123. fz_list_begin_group(fz_context *ctx, fz_device *dev, fz_rect rect, fz_colorspace *colorspace, int isolated, int knockout, int blendmode, float alpha)
  1124. {
  1125. int flags;
  1126. static const float color[FZ_MAX_COLORS] = { 0 };
  1127. flags = (blendmode<<2);
  1128. if (isolated)
  1129. flags |= ISOLATED;
  1130. if (knockout)
  1131. flags |= KNOCKOUT;
  1132. fz_append_display_node(
  1133. ctx,
  1134. dev,
  1135. FZ_CMD_BEGIN_GROUP,
  1136. flags,
  1137. &rect,
  1138. NULL, /* path */
  1139. color, /* color */
  1140. colorspace, /* colorspace */
  1141. &alpha, /* alpha */
  1142. NULL, /* ctm */
  1143. NULL, /* stroke */
  1144. NULL, /* private_data */
  1145. 0); /* private_data_len */
  1146. }
  1147. static void
  1148. fz_list_end_group(fz_context *ctx, fz_device *dev)
  1149. {
  1150. fz_append_display_node(
  1151. ctx,
  1152. dev,
  1153. FZ_CMD_END_GROUP,
  1154. 0, /* flags */
  1155. NULL, /* rect */
  1156. NULL, /* path */
  1157. NULL, /* color */
  1158. NULL, /* colorspace */
  1159. NULL, /* alpha */
  1160. NULL, /* ctm */
  1161. NULL, /* stroke */
  1162. NULL, /* private_data */
  1163. 0); /* private_data_len */
  1164. }
  1165. typedef struct
  1166. {
  1167. float xstep;
  1168. float ystep;
  1169. fz_rect view;
  1170. int id;
  1171. } fz_list_tile_data;
  1172. static int
  1173. fz_list_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id)
  1174. {
  1175. fz_list_tile_data tile;
  1176. tile.xstep = xstep;
  1177. tile.ystep = ystep;
  1178. tile.view = view;
  1179. tile.id = id;
  1180. fz_append_display_node(
  1181. ctx,
  1182. dev,
  1183. FZ_CMD_BEGIN_TILE,
  1184. 0, /* flags */
  1185. &area,
  1186. NULL, /* path */
  1187. NULL, /* color */
  1188. NULL, /* colorspace */
  1189. NULL, /* alpha */
  1190. &ctm, /* ctm */
  1191. NULL, /* stroke */
  1192. &tile, /* private_data */
  1193. sizeof(tile)); /* private_data_len */
  1194. return 0;
  1195. }
  1196. static void
  1197. fz_list_end_tile(fz_context *ctx, fz_device *dev)
  1198. {
  1199. fz_append_display_node(
  1200. ctx,
  1201. dev,
  1202. FZ_CMD_END_TILE,
  1203. 0, /* flags */
  1204. NULL,
  1205. NULL, /* path */
  1206. NULL, /* color */
  1207. NULL, /* colorspace */
  1208. NULL, /* alpha */
  1209. NULL, /* ctm */
  1210. NULL, /* stroke */
  1211. NULL, /* private_data */
  1212. 0); /* private_data_len */
  1213. }
  1214. static void
  1215. fz_list_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
  1216. {
  1217. int flags;
  1218. /* Pack the options down */
  1219. if (set == FZ_DEVFLAG_GRIDFIT_AS_TILED && clear == 0)
  1220. flags = 1;
  1221. else if (set == 0 && clear == FZ_DEVFLAG_GRIDFIT_AS_TILED)
  1222. flags = 0;
  1223. else
  1224. {
  1225. assert("Unsupported flags combination" == NULL);
  1226. return;
  1227. }
  1228. fz_append_display_node(
  1229. ctx,
  1230. dev,
  1231. FZ_CMD_RENDER_FLAGS,
  1232. flags, /* flags */
  1233. NULL,
  1234. NULL, /* path */
  1235. NULL, /* color */
  1236. NULL, /* colorspace */
  1237. NULL, /* alpha */
  1238. NULL, /* ctm */
  1239. NULL, /* stroke */
  1240. NULL, /* private_data */
  1241. 0); /* private_data_len */
  1242. }
  1243. static void
  1244. fz_list_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs)
  1245. {
  1246. fz_default_colorspaces *default_cs2 = fz_keep_default_colorspaces(ctx, default_cs);
  1247. fz_try(ctx)
  1248. {
  1249. fz_append_display_node(
  1250. ctx,
  1251. dev,
  1252. FZ_CMD_DEFAULT_COLORSPACES,
  1253. 0, /* flags */
  1254. NULL,
  1255. NULL, /* path */
  1256. NULL, /* color */
  1257. NULL, /* colorspace */
  1258. NULL, /* alpha */
  1259. NULL, /* ctm */
  1260. NULL, /* stroke */
  1261. &default_cs2, /* private_data */
  1262. sizeof(default_cs2)); /* private_data_len */
  1263. }
  1264. fz_catch(ctx)
  1265. {
  1266. fz_drop_default_colorspaces(ctx, default_cs2);
  1267. fz_rethrow(ctx);
  1268. }
  1269. }
  1270. static void
  1271. fz_list_begin_layer(fz_context *ctx, fz_device *dev, const char *layer_name)
  1272. {
  1273. size_t len = layer_name ? strlen(layer_name) : 0;
  1274. fz_append_display_node(
  1275. ctx,
  1276. dev,
  1277. FZ_CMD_BEGIN_LAYER,
  1278. 0, /* flags */
  1279. NULL,
  1280. NULL, /* path */
  1281. NULL, /* color */
  1282. NULL, /* colorspace */
  1283. NULL, /* alpha */
  1284. NULL,
  1285. NULL, /* stroke */
  1286. len ? layer_name : "", /* private_data */
  1287. len + 1); /* private_data_len */
  1288. }
  1289. static void
  1290. fz_list_end_layer(fz_context *ctx, fz_device *dev)
  1291. {
  1292. fz_append_display_node(
  1293. ctx,
  1294. dev,
  1295. FZ_CMD_END_LAYER,
  1296. 0, /* flags */
  1297. NULL,
  1298. NULL, /* path */
  1299. NULL, /* color */
  1300. NULL, /* colorspace */
  1301. NULL, /* alpha */
  1302. NULL, /* ctm */
  1303. NULL, /* stroke */
  1304. NULL, /* private_data */
  1305. 0); /* private_data_len */
  1306. }
  1307. static void
  1308. fz_list_begin_structure(fz_context *ctx, fz_device *dev, fz_structure standard, const char *raw, int idx)
  1309. {
  1310. unsigned char *data;
  1311. size_t len = (raw ? strlen(raw) : 0);
  1312. data = fz_append_display_node(
  1313. ctx,
  1314. dev,
  1315. FZ_CMD_BEGIN_STRUCTURE,
  1316. 0, /* flags */
  1317. NULL,
  1318. NULL, /* path */
  1319. NULL, /* color */
  1320. NULL, /* colorspace */
  1321. NULL, /* alpha */
  1322. NULL,
  1323. NULL, /* stroke */
  1324. NULL, /* private_data */
  1325. len+2+sizeof(idx)); /* private_data_len */
  1326. data[0] = (char)standard;
  1327. memcpy(data+1, &idx, sizeof(idx));
  1328. if (len)
  1329. memcpy(data+1+sizeof(idx), raw, len+1);
  1330. else
  1331. data[1+sizeof(idx)] = 0;
  1332. }
  1333. static void
  1334. fz_list_end_structure(fz_context *ctx, fz_device *dev)
  1335. {
  1336. fz_append_display_node(
  1337. ctx,
  1338. dev,
  1339. FZ_CMD_END_STRUCTURE,
  1340. 0, /* flags */
  1341. NULL,
  1342. NULL, /* path */
  1343. NULL, /* color */
  1344. NULL, /* colorspace */
  1345. NULL, /* alpha */
  1346. NULL, /* ctm */
  1347. NULL, /* stroke */
  1348. NULL, /* private_data */
  1349. 0); /* private_data_len */
  1350. }
  1351. static void
  1352. fz_list_begin_metatext(fz_context *ctx, fz_device *dev, fz_metatext meta, const char *text)
  1353. {
  1354. unsigned char *data;
  1355. size_t len = (text ? strlen(text) : 0);
  1356. data = fz_append_display_node(
  1357. ctx,
  1358. dev,
  1359. FZ_CMD_BEGIN_METATEXT,
  1360. 0, /* flags */
  1361. NULL,
  1362. NULL, /* path */
  1363. NULL, /* color */
  1364. NULL, /* colorspace */
  1365. NULL, /* alpha */
  1366. NULL,
  1367. NULL, /* stroke */
  1368. NULL, /* private_data */
  1369. len + 2); /* private_data_len */
  1370. data[0] = (char)meta;
  1371. if (len)
  1372. memcpy(data+1, text, len+1);
  1373. else
  1374. data[1] = 0;
  1375. }
  1376. static void
  1377. fz_list_end_metatext(fz_context *ctx, fz_device *dev)
  1378. {
  1379. fz_append_display_node(
  1380. ctx,
  1381. dev,
  1382. FZ_CMD_END_METATEXT,
  1383. 0, /* flags */
  1384. NULL,
  1385. NULL, /* path */
  1386. NULL, /* color */
  1387. NULL, /* colorspace */
  1388. NULL, /* alpha */
  1389. NULL, /* ctm */
  1390. NULL, /* stroke */
  1391. NULL, /* private_data */
  1392. 0); /* private_data_len */
  1393. }
  1394. static void
  1395. fz_list_drop_device(fz_context *ctx, fz_device *dev)
  1396. {
  1397. fz_list_device *writer = (fz_list_device *)dev;
  1398. fz_drop_colorspace(ctx, writer->colorspace);
  1399. fz_drop_stroke_state(ctx, writer->stroke);
  1400. fz_drop_path(ctx, writer->path);
  1401. fz_drop_display_list(ctx, writer->list);
  1402. }
  1403. fz_device *
  1404. fz_new_list_device(fz_context *ctx, fz_display_list *list)
  1405. {
  1406. fz_list_device *dev;
  1407. dev = fz_new_derived_device(ctx, fz_list_device);
  1408. dev->super.fill_path = fz_list_fill_path;
  1409. dev->super.stroke_path = fz_list_stroke_path;
  1410. dev->super.clip_path = fz_list_clip_path;
  1411. dev->super.clip_stroke_path = fz_list_clip_stroke_path;
  1412. dev->super.fill_text = fz_list_fill_text;
  1413. dev->super.stroke_text = fz_list_stroke_text;
  1414. dev->super.clip_text = fz_list_clip_text;
  1415. dev->super.clip_stroke_text = fz_list_clip_stroke_text;
  1416. dev->super.ignore_text = fz_list_ignore_text;
  1417. dev->super.fill_shade = fz_list_fill_shade;
  1418. dev->super.fill_image = fz_list_fill_image;
  1419. dev->super.fill_image_mask = fz_list_fill_image_mask;
  1420. dev->super.clip_image_mask = fz_list_clip_image_mask;
  1421. dev->super.pop_clip = fz_list_pop_clip;
  1422. dev->super.begin_mask = fz_list_begin_mask;
  1423. dev->super.end_mask = fz_list_end_mask;
  1424. dev->super.begin_group = fz_list_begin_group;
  1425. dev->super.end_group = fz_list_end_group;
  1426. dev->super.begin_tile = fz_list_begin_tile;
  1427. dev->super.end_tile = fz_list_end_tile;
  1428. dev->super.render_flags = fz_list_render_flags;
  1429. dev->super.set_default_colorspaces = fz_list_set_default_colorspaces;
  1430. dev->super.begin_layer = fz_list_begin_layer;
  1431. dev->super.end_layer = fz_list_end_layer;
  1432. dev->super.begin_structure = fz_list_begin_structure;
  1433. dev->super.end_structure = fz_list_end_structure;
  1434. dev->super.begin_metatext = fz_list_begin_metatext;
  1435. dev->super.end_metatext = fz_list_end_metatext;
  1436. dev->super.drop_device = fz_list_drop_device;
  1437. dev->list = fz_keep_display_list(ctx, list);
  1438. dev->path = NULL;
  1439. dev->alpha = 1.0f;
  1440. dev->ctm = fz_identity;
  1441. dev->stroke = NULL;
  1442. dev->colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
  1443. memset(dev->color, 0, sizeof(float)*FZ_MAX_COLORS);
  1444. dev->top = 0;
  1445. dev->tiled = 0;
  1446. return &dev->super;
  1447. }
  1448. static void
  1449. fz_drop_display_list_imp(fz_context *ctx, fz_storable *list_)
  1450. {
  1451. fz_display_list *list = (fz_display_list *)list_;
  1452. fz_display_node *node = list->list;
  1453. fz_display_node *node_end = list->list + list->len;
  1454. int cs_n = 1;
  1455. fz_colorspace *cs;
  1456. while (node != node_end)
  1457. {
  1458. fz_display_node n = *node;
  1459. size_t size = n.size;
  1460. fz_display_node *next;
  1461. if (size == INDIRECT_NODE_THRESHOLD)
  1462. {
  1463. memcpy(&size, &node[1], sizeof(size));
  1464. node += SIZE_IN_NODES(sizeof(size_t));
  1465. size -= SIZE_IN_NODES(sizeof(size_t));
  1466. }
  1467. next = node + size;
  1468. node++;
  1469. if (n.rect)
  1470. {
  1471. node += SIZE_IN_NODES(sizeof(fz_rect));
  1472. }
  1473. switch (n.cs)
  1474. {
  1475. default:
  1476. case CS_UNCHANGED:
  1477. break;
  1478. case CS_GRAY_0:
  1479. case CS_GRAY_1:
  1480. cs_n = 1;
  1481. break;
  1482. case CS_RGB_0:
  1483. case CS_RGB_1:
  1484. cs_n = 3;
  1485. break;
  1486. case CS_CMYK_0:
  1487. case CS_CMYK_1:
  1488. cs_n = 4;
  1489. break;
  1490. case CS_OTHER_0:
  1491. align_node_for_pointer(&node);
  1492. cs = *(fz_colorspace **)node;
  1493. cs_n = fz_colorspace_n(ctx, cs);
  1494. fz_drop_colorspace(ctx, cs);
  1495. node += SIZE_IN_NODES(sizeof(fz_colorspace *));
  1496. break;
  1497. }
  1498. if (n.color)
  1499. {
  1500. node += SIZE_IN_NODES(cs_n * sizeof(float));
  1501. }
  1502. if (n.alpha == ALPHA_PRESENT)
  1503. {
  1504. node += SIZE_IN_NODES(sizeof(float));
  1505. }
  1506. if (n.ctm & CTM_CHANGE_AD)
  1507. node += SIZE_IN_NODES(2*sizeof(float));
  1508. if (n.ctm & CTM_CHANGE_BC)
  1509. node += SIZE_IN_NODES(2*sizeof(float));
  1510. if (n.ctm & CTM_CHANGE_EF)
  1511. node += SIZE_IN_NODES(2*sizeof(float));
  1512. if (n.stroke)
  1513. {
  1514. align_node_for_pointer(&node);
  1515. fz_drop_stroke_state(ctx, *(fz_stroke_state **)node);
  1516. node += SIZE_IN_NODES(sizeof(fz_stroke_state *));
  1517. }
  1518. if (n.path)
  1519. {
  1520. int path_size;
  1521. align_node_for_pointer(&node);
  1522. path_size = fz_packed_path_size((fz_path *)node);
  1523. fz_drop_path(ctx, (fz_path *)node);
  1524. node += SIZE_IN_NODES(path_size);
  1525. }
  1526. switch(n.cmd)
  1527. {
  1528. case FZ_CMD_FILL_TEXT:
  1529. case FZ_CMD_STROKE_TEXT:
  1530. case FZ_CMD_CLIP_TEXT:
  1531. case FZ_CMD_CLIP_STROKE_TEXT:
  1532. case FZ_CMD_IGNORE_TEXT:
  1533. align_node_for_pointer(&node);
  1534. fz_drop_text(ctx, *(fz_text **)node);
  1535. break;
  1536. case FZ_CMD_FILL_SHADE:
  1537. align_node_for_pointer(&node);
  1538. fz_drop_shade(ctx, *(fz_shade **)node);
  1539. break;
  1540. case FZ_CMD_FILL_IMAGE:
  1541. case FZ_CMD_FILL_IMAGE_MASK:
  1542. case FZ_CMD_CLIP_IMAGE_MASK:
  1543. align_node_for_pointer(&node);
  1544. fz_drop_image(ctx, *(fz_image **)node);
  1545. break;
  1546. case FZ_CMD_END_MASK:
  1547. align_node_for_pointer(&node);
  1548. fz_drop_function(ctx, *(fz_function **)node);
  1549. break;
  1550. case FZ_CMD_DEFAULT_COLORSPACES:
  1551. align_node_for_pointer(&node);
  1552. fz_drop_default_colorspaces(ctx, *(fz_default_colorspaces **)node);
  1553. break;
  1554. }
  1555. node = next;
  1556. }
  1557. fz_free(ctx, list->list);
  1558. fz_free(ctx, list);
  1559. }
  1560. fz_display_list *
  1561. fz_new_display_list(fz_context *ctx, fz_rect mediabox)
  1562. {
  1563. fz_display_list *list = fz_malloc_struct(ctx, fz_display_list);
  1564. FZ_INIT_STORABLE(list, 1, fz_drop_display_list_imp);
  1565. list->list = NULL;
  1566. list->mediabox = mediabox;
  1567. list->max = 0;
  1568. list->len = 0;
  1569. return list;
  1570. }
  1571. fz_display_list *
  1572. fz_keep_display_list(fz_context *ctx, fz_display_list *list)
  1573. {
  1574. return fz_keep_storable(ctx, &list->storable);
  1575. }
  1576. void
  1577. fz_drop_display_list(fz_context *ctx, fz_display_list *list)
  1578. {
  1579. fz_defer_reap_start(ctx);
  1580. fz_drop_storable(ctx, &list->storable);
  1581. fz_defer_reap_end(ctx);
  1582. }
  1583. fz_rect
  1584. fz_bound_display_list(fz_context *ctx, fz_display_list *list)
  1585. {
  1586. return list->mediabox;
  1587. }
  1588. int fz_display_list_is_empty(fz_context *ctx, const fz_display_list *list)
  1589. {
  1590. return !list || list->len == 0;
  1591. }
  1592. void
  1593. fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz_rect scissor, fz_cookie *cookie)
  1594. {
  1595. fz_display_node *node;
  1596. fz_display_node *node_end;
  1597. fz_display_node *next_node;
  1598. int clipped = 0;
  1599. int tiled = 0;
  1600. int progress = 0;
  1601. /* Current graphics state as unpacked from list */
  1602. fz_path *path = NULL;
  1603. float alpha = 1.0f;
  1604. fz_matrix ctm = fz_identity;
  1605. fz_stroke_state *stroke = NULL;
  1606. float color[FZ_MAX_COLORS] = { 0 };
  1607. fz_colorspace *colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
  1608. fz_color_params color_params;
  1609. fz_rect rect = { 0 };
  1610. /* Transformed versions of graphic state entries */
  1611. fz_rect trans_rect;
  1612. fz_matrix trans_ctm;
  1613. int tile_skip_depth = 0;
  1614. if (cookie)
  1615. {
  1616. cookie->progress_max = list->len;
  1617. cookie->progress = 0;
  1618. }
  1619. color_params = fz_default_color_params;
  1620. node = list->list;
  1621. node_end = &list->list[list->len];
  1622. for (; node != node_end ; node = next_node)
  1623. {
  1624. int empty;
  1625. fz_display_node n = *node;
  1626. size_t size = n.size;
  1627. if (size == INDIRECT_NODE_THRESHOLD)
  1628. {
  1629. memcpy(&size, &node[1], sizeof(size_t));
  1630. node += SIZE_IN_NODES(sizeof(size_t));
  1631. size -= SIZE_IN_NODES(sizeof(size_t));
  1632. }
  1633. next_node = node + size;
  1634. /* Check the cookie for aborting */
  1635. if (cookie)
  1636. {
  1637. if (cookie->abort)
  1638. break;
  1639. cookie->progress = progress;
  1640. progress += (int)size;
  1641. }
  1642. node++;
  1643. if (n.rect)
  1644. {
  1645. rect = *(fz_rect *)node;
  1646. node += SIZE_IN_NODES(sizeof(fz_rect));
  1647. }
  1648. if (n.cs)
  1649. {
  1650. int i, en;
  1651. fz_drop_colorspace(ctx, colorspace);
  1652. switch (n.cs)
  1653. {
  1654. default:
  1655. case CS_GRAY_0:
  1656. colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
  1657. color[0] = 0.0f;
  1658. break;
  1659. case CS_GRAY_1:
  1660. colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
  1661. color[0] = 1.0f;
  1662. break;
  1663. case CS_RGB_0:
  1664. colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
  1665. color[0] = 0.0f;
  1666. color[1] = 0.0f;
  1667. color[2] = 0.0f;
  1668. break;
  1669. case CS_RGB_1:
  1670. colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
  1671. color[0] = 1.0f;
  1672. color[1] = 1.0f;
  1673. color[2] = 1.0f;
  1674. break;
  1675. case CS_CMYK_0:
  1676. colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
  1677. color[0] = 0.0f;
  1678. color[1] = 0.0f;
  1679. color[2] = 0.0f;
  1680. color[3] = 0.0f;
  1681. break;
  1682. case CS_CMYK_1:
  1683. colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
  1684. color[0] = 0.0f;
  1685. color[1] = 0.0f;
  1686. color[2] = 0.0f;
  1687. color[3] = 1.0f;
  1688. break;
  1689. case CS_OTHER_0:
  1690. align_node_for_pointer(&node);
  1691. colorspace = fz_keep_colorspace(ctx, *(fz_colorspace **)(node));
  1692. node += SIZE_IN_NODES(sizeof(fz_colorspace *));
  1693. en = fz_colorspace_n(ctx, colorspace);
  1694. for (i = 0; i < en; i++)
  1695. color[i] = 0.0f;
  1696. break;
  1697. }
  1698. }
  1699. if (n.color)
  1700. {
  1701. int nc = fz_colorspace_n(ctx, colorspace);
  1702. memcpy(color, (float *)node, nc * sizeof(float));
  1703. node += SIZE_IN_NODES(nc * sizeof(float));
  1704. }
  1705. if (n.alpha)
  1706. {
  1707. switch(n.alpha)
  1708. {
  1709. default:
  1710. case ALPHA_0:
  1711. alpha = 0.0f;
  1712. break;
  1713. case ALPHA_1:
  1714. alpha = 1.0f;
  1715. break;
  1716. case ALPHA_PRESENT:
  1717. alpha = *(float *)node;
  1718. node += SIZE_IN_NODES(sizeof(float));
  1719. break;
  1720. }
  1721. }
  1722. if (n.ctm != 0)
  1723. {
  1724. float *packed_ctm = (float *)node;
  1725. if (n.ctm & CTM_CHANGE_AD)
  1726. {
  1727. ctm.a = *packed_ctm++;
  1728. ctm.d = *packed_ctm++;
  1729. node += SIZE_IN_NODES(2*sizeof(float));
  1730. }
  1731. if (n.ctm & CTM_CHANGE_BC)
  1732. {
  1733. ctm.b = *packed_ctm++;
  1734. ctm.c = *packed_ctm++;
  1735. node += SIZE_IN_NODES(2*sizeof(float));
  1736. }
  1737. if (n.ctm & CTM_CHANGE_EF)
  1738. {
  1739. ctm.e = *packed_ctm++;
  1740. ctm.f = *packed_ctm;
  1741. node += SIZE_IN_NODES(2*sizeof(float));
  1742. }
  1743. }
  1744. if (n.stroke)
  1745. {
  1746. align_node_for_pointer(&node);
  1747. fz_drop_stroke_state(ctx, stroke);
  1748. stroke = fz_keep_stroke_state(ctx, *(fz_stroke_state **)node);
  1749. node += SIZE_IN_NODES(sizeof(fz_stroke_state *));
  1750. }
  1751. if (n.path)
  1752. {
  1753. align_node_for_pointer(&node);
  1754. fz_drop_path(ctx, path);
  1755. path = fz_keep_path(ctx, (fz_path *)node);
  1756. node += SIZE_IN_NODES(fz_packed_path_size(path));
  1757. }
  1758. if (tile_skip_depth > 0)
  1759. {
  1760. if (n.cmd == FZ_CMD_BEGIN_TILE)
  1761. tile_skip_depth++;
  1762. else if (n.cmd == FZ_CMD_END_TILE)
  1763. tile_skip_depth--;
  1764. if (tile_skip_depth > 0)
  1765. continue;
  1766. }
  1767. trans_rect = fz_transform_rect(rect, top_ctm);
  1768. /* cull objects to draw using a quick visibility test */
  1769. if (tiled ||
  1770. n.cmd == FZ_CMD_BEGIN_TILE || n.cmd == FZ_CMD_END_TILE ||
  1771. n.cmd == FZ_CMD_RENDER_FLAGS || n.cmd == FZ_CMD_DEFAULT_COLORSPACES ||
  1772. n.cmd == FZ_CMD_BEGIN_LAYER || n.cmd == FZ_CMD_END_LAYER ||
  1773. n.cmd == FZ_CMD_BEGIN_STRUCTURE || n.cmd == FZ_CMD_END_STRUCTURE ||
  1774. n.cmd == FZ_CMD_BEGIN_METATEXT || n.cmd == FZ_CMD_END_METATEXT
  1775. )
  1776. {
  1777. empty = 0;
  1778. }
  1779. else if (n.cmd == FZ_CMD_FILL_PATH || n.cmd == FZ_CMD_STROKE_PATH)
  1780. {
  1781. /* Zero area paths are suitable for stroking. */
  1782. empty = !fz_is_valid_rect(fz_intersect_rect(trans_rect, scissor));
  1783. }
  1784. else if (n.cmd == FZ_CMD_FILL_TEXT || n.cmd == FZ_CMD_STROKE_TEXT ||
  1785. n.cmd == FZ_CMD_CLIP_TEXT || n.cmd == FZ_CMD_CLIP_STROKE_TEXT)
  1786. {
  1787. /* Zero area text (such as spaces) should be passed
  1788. * through. Text that is completely outside the scissor
  1789. * can be elided. */
  1790. empty = !fz_is_valid_rect(fz_intersect_rect(trans_rect, scissor));
  1791. }
  1792. else
  1793. {
  1794. empty = fz_is_empty_rect(fz_intersect_rect(trans_rect, scissor));
  1795. }
  1796. /* clipped starts out as 0. It only goes non-zero here if we move inside
  1797. * an 'empty' region. Whenever clipped is non zero, or we are in an empty
  1798. * region, we therefore may need to increment clipped according to the
  1799. * nesting. */
  1800. if (clipped || empty)
  1801. {
  1802. switch (n.cmd)
  1803. {
  1804. case FZ_CMD_CLIP_PATH:
  1805. case FZ_CMD_CLIP_STROKE_PATH:
  1806. case FZ_CMD_CLIP_TEXT:
  1807. case FZ_CMD_CLIP_STROKE_TEXT:
  1808. case FZ_CMD_CLIP_IMAGE_MASK:
  1809. case FZ_CMD_BEGIN_MASK:
  1810. case FZ_CMD_BEGIN_GROUP:
  1811. clipped++;
  1812. continue;
  1813. case FZ_CMD_BEGIN_STRUCTURE:
  1814. case FZ_CMD_END_STRUCTURE:
  1815. case FZ_CMD_BEGIN_METATEXT:
  1816. case FZ_CMD_END_METATEXT:
  1817. /* These may not nest as nicely as we'd like. Just ignore them for
  1818. * the purposes of clipping. */
  1819. break;
  1820. case FZ_CMD_POP_CLIP:
  1821. case FZ_CMD_END_GROUP:
  1822. if (!clipped)
  1823. goto visible;
  1824. clipped--;
  1825. continue;
  1826. case FZ_CMD_END_MASK:
  1827. if (!clipped)
  1828. goto visible;
  1829. continue;
  1830. default:
  1831. continue;
  1832. }
  1833. }
  1834. visible:
  1835. trans_ctm = fz_concat(ctm, top_ctm);
  1836. fz_try(ctx)
  1837. {
  1838. switch (n.cmd)
  1839. {
  1840. case FZ_CMD_FILL_PATH:
  1841. fz_unpack_color_params(&color_params, n.flags);
  1842. fz_fill_path(ctx, dev, path, n.flags & 1, trans_ctm, colorspace, color, alpha, color_params);
  1843. break;
  1844. case FZ_CMD_STROKE_PATH:
  1845. fz_unpack_color_params(&color_params, n.flags);
  1846. fz_stroke_path(ctx, dev, path, stroke, trans_ctm, colorspace, color, alpha, color_params);
  1847. break;
  1848. case FZ_CMD_CLIP_PATH:
  1849. fz_clip_path(ctx, dev, path, n.flags, trans_ctm, trans_rect);
  1850. break;
  1851. case FZ_CMD_CLIP_STROKE_PATH:
  1852. fz_clip_stroke_path(ctx, dev, path, stroke, trans_ctm, trans_rect);
  1853. break;
  1854. case FZ_CMD_FILL_TEXT:
  1855. fz_unpack_color_params(&color_params, n.flags);
  1856. align_node_for_pointer(&node);
  1857. fz_fill_text(ctx, dev, *(fz_text **)node, trans_ctm, colorspace, color, alpha, color_params);
  1858. break;
  1859. case FZ_CMD_STROKE_TEXT:
  1860. fz_unpack_color_params(&color_params, n.flags);
  1861. align_node_for_pointer(&node);
  1862. fz_stroke_text(ctx, dev, *(fz_text **)node, stroke, trans_ctm, colorspace, color, alpha, color_params);
  1863. break;
  1864. case FZ_CMD_CLIP_TEXT:
  1865. align_node_for_pointer(&node);
  1866. fz_clip_text(ctx, dev, *(fz_text **)node, trans_ctm, trans_rect);
  1867. break;
  1868. case FZ_CMD_CLIP_STROKE_TEXT:
  1869. align_node_for_pointer(&node);
  1870. fz_clip_stroke_text(ctx, dev, *(fz_text **)node, stroke, trans_ctm, trans_rect);
  1871. break;
  1872. case FZ_CMD_IGNORE_TEXT:
  1873. align_node_for_pointer(&node);
  1874. fz_ignore_text(ctx, dev, *(fz_text **)node, trans_ctm);
  1875. break;
  1876. case FZ_CMD_FILL_SHADE:
  1877. fz_unpack_color_params(&color_params, n.flags);
  1878. align_node_for_pointer(&node);
  1879. fz_fill_shade(ctx, dev, *(fz_shade **)node, trans_ctm, alpha, color_params);
  1880. break;
  1881. case FZ_CMD_FILL_IMAGE:
  1882. fz_unpack_color_params(&color_params, n.flags);
  1883. align_node_for_pointer(&node);
  1884. fz_fill_image(ctx, dev, *(fz_image **)node, trans_ctm, alpha, color_params);
  1885. break;
  1886. case FZ_CMD_FILL_IMAGE_MASK:
  1887. fz_unpack_color_params(&color_params, n.flags);
  1888. align_node_for_pointer(&node);
  1889. fz_fill_image_mask(ctx, dev, *(fz_image **)node, trans_ctm, colorspace, color, alpha, color_params);
  1890. break;
  1891. case FZ_CMD_CLIP_IMAGE_MASK:
  1892. align_node_for_pointer(&node);
  1893. fz_clip_image_mask(ctx, dev, *(fz_image **)node, trans_ctm, trans_rect);
  1894. break;
  1895. case FZ_CMD_POP_CLIP:
  1896. fz_pop_clip(ctx, dev);
  1897. break;
  1898. case FZ_CMD_BEGIN_MASK:
  1899. fz_unpack_color_params(&color_params, n.flags);
  1900. fz_begin_mask(ctx, dev, trans_rect, n.flags & 1, colorspace, color, color_params);
  1901. break;
  1902. case FZ_CMD_END_MASK:
  1903. align_node_for_pointer(&node);
  1904. fz_end_mask_tr(ctx, dev, *(fz_function **)node);
  1905. break;
  1906. case FZ_CMD_BEGIN_GROUP:
  1907. fz_begin_group(ctx, dev, trans_rect, colorspace, (n.flags & ISOLATED) != 0, (n.flags & KNOCKOUT) != 0, (n.flags>>2), alpha);
  1908. break;
  1909. case FZ_CMD_END_GROUP:
  1910. fz_end_group(ctx, dev);
  1911. break;
  1912. case FZ_CMD_BEGIN_TILE:
  1913. {
  1914. int cached;
  1915. fz_list_tile_data *data;
  1916. fz_rect tile_rect;
  1917. data = (fz_list_tile_data *)node;
  1918. tiled++;
  1919. tile_rect = data->view;
  1920. cached = fz_begin_tile_id(ctx, dev, rect, tile_rect, data->xstep, data->ystep, trans_ctm, data->id);
  1921. if (cached)
  1922. tile_skip_depth = 1;
  1923. break;
  1924. }
  1925. case FZ_CMD_END_TILE:
  1926. tiled--;
  1927. fz_end_tile(ctx, dev);
  1928. break;
  1929. case FZ_CMD_RENDER_FLAGS:
  1930. if (n.flags == 0)
  1931. fz_render_flags(ctx, dev, 0, FZ_DEVFLAG_GRIDFIT_AS_TILED);
  1932. else if (n.flags == 1)
  1933. fz_render_flags(ctx, dev, FZ_DEVFLAG_GRIDFIT_AS_TILED, 0);
  1934. break;
  1935. case FZ_CMD_DEFAULT_COLORSPACES:
  1936. align_node_for_pointer(&node);
  1937. fz_set_default_colorspaces(ctx, dev, *(fz_default_colorspaces **)node);
  1938. break;
  1939. case FZ_CMD_BEGIN_LAYER:
  1940. fz_begin_layer(ctx, dev, (const char *)node);
  1941. break;
  1942. case FZ_CMD_END_LAYER:
  1943. fz_end_layer(ctx, dev);
  1944. break;
  1945. case FZ_CMD_BEGIN_STRUCTURE:
  1946. {
  1947. const unsigned char *data;
  1948. int idx;
  1949. data = (const unsigned char *)node;
  1950. memcpy(&idx, data+1, sizeof(idx));
  1951. fz_begin_structure(ctx, dev, (fz_structure)data[0], (const char *)(&data[1+sizeof(idx)]), idx);
  1952. break;
  1953. }
  1954. case FZ_CMD_END_STRUCTURE:
  1955. fz_end_structure(ctx, dev);
  1956. break;
  1957. case FZ_CMD_BEGIN_METATEXT:
  1958. {
  1959. const unsigned char *data;
  1960. const char *text;
  1961. data = (const unsigned char *)node;
  1962. text = (const char *)&data[1];
  1963. fz_begin_metatext(ctx, dev, (fz_metatext)data[0], text);
  1964. break;
  1965. }
  1966. case FZ_CMD_END_METATEXT:
  1967. fz_end_metatext(ctx, dev);
  1968. break;
  1969. }
  1970. }
  1971. fz_catch(ctx)
  1972. {
  1973. if (fz_caught(ctx) == FZ_ERROR_SYSTEM)
  1974. {
  1975. fz_drop_colorspace(ctx, colorspace);
  1976. fz_drop_stroke_state(ctx, stroke);
  1977. fz_drop_path(ctx, path);
  1978. fz_rethrow(ctx);
  1979. }
  1980. /* Swallow the error */
  1981. if (cookie)
  1982. cookie->errors++;
  1983. if (fz_caught(ctx) == FZ_ERROR_ABORT)
  1984. {
  1985. fz_ignore_error(ctx);
  1986. break;
  1987. }
  1988. fz_report_error(ctx);
  1989. fz_warn(ctx, "Ignoring error during interpretation");
  1990. }
  1991. }
  1992. fz_drop_colorspace(ctx, colorspace);
  1993. fz_drop_stroke_state(ctx, stroke);
  1994. fz_drop_path(ctx, path);
  1995. if (cookie)
  1996. cookie->progress = progress;
  1997. }