gdevpdft.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /* Copyright (C) 1996, 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: gdevpdft.c,v 1.52 2005/09/06 22:21:14 leonardo Exp $ */
  14. /* transparency processing for PDF-writing driver */
  15. #include "gx.h"
  16. #include "string_.h"
  17. #include "gserrors.h"
  18. #include "gstrans.h"
  19. #include "gscolor2.h"
  20. #include "gzstate.h"
  21. #include "gdevpdfx.h"
  22. #include "gdevpdfg.h"
  23. #include "gdevpdfo.h"
  24. private int
  25. pdf_make_soft_mask_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams)
  26. {
  27. pdf_resource_t *pres_soft_mask_dict = 0;
  28. cos_dict_t *soft_mask_dict;
  29. int code;
  30. /* Fixme : merge redundant objects. */
  31. code = pdf_alloc_resource(pdev, resourceSoftMaskDict, gs_no_id, &pres_soft_mask_dict, -1);
  32. if (code < 0)
  33. return code;
  34. cos_become(pres_soft_mask_dict->object, cos_type_dict);
  35. pdev->pres_soft_mask_dict = pres_soft_mask_dict;
  36. soft_mask_dict = (cos_dict_t *)pres_soft_mask_dict->object;
  37. code = cos_dict_put_c_key_string(soft_mask_dict, "/S",
  38. pparams->subtype == TRANSPARENCY_MASK_Alpha ? (byte *)"/Alpha" : (byte *)"/Luminosity",
  39. pparams->subtype == TRANSPARENCY_MASK_Alpha ? 6 : 11);
  40. if (code < 0)
  41. return code;
  42. if (pparams->Background_components) {
  43. cos_array_t *Background;
  44. Background = cos_array_from_floats(pdev, pparams->Background,
  45. pparams->Background_components, "pdf_write_soft_mask_dict");
  46. if (Background == NULL)
  47. return_error(gs_error_VMerror);
  48. code = cos_dict_put_c_key_object(soft_mask_dict, "/BC", (cos_object_t *)Background);
  49. if (code < 0)
  50. return code;
  51. }
  52. if (pparams->transfer_function != NULL) {
  53. long id;
  54. char buf[20];
  55. code = pdf_write_function(pdev, pparams->transfer_function, &id);
  56. if (code < 0)
  57. return code;
  58. sprintf(buf, " %ld 0 R", id);
  59. code = cos_dict_put_c_key_string(soft_mask_dict, "/TR", (const byte *)buf, strlen(buf));
  60. if (code < 0)
  61. return code;
  62. }
  63. return 0;
  64. }
  65. private int
  66. pdf_make_group_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams,
  67. const gs_imager_state * pis, cos_dict_t **pdict)
  68. {
  69. pdf_resource_t *pres_group;
  70. cos_dict_t *group_dict;
  71. int code;
  72. const gs_state *gstate = gx_hld_get_gstate_ptr(pis);
  73. cos_value_t cs_value;
  74. code = pdf_alloc_resource(pdev, resourceGroup, gs_no_id, &pres_group, -1);
  75. if (code < 0)
  76. return code;
  77. cos_become(pres_group->object, cos_type_dict);
  78. group_dict = (cos_dict_t *)pres_group->object;
  79. code = cos_dict_put_c_key_string(group_dict, "/Type", (const byte *)"/Group", 6);
  80. if (code < 0)
  81. return code;
  82. code = cos_dict_put_c_key_string(group_dict, "/S", (const byte *)"/Transparency", 13);
  83. if (code < 0)
  84. return code;
  85. if (pparams->Isolated) {
  86. code = cos_dict_put_c_key_bool(group_dict, "/I", true);
  87. if (code < 0)
  88. return code;
  89. }
  90. if (pparams->Knockout) {
  91. code = cos_dict_put_c_key_bool(group_dict, "/K", true);
  92. if (code < 0)
  93. return code;
  94. }
  95. if (gstate != NULL) {
  96. const gs_color_space *cs = gstate->color_space;
  97. code = pdf_color_space(pdev, &cs_value, NULL, cs,
  98. &pdf_color_space_names, false);
  99. if (code < 0)
  100. return code;
  101. code = cos_dict_put_c_key(group_dict, "/CS", &cs_value);
  102. if (code < 0)
  103. return code;
  104. }
  105. group_dict = NULL; /* The next line invalidates it. */
  106. code = pdf_substitute_resource(pdev, &pres_group, resourceGroup, NULL, false);
  107. if (code < 0)
  108. return code;
  109. *pdict = (cos_dict_t *)pres_group->object;
  110. return 0;
  111. }
  112. private int
  113. pdf_make_form_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams,
  114. const gs_imager_state * pis,
  115. const cos_dict_t *group_dict, cos_dict_t *form_dict)
  116. {
  117. cos_array_t *bbox_array;
  118. float bbox[4];
  119. gs_rect bbox_rect;
  120. int code;
  121. code = gs_bbox_transform(&pparams->bbox, &ctm_only(pis), &bbox_rect);
  122. if (code < 0)
  123. return code;
  124. bbox[0] = bbox_rect.p.x;
  125. bbox[1] = bbox_rect.p.y;
  126. bbox[2] = bbox_rect.q.x;
  127. bbox[3] = bbox_rect.q.y;
  128. code = cos_dict_put_c_key_string(form_dict, "/Type", (const byte *)"/XObject", 8);
  129. if (code < 0)
  130. return code;
  131. code = cos_dict_put_c_key_string(form_dict, "/Subtype", (const byte *)"/Form", 5);
  132. if (code < 0)
  133. return code;
  134. code = cos_dict_put_c_key_int(form_dict, "/FormType", 1);
  135. if (code < 0)
  136. return code;
  137. code = cos_dict_put_c_key_string(form_dict, "/Matrix", (const byte *)"[1 0 0 1 0 0]", 13);
  138. if (code < 0)
  139. return code;
  140. bbox_array = cos_array_from_floats(pdev, bbox, 4, "pdf_begin_transparency_group");
  141. if (bbox_array == NULL)
  142. return_error(gs_error_VMerror);
  143. code = cos_dict_put_c_key_object(form_dict, "/BBox", (cos_object_t *)bbox_array);
  144. if (code < 0)
  145. return code;
  146. return cos_dict_put_c_key_object(form_dict, "/Group", (cos_object_t *)group_dict);
  147. }
  148. private int
  149. pdf_begin_transparency_group(gs_imager_state * pis, gx_device_pdf * pdev,
  150. const gs_pdf14trans_params_t * pparams)
  151. {
  152. cos_dict_t *group_dict;
  153. bool in_page = is_in_page(pdev);
  154. const gs_state *gstate = gx_hld_get_gstate_ptr(pis);
  155. int code;
  156. if (gstate == NULL)
  157. return_error(gs_error_unregistered); /* Must not happen. */
  158. code = pdf_make_group_dict(pdev, pparams, pis, &group_dict);
  159. if (code < 0)
  160. return code;
  161. code = pdf_open_page(pdev, PDF_IN_STREAM);
  162. if (code < 0)
  163. return code;
  164. if (pdf_must_put_clip_path(pdev, gstate->clip_path)) {
  165. code = pdf_put_clip_path(pdev, gstate->clip_path);
  166. if (code < 0)
  167. return code;
  168. }
  169. if (!in_page)
  170. pdev->pages[pdev->next_page].group_id = group_dict->id;
  171. else {
  172. pdf_resource_t *pres, *pres_gstate = NULL;
  173. code = pdf_prepare_drawing(pdev, pis, &pres_gstate);
  174. if (code < 0)
  175. return code;
  176. code = pdf_end_gstate(pdev, pres_gstate);
  177. if (code < 0)
  178. return code;
  179. code = pdf_enter_substream(pdev, resourceXObject,
  180. gs_no_id, &pres, false, pdev->params.CompressPages);
  181. if (code < 0)
  182. return code;
  183. return pdf_make_form_dict(pdev, pparams, pis, group_dict, (cos_dict_t *)pres->object);
  184. }
  185. return 0;
  186. }
  187. private int
  188. pdf_end_transparency_group(gs_imager_state * pis, gx_device_pdf * pdev)
  189. {
  190. int bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
  191. if (pdev->sbstack_depth == bottom) {
  192. /* We're closing the page group. */
  193. if (pdev->pages[pdev->next_page].group_id == 0)
  194. return_error(gs_error_unregistered); /* Must not happen. */
  195. return 0;
  196. } else {
  197. pdf_resource_t *pres = pdev->accumulating_substream_resource;
  198. int code;
  199. uint ignore;
  200. code = pdf_exit_substream(pdev);
  201. if (code < 0)
  202. return code;
  203. code = pdf_substitute_resource(pdev, &pres, resourceXObject, NULL, false);
  204. if (code < 0)
  205. return code;
  206. sputc(pdev->strm,'/');
  207. sputs(pdev->strm, (const byte *)pres->rname, strlen(pres->rname), &ignore);
  208. sputs(pdev->strm, (const byte *)" Do\n", 4, &ignore);
  209. return 0;
  210. }
  211. }
  212. private int
  213. pdf_begin_transparency_mask(gs_imager_state * pis, gx_device_pdf * pdev,
  214. const gs_pdf14trans_params_t * pparams)
  215. {
  216. if (pparams->mask_is_image) {
  217. /* HACK :
  218. The control comes here when
  219. the PDF interpreter will make the PS interpreter
  220. to interprete the mask for filling the transparency buffer
  221. with an SMask image.
  222. Since we handle Type 3 images as a high level objects,
  223. we don't install the transparency buffer here
  224. and need to skip the image enumeration for the SMask.
  225. However we have no right method for skipping
  226. an image enumeration due to possible side effect
  227. of the image data proc in Postscript language.
  228. Therefore we do enumerate the image mask and accumulate
  229. it as a PDF stream, but don't create a reference to it.
  230. Later it will be enumerated once again as a part of SMask-ed image,
  231. and the pdfwrite image handler will recognize duplicated images
  232. and won't create the second stream for same image.
  233. We could make a special workaround for
  234. skipping mask images either in the graphics library or
  235. in the PS code of the PDF interpreter,
  236. but we don't want to complicate things now.
  237. The performance leak for the second enumeration
  238. shouldn't be harmful.
  239. So now just set a flag for pdf_end_and_do_image.
  240. */
  241. pdev->image_mask_skip = true;
  242. return 0;
  243. } else {
  244. int code;
  245. code = pdf_make_soft_mask_dict(pdev, pparams);
  246. if (code < 0)
  247. return code;
  248. code = pdf_open_page(pdev, PDF_IN_STREAM);
  249. if (code < 0)
  250. return code;
  251. return pdf_begin_transparency_group(pis, pdev, pparams);
  252. }
  253. }
  254. private int
  255. pdf_end_transparency_mask(gs_imager_state * pis, gx_device_pdf * pdev,
  256. const gs_pdf14trans_params_t * pparams)
  257. {
  258. if (pdev->image_mask_skip)
  259. pdev->image_mask_skip = false;
  260. else {
  261. pdf_resource_t *pres = pdev->accumulating_substream_resource;
  262. int code;
  263. char buf[20];
  264. code = pdf_exit_substream(pdev);
  265. if (code < 0)
  266. return code;
  267. code = pdf_substitute_resource(pdev, &pres, resourceXObject, NULL, false);
  268. if (code < 0)
  269. return 0;
  270. sprintf(buf, "%ld 0 R", pdf_resource_id(pres));
  271. code = cos_dict_put_c_key_string((cos_dict_t *)pdev->pres_soft_mask_dict->object,
  272. "/G", (const byte *)buf, strlen(buf));
  273. if (code < 0)
  274. return code;
  275. code = pdf_substitute_resource(pdev, &pdev->pres_soft_mask_dict,
  276. resourceSoftMaskDict, NULL, false);
  277. if (code < 0)
  278. return code;
  279. pis->soft_mask_id = pdev->pres_soft_mask_dict->object->id;
  280. pdev->pres_soft_mask_dict = NULL;
  281. }
  282. return 0;
  283. }
  284. private int
  285. pdf_set_blend_params(gs_imager_state * pis, gx_device_pdf * dev,
  286. const gs_pdf14trans_params_t * pparams)
  287. {
  288. return 0;
  289. }
  290. int
  291. gdev_pdf_create_compositor(gx_device *dev,
  292. gx_device **pcdev, const gs_composite_t *pct,
  293. gs_imager_state *pis, gs_memory_t *memory)
  294. {
  295. gx_device_pdf *pdev = (gx_device_pdf *)dev;
  296. if (pdev->HaveTransparency && pdev->CompatibilityLevel >= 1.4 &&
  297. pct->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) {
  298. gs_pdf14trans_t *pcte = (gs_pdf14trans_t *)pct;
  299. gs_pdf14trans_params_t *params = &pcte->params;
  300. *pcdev = dev;
  301. switch(params->pdf14_op) {
  302. case PDF14_PUSH_DEVICE:
  303. return 0;
  304. case PDF14_POP_DEVICE:
  305. return 0;
  306. case PDF14_BEGIN_TRANS_GROUP:
  307. return pdf_begin_transparency_group(pis, pdev, params);
  308. case PDF14_END_TRANS_GROUP:
  309. return pdf_end_transparency_group(pis, pdev);
  310. case PDF14_INIT_TRANS_MASK:
  311. return gx_init_transparency_mask(pis, params);
  312. case PDF14_BEGIN_TRANS_MASK:
  313. return pdf_begin_transparency_mask(pis, pdev, params);
  314. case PDF14_END_TRANS_MASK:
  315. return pdf_end_transparency_mask(pis, pdev, params);
  316. case PDF14_SET_BLEND_PARAMS:
  317. return pdf_set_blend_params(pis, pdev, params);
  318. default :
  319. return_error(gs_error_unregistered); /* Must not happen. */
  320. }
  321. return 0;
  322. }
  323. return psdf_create_compositor(dev, pcdev, pct, pis, memory);
  324. }
  325. /* We're not sure why the folllowing device methods are never called.
  326. Stub them for a while. */
  327. int
  328. gdev_pdf_begin_transparency_group(gx_device *dev,
  329. const gs_transparency_group_params_t *ptgp,
  330. const gs_rect *pbbox,
  331. gs_imager_state *pis,
  332. gs_transparency_state_t **ppts,
  333. gs_memory_t *mem)
  334. {
  335. return 0;
  336. }
  337. int
  338. gdev_pdf_end_transparency_group(gx_device *dev,
  339. gs_imager_state *pis,
  340. gs_transparency_state_t **ppts)
  341. {
  342. return 0;
  343. }
  344. int
  345. gdev_pdf_begin_transparency_mask(gx_device *dev,
  346. const gx_transparency_mask_params_t *ptmp,
  347. const gs_rect *pbbox,
  348. gs_imager_state *pis,
  349. gs_transparency_state_t **ppts,
  350. gs_memory_t *mem)
  351. {
  352. return 0;
  353. }
  354. int
  355. gdev_pdf_end_transparency_mask(gx_device *dev,
  356. gs_transparency_mask_t **pptm)
  357. {
  358. return 0;
  359. }
  360. int
  361. gdev_pdf_discard_transparency_layer(gx_device *dev,
  362. gs_transparency_state_t **ppts)
  363. {
  364. return 0;
  365. }