1 /*
2  * Imaging library stubs for CUPS.
3  *
4  * Copyright © 2018 by Apple Inc.
5  *
6  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
7  * information.
8  */
9 
10 /*
11  * Include necessary headers...
12  */
13 
14 #include "raster-private.h"
15 
16 
17 /*
18  * These stubs wrap the real functions in libcups - this allows one library to
19  * provide all of the CUPS API functions while still supporting the old split
20  * library organization...
21  */
22 
23 
24 /*
25  * Local functions...
26  */
27 
28 static ssize_t	cups_read_fd(void *ctx, unsigned char *buf, size_t bytes);
29 static ssize_t	cups_write_fd(void *ctx, unsigned char *buf, size_t bytes);
30 
31 
32 
33 /*
34  * 'cupsRasterClose()' - Close a raster stream.
35  *
36  * The file descriptor associated with the raster stream must be closed
37  * separately as needed.
38  */
39 
40 void
cupsRasterClose(cups_raster_t * r)41 cupsRasterClose(cups_raster_t *r)	/* I - Stream to close */
42 {
43   _cupsRasterDelete(r);
44 }
45 
46 
47 /*
48  * 'cupsRasterErrorString()' - Return the last error from a raster function.
49  *
50  * If there are no recent errors, `NULL` is returned.
51  *
52  * @since CUPS 1.3/macOS 10.5@
53  */
54 
55 const char *				/* O - Last error or `NULL` */
cupsRasterErrorString(void)56 cupsRasterErrorString(void)
57 {
58   return (_cupsRasterErrorString());
59 }
60 
61 
62 /*
63  * 'cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output.
64  *
65  * The "media" argument specifies the media to use.
66  *
67  * The "type" argument specifies a "pwg-raster-document-type-supported" value
68  * that controls the color space and bit depth of the raster data.
69  *
70  * The "xres" and "yres" arguments specify the raster resolution in dots per
71  * inch.
72  *
73  * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value
74  * to apply for the back side of a page.  Pass @code NULL@ for the front side.
75  *
76  * @since CUPS 2.2/macOS 10.12@
77  */
78 
79 int					/* O - 1 on success, 0 on failure */
cupsRasterInitPWGHeader(cups_page_header2_t * h,pwg_media_t * media,const char * type,int xdpi,int ydpi,const char * sides,const char * sheet_back)80 cupsRasterInitPWGHeader(
81     cups_page_header2_t *h,		/* I - Page header */
82     pwg_media_t         *media,		/* I - PWG media information */
83     const char          *type,		/* I - PWG raster type string */
84     int                 xdpi,		/* I - Cross-feed direction (horizontal) resolution */
85     int                 ydpi,		/* I - Feed direction (vertical) resolution */
86     const char          *sides,		/* I - IPP "sides" option value */
87     const char          *sheet_back)	/* I - Transform for back side or @code NULL@ for none */
88 {
89   return (_cupsRasterInitPWGHeader(h, media, type, xdpi, ydpi, sides, sheet_back));
90 }
91 
92 
93 /*
94  * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
95  *
96  * This function associates a raster stream with the given file descriptor.
97  * For most printer driver filters, "fd" will be 0 (stdin).  For most raster
98  * image processor (RIP) filters that generate raster data, "fd" will be 1
99  * (stdout).
100  *
101  * When writing raster data, the @code CUPS_RASTER_WRITE@,
102  * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
103  * be used - compressed and PWG output is generally 25-50% smaller but adds a
104  * 100-300% execution time overhead.
105  */
106 
107 cups_raster_t *				/* O - New stream */
cupsRasterOpen(int fd,cups_mode_t mode)108 cupsRasterOpen(int         fd,		/* I - File descriptor */
109                cups_mode_t mode)	/* I - Mode - @code CUPS_RASTER_READ@,
110 	                                       @code CUPS_RASTER_WRITE@,
111 					       @code CUPS_RASTER_WRITE_COMPRESSED@,
112 					       or @code CUPS_RASTER_WRITE_PWG@ */
113 {
114   if (mode == CUPS_RASTER_READ)
115     return (_cupsRasterNew(cups_read_fd, (void *)((intptr_t)fd), mode));
116   else
117     return (_cupsRasterNew(cups_write_fd, (void *)((intptr_t)fd), mode));
118 }
119 
120 
121 /*
122  * 'cupsRasterOpenIO()' - Open a raster stream using a callback function.
123  *
124  * This function associates a raster stream with the given callback function and
125  * context pointer.
126  *
127  * When writing raster data, the @code CUPS_RASTER_WRITE@,
128  * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
129  * be used - compressed and PWG output is generally 25-50% smaller but adds a
130  * 100-300% execution time overhead.
131  */
132 
133 cups_raster_t *				/* O - New stream */
cupsRasterOpenIO(cups_raster_iocb_t iocb,void * ctx,cups_mode_t mode)134 cupsRasterOpenIO(
135     cups_raster_iocb_t iocb,		/* I - Read/write callback */
136     void               *ctx,		/* I - Context pointer for callback */
137     cups_mode_t        mode)		/* I - Mode - @code CUPS_RASTER_READ@,
138 	                                       @code CUPS_RASTER_WRITE@,
139 					       @code CUPS_RASTER_WRITE_COMPRESSED@,
140 					       or @code CUPS_RASTER_WRITE_PWG@ */
141 {
142   return (_cupsRasterNew(iocb, ctx, mode));
143 }
144 
145 
146 /*
147  * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
148  *                            version 1 page header structure.
149  *
150  * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
151  *
152  * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
153  * of the version 2 page header data. This function handles reading version 2
154  * page headers and copying only the version 1 data into the provided buffer.
155  *
156  * @deprecated@
157  */
158 
159 unsigned				/* O - 1 on success, 0 on failure/end-of-file */
cupsRasterReadHeader(cups_raster_t * r,cups_page_header_t * h)160 cupsRasterReadHeader(
161     cups_raster_t      *r,		/* I - Raster stream */
162     cups_page_header_t *h)		/* I - Pointer to header data */
163 {
164  /*
165   * Get the raster header...
166   */
167 
168   if (!_cupsRasterReadHeader(r))
169   {
170     memset(h, 0, sizeof(cups_page_header_t));
171     return (0);
172   }
173 
174  /*
175   * Copy the header to the user-supplied buffer...
176   */
177 
178   memcpy(h, &(r->header), sizeof(cups_page_header_t));
179   return (1);
180 }
181 
182 
183 /*
184  * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
185  *                             version 2 page header structure.
186  *
187  * @since CUPS 1.2/macOS 10.5@
188  */
189 
190 unsigned				/* O - 1 on success, 0 on failure/end-of-file */
cupsRasterReadHeader2(cups_raster_t * r,cups_page_header2_t * h)191 cupsRasterReadHeader2(
192     cups_raster_t       *r,		/* I - Raster stream */
193     cups_page_header2_t *h)		/* I - Pointer to header data */
194 {
195  /*
196   * Get the raster header...
197   */
198 
199   if (!_cupsRasterReadHeader(r))
200   {
201     memset(h, 0, sizeof(cups_page_header2_t));
202     return (0);
203   }
204 
205  /*
206   * Copy the header to the user-supplied buffer...
207   */
208 
209   memcpy(h, &(r->header), sizeof(cups_page_header2_t));
210   return (1);
211 }
212 
213 
214 /*
215  * 'cupsRasterReadPixels()' - Read raster pixels.
216  *
217  * For best performance, filters should read one or more whole lines.
218  * The "cupsBytesPerLine" value from the page header can be used to allocate
219  * the line buffer and as the number of bytes to read.
220  */
221 
222 unsigned				/* O - Number of bytes read */
cupsRasterReadPixels(cups_raster_t * r,unsigned char * p,unsigned len)223 cupsRasterReadPixels(
224     cups_raster_t *r,			/* I - Raster stream */
225     unsigned char *p,			/* I - Pointer to pixel buffer */
226     unsigned      len)			/* I - Number of bytes to read */
227 {
228   return (_cupsRasterReadPixels(r, p, len));
229 }
230 
231 
232 /*
233  * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
234  *                             header structure.
235  *
236  * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
237  *
238  * @deprecated@
239  */
240 
241 unsigned				/* O - 1 on success, 0 on failure */
cupsRasterWriteHeader(cups_raster_t * r,cups_page_header_t * h)242 cupsRasterWriteHeader(
243     cups_raster_t      *r,		/* I - Raster stream */
244     cups_page_header_t *h)		/* I - Raster page header */
245 {
246   if (r == NULL || r->mode == CUPS_RASTER_READ)
247     return (0);
248 
249  /*
250   * Make a copy of the header and write using the private function...
251   */
252 
253   memset(&(r->header), 0, sizeof(r->header));
254   memcpy(&(r->header), h, sizeof(cups_page_header_t));
255 
256   return (_cupsRasterWriteHeader(r));
257 }
258 
259 
260 /*
261  * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
262  *                              page header structure.
263  *
264  * The page header can be initialized using @link cupsRasterInitPWGHeader@.
265  *
266  * @since CUPS 1.2/macOS 10.5@
267  */
268 
269 unsigned				/* O - 1 on success, 0 on failure */
cupsRasterWriteHeader2(cups_raster_t * r,cups_page_header2_t * h)270 cupsRasterWriteHeader2(
271     cups_raster_t       *r,		/* I - Raster stream */
272     cups_page_header2_t *h)		/* I - Raster page header */
273 {
274   if (r == NULL || r->mode == CUPS_RASTER_READ)
275     return (0);
276 
277  /*
278   * Make a copy of the header, and compute the number of raster
279   * lines in the page image...
280   */
281 
282   memcpy(&(r->header), h, sizeof(cups_page_header2_t));
283 
284   return (_cupsRasterWriteHeader(r));
285 }
286 
287 
288 /*
289  * 'cupsRasterWritePixels()' - Write raster pixels.
290  *
291  * For best performance, filters should write one or more whole lines.
292  * The "cupsBytesPerLine" value from the page header can be used to allocate
293  * the line buffer and as the number of bytes to write.
294  */
295 
296 unsigned				/* O - Number of bytes written */
cupsRasterWritePixels(cups_raster_t * r,unsigned char * p,unsigned len)297 cupsRasterWritePixels(
298     cups_raster_t *r,			/* I - Raster stream */
299     unsigned char *p,			/* I - Bytes to write */
300     unsigned      len)			/* I - Number of bytes to write */
301 {
302   return (_cupsRasterWritePixels(r, p, len));
303 }
304 
305 
306 /*
307  * 'cups_read_fd()' - Read bytes from a file.
308  */
309 
310 static ssize_t				/* O - Bytes read or -1 */
cups_read_fd(void * ctx,unsigned char * buf,size_t bytes)311 cups_read_fd(void          *ctx,	/* I - File descriptor as pointer */
312              unsigned char *buf,	/* I - Buffer for read */
313 	     size_t        bytes)	/* I - Maximum number of bytes to read */
314 {
315   int		fd = (int)((intptr_t)ctx);
316 					/* File descriptor */
317   ssize_t	count;			/* Number of bytes read */
318 
319 
320 #ifdef _WIN32 /* Sigh */
321   while ((count = read(fd, buf, (unsigned)bytes)) < 0)
322 #else
323   while ((count = read(fd, buf, bytes)) < 0)
324 #endif /* _WIN32 */
325     if (errno != EINTR && errno != EAGAIN)
326       return (-1);
327 
328   return (count);
329 }
330 
331 
332 /*
333  * 'cups_write_fd()' - Write bytes to a file.
334  */
335 
336 static ssize_t				/* O - Bytes written or -1 */
cups_write_fd(void * ctx,unsigned char * buf,size_t bytes)337 cups_write_fd(void          *ctx,	/* I - File descriptor pointer */
338               unsigned char *buf,	/* I - Bytes to write */
339 	      size_t        bytes)	/* I - Number of bytes to write */
340 {
341   int		fd = (int)((intptr_t)ctx);
342 					/* File descriptor */
343   ssize_t	count;			/* Number of bytes written */
344 
345 
346 #ifdef _WIN32 /* Sigh */
347   while ((count = write(fd, buf, (unsigned)bytes)) < 0)
348 #else
349   while ((count = write(fd, buf, bytes)) < 0)
350 #endif /* _WIN32 */
351     if (errno != EINTR && errno != EAGAIN)
352       return (-1);
353 
354   return (count);
355 }
356