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