draw-device.c 95 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379
  1. // Copyright (C) 2004-2024 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/fitz.h"
  23. #include "context-imp.h"
  24. #include "color-imp.h"
  25. #include "draw-imp.h"
  26. #include "glyph-imp.h"
  27. #include "pixmap-imp.h"
  28. #include <string.h>
  29. #include <assert.h>
  30. #include <math.h>
  31. #include <float.h>
  32. #define STACK_SIZE 96
  33. /* Enable the following to attempt to support knockout and/or isolated
  34. * blending groups. */
  35. #define ATTEMPT_KNOCKOUT_AND_ISOLATED
  36. /* Enable the following to help debug group blending. */
  37. #undef DUMP_GROUP_BLENDS
  38. /* Enable the following to help debug graphics stack pushes/pops */
  39. #undef DUMP_STACK_CHANGES
  40. enum {
  41. FZ_DRAWDEV_FLAGS_TYPE3 = 1,
  42. };
  43. typedef struct {
  44. fz_irect scissor;
  45. fz_pixmap *dest;
  46. fz_pixmap *mask;
  47. fz_pixmap *shape;
  48. fz_pixmap *group_alpha;
  49. int blendmode;
  50. int id, encache;
  51. float alpha;
  52. fz_matrix ctm;
  53. float xstep, ystep;
  54. fz_irect area;
  55. int flags;
  56. } fz_draw_state;
  57. typedef struct fz_draw_device
  58. {
  59. fz_device super;
  60. fz_matrix transform;
  61. fz_rasterizer *rast;
  62. fz_default_colorspaces *default_cs;
  63. fz_colorspace *proof_cs;
  64. int flags;
  65. int resolve_spots;
  66. int overprint_possible;
  67. int top;
  68. fz_scale_cache *cache_x;
  69. fz_scale_cache *cache_y;
  70. fz_draw_state *stack;
  71. int stack_cap;
  72. fz_draw_state init_stack[STACK_SIZE];
  73. fz_shade_color_cache *shade_cache;
  74. } fz_draw_device;
  75. #ifdef DUMP_GROUP_BLENDS
  76. #include <stdio.h>
  77. static int group_dump_count = 0;
  78. static void fz_dump_blend(fz_context *ctx, const char *s, fz_pixmap *pix)
  79. {
  80. char name[80];
  81. int psd = 0;
  82. if (!pix)
  83. return;
  84. if (pix->s || fz_colorspace_is_subtractive(ctx, pix->colorspace))
  85. psd = 1;
  86. fz_snprintf(name, sizeof(name), "dump%02d.%s", group_dump_count, psd ? "psd" : "png");
  87. printf("%s%02d%s(%p)", s ? s : "", group_dump_count++, psd ? "(PSD)" : "", pix);
  88. if (psd)
  89. fz_save_pixmap_as_psd(ctx, pix, name);
  90. else
  91. fz_save_pixmap_as_png(ctx, pix, name);
  92. }
  93. static void dump_spaces(int x, const char *s)
  94. {
  95. int i;
  96. for (i = 0; i < x; i++)
  97. printf(" ");
  98. printf("%s", s);
  99. }
  100. #endif
  101. #ifdef DUMP_STACK_CHANGES
  102. #define STACK_PUSHED(A) stack_change(ctx, dev, '>', A)
  103. #define STACK_POPPED(A) stack_change(ctx, dev, '<', A)
  104. #define STACK_CONVERT(A) stack_change(ctx, dev, '=', A)
  105. static void stack_change(fz_context *ctx, fz_draw_device *dev, int c, const char *s)
  106. {
  107. int n, depth = dev->top;
  108. if (c != '<')
  109. depth--;
  110. n = depth;
  111. while (n-- > 0)
  112. fputc('\t', stderr);
  113. fprintf(stderr, "%c%s (%d)\n", c, s, depth);
  114. }
  115. #else
  116. #define STACK_PUSHED(A) do {} while (0)
  117. #define STACK_POPPED(A) do {} while (0)
  118. #define STACK_CONVERT(A) do {} while (0)
  119. #endif
  120. /* Logic below assumes that default cs is set to color context cs if there
  121. * was not a default in the document for that particular cs
  122. */
  123. static fz_colorspace *fz_default_colorspace(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs)
  124. {
  125. if (cs == NULL)
  126. return NULL;
  127. if (default_cs == NULL)
  128. return cs;
  129. switch (fz_colorspace_type(ctx, cs))
  130. {
  131. case FZ_COLORSPACE_GRAY:
  132. if (cs == fz_device_gray(ctx))
  133. return fz_default_gray(ctx, default_cs);
  134. break;
  135. case FZ_COLORSPACE_RGB:
  136. if (cs == fz_device_rgb(ctx))
  137. return fz_default_rgb(ctx, default_cs);
  138. break;
  139. case FZ_COLORSPACE_CMYK:
  140. if (cs == fz_device_cmyk(ctx))
  141. return fz_default_cmyk(ctx, default_cs);
  142. break;
  143. default:
  144. break;
  145. }
  146. return cs;
  147. }
  148. static void grow_stack(fz_context *ctx, fz_draw_device *dev)
  149. {
  150. int max = dev->stack_cap * 2;
  151. fz_draw_state *stack;
  152. if (dev->stack == &dev->init_stack[0])
  153. {
  154. stack = fz_malloc_array(ctx, max, fz_draw_state);
  155. memcpy(stack, dev->stack, sizeof(*stack) * dev->stack_cap);
  156. }
  157. else
  158. {
  159. stack = fz_realloc_array(ctx, dev->stack, max, fz_draw_state);
  160. }
  161. dev->stack = Memento_label(stack, "draw_stack");
  162. dev->stack_cap = max;
  163. }
  164. /* 'Push' the stack. Returns a pointer to the current state, with state[1]
  165. * already having been initialised to contain the same thing. Simply
  166. * change any contents of state[1] that you want to and continue. */
  167. static fz_draw_state *push_stack(fz_context *ctx, fz_draw_device *dev, const char *message)
  168. {
  169. fz_draw_state *state;
  170. if (dev->top == dev->stack_cap-1)
  171. grow_stack(ctx, dev);
  172. state = &dev->stack[dev->top];
  173. dev->top++;
  174. memcpy(&state[1], state, sizeof(*state));
  175. STACK_PUSHED(message);
  176. return state;
  177. }
  178. static fz_draw_state *pop_stack(fz_context *ctx, fz_draw_device *dev, const char *message)
  179. {
  180. fz_draw_state *state = &dev->stack[--dev->top];
  181. STACK_POPPED(message);
  182. return state;
  183. }
  184. static void
  185. cleanup_post_pop(fz_context *ctx, fz_draw_state *state)
  186. {
  187. if (state[0].dest != state[1].dest)
  188. {
  189. fz_drop_pixmap(ctx, state[1].dest);
  190. state[1].dest = NULL;
  191. }
  192. if (state[0].mask != state[1].mask)
  193. {
  194. fz_drop_pixmap(ctx, state[1].mask);
  195. state[1].mask = NULL;
  196. }
  197. if (state[1].group_alpha != state[0].group_alpha)
  198. {
  199. fz_drop_pixmap(ctx, state[1].group_alpha);
  200. state[1].group_alpha = NULL;
  201. }
  202. if (state[1].shape != state[0].shape)
  203. {
  204. fz_drop_pixmap(ctx, state[1].shape);
  205. state[1].shape = NULL;
  206. }
  207. }
  208. static fz_draw_state *convert_stack(fz_context *ctx, fz_draw_device *dev, const char *message)
  209. {
  210. fz_draw_state *state = &dev->stack[dev->top-1];
  211. STACK_CONVERT(message);
  212. return state;
  213. }
  214. static fz_draw_state *
  215. fz_knockout_begin(fz_context *ctx, fz_draw_device *dev)
  216. {
  217. fz_irect bbox, ga_bbox;
  218. fz_draw_state *state = &dev->stack[dev->top];
  219. int isolated = state->blendmode & FZ_BLEND_ISOLATED;
  220. if ((state->blendmode & FZ_BLEND_KNOCKOUT) == 0)
  221. return state;
  222. state = push_stack(ctx, dev, "knockout");
  223. bbox = fz_pixmap_bbox(ctx, state->dest);
  224. bbox = fz_intersect_irect(bbox, state->scissor);
  225. state[1].dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, bbox, state->dest->seps, state->dest->alpha);
  226. if (state[0].group_alpha)
  227. {
  228. ga_bbox = fz_pixmap_bbox(ctx, state->group_alpha);
  229. ga_bbox = fz_intersect_irect(ga_bbox, state->scissor);
  230. state[1].group_alpha = fz_new_pixmap_with_bbox(ctx, state->group_alpha->colorspace, ga_bbox, state->group_alpha->seps, state->group_alpha->alpha);
  231. }
  232. if (isolated)
  233. {
  234. fz_clear_pixmap(ctx, state[1].dest);
  235. if (state[1].group_alpha)
  236. fz_clear_pixmap(ctx, state[1].group_alpha);
  237. }
  238. else
  239. {
  240. /* Find the last but one destination to copy */
  241. int i = dev->top-1; /* i = the one on entry (i.e. the last one) */
  242. fz_draw_state *prev = state;
  243. while (i > 0)
  244. {
  245. prev = &dev->stack[--i];
  246. if (prev->dest != state->dest)
  247. break;
  248. }
  249. if (prev->dest)
  250. {
  251. fz_copy_pixmap_rect(ctx, state[1].dest, prev->dest, bbox, dev->default_cs);
  252. if (state[1].group_alpha)
  253. {
  254. if (prev->group_alpha)
  255. fz_copy_pixmap_rect(ctx, state[1].group_alpha, prev->group_alpha, ga_bbox, dev->default_cs);
  256. else
  257. fz_clear_pixmap(ctx, state[1].group_alpha);
  258. }
  259. }
  260. else
  261. {
  262. fz_clear_pixmap(ctx, state[1].dest);
  263. if (state[1].group_alpha)
  264. fz_clear_pixmap(ctx, state[1].group_alpha);
  265. }
  266. }
  267. /* Knockout groups (and only knockout groups) rely on shape */
  268. state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  269. fz_clear_pixmap(ctx, state[1].shape);
  270. #ifdef DUMP_GROUP_BLENDS
  271. dump_spaces(dev->top-1, "");
  272. fz_dump_blend(ctx, "Knockout begin: background is ", state[1].dest);
  273. if (state[1].shape)
  274. fz_dump_blend(ctx, "/S=", state[1].shape);
  275. if (state[1].group_alpha)
  276. fz_dump_blend(ctx, "/GA=", state[1].group_alpha);
  277. printf("\n");
  278. #endif
  279. state[1].scissor = bbox;
  280. state[1].blendmode &= ~(FZ_BLEND_MODEMASK | FZ_BLEND_ISOLATED);
  281. return &state[1];
  282. }
  283. static void fz_knockout_end(fz_context *ctx, fz_draw_device *dev)
  284. {
  285. fz_draw_state *state;
  286. if (dev->top == 0)
  287. fz_throw(ctx, FZ_ERROR_ARGUMENT, "unexpected knockout end");
  288. state = pop_stack(ctx, dev, "knockout");
  289. if ((state[0].blendmode & FZ_BLEND_KNOCKOUT) == 0)
  290. {
  291. cleanup_post_pop(ctx, state);
  292. return;
  293. }
  294. fz_try(ctx)
  295. {
  296. assert((state[1].blendmode & FZ_BLEND_ISOLATED) == 0);
  297. assert((state[1].blendmode & FZ_BLEND_MODEMASK) == 0);
  298. assert(state[1].shape);
  299. #ifdef DUMP_GROUP_BLENDS
  300. dump_spaces(dev->top, "");
  301. fz_dump_blend(ctx, "Knockout end: blending ", state[1].dest);
  302. if (state[1].shape)
  303. fz_dump_blend(ctx, "/S=", state[1].shape);
  304. if (state[1].group_alpha)
  305. fz_dump_blend(ctx, "/GA=", state[1].group_alpha);
  306. fz_dump_blend(ctx, " onto ", state[0].dest);
  307. if (state[0].shape)
  308. fz_dump_blend(ctx, "/S=", state[0].shape);
  309. if (state[0].group_alpha)
  310. fz_dump_blend(ctx, "/GA=", state[0].group_alpha);
  311. if ((state->blendmode & FZ_BLEND_MODEMASK) != 0)
  312. printf(" (blend %d)", state->blendmode & FZ_BLEND_MODEMASK);
  313. if ((state->blendmode & FZ_BLEND_ISOLATED) != 0)
  314. printf(" (isolated)");
  315. printf(" (knockout)");
  316. #endif
  317. fz_blend_pixmap_knockout(ctx, state[0].dest, state[1].dest, state[1].shape);
  318. if (state[1].group_alpha && state[0].group_alpha != state[1].group_alpha)
  319. {
  320. if (state[0].group_alpha)
  321. fz_blend_pixmap_knockout(ctx, state[0].group_alpha, state[1].group_alpha, state[1].shape);
  322. }
  323. if (state[0].shape != state[1].shape)
  324. {
  325. if (state[0].shape)
  326. fz_paint_pixmap(state[0].shape, state[1].shape, 255);
  327. }
  328. #ifdef DUMP_GROUP_BLENDS
  329. fz_dump_blend(ctx, " to get ", state[0].dest);
  330. if (state[0].shape)
  331. fz_dump_blend(ctx, "/S=", state[0].shape);
  332. if (state[0].group_alpha)
  333. fz_dump_blend(ctx, "/GA=", state[0].group_alpha);
  334. printf("\n");
  335. #endif
  336. }
  337. fz_always(ctx)
  338. cleanup_post_pop(ctx, state);
  339. fz_catch(ctx)
  340. fz_rethrow(ctx);
  341. }
  342. static int
  343. colors_supported(fz_context *ctx, fz_colorspace *cs, fz_pixmap *dest)
  344. {
  345. /* Even if we support separations in the destination, if the color space has CMY or K as one of
  346. * its colorants and we are in RGB or Gray we will want to do the tint transform */
  347. if (!fz_colorspace_is_subtractive(ctx, dest->colorspace) && fz_colorspace_device_n_has_cmyk(ctx, cs))
  348. return 0;
  349. /* If we have separations then we should support it */
  350. if (dest->seps)
  351. return 1;
  352. /* If our destination is CMYK and the source color space is only C, M, Y or K we support it
  353. * even if we have no seps */
  354. if (fz_colorspace_is_subtractive(ctx, dest->colorspace))
  355. {
  356. int i, n;
  357. if (fz_colorspace_device_n_has_only_cmyk(ctx, cs))
  358. return 1;
  359. n = fz_colorspace_n(ctx, cs);
  360. for (i = 0; i < n; i++)
  361. {
  362. const char *name = fz_colorspace_colorant(ctx, cs, i);
  363. if (!name)
  364. return 0;
  365. if (!strcmp(name, "All"))
  366. continue;
  367. if (!strcmp(name, "Cyan"))
  368. continue;
  369. if (!strcmp(name, "Magenta"))
  370. continue;
  371. if (!strcmp(name, "Yellow"))
  372. continue;
  373. if (!strcmp(name, "Black"))
  374. continue;
  375. if (!strcmp(name, "None"))
  376. continue;
  377. return 0;
  378. }
  379. return 1;
  380. }
  381. return 0;
  382. }
  383. static fz_overprint *
  384. set_op_from_spaces(fz_context *ctx, fz_overprint *op, const fz_pixmap *dest, fz_colorspace *src, int opm)
  385. {
  386. int dn, sn, i, j, dc;
  387. if (!op)
  388. return NULL;
  389. if (fz_colorspace_is_indexed(ctx, src))
  390. src = fz_base_colorspace(ctx, src);
  391. if (!fz_colorspace_is_subtractive(ctx, dest->colorspace))
  392. return NULL;
  393. if (fz_colorspace_is_gray(ctx, src))
  394. {
  395. /* gray counts as a CMYK with CMY = 0 */
  396. }
  397. else if (!fz_colorspace_is_subtractive(ctx, src))
  398. {
  399. /* The source pixmap was not in a subtractive space, so we can't
  400. * base overprint decisions on that. But we know we've converted
  401. * to a subtractive destination, so we can base overprint
  402. * decisions on what we ended up with. */
  403. src = dest->colorspace;
  404. }
  405. sn = fz_colorspace_n(ctx, src);
  406. dn = dest->n - dest->alpha;
  407. dc = dn - dest->s;
  408. /* If a source colorant is not mentioned in the destination
  409. * colorants (either process or spots), then it will be mapped
  410. * to process colorants. In this case, the process colorants
  411. * can never be protected.
  412. */
  413. for (j = 0; j < sn; j++)
  414. {
  415. /* Run through the colorants looking for one that isn't mentioned.
  416. * i.e. continue if we we find one, break if not. */
  417. const char *sname = fz_colorspace_colorant(ctx, src, j);
  418. if (!sname)
  419. break;
  420. if (!strcmp(sname, "All") || !strcmp(sname, "None"))
  421. continue;
  422. for (i = 0; i < dc; i++)
  423. {
  424. const char *name = fz_colorspace_colorant(ctx, dest->colorspace, i);
  425. if (!name)
  426. continue;
  427. if (!strcmp(name, sname))
  428. break;
  429. }
  430. if (i != dc)
  431. continue;
  432. for (; i < dn; i++)
  433. {
  434. const char *name = fz_separation_name(ctx, dest->seps, i - dc);
  435. if (!name)
  436. continue;
  437. if (!strcmp(name, sname))
  438. break;
  439. }
  440. if (i == dn)
  441. {
  442. /* This source colorant wasn't mentioned */
  443. break;
  444. }
  445. }
  446. if (j == sn)
  447. {
  448. /* We did not find any source colorants that weren't mentioned, so
  449. * process colorants might not be touched... */
  450. for (i = 0; i < dc; i++)
  451. {
  452. const char *name = fz_colorspace_colorant(ctx, dest->colorspace, i);
  453. for (j = 0; j < sn; j++)
  454. {
  455. const char *sname = fz_colorspace_colorant(ctx, src, j);
  456. if (!name || !sname)
  457. continue;
  458. if (!strcmp(name, sname))
  459. break;
  460. if (!strcmp(sname, "All"))
  461. break;
  462. }
  463. if (j == sn)
  464. fz_set_overprint(op, i);
  465. }
  466. }
  467. for (i = dc; i < dn; i++)
  468. {
  469. const char *name = fz_separation_name(ctx, dest->seps, i - dc);
  470. for (j = 0; j < sn; j++)
  471. {
  472. const char *sname = fz_colorspace_colorant(ctx, src, j);
  473. if (!name || !sname)
  474. continue;
  475. if (!strcmp(name, sname))
  476. break;
  477. if (!strcmp(sname, "All"))
  478. break;
  479. }
  480. if (j == sn)
  481. fz_set_overprint(op, i);
  482. }
  483. return op;
  484. }
  485. static fz_overprint *
  486. resolve_color(fz_context *ctx,
  487. fz_overprint *op,
  488. const float *color,
  489. fz_colorspace *colorspace,
  490. float alpha,
  491. fz_color_params color_params,
  492. unsigned char *colorbv,
  493. fz_pixmap *dest,
  494. int overprint_possible)
  495. {
  496. float colorfv[FZ_MAX_COLORS];
  497. int i;
  498. int n = dest->n - dest->alpha;
  499. fz_colorspace *model = dest->colorspace;
  500. int devn, devgray;
  501. int effective_opm;
  502. if (colorspace == NULL && model != NULL)
  503. fz_throw(ctx, FZ_ERROR_ARGUMENT, "color destination requires source color");
  504. effective_opm = color_params.opm;
  505. devn = fz_colorspace_is_device_n(ctx, colorspace);
  506. devgray = fz_colorspace_is_device_gray(ctx, colorspace);
  507. /* We can only overprint when enabled, and when we are in a subtractive colorspace */
  508. if (color_params.op == 0 || !fz_colorspace_is_subtractive(ctx, dest->colorspace) || !overprint_possible)
  509. op = NULL;
  510. else if (devgray)
  511. {
  512. /* Device Gray is additive, but seems to still be
  513. * counted for overprint (see
  514. * Ghent_V3.0/030_Gray_K_black_OP_x1a.pdf 030.pdf). */
  515. }
  516. /* If we are in a CMYK space (i.e. not a devn one, given we know we are subtractive at this point),
  517. * then we only adhere to overprint mode if it's the same space as the destination. */
  518. /* FIXME: Possibly we need a better equivalency test here. */
  519. else if (!devn && colorspace != dest->colorspace)
  520. {
  521. effective_opm = 0;
  522. }
  523. if (n == 0)
  524. i = 0;
  525. else if (devn && colors_supported(ctx, colorspace, dest))
  526. {
  527. fz_convert_separation_colors(ctx, colorspace, color, dest->seps, dest->colorspace, colorfv, color_params);
  528. for (i = 0; i < n; i++)
  529. colorbv[i] = colorfv[i] * 255;
  530. op = set_op_from_spaces(ctx, op, dest, colorspace, effective_opm);
  531. }
  532. else
  533. {
  534. int c = n - dest->s;
  535. fz_convert_color(ctx, colorspace, color, dest->colorspace, colorfv, NULL, color_params);
  536. for (i = 0; i < c; i++)
  537. colorbv[i] = colorfv[i] * 255;
  538. for (; i < n; i++)
  539. {
  540. colorfv[i] = 0;
  541. colorbv[i] = 0;
  542. }
  543. }
  544. colorbv[i] = alpha * 255;
  545. /* op && !devn => overprinting in cmyk or devicegray. */
  546. if (op && !devn)
  547. {
  548. /* We are overprinting, so protect all spots. */
  549. for (i = 4; i < n; i++)
  550. fz_set_overprint(op, i);
  551. /* If OPM, then protect all components for which the color values are zero.
  552. * (but only if we're in devicecmyk). */
  553. if (effective_opm == 1 && colorspace != fz_device_gray(ctx))
  554. for (i = 0; i < n; i++)
  555. if (colorfv[i] == 0)
  556. fz_set_overprint(op, i);
  557. }
  558. return op;
  559. }
  560. static fz_draw_state *
  561. push_group_for_separations(fz_context *ctx, fz_draw_device *dev, fz_color_params color_params, fz_default_colorspaces *default_cs)
  562. {
  563. fz_separations *clone = fz_clone_separations_for_overprint(ctx, dev->stack[0].dest->seps);
  564. fz_colorspace *oi = fz_default_output_intent(ctx, default_cs);
  565. fz_colorspace *dcs = fz_device_cmyk(ctx);
  566. /* Pick sep target CMYK based upon proof and output intent settings. Priority
  567. * is oi, proof, devicecmyk. */
  568. if (dev->proof_cs)
  569. {
  570. dcs = dev->proof_cs;
  571. }
  572. if (oi)
  573. {
  574. dcs = oi;
  575. }
  576. /* Not needed if dest has the seps, and we are not using a proof or the target is the same as the proof and we don't have an oi or the target is the same as the oi */
  577. if ((clone == dev->stack[0].dest->seps) && (dev->proof_cs == NULL || dev->proof_cs == dev->stack[0].dest->colorspace) && (oi == NULL || oi == dev->stack[0].dest->colorspace))
  578. {
  579. fz_drop_separations(ctx, clone);
  580. dev->resolve_spots = 0;
  581. return &dev->stack[0];
  582. }
  583. /* Make a new pixmap to render to. */
  584. fz_try(ctx)
  585. {
  586. push_stack(ctx, dev, "separations");
  587. dev->stack[1].dest = fz_clone_pixmap_area_with_different_seps(ctx, dev->stack[0].dest, &dev->stack[0].scissor, dcs, clone, color_params, default_cs);
  588. }
  589. fz_always(ctx)
  590. fz_drop_separations(ctx, clone);
  591. fz_catch(ctx)
  592. fz_rethrow(ctx);
  593. return &dev->stack[1];
  594. }
  595. static void
  596. fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, fz_matrix in_ctm,
  597. fz_colorspace *colorspace_in, const float *color, float alpha, fz_color_params color_params)
  598. {
  599. fz_draw_device *dev = (fz_draw_device*)devp;
  600. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  601. fz_rasterizer *rast = dev->rast;
  602. fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
  603. float expansion = fz_matrix_expansion(ctm);
  604. float flatness;
  605. unsigned char colorbv[FZ_MAX_COLORS + 1];
  606. fz_irect bbox;
  607. fz_draw_state *state = &dev->stack[dev->top];
  608. fz_overprint op = { { 0 } };
  609. fz_overprint *eop;
  610. if (dev->top == 0 && dev->resolve_spots)
  611. state = push_group_for_separations(ctx, dev, color_params, dev->default_cs);
  612. if (expansion < FLT_EPSILON)
  613. expansion = 1;
  614. flatness = 0.3f / expansion;
  615. if (flatness < 0.001f)
  616. flatness = 0.001f;
  617. bbox = fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest), state->scissor);
  618. if (fz_flatten_fill_path(ctx, rast, path, ctm, flatness, bbox, &bbox))
  619. return;
  620. if (alpha == 0)
  621. return;
  622. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  623. state = fz_knockout_begin(ctx, dev);
  624. eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, dev->overprint_possible);
  625. fz_convert_rasterizer(ctx, rast, even_odd, state->dest, colorbv, eop);
  626. if (state->shape)
  627. {
  628. if (!rast->fns.reusable)
  629. fz_flatten_fill_path(ctx, rast, path, ctm, flatness, bbox, NULL);
  630. colorbv[0] = 255;
  631. fz_convert_rasterizer(ctx, rast, even_odd, state->shape, colorbv, 0);
  632. }
  633. if (state->group_alpha)
  634. {
  635. if (!rast->fns.reusable)
  636. fz_flatten_fill_path(ctx, rast, path, ctm, flatness, bbox, NULL);
  637. colorbv[0] = alpha * 255;
  638. fz_convert_rasterizer(ctx, rast, even_odd, state->group_alpha, colorbv, 0);
  639. }
  640. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  641. fz_knockout_end(ctx, dev);
  642. }
  643. static void
  644. fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const fz_stroke_state *stroke, fz_matrix in_ctm,
  645. fz_colorspace *colorspace_in, const float *color, float alpha, fz_color_params color_params)
  646. {
  647. fz_draw_device *dev = (fz_draw_device*)devp;
  648. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  649. fz_rasterizer *rast = dev->rast;
  650. fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
  651. float expansion = fz_matrix_expansion(ctm);
  652. float flatness;
  653. float linewidth = stroke->linewidth;
  654. unsigned char colorbv[FZ_MAX_COLORS + 1];
  655. fz_irect bbox;
  656. float aa_level = 2.0f/(fz_rasterizer_graphics_aa_level(rast)+2);
  657. fz_draw_state *state = &dev->stack[dev->top];
  658. float mlw = fz_rasterizer_graphics_min_line_width(rast);
  659. fz_overprint op = { { 0 } };
  660. fz_overprint *eop;
  661. if (dev->top == 0 && dev->resolve_spots)
  662. state = push_group_for_separations(ctx, dev, color_params, dev->default_cs);
  663. if (mlw > aa_level)
  664. aa_level = mlw;
  665. if (expansion < FLT_EPSILON)
  666. expansion = 1;
  667. if (linewidth * expansion < aa_level)
  668. linewidth = aa_level / expansion;
  669. flatness = 0.3f / expansion;
  670. if (flatness < 0.001f)
  671. flatness = 0.001f;
  672. bbox = fz_intersect_irect(fz_pixmap_bbox_no_ctx(state->dest), state->scissor);
  673. if (fz_flatten_stroke_path(ctx, rast, path, stroke, ctm, flatness, linewidth, bbox, &bbox))
  674. return;
  675. if (alpha == 0)
  676. return;
  677. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  678. state = fz_knockout_begin(ctx, dev);
  679. eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, dev->overprint_possible);
  680. #ifdef DUMP_GROUP_BLENDS
  681. dump_spaces(dev->top, "");
  682. fz_dump_blend(ctx, "Before stroke ", state->dest);
  683. if (state->shape)
  684. fz_dump_blend(ctx, "/S=", state->shape);
  685. if (state->group_alpha)
  686. fz_dump_blend(ctx, "/GA=", state->group_alpha);
  687. printf("\n");
  688. #endif
  689. fz_convert_rasterizer(ctx, rast, 0, state->dest, colorbv, eop);
  690. if (state->shape)
  691. {
  692. if (!rast->fns.reusable)
  693. (void)fz_flatten_stroke_path(ctx, rast, path, stroke, ctm, flatness, linewidth, bbox, NULL);
  694. colorbv[0] = 255;
  695. fz_convert_rasterizer(ctx, rast, 0, state->shape, colorbv, 0);
  696. }
  697. if (state->group_alpha)
  698. {
  699. if (!rast->fns.reusable)
  700. (void)fz_flatten_stroke_path(ctx, rast, path, stroke, ctm, flatness, linewidth, bbox, NULL);
  701. colorbv[0] = 255 * alpha;
  702. fz_convert_rasterizer(ctx, rast, 0, state->group_alpha, colorbv, 0);
  703. }
  704. #ifdef DUMP_GROUP_BLENDS
  705. dump_spaces(dev->top, "");
  706. fz_dump_blend(ctx, "After stroke ", state->dest);
  707. if (state->shape)
  708. fz_dump_blend(ctx, "/S=", state->shape);
  709. if (state->group_alpha)
  710. fz_dump_blend(ctx, "/GA=", state->group_alpha);
  711. printf("\n");
  712. #endif
  713. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  714. fz_knockout_end(ctx, dev);
  715. }
  716. static void
  717. fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, fz_matrix in_ctm, fz_rect scissor)
  718. {
  719. fz_draw_device *dev = (fz_draw_device*)devp;
  720. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  721. fz_rasterizer *rast = dev->rast;
  722. float expansion = fz_matrix_expansion(ctm);
  723. float flatness;
  724. fz_irect bbox;
  725. fz_draw_state *state = &dev->stack[dev->top];
  726. fz_colorspace *model;
  727. if (dev->top == 0 && dev->resolve_spots)
  728. state = push_group_for_separations(ctx, dev, fz_default_color_params /* FIXME */, dev->default_cs);
  729. if (expansion < FLT_EPSILON)
  730. expansion = 1;
  731. flatness = 0.3f / expansion;
  732. if (flatness < 0.001f)
  733. flatness = 0.001f;
  734. state = push_stack(ctx, dev, "clip path");
  735. model = state->dest->colorspace;
  736. bbox = fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest), state->scissor);
  737. if (!fz_is_infinite_rect(scissor))
  738. bbox = fz_intersect_irect(bbox, fz_irect_from_rect(fz_transform_rect(scissor, dev->transform)));
  739. if (fz_flatten_fill_path(ctx, rast, path, ctm, flatness, bbox, &bbox) || fz_is_rect_rasterizer(ctx, rast))
  740. {
  741. state[1].scissor = bbox;
  742. state[1].mask = NULL;
  743. #ifdef DUMP_GROUP_BLENDS
  744. dump_spaces(dev->top-1, "Clip (rectangular) begin\n");
  745. #endif
  746. return;
  747. }
  748. state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  749. fz_clear_pixmap(ctx, state[1].mask);
  750. state[1].dest = fz_new_pixmap_with_bbox(ctx, model, bbox, state[0].dest->seps, state[0].dest->alpha);
  751. fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, bbox, dev->default_cs);
  752. if (state[1].shape)
  753. {
  754. state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  755. fz_copy_pixmap_rect(ctx, state[1].shape, state[0].shape, bbox, dev->default_cs);
  756. }
  757. if (state[1].group_alpha)
  758. {
  759. state[1].group_alpha = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  760. fz_copy_pixmap_rect(ctx, state[1].group_alpha, state[0].group_alpha, bbox, dev->default_cs);
  761. }
  762. fz_convert_rasterizer(ctx, rast, even_odd, state[1].mask, NULL, 0);
  763. state[1].scissor = bbox;
  764. #ifdef DUMP_GROUP_BLENDS
  765. dump_spaces(dev->top-1, "Clip (non-rectangular) begin\n");
  766. #endif
  767. }
  768. static void
  769. fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const fz_stroke_state *stroke, fz_matrix in_ctm, fz_rect scissor)
  770. {
  771. fz_draw_device *dev = (fz_draw_device*)devp;
  772. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  773. fz_rasterizer *rast = dev->rast;
  774. float expansion = fz_matrix_expansion(ctm);
  775. float flatness;
  776. float linewidth = stroke->linewidth;
  777. fz_irect bbox;
  778. fz_draw_state *state = &dev->stack[dev->top];
  779. fz_colorspace *model;
  780. float aa_level = 2.0f/(fz_rasterizer_graphics_aa_level(rast)+2);
  781. float mlw = fz_rasterizer_graphics_min_line_width(rast);
  782. if (dev->top == 0 && dev->resolve_spots)
  783. state = push_group_for_separations(ctx, dev, fz_default_color_params /* FIXME */, dev->default_cs);
  784. if (mlw > aa_level)
  785. aa_level = mlw;
  786. if (expansion < FLT_EPSILON)
  787. expansion = 1;
  788. if (linewidth * expansion < aa_level)
  789. linewidth = aa_level / expansion;
  790. flatness = 0.3f / expansion;
  791. if (flatness < 0.001f)
  792. flatness = 0.001f;
  793. state = push_stack(ctx, dev, "clip stroke");
  794. model = state->dest->colorspace;
  795. bbox = fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest), state->scissor);
  796. if (!fz_is_infinite_rect(scissor))
  797. bbox = fz_intersect_irect(bbox, fz_irect_from_rect(fz_transform_rect(scissor, dev->transform)));
  798. if (fz_flatten_stroke_path(ctx, rast, path, stroke, ctm, flatness, linewidth, bbox, &bbox))
  799. {
  800. state[1].scissor = bbox;
  801. state[1].mask = NULL;
  802. #ifdef DUMP_GROUP_BLENDS
  803. dump_spaces(dev->top-1, "Clip (stroke, empty) begin\n");
  804. #endif
  805. return;
  806. }
  807. state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  808. fz_clear_pixmap(ctx, state[1].mask);
  809. state[1].dest = fz_new_pixmap_with_bbox(ctx, model, bbox, state[0].dest->seps, state[0].dest->alpha);
  810. fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, bbox, dev->default_cs);
  811. if (state->shape)
  812. {
  813. state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  814. fz_copy_pixmap_rect(ctx, state[1].shape, state[0].shape, bbox, dev->default_cs);
  815. }
  816. if (state->group_alpha)
  817. {
  818. state[1].group_alpha = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  819. fz_copy_pixmap_rect(ctx, state[1].group_alpha, state[0].group_alpha, bbox, dev->default_cs);
  820. }
  821. fz_convert_rasterizer(ctx, rast, 0, state[1].mask, NULL, 0);
  822. state[1].blendmode |= FZ_BLEND_ISOLATED;
  823. state[1].scissor = bbox;
  824. #ifdef DUMP_GROUP_BLENDS
  825. dump_spaces(dev->top-1, "Clip (stroke) begin\n");
  826. #endif
  827. }
  828. static void
  829. draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
  830. int xorig, int yorig, const fz_irect *scissor, fz_overprint *eop)
  831. {
  832. unsigned char *dp;
  833. fz_irect bbox;
  834. int x, y, w, h;
  835. int skip_x, skip_y;
  836. fz_pixmap *msk;
  837. bbox = fz_glyph_bbox_no_ctx(glyph);
  838. bbox = fz_translate_irect(bbox, xorig, yorig);
  839. bbox = fz_intersect_irect(bbox, *scissor); /* scissor < dst */
  840. bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(dst));
  841. if (fz_is_empty_irect(bbox))
  842. return;
  843. x = bbox.x0;
  844. y = bbox.y0;
  845. w = bbox.x1 - bbox.x0;
  846. h = bbox.y1 - bbox.y0;
  847. skip_x = x - glyph->x - xorig;
  848. skip_y = y - glyph->y - yorig;
  849. msk = glyph->pixmap;
  850. dp = dst->samples + (y - dst->y) * (size_t)dst->stride + (x - dst->x) * (size_t)dst->n;
  851. if (msk == NULL)
  852. {
  853. fz_paint_glyph(colorbv, dst, dp, glyph, w, h, skip_x, skip_y, eop);
  854. }
  855. else
  856. {
  857. unsigned char *mp = msk->samples + skip_y * msk->stride + skip_x;
  858. int da = dst->alpha;
  859. if (dst->colorspace)
  860. {
  861. fz_span_color_painter_t *fn;
  862. fn = fz_get_span_color_painter(dst->n, da, colorbv, eop);
  863. if (fn == NULL)
  864. return;
  865. while (h--)
  866. {
  867. (*fn)(dp, mp, dst->n, w, colorbv, da, eop);
  868. dp += dst->stride;
  869. mp += msk->stride;
  870. }
  871. }
  872. else
  873. {
  874. fz_span_painter_t *fn;
  875. int col = colorbv ? colorbv[0] : 255;
  876. fn = fz_get_span_painter(da, 1, 0, col, eop);
  877. if (fn == NULL)
  878. return;
  879. while (h--)
  880. {
  881. (*fn)(dp, da, mp, 1, 0, w, col, eop);
  882. dp += dst->stride;
  883. mp += msk->stride;
  884. }
  885. }
  886. }
  887. }
  888. static void
  889. fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, fz_matrix in_ctm,
  890. fz_colorspace *colorspace_in, const float *color, float alpha, fz_color_params color_params)
  891. {
  892. fz_draw_device *dev = (fz_draw_device*)devp;
  893. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  894. fz_draw_state *state = &dev->stack[dev->top];
  895. fz_colorspace *model = state->dest->colorspace;
  896. unsigned char colorbv[FZ_MAX_COLORS + 1];
  897. unsigned char shapebv, shapebva;
  898. fz_text_span *span;
  899. int i;
  900. fz_colorspace *colorspace = NULL;
  901. fz_rasterizer *rast = dev->rast;
  902. fz_overprint op = { { 0 } };
  903. fz_overprint *eop;
  904. if (dev->top == 0 && dev->resolve_spots)
  905. state = push_group_for_separations(ctx, dev, color_params, dev->default_cs);
  906. if (colorspace_in)
  907. colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
  908. if (colorspace == NULL && model != NULL)
  909. fz_throw(ctx, FZ_ERROR_ARGUMENT, "color destination requires source color");
  910. if (alpha == 0)
  911. return;
  912. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  913. state = fz_knockout_begin(ctx, dev);
  914. eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, dev->overprint_possible);
  915. shapebv = 255;
  916. shapebva = 255 * alpha;
  917. for (span = text->head; span; span = span->next)
  918. {
  919. fz_matrix tm, trm;
  920. fz_glyph *glyph;
  921. int gid;
  922. tm = span->trm;
  923. for (i = 0; i < span->len; i++)
  924. {
  925. gid = span->items[i].gid;
  926. if (gid < 0)
  927. continue;
  928. tm.e = span->items[i].x;
  929. tm.f = span->items[i].y;
  930. trm = fz_concat(tm, ctm);
  931. glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state->dest->alpha, fz_rasterizer_text_aa_level(rast));
  932. if (glyph)
  933. {
  934. fz_pixmap *pixmap = glyph->pixmap;
  935. int x = floorf(trm.e);
  936. int y = floorf(trm.f);
  937. if (pixmap == NULL || pixmap->n == 1)
  938. {
  939. draw_glyph(colorbv, state->dest, glyph, x, y, &state->scissor, eop);
  940. if (state->shape)
  941. draw_glyph(&shapebv, state->shape, glyph, x, y, &state->scissor, 0);
  942. if (state->group_alpha)
  943. draw_glyph(&shapebva, state->group_alpha, glyph, x, y, &state->scissor, 0);
  944. }
  945. else
  946. {
  947. fz_matrix mat;
  948. mat.a = pixmap->w; mat.b = mat.c = 0; mat.d = pixmap->h;
  949. mat.e = x + pixmap->x; mat.f = y + pixmap->y;
  950. mat = fz_gridfit_matrix(devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, mat);
  951. fz_paint_image(ctx, state->dest, &state->scissor, state->shape, state->group_alpha, pixmap, mat, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), eop);
  952. }
  953. fz_drop_glyph(ctx, glyph);
  954. }
  955. else
  956. {
  957. fz_path *path = fz_outline_glyph(ctx, span->font, gid, tm);
  958. if (path)
  959. {
  960. fz_try(ctx)
  961. fz_draw_fill_path(ctx, devp, path, 0, in_ctm, colorspace, color, alpha, color_params);
  962. fz_always(ctx)
  963. fz_drop_path(ctx, path);
  964. fz_catch(ctx)
  965. fz_rethrow(ctx);
  966. }
  967. else
  968. {
  969. fz_warn(ctx, "cannot render glyph");
  970. }
  971. }
  972. }
  973. }
  974. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  975. fz_knockout_end(ctx, dev);
  976. }
  977. static void
  978. fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_stroke_state *stroke,
  979. fz_matrix in_ctm, fz_colorspace *colorspace_in, const float *color, float alpha, fz_color_params color_params)
  980. {
  981. fz_draw_device *dev = (fz_draw_device*)devp;
  982. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  983. fz_draw_state *state = &dev->stack[dev->top];
  984. fz_colorspace *model = state->dest->colorspace;
  985. unsigned char colorbv[FZ_MAX_COLORS + 1];
  986. unsigned char solid = 255;
  987. unsigned char alpha_byte = alpha * 255;
  988. fz_text_span *span;
  989. int i;
  990. fz_colorspace *colorspace = NULL;
  991. int aa = fz_rasterizer_text_aa_level(dev->rast);
  992. fz_overprint op = { { 0 } };
  993. fz_overprint *eop;
  994. if (dev->top == 0 && dev->resolve_spots)
  995. state = push_group_for_separations(ctx, dev, color_params, dev->default_cs);
  996. if (colorspace_in)
  997. colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
  998. if (alpha == 0)
  999. return;
  1000. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  1001. state = fz_knockout_begin(ctx, dev);
  1002. eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, dev->overprint_possible);
  1003. for (span = text->head; span; span = span->next)
  1004. {
  1005. fz_matrix tm, trm;
  1006. fz_glyph *glyph;
  1007. int gid;
  1008. tm = span->trm;
  1009. for (i = 0; i < span->len; i++)
  1010. {
  1011. gid = span->items[i].gid;
  1012. if (gid < 0)
  1013. continue;
  1014. tm.e = span->items[i].x;
  1015. tm.f = span->items[i].y;
  1016. trm = fz_concat(tm, ctm);
  1017. glyph = fz_render_stroked_glyph(ctx, span->font, gid, &trm, ctm, model, stroke, &state->scissor, aa);
  1018. if (glyph)
  1019. {
  1020. fz_pixmap *pixmap = glyph->pixmap;
  1021. int x = (int)trm.e;
  1022. int y = (int)trm.f;
  1023. if (pixmap == NULL || pixmap->n == 1)
  1024. {
  1025. draw_glyph(colorbv, state->dest, glyph, x, y, &state->scissor, eop);
  1026. if (state->shape)
  1027. draw_glyph(&solid, state->shape, glyph, x, y, &state->scissor, 0);
  1028. if (state->group_alpha)
  1029. draw_glyph(&alpha_byte, state->group_alpha, glyph, x, y, &state->scissor, 0);
  1030. }
  1031. else
  1032. {
  1033. fz_matrix mat;
  1034. mat.a = pixmap->w; mat.b = mat.c = 0; mat.d = pixmap->h;
  1035. mat.e = x + pixmap->x; mat.f = y + pixmap->y;
  1036. mat = fz_gridfit_matrix(devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, mat);
  1037. fz_paint_image(ctx, state->dest, &state->scissor, state->shape, state->group_alpha, pixmap, mat, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), eop);
  1038. }
  1039. fz_drop_glyph(ctx, glyph);
  1040. }
  1041. else
  1042. {
  1043. fz_path *path = fz_outline_glyph(ctx, span->font, gid, tm);
  1044. if (!path)
  1045. fz_warn(ctx, "cannot render glyph");
  1046. else
  1047. {
  1048. fz_try(ctx)
  1049. fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, colorspace, color, alpha, color_params);
  1050. fz_always(ctx)
  1051. fz_drop_path(ctx, path);
  1052. fz_catch(ctx)
  1053. fz_rethrow(ctx);
  1054. }
  1055. }
  1056. }
  1057. }
  1058. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  1059. fz_knockout_end(ctx, dev);
  1060. }
  1061. static void
  1062. fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, fz_matrix in_ctm, fz_rect scissor)
  1063. {
  1064. fz_draw_device *dev = (fz_draw_device*)devp;
  1065. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  1066. fz_irect bbox;
  1067. fz_matrix tm, trm;
  1068. fz_glyph *glyph;
  1069. int i, gid;
  1070. fz_draw_state *state;
  1071. fz_colorspace *model;
  1072. fz_text_span *span;
  1073. fz_rasterizer *rast = dev->rast;
  1074. if (dev->top == 0 && dev->resolve_spots)
  1075. state = push_group_for_separations(ctx, dev, fz_default_color_params /* FIXME */, dev->default_cs);
  1076. state = push_stack(ctx, dev, "clip text");
  1077. model = state->dest->colorspace;
  1078. /* make the mask the exact size needed */
  1079. bbox = fz_irect_from_rect(fz_bound_text(ctx, text, NULL, ctm));
  1080. bbox = fz_intersect_irect(bbox, state->scissor);
  1081. if (!fz_is_infinite_rect(scissor))
  1082. {
  1083. fz_rect tscissor = fz_transform_rect(scissor, dev->transform);
  1084. bbox = fz_intersect_irect(bbox, fz_irect_from_rect(tscissor));
  1085. }
  1086. state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1087. fz_clear_pixmap(ctx, state[1].mask);
  1088. /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
  1089. * we have a choice. We can either create the new destination WITH alpha, or
  1090. * we can copy the old pixmap contents in. We opt for the latter here, but
  1091. * may want to revisit this decision in the future. */
  1092. state[1].dest = fz_new_pixmap_with_bbox(ctx, model, bbox, state[0].dest->seps, state[0].dest->alpha);
  1093. if (state[0].dest->alpha)
  1094. fz_clear_pixmap(ctx, state[1].dest);
  1095. else
  1096. fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, bbox, dev->default_cs);
  1097. if (state->shape)
  1098. {
  1099. state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1100. fz_copy_pixmap_rect(ctx, state[1].shape, state[0].shape, bbox, dev->default_cs);
  1101. }
  1102. else
  1103. state[1].shape = NULL;
  1104. if (state->group_alpha)
  1105. {
  1106. state[1].group_alpha = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1107. fz_copy_pixmap_rect(ctx, state[1].group_alpha, state[0].group_alpha, bbox, dev->default_cs);
  1108. }
  1109. else
  1110. state[1].group_alpha = NULL;
  1111. state[1].blendmode |= FZ_BLEND_ISOLATED;
  1112. state[1].scissor = bbox;
  1113. #ifdef DUMP_GROUP_BLENDS
  1114. dump_spaces(dev->top-1, "Clip (text) begin\n");
  1115. #endif
  1116. if (!fz_is_empty_irect(bbox) && state[1].mask)
  1117. {
  1118. for (span = text->head; span; span = span->next)
  1119. {
  1120. tm = span->trm;
  1121. for (i = 0; i < span->len; i++)
  1122. {
  1123. gid = span->items[i].gid;
  1124. if (gid < 0)
  1125. continue;
  1126. tm.e = span->items[i].x;
  1127. tm.f = span->items[i].y;
  1128. trm = fz_concat(tm, ctm);
  1129. glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state[1].dest->alpha, fz_rasterizer_text_aa_level(rast));
  1130. if (glyph)
  1131. {
  1132. int x = (int)trm.e;
  1133. int y = (int)trm.f;
  1134. draw_glyph(NULL, state[1].mask, glyph, x, y, &bbox, 0);
  1135. if (state[1].shape)
  1136. draw_glyph(NULL, state[1].shape, glyph, x, y, &bbox, 0);
  1137. if (state[1].group_alpha)
  1138. draw_glyph(NULL, state[1].group_alpha, glyph, x, y, &bbox, 0);
  1139. fz_drop_glyph(ctx, glyph);
  1140. }
  1141. else
  1142. {
  1143. fz_path *path = fz_outline_glyph(ctx, span->font, gid, tm);
  1144. if (path)
  1145. {
  1146. fz_pixmap *old_dest;
  1147. float white = 1;
  1148. old_dest = state[1].dest;
  1149. state[1].dest = state[1].mask;
  1150. state[1].mask = NULL;
  1151. fz_try(ctx)
  1152. {
  1153. fz_draw_fill_path(ctx, devp, path, 0, in_ctm, fz_device_gray(ctx), &white, 1, fz_default_color_params);
  1154. }
  1155. fz_always(ctx)
  1156. {
  1157. state[1].mask = state[1].dest;
  1158. state[1].dest = old_dest;
  1159. fz_drop_path(ctx, path);
  1160. }
  1161. fz_catch(ctx)
  1162. {
  1163. fz_rethrow(ctx);
  1164. }
  1165. }
  1166. else
  1167. {
  1168. fz_warn(ctx, "cannot render glyph for clipping");
  1169. }
  1170. }
  1171. }
  1172. }
  1173. }
  1174. }
  1175. static void
  1176. fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_stroke_state *stroke, fz_matrix in_ctm, fz_rect scissor)
  1177. {
  1178. fz_draw_device *dev = (fz_draw_device*)devp;
  1179. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  1180. fz_irect bbox;
  1181. fz_pixmap *mask, *shape, *group_alpha;
  1182. fz_matrix tm, trm;
  1183. fz_glyph *glyph;
  1184. int i, gid;
  1185. fz_draw_state *state = push_stack(ctx, dev, "clip stroke text");
  1186. fz_colorspace *model = state->dest->colorspace;
  1187. fz_text_span *span;
  1188. int aa = fz_rasterizer_text_aa_level(dev->rast);
  1189. if (dev->top == 0 && dev->resolve_spots)
  1190. state = push_group_for_separations(ctx, dev, fz_default_color_params /* FIXME */, dev->default_cs);
  1191. /* make the mask the exact size needed */
  1192. bbox = fz_irect_from_rect(fz_bound_text(ctx, text, stroke, ctm));
  1193. bbox = fz_intersect_irect(bbox, state->scissor);
  1194. if (!fz_is_infinite_rect(scissor))
  1195. {
  1196. fz_rect tscissor = fz_transform_rect(scissor, dev->transform);
  1197. bbox = fz_intersect_irect(bbox, fz_irect_from_rect(tscissor));
  1198. }
  1199. state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1200. fz_clear_pixmap(ctx, mask);
  1201. /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
  1202. * we have a choice. We can either create the new destination WITH alpha, or
  1203. * we can copy the old pixmap contents in. We opt for the latter here, but
  1204. * may want to revisit this decision in the future. */
  1205. state[1].dest = fz_new_pixmap_with_bbox(ctx, model, bbox, state[0].dest->seps, state[0].dest->alpha);
  1206. if (state[0].dest->alpha)
  1207. fz_clear_pixmap(ctx, state[1].dest);
  1208. else
  1209. fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, bbox, dev->default_cs);
  1210. if (state->shape)
  1211. {
  1212. state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1213. fz_copy_pixmap_rect(ctx, state[1].shape, state[0].shape, bbox, dev->default_cs);
  1214. }
  1215. else
  1216. shape = state->shape;
  1217. if (state->group_alpha)
  1218. {
  1219. state[1].group_alpha = group_alpha = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1220. fz_copy_pixmap_rect(ctx, state[1].group_alpha, state[0].group_alpha, bbox, dev->default_cs);
  1221. }
  1222. else
  1223. group_alpha = NULL;
  1224. state[1].blendmode |= FZ_BLEND_ISOLATED;
  1225. state[1].scissor = bbox;
  1226. #ifdef DUMP_GROUP_BLENDS
  1227. dump_spaces(dev->top-1, "Clip (stroke text) begin\n");
  1228. #endif
  1229. if (!fz_is_empty_irect(bbox))
  1230. {
  1231. for (span = text->head; span; span = span->next)
  1232. {
  1233. tm = span->trm;
  1234. for (i = 0; i < span->len; i++)
  1235. {
  1236. gid = span->items[i].gid;
  1237. if (gid < 0)
  1238. continue;
  1239. tm.e = span->items[i].x;
  1240. tm.f = span->items[i].y;
  1241. trm = fz_concat(tm, ctm);
  1242. glyph = fz_render_stroked_glyph(ctx, span->font, gid, &trm, ctm, model, stroke, &state->scissor, aa);
  1243. if (glyph)
  1244. {
  1245. int x = (int)trm.e;
  1246. int y = (int)trm.f;
  1247. draw_glyph(NULL, mask, glyph, x, y, &bbox, 0);
  1248. if (shape)
  1249. draw_glyph(NULL, shape, glyph, x, y, &bbox, 0);
  1250. if (group_alpha)
  1251. draw_glyph(NULL, group_alpha, glyph, x, y, &bbox, 0);
  1252. fz_drop_glyph(ctx, glyph);
  1253. }
  1254. else
  1255. {
  1256. fz_path *path = fz_outline_glyph(ctx, span->font, gid, tm);
  1257. if (path)
  1258. {
  1259. fz_pixmap *old_dest;
  1260. float white = 1;
  1261. state = &dev->stack[dev->top];
  1262. old_dest = state[0].dest;
  1263. state[0].dest = state[0].mask;
  1264. state[0].mask = NULL;
  1265. fz_try(ctx)
  1266. {
  1267. fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, fz_device_gray(ctx), &white, 1, fz_default_color_params);
  1268. }
  1269. fz_always(ctx)
  1270. {
  1271. state[0].mask = state[0].dest;
  1272. state[0].dest = old_dest;
  1273. fz_drop_path(ctx, path);
  1274. }
  1275. fz_catch(ctx)
  1276. {
  1277. fz_rethrow(ctx);
  1278. }
  1279. }
  1280. else
  1281. {
  1282. fz_warn(ctx, "cannot render glyph for stroked clipping");
  1283. }
  1284. }
  1285. }
  1286. }
  1287. }
  1288. }
  1289. static void
  1290. fz_draw_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm)
  1291. {
  1292. }
  1293. static void
  1294. fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, fz_matrix in_ctm, float alpha, fz_color_params color_params)
  1295. {
  1296. fz_draw_device *dev = (fz_draw_device*)devp;
  1297. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  1298. fz_irect bbox, scissor;
  1299. fz_pixmap *dest, *shape, *group_alpha;
  1300. unsigned char colorbv[FZ_MAX_COLORS + 1];
  1301. unsigned char alpha_byte = 255 * alpha;
  1302. fz_draw_state *state = &dev->stack[dev->top];
  1303. fz_overprint op = { { 0 } };
  1304. fz_overprint *eop;
  1305. fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, shade->colorspace);
  1306. if (dev->top == 0 && dev->resolve_spots)
  1307. state = push_group_for_separations(ctx, dev, color_params, dev->default_cs);
  1308. scissor = state->scissor;
  1309. bbox = fz_irect_from_rect(fz_bound_shade(ctx, shade, ctm));
  1310. bbox = fz_intersect_irect(bbox, scissor);
  1311. if (fz_is_empty_irect(bbox))
  1312. return;
  1313. if (alpha == 0)
  1314. return;
  1315. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  1316. state = fz_knockout_begin(ctx, dev);
  1317. fz_var(dest);
  1318. fz_var(shape);
  1319. fz_var(group_alpha);
  1320. dest = state->dest;
  1321. shape = state->shape;
  1322. group_alpha = state->group_alpha;
  1323. fz_try(ctx)
  1324. {
  1325. if (alpha < 1)
  1326. {
  1327. dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, bbox, state->dest->seps, state->dest->alpha);
  1328. if (state->dest->alpha)
  1329. fz_clear_pixmap(ctx, dest);
  1330. else
  1331. fz_copy_pixmap_rect(ctx, dest, state[0].dest, bbox, dev->default_cs);
  1332. if (shape)
  1333. {
  1334. shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1335. fz_clear_pixmap(ctx, shape);
  1336. }
  1337. if (group_alpha)
  1338. {
  1339. group_alpha = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1340. fz_clear_pixmap(ctx, group_alpha);
  1341. }
  1342. }
  1343. if (shade->use_background)
  1344. {
  1345. unsigned char *s;
  1346. int x, y, n, i;
  1347. /* Disable OPM */
  1348. color_params.opm = 0;
  1349. eop = resolve_color(ctx, &op, shade->background, colorspace, alpha, color_params, colorbv, state->dest, dev->overprint_possible);
  1350. n = dest->n;
  1351. if (fz_overprint_required(eop))
  1352. {
  1353. for (y = scissor.y0; y < scissor.y1; y++)
  1354. {
  1355. s = dest->samples + (unsigned int)((y - dest->y) * dest->stride + (scissor.x0 - dest->x) * n);
  1356. for (x = scissor.x0; x < scissor.x1; x++)
  1357. {
  1358. for (i = 0; i < n; i++)
  1359. if (fz_overprint_component(eop, i))
  1360. *s++ = colorbv[i];
  1361. }
  1362. }
  1363. }
  1364. else
  1365. {
  1366. for (y = scissor.y0; y < scissor.y1; y++)
  1367. {
  1368. s = dest->samples + (unsigned int)((y - dest->y) * dest->stride + (scissor.x0 - dest->x) * n);
  1369. for (x = scissor.x0; x < scissor.x1; x++)
  1370. {
  1371. for (i = 0; i < n; i++)
  1372. *s++ = colorbv[i];
  1373. }
  1374. }
  1375. }
  1376. if (shape)
  1377. {
  1378. for (y = scissor.y0; y < scissor.y1; y++)
  1379. {
  1380. s = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (scissor.x0 - shape->x));
  1381. for (x = scissor.x0; x < scissor.x1; x++)
  1382. {
  1383. *s++ = 255;
  1384. }
  1385. }
  1386. }
  1387. if (group_alpha)
  1388. {
  1389. for (y = scissor.y0; y < scissor.y1; y++)
  1390. {
  1391. s = group_alpha->samples + (unsigned int)((y - group_alpha->y) * group_alpha->stride + (scissor.x0 - group_alpha->x));
  1392. for (x = scissor.x0; x < scissor.x1; x++)
  1393. {
  1394. *s++ = alpha_byte;
  1395. }
  1396. }
  1397. }
  1398. }
  1399. if (color_params.op)
  1400. eop = set_op_from_spaces(ctx, &op, dest, colorspace, 0);
  1401. else
  1402. eop = NULL;
  1403. fz_paint_shade(ctx, shade, colorspace, ctm, dest, color_params, bbox, eop, &dev->shade_cache);
  1404. if (shape)
  1405. fz_clear_pixmap_rect_with_value(ctx, shape, 255, bbox);
  1406. if (group_alpha)
  1407. fz_clear_pixmap_rect_with_value(ctx, group_alpha, 255, bbox);
  1408. #ifdef DUMP_GROUP_BLENDS
  1409. dump_spaces(dev->top, "");
  1410. fz_dump_blend(ctx, "Shade ", dest);
  1411. if (shape)
  1412. fz_dump_blend(ctx, "/S=", shape);
  1413. if (group_alpha)
  1414. fz_dump_blend(ctx, "/GA=", group_alpha);
  1415. printf("\n");
  1416. #endif
  1417. if (alpha < 1)
  1418. {
  1419. /* FIXME: eop */
  1420. fz_paint_pixmap(state->dest, dest, alpha * 255);
  1421. fz_drop_pixmap(ctx, dest);
  1422. dest = NULL;
  1423. if (shape)
  1424. {
  1425. fz_paint_pixmap(state->shape, shape, 255);
  1426. fz_drop_pixmap(ctx, shape);
  1427. shape = NULL;
  1428. }
  1429. if (group_alpha)
  1430. {
  1431. fz_paint_pixmap(state->group_alpha, group_alpha, alpha * 255);
  1432. fz_drop_pixmap(ctx, group_alpha);
  1433. group_alpha = NULL;
  1434. }
  1435. }
  1436. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  1437. fz_knockout_end(ctx, dev);
  1438. }
  1439. fz_catch(ctx)
  1440. {
  1441. if (dest != state[0].dest) fz_drop_pixmap(ctx, dest);
  1442. if (shape != state[0].shape) fz_drop_pixmap(ctx, shape);
  1443. if (group_alpha != state[0].group_alpha) fz_drop_pixmap(ctx, group_alpha);
  1444. fz_rethrow(ctx);
  1445. }
  1446. }
  1447. static fz_pixmap *
  1448. fz_transform_pixmap(fz_context *ctx, fz_draw_device *dev, const fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy, int gridfit, const fz_irect *clip)
  1449. {
  1450. fz_pixmap *scaled;
  1451. if (clip != NULL && fz_is_empty_irect(*clip))
  1452. return NULL;
  1453. if (ctm->a != 0 && ctm->b == 0 && ctm->c == 0 && ctm->d != 0)
  1454. {
  1455. /* Unrotated or X-flip or Y-flip or XY-flip */
  1456. fz_matrix m = *ctm;
  1457. if (gridfit)
  1458. {
  1459. m = fz_gridfit_matrix(dev->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, m);
  1460. }
  1461. scaled = fz_scale_pixmap_cached(ctx, image, m.e, m.f, m.a, m.d, clip, dev->cache_x, dev->cache_y);
  1462. if (!scaled)
  1463. return NULL;
  1464. ctm->a = scaled->w;
  1465. ctm->d = scaled->h;
  1466. ctm->e = scaled->x;
  1467. ctm->f = scaled->y;
  1468. return scaled;
  1469. }
  1470. if (ctm->a == 0 && ctm->b != 0 && ctm->c != 0 && ctm->d == 0)
  1471. {
  1472. /* Other orthogonal flip/rotation cases */
  1473. fz_matrix m = *ctm;
  1474. fz_irect rclip;
  1475. if (gridfit)
  1476. m = fz_gridfit_matrix(dev->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, m);
  1477. if (clip)
  1478. {
  1479. rclip.x0 = clip->y0;
  1480. rclip.y0 = clip->x0;
  1481. rclip.x1 = clip->y1;
  1482. rclip.y1 = clip->x1;
  1483. }
  1484. scaled = fz_scale_pixmap_cached(ctx, image, m.f, m.e, m.b, m.c, (clip ? &rclip : NULL), dev->cache_x, dev->cache_y);
  1485. if (!scaled)
  1486. return NULL;
  1487. ctm->b = scaled->w;
  1488. ctm->c = scaled->h;
  1489. ctm->f = scaled->x;
  1490. ctm->e = scaled->y;
  1491. return scaled;
  1492. }
  1493. /* Downscale, non rectilinear case */
  1494. if (dx > 0 && dy > 0)
  1495. {
  1496. scaled = fz_scale_pixmap_cached(ctx, image, 0, 0, dx, dy, NULL, dev->cache_x, dev->cache_y);
  1497. return scaled;
  1498. }
  1499. return NULL;
  1500. }
  1501. int
  1502. fz_default_image_scale(void *arg, int dst_w, int dst_h, int src_w, int src_h)
  1503. {
  1504. (void)arg;
  1505. return dst_w < src_w && dst_h < src_h;
  1506. }
  1507. static fz_pixmap *
  1508. convert_pixmap_for_painting(fz_context *ctx, fz_pixmap *pixmap, fz_colorspace *model, fz_colorspace *src_cs, fz_pixmap *dest, fz_color_params color_params, fz_draw_device *dev, fz_overprint **eop)
  1509. {
  1510. fz_pixmap *converted;
  1511. /* It's OK to plot a pixmap with no seps onto a dest with seps, but if the pixmap has seps, then they must match! */
  1512. if ((fz_colorspace_is_device_n(ctx, src_cs) && dest->seps) || (pixmap->seps != NULL && fz_compare_separations(ctx, pixmap->seps, dest->seps)))
  1513. {
  1514. converted = fz_clone_pixmap_area_with_different_seps(ctx, pixmap, NULL, model, dest->seps, color_params, dev->default_cs);
  1515. *eop = set_op_from_spaces(ctx, *eop, dest, src_cs, 0);
  1516. }
  1517. else
  1518. {
  1519. converted = fz_convert_pixmap(ctx, pixmap, model, NULL, dev->default_cs, color_params, 1);
  1520. if (*eop)
  1521. {
  1522. if (fz_colorspace_type(ctx, model) != FZ_COLORSPACE_CMYK)
  1523. {
  1524. /* Can only overprint to CMYK based spaces */
  1525. *eop = NULL;
  1526. }
  1527. else if (!fz_colorspace_is_device_n(ctx, pixmap->colorspace))
  1528. {
  1529. int i;
  1530. int n = dest->n - dest->alpha;
  1531. for (i = 4; i < n; i++)
  1532. fz_set_overprint(*eop, i);
  1533. }
  1534. else
  1535. {
  1536. *eop = set_op_from_spaces(ctx, *eop, dest, src_cs, 0);
  1537. }
  1538. }
  1539. }
  1540. fz_drop_pixmap(ctx, pixmap);
  1541. return converted;
  1542. }
  1543. static fz_irect
  1544. find_src_area_required(fz_matrix local_ctm, fz_image *image, fz_irect clip)
  1545. {
  1546. fz_matrix inverse;
  1547. fz_irect src_area;
  1548. /* ctm maps the image (expressed as the unit square) onto the
  1549. * destination device. Reverse that to get a mapping from
  1550. * the destination device to the source pixels. */
  1551. if (fz_try_invert_matrix(&inverse, local_ctm))
  1552. {
  1553. /* Not invertible. Could just bail? Use the whole image
  1554. * for now. */
  1555. src_area.x0 = 0;
  1556. src_area.x1 = image->w;
  1557. src_area.y0 = 0;
  1558. src_area.y1 = image->h;
  1559. }
  1560. else
  1561. {
  1562. float exp;
  1563. fz_rect rect;
  1564. fz_irect sane;
  1565. /* We want to scale from image coords, not from unit square */
  1566. inverse = fz_post_scale(inverse, image->w, image->h);
  1567. /* Are we scaling up or down? exp < 1 means scaling down. */
  1568. exp = fz_matrix_max_expansion(inverse);
  1569. rect = fz_rect_from_irect(clip);
  1570. rect = fz_transform_rect(rect, inverse);
  1571. /* Allow for support requirements for scalers. */
  1572. rect = fz_expand_rect(rect, fz_max(exp, 1) * 4);
  1573. src_area = fz_irect_from_rect(rect);
  1574. sane.x0 = 0;
  1575. sane.y0 = 0;
  1576. sane.x1 = image->w;
  1577. sane.y1 = image->h;
  1578. src_area = fz_intersect_irect(src_area, sane);
  1579. }
  1580. return src_area;
  1581. }
  1582. static void
  1583. fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, fz_matrix in_ctm, float alpha, fz_color_params color_params)
  1584. {
  1585. fz_draw_device *dev = (fz_draw_device*)devp;
  1586. fz_matrix local_ctm = fz_concat(in_ctm, dev->transform);
  1587. fz_pixmap *pixmap;
  1588. int after;
  1589. int dx, dy;
  1590. fz_draw_state *state = &dev->stack[dev->top];
  1591. fz_colorspace *model;
  1592. fz_irect clip;
  1593. fz_irect src_area;
  1594. fz_colorspace *src_cs;
  1595. fz_overprint op = { { 0 } };
  1596. fz_overprint *eop = &op;
  1597. if (alpha == 0)
  1598. return;
  1599. if (dev->top == 0 && dev->resolve_spots)
  1600. state = push_group_for_separations(ctx, dev, color_params, dev->default_cs);
  1601. model = state->dest->colorspace;
  1602. clip = fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest), state->scissor);
  1603. if (image->w == 0 || image->h == 0 || fz_is_empty_irect(clip))
  1604. return;
  1605. if (color_params.op == 0)
  1606. eop = NULL;
  1607. if (!(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3))
  1608. local_ctm = fz_gridfit_matrix(devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, local_ctm);
  1609. src_area = find_src_area_required(local_ctm, image, clip);
  1610. if (fz_is_empty_irect(src_area))
  1611. return;
  1612. pixmap = fz_get_pixmap_from_image(ctx, image, &src_area, &local_ctm, &dx, &dy);
  1613. src_cs = fz_default_colorspace(ctx, dev->default_cs, pixmap->colorspace);
  1614. /* convert images with more components (cmyk->rgb) before scaling */
  1615. /* convert images with fewer components (gray->rgb) after scaling */
  1616. /* convert images with expensive colorspace transforms after scaling */
  1617. fz_var(pixmap);
  1618. fz_try(ctx)
  1619. {
  1620. int conversion_required = (src_cs != model || fz_compare_separations(ctx, state->dest->seps, pixmap->seps));
  1621. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  1622. state = fz_knockout_begin(ctx, dev);
  1623. switch (fz_colorspace_type(ctx, src_cs))
  1624. {
  1625. case FZ_COLORSPACE_GRAY:
  1626. after = 1;
  1627. break;
  1628. case FZ_COLORSPACE_INDEXED:
  1629. after = 0;
  1630. break;
  1631. default:
  1632. if (fz_colorspace_n(ctx, src_cs) <= fz_colorspace_n(ctx, model))
  1633. after = 1;
  1634. else
  1635. after = 0;
  1636. break;
  1637. }
  1638. if (conversion_required && !after)
  1639. pixmap = convert_pixmap_for_painting(ctx, pixmap, model, src_cs, state->dest, color_params, dev, &eop);
  1640. if (!(devp->hints & FZ_DONT_INTERPOLATE_IMAGES) && ctx->tuning->image_scale(ctx->tuning->image_scale_arg, dx, dy, pixmap->w, pixmap->h))
  1641. {
  1642. int gridfit = alpha == 1.0f && !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3);
  1643. fz_pixmap *scaled = fz_transform_pixmap(ctx, dev, pixmap, &local_ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip);
  1644. if (!scaled)
  1645. {
  1646. if (dx < 1)
  1647. dx = 1;
  1648. if (dy < 1)
  1649. dy = 1;
  1650. scaled = fz_scale_pixmap_cached(ctx, pixmap, pixmap->x, pixmap->y, dx, dy, NULL, dev->cache_x, dev->cache_y);
  1651. }
  1652. if (scaled)
  1653. {
  1654. fz_drop_pixmap(ctx, pixmap);
  1655. pixmap = scaled;
  1656. }
  1657. }
  1658. if (conversion_required && after)
  1659. {
  1660. #if FZ_PLOTTERS_RGB
  1661. if (state->dest->seps == NULL &&
  1662. ((src_cs == fz_device_gray(ctx) && model == fz_device_rgb(ctx)) ||
  1663. (src_cs == fz_device_gray(ctx) && model == fz_device_bgr(ctx))))
  1664. {
  1665. /* We have special case rendering code for gray -> rgb/bgr */
  1666. }
  1667. else
  1668. #endif
  1669. pixmap = convert_pixmap_for_painting(ctx, pixmap, model, src_cs, state->dest, color_params, dev, &eop);
  1670. }
  1671. fz_paint_image(ctx, state->dest, &state->scissor, state->shape, state->group_alpha, pixmap, local_ctm, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), eop);
  1672. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  1673. fz_knockout_end(ctx, dev);
  1674. }
  1675. fz_always(ctx)
  1676. fz_drop_pixmap(ctx, pixmap);
  1677. fz_catch(ctx)
  1678. fz_rethrow(ctx);
  1679. }
  1680. static void
  1681. fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, fz_matrix in_ctm,
  1682. fz_colorspace *colorspace_in, const float *color, float alpha, fz_color_params color_params)
  1683. {
  1684. fz_draw_device *dev = (fz_draw_device*)devp;
  1685. fz_matrix local_ctm = fz_concat(in_ctm, dev->transform);
  1686. unsigned char colorbv[FZ_MAX_COLORS + 1];
  1687. fz_pixmap *scaled = NULL;
  1688. fz_pixmap *pixmap;
  1689. int dx, dy;
  1690. fz_draw_state *state = &dev->stack[dev->top];
  1691. fz_irect clip;
  1692. fz_irect src_area;
  1693. fz_colorspace *colorspace = NULL;
  1694. fz_overprint op = { { 0 } };
  1695. fz_overprint *eop;
  1696. if (alpha == 0)
  1697. return;
  1698. if (dev->top == 0 && dev->resolve_spots)
  1699. state = push_group_for_separations(ctx, dev, color_params, dev->default_cs);
  1700. if (colorspace_in)
  1701. colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
  1702. clip = fz_pixmap_bbox(ctx, state->dest);
  1703. clip = fz_intersect_irect(clip, state->scissor);
  1704. if (image->w == 0 || image->h == 0)
  1705. return;
  1706. if (!(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3))
  1707. local_ctm = fz_gridfit_matrix(devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, local_ctm);
  1708. src_area = find_src_area_required(local_ctm, image, clip);
  1709. if (fz_is_empty_irect(src_area))
  1710. return;
  1711. pixmap = fz_get_pixmap_from_image(ctx, image, &src_area, &local_ctm, &dx, &dy);
  1712. fz_var(pixmap);
  1713. fz_try(ctx)
  1714. {
  1715. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  1716. state = fz_knockout_begin(ctx, dev);
  1717. if (!(devp->hints & FZ_DONT_INTERPOLATE_IMAGES) && ctx->tuning->image_scale(ctx->tuning->image_scale_arg, dx, dy, pixmap->w, pixmap->h))
  1718. {
  1719. int gridfit = alpha == 1.0f && !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3);
  1720. scaled = fz_transform_pixmap(ctx, dev, pixmap, &local_ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip);
  1721. if (!scaled)
  1722. {
  1723. if (dx < 1)
  1724. dx = 1;
  1725. if (dy < 1)
  1726. dy = 1;
  1727. scaled = fz_scale_pixmap_cached(ctx, pixmap, pixmap->x, pixmap->y, dx, dy, NULL, dev->cache_x, dev->cache_y);
  1728. }
  1729. if (scaled)
  1730. {
  1731. fz_drop_pixmap(ctx, pixmap);
  1732. pixmap = scaled;
  1733. }
  1734. }
  1735. eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, dev->overprint_possible);
  1736. fz_paint_image_with_color(ctx, state->dest, &state->scissor, state->shape, state->group_alpha, pixmap, local_ctm, colorbv, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), eop);
  1737. if (state->blendmode & FZ_BLEND_KNOCKOUT && alpha != 1)
  1738. fz_knockout_end(ctx, dev);
  1739. }
  1740. fz_always(ctx)
  1741. fz_drop_pixmap(ctx, pixmap);
  1742. fz_catch(ctx)
  1743. fz_rethrow(ctx);
  1744. }
  1745. static void
  1746. fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, fz_matrix in_ctm, fz_rect scissor)
  1747. {
  1748. fz_draw_device *dev = (fz_draw_device*)devp;
  1749. fz_matrix local_ctm = fz_concat(in_ctm, dev->transform);
  1750. fz_irect bbox;
  1751. fz_pixmap *scaled = NULL;
  1752. fz_pixmap *pixmap = NULL;
  1753. int dx, dy;
  1754. fz_draw_state *state = push_stack(ctx, dev, "clip image mask");
  1755. fz_colorspace *model = state->dest->colorspace;
  1756. fz_irect clip;
  1757. fz_irect src_area;
  1758. fz_var(pixmap);
  1759. if (dev->top == 0 && dev->resolve_spots)
  1760. state = push_group_for_separations(ctx, dev, fz_default_color_params /* FIXME */, dev->default_cs);
  1761. clip = fz_pixmap_bbox(ctx, state->dest);
  1762. clip = fz_intersect_irect(clip, state->scissor);
  1763. if (image->w == 0 || image->h == 0)
  1764. {
  1765. #ifdef DUMP_GROUP_BLENDS
  1766. dump_spaces(dev->top-1, "Clip (image mask) (empty) begin\n");
  1767. #endif
  1768. state[1].scissor = fz_empty_irect;
  1769. state[1].mask = NULL;
  1770. return;
  1771. }
  1772. if (!(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3))
  1773. local_ctm = fz_gridfit_matrix(devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, local_ctm);
  1774. src_area = find_src_area_required(local_ctm, image, clip);
  1775. if (fz_is_empty_irect(src_area))
  1776. {
  1777. #ifdef DUMP_GROUP_BLENDS
  1778. dump_spaces(dev->top-1, "Clip (image mask) (empty source area) begin\n");
  1779. #endif
  1780. state[1].scissor = fz_empty_irect;
  1781. state[1].mask = NULL;
  1782. return;
  1783. }
  1784. bbox = fz_irect_from_rect(fz_transform_rect(fz_unit_rect, local_ctm));
  1785. bbox = fz_intersect_irect(bbox, state->scissor);
  1786. if (!fz_is_infinite_rect(scissor))
  1787. {
  1788. fz_rect tscissor = fz_transform_rect(scissor, dev->transform);
  1789. bbox = fz_intersect_irect(bbox, fz_irect_from_rect(tscissor));
  1790. }
  1791. if (!fz_is_valid_irect(bbox))
  1792. {
  1793. #ifdef DUMP_GROUP_BLENDS
  1794. dump_spaces(dev->top-1, "Clip (image mask) (invalid) begin\n");
  1795. #endif
  1796. state[1].scissor = fz_empty_irect;
  1797. state[1].mask = NULL;
  1798. return;
  1799. }
  1800. #ifdef DUMP_GROUP_BLENDS
  1801. dump_spaces(dev->top-1, "Clip (image mask) begin\n");
  1802. #endif
  1803. fz_try(ctx)
  1804. {
  1805. pixmap = fz_get_pixmap_from_image(ctx, image, &src_area, &local_ctm, &dx, &dy);
  1806. state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1807. fz_clear_pixmap(ctx, state[1].mask);
  1808. state[1].dest = fz_new_pixmap_with_bbox(ctx, model, bbox, state[0].dest->seps, state[0].dest->alpha);
  1809. fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, bbox, dev->default_cs);
  1810. if (state[0].shape)
  1811. {
  1812. state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1813. fz_clear_pixmap(ctx, state[1].shape);
  1814. }
  1815. if (state[0].group_alpha)
  1816. {
  1817. state[1].group_alpha = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1818. fz_clear_pixmap(ctx, state[1].group_alpha);
  1819. }
  1820. state[1].blendmode |= FZ_BLEND_ISOLATED;
  1821. state[1].scissor = bbox;
  1822. if (!(devp->hints & FZ_DONT_INTERPOLATE_IMAGES) && ctx->tuning->image_scale(ctx->tuning->image_scale_arg, dx, dy, pixmap->w, pixmap->h))
  1823. {
  1824. int gridfit = !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3);
  1825. scaled = fz_transform_pixmap(ctx, dev, pixmap, &local_ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip);
  1826. if (!scaled)
  1827. {
  1828. if (dx < 1)
  1829. dx = 1;
  1830. if (dy < 1)
  1831. dy = 1;
  1832. scaled = fz_scale_pixmap_cached(ctx, pixmap, pixmap->x, pixmap->y, dx, dy, NULL, dev->cache_x, dev->cache_y);
  1833. }
  1834. if (scaled)
  1835. {
  1836. fz_drop_pixmap(ctx, pixmap);
  1837. pixmap = scaled;
  1838. }
  1839. }
  1840. #ifdef DUMP_GROUP_BLENDS
  1841. dump_spaces(dev->top, "");
  1842. fz_dump_blend(ctx, "Creating imagemask: plotting ", pixmap);
  1843. fz_dump_blend(ctx, " onto ", state[1].mask);
  1844. if (state[1].shape)
  1845. fz_dump_blend(ctx, "/S=", state[1].shape);
  1846. if (state[1].group_alpha)
  1847. fz_dump_blend(ctx, "/GA=", state[1].group_alpha);
  1848. #endif
  1849. fz_paint_image(ctx, state[1].mask, &bbox, state[1].shape, state[1].group_alpha, pixmap, local_ctm, 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), 0);
  1850. #ifdef DUMP_GROUP_BLENDS
  1851. fz_dump_blend(ctx, " to get ", state[1].mask);
  1852. if (state[1].shape)
  1853. fz_dump_blend(ctx, "/S=", state[1].shape);
  1854. if (state[1].group_alpha)
  1855. fz_dump_blend(ctx, "/GA=", state[1].group_alpha);
  1856. printf("\n");
  1857. #endif
  1858. }
  1859. fz_always(ctx)
  1860. fz_drop_pixmap(ctx, pixmap);
  1861. fz_catch(ctx)
  1862. fz_rethrow(ctx);
  1863. }
  1864. static void
  1865. fz_draw_pop_clip(fz_context *ctx, fz_device *devp)
  1866. {
  1867. fz_draw_device *dev = (fz_draw_device*)devp;
  1868. fz_draw_state *state;
  1869. if (dev->top == 0)
  1870. fz_throw(ctx, FZ_ERROR_ARGUMENT, "unexpected pop clip");
  1871. state = pop_stack(ctx, dev, "clip");
  1872. /* We can get here with state[1].mask == NULL if the clipping actually
  1873. * resolved to a rectangle earlier.
  1874. */
  1875. if (state[1].mask)
  1876. {
  1877. fz_try(ctx)
  1878. {
  1879. #ifdef DUMP_GROUP_BLENDS
  1880. dump_spaces(dev->top, "");
  1881. fz_dump_blend(ctx, "Clipping ", state[1].dest);
  1882. if (state[1].shape)
  1883. fz_dump_blend(ctx, "/S=", state[1].shape);
  1884. if (state[1].group_alpha)
  1885. fz_dump_blend(ctx, "/GA=", state[1].group_alpha);
  1886. fz_dump_blend(ctx, " onto ", state[0].dest);
  1887. if (state[0].shape)
  1888. fz_dump_blend(ctx, "/S=", state[0].shape);
  1889. if (state[0].group_alpha)
  1890. fz_dump_blend(ctx, "/GA=", state[0].group_alpha);
  1891. fz_dump_blend(ctx, " with ", state[1].mask);
  1892. #endif
  1893. fz_paint_pixmap_with_mask(state[0].dest, state[1].dest, state[1].mask);
  1894. if (state[0].shape != state[1].shape)
  1895. {
  1896. fz_paint_over_pixmap_with_mask(state[0].shape, state[1].shape, state[1].mask);
  1897. }
  1898. if (state[0].group_alpha != state[1].group_alpha)
  1899. {
  1900. fz_paint_over_pixmap_with_mask(state[0].group_alpha, state[1].group_alpha, state[1].mask);
  1901. }
  1902. #ifdef DUMP_GROUP_BLENDS
  1903. fz_dump_blend(ctx, " to get ", state[0].dest);
  1904. if (state[0].shape)
  1905. fz_dump_blend(ctx, "/S=", state[0].shape);
  1906. if (state[0].group_alpha)
  1907. fz_dump_blend(ctx, "/GA=", state[0].group_alpha);
  1908. printf("\n");
  1909. #endif
  1910. }
  1911. fz_always(ctx)
  1912. cleanup_post_pop(ctx, state);
  1913. fz_catch(ctx)
  1914. fz_rethrow(ctx);
  1915. }
  1916. else
  1917. {
  1918. #ifdef DUMP_GROUP_BLENDS
  1919. dump_spaces(dev->top, "Clip end\n");
  1920. #endif
  1921. }
  1922. }
  1923. static void
  1924. fz_draw_begin_mask(fz_context *ctx, fz_device *devp, fz_rect area, int luminosity, fz_colorspace *colorspace_in, const float *colorfv, fz_color_params color_params)
  1925. {
  1926. fz_draw_device *dev = (fz_draw_device*)devp;
  1927. fz_pixmap *dest;
  1928. fz_irect bbox;
  1929. fz_draw_state *state = push_stack(ctx, dev, "mask");
  1930. fz_pixmap *shape = state->shape;
  1931. fz_pixmap *group_alpha = state->group_alpha;
  1932. fz_rect trect;
  1933. fz_colorspace *colorspace = NULL;
  1934. if (dev->top == 0 && dev->resolve_spots)
  1935. state = push_group_for_separations(ctx, dev, color_params, dev->default_cs);
  1936. if (colorspace_in)
  1937. colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
  1938. trect = fz_transform_rect(area, dev->transform);
  1939. bbox = fz_intersect_irect(fz_irect_from_rect(trect), state->scissor);
  1940. /* Reset the blendmode for the mask rendering. In particular,
  1941. * don't carry forward knockout or isolated. */
  1942. state[1].blendmode = 0;
  1943. /* If luminosity, then we generate a mask from the greyscale value of the shapes.
  1944. * If !luminosity, then we generate a mask from the alpha value of the shapes.
  1945. */
  1946. if (luminosity)
  1947. state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), bbox, NULL, 0);
  1948. else
  1949. state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  1950. if (state->shape)
  1951. {
  1952. /* FIXME: If we ever want to support AIS true, then
  1953. * we probably want to create a shape pixmap here,
  1954. * using: shape = fz_new_pixmap_with_bbox(NULL, bbox);
  1955. * then, in the end_mask code, we create the mask
  1956. * from this rather than dest.
  1957. */
  1958. state[1].shape = shape = NULL;
  1959. }
  1960. if (state->group_alpha)
  1961. {
  1962. state[1].group_alpha = group_alpha = NULL;
  1963. }
  1964. if (luminosity)
  1965. {
  1966. float bc;
  1967. if (!colorspace)
  1968. colorspace = fz_device_gray(ctx);
  1969. fz_convert_color(ctx, colorspace, colorfv, fz_device_gray(ctx), &bc, NULL, color_params);
  1970. fz_clear_pixmap_with_value(ctx, dest, bc * 255);
  1971. if (shape)
  1972. fz_clear_pixmap_with_value(ctx, shape, 255);
  1973. if (group_alpha)
  1974. fz_clear_pixmap_with_value(ctx, group_alpha, 255);
  1975. }
  1976. else
  1977. {
  1978. fz_clear_pixmap(ctx, dest);
  1979. if (shape)
  1980. fz_clear_pixmap(ctx, shape);
  1981. if (group_alpha)
  1982. fz_clear_pixmap(ctx, group_alpha);
  1983. }
  1984. #ifdef DUMP_GROUP_BLENDS
  1985. dump_spaces(dev->top-1, "Mask begin\n");
  1986. #endif
  1987. state[1].scissor = bbox;
  1988. }
  1989. static void
  1990. apply_transfer_function_to_pixmap(fz_context *ctx, fz_pixmap *pix, fz_function *tr)
  1991. {
  1992. int w, h;
  1993. ptrdiff_t stride;
  1994. uint8_t *s;
  1995. assert(pix && pix->n == 1);
  1996. if (pix->w * (size_t)pix->h > 1024)
  1997. {
  1998. uint8_t memo[256];
  1999. for (w = 0; w < 256; w++)
  2000. {
  2001. float f = w / 255.0f;
  2002. float d;
  2003. fz_eval_function(ctx, tr, &f, 1, &d, 1);
  2004. memo[w] = (uint8_t)fz_clampi(d*255.0f, 0, 255);
  2005. }
  2006. s = pix->samples;
  2007. stride = pix->stride - pix->w;
  2008. for (h = pix->h; h > 0; h--)
  2009. {
  2010. for (w = pix->w; w > 0; w--)
  2011. {
  2012. *s = memo[*s];
  2013. s++;
  2014. }
  2015. s += stride;
  2016. }
  2017. return;
  2018. }
  2019. s = pix->samples;
  2020. stride = pix->stride - pix->w;
  2021. for (h = pix->h; h > 0; h--)
  2022. {
  2023. for (w = pix->w; w > 0; w--)
  2024. {
  2025. float f = *s / 255.0f;
  2026. float d;
  2027. fz_eval_function(ctx, tr, &f, 1, &d, 1);
  2028. *s++ = (uint8_t)fz_clampi(d*255.0f, 0, 255);
  2029. }
  2030. s += stride;
  2031. }
  2032. }
  2033. static void
  2034. fz_draw_end_mask(fz_context *ctx, fz_device *devp, fz_function *tr)
  2035. {
  2036. fz_draw_device *dev = (fz_draw_device*)devp;
  2037. fz_pixmap *temp, *dest;
  2038. fz_irect bbox;
  2039. fz_draw_state *state;
  2040. if (dev->top == 0)
  2041. fz_throw(ctx, FZ_ERROR_ARGUMENT, "unexpected end mask");
  2042. state = convert_stack(ctx, dev, "mask");
  2043. #ifdef DUMP_GROUP_BLENDS
  2044. dump_spaces(dev->top-1, "Mask -> Clip: ");
  2045. fz_dump_blend(ctx, "Mask ", state[1].dest);
  2046. if (state[1].shape)
  2047. fz_dump_blend(ctx, "/S=", state[1].shape);
  2048. if (state[1].group_alpha)
  2049. fz_dump_blend(ctx, "/GA=", state[1].group_alpha);
  2050. #endif
  2051. {
  2052. /* convert to alpha mask */
  2053. temp = fz_alpha_from_gray(ctx, state[1].dest);
  2054. if (state[1].mask != state[0].mask)
  2055. fz_drop_pixmap(ctx, state[1].mask);
  2056. state[1].mask = temp;
  2057. if (state[1].dest != state[0].dest)
  2058. fz_drop_pixmap(ctx, state[1].dest);
  2059. state[1].dest = NULL;
  2060. if (state[1].shape != state[0].shape)
  2061. fz_drop_pixmap(ctx, state[1].shape);
  2062. state[1].shape = NULL;
  2063. if (state[1].group_alpha != state[0].group_alpha)
  2064. fz_drop_pixmap(ctx, state[1].group_alpha);
  2065. state[1].group_alpha = NULL;
  2066. #ifdef DUMP_GROUP_BLENDS
  2067. fz_dump_blend(ctx, "-> Clip ", temp);
  2068. printf("\n");
  2069. #endif
  2070. if (tr)
  2071. {
  2072. /* Apply transfer function to state[1].mask */
  2073. apply_transfer_function_to_pixmap(ctx, state[1].mask, tr);
  2074. }
  2075. /* create new dest scratch buffer */
  2076. bbox = fz_pixmap_bbox(ctx, temp);
  2077. dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, bbox, state->dest->seps, state->dest->alpha);
  2078. fz_copy_pixmap_rect(ctx, dest, state->dest, bbox, dev->default_cs);
  2079. /* push soft mask as clip mask */
  2080. state[1].dest = dest;
  2081. state[1].blendmode |= FZ_BLEND_ISOLATED;
  2082. /* If we have a shape, then it'll need to be masked with the
  2083. * clip mask when we pop. So create a new shape now. */
  2084. if (state[0].shape)
  2085. {
  2086. state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  2087. fz_clear_pixmap(ctx, state[1].shape);
  2088. }
  2089. if (state[0].group_alpha)
  2090. {
  2091. state[1].group_alpha = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  2092. fz_clear_pixmap(ctx, state[1].group_alpha);
  2093. }
  2094. state[1].scissor = bbox;
  2095. }
  2096. }
  2097. static void
  2098. fz_draw_begin_group(fz_context *ctx, fz_device *devp, fz_rect area, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
  2099. {
  2100. fz_draw_device *dev = (fz_draw_device*)devp;
  2101. fz_irect bbox;
  2102. fz_pixmap *dest;
  2103. fz_draw_state *state = &dev->stack[dev->top];
  2104. fz_colorspace *model = state->dest->colorspace;
  2105. fz_rect trect;
  2106. if (dev->top == 0 && dev->resolve_spots)
  2107. state = push_group_for_separations(ctx, dev, fz_default_color_params /* FIXME */, dev->default_cs);
  2108. if (cs != NULL)
  2109. model = fz_default_colorspace(ctx, dev->default_cs, cs);
  2110. if (state->blendmode & FZ_BLEND_KNOCKOUT)
  2111. fz_knockout_begin(ctx, dev);
  2112. state = push_stack(ctx, dev, "group");
  2113. trect = fz_transform_rect(area, dev->transform);
  2114. bbox = fz_intersect_irect(fz_irect_from_rect(trect), state->scissor);
  2115. #ifndef ATTEMPT_KNOCKOUT_AND_ISOLATED
  2116. knockout = 0;
  2117. isolated = 1;
  2118. #endif
  2119. state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, bbox, state[0].dest->seps, state[0].dest->alpha || isolated);
  2120. if (isolated)
  2121. {
  2122. fz_clear_pixmap(ctx, dest);
  2123. state[1].group_alpha = NULL;
  2124. }
  2125. else
  2126. {
  2127. fz_copy_pixmap_rect(ctx, dest, state[0].dest, bbox, dev->default_cs);
  2128. state[1].group_alpha = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  2129. fz_clear_pixmap(ctx, state[1].group_alpha);
  2130. }
  2131. /* shape is inherited from the previous group */
  2132. state[1].alpha = alpha;
  2133. #ifdef DUMP_GROUP_BLENDS
  2134. dump_spaces(dev->top-1, "");
  2135. {
  2136. char text[240];
  2137. char atext[80];
  2138. char btext[80];
  2139. if (alpha != 1)
  2140. sprintf(atext, " (alpha %g)", alpha);
  2141. else
  2142. atext[0] = 0;
  2143. if (blendmode != 0)
  2144. sprintf(btext, " (blend %d)", blendmode);
  2145. else
  2146. btext[0] = 0;
  2147. sprintf(text, "Group begin%s%s%s%s: background is ", isolated ? " (isolated)" : "", knockout ? " (knockout)" : "", atext, btext);
  2148. fz_dump_blend(ctx, text, state[1].dest);
  2149. }
  2150. if (state[1].shape)
  2151. fz_dump_blend(ctx, "/S=", state[1].shape);
  2152. if (state[1].group_alpha)
  2153. fz_dump_blend(ctx, "/GA=", state[1].group_alpha);
  2154. printf("\n");
  2155. #endif
  2156. state[1].scissor = bbox;
  2157. state[1].blendmode = blendmode | (isolated ? FZ_BLEND_ISOLATED : 0) | (knockout ? FZ_BLEND_KNOCKOUT : 0);
  2158. }
  2159. static void
  2160. fz_draw_end_group(fz_context *ctx, fz_device *devp)
  2161. {
  2162. fz_draw_device *dev = (fz_draw_device*)devp;
  2163. int blendmode;
  2164. int isolated;
  2165. float alpha;
  2166. fz_draw_state *state;
  2167. if (dev->top == 0)
  2168. fz_throw(ctx, FZ_ERROR_ARGUMENT, "unexpected end group");
  2169. state = pop_stack(ctx, dev, "group");
  2170. fz_try(ctx)
  2171. {
  2172. alpha = state[1].alpha;
  2173. blendmode = state[1].blendmode & FZ_BLEND_MODEMASK;
  2174. isolated = state[1].blendmode & FZ_BLEND_ISOLATED;
  2175. #ifdef DUMP_GROUP_BLENDS
  2176. dump_spaces(dev->top, "");
  2177. fz_dump_blend(ctx, "Group end: blending ", state[1].dest);
  2178. if (state[1].shape)
  2179. fz_dump_blend(ctx, "/S=", state[1].shape);
  2180. if (state[1].group_alpha)
  2181. fz_dump_blend(ctx, "/GA=", state[1].group_alpha);
  2182. fz_dump_blend(ctx, " onto ", state[0].dest);
  2183. if (state[0].shape)
  2184. fz_dump_blend(ctx, "/S=", state[0].shape);
  2185. if (state[0].group_alpha)
  2186. fz_dump_blend(ctx, "/GA=", state[0].group_alpha);
  2187. if (alpha != 1.0f)
  2188. printf(" (alpha %g)", alpha);
  2189. if (blendmode != 0)
  2190. printf(" (blend %d)", blendmode);
  2191. if (isolated != 0)
  2192. printf(" (isolated)");
  2193. if (state[1].blendmode & FZ_BLEND_KNOCKOUT)
  2194. printf(" (knockout)");
  2195. #endif
  2196. if (state[0].dest->colorspace != state[1].dest->colorspace)
  2197. {
  2198. fz_pixmap *converted = fz_convert_pixmap(ctx, state[1].dest, state[0].dest->colorspace, NULL, dev->default_cs, fz_default_color_params, 1);
  2199. fz_drop_pixmap(ctx, state[1].dest);
  2200. state[1].dest = converted;
  2201. }
  2202. if ((blendmode == 0) && (state[0].shape == state[1].shape) && (state[0].group_alpha == state[1].group_alpha))
  2203. fz_paint_pixmap(state[0].dest, state[1].dest, alpha * 255);
  2204. else
  2205. fz_blend_pixmap(ctx, state[0].dest, state[1].dest, alpha * 255, blendmode, isolated, state[1].group_alpha);
  2206. if (state[0].shape != state[1].shape)
  2207. {
  2208. /* The 'D' on page 7 of Altona_Technical_v20_x4.pdf goes wrong if this
  2209. * isn't alpha * 255, as the blend back fails to take account of alpha. */
  2210. if (state[0].shape)
  2211. {
  2212. if (state[1].shape)
  2213. fz_paint_pixmap(state[0].shape, state[1].shape, alpha * 255);
  2214. else
  2215. fz_paint_pixmap_alpha(state[0].shape, state[1].dest, alpha * 255);
  2216. }
  2217. }
  2218. assert(state[0].group_alpha == NULL || state[0].group_alpha != state[1].group_alpha);
  2219. if (state[0].group_alpha && state[0].group_alpha != state[1].group_alpha)
  2220. {
  2221. /* The 'D' on page 7 of Altona_Technical_v20_x4.pdf uses an isolated group,
  2222. * and goes wrong if this is 255 * alpha, as an alpha effectively gets
  2223. * applied twice. CATX5233 page 7 uses a non-isolated group, and goes wrong
  2224. * if alpha isn't applied here. */
  2225. if (state[1].group_alpha)
  2226. fz_paint_pixmap(state[0].group_alpha, state[1].group_alpha, isolated ? 255 : alpha * 255);
  2227. else
  2228. fz_paint_pixmap_alpha(state[0].group_alpha, state[1].dest, isolated ? 255 : alpha * 255);
  2229. }
  2230. assert(state[0].dest != state[1].dest);
  2231. #ifdef DUMP_GROUP_BLENDS
  2232. fz_dump_blend(ctx, " to get ", state[0].dest);
  2233. if (state[0].shape)
  2234. fz_dump_blend(ctx, "/S=", state[0].shape);
  2235. if (state[0].group_alpha)
  2236. fz_dump_blend(ctx, "/GA=", state[0].group_alpha);
  2237. printf("\n");
  2238. #endif
  2239. }
  2240. fz_always(ctx)
  2241. cleanup_post_pop(ctx, state);
  2242. fz_catch(ctx)
  2243. fz_rethrow(ctx);
  2244. if (state[0].blendmode & FZ_BLEND_KNOCKOUT)
  2245. fz_knockout_end(ctx, dev);
  2246. }
  2247. typedef struct
  2248. {
  2249. int refs;
  2250. float ctm[4];
  2251. int id;
  2252. char has_shape;
  2253. char has_group_alpha;
  2254. fz_colorspace *cs;
  2255. } tile_key;
  2256. typedef struct
  2257. {
  2258. fz_storable storable;
  2259. fz_pixmap *dest;
  2260. fz_pixmap *shape;
  2261. fz_pixmap *group_alpha;
  2262. } tile_record;
  2263. static int
  2264. fz_make_hash_tile_key(fz_context *ctx, fz_store_hash *hash, void *key_)
  2265. {
  2266. tile_key *key = key_;
  2267. hash->u.im.id = key->id;
  2268. hash->u.im.has_shape = key->has_shape;
  2269. hash->u.im.has_group_alpha = key->has_group_alpha;
  2270. hash->u.im.m[0] = key->ctm[0];
  2271. hash->u.im.m[1] = key->ctm[1];
  2272. hash->u.im.m[2] = key->ctm[2];
  2273. hash->u.im.m[3] = key->ctm[3];
  2274. hash->u.im.ptr = key->cs;
  2275. return 1;
  2276. }
  2277. static void *
  2278. fz_keep_tile_key(fz_context *ctx, void *key_)
  2279. {
  2280. tile_key *key = key_;
  2281. return fz_keep_imp(ctx, key, &key->refs);
  2282. }
  2283. static void
  2284. fz_drop_tile_key(fz_context *ctx, void *key_)
  2285. {
  2286. tile_key *key = key_;
  2287. if (fz_drop_imp(ctx, key, &key->refs))
  2288. {
  2289. fz_drop_colorspace_store_key(ctx, key->cs);
  2290. fz_free(ctx, key);
  2291. }
  2292. }
  2293. static int
  2294. fz_cmp_tile_key(fz_context *ctx, void *k0_, void *k1_)
  2295. {
  2296. tile_key *k0 = k0_;
  2297. tile_key *k1 = k1_;
  2298. return k0->id == k1->id &&
  2299. k0->has_shape == k1->has_shape &&
  2300. k0->has_group_alpha == k1->has_group_alpha &&
  2301. k0->ctm[0] == k1->ctm[0] &&
  2302. k0->ctm[1] == k1->ctm[1] &&
  2303. k0->ctm[2] == k1->ctm[2] &&
  2304. k0->ctm[3] == k1->ctm[3] &&
  2305. k0->cs == k1->cs;
  2306. }
  2307. static void
  2308. fz_format_tile_key(fz_context *ctx, char *s, size_t n, void *key_)
  2309. {
  2310. tile_key *key = (tile_key *)key_;
  2311. fz_snprintf(s, n, "(tile id=%x, ctm=%g %g %g %g, cs=%x, shape=%d, ga=%d)",
  2312. key->id, key->ctm[0], key->ctm[1], key->ctm[2], key->ctm[3], key->cs,
  2313. key->has_shape, key->has_group_alpha);
  2314. }
  2315. static const fz_store_type fz_tile_store_type =
  2316. {
  2317. "struct tile_record",
  2318. fz_make_hash_tile_key,
  2319. fz_keep_tile_key,
  2320. fz_drop_tile_key,
  2321. fz_cmp_tile_key,
  2322. fz_format_tile_key,
  2323. NULL
  2324. };
  2325. static void
  2326. fz_drop_tile_record_imp(fz_context *ctx, fz_storable *storable)
  2327. {
  2328. tile_record *tr = (tile_record *)storable;
  2329. fz_drop_pixmap(ctx, tr->dest);
  2330. fz_drop_pixmap(ctx, tr->shape);
  2331. fz_drop_pixmap(ctx, tr->group_alpha);
  2332. fz_free(ctx, tr);
  2333. }
  2334. static void
  2335. fz_drop_tile_record(fz_context *ctx, tile_record *tile)
  2336. {
  2337. fz_drop_storable(ctx, &tile->storable);
  2338. }
  2339. static tile_record *
  2340. fz_new_tile_record(fz_context *ctx, fz_pixmap *dest, fz_pixmap *shape, fz_pixmap *group_alpha)
  2341. {
  2342. tile_record *tile = fz_malloc_struct(ctx, tile_record);
  2343. FZ_INIT_STORABLE(tile, 1, fz_drop_tile_record_imp);
  2344. tile->dest = fz_keep_pixmap(ctx, dest);
  2345. tile->shape = fz_keep_pixmap(ctx, shape);
  2346. tile->group_alpha = fz_keep_pixmap(ctx, group_alpha);
  2347. return tile;
  2348. }
  2349. size_t
  2350. fz_tile_size(fz_context *ctx, tile_record *tile)
  2351. {
  2352. if (!tile)
  2353. return 0;
  2354. return sizeof(*tile) + fz_pixmap_size(ctx, tile->dest) + fz_pixmap_size(ctx, tile->shape) + fz_pixmap_size(ctx, tile->group_alpha);
  2355. }
  2356. static int
  2357. fz_draw_begin_tile(fz_context *ctx, fz_device *devp, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix in_ctm, int id)
  2358. {
  2359. fz_draw_device *dev = (fz_draw_device*)devp;
  2360. fz_matrix ctm = fz_concat(in_ctm, dev->transform);
  2361. fz_pixmap *dest = NULL;
  2362. fz_pixmap *shape, *group_alpha;
  2363. fz_irect bbox;
  2364. fz_draw_state *state = &dev->stack[dev->top];
  2365. fz_colorspace *model = state->dest->colorspace;
  2366. fz_rect local_view;
  2367. if (dev->top == 0 && dev->resolve_spots)
  2368. state = push_group_for_separations(ctx, dev, fz_default_color_params /* FIXME */, dev->default_cs);
  2369. /* area, view, xstep, ystep are in pattern space
  2370. * area = the extent that we need to tile the pattern into. (i.e this is
  2371. * the area to be filled with the pattern mapped back into pattern space).
  2372. * view = the pattern bbox.
  2373. * xstep and ystep are the repeats for the file.
  2374. */
  2375. /* ctm maps from pattern space to device space */
  2376. if (state->blendmode & FZ_BLEND_KNOCKOUT)
  2377. fz_knockout_begin(ctx, dev);
  2378. state = push_stack(ctx, dev, "tile");
  2379. state[1].flags = dev->flags;
  2380. dev->flags &= ~FZ_DRAWDEV_FLAGS_TYPE3;
  2381. local_view = fz_transform_rect(view, ctm);
  2382. bbox = fz_irect_from_rect(local_view);
  2383. /* We should never have a bbox that entirely covers our destination.
  2384. * If we do, then the check for only 1 tile being visible above has
  2385. * failed. Actually, this *can* fail due to the round_rect, at extreme
  2386. * resolutions, so disable this assert.
  2387. * assert(bbox.x0 > state->dest->x || bbox.x1 < state->dest->x + state->dest->w ||
  2388. * bbox.y0 > state->dest->y || bbox.y1 < state->dest->y + state->dest->h);
  2389. */
  2390. /* A BBox of zero height or width should still paint one pixel! */
  2391. if (bbox.x1 == bbox.x0)
  2392. bbox.x1 = bbox.x0 + 1;
  2393. if (bbox.y1 == bbox.y0)
  2394. bbox.y1 = bbox.y0 + 1;
  2395. /* Check to see if we have one cached */
  2396. if (id)
  2397. {
  2398. tile_key tk;
  2399. tile_record *tile;
  2400. tk.ctm[0] = ctm.a;
  2401. tk.ctm[1] = ctm.b;
  2402. tk.ctm[2] = ctm.c;
  2403. tk.ctm[3] = ctm.d;
  2404. tk.id = id;
  2405. tk.cs = state[1].dest->colorspace;
  2406. tk.has_shape = (state[1].shape != NULL);
  2407. tk.has_group_alpha = (state[1].group_alpha != NULL);
  2408. tile = fz_find_item(ctx, fz_drop_tile_record_imp, &tk, &fz_tile_store_type);
  2409. if (tile)
  2410. {
  2411. state[1].dest = fz_keep_pixmap(ctx, tile->dest);
  2412. state[1].shape = fz_keep_pixmap(ctx, tile->shape);
  2413. state[1].group_alpha = fz_keep_pixmap(ctx, tile->group_alpha);
  2414. state[1].blendmode |= FZ_BLEND_ISOLATED;
  2415. state[1].xstep = xstep;
  2416. state[1].ystep = ystep;
  2417. state[1].id = id;
  2418. state[1].encache = 0;
  2419. state[1].area = fz_irect_from_rect(area);
  2420. state[1].ctm = ctm;
  2421. state[1].scissor = bbox;
  2422. #ifdef DUMP_GROUP_BLENDS
  2423. dump_spaces(dev->top-1, "Tile begin (cached)\n");
  2424. #endif
  2425. fz_drop_tile_record(ctx, tile);
  2426. return 1;
  2427. }
  2428. }
  2429. /* Patterns can be transparent, so we need to have an alpha here. */
  2430. state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, bbox, state[0].dest->seps, 1);
  2431. fz_clear_pixmap(ctx, dest);
  2432. shape = state[0].shape;
  2433. if (shape)
  2434. {
  2435. state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  2436. fz_clear_pixmap(ctx, shape);
  2437. }
  2438. group_alpha = state[0].group_alpha;
  2439. if (group_alpha)
  2440. {
  2441. state[1].group_alpha = group_alpha = fz_new_pixmap_with_bbox(ctx, NULL, bbox, NULL, 1);
  2442. fz_clear_pixmap(ctx, group_alpha);
  2443. }
  2444. state[1].blendmode |= FZ_BLEND_ISOLATED;
  2445. state[1].xstep = xstep;
  2446. state[1].ystep = ystep;
  2447. state[1].id = id;
  2448. state[1].encache = 1;
  2449. state[1].area = fz_irect_from_rect(area);
  2450. state[1].ctm = ctm;
  2451. state[1].scissor = bbox;
  2452. #ifdef DUMP_GROUP_BLENDS
  2453. dump_spaces(dev->top-1, "Tile begin\n");
  2454. #endif
  2455. return 0;
  2456. }
  2457. static void
  2458. fz_draw_end_tile(fz_context *ctx, fz_device *devp)
  2459. {
  2460. fz_draw_device *dev = (fz_draw_device*)devp;
  2461. float xstep, ystep;
  2462. fz_matrix ttm, ctm, shapectm, gactm;
  2463. fz_irect area, scissor, tile_bbox;
  2464. fz_rect scissor_tmp, tile_tmp;
  2465. int x0, y0, x1, y1, x, y, extra_x, extra_y;
  2466. fz_draw_state *state;
  2467. fz_pixmap *dest = NULL;
  2468. fz_pixmap *shape = NULL;
  2469. fz_pixmap *group_alpha = NULL;
  2470. if (dev->top == 0)
  2471. fz_throw(ctx, FZ_ERROR_ARGUMENT, "unexpected end tile");
  2472. state = pop_stack(ctx, dev, "tile");
  2473. dev->flags = state[1].flags;
  2474. xstep = state[1].xstep;
  2475. ystep = state[1].ystep;
  2476. area = state[1].area;
  2477. ctm = state[1].ctm;
  2478. /* Fudge the scissor bbox a little to allow for inaccuracies in the
  2479. * matrix inversion. */
  2480. ttm = fz_invert_matrix(ctm);
  2481. scissor_tmp = fz_rect_from_irect(state[0].scissor);
  2482. scissor_tmp = fz_expand_rect(scissor_tmp, 1);
  2483. scissor_tmp = fz_transform_rect(scissor_tmp, ttm);
  2484. scissor = fz_irect_from_rect(scissor_tmp);
  2485. area = fz_intersect_irect(area, scissor);
  2486. tile_bbox.x0 = state[1].dest->x;
  2487. tile_bbox.y0 = state[1].dest->y;
  2488. tile_bbox.x1 = state[1].dest->w + tile_bbox.x0;
  2489. tile_bbox.y1 = state[1].dest->h + tile_bbox.y0;
  2490. tile_tmp = fz_rect_from_irect(tile_bbox);
  2491. tile_tmp = fz_expand_rect(tile_tmp, 1);
  2492. tile_tmp = fz_transform_rect(tile_tmp, ttm);
  2493. /* FIXME: area is a bbox, so FP not appropriate here */
  2494. /* In PDF files xstep/ystep can be smaller than view (the area of a
  2495. * single tile) (see fts_15_1506.pdf for an example). This means that
  2496. * we have to bias the left hand/bottom edge calculations by the
  2497. * difference between the step and the width/height of the tile. */
  2498. /* scissor, xstep and area are all in pattern space. */
  2499. extra_x = tile_tmp.x1 - tile_tmp.x0 - xstep;
  2500. if (extra_x < 0)
  2501. extra_x = 0;
  2502. extra_y = tile_tmp.y1 - tile_tmp.y0 - ystep;
  2503. if (extra_y < 0)
  2504. extra_y = 0;
  2505. x0 = floorf((area.x0 - tile_tmp.x0 - extra_x) / xstep);
  2506. y0 = floorf((area.y0 - tile_tmp.y0 - extra_y) / ystep);
  2507. x1 = ceilf((area.x1 - tile_tmp.x0 + extra_x) / xstep);
  2508. y1 = ceilf((area.y1 - tile_tmp.y0 + extra_y) / ystep);
  2509. ctm.e = state[1].dest->x;
  2510. ctm.f = state[1].dest->y;
  2511. if (state[1].shape)
  2512. {
  2513. shapectm = ctm;
  2514. shapectm.e = state[1].shape->x;
  2515. shapectm.f = state[1].shape->y;
  2516. }
  2517. if (state[1].group_alpha)
  2518. {
  2519. gactm = ctm;
  2520. gactm.e = state[1].group_alpha->x;
  2521. gactm.f = state[1].group_alpha->y;
  2522. }
  2523. #ifdef DUMP_GROUP_BLENDS
  2524. dump_spaces(dev->top, "");
  2525. fz_dump_blend(ctx, "Tiling ", state[1].dest);
  2526. if (state[1].shape)
  2527. fz_dump_blend(ctx, "/S=", state[1].shape);
  2528. if (state[1].group_alpha)
  2529. fz_dump_blend(ctx, "/GA=", state[1].group_alpha);
  2530. fz_dump_blend(ctx, " onto ", state[0].dest);
  2531. if (state[0].shape)
  2532. fz_dump_blend(ctx, "/S=", state[0].shape);
  2533. if (state[0].group_alpha)
  2534. fz_dump_blend(ctx, "/GA=", state[0].group_alpha);
  2535. #endif
  2536. fz_var(dest);
  2537. fz_var(shape);
  2538. fz_var(group_alpha);
  2539. fz_try(ctx)
  2540. {
  2541. dest = fz_new_pixmap_from_pixmap(ctx, state[1].dest, NULL);
  2542. shape = fz_new_pixmap_from_pixmap(ctx, state[1].shape, NULL);
  2543. group_alpha = fz_new_pixmap_from_pixmap(ctx, state[1].group_alpha, NULL);
  2544. for (y = y0; y < y1; y++)
  2545. {
  2546. for (x = x0; x < x1; x++)
  2547. {
  2548. ttm = fz_pre_translate(ctm, x * xstep, y * ystep);
  2549. dest->x = ttm.e;
  2550. dest->y = ttm.f;
  2551. /* Check for overflow due to float -> int conversions */
  2552. if (dest->x > 0 && dest->x + dest->w < 0)
  2553. continue;
  2554. if (dest->y > 0 && dest->y + dest->h < 0)
  2555. continue;
  2556. fz_paint_pixmap_with_bbox(state[0].dest, dest, 255, state[0].scissor);
  2557. if (shape)
  2558. {
  2559. ttm = fz_pre_translate(shapectm, x * xstep, y * ystep);
  2560. shape->x = ttm.e;
  2561. shape->y = ttm.f;
  2562. fz_paint_pixmap_with_bbox(state[0].shape, shape, 255, state[0].scissor);
  2563. }
  2564. if (group_alpha)
  2565. {
  2566. ttm = fz_pre_translate(gactm, x * xstep, y * ystep);
  2567. group_alpha->x = ttm.e;
  2568. group_alpha->y = ttm.f;
  2569. fz_paint_pixmap_with_bbox(state[0].group_alpha, group_alpha, 255, state[0].scissor);
  2570. }
  2571. }
  2572. }
  2573. /* Now we try to cache the tiles. Any failure here will just result in us not caching. */
  2574. if (state[1].encache && state[1].id != 0)
  2575. {
  2576. tile_record *tile = NULL;
  2577. tile_key *key = NULL;
  2578. fz_var(tile);
  2579. fz_var(key);
  2580. fz_try(ctx)
  2581. {
  2582. tile_record *existing_tile;
  2583. tile = fz_new_tile_record(ctx, state[1].dest, state[1].shape, state[1].group_alpha);
  2584. key = fz_malloc_struct(ctx, tile_key);
  2585. key->refs = 1;
  2586. key->id = state[1].id;
  2587. key->ctm[0] = ctm.a;
  2588. key->ctm[1] = ctm.b;
  2589. key->ctm[2] = ctm.c;
  2590. key->ctm[3] = ctm.d;
  2591. key->cs = fz_keep_colorspace_store_key(ctx, state[1].dest->colorspace);
  2592. key->has_shape = (state[1].shape != NULL);
  2593. key->has_group_alpha = (state[1].group_alpha != NULL);
  2594. existing_tile = fz_store_item(ctx, key, tile, fz_tile_size(ctx, tile), &fz_tile_store_type);
  2595. if (existing_tile)
  2596. {
  2597. /* We already have a tile. This will either have been
  2598. * produced by a racing thread, or there is already
  2599. * an entry for this one in the store. */
  2600. fz_drop_tile_record(ctx, tile);
  2601. tile = existing_tile;
  2602. }
  2603. }
  2604. fz_always(ctx)
  2605. {
  2606. fz_drop_tile_key(ctx, key);
  2607. fz_drop_tile_record(ctx, tile);
  2608. }
  2609. fz_catch(ctx)
  2610. {
  2611. /* Do nothing */
  2612. }
  2613. }
  2614. }
  2615. fz_always(ctx)
  2616. {
  2617. cleanup_post_pop(ctx, state);
  2618. fz_drop_pixmap(ctx, dest);
  2619. fz_drop_pixmap(ctx, shape);
  2620. fz_drop_pixmap(ctx, group_alpha);
  2621. }
  2622. fz_catch(ctx)
  2623. fz_rethrow(ctx);
  2624. #ifdef DUMP_GROUP_BLENDS
  2625. fz_dump_blend(ctx, " to get ", state[0].dest);
  2626. if (state[0].shape)
  2627. fz_dump_blend(ctx, "/S=", state[0].shape);
  2628. if (state[0].group_alpha)
  2629. fz_dump_blend(ctx, "/GA=", state[0].group_alpha);
  2630. printf("\n");
  2631. #endif
  2632. if (state->blendmode & FZ_BLEND_KNOCKOUT)
  2633. fz_knockout_end(ctx, dev);
  2634. }
  2635. static void
  2636. fz_draw_render_flags(fz_context *ctx, fz_device *devp, int set, int clear)
  2637. {
  2638. fz_draw_device *dev = (fz_draw_device*)devp;
  2639. dev->flags = (dev->flags | set ) & ~clear;
  2640. }
  2641. static void
  2642. fz_draw_set_default_colorspaces(fz_context *ctx, fz_device *devp, fz_default_colorspaces *default_cs)
  2643. {
  2644. fz_draw_device *dev = (fz_draw_device*)devp;
  2645. fz_drop_default_colorspaces(ctx, dev->default_cs);
  2646. dev->default_cs = fz_keep_default_colorspaces(ctx, default_cs);
  2647. }
  2648. static void
  2649. fz_draw_close_device(fz_context *ctx, fz_device *devp)
  2650. {
  2651. fz_draw_device *dev = (fz_draw_device*)devp;
  2652. /* pop and free the stacks */
  2653. if (dev->top > dev->resolve_spots)
  2654. fz_throw(ctx, FZ_ERROR_ARGUMENT, "items left on stack in draw device: %d", dev->top);
  2655. if (dev->resolve_spots && dev->top)
  2656. {
  2657. fz_draw_state *state = &dev->stack[--dev->top];
  2658. fz_try(ctx)
  2659. {
  2660. fz_copy_pixmap_area_converting_seps(ctx, state[1].dest, state[0].dest, dev->proof_cs, fz_default_color_params, dev->default_cs);
  2661. assert(state[1].mask == NULL);
  2662. assert(state[1].shape == NULL);
  2663. assert(state[1].group_alpha == NULL);
  2664. }
  2665. fz_always(ctx)
  2666. {
  2667. fz_drop_pixmap(ctx, state[1].dest);
  2668. state[1].dest = NULL;
  2669. }
  2670. fz_catch(ctx)
  2671. fz_rethrow(ctx);
  2672. }
  2673. }
  2674. static void
  2675. fz_draw_drop_device(fz_context *ctx, fz_device *devp)
  2676. {
  2677. fz_draw_device *dev = (fz_draw_device*)devp;
  2678. fz_rasterizer *rast = dev->rast;
  2679. fz_drop_default_colorspaces(ctx, dev->default_cs);
  2680. fz_drop_colorspace(ctx, dev->proof_cs);
  2681. /* pop and free the stacks */
  2682. for (; dev->top > 0; dev->top--)
  2683. {
  2684. fz_draw_state *state = &dev->stack[dev->top - 1];
  2685. if (state[1].mask != state[0].mask)
  2686. fz_drop_pixmap(ctx, state[1].mask);
  2687. if (state[1].dest != state[0].dest)
  2688. fz_drop_pixmap(ctx, state[1].dest);
  2689. if (state[1].shape != state[0].shape)
  2690. fz_drop_pixmap(ctx, state[1].shape);
  2691. if (state[1].group_alpha != state[0].group_alpha)
  2692. fz_drop_pixmap(ctx, state[1].group_alpha);
  2693. }
  2694. /* We never free the dest/mask/shape at level 0, as:
  2695. * 1) dest is passed in and ownership remains with the caller.
  2696. * 2) shape and mask are NULL at level 0.
  2697. */
  2698. if (dev->stack != &dev->init_stack[0])
  2699. fz_free(ctx, dev->stack);
  2700. fz_drop_scale_cache(ctx, dev->cache_x);
  2701. fz_drop_scale_cache(ctx, dev->cache_y);
  2702. fz_drop_rasterizer(ctx, rast);
  2703. fz_drop_shade_color_cache(ctx, dev->shade_cache);
  2704. }
  2705. static fz_device *
  2706. new_draw_device(fz_context *ctx, fz_matrix transform, fz_pixmap *dest, const fz_aa_context *aa, const fz_irect *clip, fz_colorspace *proof_cs)
  2707. {
  2708. fz_draw_device *dev = fz_new_derived_device(ctx, fz_draw_device);
  2709. dev->super.drop_device = fz_draw_drop_device;
  2710. dev->super.close_device = fz_draw_close_device;
  2711. dev->super.fill_path = fz_draw_fill_path;
  2712. dev->super.stroke_path = fz_draw_stroke_path;
  2713. dev->super.clip_path = fz_draw_clip_path;
  2714. dev->super.clip_stroke_path = fz_draw_clip_stroke_path;
  2715. dev->super.fill_text = fz_draw_fill_text;
  2716. dev->super.stroke_text = fz_draw_stroke_text;
  2717. dev->super.clip_text = fz_draw_clip_text;
  2718. dev->super.clip_stroke_text = fz_draw_clip_stroke_text;
  2719. dev->super.ignore_text = fz_draw_ignore_text;
  2720. dev->super.fill_image_mask = fz_draw_fill_image_mask;
  2721. dev->super.clip_image_mask = fz_draw_clip_image_mask;
  2722. dev->super.fill_image = fz_draw_fill_image;
  2723. dev->super.fill_shade = fz_draw_fill_shade;
  2724. dev->super.pop_clip = fz_draw_pop_clip;
  2725. dev->super.begin_mask = fz_draw_begin_mask;
  2726. dev->super.end_mask = fz_draw_end_mask;
  2727. dev->super.begin_group = fz_draw_begin_group;
  2728. dev->super.end_group = fz_draw_end_group;
  2729. dev->super.begin_tile = fz_draw_begin_tile;
  2730. dev->super.end_tile = fz_draw_end_tile;
  2731. dev->super.render_flags = fz_draw_render_flags;
  2732. dev->super.set_default_colorspaces = fz_draw_set_default_colorspaces;
  2733. dev->proof_cs = fz_keep_colorspace(ctx, proof_cs);
  2734. dev->transform = transform;
  2735. dev->flags = 0;
  2736. dev->resolve_spots = 0;
  2737. dev->top = 0;
  2738. dev->stack = &dev->init_stack[0];
  2739. dev->stack_cap = STACK_SIZE;
  2740. dev->stack[0].dest = dest;
  2741. dev->stack[0].shape = NULL;
  2742. dev->stack[0].group_alpha = NULL;
  2743. dev->stack[0].mask = NULL;
  2744. dev->stack[0].blendmode = 0;
  2745. dev->stack[0].scissor.x0 = dest->x;
  2746. dev->stack[0].scissor.y0 = dest->y;
  2747. dev->stack[0].scissor.x1 = dest->x + dest->w;
  2748. dev->stack[0].scissor.y1 = dest->y + dest->h;
  2749. dev->stack[0].flags = dev->flags;
  2750. if (clip)
  2751. {
  2752. if (clip->x0 > dev->stack[0].scissor.x0)
  2753. dev->stack[0].scissor.x0 = clip->x0;
  2754. if (clip->x1 < dev->stack[0].scissor.x1)
  2755. dev->stack[0].scissor.x1 = clip->x1;
  2756. if (clip->y0 > dev->stack[0].scissor.y0)
  2757. dev->stack[0].scissor.y0 = clip->y0;
  2758. if (clip->y1 < dev->stack[0].scissor.y1)
  2759. dev->stack[0].scissor.y1 = clip->y1;
  2760. }
  2761. /* If we have no separations structure at all, then we want a
  2762. * simple composite rendering (with no overprint simulation).
  2763. * If we do have a separations structure, so: 1) Any
  2764. * 'disabled' separations are ignored. 2) Any 'composite'
  2765. * separations means we will need to do an overprint
  2766. * simulation.
  2767. *
  2768. * The supplied pixmaps 's' will match the number of
  2769. * 'spots' separations. If we have any 'composite'
  2770. * separations therefore, we'll need to make a new pixmap
  2771. * with a new (completely 'spots') separations structure,
  2772. * render to that, and then map down at the end.
  2773. *
  2774. * Unfortunately we can't produce this until we know what
  2775. * the default_colorspaces etc are, so set a flag for us
  2776. * to trigger on later.
  2777. */
  2778. if (dest->seps || dev->proof_cs != NULL)
  2779. #if FZ_ENABLE_SPOT_RENDERING
  2780. dev->resolve_spots = 1;
  2781. #else
  2782. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Spot rendering (and overprint/overprint simulation) not available in this build");
  2783. #endif
  2784. dev->overprint_possible = (dest->seps != NULL);
  2785. fz_try(ctx)
  2786. {
  2787. dev->rast = fz_new_rasterizer(ctx, aa);
  2788. dev->cache_x = fz_new_scale_cache(ctx);
  2789. dev->cache_y = fz_new_scale_cache(ctx);
  2790. }
  2791. fz_catch(ctx)
  2792. {
  2793. fz_drop_device(ctx, (fz_device*)dev);
  2794. fz_rethrow(ctx);
  2795. }
  2796. return (fz_device*)dev;
  2797. }
  2798. fz_device *
  2799. fz_new_draw_device(fz_context *ctx, fz_matrix transform, fz_pixmap *dest)
  2800. {
  2801. return new_draw_device(ctx, transform, dest, NULL, NULL, NULL);
  2802. }
  2803. fz_device *
  2804. fz_new_draw_device_with_bbox(fz_context *ctx, fz_matrix transform, fz_pixmap *dest, const fz_irect *clip)
  2805. {
  2806. return new_draw_device(ctx, transform, dest, NULL, clip, NULL);
  2807. }
  2808. fz_device *
  2809. fz_new_draw_device_with_proof(fz_context *ctx, fz_matrix transform, fz_pixmap *dest, fz_colorspace *cs)
  2810. {
  2811. return new_draw_device(ctx, transform, dest, NULL, NULL, cs);
  2812. }
  2813. fz_device *
  2814. fz_new_draw_device_with_bbox_proof(fz_context *ctx, fz_matrix transform, fz_pixmap *dest, const fz_irect *clip, fz_colorspace *cs)
  2815. {
  2816. return new_draw_device(ctx, transform, dest, NULL, clip, cs);
  2817. }
  2818. fz_device *
  2819. fz_new_draw_device_type3(fz_context *ctx, fz_matrix transform, fz_pixmap *dest)
  2820. {
  2821. fz_draw_device *dev = (fz_draw_device*)fz_new_draw_device(ctx, transform, dest);
  2822. dev->flags |= FZ_DRAWDEV_FLAGS_TYPE3;
  2823. return (fz_device*)dev;
  2824. }
  2825. fz_irect *
  2826. fz_bound_path_accurate(fz_context *ctx, fz_irect *bbox, fz_irect scissor, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth)
  2827. {
  2828. fz_rasterizer *rast = fz_new_rasterizer(ctx, NULL);
  2829. fz_try(ctx)
  2830. {
  2831. if (stroke)
  2832. (void)fz_flatten_stroke_path(ctx, rast, path, stroke, ctm, flatness, linewidth, scissor, bbox);
  2833. else
  2834. (void)fz_flatten_fill_path(ctx, rast, path, ctm, flatness, scissor, bbox);
  2835. }
  2836. fz_always(ctx)
  2837. fz_drop_rasterizer(ctx, rast);
  2838. fz_catch(ctx)
  2839. fz_rethrow(ctx);
  2840. return bbox;
  2841. }
  2842. const char *fz_draw_options_usage =
  2843. "Raster output options:\n"
  2844. "\trotate=N: rotate rendered pages N degrees counterclockwise\n"
  2845. "\tresolution=N: set both X and Y resolution in pixels per inch\n"
  2846. "\tx-resolution=N: X resolution of rendered pages in pixels per inch\n"
  2847. "\ty-resolution=N: Y resolution of rendered pages in pixels per inch\n"
  2848. "\twidth=N: render pages to fit N pixels wide (ignore resolution option)\n"
  2849. "\theight=N: render pages to fit N pixels tall (ignore resolution option)\n"
  2850. "\tcolorspace=(gray|rgb|cmyk): render using specified colorspace\n"
  2851. "\talpha: render pages with alpha channel and transparent background\n"
  2852. "\tgraphics=(aaN|cop|app): set the rasterizer to use\n"
  2853. "\ttext=(aaN|cop|app): set the rasterizer to use for text\n"
  2854. "\t\taaN=antialias with N bits (0 to 8)\n"
  2855. "\t\tcop=center of pixel\n"
  2856. "\t\tapp=any part of pixel\n"
  2857. "\n";
  2858. static int parse_aa_opts(const char *val)
  2859. {
  2860. if (fz_option_eq(val, "cop"))
  2861. return 9;
  2862. if (fz_option_eq(val, "app"))
  2863. return 10;
  2864. if (val[0] == 'a' && val[1] == 'a' && val[2] >= '0' && val[2] <= '9')
  2865. return fz_clampi(fz_atoi(&val[2]), 0, 8);
  2866. return 8;
  2867. }
  2868. fz_draw_options *
  2869. fz_parse_draw_options(fz_context *ctx, fz_draw_options *opts, const char *args)
  2870. {
  2871. const char *val;
  2872. memset(opts, 0, sizeof *opts);
  2873. opts->x_resolution = 96;
  2874. opts->y_resolution = 96;
  2875. opts->rotate = 0;
  2876. opts->width = 0;
  2877. opts->height = 0;
  2878. opts->colorspace = fz_device_rgb(ctx);
  2879. opts->alpha = 0;
  2880. opts->graphics = fz_aa_level(ctx);
  2881. opts->text = fz_text_aa_level(ctx);
  2882. if (fz_has_option(ctx, args, "rotate", &val))
  2883. opts->rotate = fz_atoi(val);
  2884. if (fz_has_option(ctx, args, "resolution", &val))
  2885. opts->x_resolution = opts->y_resolution = fz_atoi(val);
  2886. if (fz_has_option(ctx, args, "x-resolution", &val))
  2887. opts->x_resolution = fz_atoi(val);
  2888. if (fz_has_option(ctx, args, "y-resolution", &val))
  2889. opts->y_resolution = fz_atoi(val);
  2890. if (fz_has_option(ctx, args, "width", &val))
  2891. opts->width = fz_atoi(val);
  2892. if (fz_has_option(ctx, args, "height", &val))
  2893. opts->height = fz_atoi(val);
  2894. if (fz_has_option(ctx, args, "colorspace", &val))
  2895. {
  2896. if (fz_option_eq(val, "gray") || fz_option_eq(val, "grey") || fz_option_eq(val, "mono"))
  2897. opts->colorspace = fz_device_gray(ctx);
  2898. else if (fz_option_eq(val, "rgb"))
  2899. opts->colorspace = fz_device_rgb(ctx);
  2900. else if (fz_option_eq(val, "cmyk"))
  2901. opts->colorspace = fz_device_cmyk(ctx);
  2902. else
  2903. fz_throw(ctx, FZ_ERROR_ARGUMENT, "unknown colorspace in options");
  2904. }
  2905. if (fz_has_option(ctx, args, "alpha", &val))
  2906. opts->alpha = fz_option_eq(val, "yes");
  2907. if (fz_has_option(ctx, args, "graphics", &val))
  2908. opts->text = opts->graphics = parse_aa_opts(val);
  2909. if (fz_has_option(ctx, args, "text", &val))
  2910. opts->text = parse_aa_opts(val);
  2911. /* Sanity check values */
  2912. if (opts->x_resolution <= 0) opts->x_resolution = 96;
  2913. if (opts->y_resolution <= 0) opts->y_resolution = 96;
  2914. if (opts->width < 0) opts->width = 0;
  2915. if (opts->height < 0) opts->height = 0;
  2916. return opts;
  2917. }
  2918. fz_device *
  2919. fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *opts, fz_rect mediabox, fz_pixmap **pixmap)
  2920. {
  2921. fz_aa_context aa = ctx->aa;
  2922. float x_zoom = opts->x_resolution / 72.0f;
  2923. float y_zoom = opts->y_resolution / 72.0f;
  2924. float page_w = mediabox.x1 - mediabox.x0;
  2925. float page_h = mediabox.y1 - mediabox.y0;
  2926. float w = opts->width;
  2927. float h = opts->height;
  2928. float x_scale, y_scale;
  2929. fz_matrix transform;
  2930. fz_irect bbox;
  2931. fz_device *dev;
  2932. fz_set_rasterizer_graphics_aa_level(ctx, &aa, opts->graphics);
  2933. fz_set_rasterizer_text_aa_level(ctx, &aa, opts->text);
  2934. if (w > 0)
  2935. {
  2936. x_scale = w / page_w;
  2937. if (h > 0)
  2938. y_scale = h / page_h;
  2939. else
  2940. y_scale = floorf(page_h * x_scale + 0.5f) / page_h;
  2941. }
  2942. else if (h > 0)
  2943. {
  2944. y_scale = h / page_h;
  2945. x_scale = floorf(page_w * y_scale + 0.5f) / page_w;
  2946. }
  2947. else
  2948. {
  2949. x_scale = floorf(page_w * x_zoom + 0.5f) / page_w;
  2950. y_scale = floorf(page_h * y_zoom + 0.5f) / page_h;
  2951. }
  2952. transform = fz_pre_rotate(fz_scale(x_scale, y_scale), opts->rotate);
  2953. bbox = fz_irect_from_rect(fz_transform_rect(mediabox, transform));
  2954. *pixmap = fz_new_pixmap_with_bbox(ctx, opts->colorspace, bbox, NULL, opts->alpha);
  2955. fz_try(ctx)
  2956. {
  2957. fz_set_pixmap_resolution(ctx, *pixmap, opts->x_resolution, opts->y_resolution);
  2958. if (opts->alpha)
  2959. fz_clear_pixmap(ctx, *pixmap);
  2960. else
  2961. fz_clear_pixmap_with_value(ctx, *pixmap, 255);
  2962. dev = new_draw_device(ctx, transform, *pixmap, &aa, NULL, NULL);
  2963. }
  2964. fz_catch(ctx)
  2965. {
  2966. fz_drop_pixmap(ctx, *pixmap);
  2967. *pixmap = NULL;
  2968. fz_rethrow(ctx);
  2969. }
  2970. return dev;
  2971. }