gstrans.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /* Copyright (C) 2000 Aladdin Enterprises. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: gstrans.c,v 1.25 2005/08/30 16:49:34 igor Exp $ */
  14. /* Implementation of transparency, other than rendering */
  15. #include "math_.h"
  16. #include "memory_.h"
  17. #include "gx.h"
  18. #include "gserrors.h"
  19. #include "gstrans.h"
  20. #include "gsutil.h"
  21. #include "gzstate.h"
  22. #include "gxdevcli.h"
  23. #include "gdevp14.h"
  24. #define PUSH_TS 0
  25. /* ------ Transparency-related graphics state elements ------ */
  26. int
  27. gs_setblendmode(gs_state *pgs, gs_blend_mode_t mode)
  28. {
  29. #ifdef DEBUG
  30. if (gs_debug_c('v')) {
  31. static const char *const bm_names[] = { GS_BLEND_MODE_NAMES };
  32. dlprintf1("[v](0x%lx)blend_mode = ", (ulong)pgs);
  33. if (mode >= 0 && mode < countof(bm_names))
  34. dprintf1("%s\n", bm_names[mode]);
  35. else
  36. dprintf1("%d??\n", (int)mode);
  37. }
  38. #endif
  39. if (mode < 0 || mode > MAX_BLEND_MODE)
  40. return_error(gs_error_rangecheck);
  41. pgs->blend_mode = mode;
  42. return 0;
  43. }
  44. gs_blend_mode_t
  45. gs_currentblendmode(const gs_state *pgs)
  46. {
  47. return pgs->blend_mode;
  48. }
  49. int
  50. gs_setopacityalpha(gs_state *pgs, floatp alpha)
  51. {
  52. if_debug2('v', "[v](0x%lx)opacity.alpha = %g\n", (ulong)pgs, alpha);
  53. pgs->opacity.alpha = (alpha < 0.0 ? 0.0 : alpha > 1.0 ? 1.0 : alpha);
  54. return 0;
  55. }
  56. float
  57. gs_currentopacityalpha(const gs_state *pgs)
  58. {
  59. return pgs->opacity.alpha;
  60. }
  61. int
  62. gs_setshapealpha(gs_state *pgs, floatp alpha)
  63. {
  64. if_debug2('v', "[v](0x%lx)shape.alpha = %g\n", (ulong)pgs, alpha);
  65. pgs->shape.alpha = (alpha < 0.0 ? 0.0 : alpha > 1.0 ? 1.0 : alpha);
  66. return 0;
  67. }
  68. float
  69. gs_currentshapealpha(const gs_state *pgs)
  70. {
  71. return pgs->shape.alpha;
  72. }
  73. int
  74. gs_settextknockout(gs_state *pgs, bool knockout)
  75. {
  76. if_debug2('v', "[v](0x%lx)text_knockout = %s\n", (ulong)pgs,
  77. (knockout ? "true" : "false"));
  78. pgs->text_knockout = knockout;
  79. return 0;
  80. }
  81. bool
  82. gs_currenttextknockout(const gs_state *pgs)
  83. {
  84. return pgs->text_knockout;
  85. }
  86. /* ------ Transparency rendering stack ------ */
  87. gs_transparency_state_type_t
  88. gs_current_transparency_type(const gs_state *pgs)
  89. {
  90. return (pgs->transparency_stack == 0 ? 0 :
  91. pgs->transparency_stack->type);
  92. }
  93. /* Support for dummy implementation */
  94. gs_private_st_ptrs1(st_transparency_state, gs_transparency_state_t,
  95. "gs_transparency_state_t", transparency_state_enum_ptrs,
  96. transparency_state_reloc_ptrs, saved);
  97. #if PUSH_TS
  98. private int
  99. push_transparency_stack(gs_state *pgs, gs_transparency_state_type_t type,
  100. client_name_t cname)
  101. {
  102. gs_transparency_state_t *pts =
  103. gs_alloc_struct(pgs->memory, gs_transparency_state_t,
  104. &st_transparency_state, cname);
  105. if (pts == 0)
  106. return_error(gs_error_VMerror);
  107. pts->saved = pgs->transparency_stack;
  108. pts->type = type;
  109. pgs->transparency_stack = pts;
  110. return 0;
  111. }
  112. #endif
  113. private void
  114. pop_transparency_stack(gs_state *pgs, client_name_t cname)
  115. {
  116. gs_transparency_state_t *pts = pgs->transparency_stack; /* known non-0 */
  117. gs_transparency_state_t *saved = pts->saved;
  118. gs_free_object(pgs->memory, pts, cname);
  119. pgs->transparency_stack = saved;
  120. }
  121. /*
  122. * Push a PDF 1.4 transparency compositor onto the current device. Note that
  123. * if the current device already is a PDF 1.4 transparency compositor, the
  124. * create_compositor will update its parameters but not create a new
  125. * compositor device.
  126. */
  127. private int
  128. gs_state_update_pdf14trans(gs_state * pgs, gs_pdf14trans_params_t * pparams)
  129. {
  130. gs_imager_state * pis = (gs_imager_state *)pgs;
  131. gx_device * dev = pgs->device;
  132. gx_device * pdf14dev;
  133. int code;
  134. /*
  135. * Send the PDF 1.4 create compositor action specified by the parameters.
  136. */
  137. code = send_pdf14trans(pis, dev, &pdf14dev, pparams, pgs->memory);
  138. /*
  139. * If we created a new PDF 1.4 compositor device then we need to install it
  140. * into the graphics state.
  141. */
  142. if (code >= 0 && pdf14dev != dev)
  143. gx_set_device_only(pgs, pdf14dev);
  144. return code;
  145. }
  146. void
  147. gs_trans_group_params_init(gs_transparency_group_params_t *ptgp)
  148. {
  149. ptgp->ColorSpace = 0; /* bogus, but can't do better */
  150. ptgp->Isolated = false;
  151. ptgp->Knockout = false;
  152. }
  153. int
  154. gs_begin_transparency_group(gs_state *pgs,
  155. const gs_transparency_group_params_t *ptgp,
  156. const gs_rect *pbbox)
  157. {
  158. gs_pdf14trans_params_t params = { 0 };
  159. #ifdef DEBUG
  160. if (gs_debug_c('v')) {
  161. static const char *const cs_names[] = {
  162. GS_COLOR_SPACE_TYPE_NAMES
  163. };
  164. dlprintf5("[v](0x%lx)begin_transparency_group [%g %g %g %g]\n",
  165. (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y);
  166. if (ptgp->ColorSpace)
  167. dprintf1(" CS = %s",
  168. cs_names[(int)gs_color_space_get_index(ptgp->ColorSpace)]);
  169. else
  170. dputs(" (no CS)");
  171. dprintf2(" Isolated = %d Knockout = %d\n",
  172. ptgp->Isolated, ptgp->Knockout);
  173. }
  174. #endif
  175. /*
  176. * Put parameters into a compositor parameter and then call the
  177. * create_compositor. This will pass the data to the PDF 1.4
  178. * transparency device.
  179. */
  180. params.pdf14_op = PDF14_BEGIN_TRANS_GROUP;
  181. params.Isolated = ptgp->Isolated;
  182. params.Knockout = ptgp->Knockout;
  183. params.opacity = pgs->opacity;
  184. params.shape = pgs->shape;
  185. params.blend_mode = pgs->blend_mode;
  186. /*
  187. * We are currently doing nothing with the colorspace. Currently
  188. * the blending colorspace is based upon the processs color model
  189. * of the output device.
  190. */
  191. params.bbox = *pbbox;
  192. return gs_state_update_pdf14trans(pgs, &params);
  193. }
  194. int
  195. gx_begin_transparency_group(gs_imager_state * pis, gx_device * pdev,
  196. const gs_pdf14trans_params_t * pparams)
  197. {
  198. gs_transparency_group_params_t tgp = {0};
  199. gs_rect bbox;
  200. if (pparams->Background_components != 0 &&
  201. pparams->Background_components != pdev->color_info.num_components)
  202. return_error(gs_error_rangecheck);
  203. tgp.Isolated = pparams->Isolated;
  204. tgp.Knockout = pparams->Knockout;
  205. pis->opacity.alpha = pparams->opacity.alpha;
  206. pis->shape.alpha = pparams->shape.alpha;
  207. pis->blend_mode = pparams->blend_mode;
  208. bbox = pparams->bbox;
  209. #ifdef DEBUG
  210. if (gs_debug_c('v')) {
  211. static const char *const cs_names[] = {
  212. GS_COLOR_SPACE_TYPE_NAMES
  213. };
  214. dlprintf5("[v](0x%lx)begin_transparency_group [%g %g %g %g]\n",
  215. (ulong)pis, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
  216. if (tgp.ColorSpace)
  217. dprintf1(" CS = %s",
  218. cs_names[(int)gs_color_space_get_index(tgp.ColorSpace)]);
  219. else
  220. dputs(" (no CS)");
  221. dprintf2(" Isolated = %d Knockout = %d\n",
  222. tgp.Isolated, tgp.Knockout);
  223. }
  224. #endif
  225. if (dev_proc(pdev, begin_transparency_group) != 0)
  226. return (*dev_proc(pdev, begin_transparency_group)) (pdev, &tgp,
  227. &bbox, pis, NULL, NULL);
  228. else
  229. return 0;
  230. }
  231. int
  232. gs_end_transparency_group(gs_state *pgs)
  233. {
  234. gs_pdf14trans_params_t params = { 0 };
  235. params.pdf14_op = PDF14_END_TRANS_GROUP; /* Other parameters not used */
  236. return gs_state_update_pdf14trans(pgs, &params);
  237. }
  238. int
  239. gx_end_transparency_group(gs_imager_state * pis, gx_device * pdev)
  240. {
  241. if (dev_proc(pdev, end_transparency_group) != 0)
  242. return (*dev_proc(pdev, end_transparency_group)) (pdev, pis, NULL);
  243. else
  244. return 0;
  245. }
  246. /*
  247. * Handler for identity mask transfer functions.
  248. */
  249. private int
  250. mask_transfer_identity(floatp in, float *out, void *proc_data)
  251. {
  252. *out = (float) in;
  253. return 0;
  254. }
  255. void
  256. gs_trans_mask_params_init(gs_transparency_mask_params_t *ptmp,
  257. gs_transparency_mask_subtype_t subtype)
  258. {
  259. ptmp->subtype = subtype;
  260. ptmp->Background_components = 0;
  261. ptmp->TransferFunction = mask_transfer_identity;
  262. ptmp->TransferFunction_data = 0;
  263. }
  264. int
  265. gs_begin_transparency_mask(gs_state * pgs,
  266. const gs_transparency_mask_params_t * ptmp,
  267. const gs_rect * pbbox, bool mask_is_image)
  268. {
  269. gs_pdf14trans_params_t params = { 0 };
  270. const int l = sizeof(params.Background[0]) * ptmp->Background_components;
  271. int i;
  272. if_debug8('v', "[v](0x%lx)begin_transparency_mask [%g %g %g %g]\n\
  273. subtype = %d Background_components = %d %s\n",
  274. (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y,
  275. (int)ptmp->subtype, ptmp->Background_components,
  276. (ptmp->TransferFunction == mask_transfer_identity ? "no TR" :
  277. "has TR"));
  278. params.pdf14_op = PDF14_BEGIN_TRANS_MASK;
  279. params.bbox = *pbbox;
  280. params.subtype = ptmp->subtype;
  281. params.Background_components = ptmp->Background_components;
  282. memcpy(params.Background, ptmp->Background, l);
  283. params.GrayBackground = ptmp->GrayBackground;
  284. params.transfer_function = ptmp->TransferFunction_data;
  285. params.function_is_identity =
  286. (ptmp->TransferFunction == mask_transfer_identity);
  287. params.mask_is_image = mask_is_image;
  288. /* Sample the transfer function */
  289. for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
  290. float in = (float)(i * (1.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)));
  291. float out;
  292. ptmp->TransferFunction(in, &out, ptmp->TransferFunction_data);
  293. params.transfer_fn[i] = (byte)floor((double)(out * 255 + 0.5));
  294. }
  295. return gs_state_update_pdf14trans(pgs, &params);
  296. }
  297. int
  298. gx_begin_transparency_mask(gs_imager_state * pis, gx_device * pdev,
  299. const gs_pdf14trans_params_t * pparams)
  300. {
  301. gx_transparency_mask_params_t tmp;
  302. const int l = sizeof(pparams->Background[0]) * pparams->Background_components;
  303. tmp.subtype = pparams->subtype;
  304. tmp.Background_components = pparams->Background_components;
  305. memcpy(tmp.Background, pparams->Background, l);
  306. tmp.GrayBackground = pparams->GrayBackground;
  307. tmp.function_is_identity = pparams->function_is_identity;
  308. memcpy(tmp.transfer_fn, pparams->transfer_fn, size_of(tmp.transfer_fn));
  309. if_debug8('v', "[v](0x%lx)begin_transparency_mask [%g %g %g %g]\n\
  310. subtype = %d Background_components = %d %s\n",
  311. (ulong)pis, pparams->bbox.p.x, pparams->bbox.p.y,
  312. pparams->bbox.q.x, pparams->bbox.q.y,
  313. (int)tmp.subtype, tmp.Background_components,
  314. (tmp.function_is_identity ? "no TR" :
  315. "has TR"));
  316. if (dev_proc(pdev, begin_transparency_mask) != 0)
  317. return (*dev_proc(pdev, begin_transparency_mask))
  318. (pdev, &tmp, &(pparams->bbox), pis, NULL, NULL);
  319. else
  320. return 0;
  321. }
  322. int
  323. gs_end_transparency_mask(gs_state *pgs,
  324. gs_transparency_channel_selector_t csel)
  325. {
  326. gs_pdf14trans_params_t params = { 0 };
  327. if_debug2('v', "[v](0x%lx)end_transparency_mask(%d)\n", (ulong)pgs,
  328. (int)csel);
  329. params.pdf14_op = PDF14_END_TRANS_MASK; /* Other parameters not used */
  330. params.csel = csel;
  331. return gs_state_update_pdf14trans(pgs, &params);
  332. }
  333. int
  334. gx_end_transparency_mask(gs_imager_state * pis, gx_device * pdev,
  335. const gs_pdf14trans_params_t * pparams)
  336. {
  337. if (dev_proc(pdev, end_transparency_mask) != 0)
  338. return (*dev_proc(pdev, end_transparency_mask)) (pdev, NULL);
  339. else
  340. return 0;
  341. }
  342. int
  343. gs_discard_transparency_layer(gs_state *pgs)
  344. {
  345. /****** NYI, DUMMY ******/
  346. gs_transparency_state_t *pts = pgs->transparency_stack;
  347. if_debug1('v', "[v](0x%lx)discard_transparency_layer\n", (ulong)pgs);
  348. if (!pts)
  349. return_error(gs_error_rangecheck);
  350. pop_transparency_stack(pgs, "gs_discard_transparency_layer");
  351. return 0;
  352. }
  353. int
  354. gs_init_transparency_mask(gs_state *pgs,
  355. gs_transparency_channel_selector_t csel)
  356. {
  357. gs_pdf14trans_params_t params = { 0 };
  358. if_debug2('v', "[v](0x%lx)init_transparency_mask(%d)\n", (ulong)pgs,
  359. (int)csel);
  360. params.pdf14_op = PDF14_INIT_TRANS_MASK;
  361. params.csel = csel;
  362. return gs_state_update_pdf14trans(pgs, &params);
  363. }
  364. int
  365. gx_init_transparency_mask(gs_imager_state * pis,
  366. const gs_pdf14trans_params_t * pparams)
  367. {
  368. gs_transparency_source_t *ptm;
  369. if_debug2('v', "[v](0x%lx)init_transparency_mask(%d)\n", (ulong)pis,
  370. (int)pparams->csel);
  371. switch (pparams->csel) {
  372. case TRANSPARENCY_CHANNEL_Opacity: ptm = &pis->opacity; break;
  373. case TRANSPARENCY_CHANNEL_Shape: ptm = &pis->shape; break;
  374. default: return_error(gs_error_rangecheck);
  375. }
  376. rc_decrement_only(ptm->mask, "gs_init_transparency_mask");
  377. ptm->mask = 0;
  378. return 0;
  379. }
  380. int
  381. gs_push_pdf14trans_device(gs_state * pgs)
  382. {
  383. gs_pdf14trans_params_t params = { 0 };
  384. params.pdf14_op = PDF14_PUSH_DEVICE; /* Other parameters not used */
  385. return gs_state_update_pdf14trans(pgs, &params);
  386. }
  387. int
  388. gs_pop_pdf14trans_device(gs_state * pgs)
  389. {
  390. gs_pdf14trans_params_t params = { 0 };
  391. params.pdf14_op = PDF14_POP_DEVICE; /* Other parameters not used */
  392. return gs_state_update_pdf14trans(pgs, &params);
  393. }