/src/libspectre/ghostscript/base/gxblend1.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2020 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | /* PDF 1.4 blending functions */ |
17 | | |
18 | | #include "memory_.h" |
19 | | #include "gx.h" |
20 | | #include "gp.h" |
21 | | #include "gstparam.h" |
22 | | #include "gsrect.h" |
23 | | #include "gxblend.h" |
24 | | #include "gxdcconv.h" |
25 | | #include "gxdevcli.h" |
26 | | #include "gxgstate.h" |
27 | | #include "gdevdevn.h" |
28 | | #include "gdevp14.h" |
29 | | #include "gxdcconv.h" |
30 | | #include "gsicc_cache.h" |
31 | | #include "gxdevsop.h" |
32 | | |
33 | | #ifdef DUMP_TO_PNG |
34 | | #include "png_.h" |
35 | | #endif |
36 | | |
37 | | /* A case where we have RGB + spots. This is actually an RGB color and we |
38 | | * should zero out the spot colorants */ |
39 | | void |
40 | | pdf14_unpack_rgb_mix(int num_comp, gx_color_index color, |
41 | | pdf14_device * p14dev, byte * out) |
42 | 0 | { |
43 | 0 | int i; |
44 | |
|
45 | 0 | memset(out, 0, num_comp); |
46 | 0 | for (i = 2; i >= 0; i--) { |
47 | 0 | out[i] = (byte)(color & 0xff); |
48 | 0 | color >>= 8; |
49 | 0 | } |
50 | 0 | } |
51 | | |
52 | | void |
53 | | pdf14_unpack16_rgb_mix(int num_comp, gx_color_index color, |
54 | | pdf14_device * p14dev, uint16_t * out) |
55 | 0 | { |
56 | 0 | int i; |
57 | |
|
58 | 0 | memset(out, 0, num_comp); |
59 | 0 | for (i = 2; i >= 0; i--) { |
60 | 0 | out[i] = (uint16_t)color; |
61 | 0 | color >>= 16; |
62 | 0 | } |
63 | 0 | } |
64 | | |
65 | | /* A case where we have Gray + spots. This is actually a Gray color and we |
66 | | * should zero out the spot colorants */ |
67 | | void |
68 | | pdf14_unpack_gray_mix(int num_comp, gx_color_index color, |
69 | | pdf14_device * p14dev, byte * out) |
70 | 0 | { |
71 | 0 | memset(out, 0, num_comp); |
72 | 0 | out[0] = (byte)(color & 0xff); |
73 | 0 | } |
74 | | |
75 | | void |
76 | | pdf14_unpack16_gray_mix(int num_comp, gx_color_index color, |
77 | | pdf14_device * p14dev, uint16_t * out) |
78 | 0 | { |
79 | 0 | memset(out, 0, num_comp); |
80 | 0 | out[0] = (uint16_t)color; |
81 | 0 | } |
82 | | |
83 | | /* |
84 | | * Unpack a device color. This routine is similar to the device's |
85 | | * decode_color procedure except for two things. The procedure produces 1 |
86 | | * byte values instead of gx_color_values (2 bytes). A separate |
87 | | * procedure is used instead of the decode_color to minimize execution time. |
88 | | */ |
89 | | void |
90 | | pdf14_unpack_additive(int num_comp, gx_color_index color, |
91 | | pdf14_device * p14dev, byte * out) |
92 | 0 | { |
93 | 0 | int i; |
94 | |
|
95 | 0 | for (i = num_comp - 1; i >= 0; i--) { |
96 | 0 | out[i] = (byte)(color & 0xff); |
97 | 0 | color >>= 8; |
98 | 0 | } |
99 | 0 | } |
100 | | |
101 | | void |
102 | | pdf14_unpack16_additive(int num_comp, gx_color_index color, |
103 | | pdf14_device * p14dev, uint16_t * out) |
104 | 0 | { |
105 | 0 | int i; |
106 | |
|
107 | 0 | for (i = num_comp - 1; i >= 0; i--) { |
108 | 0 | out[i] = (uint16_t)color; |
109 | 0 | color >>= 16; |
110 | 0 | } |
111 | 0 | } |
112 | | |
113 | | /* |
114 | | * Unpack a device color. This routine is similar to the device's |
115 | | * decode_color procedure except for two things. The procedure produces 1 |
116 | | * byte values instead of gx_color_values (2 bytes) and the output values |
117 | | * are inverted for subtractive color spaces (like CMYK). A separate |
118 | | * procedure is used instead of the decode_color to minimize execution time. |
119 | | */ |
120 | | void |
121 | | pdf14_unpack_subtractive(int num_comp, gx_color_index color, |
122 | | pdf14_device * p14dev, byte * out) |
123 | 0 | { |
124 | 0 | int i; |
125 | |
|
126 | 0 | for (i = num_comp - 1; i >= 0; i--) { |
127 | 0 | out[i] = 0xff - (byte)(color & 0xff); |
128 | 0 | color >>= 8; |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | | void |
133 | | pdf14_unpack16_subtractive(int num_comp, gx_color_index color, |
134 | | pdf14_device * p14dev, uint16_t * out) |
135 | 0 | { |
136 | 0 | int i; |
137 | |
|
138 | 0 | for (i = num_comp - 1; i >= 0; i--) { |
139 | 0 | out[i] = (uint16_t)~color; |
140 | 0 | color >>= 16; |
141 | 0 | } |
142 | 0 | } |
143 | | |
144 | | /* |
145 | | * Unpack a device color. This routine is used for devices in which we do |
146 | | * not know the details of the process color model. In this case we use |
147 | | * the device's decode_color procedure. |
148 | | */ |
149 | | void |
150 | | pdf14_unpack_custom(int num_comp, gx_color_index color, |
151 | | pdf14_device * p14dev, byte * out) |
152 | 0 | { |
153 | 0 | int i; |
154 | 0 | gx_device * tdev = p14dev->target; |
155 | 0 | gx_color_value cm_values[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
156 | |
|
157 | 0 | dev_proc(tdev, decode_color)(tdev, color, cm_values); |
158 | 0 | for (i = 0; i < num_comp; i++) |
159 | 0 | out[i] = 0xff - gx_color_value_to_byte(cm_values[i]); |
160 | 0 | } |
161 | | |
162 | | void |
163 | | pdf14_unpack16_custom(int num_comp, gx_color_index color, |
164 | | pdf14_device * p14dev, uint16_t * out) |
165 | 0 | { |
166 | 0 | int i; |
167 | 0 | gx_device * tdev = p14dev->target; |
168 | 0 | gx_color_value cm_values[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
169 | |
|
170 | 0 | dev_proc(tdev, decode_color)(tdev, color, cm_values); |
171 | 0 | for (i = 0; i < num_comp; i++) |
172 | 0 | out[i] = ~cm_values[i]; |
173 | 0 | } |
174 | | |
175 | | #if RAW_DUMP |
176 | | extern unsigned int global_index; |
177 | | #endif |
178 | | |
179 | | static void |
180 | | copy_plane_part(byte *des_ptr, int des_rowstride, byte *src_ptr, int src_rowstride, |
181 | | int width, int height, bool deep) |
182 | 0 | { |
183 | 0 | int y; |
184 | |
|
185 | 0 | width <<= deep; |
186 | |
|
187 | 0 | if (width == des_rowstride && width == src_rowstride) { |
188 | 0 | width *= height; |
189 | 0 | height = 1; |
190 | 0 | } |
191 | |
|
192 | 0 | for (y = 0; y < height; ++y) { |
193 | 0 | memcpy(des_ptr, src_ptr, width); |
194 | 0 | des_ptr += des_rowstride; |
195 | 0 | src_ptr += src_rowstride; |
196 | 0 | } |
197 | 0 | } |
198 | | |
199 | | static void |
200 | | copy_extra_planes(byte *des_buf, pdf14_buf *des_info, byte *src_buf, |
201 | | pdf14_buf *src_info, int width, int height) |
202 | 0 | { |
203 | | /* alpha_g and shape do not copy */ |
204 | 0 | des_buf += des_info->planestride * ((des_info->has_shape ? 1 : 0) + |
205 | 0 | (des_info->has_alpha_g ? 1 : 0)); |
206 | 0 | src_buf += src_info->planestride * ((src_info->has_shape ? 1 : 0) + |
207 | 0 | (src_info->has_alpha_g ? 1 : 0)); |
208 | | /* tags plane does copy */ |
209 | 0 | if (des_info->has_tags) { |
210 | 0 | if (src_info->has_tags) { |
211 | 0 | copy_plane_part(des_buf, des_info->rowstride, src_buf, |
212 | 0 | src_info->rowstride, width, height, src_info->deep); |
213 | 0 | } |
214 | 0 | } |
215 | 0 | } |
216 | | |
217 | | int |
218 | | pdf14_preserve_backdrop_cm(pdf14_buf *buf, cmm_profile_t *group_profile, |
219 | | pdf14_buf *tos, cmm_profile_t *tos_profile, |
220 | | gs_memory_t *memory, gs_gstate *pgs, gx_device *dev, |
221 | | bool knockout_buff) |
222 | 0 | { |
223 | | /* Make copy of backdrop, but convert to new group's colorspace */ |
224 | 0 | int x0 = max(buf->rect.p.x, tos->rect.p.x); |
225 | 0 | int x1 = min(buf->rect.q.x, tos->rect.q.x); |
226 | 0 | int y0 = max(buf->rect.p.y, tos->rect.p.y); |
227 | 0 | int y1 = min(buf->rect.q.y, tos->rect.q.y); |
228 | 0 | bool deep = buf->deep; |
229 | |
|
230 | 0 | if (x0 < x1 && y0 < y1) { |
231 | 0 | int width = x1 - x0; |
232 | 0 | int height = y1 - y0; |
233 | 0 | byte *buf_plane, *tos_plane; |
234 | 0 | gsicc_rendering_param_t rendering_params; |
235 | 0 | gsicc_link_t *icc_link; |
236 | 0 | gsicc_bufferdesc_t input_buff_desc; |
237 | 0 | gsicc_bufferdesc_t output_buff_desc; |
238 | | |
239 | | /* Define the rendering intents */ |
240 | 0 | rendering_params.black_point_comp = gsBLACKPTCOMP_ON; |
241 | 0 | rendering_params.graphics_type_tag = GS_IMAGE_TAG; |
242 | 0 | rendering_params.override_icc = false; |
243 | 0 | rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; |
244 | 0 | rendering_params.rendering_intent = gsPERCEPTUAL; |
245 | 0 | rendering_params.cmm = gsCMM_DEFAULT; |
246 | | /* Request the ICC link for the transform that we will need to use */ |
247 | 0 | icc_link = gsicc_get_link_profile(pgs, dev, tos_profile, group_profile, |
248 | 0 | &rendering_params, memory, false); |
249 | 0 | if (icc_link == NULL) |
250 | 0 | return gs_throw(gs_error_unknownerror, "ICC link failed. Trans backdrop"); |
251 | | |
252 | 0 | if (icc_link->is_identity) { |
253 | 0 | pdf14_preserve_backdrop(buf, tos, knockout_buff |
254 | | #if RAW_DUMP |
255 | | , dev->memory |
256 | | #endif |
257 | 0 | ); |
258 | 0 | gsicc_release_link(icc_link); |
259 | 0 | return 0; |
260 | 0 | } else { |
261 | 0 | if (knockout_buff) { |
262 | 0 | buf_plane = buf->backdrop + ((x0 - buf->rect.p.x)<<deep) + |
263 | 0 | (y0 - buf->rect.p.y) * buf->rowstride; |
264 | 0 | tos_plane = tos->backdrop + ((x0 - tos->rect.p.x)<<deep) + |
265 | 0 | (y0 - tos->rect.p.y) * tos->rowstride; |
266 | 0 | memset(buf->backdrop, 0, buf->n_chan * buf->planestride<<deep); |
267 | 0 | } else { |
268 | 0 | buf_plane = buf->data + ((x0 - buf->rect.p.x)<<deep) + |
269 | 0 | (y0 - buf->rect.p.y) * buf->rowstride; |
270 | 0 | tos_plane = tos->data + ((x0 - tos->rect.p.x)<<deep) + |
271 | 0 | (y0 - tos->rect.p.y) * tos->rowstride; |
272 | | /* First clear out everything. There are cases where the incoming buf |
273 | | has a region outside the existing tos group. Need to check if this |
274 | | is getting clipped in which case we need to fix the allocation of |
275 | | the buffer to be smaller */ |
276 | 0 | memset(buf->data, 0, buf->n_planes * buf->planestride<<deep); |
277 | 0 | } |
278 | | /* Set up the buffer descriptors. */ |
279 | 0 | gsicc_init_buffer(&input_buff_desc, tos_profile->num_comps, 1<<deep, false, |
280 | 0 | false, true, tos->planestride, tos->rowstride, height, |
281 | 0 | width); |
282 | 0 | gsicc_init_buffer(&output_buff_desc, group_profile->num_comps, 1<<deep, false, |
283 | 0 | false, true, buf->planestride, buf->rowstride, height, |
284 | 0 | width); |
285 | | /* Transform the data. */ |
286 | 0 | (icc_link->procs.map_buffer)(dev, icc_link, &input_buff_desc, |
287 | 0 | &output_buff_desc, tos_plane, buf_plane); |
288 | 0 | gsicc_release_link(icc_link); |
289 | 0 | } |
290 | | /* Copy the alpha data */ |
291 | 0 | buf_plane += buf->planestride * (buf->n_chan - 1); |
292 | 0 | tos_plane += tos->planestride * (tos->n_chan - 1); |
293 | 0 | copy_plane_part(buf_plane, buf->rowstride, tos_plane, tos->rowstride, width, |
294 | 0 | height, deep); |
295 | 0 | buf_plane += buf->planestride; |
296 | 0 | tos_plane += tos->planestride; |
297 | |
|
298 | 0 | if (!knockout_buff) |
299 | 0 | copy_extra_planes(buf_plane, buf, tos_plane, tos, width, height); |
300 | 0 | } |
301 | | #if RAW_DUMP |
302 | | if (x0 < x1 && y0 < y1) { |
303 | | byte *buf_plane = buf->data + ((x0 - buf->rect.p.x)<<deep) + |
304 | | (y0 - buf->rect.p.y) * buf->rowstride; |
305 | | dump_raw_buffer(dev->memory, y1 - y0, x1 - x0, buf->n_planes, buf->planestride, |
306 | | buf->rowstride, "BackDropInit_CM", buf_plane, deep); |
307 | | global_index++; |
308 | | } |
309 | | #endif |
310 | 0 | return 0; |
311 | 0 | } |
312 | | |
313 | | void |
314 | | pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool from_backdrop |
315 | | #if RAW_DUMP |
316 | | , const gs_memory_t *mem |
317 | | #endif |
318 | | ) |
319 | 0 | { |
320 | | /* make copy of backdrop for compositing */ |
321 | 0 | int x0 = max(buf->rect.p.x, tos->rect.p.x); |
322 | 0 | int x1 = min(buf->rect.q.x, tos->rect.q.x); |
323 | 0 | int y0 = max(buf->rect.p.y, tos->rect.p.y); |
324 | 0 | int y1 = min(buf->rect.q.y, tos->rect.q.y); |
325 | |
|
326 | 0 | if (x0 < x1 && y0 < y1) { |
327 | 0 | int width = x1 - x0; |
328 | 0 | int height = y1 - y0; |
329 | 0 | byte *buf_plane, *tos_plane; |
330 | 0 | int i, n_planes; |
331 | 0 | bool deep = buf->deep; |
332 | |
|
333 | 0 | buf_plane = buf->data; |
334 | 0 | n_planes = buf->n_planes; |
335 | 0 | if (from_backdrop) { |
336 | 0 | tos_plane = tos->backdrop; |
337 | 0 | } else { |
338 | 0 | tos_plane = tos->data; |
339 | 0 | } |
340 | | |
341 | | /* First clear out everything. There are cases where the incoming buf |
342 | | has a region outside the existing tos group. Need to check if this |
343 | | is getting clipped in which case we need to fix the allocation of |
344 | | the buffer to be smaller */ |
345 | 0 | if (x0 > buf->rect.p.x || x1 < buf->rect.q.x || |
346 | 0 | y0 > buf->rect.p.y || y1 < buf->rect.q.y) { |
347 | | /* FIXME: There is potential for more optimisation here, |
348 | | * but I don't know how often we hit this case. */ |
349 | 0 | memset(buf_plane, 0, (size_t)n_planes * buf->planestride); |
350 | 0 | } else if (n_planes > tos->n_chan) { |
351 | | /* The next planes are alpha_g, shape, tags. We need to clear |
352 | | * alpha_g and shape, but don't need to clear the tag plane |
353 | | * if it would be copied below (and if it exists). */ |
354 | 0 | int tag_plane_num = tos->n_chan + !!buf->has_shape + !!buf->has_alpha_g; |
355 | 0 | if (!from_backdrop && n_planes > tag_plane_num) |
356 | 0 | n_planes = tag_plane_num; |
357 | 0 | if (n_planes > tos->n_chan) |
358 | 0 | memset(buf->data + (size_t)tos->n_chan * buf->planestride, 0, |
359 | 0 | (size_t)(n_planes - tos->n_chan) * buf->planestride); |
360 | 0 | } |
361 | 0 | buf_plane += (y0 - buf->rect.p.y) * buf->rowstride + |
362 | 0 | ((x0 - buf->rect.p.x)<<deep); |
363 | 0 | tos_plane += (y0 - tos->rect.p.y) * tos->rowstride + |
364 | 0 | ((x0 - tos->rect.p.x)<<deep); |
365 | | /* Color and alpha plane */ |
366 | 0 | for (i = 0; i < tos->n_chan; i++) { |
367 | 0 | copy_plane_part(buf_plane, buf->rowstride, tos_plane, tos->rowstride, |
368 | 0 | width, height, buf->deep); |
369 | 0 | buf_plane += buf->planestride; |
370 | 0 | tos_plane += tos->planestride; |
371 | 0 | } |
372 | 0 | if (!from_backdrop) |
373 | 0 | copy_extra_planes(buf_plane, buf, tos_plane, tos, width, height); |
374 | 0 | } |
375 | | #if RAW_DUMP |
376 | | if (x0 < x1 && y0 < y1) { |
377 | | byte *buf_plane = (from_backdrop ? buf->backdrop : buf->data); |
378 | | if (buf_plane != NULL) { |
379 | | buf_plane += ((x0 - buf->rect.p.x) << buf->deep) + |
380 | | (y0 - buf->rect.p.y) * buf->rowstride; |
381 | | dump_raw_buffer(mem, y1 - y0, x1 - x0, buf->n_planes, buf->planestride, |
382 | | buf->rowstride, "BackDropInit", buf_plane, buf->deep); |
383 | | global_index++; |
384 | | } |
385 | | } |
386 | | #endif |
387 | 0 | } |
388 | | |
389 | | /* |
390 | | * Encode a list of colorant values into a gx_color_index_value. |
391 | | */ |
392 | | gx_color_index |
393 | | pdf14_encode_color(gx_device *dev, const gx_color_value colors[]) |
394 | 0 | { |
395 | 0 | gx_color_index color = 0; |
396 | 0 | uchar i; |
397 | 0 | uchar ncomp = dev->color_info.num_components; |
398 | 0 | COLROUND_VARS; |
399 | |
|
400 | 0 | COLROUND_SETUP(8); |
401 | 0 | for (i = 0; i < ncomp; i++) { |
402 | 0 | color <<= 8; |
403 | 0 | color |= COLROUND_ROUND(colors[i]); |
404 | 0 | } |
405 | 0 | return (color == gx_no_color_index ? color ^ 1 : color); |
406 | 0 | } |
407 | | |
408 | | gx_color_index |
409 | | pdf14_encode_color16(gx_device *dev, const gx_color_value colors[]) |
410 | 0 | { |
411 | 0 | gx_color_index color = 0; |
412 | 0 | uchar i; |
413 | 0 | uchar ncomp = dev->color_info.num_components; |
414 | 0 | COLROUND_VARS; |
415 | |
|
416 | 0 | COLROUND_SETUP(16); |
417 | 0 | for (i = 0; i < ncomp; i++) { |
418 | 0 | color <<= 16; |
419 | 0 | color |= COLROUND_ROUND(colors[i]); |
420 | 0 | } |
421 | 0 | return (color == gx_no_color_index ? color ^ 1 : color); |
422 | 0 | } |
423 | | |
424 | | /* |
425 | | * Encode a list of colorant values into a gx_color_index_value. |
426 | | Stick the tag information at the end. |
427 | | */ |
428 | | gx_color_index |
429 | | pdf14_encode_color_tag(gx_device *dev, const gx_color_value colors[]) |
430 | 0 | { |
431 | 0 | gx_color_index color; |
432 | 0 | uchar i; |
433 | 0 | uchar ncomp = dev->color_info.num_components; |
434 | 0 | COLROUND_VARS; |
435 | |
|
436 | 0 | COLROUND_SETUP(8); |
437 | | /* Add in the tag information */ |
438 | 0 | color = dev->graphics_type_tag & ~GS_DEVICE_ENCODES_TAGS; |
439 | 0 | for (i = 0; i < ncomp; i++) { |
440 | 0 | color <<= 8; |
441 | 0 | color |= COLROUND_ROUND(colors[i]); |
442 | 0 | } |
443 | 0 | return (color == gx_no_color_index ? color ^ 1 : color); |
444 | 0 | } |
445 | | |
446 | | gx_color_index |
447 | | pdf14_encode_color16_tag(gx_device *dev, const gx_color_value colors[]) |
448 | 0 | { |
449 | 0 | gx_color_index color; |
450 | 0 | uchar i; |
451 | 0 | uchar ncomp = dev->color_info.num_components; |
452 | 0 | COLROUND_VARS; |
453 | |
|
454 | 0 | COLROUND_SETUP(16); |
455 | | /* Add in the tag information */ |
456 | 0 | color = dev->graphics_type_tag & ~GS_DEVICE_ENCODES_TAGS; |
457 | 0 | for (i = 0; i < ncomp; i++) { |
458 | 0 | color <<= 16; |
459 | 0 | color |= COLROUND_ROUND(colors[i]); |
460 | 0 | } |
461 | 0 | return (color == gx_no_color_index ? color ^ 1 : color); |
462 | 0 | } |
463 | | |
464 | | /* |
465 | | * Decode a gx_color_index value back to a list of colorant values. |
466 | | */ |
467 | | int |
468 | | pdf14_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out) |
469 | 0 | { |
470 | 0 | uchar i; |
471 | 0 | uchar ncomp = dev->color_info.num_components; |
472 | |
|
473 | 0 | for (i = 0; i < ncomp; i++) { |
474 | 0 | out[ncomp - i - 1] = (gx_color_value) ((color & 0xff) * 0x101); |
475 | 0 | color >>= 8; |
476 | 0 | } |
477 | 0 | return 0; |
478 | 0 | } |
479 | | |
480 | | int |
481 | | pdf14_decode_color16(gx_device * dev, gx_color_index color, gx_color_value * out) |
482 | 0 | { |
483 | 0 | uchar i; |
484 | 0 | uchar ncomp = dev->color_info.num_components; |
485 | |
|
486 | 0 | for (i = 0; i < ncomp; i++) { |
487 | 0 | out[ncomp - i - 1] = (gx_color_value) (color & 0xffff); |
488 | 0 | color >>= 16; |
489 | 0 | } |
490 | 0 | return 0; |
491 | 0 | } |
492 | | |
493 | | void |
494 | | pdf14_gray_cs_to_cmyk_cm(gx_device * dev, frac gray, frac out[]) |
495 | 0 | { |
496 | 0 | uchar num_comp = dev->color_info.num_components; |
497 | |
|
498 | 0 | out[0] = out[1] = out[2] = frac_0; |
499 | 0 | out[3] = frac_1 - gray; |
500 | 0 | for (--num_comp; num_comp > 3; num_comp--) |
501 | 0 | out[num_comp] = 0; |
502 | 0 | } |
503 | | |
504 | | /* These three must handle rgb + spot */ |
505 | | void |
506 | | pdf14_gray_cs_to_rgbspot_cm(gx_device * dev, frac gray, frac out[]) |
507 | 0 | { |
508 | 0 | uchar num_comp = dev->color_info.num_components; |
509 | |
|
510 | 0 | out[0] = out[1] = out[2] = gray; |
511 | 0 | for (--num_comp; num_comp > 2; num_comp--) |
512 | 0 | out[num_comp] = 0; |
513 | 0 | } |
514 | | |
515 | | void |
516 | | pdf14_rgb_cs_to_rgbspot_cm(gx_device * dev, const gs_gstate *pgs, |
517 | | frac r, frac g, frac b, frac out[]) |
518 | 0 | { |
519 | 0 | uchar num_comp = dev->color_info.num_components; |
520 | |
|
521 | 0 | out[0] = r; |
522 | 0 | out[1] = g; |
523 | 0 | out[2] = b; |
524 | 0 | for (--num_comp; num_comp > 2; num_comp--) |
525 | 0 | out[num_comp] = 0; |
526 | 0 | } |
527 | | |
528 | | void |
529 | | pdf14_cmyk_cs_to_rgbspot_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[]) |
530 | 0 | { |
531 | 0 | uchar num_comp = dev->color_info.num_components; |
532 | |
|
533 | 0 | color_cmyk_to_rgb(c, m, y, k, NULL, out, dev->memory); |
534 | 0 | for (--num_comp; num_comp > 2; num_comp--) |
535 | 0 | out[num_comp] = 0; |
536 | 0 | } |
537 | | |
538 | | /* These three must handle gray + spot */ |
539 | | void |
540 | | pdf14_gray_cs_to_grayspot_cm(gx_device * dev, frac gray, frac out[]) |
541 | 0 | { |
542 | 0 | uchar num_comp = dev->color_info.num_components; |
543 | |
|
544 | 0 | out[0] = gray; |
545 | 0 | for (--num_comp; num_comp > 0; num_comp--) |
546 | 0 | out[num_comp] = 0; |
547 | 0 | } |
548 | | |
549 | | void |
550 | | pdf14_rgb_cs_to_grayspot_cm(gx_device * dev, const gs_gstate *pgs, |
551 | | frac r, frac g, frac b, frac out[]) |
552 | 0 | { |
553 | 0 | uchar num_comp = dev->color_info.num_components; |
554 | |
|
555 | 0 | out[0] = (r + g + b) / 3; |
556 | 0 | for (--num_comp; num_comp > 0; num_comp--) |
557 | 0 | out[num_comp] = 0; |
558 | 0 | } |
559 | | |
560 | | void |
561 | | pdf14_cmyk_cs_to_grayspot_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[]) |
562 | 0 | { |
563 | 0 | uchar num_comp = dev->color_info.num_components; |
564 | |
|
565 | 0 | out[0] = color_cmyk_to_gray(c, m, y, k, NULL); |
566 | 0 | for (--num_comp; num_comp > 0; num_comp--) |
567 | 0 | out[num_comp] = 0; |
568 | 0 | } |
569 | | |
570 | | /* |
571 | | * Default map from DeviceRGB color space to DeviceCMYK color |
572 | | * model. Since this mapping is defined by the PostScript language |
573 | | * it is unlikely that any device with a DeviceCMYK color model |
574 | | * would define this mapping on its own. |
575 | | * |
576 | | * If the gs_gstate is not available, map as though the black |
577 | | * generation and undercolor removal functions are identity |
578 | | * transformations. This mode is used primarily to support the |
579 | | * raster operation (rop) feature of PCL, which requires that |
580 | | * the raster operation be performed in an RGB color space. |
581 | | * Note that default black generation and undercolor removal |
582 | | * functions in PostScript need NOT be identity transformations: |
583 | | * often they are { pop 0 }. |
584 | | */ |
585 | | void |
586 | | pdf14_rgb_cs_to_cmyk_cm(gx_device * dev, const gs_gstate *pgs, |
587 | | frac r, frac g, frac b, frac out[]) |
588 | 0 | { |
589 | 0 | uchar num_comp = dev->color_info.num_components; |
590 | |
|
591 | 0 | if (pgs != 0) |
592 | 0 | color_rgb_to_cmyk(r, g, b, pgs, out, dev->memory); |
593 | 0 | else { |
594 | 0 | frac c = frac_1 - r, m = frac_1 - g, y = frac_1 - b; |
595 | 0 | frac k = min(c, min(m, y)); |
596 | |
|
597 | 0 | out[0] = c - k; |
598 | 0 | out[1] = m - k; |
599 | 0 | out[2] = y - k; |
600 | 0 | out[3] = k; |
601 | 0 | } |
602 | 0 | for (--num_comp; num_comp > 3; num_comp--) |
603 | 0 | out[num_comp] = 0; |
604 | 0 | } |
605 | | |
606 | | void |
607 | | pdf14_cmyk_cs_to_cmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[]) |
608 | 0 | { |
609 | 0 | uchar num_comp = dev->color_info.num_components; |
610 | |
|
611 | 0 | out[0] = c; |
612 | 0 | out[1] = m; |
613 | 0 | out[2] = y; |
614 | 0 | out[3] = k; |
615 | 0 | for (--num_comp; num_comp > 3; num_comp--) |
616 | 0 | out[num_comp] = 0; |
617 | 0 | } |
618 | | |
619 | | #ifdef DUMP_TO_PNG |
620 | | /* Dumps a planar RGBA image to a PNG file. */ |
621 | | static int |
622 | | dump_planar_rgba(gs_memory_t *mem, const pdf14_buf *pbuf) |
623 | | { |
624 | | int rowstride = pbuf->rowstride, planestride = pbuf->planestride; |
625 | | int rowbytes = width << 2; |
626 | | gs_int_rect rect = buf->rect; |
627 | | int x1 = min(pdev->width, rect.q.x); |
628 | | int y1 = min(pdev->height, rect.q.y); |
629 | | int width = x1 - rect.p.x; |
630 | | int height = y1 - rect.p.y; |
631 | | byte *buf_ptr = buf->data + rect.p.y * buf->rowstride + rect.p.x; |
632 | | byte *row = gs_malloc(mem, rowbytes, 1, "png raster buffer"); |
633 | | png_struct *png_ptr = |
634 | | png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); |
635 | | png_info *info_ptr = |
636 | | png_create_info_struct(png_ptr); |
637 | | const char *software_key = "Software"; |
638 | | char software_text[256]; |
639 | | png_text text_png; |
640 | | gp_file *file; |
641 | | int code; |
642 | | int y; |
643 | | |
644 | | if (buf->data == NULL) |
645 | | return 0; |
646 | | |
647 | | file = gp_fopen (mem, "c:\\temp\\tmp.png", "wb"); |
648 | | |
649 | | if_debug0m('v', mem, "[v]pnga_output_page\n"); |
650 | | |
651 | | if (row == 0 || png_ptr == 0 || info_ptr == 0) { |
652 | | code = gs_note_error(gs_error_VMerror); |
653 | | goto done; |
654 | | } |
655 | | /* set error handling */ |
656 | | if (setjmp(png_ptr->jmpbuf)) { |
657 | | /* If we get here, we had a problem reading the file */ |
658 | | code = gs_note_error(gs_error_VMerror); |
659 | | goto done; |
660 | | } |
661 | | |
662 | | code = 0; /* for normal path */ |
663 | | /* set up the output control */ |
664 | | png_init_io(png_ptr, file); |
665 | | |
666 | | /* set the file information here */ |
667 | | info_ptr->width = width; |
668 | | info_ptr->height = height; |
669 | | /* resolution is in pixels per meter vs. dpi */ |
670 | | info_ptr->x_pixels_per_unit = |
671 | | (png_uint_32) (96.0 * (100.0 / 2.54)); |
672 | | info_ptr->y_pixels_per_unit = |
673 | | (png_uint_32) (96.0 * (100.0 / 2.54)); |
674 | | info_ptr->phys_unit_type = PNG_RESOLUTION_METER; |
675 | | info_ptr->valid |= PNG_INFO_pHYs; |
676 | | |
677 | | /* At present, only supporting 32-bit rgba */ |
678 | | info_ptr->bit_depth = 8; |
679 | | info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; |
680 | | |
681 | | /* add comment */ |
682 | | gs_sprintf(software_text, "%s %d.%02d", gs_product, |
683 | | (int)(gs_revision / 100), (int)(gs_revision % 100)); |
684 | | text_png.compression = -1; /* uncompressed */ |
685 | | text_png.key = (char *)software_key; /* not const, unfortunately */ |
686 | | text_png.text = software_text; |
687 | | text_png.text_length = strlen(software_text); |
688 | | info_ptr->text = &text_png; |
689 | | info_ptr->num_text = 1; |
690 | | |
691 | | /* write the file information */ |
692 | | png_write_info(png_ptr, info_ptr); |
693 | | |
694 | | /* don't write the comments twice */ |
695 | | info_ptr->num_text = 0; |
696 | | info_ptr->text = NULL; |
697 | | |
698 | | /* Write the contents of the image. */ |
699 | | for (y = 0; y < height; ++y) { |
700 | | int x; |
701 | | |
702 | | for (x = 0; x < width; ++x) { |
703 | | row[(x << 2)] = buf_ptr[x]; |
704 | | row[(x << 2) + 1] = buf_ptr[x + planestride]; |
705 | | row[(x << 2) + 2] = buf_ptr[x + planestride * 2]; |
706 | | row[(x << 2) + 3] = buf_ptr[x + planestride * 3]; |
707 | | } |
708 | | png_write_row(png_ptr, row); |
709 | | buf_ptr += rowstride; |
710 | | } |
711 | | |
712 | | /* write the rest of the file */ |
713 | | png_write_end(png_ptr, info_ptr); |
714 | | |
715 | | done: |
716 | | /* free the structures */ |
717 | | png_destroy_write_struct(&png_ptr, &info_ptr); |
718 | | gs_free(mem, row, rowbytes, 1, "png raster buffer"); |
719 | | |
720 | | fclose (file); |
721 | | return code; |
722 | | } |
723 | | #endif |
724 | | |
725 | | void |
726 | | gx_build_blended_image_row(const byte *gs_restrict buf_ptr, int planestride, |
727 | | int width, int num_comp, uint16_t bg, byte *gs_restrict linebuf) |
728 | 0 | { |
729 | 0 | int inc = planestride * num_comp; |
730 | |
|
731 | 0 | buf_ptr += inc - 1; |
732 | 0 | for (; width > 0; width--) { |
733 | | /* composite RGBA (or CMYKA, etc.) pixel with over solid background */ |
734 | 0 | byte a = *++buf_ptr; |
735 | 0 | int i = num_comp; |
736 | |
|
737 | 0 | if (a == 0) { |
738 | 0 | do { |
739 | 0 | *linebuf++ = bg; |
740 | 0 | } while (--i); |
741 | 0 | } else { |
742 | 0 | buf_ptr -= inc; |
743 | 0 | if (a == 0xff) { |
744 | 0 | do { |
745 | 0 | *linebuf++ = *buf_ptr; |
746 | 0 | buf_ptr += planestride; |
747 | 0 | } while (--i); |
748 | 0 | } else { |
749 | 0 | a ^= 0xff; |
750 | 0 | do { |
751 | 0 | byte comp = *buf_ptr; |
752 | 0 | int tmp = ((bg - comp) * a) + 0x80; |
753 | 0 | buf_ptr += planestride; |
754 | 0 | comp += (tmp + (tmp >> 8)) >> 8; |
755 | 0 | *linebuf++ = comp; |
756 | 0 | } while (--i); |
757 | 0 | } |
758 | 0 | } |
759 | 0 | } |
760 | 0 | } |
761 | | |
762 | | void |
763 | | gx_build_blended_image_row16(const byte *gs_restrict buf_ptr_, int planestride, |
764 | | int width, int num_comp, uint16_t bg, byte *gs_restrict linebuf) |
765 | 0 | { |
766 | 0 | const uint16_t *gs_restrict buf_ptr = (const uint16_t *)(const void *)buf_ptr_; |
767 | 0 | int inc; |
768 | | |
769 | | /* Note that we read in in native endian and blend, |
770 | | * then store out in big endian. */ |
771 | 0 | planestride >>= 1; /* Array indexing, not byte indexing */ |
772 | 0 | inc = planestride * num_comp; |
773 | 0 | buf_ptr += inc - 1; |
774 | 0 | for (; width > 0; width--) { |
775 | | /* composite RGBA (or CMYKA, etc.) pixel with over solid background */ |
776 | 0 | uint16_t a = *++buf_ptr; |
777 | 0 | int i = num_comp; |
778 | |
|
779 | 0 | if (a == 0) { |
780 | 0 | do { |
781 | 0 | *linebuf++ = bg>>8; |
782 | 0 | *linebuf++ = bg; |
783 | 0 | } while (--i); |
784 | 0 | } else { |
785 | 0 | buf_ptr -= inc; |
786 | 0 | if (a == 0xffff) { |
787 | 0 | do { |
788 | 0 | uint16_t comp = *buf_ptr; |
789 | 0 | *linebuf++ = comp>>8; |
790 | 0 | *linebuf++ = comp; |
791 | 0 | buf_ptr += planestride; |
792 | 0 | } while (--i); |
793 | 0 | } else { |
794 | 0 | a ^= 0xffff; |
795 | 0 | a += a>>15; |
796 | 0 | do { |
797 | 0 | uint32_t comp = *buf_ptr; |
798 | 0 | comp += (((bg - comp) * a) + 0x8000)>>16; |
799 | | /* Errors in bit 16 and above will be ignored */ |
800 | 0 | buf_ptr += planestride; |
801 | 0 | *linebuf++ = comp>>8; |
802 | 0 | *linebuf++ = comp; |
803 | 0 | } while (--i); |
804 | 0 | } |
805 | 0 | } |
806 | 0 | } |
807 | 0 | } |
808 | | |
809 | | void |
810 | | gx_blend_image_buffer(byte *buf_ptr, int width, int height, int rowstride, |
811 | | int planestride, int num_comp, byte bg) |
812 | 0 | { |
813 | 0 | int x, y; |
814 | 0 | int position; |
815 | 0 | byte comp, a; |
816 | 0 | int tmp, comp_num; |
817 | |
|
818 | 0 | for (y = 0; y < height; y++) { |
819 | 0 | position = y * rowstride; |
820 | 0 | for (x = 0; x < width; x++) { |
821 | | /* composite RGBA (or CMYKA, etc.) pixel with over solid background */ |
822 | 0 | a = buf_ptr[position + planestride * num_comp]; |
823 | 0 | if ((a + 1) & 0xfe) { |
824 | 0 | a ^= 0xff; |
825 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
826 | 0 | comp = buf_ptr[position + planestride * comp_num]; |
827 | 0 | tmp = ((bg - comp) * a) + 0x80; |
828 | 0 | comp += (tmp + (tmp >> 8)) >> 8; |
829 | 0 | buf_ptr[position + planestride * comp_num] = comp; |
830 | 0 | } |
831 | 0 | } else if (a == 0) { |
832 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
833 | 0 | buf_ptr[position + planestride * comp_num] = bg; |
834 | 0 | } |
835 | 0 | } |
836 | 0 | position+=1; |
837 | 0 | } |
838 | 0 | } |
839 | 0 | } |
840 | | |
841 | | void |
842 | | gx_blend_image_buffer16(byte *buf_ptr_, int width, int height, int rowstride, |
843 | | int planestride, int num_comp, uint16_t bg) |
844 | 0 | { |
845 | 0 | uint16_t *buf_ptr = (uint16_t *)(void *)buf_ptr_; |
846 | 0 | int x, y; |
847 | 0 | int position; |
848 | 0 | int comp, a; |
849 | 0 | int tmp, comp_num; |
850 | 0 | uint16_t bebg; |
851 | | |
852 | | /* Convert bg to be */ |
853 | 0 | ((byte *)&bebg)[0] = bg >> 8; |
854 | 0 | ((byte *)&bebg)[1] = bg; |
855 | | |
856 | | /* planestride and rowstride are in bytes, and we want them in shorts */ |
857 | 0 | planestride >>= 1; |
858 | 0 | rowstride >>= 1; |
859 | | |
860 | | /* Note that the input here is native endian, and the output must be in big endian! */ |
861 | 0 | for (y = 0; y < height; y++) { |
862 | 0 | position = y * rowstride; |
863 | 0 | for (x = 0; x < width; x++) { |
864 | | /* composite RGBA (or CMYKA, etc.) pixel with over solid background */ |
865 | 0 | a = buf_ptr[position + planestride * num_comp]; |
866 | 0 | if (a == 0) { |
867 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
868 | 0 | buf_ptr[position + planestride * comp_num] = bebg; |
869 | 0 | } |
870 | 0 | } else if (a == 0xffff) { |
871 | | #if ARCH_IS_BIG_ENDIAN |
872 | | #else |
873 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
874 | 0 | comp = buf_ptr[position + planestride * comp_num]; |
875 | 0 | ((byte *)&buf_ptr[position + planestride * comp_num])[0] = comp>>8; |
876 | 0 | ((byte *)&buf_ptr[position + planestride * comp_num])[1] = comp; |
877 | 0 | } |
878 | 0 | #endif |
879 | 0 | } else { |
880 | 0 | a ^= 0xffff; |
881 | 0 | a += a>>15; /* a is now 0 to 0x10000 */ |
882 | 0 | a >>= 1; /* We can only use 15 bits as bg-comp has a sign bit we can't lose */ |
883 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
884 | 0 | comp = buf_ptr[position + planestride * comp_num]; |
885 | 0 | tmp = (((int)bg - comp) * a) + 0x4000; |
886 | 0 | comp += (tmp >> 15); /* Errors in bit 16 upwards will be ignored */ |
887 | | /* Store as big endian */ |
888 | 0 | ((byte *)&buf_ptr[position + planestride * comp_num])[0] = comp>>8; |
889 | 0 | ((byte *)&buf_ptr[position + planestride * comp_num])[1] = comp; |
890 | 0 | } |
891 | 0 | } |
892 | 0 | position+=1; |
893 | 0 | } |
894 | 0 | } |
895 | 0 | } |
896 | | |
897 | | void |
898 | | gx_blend_image_buffer8to16(const byte *buf_ptr_in, unsigned short *buf_ptr_out, int width, |
899 | | int height, int rowstride, int planestride, int num_comp, byte bg) |
900 | 0 | { |
901 | 0 | int x, y; |
902 | 0 | int position; |
903 | 0 | int comp, a; |
904 | 0 | int tmp, comp_num; |
905 | 0 | int bg_out = bg + (bg << 8); |
906 | |
|
907 | 0 | for (y = 0; y < height; y++) { |
908 | 0 | position = y * rowstride; |
909 | 0 | for (x = 0; x < width; x++) { |
910 | | /* composite RGBA (or CMYKA, etc.) pixel with over solid background */ |
911 | 0 | a = buf_ptr_in[position + planestride * num_comp]; |
912 | 0 | if (a == 0xff) { |
913 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
914 | 0 | comp = buf_ptr_in[position + planestride * comp_num]; |
915 | 0 | buf_ptr_out[position + planestride * comp_num] = (comp + (comp << 8)); |
916 | 0 | } |
917 | 0 | } else if (a == 0) { |
918 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
919 | 0 | buf_ptr_out[position + planestride * comp_num] = bg_out; |
920 | 0 | } |
921 | 0 | } else { |
922 | 0 | a ^= 0xff; |
923 | 0 | a += (a << 8); |
924 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
925 | 0 | comp = buf_ptr_in[position + planestride * comp_num]; |
926 | 0 | comp += (comp << 8); |
927 | 0 | tmp = ((bg_out - comp) * a) + 0x8000; |
928 | 0 | comp += (tmp + (tmp >> 16)) >> 16; |
929 | 0 | comp = ((comp & 0xff) << 8) + ((comp & 0xff00) >> 8); |
930 | 0 | buf_ptr_out[position + planestride * comp_num] = comp; |
931 | 0 | } |
932 | 0 | } |
933 | 0 | position += 1; |
934 | 0 | } |
935 | 0 | } |
936 | 0 | } |
937 | | |
938 | | int |
939 | | gx_put_blended_image_custom(gx_device *target, byte *buf_ptr_, |
940 | | int planestride, int rowstride, |
941 | | int x0, int y0, int width, int height, |
942 | | int num_comp, uint16_t bg, bool deep) |
943 | 0 | { |
944 | 0 | int code = 0; |
945 | 0 | int x, y, tmp, comp_num; |
946 | 0 | gx_color_index color; |
947 | 0 | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
948 | 0 | gx_color_value comp; |
949 | 0 | uint16_t *buf_ptr = (uint16_t *)(void *)buf_ptr_; |
950 | | |
951 | | /* Send pixel data to the target device. */ |
952 | 0 | if (deep) { |
953 | 0 | for (y = 0; y < height; y++) { |
954 | 0 | for (x = 0; x < width; x++) { |
955 | | |
956 | | /* composite CMYKA, etc. pixel with over solid background */ |
957 | 0 | #define GET16(v) (*((uint16_t *)(void *)&(v))) |
958 | 0 | uint16_t a = GET16(buf_ptr[x + planestride * num_comp]); |
959 | |
|
960 | 0 | if (a == 0) { |
961 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
962 | 0 | cv[comp_num] = bg; |
963 | 0 | } |
964 | 0 | } else if (a == 0xffff) { |
965 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
966 | 0 | comp = buf_ptr[x + planestride * comp_num]; |
967 | 0 | cv[comp_num] = comp; |
968 | 0 | } |
969 | 0 | } else { |
970 | 0 | a ^= 0xffff; |
971 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
972 | 0 | comp = GET16(buf_ptr[x + planestride * comp_num]); |
973 | 0 | tmp = ((bg - comp) * a) + 0x8000; |
974 | 0 | cv[comp_num] = comp + ((tmp + (tmp>>16))>>16); |
975 | 0 | } |
976 | 0 | } |
977 | 0 | color = dev_proc(target, encode_color)(target, cv); |
978 | 0 | code = dev_proc(target, fill_rectangle)(target, x + x0, |
979 | 0 | y + y0, 1, 1, color); |
980 | 0 | if (code < 0) |
981 | 0 | return code; |
982 | 0 | } |
983 | | |
984 | 0 | buf_ptr += rowstride; |
985 | 0 | } |
986 | 0 | } else { |
987 | 0 | bg >>= 8; |
988 | 0 | for (y = 0; y < height; y++) { |
989 | 0 | for (x = 0; x < width; x++) { |
990 | | |
991 | | /* composite CMYKA, etc. pixel with over solid background */ |
992 | 0 | byte a = buf_ptr[x + planestride * num_comp]; |
993 | |
|
994 | 0 | if ((a + 1) & 0xfe) { |
995 | 0 | a ^= 0xff; |
996 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
997 | 0 | comp = buf_ptr[x + planestride * comp_num]; |
998 | 0 | tmp = ((bg - comp) * a) + 0x80; |
999 | 0 | comp += tmp + (tmp >> 8); |
1000 | 0 | cv[comp_num] = comp; |
1001 | 0 | } |
1002 | 0 | } else if (a == 0) { |
1003 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
1004 | 0 | cv[comp_num] = bg; |
1005 | 0 | } |
1006 | 0 | } else { |
1007 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
1008 | 0 | comp = buf_ptr[x + planestride * comp_num]; |
1009 | 0 | cv[comp_num] = (comp << 8) + comp; |
1010 | 0 | } |
1011 | 0 | } |
1012 | 0 | color = dev_proc(target, encode_color)(target, cv); |
1013 | 0 | code = dev_proc(target, fill_rectangle)(target, x + x0, |
1014 | 0 | y + y0, 1, 1, color); |
1015 | 0 | if (code < 0) |
1016 | 0 | return code; |
1017 | 0 | } |
1018 | | |
1019 | 0 | buf_ptr += rowstride; |
1020 | 0 | } |
1021 | 0 | } |
1022 | 0 | return code; |
1023 | 0 | } |