| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124 |
- // Copyright (C) 2004-2025 Artifex Software, Inc.
- //
- // This file is part of MuPDF.
- //
- // MuPDF is free software: you can redistribute it and/or modify it under the
- // terms of the GNU Affero General Public License as published by the Free
- // Software Foundation, either version 3 of the License, or (at your option)
- // any later version.
- //
- // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
- // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- // details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
- //
- // Alternative licensing terms are available from the licensor.
- // For commercial licensing, see <https://www.artifex.com/> or contact
- // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
- // CA 94129, USA, for further information.
- #include "mupdf/fitz.h"
- #include <assert.h>
- #include <string.h>
- #define STACK_SIZE 96
- typedef enum
- {
- FZ_CMD_FILL_PATH,
- FZ_CMD_STROKE_PATH,
- FZ_CMD_CLIP_PATH,
- FZ_CMD_CLIP_STROKE_PATH,
- FZ_CMD_FILL_TEXT,
- FZ_CMD_STROKE_TEXT,
- FZ_CMD_CLIP_TEXT,
- FZ_CMD_CLIP_STROKE_TEXT,
- FZ_CMD_IGNORE_TEXT,
- FZ_CMD_FILL_SHADE,
- FZ_CMD_FILL_IMAGE,
- FZ_CMD_FILL_IMAGE_MASK,
- FZ_CMD_CLIP_IMAGE_MASK,
- FZ_CMD_POP_CLIP,
- FZ_CMD_BEGIN_MASK,
- FZ_CMD_END_MASK,
- FZ_CMD_BEGIN_GROUP,
- FZ_CMD_END_GROUP,
- FZ_CMD_BEGIN_TILE,
- FZ_CMD_END_TILE,
- FZ_CMD_RENDER_FLAGS,
- FZ_CMD_DEFAULT_COLORSPACES,
- FZ_CMD_BEGIN_LAYER,
- FZ_CMD_END_LAYER,
- FZ_CMD_BEGIN_STRUCTURE,
- FZ_CMD_END_STRUCTURE,
- FZ_CMD_BEGIN_METATEXT,
- FZ_CMD_END_METATEXT
- } fz_display_command;
- /* The display list is a list of nodes.
- * Each node is a structure consisting of a bitfield (that packs into a
- * 32 bit word).
- * The different fields in the bitfield identify what information is
- * present in the node.
- *
- * cmd: What type of node this is.
- *
- * size: The number of sizeof(fz_display_node) bytes that this node's
- * data occupies. (i.e. &node[size] = the next node in the
- * chain; 0 for end of list).
- *
- * At 9 bits for this field, and 4 bytes for a node, this means
- * the largest node can span 511*4 bytes. We therefore reserve
- * 511 as a special value to mean that the actual size for the
- * node is given in an (unaligned!) size_t following the node
- * before the rest of the data.
- *
- * rect: 0 for unchanged, 1 for present.
- *
- * path: 0 for unchanged, 1 for present.
- *
- * cs: 0 for unchanged
- * 1 for devicegray (color defaults to 0)
- * 2 for devicegray (color defaults to 1)
- * 3 for devicergb (color defaults to 0,0,0)
- * 4 for devicergb (color defaults to 1,1,1)
- * 5 for devicecmyk (color defaults to 0,0,0,0)
- * 6 for devicecmyk (color defaults to 0,0,0,1)
- * 7 for present (color defaults to 0)
- *
- * color: 0 for unchanged color, 1 for present.
- *
- * alpha: 0 for unchanged, 1 for solid, 2 for transparent, 3
- * for alpha value present.
- *
- * ctm: 0 for unchanged,
- * 1 for change ad
- * 2 for change bc
- * 4 for change ef.
- *
- * stroke: 0 for unchanged, 1 for present.
- *
- * flags: Flags (node specific meanings)
- *
- * Nodes are packed in the order:
- * header, rect, colorspace, color, alpha, ctm, stroke_state, path, private data.
- */
- typedef struct
- {
- unsigned int cmd : 5;
- unsigned int size : 9;
- unsigned int rect : 1;
- unsigned int path : 1;
- unsigned int cs : 3;
- unsigned int color : 1;
- unsigned int alpha : 2;
- unsigned int ctm : 3;
- unsigned int stroke : 1;
- unsigned int flags : 6;
- } fz_display_node;
- enum {
- CS_UNCHANGED = 0,
- CS_GRAY_0 = 1,
- CS_GRAY_1 = 2,
- CS_RGB_0 = 3,
- CS_RGB_1 = 4,
- CS_CMYK_0 = 5,
- CS_CMYK_1 = 6,
- CS_OTHER_0 = 7,
- ALPHA_UNCHANGED = 0,
- ALPHA_1 = 1,
- ALPHA_0 = 2,
- ALPHA_PRESENT = 3,
- CTM_UNCHANGED = 0,
- CTM_CHANGE_AD = 1,
- CTM_CHANGE_BC = 2,
- CTM_CHANGE_EF = 4,
- INDIRECT_NODE_THRESHOLD = (1<<9)-1
- };
- struct fz_display_list
- {
- fz_storable storable;
- fz_display_node *list;
- fz_rect mediabox;
- size_t max;
- size_t len;
- };
- typedef struct
- {
- fz_device super;
- fz_display_list *list;
- fz_path *path;
- float alpha;
- fz_matrix ctm;
- fz_stroke_state *stroke;
- fz_colorspace *colorspace;
- fz_color_params *color_params;
- float color[FZ_MAX_COLORS];
- fz_rect rect;
- int top;
- struct {
- fz_rect *update;
- fz_rect rect;
- } stack[STACK_SIZE];
- int tiled;
- } fz_list_device;
- enum { ISOLATED = 1, KNOCKOUT = 2 };
- enum { OPM = 1, OP = 2, BP = 3, RI = 4};
- #define SIZE_IN_NODES(t) \
- ((t + sizeof(fz_display_node) - 1) / sizeof(fz_display_node))
- /* The display list node are 32bit aligned. For some architectures we
- * need to pad to 64bit for pointers. We allow for that here. */
- static void pad_size_for_pointer(const fz_display_list *list, size_t *size)
- {
- /* list->len and size are both counting in nodes, not bytes.
- * Nodes are consistently 32bit things, hence we are looking
- * for even/odd for "8 byte aligned or not". */
- if (FZ_POINTER_ALIGN_MOD <= 4)
- return;
- /* Otherwise, ensure we're on an even boundary. */
- if (FZ_POINTER_ALIGN_MOD == 8)
- {
- if ((list->len + (*size)) & 1)
- (*size)++;
- } else
- (*size) = ((list->len + (*size) + (FZ_POINTER_ALIGN_MOD>>2) - 1) & ~((FZ_POINTER_ALIGN_MOD>>2)-1)) - list->len;
- }
- static void align_node_for_pointer(fz_display_node **node)
- {
- intptr_t ptr;
- if (FZ_POINTER_ALIGN_MOD <= 4)
- return;
- ptr = (intptr_t)*node;
- if (FZ_POINTER_ALIGN_MOD == 8)
- {
- if (ptr & 4)
- (*node) = (fz_display_node *)(ptr+4);
- }
- else
- (*node) = (fz_display_node *)((ptr + FZ_POINTER_ALIGN_MOD - 1) & ~(FZ_POINTER_ALIGN_MOD-1));
- }
- static int
- cmd_needs_alignment(fz_display_command cmd)
- {
- return (cmd == FZ_CMD_FILL_TEXT ||
- cmd == FZ_CMD_STROKE_TEXT ||
- cmd == FZ_CMD_CLIP_TEXT ||
- cmd == FZ_CMD_CLIP_STROKE_TEXT ||
- cmd == FZ_CMD_IGNORE_TEXT ||
- cmd == FZ_CMD_FILL_SHADE ||
- cmd == FZ_CMD_FILL_IMAGE ||
- cmd == FZ_CMD_FILL_IMAGE_MASK ||
- cmd == FZ_CMD_CLIP_IMAGE_MASK ||
- cmd == FZ_CMD_END_MASK ||
- cmd == FZ_CMD_DEFAULT_COLORSPACES);
- }
- static unsigned char *
- fz_append_display_node(
- fz_context *ctx,
- fz_device *dev,
- fz_display_command cmd,
- int flags,
- const fz_rect *rect,
- const fz_path *path,
- const float *color,
- fz_colorspace *colorspace,
- const float *alpha,
- const fz_matrix *ctm,
- const fz_stroke_state *stroke,
- const void *private_data,
- size_t private_data_len)
- {
- fz_display_node node = { 0 };
- fz_display_node *node_ptr;
- fz_list_device *writer = (fz_list_device *)dev;
- fz_display_list *list = writer->list;
- size_t size;
- size_t rect_off = 0;
- size_t path_off = 0;
- size_t color_off = 0;
- size_t colorspace_off = 0;
- size_t alpha_off = 0;
- size_t ctm_off = 0;
- size_t stroke_off = 0;
- int rect_for_updates = 0;
- size_t private_off = 0;
- fz_path *my_path = NULL;
- fz_stroke_state *my_stroke = NULL;
- fz_rect local_rect;
- size_t path_size = 0;
- unsigned char *out_private = NULL;
- switch (cmd)
- {
- case FZ_CMD_CLIP_PATH:
- case FZ_CMD_CLIP_STROKE_PATH:
- case FZ_CMD_CLIP_TEXT:
- case FZ_CMD_CLIP_STROKE_TEXT:
- case FZ_CMD_CLIP_IMAGE_MASK:
- if (writer->top < STACK_SIZE)
- {
- rect_for_updates = 1;
- writer->stack[writer->top].rect = fz_empty_rect;
- }
- writer->top++;
- break;
- case FZ_CMD_END_MASK:
- if (writer->top < STACK_SIZE)
- {
- writer->stack[writer->top].update = NULL;
- writer->stack[writer->top].rect = fz_empty_rect;
- }
- writer->top++;
- break;
- case FZ_CMD_BEGIN_TILE:
- writer->tiled++;
- if (writer->top > 0 && writer->top <= STACK_SIZE)
- {
- writer->stack[writer->top-1].rect = fz_infinite_rect;
- }
- break;
- case FZ_CMD_END_TILE:
- writer->tiled--;
- break;
- case FZ_CMD_END_GROUP:
- break;
- case FZ_CMD_POP_CLIP:
- if (writer->top > STACK_SIZE)
- {
- writer->top--;
- rect = &fz_infinite_rect;
- }
- else if (writer->top > 0)
- {
- fz_rect *update;
- writer->top--;
- update = writer->stack[writer->top].update;
- if (writer->tiled == 0)
- {
- if (update)
- {
- *update = fz_intersect_rect(*update, writer->stack[writer->top].rect);
- local_rect = *update;
- rect = &local_rect;
- }
- else
- rect = &writer->stack[writer->top].rect;
- }
- else
- rect = &fz_infinite_rect;
- }
- /* fallthrough */
- default:
- if (writer->top > 0 && writer->tiled == 0 && writer->top <= STACK_SIZE && rect)
- writer->stack[writer->top-1].rect = fz_union_rect(writer->stack[writer->top-1].rect, *rect);
- break;
- }
- size = 1; /* 1 for the fz_display_node */
- node.cmd = cmd;
- /* Figure out what we need to write, and the offsets at which we will
- * write it. */
- 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)))
- {
- node.rect = 1;
- rect_off = size;
- size += SIZE_IN_NODES(sizeof(fz_rect));
- }
- if (color == NULL)
- {
- if (colorspace)
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "Colorspace cannot be specified without color.");
- }
- else
- {
- if (colorspace != writer->colorspace)
- {
- if (colorspace == fz_device_gray(ctx))
- {
- if (color[0] == 0.0f)
- node.cs = CS_GRAY_0, color = NULL;
- else
- {
- node.cs = CS_GRAY_1;
- if (color[0] == 1.0f)
- color = NULL;
- }
- }
- else if (colorspace == fz_device_rgb(ctx))
- {
- if (color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f)
- node.cs = CS_RGB_0, color = NULL;
- else
- {
- node.cs = CS_RGB_1;
- if (color[0] == 1.0f && color[1] == 1.0f && color[2] == 1.0f)
- color = NULL;
- }
- }
- else if (colorspace == fz_device_cmyk(ctx))
- {
- node.cs = CS_CMYK_0;
- if (color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f)
- {
- if (color[3] == 0.0f)
- color = NULL;
- else
- {
- node.cs = CS_CMYK_1;
- if (color[3] == 1.0f)
- color = NULL;
- }
- }
- }
- else
- {
- int i;
- int n = fz_colorspace_n(ctx, colorspace);
- pad_size_for_pointer(list, &size);
- colorspace_off = size;
- size += SIZE_IN_NODES(sizeof(fz_colorspace *));
- node.cs = CS_OTHER_0;
- for (i = 0; i < n; i++)
- if (color[i] != 0.0f)
- break;
- if (i == n)
- color = NULL;
- memset(writer->color, 0, sizeof(float)*n);
- }
- }
- else
- {
- /* Colorspace is unchanged, but color may have changed
- * to something best coded as a colorspace change */
- if (colorspace == fz_device_gray(ctx))
- {
- if (writer->color[0] != color[0])
- {
- if (color[0] == 0.0f)
- {
- node.cs = CS_GRAY_0;
- color = NULL;
- }
- else if (color[0] == 1.0f)
- {
- node.cs = CS_GRAY_1;
- color = NULL;
- }
- }
- }
- else if (colorspace == fz_device_rgb(ctx))
- {
- if (writer->color[0] != color[0] || writer->color[1] != color[1] || writer->color[2] != color[2])
- {
- if (color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f)
- {
- node.cs = CS_RGB_0;
- color = NULL;
- }
- else if (color[0] == 1.0f && color[1] == 1.0f && color[2] == 1.0f)
- {
- node.cs = CS_RGB_1;
- color = NULL;
- }
- }
- }
- else if (colorspace == fz_device_cmyk(ctx))
- {
- if (writer->color[0] != color[0] || writer->color[1] != color[1] || writer->color[2] != color[2] || writer->color[3] != color[3])
- {
- if (color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f)
- {
- if (color[3] == 0.0f)
- {
- node.cs = CS_CMYK_0;
- color = NULL;
- }
- else if (color[3] == 1.0f)
- {
- node.cs = CS_CMYK_1;
- color = NULL;
- }
- }
- }
- }
- else
- {
- int i;
- int n = fz_colorspace_n(ctx, colorspace);
- for (i=0; i < n; i++)
- if (color[i] != 0.0f)
- break;
- if (i == n)
- {
- node.cs = CS_OTHER_0;
- pad_size_for_pointer(list, &size);
- colorspace_off = size;
- size += SIZE_IN_NODES(sizeof(fz_colorspace *));
- color = NULL;
- }
- }
- }
- }
- if (color)
- {
- int i, n;
- const float *wc = &writer->color[0];
- assert(colorspace != NULL);
- n = fz_colorspace_n(ctx, colorspace);
- i = 0;
- /* Only check colors if the colorspace is unchanged. If the
- * colorspace *has* changed and the colors are implicit then
- * this will have been caught above. */
- if (colorspace == writer->colorspace)
- for (; i < n; i++)
- if (color[i] != wc[i])
- break;
- if (i != n)
- {
- node.color = 1;
- color_off = size;
- size += n * SIZE_IN_NODES(sizeof(float));
- }
- }
- if (alpha && (*alpha != writer->alpha))
- {
- if (*alpha >= 1.0f)
- node.alpha = ALPHA_1;
- else if (*alpha <= 0.0f)
- node.alpha = ALPHA_0;
- else
- {
- alpha_off = size;
- size += SIZE_IN_NODES(sizeof(float));
- node.alpha = ALPHA_PRESENT;
- }
- }
- 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))
- {
- int ctm_flags;
- ctm_off = size;
- ctm_flags = CTM_UNCHANGED;
- if (ctm->a != writer->ctm.a || ctm->d != writer->ctm.d)
- ctm_flags = CTM_CHANGE_AD, size += SIZE_IN_NODES(2*sizeof(float));
- if (ctm->b != writer->ctm.b || ctm->c != writer->ctm.c)
- ctm_flags |= CTM_CHANGE_BC, size += SIZE_IN_NODES(2*sizeof(float));
- if (ctm->e != writer->ctm.e || ctm->f != writer->ctm.f)
- ctm_flags |= CTM_CHANGE_EF, size += SIZE_IN_NODES(2*sizeof(float));
- node.ctm = ctm_flags;
- }
- if (stroke && (writer->stroke == NULL || !fz_stroke_state_eq(ctx, stroke, writer->stroke)))
- {
- pad_size_for_pointer(list, &size);
- stroke_off = size;
- size += SIZE_IN_NODES(sizeof(fz_stroke_state *));
- node.stroke = 1;
- }
- if (path && (writer->path == NULL || path != writer->path))
- {
- pad_size_for_pointer(list, &size);
- path_size = SIZE_IN_NODES(fz_pack_path(ctx, NULL, path));
- node.path = 1;
- path_off = size;
- size += path_size;
- }
- if (private_data_len)
- {
- if (cmd_needs_alignment(cmd))
- pad_size_for_pointer(list, &size);
- private_off = size;
- size += SIZE_IN_NODES(private_data_len);
- }
- /* If the size is more than 511, then we can't signal that in 9 bits,
- * so we'll send it as 511, and then put an extra size_t with the
- * size in. */
- if (size >= INDIRECT_NODE_THRESHOLD)
- size += SIZE_IN_NODES(sizeof(size_t));
- while (list->len + size > list->max)
- {
- size_t newsize = list->max * 2;
- fz_display_node *old = list->list;
- ptrdiff_t diff;
- int i, n;
- if (newsize < 256)
- newsize = 256;
- list->list = fz_realloc_array(ctx, list->list, newsize, fz_display_node);
- list->max = newsize;
- diff = (char *)(list->list) - (char *)old;
- n = (writer->top < STACK_SIZE ? writer->top : STACK_SIZE);
- for (i = 0; i < n; i++)
- {
- if (writer->stack[i].update != NULL)
- writer->stack[i].update = (fz_rect *)(((char *)writer->stack[i].update) + diff);
- }
- if (writer->path)
- writer->path = (fz_path *)(((char *)writer->path) + diff);
- }
- /* Write the node to the list */
- if (size >= INDIRECT_NODE_THRESHOLD)
- node.size = INDIRECT_NODE_THRESHOLD;
- else
- node.size = (unsigned int)size;
- node.flags = flags;
- node_ptr = &list->list[list->len];
- *node_ptr = node;
- /* Insert the explicit size (unaligned) if required. */
- if (size >= INDIRECT_NODE_THRESHOLD)
- {
- memcpy(&node_ptr[1], &size, sizeof(size));
- node_ptr += SIZE_IN_NODES(sizeof(size_t));
- }
- /* Path is the most frequent one, so try to avoid the try/catch in
- * this case */
- if (path_off)
- {
- my_path = (void *)(&node_ptr[path_off]);
- (void)fz_pack_path(ctx, (void *)my_path, path);
- }
- if (stroke_off)
- {
- fz_try(ctx)
- {
- my_stroke = fz_clone_stroke_state(ctx, stroke);
- }
- fz_catch(ctx)
- {
- fz_drop_path(ctx, my_path);
- fz_rethrow(ctx);
- }
- }
- if (rect_off)
- {
- fz_rect *out_rect = (fz_rect *)(void *)(&node_ptr[rect_off]);
- writer->rect = *rect;
- *out_rect = *rect;
- if (rect_for_updates)
- writer->stack[writer->top-1].update = out_rect;
- }
- if (path_off)
- {
- fz_drop_path(ctx, writer->path);
- writer->path = fz_keep_path(ctx, my_path); /* Can never fail */
- }
- if (node.cs)
- {
- fz_drop_colorspace(ctx, writer->colorspace);
- switch(node.cs)
- {
- case CS_GRAY_0:
- writer->colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
- writer->color[0] = 0;
- break;
- case CS_GRAY_1:
- writer->colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
- writer->color[0] = 1;
- break;
- case CS_RGB_0:
- writer->color[0] = 0;
- writer->color[1] = 0;
- writer->color[2] = 0;
- writer->colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- break;
- case CS_RGB_1:
- writer->color[0] = 1;
- writer->color[1] = 1;
- writer->color[2] = 1;
- writer->colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- break;
- case CS_CMYK_0:
- writer->color[0] = 0;
- writer->color[1] = 0;
- writer->color[2] = 0;
- writer->color[3] = 0;
- writer->colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- break;
- case CS_CMYK_1:
- writer->color[0] = 0;
- writer->color[1] = 0;
- writer->color[2] = 0;
- writer->color[3] = 1;
- writer->colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- break;
- default:
- {
- fz_colorspace **out_colorspace = (fz_colorspace **)(void *)(&node_ptr[colorspace_off]);
- int i, n;
- n = fz_colorspace_n(ctx, colorspace);
- *out_colorspace = fz_keep_colorspace(ctx, colorspace);
- writer->colorspace = fz_keep_colorspace(ctx, colorspace);
- for (i = 0; i < n; i++)
- writer->color[i] = 0;
- break;
- }
- }
- }
- if (color_off)
- {
- int n = fz_colorspace_n(ctx, colorspace);
- float *out_color = (float *)(void *)(&node_ptr[color_off]);
- memcpy(writer->color, color, n * sizeof(float));
- memcpy(out_color, color, n * sizeof(float));
- }
- if (node.alpha)
- {
- writer->alpha = *alpha;
- if (alpha_off)
- {
- float *out_alpha = (float *)(void *)(&node_ptr[alpha_off]);
- *out_alpha = *alpha;
- }
- }
- if (ctm_off)
- {
- float *out_ctm = (float *)(void *)(&node_ptr[ctm_off]);
- if (node.ctm & CTM_CHANGE_AD)
- {
- writer->ctm.a = *out_ctm++ = ctm->a;
- writer->ctm.d = *out_ctm++ = ctm->d;
- }
- if (node.ctm & CTM_CHANGE_BC)
- {
- writer->ctm.b = *out_ctm++ = ctm->b;
- writer->ctm.c = *out_ctm++ = ctm->c;
- }
- if (node.ctm & CTM_CHANGE_EF)
- {
- writer->ctm.e = *out_ctm++ = ctm->e;
- writer->ctm.f = *out_ctm = ctm->f;
- }
- }
- if (stroke_off)
- {
- fz_stroke_state **out_stroke = (fz_stroke_state **)(void *)(&node_ptr[stroke_off]);
- *out_stroke = my_stroke;
- fz_drop_stroke_state(ctx, writer->stroke);
- /* Can never fail as my_stroke was cloned above */
- writer->stroke = fz_keep_stroke_state(ctx, my_stroke);
- }
- if (private_data_len)
- {
- out_private = (unsigned char *)(void *)(&node_ptr[private_off]);
- if (private_data)
- memcpy(out_private, private_data, private_data_len);
- }
- list->len += size;
- return out_private;
- }
- /* Pack ri, op, opm, bp into flags upper bits, even/odd in lower bit */
- static int
- fz_pack_color_params(fz_color_params color_params)
- {
- int flags = 0;
- flags |= color_params.ri << RI; /* 2 bits */
- flags |= color_params.bp << BP;
- flags |= color_params.op << OP;
- flags |= color_params.opm << OPM;
- return flags;
- }
- /* unpack ri, op, opm, bp from flags, even/odd in lower bit */
- static void
- fz_unpack_color_params(fz_color_params *color_params, int flags)
- {
- color_params->ri = (flags >> RI) & 3;
- color_params->bp = (flags >> BP) & 1;
- color_params->op = (flags >> OP) & 1;
- color_params->opm = (flags >> OPM) & 1;
- }
- static void
- fz_list_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm,
- fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
- {
- fz_rect rect = fz_bound_path(ctx, path, NULL, ctm);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_FILL_PATH,
- even_odd | fz_pack_color_params(color_params), /* flags */
- &rect,
- path, /* path */
- color,
- colorspace,
- &alpha, /* alpha */
- &ctm,
- NULL, /* stroke_state */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke,
- fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
- {
- fz_rect rect = fz_bound_path(ctx, path, stroke, ctm);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_STROKE_PATH,
- fz_pack_color_params(color_params), /* flags */
- &rect,
- path, /* path */
- color,
- colorspace,
- &alpha, /* alpha */
- &ctm, /* ctm */
- stroke,
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor)
- {
- fz_rect rect = fz_bound_path(ctx, path, NULL, ctm);
- rect = fz_intersect_rect(rect, scissor);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_CLIP_PATH,
- even_odd, /* flags */
- &rect,
- path, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- &ctm, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- 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)
- {
- fz_rect rect = fz_bound_path(ctx, path, stroke, ctm);
- rect = fz_intersect_rect(rect, scissor);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_CLIP_STROKE_PATH,
- 0, /* flags */
- &rect,
- path, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- &ctm, /* ctm */
- stroke, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm,
- fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
- {
- fz_text *cloned_text = fz_keep_text(ctx, text);
- fz_try(ctx)
- {
- fz_rect rect = fz_bound_text(ctx, text, NULL, ctm);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_FILL_TEXT,
- fz_pack_color_params(color_params), /* flags */
- &rect,
- NULL, /* path */
- color, /* color */
- colorspace, /* colorspace */
- &alpha, /* alpha */
- &ctm, /* ctm */
- NULL, /* stroke */
- &cloned_text, /* private_data */
- sizeof(cloned_text)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_text(ctx, cloned_text);
- fz_rethrow(ctx);
- }
- }
- static void
- fz_list_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm,
- fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
- {
- fz_text *cloned_text = fz_keep_text(ctx, text);
- fz_try(ctx)
- {
- fz_rect rect = fz_bound_text(ctx, text, stroke, ctm);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_STROKE_TEXT,
- fz_pack_color_params(color_params), /* flags */
- &rect,
- NULL, /* path */
- color, /* color */
- colorspace, /* colorspace */
- &alpha, /* alpha */
- &ctm, /* ctm */
- stroke,
- &cloned_text, /* private_data */
- sizeof(cloned_text)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_text(ctx, cloned_text);
- fz_rethrow(ctx);
- }
- }
- static void
- fz_list_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor)
- {
- fz_text *cloned_text = fz_keep_text(ctx, text);
- fz_try(ctx)
- {
- fz_rect rect = fz_bound_text(ctx, text, NULL, ctm);
- rect = fz_intersect_rect(rect, scissor);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_CLIP_TEXT,
- 0, /* flags */
- &rect,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- &ctm, /* ctm */
- NULL, /* stroke */
- &cloned_text, /* private_data */
- sizeof(cloned_text)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_text(ctx, cloned_text);
- fz_rethrow(ctx);
- }
- }
- static void
- 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)
- {
- fz_text *cloned_text = fz_keep_text(ctx, text);
- fz_try(ctx)
- {
- fz_rect rect = fz_bound_text(ctx, text, stroke, ctm);
- rect = fz_intersect_rect(rect, scissor);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_CLIP_STROKE_TEXT,
- 0, /* flags */
- &rect,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- &ctm, /* ctm */
- stroke, /* stroke */
- &cloned_text, /* private_data */
- sizeof(cloned_text)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_text(ctx, cloned_text);
- fz_rethrow(ctx);
- }
- }
- static void
- fz_list_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm)
- {
- fz_text *cloned_text = fz_keep_text(ctx, text);
- fz_try(ctx)
- {
- fz_rect rect = fz_bound_text(ctx, text, NULL, ctm);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_IGNORE_TEXT,
- 0, /* flags */
- &rect,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- &ctm, /* ctm */
- NULL, /* stroke */
- &cloned_text, /* private_data */
- sizeof(cloned_text)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_text(ctx, cloned_text);
- fz_rethrow(ctx);
- }
- }
- static void
- fz_list_pop_clip(fz_context *ctx, fz_device *dev)
- {
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_POP_CLIP,
- 0, /* flags */
- NULL, /* rect */
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params)
- {
- fz_shade *shade2 = fz_keep_shade(ctx, shade);
- fz_try(ctx)
- {
- fz_rect rect = fz_bound_shade(ctx, shade, ctm);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_FILL_SHADE,
- fz_pack_color_params(color_params), /* flags */
- &rect,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- &alpha, /* alpha */
- &ctm, /* ctm */
- NULL, /* stroke */
- &shade2, /* private_data */
- sizeof(shade2)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_shade(ctx, shade2);
- fz_rethrow(ctx);
- }
- }
- static void
- fz_list_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params)
- {
- fz_image *image2 = fz_keep_image(ctx, image);
- fz_try(ctx)
- {
- fz_rect rect = fz_transform_rect(fz_unit_rect, ctm);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_FILL_IMAGE,
- fz_pack_color_params(color_params), /* flags */
- &rect,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- &alpha, /* alpha */
- &ctm, /* ctm */
- NULL, /* stroke */
- &image2, /* private_data */
- sizeof(image2)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_image(ctx, image2);
- fz_rethrow(ctx);
- }
- }
- static void
- fz_list_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm,
- fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
- {
- fz_image *image2 = fz_keep_image(ctx, image);
- fz_try(ctx)
- {
- fz_rect rect = fz_transform_rect(fz_unit_rect, ctm);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_FILL_IMAGE_MASK,
- fz_pack_color_params(color_params), /* flags */
- &rect,
- NULL, /* path */
- color,
- colorspace,
- &alpha, /* alpha */
- &ctm, /* ctm */
- NULL, /* stroke */
- &image2, /* private_data */
- sizeof(image2)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_image(ctx, image2);
- fz_rethrow(ctx);
- }
- }
- static void
- fz_list_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor)
- {
- fz_image *image2 = fz_keep_image(ctx, image);
- fz_try(ctx)
- {
- fz_rect rect = fz_transform_rect(fz_unit_rect, ctm);
- rect = fz_intersect_rect(rect, scissor);
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_CLIP_IMAGE_MASK,
- 0, /* flags */
- &rect,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- &ctm, /* ctm */
- NULL, /* stroke */
- &image2, /* private_data */
- sizeof(image2)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_image(ctx, image2);
- fz_rethrow(ctx);
- }
- }
- static void
- 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)
- {
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_BEGIN_MASK,
- (!!luminosity) | fz_pack_color_params(color_params), /* flags */
- &rect,
- NULL, /* path */
- color,
- colorspace,
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
- {
- fz_function *tr2 = fz_keep_function(ctx, tr);
- fz_try(ctx)
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_END_MASK,
- 0, /* flags */
- NULL, /* rect */
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- &tr2, /* private_data */
- sizeof(tr2)); /* private_data_len */
- fz_catch(ctx)
- {
- fz_drop_function(ctx, tr);
- fz_rethrow(ctx);
- }
- }
- static void
- fz_list_begin_group(fz_context *ctx, fz_device *dev, fz_rect rect, fz_colorspace *colorspace, int isolated, int knockout, int blendmode, float alpha)
- {
- int flags;
- static const float color[FZ_MAX_COLORS] = { 0 };
- flags = (blendmode<<2);
- if (isolated)
- flags |= ISOLATED;
- if (knockout)
- flags |= KNOCKOUT;
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_BEGIN_GROUP,
- flags,
- &rect,
- NULL, /* path */
- color, /* color */
- colorspace, /* colorspace */
- &alpha, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_end_group(fz_context *ctx, fz_device *dev)
- {
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_END_GROUP,
- 0, /* flags */
- NULL, /* rect */
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- typedef struct
- {
- float xstep;
- float ystep;
- fz_rect view;
- int id;
- } fz_list_tile_data;
- static int
- 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)
- {
- fz_list_tile_data tile;
- tile.xstep = xstep;
- tile.ystep = ystep;
- tile.view = view;
- tile.id = id;
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_BEGIN_TILE,
- 0, /* flags */
- &area,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- &ctm, /* ctm */
- NULL, /* stroke */
- &tile, /* private_data */
- sizeof(tile)); /* private_data_len */
- return 0;
- }
- static void
- fz_list_end_tile(fz_context *ctx, fz_device *dev)
- {
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_END_TILE,
- 0, /* flags */
- NULL,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
- {
- int flags;
- /* Pack the options down */
- if (set == FZ_DEVFLAG_GRIDFIT_AS_TILED && clear == 0)
- flags = 1;
- else if (set == 0 && clear == FZ_DEVFLAG_GRIDFIT_AS_TILED)
- flags = 0;
- else
- {
- assert("Unsupported flags combination" == NULL);
- return;
- }
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_RENDER_FLAGS,
- flags, /* flags */
- NULL,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs)
- {
- fz_default_colorspaces *default_cs2 = fz_keep_default_colorspaces(ctx, default_cs);
- fz_try(ctx)
- {
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_DEFAULT_COLORSPACES,
- 0, /* flags */
- NULL,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- &default_cs2, /* private_data */
- sizeof(default_cs2)); /* private_data_len */
- }
- fz_catch(ctx)
- {
- fz_drop_default_colorspaces(ctx, default_cs2);
- fz_rethrow(ctx);
- }
- }
- static void
- fz_list_begin_layer(fz_context *ctx, fz_device *dev, const char *layer_name)
- {
- size_t len = layer_name ? strlen(layer_name) : 0;
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_BEGIN_LAYER,
- 0, /* flags */
- NULL,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL,
- NULL, /* stroke */
- len ? layer_name : "", /* private_data */
- len + 1); /* private_data_len */
- }
- static void
- fz_list_end_layer(fz_context *ctx, fz_device *dev)
- {
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_END_LAYER,
- 0, /* flags */
- NULL,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_begin_structure(fz_context *ctx, fz_device *dev, fz_structure standard, const char *raw, int idx)
- {
- unsigned char *data;
- size_t len = (raw ? strlen(raw) : 0);
- data = fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_BEGIN_STRUCTURE,
- 0, /* flags */
- NULL,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL,
- NULL, /* stroke */
- NULL, /* private_data */
- len+2+sizeof(idx)); /* private_data_len */
- data[0] = (char)standard;
- memcpy(data+1, &idx, sizeof(idx));
- if (len)
- memcpy(data+1+sizeof(idx), raw, len+1);
- else
- data[1+sizeof(idx)] = 0;
- }
- static void
- fz_list_end_structure(fz_context *ctx, fz_device *dev)
- {
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_END_STRUCTURE,
- 0, /* flags */
- NULL,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_begin_metatext(fz_context *ctx, fz_device *dev, fz_metatext meta, const char *text)
- {
- unsigned char *data;
- size_t len = (text ? strlen(text) : 0);
- data = fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_BEGIN_METATEXT,
- 0, /* flags */
- NULL,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL,
- NULL, /* stroke */
- NULL, /* private_data */
- len + 2); /* private_data_len */
- data[0] = (char)meta;
- if (len)
- memcpy(data+1, text, len+1);
- else
- data[1] = 0;
- }
- static void
- fz_list_end_metatext(fz_context *ctx, fz_device *dev)
- {
- fz_append_display_node(
- ctx,
- dev,
- FZ_CMD_END_METATEXT,
- 0, /* flags */
- NULL,
- NULL, /* path */
- NULL, /* color */
- NULL, /* colorspace */
- NULL, /* alpha */
- NULL, /* ctm */
- NULL, /* stroke */
- NULL, /* private_data */
- 0); /* private_data_len */
- }
- static void
- fz_list_drop_device(fz_context *ctx, fz_device *dev)
- {
- fz_list_device *writer = (fz_list_device *)dev;
- fz_drop_colorspace(ctx, writer->colorspace);
- fz_drop_stroke_state(ctx, writer->stroke);
- fz_drop_path(ctx, writer->path);
- fz_drop_display_list(ctx, writer->list);
- }
- fz_device *
- fz_new_list_device(fz_context *ctx, fz_display_list *list)
- {
- fz_list_device *dev;
- dev = fz_new_derived_device(ctx, fz_list_device);
- dev->super.fill_path = fz_list_fill_path;
- dev->super.stroke_path = fz_list_stroke_path;
- dev->super.clip_path = fz_list_clip_path;
- dev->super.clip_stroke_path = fz_list_clip_stroke_path;
- dev->super.fill_text = fz_list_fill_text;
- dev->super.stroke_text = fz_list_stroke_text;
- dev->super.clip_text = fz_list_clip_text;
- dev->super.clip_stroke_text = fz_list_clip_stroke_text;
- dev->super.ignore_text = fz_list_ignore_text;
- dev->super.fill_shade = fz_list_fill_shade;
- dev->super.fill_image = fz_list_fill_image;
- dev->super.fill_image_mask = fz_list_fill_image_mask;
- dev->super.clip_image_mask = fz_list_clip_image_mask;
- dev->super.pop_clip = fz_list_pop_clip;
- dev->super.begin_mask = fz_list_begin_mask;
- dev->super.end_mask = fz_list_end_mask;
- dev->super.begin_group = fz_list_begin_group;
- dev->super.end_group = fz_list_end_group;
- dev->super.begin_tile = fz_list_begin_tile;
- dev->super.end_tile = fz_list_end_tile;
- dev->super.render_flags = fz_list_render_flags;
- dev->super.set_default_colorspaces = fz_list_set_default_colorspaces;
- dev->super.begin_layer = fz_list_begin_layer;
- dev->super.end_layer = fz_list_end_layer;
- dev->super.begin_structure = fz_list_begin_structure;
- dev->super.end_structure = fz_list_end_structure;
- dev->super.begin_metatext = fz_list_begin_metatext;
- dev->super.end_metatext = fz_list_end_metatext;
- dev->super.drop_device = fz_list_drop_device;
- dev->list = fz_keep_display_list(ctx, list);
- dev->path = NULL;
- dev->alpha = 1.0f;
- dev->ctm = fz_identity;
- dev->stroke = NULL;
- dev->colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
- memset(dev->color, 0, sizeof(float)*FZ_MAX_COLORS);
- dev->top = 0;
- dev->tiled = 0;
- return &dev->super;
- }
- static void
- fz_drop_display_list_imp(fz_context *ctx, fz_storable *list_)
- {
- fz_display_list *list = (fz_display_list *)list_;
- fz_display_node *node = list->list;
- fz_display_node *node_end = list->list + list->len;
- int cs_n = 1;
- fz_colorspace *cs;
- while (node != node_end)
- {
- fz_display_node n = *node;
- size_t size = n.size;
- fz_display_node *next;
- if (size == INDIRECT_NODE_THRESHOLD)
- {
- memcpy(&size, &node[1], sizeof(size));
- node += SIZE_IN_NODES(sizeof(size_t));
- size -= SIZE_IN_NODES(sizeof(size_t));
- }
- next = node + size;
- node++;
- if (n.rect)
- {
- node += SIZE_IN_NODES(sizeof(fz_rect));
- }
- switch (n.cs)
- {
- default:
- case CS_UNCHANGED:
- break;
- case CS_GRAY_0:
- case CS_GRAY_1:
- cs_n = 1;
- break;
- case CS_RGB_0:
- case CS_RGB_1:
- cs_n = 3;
- break;
- case CS_CMYK_0:
- case CS_CMYK_1:
- cs_n = 4;
- break;
- case CS_OTHER_0:
- align_node_for_pointer(&node);
- cs = *(fz_colorspace **)node;
- cs_n = fz_colorspace_n(ctx, cs);
- fz_drop_colorspace(ctx, cs);
- node += SIZE_IN_NODES(sizeof(fz_colorspace *));
- break;
- }
- if (n.color)
- {
- node += SIZE_IN_NODES(cs_n * sizeof(float));
- }
- if (n.alpha == ALPHA_PRESENT)
- {
- node += SIZE_IN_NODES(sizeof(float));
- }
- if (n.ctm & CTM_CHANGE_AD)
- node += SIZE_IN_NODES(2*sizeof(float));
- if (n.ctm & CTM_CHANGE_BC)
- node += SIZE_IN_NODES(2*sizeof(float));
- if (n.ctm & CTM_CHANGE_EF)
- node += SIZE_IN_NODES(2*sizeof(float));
- if (n.stroke)
- {
- align_node_for_pointer(&node);
- fz_drop_stroke_state(ctx, *(fz_stroke_state **)node);
- node += SIZE_IN_NODES(sizeof(fz_stroke_state *));
- }
- if (n.path)
- {
- int path_size;
- align_node_for_pointer(&node);
- path_size = fz_packed_path_size((fz_path *)node);
- fz_drop_path(ctx, (fz_path *)node);
- node += SIZE_IN_NODES(path_size);
- }
- switch(n.cmd)
- {
- case FZ_CMD_FILL_TEXT:
- case FZ_CMD_STROKE_TEXT:
- case FZ_CMD_CLIP_TEXT:
- case FZ_CMD_CLIP_STROKE_TEXT:
- case FZ_CMD_IGNORE_TEXT:
- align_node_for_pointer(&node);
- fz_drop_text(ctx, *(fz_text **)node);
- break;
- case FZ_CMD_FILL_SHADE:
- align_node_for_pointer(&node);
- fz_drop_shade(ctx, *(fz_shade **)node);
- break;
- case FZ_CMD_FILL_IMAGE:
- case FZ_CMD_FILL_IMAGE_MASK:
- case FZ_CMD_CLIP_IMAGE_MASK:
- align_node_for_pointer(&node);
- fz_drop_image(ctx, *(fz_image **)node);
- break;
- case FZ_CMD_END_MASK:
- align_node_for_pointer(&node);
- fz_drop_function(ctx, *(fz_function **)node);
- break;
- case FZ_CMD_DEFAULT_COLORSPACES:
- align_node_for_pointer(&node);
- fz_drop_default_colorspaces(ctx, *(fz_default_colorspaces **)node);
- break;
- }
- node = next;
- }
- fz_free(ctx, list->list);
- fz_free(ctx, list);
- }
- fz_display_list *
- fz_new_display_list(fz_context *ctx, fz_rect mediabox)
- {
- fz_display_list *list = fz_malloc_struct(ctx, fz_display_list);
- FZ_INIT_STORABLE(list, 1, fz_drop_display_list_imp);
- list->list = NULL;
- list->mediabox = mediabox;
- list->max = 0;
- list->len = 0;
- return list;
- }
- fz_display_list *
- fz_keep_display_list(fz_context *ctx, fz_display_list *list)
- {
- return fz_keep_storable(ctx, &list->storable);
- }
- void
- fz_drop_display_list(fz_context *ctx, fz_display_list *list)
- {
- fz_defer_reap_start(ctx);
- fz_drop_storable(ctx, &list->storable);
- fz_defer_reap_end(ctx);
- }
- fz_rect
- fz_bound_display_list(fz_context *ctx, fz_display_list *list)
- {
- return list->mediabox;
- }
- int fz_display_list_is_empty(fz_context *ctx, const fz_display_list *list)
- {
- return !list || list->len == 0;
- }
- void
- fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz_rect scissor, fz_cookie *cookie)
- {
- fz_display_node *node;
- fz_display_node *node_end;
- fz_display_node *next_node;
- int clipped = 0;
- int tiled = 0;
- int progress = 0;
- /* Current graphics state as unpacked from list */
- fz_path *path = NULL;
- float alpha = 1.0f;
- fz_matrix ctm = fz_identity;
- fz_stroke_state *stroke = NULL;
- float color[FZ_MAX_COLORS] = { 0 };
- fz_colorspace *colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
- fz_color_params color_params;
- fz_rect rect = { 0 };
- /* Transformed versions of graphic state entries */
- fz_rect trans_rect;
- fz_matrix trans_ctm;
- int tile_skip_depth = 0;
- if (cookie)
- {
- cookie->progress_max = list->len;
- cookie->progress = 0;
- }
- color_params = fz_default_color_params;
- node = list->list;
- node_end = &list->list[list->len];
- for (; node != node_end ; node = next_node)
- {
- int empty;
- fz_display_node n = *node;
- size_t size = n.size;
- if (size == INDIRECT_NODE_THRESHOLD)
- {
- memcpy(&size, &node[1], sizeof(size_t));
- node += SIZE_IN_NODES(sizeof(size_t));
- size -= SIZE_IN_NODES(sizeof(size_t));
- }
- next_node = node + size;
- /* Check the cookie for aborting */
- if (cookie)
- {
- if (cookie->abort)
- break;
- cookie->progress = progress;
- progress += (int)size;
- }
- node++;
- if (n.rect)
- {
- rect = *(fz_rect *)node;
- node += SIZE_IN_NODES(sizeof(fz_rect));
- }
- if (n.cs)
- {
- int i, en;
- fz_drop_colorspace(ctx, colorspace);
- switch (n.cs)
- {
- default:
- case CS_GRAY_0:
- colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
- color[0] = 0.0f;
- break;
- case CS_GRAY_1:
- colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
- color[0] = 1.0f;
- break;
- case CS_RGB_0:
- colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- color[0] = 0.0f;
- color[1] = 0.0f;
- color[2] = 0.0f;
- break;
- case CS_RGB_1:
- colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- color[0] = 1.0f;
- color[1] = 1.0f;
- color[2] = 1.0f;
- break;
- case CS_CMYK_0:
- colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- color[0] = 0.0f;
- color[1] = 0.0f;
- color[2] = 0.0f;
- color[3] = 0.0f;
- break;
- case CS_CMYK_1:
- colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- color[0] = 0.0f;
- color[1] = 0.0f;
- color[2] = 0.0f;
- color[3] = 1.0f;
- break;
- case CS_OTHER_0:
- align_node_for_pointer(&node);
- colorspace = fz_keep_colorspace(ctx, *(fz_colorspace **)(node));
- node += SIZE_IN_NODES(sizeof(fz_colorspace *));
- en = fz_colorspace_n(ctx, colorspace);
- for (i = 0; i < en; i++)
- color[i] = 0.0f;
- break;
- }
- }
- if (n.color)
- {
- int nc = fz_colorspace_n(ctx, colorspace);
- memcpy(color, (float *)node, nc * sizeof(float));
- node += SIZE_IN_NODES(nc * sizeof(float));
- }
- if (n.alpha)
- {
- switch(n.alpha)
- {
- default:
- case ALPHA_0:
- alpha = 0.0f;
- break;
- case ALPHA_1:
- alpha = 1.0f;
- break;
- case ALPHA_PRESENT:
- alpha = *(float *)node;
- node += SIZE_IN_NODES(sizeof(float));
- break;
- }
- }
- if (n.ctm != 0)
- {
- float *packed_ctm = (float *)node;
- if (n.ctm & CTM_CHANGE_AD)
- {
- ctm.a = *packed_ctm++;
- ctm.d = *packed_ctm++;
- node += SIZE_IN_NODES(2*sizeof(float));
- }
- if (n.ctm & CTM_CHANGE_BC)
- {
- ctm.b = *packed_ctm++;
- ctm.c = *packed_ctm++;
- node += SIZE_IN_NODES(2*sizeof(float));
- }
- if (n.ctm & CTM_CHANGE_EF)
- {
- ctm.e = *packed_ctm++;
- ctm.f = *packed_ctm;
- node += SIZE_IN_NODES(2*sizeof(float));
- }
- }
- if (n.stroke)
- {
- align_node_for_pointer(&node);
- fz_drop_stroke_state(ctx, stroke);
- stroke = fz_keep_stroke_state(ctx, *(fz_stroke_state **)node);
- node += SIZE_IN_NODES(sizeof(fz_stroke_state *));
- }
- if (n.path)
- {
- align_node_for_pointer(&node);
- fz_drop_path(ctx, path);
- path = fz_keep_path(ctx, (fz_path *)node);
- node += SIZE_IN_NODES(fz_packed_path_size(path));
- }
- if (tile_skip_depth > 0)
- {
- if (n.cmd == FZ_CMD_BEGIN_TILE)
- tile_skip_depth++;
- else if (n.cmd == FZ_CMD_END_TILE)
- tile_skip_depth--;
- if (tile_skip_depth > 0)
- continue;
- }
- trans_rect = fz_transform_rect(rect, top_ctm);
- /* cull objects to draw using a quick visibility test */
- if (tiled ||
- n.cmd == FZ_CMD_BEGIN_TILE || n.cmd == FZ_CMD_END_TILE ||
- n.cmd == FZ_CMD_RENDER_FLAGS || n.cmd == FZ_CMD_DEFAULT_COLORSPACES ||
- n.cmd == FZ_CMD_BEGIN_LAYER || n.cmd == FZ_CMD_END_LAYER ||
- n.cmd == FZ_CMD_BEGIN_STRUCTURE || n.cmd == FZ_CMD_END_STRUCTURE ||
- n.cmd == FZ_CMD_BEGIN_METATEXT || n.cmd == FZ_CMD_END_METATEXT
- )
- {
- empty = 0;
- }
- else if (n.cmd == FZ_CMD_FILL_PATH || n.cmd == FZ_CMD_STROKE_PATH)
- {
- /* Zero area paths are suitable for stroking. */
- empty = !fz_is_valid_rect(fz_intersect_rect(trans_rect, scissor));
- }
- else if (n.cmd == FZ_CMD_FILL_TEXT || n.cmd == FZ_CMD_STROKE_TEXT ||
- n.cmd == FZ_CMD_CLIP_TEXT || n.cmd == FZ_CMD_CLIP_STROKE_TEXT)
- {
- /* Zero area text (such as spaces) should be passed
- * through. Text that is completely outside the scissor
- * can be elided. */
- empty = !fz_is_valid_rect(fz_intersect_rect(trans_rect, scissor));
- }
- else
- {
- empty = fz_is_empty_rect(fz_intersect_rect(trans_rect, scissor));
- }
- /* clipped starts out as 0. It only goes non-zero here if we move inside
- * an 'empty' region. Whenever clipped is non zero, or we are in an empty
- * region, we therefore may need to increment clipped according to the
- * nesting. */
- if (clipped || empty)
- {
- switch (n.cmd)
- {
- case FZ_CMD_CLIP_PATH:
- case FZ_CMD_CLIP_STROKE_PATH:
- case FZ_CMD_CLIP_TEXT:
- case FZ_CMD_CLIP_STROKE_TEXT:
- case FZ_CMD_CLIP_IMAGE_MASK:
- case FZ_CMD_BEGIN_MASK:
- case FZ_CMD_BEGIN_GROUP:
- clipped++;
- continue;
- case FZ_CMD_BEGIN_STRUCTURE:
- case FZ_CMD_END_STRUCTURE:
- case FZ_CMD_BEGIN_METATEXT:
- case FZ_CMD_END_METATEXT:
- /* These may not nest as nicely as we'd like. Just ignore them for
- * the purposes of clipping. */
- break;
- case FZ_CMD_POP_CLIP:
- case FZ_CMD_END_GROUP:
- if (!clipped)
- goto visible;
- clipped--;
- continue;
- case FZ_CMD_END_MASK:
- if (!clipped)
- goto visible;
- continue;
- default:
- continue;
- }
- }
- visible:
- trans_ctm = fz_concat(ctm, top_ctm);
- fz_try(ctx)
- {
- switch (n.cmd)
- {
- case FZ_CMD_FILL_PATH:
- fz_unpack_color_params(&color_params, n.flags);
- fz_fill_path(ctx, dev, path, n.flags & 1, trans_ctm, colorspace, color, alpha, color_params);
- break;
- case FZ_CMD_STROKE_PATH:
- fz_unpack_color_params(&color_params, n.flags);
- fz_stroke_path(ctx, dev, path, stroke, trans_ctm, colorspace, color, alpha, color_params);
- break;
- case FZ_CMD_CLIP_PATH:
- fz_clip_path(ctx, dev, path, n.flags, trans_ctm, trans_rect);
- break;
- case FZ_CMD_CLIP_STROKE_PATH:
- fz_clip_stroke_path(ctx, dev, path, stroke, trans_ctm, trans_rect);
- break;
- case FZ_CMD_FILL_TEXT:
- fz_unpack_color_params(&color_params, n.flags);
- align_node_for_pointer(&node);
- fz_fill_text(ctx, dev, *(fz_text **)node, trans_ctm, colorspace, color, alpha, color_params);
- break;
- case FZ_CMD_STROKE_TEXT:
- fz_unpack_color_params(&color_params, n.flags);
- align_node_for_pointer(&node);
- fz_stroke_text(ctx, dev, *(fz_text **)node, stroke, trans_ctm, colorspace, color, alpha, color_params);
- break;
- case FZ_CMD_CLIP_TEXT:
- align_node_for_pointer(&node);
- fz_clip_text(ctx, dev, *(fz_text **)node, trans_ctm, trans_rect);
- break;
- case FZ_CMD_CLIP_STROKE_TEXT:
- align_node_for_pointer(&node);
- fz_clip_stroke_text(ctx, dev, *(fz_text **)node, stroke, trans_ctm, trans_rect);
- break;
- case FZ_CMD_IGNORE_TEXT:
- align_node_for_pointer(&node);
- fz_ignore_text(ctx, dev, *(fz_text **)node, trans_ctm);
- break;
- case FZ_CMD_FILL_SHADE:
- fz_unpack_color_params(&color_params, n.flags);
- align_node_for_pointer(&node);
- fz_fill_shade(ctx, dev, *(fz_shade **)node, trans_ctm, alpha, color_params);
- break;
- case FZ_CMD_FILL_IMAGE:
- fz_unpack_color_params(&color_params, n.flags);
- align_node_for_pointer(&node);
- fz_fill_image(ctx, dev, *(fz_image **)node, trans_ctm, alpha, color_params);
- break;
- case FZ_CMD_FILL_IMAGE_MASK:
- fz_unpack_color_params(&color_params, n.flags);
- align_node_for_pointer(&node);
- fz_fill_image_mask(ctx, dev, *(fz_image **)node, trans_ctm, colorspace, color, alpha, color_params);
- break;
- case FZ_CMD_CLIP_IMAGE_MASK:
- align_node_for_pointer(&node);
- fz_clip_image_mask(ctx, dev, *(fz_image **)node, trans_ctm, trans_rect);
- break;
- case FZ_CMD_POP_CLIP:
- fz_pop_clip(ctx, dev);
- break;
- case FZ_CMD_BEGIN_MASK:
- fz_unpack_color_params(&color_params, n.flags);
- fz_begin_mask(ctx, dev, trans_rect, n.flags & 1, colorspace, color, color_params);
- break;
- case FZ_CMD_END_MASK:
- align_node_for_pointer(&node);
- fz_end_mask_tr(ctx, dev, *(fz_function **)node);
- break;
- case FZ_CMD_BEGIN_GROUP:
- fz_begin_group(ctx, dev, trans_rect, colorspace, (n.flags & ISOLATED) != 0, (n.flags & KNOCKOUT) != 0, (n.flags>>2), alpha);
- break;
- case FZ_CMD_END_GROUP:
- fz_end_group(ctx, dev);
- break;
- case FZ_CMD_BEGIN_TILE:
- {
- int cached;
- fz_list_tile_data *data;
- fz_rect tile_rect;
- data = (fz_list_tile_data *)node;
- tiled++;
- tile_rect = data->view;
- cached = fz_begin_tile_id(ctx, dev, rect, tile_rect, data->xstep, data->ystep, trans_ctm, data->id);
- if (cached)
- tile_skip_depth = 1;
- break;
- }
- case FZ_CMD_END_TILE:
- tiled--;
- fz_end_tile(ctx, dev);
- break;
- case FZ_CMD_RENDER_FLAGS:
- if (n.flags == 0)
- fz_render_flags(ctx, dev, 0, FZ_DEVFLAG_GRIDFIT_AS_TILED);
- else if (n.flags == 1)
- fz_render_flags(ctx, dev, FZ_DEVFLAG_GRIDFIT_AS_TILED, 0);
- break;
- case FZ_CMD_DEFAULT_COLORSPACES:
- align_node_for_pointer(&node);
- fz_set_default_colorspaces(ctx, dev, *(fz_default_colorspaces **)node);
- break;
- case FZ_CMD_BEGIN_LAYER:
- fz_begin_layer(ctx, dev, (const char *)node);
- break;
- case FZ_CMD_END_LAYER:
- fz_end_layer(ctx, dev);
- break;
- case FZ_CMD_BEGIN_STRUCTURE:
- {
- const unsigned char *data;
- int idx;
- data = (const unsigned char *)node;
- memcpy(&idx, data+1, sizeof(idx));
- fz_begin_structure(ctx, dev, (fz_structure)data[0], (const char *)(&data[1+sizeof(idx)]), idx);
- break;
- }
- case FZ_CMD_END_STRUCTURE:
- fz_end_structure(ctx, dev);
- break;
- case FZ_CMD_BEGIN_METATEXT:
- {
- const unsigned char *data;
- const char *text;
- data = (const unsigned char *)node;
- text = (const char *)&data[1];
- fz_begin_metatext(ctx, dev, (fz_metatext)data[0], text);
- break;
- }
- case FZ_CMD_END_METATEXT:
- fz_end_metatext(ctx, dev);
- break;
- }
- }
- fz_catch(ctx)
- {
- if (fz_caught(ctx) == FZ_ERROR_SYSTEM)
- {
- fz_drop_colorspace(ctx, colorspace);
- fz_drop_stroke_state(ctx, stroke);
- fz_drop_path(ctx, path);
- fz_rethrow(ctx);
- }
- /* Swallow the error */
- if (cookie)
- cookie->errors++;
- if (fz_caught(ctx) == FZ_ERROR_ABORT)
- {
- fz_ignore_error(ctx);
- break;
- }
- fz_report_error(ctx);
- fz_warn(ctx, "Ignoring error during interpretation");
- }
- }
- fz_drop_colorspace(ctx, colorspace);
- fz_drop_stroke_state(ctx, stroke);
- fz_drop_path(ctx, path);
- if (cookie)
- cookie->progress = progress;
- }
|