gsdevice.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. /* Copyright (C) 1989, 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: gsdevice.c,v 1.25 2005/10/12 17:59:55 leonardo Exp $ */
  14. /* Device operators for Ghostscript library */
  15. #include "ctype_.h"
  16. #include "memory_.h" /* for memchr, memcpy */
  17. #include "string_.h"
  18. #include "gx.h"
  19. #include "gp.h"
  20. #include "gscdefs.h" /* for gs_lib_device_list */
  21. #include "gserrors.h"
  22. #include "gsfname.h"
  23. #include "gsstruct.h"
  24. #include "gspath.h" /* gs_initclip prototype */
  25. #include "gspaint.h" /* gs_erasepage prototype */
  26. #include "gsmatrix.h" /* for gscoord.h */
  27. #include "gscoord.h" /* for gs_initmatrix */
  28. #include "gzstate.h"
  29. #include "gxcmap.h"
  30. #include "gxdevice.h"
  31. #include "gxdevmem.h"
  32. #include "gxiodev.h"
  33. #include "gxcspace.h"
  34. /* Include the extern for the device list. */
  35. extern_gs_lib_device_list();
  36. /*
  37. * Finalization for devices: do any special finalization first, then
  38. * close the device if it is open, and finally free the structure
  39. * descriptor if it is dynamic.
  40. */
  41. void
  42. gx_device_finalize(void *vptr)
  43. {
  44. gx_device * const dev = (gx_device *)vptr;
  45. if (dev->finalize)
  46. dev->finalize(dev);
  47. discard(gs_closedevice(dev));
  48. if (dev->stype_is_dynamic)
  49. gs_free_const_object(dev->memory->non_gc_memory, dev->stype,
  50. "gx_device_finalize");
  51. }
  52. /* "Free" a device locally allocated on the stack, by finalizing it. */
  53. void
  54. gx_device_free_local(gx_device *dev)
  55. {
  56. gx_device_finalize(dev);
  57. }
  58. /* GC procedures */
  59. private
  60. ENUM_PTRS_WITH(device_forward_enum_ptrs, gx_device_forward *fdev) return 0;
  61. case 0: ENUM_RETURN(gx_device_enum_ptr(fdev->target));
  62. ENUM_PTRS_END
  63. private RELOC_PTRS_WITH(device_forward_reloc_ptrs, gx_device_forward *fdev)
  64. {
  65. fdev->target = gx_device_reloc_ptr(fdev->target, gcst);
  66. }
  67. RELOC_PTRS_END
  68. /*
  69. * Structure descriptors. These must follow the procedures, because
  70. * we can't conveniently forward-declare the procedures.
  71. * (See gxdevice.h for details.)
  72. */
  73. public_st_device();
  74. public_st_device_forward();
  75. public_st_device_null();
  76. /* GC utilities */
  77. /* Enumerate or relocate a device pointer for a client. */
  78. gx_device *
  79. gx_device_enum_ptr(gx_device * dev)
  80. {
  81. if (dev == 0 || dev->memory == 0)
  82. return 0;
  83. return dev;
  84. }
  85. gx_device *
  86. gx_device_reloc_ptr(gx_device * dev, gc_state_t * gcst)
  87. {
  88. if (dev == 0 || dev->memory == 0)
  89. return dev;
  90. return RELOC_OBJ(dev); /* gcst implicit */
  91. }
  92. /* Set up the device procedures in the device structure. */
  93. /* Also copy old fields to new ones. */
  94. void
  95. gx_device_set_procs(gx_device * dev)
  96. {
  97. if (dev->static_procs != 0) { /* 0 if already populated */
  98. dev->procs = *dev->static_procs;
  99. dev->static_procs = 0;
  100. }
  101. }
  102. /* Flush buffered output to the device */
  103. int
  104. gs_flushpage(gs_state * pgs)
  105. {
  106. gx_device *dev = gs_currentdevice(pgs);
  107. return (*dev_proc(dev, sync_output)) (dev);
  108. }
  109. /* Make the device output the accumulated page description */
  110. int
  111. gs_copypage(gs_state * pgs)
  112. {
  113. return gs_output_page(pgs, 1, 0);
  114. }
  115. int
  116. gs_output_page(gs_state * pgs, int num_copies, int flush)
  117. {
  118. gx_device *dev = gs_currentdevice(pgs);
  119. if (dev->IgnoreNumCopies)
  120. num_copies = 1;
  121. return (*dev_proc(dev, output_page)) (dev, num_copies, flush);
  122. }
  123. /*
  124. * Do generic work for output_page. All output_page procedures must call
  125. * this as the last thing they do, unless an error has occurred earlier.
  126. */
  127. int
  128. gx_finish_output_page(gx_device *dev, int num_copies, int flush)
  129. {
  130. dev->PageCount += num_copies;
  131. return 0;
  132. }
  133. /* Copy scan lines from an image device */
  134. int
  135. gs_copyscanlines(gx_device * dev, int start_y, byte * data, uint size,
  136. int *plines_copied, uint * pbytes_copied)
  137. {
  138. uint line_size = gx_device_raster(dev, 0);
  139. uint count = size / line_size;
  140. uint i;
  141. byte *dest = data;
  142. for (i = 0; i < count; i++, dest += line_size) {
  143. int code = (*dev_proc(dev, get_bits)) (dev, start_y + i, dest, NULL);
  144. if (code < 0) {
  145. /* Might just be an overrun. */
  146. if (start_y + i == dev->height)
  147. break;
  148. return_error(code);
  149. }
  150. }
  151. if (plines_copied != NULL)
  152. *plines_copied = i;
  153. if (pbytes_copied != NULL)
  154. *pbytes_copied = i * line_size;
  155. return 0;
  156. }
  157. /* Get the current device from the graphics state. */
  158. gx_device *
  159. gs_currentdevice(const gs_state * pgs)
  160. {
  161. return pgs->device;
  162. }
  163. /* Get the name of a device. */
  164. const char *
  165. gs_devicename(const gx_device * dev)
  166. {
  167. return dev->dname;
  168. }
  169. /* Get the initial matrix of a device. */
  170. void
  171. gs_deviceinitialmatrix(gx_device * dev, gs_matrix * pmat)
  172. {
  173. fill_dev_proc(dev, get_initial_matrix, gx_default_get_initial_matrix);
  174. (*dev_proc(dev, get_initial_matrix)) (dev, pmat);
  175. }
  176. /* Get the N'th device from the known device list */
  177. const gx_device *
  178. gs_getdevice(int index)
  179. {
  180. const gx_device *const *list;
  181. int count = gs_lib_device_list(&list, NULL);
  182. if (index < 0 || index >= count)
  183. return 0; /* index out of range */
  184. return list[index];
  185. }
  186. /* Fill in the GC structure descriptor for a device. */
  187. private void
  188. gx_device_make_struct_type(gs_memory_struct_type_t *st,
  189. const gx_device *dev)
  190. {
  191. const gx_device_procs *procs = dev->static_procs;
  192. /*
  193. * Try to figure out whether this is a forwarding device. For printer
  194. * devices, we rely on the prototype referencing the correct structure
  195. * descriptor; for other devices, we look for a likely forwarding
  196. * procedure in the vector. The algorithm isn't foolproof, but it's the
  197. * best we can come up with.
  198. */
  199. if (procs == 0)
  200. procs = &dev->procs;
  201. if (dev->stype)
  202. *st = *dev->stype;
  203. else if (procs->get_xfont_procs == gx_forward_get_xfont_procs)
  204. *st = st_device_forward;
  205. else
  206. *st = st_device;
  207. st->ssize = dev->params_size;
  208. }
  209. /* Clone an existing device. */
  210. int
  211. gs_copydevice2(gx_device ** pnew_dev, const gx_device * dev, bool keep_open,
  212. gs_memory_t * mem)
  213. {
  214. gx_device *new_dev;
  215. const gs_memory_struct_type_t *std = dev->stype;
  216. const gs_memory_struct_type_t *new_std;
  217. gs_memory_struct_type_t *a_std = 0;
  218. int code;
  219. if (dev->stype_is_dynamic) {
  220. /*
  221. * We allocated the stype for this device previously.
  222. * Just allocate a new stype and copy the old one into it.
  223. */
  224. a_std = (gs_memory_struct_type_t *)
  225. gs_alloc_bytes_immovable(mem->non_gc_memory, sizeof(*std),
  226. "gs_copydevice(stype)");
  227. if (!a_std)
  228. return_error(gs_error_VMerror);
  229. *a_std = *std;
  230. new_std = a_std;
  231. } else if (std != 0 && std->ssize == dev->params_size) {
  232. /* Use the static stype. */
  233. new_std = std;
  234. } else {
  235. /* We need to figure out or adjust the stype. */
  236. a_std = (gs_memory_struct_type_t *)
  237. gs_alloc_bytes_immovable(mem->non_gc_memory, sizeof(*std),
  238. "gs_copydevice(stype)");
  239. if (!a_std)
  240. return_error(gs_error_VMerror);
  241. gx_device_make_struct_type(a_std, dev);
  242. new_std = a_std;
  243. }
  244. /*
  245. * Because command list devices have complicated internal pointer
  246. * structures, we allocate all device instances as immovable.
  247. */
  248. new_dev = gs_alloc_struct_immovable(mem, gx_device, new_std,
  249. "gs_copydevice(device)");
  250. if (new_dev == 0)
  251. return_error(gs_error_VMerror);
  252. gx_device_init(new_dev, dev, mem, false);
  253. gx_device_set_procs(new_dev);
  254. new_dev->stype = new_std;
  255. new_dev->stype_is_dynamic = new_std != std;
  256. /*
  257. * keep_open is very dangerous. On the other hand, so is copydevice in
  258. * general, since it just copies the bits without any regard to pointers
  259. * (including self-pointers) that they may contain. We handle this by
  260. * making the default finish_copydevice forbid copying of anything other
  261. * than the device prototype.
  262. */
  263. new_dev->is_open = dev->is_open && keep_open;
  264. fill_dev_proc(new_dev, finish_copydevice, gx_default_finish_copydevice);
  265. code = dev_proc(new_dev, finish_copydevice)(new_dev, dev);
  266. if (code < 0) {
  267. gs_free_object(mem, new_dev, "gs_copydevice(device)");
  268. if (a_std)
  269. gs_free_object(dev->memory->non_gc_memory, a_std, "gs_copydevice(stype)");
  270. return code;
  271. }
  272. *pnew_dev = new_dev;
  273. return 0;
  274. }
  275. int
  276. gs_copydevice(gx_device ** pnew_dev, const gx_device * dev, gs_memory_t * mem)
  277. {
  278. return gs_copydevice2(pnew_dev, dev, false, mem);
  279. }
  280. /* Open a device if not open already. Return 0 if the device was open, */
  281. /* 1 if it was closed. */
  282. int
  283. gs_opendevice(gx_device *dev)
  284. {
  285. if (dev->is_open)
  286. return 0;
  287. check_device_separable(dev);
  288. gx_device_fill_in_procs(dev);
  289. {
  290. int code = (*dev_proc(dev, open_device))(dev);
  291. if (code < 0)
  292. return_error(code);
  293. dev->is_open = true;
  294. return 1;
  295. }
  296. }
  297. /* Set device parameters, updating a graphics state or imager state. */
  298. int
  299. gs_imager_putdeviceparams(gs_imager_state *pis, gx_device *dev,
  300. gs_param_list *plist)
  301. {
  302. int code = gs_putdeviceparams(dev, plist);
  303. if (code >= 0)
  304. gx_set_cmap_procs(pis, dev);
  305. return code;
  306. }
  307. private void
  308. gs_state_update_device(gs_state *pgs)
  309. {
  310. gx_set_cmap_procs((gs_imager_state *)pgs, pgs->device);
  311. gx_unset_dev_color(pgs);
  312. }
  313. int
  314. gs_state_putdeviceparams(gs_state *pgs, gs_param_list *plist)
  315. {
  316. int code = gs_putdeviceparams(pgs->device, plist);
  317. if (code >= 0)
  318. gs_state_update_device(pgs);
  319. return code;
  320. }
  321. /* Set the device in the graphics state */
  322. int
  323. gs_setdevice(gs_state * pgs, gx_device * dev)
  324. {
  325. int code = gs_setdevice_no_erase(pgs, dev);
  326. if (code == 1)
  327. code = gs_erasepage(pgs);
  328. return code;
  329. }
  330. int
  331. gs_setdevice_no_erase(gs_state * pgs, gx_device * dev)
  332. {
  333. int open_code = 0, code;
  334. /* Initialize the device */
  335. if (!dev->is_open) {
  336. gx_device_fill_in_procs(dev);
  337. if (gs_device_is_memory(dev)) {
  338. /* Set the target to the current device. */
  339. gx_device *odev = gs_currentdevice_inline(pgs);
  340. while (odev != 0 && gs_device_is_memory(odev))
  341. odev = ((gx_device_memory *)odev)->target;
  342. gx_device_set_target(((gx_device_forward *)dev), odev);
  343. }
  344. code = open_code = gs_opendevice(dev);
  345. if (code < 0)
  346. return code;
  347. }
  348. gs_setdevice_no_init(pgs, dev);
  349. pgs->ctm_default_set = false;
  350. if ((code = gs_initmatrix(pgs)) < 0 ||
  351. (code = gs_initclip(pgs)) < 0
  352. )
  353. return code;
  354. /* If we were in a charpath or a setcachedevice, */
  355. /* we aren't any longer. */
  356. pgs->in_cachedevice = 0;
  357. pgs->in_charpath = (gs_char_path_mode) 0;
  358. return open_code;
  359. }
  360. int
  361. gs_setdevice_no_init(gs_state * pgs, gx_device * dev)
  362. {
  363. /*
  364. * Just set the device, possibly changing color space but no other
  365. * device parameters.
  366. *
  367. * Make sure we don't close the device if dev == pgs->device
  368. * This could be done by allowing the rc_assign to close the
  369. * old 'dev' if the rc goes to 0 (via the device structure's
  370. * finalization procedure), but then the 'code' from the dev
  371. * closedevice would not be propagated up. We want to allow
  372. * the code to be handled, particularly for the pdfwrite
  373. * device.
  374. */
  375. if (pgs->device != NULL && pgs->device->rc.ref_count == 1 &&
  376. pgs->device != dev) {
  377. int code = gs_closedevice(pgs->device);
  378. if (code < 0)
  379. return code;
  380. }
  381. rc_assign(pgs->device, dev, "gs_setdevice_no_init");
  382. gs_state_update_device(pgs);
  383. return pgs->overprint ? gs_do_set_overprint(pgs) : 0;
  384. }
  385. /* Initialize a just-allocated device. */
  386. void
  387. gx_device_init(gx_device * dev, const gx_device * proto, gs_memory_t * mem,
  388. bool internal)
  389. {
  390. memcpy(dev, proto, proto->params_size);
  391. dev->memory = mem;
  392. dev->retained = !internal;
  393. rc_init(dev, mem, (internal ? 0 : 1));
  394. }
  395. /* Make a null device. */
  396. void
  397. gs_make_null_device(gx_device_null *dev_null, gx_device *dev,
  398. gs_memory_t * mem)
  399. {
  400. gx_device_init((gx_device *)dev_null, (const gx_device *)&gs_null_device,
  401. mem, true);
  402. gx_device_set_target((gx_device_forward *)dev_null, dev);
  403. if (dev) {
  404. /* The gx_device_copy_color_params() call below should
  405. probably copy over these new-style color mapping procs, as
  406. well as the old-style (map_rgb_color and friends). However,
  407. the change was made here instead, to minimize the potential
  408. impact of the patch.
  409. */
  410. gx_device *dn = (gx_device *)dev_null;
  411. set_dev_proc(dn, get_color_mapping_procs, gx_forward_get_color_mapping_procs);
  412. set_dev_proc(dn, get_color_comp_index, gx_forward_get_color_comp_index);
  413. set_dev_proc(dn, encode_color, gx_forward_encode_color);
  414. set_dev_proc(dn, decode_color, gx_forward_decode_color);
  415. gx_device_copy_color_params(dn, dev);
  416. }
  417. }
  418. /* Is a null device ? */
  419. bool gs_is_null_device(gx_device *dev)
  420. {
  421. /* Assuming null_fill_path isn't used elswhere. */
  422. return dev->procs.fill_path == gs_null_device.procs.fill_path;
  423. }
  424. /* Mark a device as retained or not retained. */
  425. void
  426. gx_device_retain(gx_device *dev, bool retained)
  427. {
  428. int delta = (int)retained - (int)dev->retained;
  429. if (delta) {
  430. dev->retained = retained; /* do first in case dev is freed */
  431. rc_adjust_only(dev, delta, "gx_device_retain");
  432. }
  433. }
  434. /* Select a null device. */
  435. int
  436. gs_nulldevice(gs_state * pgs)
  437. {
  438. if (pgs->device == 0 || !gx_device_is_null(pgs->device)) {
  439. gx_device *ndev;
  440. int code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device,
  441. pgs->memory);
  442. if (code < 0)
  443. return code;
  444. /*
  445. * Internal devices have a reference count of 0, not 1,
  446. * aside from references from graphics states.
  447. */
  448. rc_init(ndev, pgs->memory, 0);
  449. return gs_setdevice_no_erase(pgs, ndev);
  450. }
  451. return 0;
  452. }
  453. /* Close a device. The client is responsible for ensuring that */
  454. /* this device is not current in any graphics state. */
  455. int
  456. gs_closedevice(gx_device * dev)
  457. {
  458. int code = 0;
  459. if (dev->is_open) {
  460. code = (*dev_proc(dev, close_device))(dev);
  461. dev->is_open = false;
  462. if (code < 0)
  463. return_error(code);
  464. }
  465. return code;
  466. }
  467. /*
  468. * Just set the device without any reinitializing.
  469. * (For internal use only.)
  470. */
  471. void
  472. gx_set_device_only(gs_state * pgs, gx_device * dev)
  473. {
  474. rc_assign(pgs->device, dev, "gx_set_device_only");
  475. }
  476. /* Compute the size of one scan line for a device, */
  477. /* with or without padding to a word boundary. */
  478. uint
  479. gx_device_raster(const gx_device * dev, bool pad)
  480. {
  481. ulong bits = (ulong) dev->width * dev->color_info.depth;
  482. return (pad ? bitmap_raster(bits) : (uint) ((bits + 7) >> 3));
  483. }
  484. /* Adjust the resolution for devices that only have a fixed set of */
  485. /* geometries, so that the apparent size in inches remains constant. */
  486. /* If fit=1, the resolution is adjusted so that the entire image fits; */
  487. /* if fit=0, one dimension fits, but the other one is clipped. */
  488. int
  489. gx_device_adjust_resolution(gx_device * dev,
  490. int actual_width, int actual_height, int fit)
  491. {
  492. double width_ratio = (double)actual_width / dev->width;
  493. double height_ratio = (double)actual_height / dev->height;
  494. double ratio =
  495. (fit ? min(width_ratio, height_ratio) :
  496. max(width_ratio, height_ratio));
  497. dev->HWResolution[0] *= ratio;
  498. dev->HWResolution[1] *= ratio;
  499. gx_device_set_width_height(dev, actual_width, actual_height);
  500. return 0;
  501. }
  502. /* Set the HWMargins to values defined in inches. */
  503. /* If move_origin is true, also reset the Margins. */
  504. /* Note that this assumes a printer-type device (Y axis inverted). */
  505. void
  506. gx_device_set_margins(gx_device * dev, const float *margins /*[4] */ ,
  507. bool move_origin)
  508. {
  509. int i;
  510. for (i = 0; i < 4; ++i)
  511. dev->HWMargins[i] = margins[i] * 72.0;
  512. if (move_origin) {
  513. dev->Margins[0] = -margins[0] * dev->MarginsHWResolution[0];
  514. dev->Margins[1] = -margins[3] * dev->MarginsHWResolution[1];
  515. }
  516. }
  517. /* Handle 90 and 270 degree rotation of the Tray
  518. * Device must support TrayOrientation in its InitialMatrix and get/put params
  519. */
  520. private void
  521. gx_device_TrayOrientationRotate(gx_device *dev)
  522. {
  523. if ( dev->TrayOrientation == 90 || dev->TrayOrientation == 270) {
  524. /* page sizes don't rotate, height and width do rotate
  525. * HWResolution, HWSize, and MediaSize parameters interact,
  526. * and must be set before TrayOrientation
  527. */
  528. int tmp = dev->height;
  529. dev->height = dev->width;
  530. dev->width = tmp;
  531. }
  532. }
  533. /* Set the width and height, updating MediaSize to remain consistent. */
  534. void
  535. gx_device_set_width_height(gx_device * dev, int width, int height)
  536. {
  537. dev->width = width;
  538. dev->height = height;
  539. dev->MediaSize[0] = width * 72.0 / dev->HWResolution[0];
  540. dev->MediaSize[1] = height * 72.0 / dev->HWResolution[1];
  541. gx_device_TrayOrientationRotate(dev);
  542. }
  543. /* Set the resolution, updating width and height to remain consistent. */
  544. void
  545. gx_device_set_resolution(gx_device * dev, floatp x_dpi, floatp y_dpi)
  546. {
  547. dev->HWResolution[0] = x_dpi;
  548. dev->HWResolution[1] = y_dpi;
  549. dev->width = (int)(dev->MediaSize[0] * x_dpi / 72.0 + 0.5);
  550. dev->height = (int)(dev->MediaSize[1] * y_dpi / 72.0 + 0.5);
  551. gx_device_TrayOrientationRotate(dev);
  552. }
  553. /* Set the MediaSize, updating width and height to remain consistent. */
  554. void
  555. gx_device_set_media_size(gx_device * dev, floatp media_width, floatp media_height)
  556. {
  557. dev->MediaSize[0] = media_width;
  558. dev->MediaSize[1] = media_height;
  559. dev->width = (int)(media_width * dev->HWResolution[0] / 72.0 + 0.499);
  560. dev->height = (int)(media_height * dev->HWResolution[1] / 72.0 + 0.499);
  561. gx_device_TrayOrientationRotate(dev);
  562. }
  563. /*
  564. * Copy the color mapping procedures from the target if they are
  565. * standard ones (saving a level of procedure call at mapping time).
  566. */
  567. void
  568. gx_device_copy_color_procs(gx_device *dev, const gx_device *target)
  569. {
  570. dev_proc_map_cmyk_color((*from_cmyk)) =
  571. dev_proc(dev, map_cmyk_color);
  572. dev_proc_map_rgb_color((*from_rgb)) =
  573. dev_proc(dev, map_rgb_color);
  574. dev_proc_map_color_rgb((*to_rgb)) =
  575. dev_proc(dev, map_color_rgb);
  576. /* The logic in this function seems a bit stale; it sets the
  577. old-style color procs, but not the new ones
  578. (get_color_mapping_procs, get_color_comp_index, encode_color,
  579. and decode_color). It should probably copy those as well.
  580. */
  581. if (from_cmyk == gx_forward_map_cmyk_color ||
  582. from_cmyk == cmyk_1bit_map_cmyk_color ||
  583. from_cmyk == cmyk_8bit_map_cmyk_color) {
  584. from_cmyk = dev_proc(target, map_cmyk_color);
  585. set_dev_proc(dev, map_cmyk_color,
  586. (from_cmyk == cmyk_1bit_map_cmyk_color ||
  587. from_cmyk == cmyk_8bit_map_cmyk_color ?
  588. from_cmyk : gx_forward_map_cmyk_color));
  589. }
  590. if (from_rgb == gx_forward_map_rgb_color ||
  591. from_rgb == gx_default_rgb_map_rgb_color) {
  592. from_rgb = dev_proc(target, map_rgb_color);
  593. set_dev_proc(dev, map_rgb_color,
  594. (from_rgb == gx_default_rgb_map_rgb_color ?
  595. from_rgb : gx_forward_map_rgb_color));
  596. }
  597. if (to_rgb == gx_forward_map_color_rgb ||
  598. to_rgb == cmyk_1bit_map_color_rgb ||
  599. to_rgb == cmyk_8bit_map_color_rgb) {
  600. to_rgb = dev_proc(target, map_color_rgb);
  601. set_dev_proc(dev, map_color_rgb,
  602. (to_rgb == cmyk_1bit_map_color_rgb ||
  603. to_rgb == cmyk_8bit_map_color_rgb ?
  604. to_rgb : gx_forward_map_color_rgb));
  605. }
  606. }
  607. #define COPY_PARAM(p) dev->p = target->p
  608. /*
  609. * Copy the color-related device parameters back from the target:
  610. * color_info and color mapping procedures.
  611. */
  612. void
  613. gx_device_copy_color_params(gx_device *dev, const gx_device *target)
  614. {
  615. COPY_PARAM(color_info);
  616. COPY_PARAM(cached_colors);
  617. gx_device_copy_color_procs(dev, target);
  618. }
  619. /*
  620. * Copy device parameters back from a target. This copies all standard
  621. * parameters related to page size and resolution, plus color_info
  622. * and (if appropriate) color mapping procedures.
  623. */
  624. void
  625. gx_device_copy_params(gx_device *dev, const gx_device *target)
  626. {
  627. #define COPY_ARRAY_PARAM(p) memcpy(dev->p, target->p, sizeof(dev->p))
  628. COPY_PARAM(width);
  629. COPY_PARAM(height);
  630. COPY_ARRAY_PARAM(MediaSize);
  631. COPY_ARRAY_PARAM(ImagingBBox);
  632. COPY_PARAM(ImagingBBox_set);
  633. COPY_ARRAY_PARAM(HWResolution);
  634. COPY_ARRAY_PARAM(MarginsHWResolution);
  635. COPY_ARRAY_PARAM(Margins);
  636. COPY_ARRAY_PARAM(HWMargins);
  637. COPY_PARAM(PageCount);
  638. #undef COPY_ARRAY_PARAM
  639. gx_device_copy_color_params(dev, target);
  640. }
  641. #undef COPY_PARAM
  642. /*
  643. * Parse the output file name detecting and validating any %nnd format
  644. * for inserting the page count. If a format is present, store a pointer
  645. * to its last character in *pfmt, otherwise store 0 there.
  646. * Note that we assume devices have already been scanned, and any % must
  647. * precede a valid format character.
  648. *
  649. * If there was a format, then return the max_width
  650. */
  651. private int
  652. gx_parse_output_format(gs_parsed_file_name_t *pfn, const char **pfmt)
  653. {
  654. bool have_format = false, field = 0;
  655. int width[2], int_width = sizeof(int) * 3, w = 0;
  656. uint i;
  657. /* Scan the file name for a format string, and validate it if present. */
  658. width[0] = width[1] = 0;
  659. for (i = 0; i < pfn->len; ++i)
  660. if (pfn->fname[i] == '%') {
  661. if (i + 1 < pfn->len && pfn->fname[i + 1] == '%')
  662. continue;
  663. if (have_format) /* more than one % */
  664. return_error(gs_error_undefinedfilename);
  665. have_format = true;
  666. sw:
  667. if (++i == pfn->len)
  668. return_error(gs_error_undefinedfilename);
  669. switch (pfn->fname[i]) {
  670. case 'l':
  671. int_width = sizeof(long) * 3;
  672. case ' ': case '#': case '+': case '-':
  673. goto sw;
  674. case '.':
  675. if (field)
  676. return_error(gs_error_undefinedfilename);
  677. field = 1;
  678. continue;
  679. case '0': case '1': case '2': case '3': case '4':
  680. case '5': case '6': case '7': case '8': case '9':
  681. width[field] = width[field] * 10 + pfn->fname[i] - '0';
  682. goto sw;
  683. case 'd': case 'i': case 'u': case 'o': case 'x': case 'X':
  684. *pfmt = &pfn->fname[i];
  685. continue;
  686. default:
  687. return_error(gs_error_undefinedfilename);
  688. }
  689. }
  690. if (have_format) {
  691. /* Calculate a conservative maximum width. */
  692. w = max(width[0], width[1]);
  693. w = max(w, int_width) + 5;
  694. }
  695. return w;
  696. }
  697. /*
  698. * Parse the output file name for a device, recognizing "-" and "|command",
  699. * and also detecting and validating any %nnd format for inserting the
  700. * page count. If a format is present, store a pointer to its last
  701. * character in *pfmt, otherwise store 0 there. Note that an empty name
  702. * is currently allowed.
  703. */
  704. int
  705. gx_parse_output_file_name(gs_parsed_file_name_t *pfn, const char **pfmt,
  706. const char *fname, uint fnlen)
  707. {
  708. int code;
  709. *pfmt = 0;
  710. pfn->memory = 0;
  711. pfn->iodev = NULL;
  712. pfn->fname = NULL; /* irrelevant since length = 0 */
  713. pfn->len = 0;
  714. if (fnlen == 0) /* allow null name */
  715. return 0;
  716. /*
  717. * If the file name begins with a %, it might be either an IODevice
  718. * or a %nnd format. Check (carefully) for this case.
  719. */
  720. code = gs_parse_file_name(pfn, fname, fnlen);
  721. if (code < 0) {
  722. if (fname[0] == '%') {
  723. /* not a recognized iodev -- may be a leading format descriptor */
  724. pfn->len = fnlen;
  725. pfn->fname = fname;
  726. code = gx_parse_output_format(pfn, pfmt);
  727. }
  728. if (code < 0)
  729. return code;
  730. }
  731. if (!pfn->iodev) {
  732. if ( (pfn->len == 1) && (pfn->fname[0] == '-') ) {
  733. pfn->iodev = gs_findiodevice((const byte *)"%stdout", 7);
  734. pfn->fname = NULL;
  735. } else if (pfn->fname[0] == '|') {
  736. pfn->iodev = gs_findiodevice((const byte *)"%pipe", 5);
  737. pfn->fname++, pfn->len--;
  738. } else
  739. pfn->iodev = iodev_default;
  740. if (!pfn->iodev)
  741. return_error(gs_error_undefinedfilename);
  742. }
  743. if (!pfn->fname)
  744. return 0;
  745. code = gx_parse_output_format(pfn, pfmt);
  746. if (code < 0)
  747. return code;
  748. if (strlen(pfn->iodev->dname) + pfn->len + code >= gp_file_name_sizeof)
  749. return_error(gs_error_undefinedfilename);
  750. return 0;
  751. }
  752. /* Open the output file for a device. */
  753. int
  754. gx_device_open_output_file(const gx_device * dev, char *fname,
  755. bool binary, bool positionable, FILE ** pfile)
  756. {
  757. gs_parsed_file_name_t parsed;
  758. const char *fmt;
  759. char pfname[gp_file_name_sizeof];
  760. int code = gx_parse_output_file_name(&parsed, &fmt, fname, strlen(fname));
  761. if (code < 0)
  762. return code;
  763. if (parsed.iodev && !strcmp(parsed.iodev->dname, "%stdout%")) {
  764. if (parsed.fname)
  765. return_error(gs_error_undefinedfilename);
  766. *pfile = dev->memory->gs_lib_ctx->fstdout;
  767. /* Force stdout to binary. */
  768. return gp_setmode_binary(*pfile, true);
  769. }
  770. if (fmt) {
  771. long count1 = dev->PageCount + 1;
  772. while (*fmt != 'l' && *fmt != '%')
  773. --fmt;
  774. if (*fmt == 'l')
  775. sprintf(pfname, parsed.fname, count1);
  776. else
  777. sprintf(pfname, parsed.fname, (int)count1);
  778. parsed.fname = pfname;
  779. parsed.len = strlen(parsed.fname);
  780. }
  781. if (positionable || (parsed.iodev && parsed.iodev != iodev_default)) {
  782. char fmode[4];
  783. if (!parsed.fname)
  784. return_error(gs_error_undefinedfilename);
  785. strcpy(fmode, gp_fmode_wb);
  786. if (positionable)
  787. strcat(fmode, "+");
  788. code = parsed.iodev->procs.fopen(parsed.iodev, parsed.fname, fmode,
  789. pfile, NULL, 0);
  790. if (code)
  791. eprintf1("**** Could not open the file %s .\n", parsed.fname);
  792. return code;
  793. }
  794. *pfile = gp_open_printer((fmt ? pfname : fname), binary);
  795. if (*pfile)
  796. return 0;
  797. eprintf1("**** Could not open the file %s .\n", (fmt ? pfname : fname));
  798. return_error(gs_error_invalidfileaccess);
  799. }
  800. /* Close the output file for a device. */
  801. int
  802. gx_device_close_output_file(const gx_device * dev, const char *fname,
  803. FILE *file)
  804. {
  805. gs_parsed_file_name_t parsed;
  806. const char *fmt;
  807. int code = gx_parse_output_file_name(&parsed, &fmt, fname, strlen(fname));
  808. if (code < 0)
  809. return code;
  810. if (parsed.iodev) {
  811. if (!strcmp(parsed.iodev->dname, "%stdout%"))
  812. return 0;
  813. /* NOTE: fname is unsubstituted if the name has any %nnd formats. */
  814. if (parsed.iodev != iodev_default)
  815. return parsed.iodev->procs.fclose(parsed.iodev, file);
  816. }
  817. gp_close_printer(file, (parsed.fname ? parsed.fname : fname));
  818. return 0;
  819. }