/src/ghostpdl/base/gdevmem.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2024 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., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | /* Generic "memory" (stored bitmap) device */ |
17 | | #include "memory_.h" |
18 | | #include "gx.h" |
19 | | #include "gsdevice.h" |
20 | | #include "gserrors.h" |
21 | | #include "gsrect.h" |
22 | | #include "gsstruct.h" |
23 | | #include "gxarith.h" |
24 | | #include "gxdevice.h" |
25 | | #include "gxgetbit.h" |
26 | | #include "gxdevmem.h" /* semi-public definitions */ |
27 | | #include "gdevmem.h" /* private definitions */ |
28 | | #include "gstrans.h" |
29 | | |
30 | | /* Structure descriptor */ |
31 | | public_st_device_memory(); |
32 | | |
33 | | /* GC procedures */ |
34 | | static |
35 | 35.7k | ENUM_PTRS_WITH(device_memory_enum_ptrs, gx_device_memory *mptr) |
36 | 11.9k | { |
37 | 11.9k | return ENUM_USING(st_device_forward, vptr, sizeof(gx_device_forward), index - 4); |
38 | 0 | } |
39 | 5.96k | case 0: ENUM_RETURN((mptr->foreign_bits ? NULL : (void *)mptr->base)); |
40 | 5.96k | case 1: ENUM_RETURN((mptr->foreign_line_pointers ? NULL : (void *)mptr->line_ptrs)); |
41 | 5.96k | ENUM_STRING_PTR(2, gx_device_memory, palette); |
42 | 5.96k | case 3: ENUM_RETURN(mptr->owner); |
43 | 35.7k | ENUM_PTRS_END |
44 | | static |
45 | 5.96k | RELOC_PTRS_WITH(device_memory_reloc_ptrs, gx_device_memory *mptr) |
46 | 5.96k | { |
47 | 5.96k | if (!mptr->foreign_bits) { |
48 | 0 | byte *base_old = mptr->base; |
49 | 0 | long reloc; |
50 | 0 | int y; |
51 | 0 | int h = mptr->height; |
52 | |
|
53 | 0 | if (mptr->num_planar_planes > 1) |
54 | 0 | h *= mptr->num_planar_planes; |
55 | |
|
56 | 0 | RELOC_PTR(gx_device_memory, base); |
57 | 0 | reloc = base_old - mptr->base; |
58 | 0 | for (y = 0; y < h; y++) |
59 | 0 | mptr->line_ptrs[y] -= reloc; |
60 | | /* Relocate line_ptrs, which also points into the data area. */ |
61 | 0 | mptr->line_ptrs = (byte **) ((byte *) mptr->line_ptrs - reloc); |
62 | 5.96k | } else if (!mptr->foreign_line_pointers) { |
63 | 0 | RELOC_PTR(gx_device_memory, line_ptrs); |
64 | 0 | } |
65 | 5.96k | RELOC_CONST_STRING_PTR(gx_device_memory, palette); |
66 | 5.96k | RELOC_PTR(gx_device_memory, owner); |
67 | 5.96k | RELOC_USING(st_device_forward, vptr, sizeof(gx_device_forward)); |
68 | 5.96k | } |
69 | 5.96k | RELOC_PTRS_END |
70 | | |
71 | | /* Define the palettes for monobit devices. */ |
72 | | static const byte b_w_palette_string[6] = { |
73 | | 0xff, 0xff, 0xff, 0, 0, 0 |
74 | | }; |
75 | | const gs_const_string mem_mono_b_w_palette = { |
76 | | b_w_palette_string, 6 |
77 | | }; |
78 | | static const byte w_b_palette_string[6] = { |
79 | | 0, 0, 0, 0xff, 0xff, 0xff |
80 | | }; |
81 | | const gs_const_string mem_mono_w_b_palette = { |
82 | | w_b_palette_string, 6 |
83 | | }; |
84 | | |
85 | | /* ------ Generic code ------ */ |
86 | | |
87 | | /* Return the appropriate memory device for a given */ |
88 | | /* number of bits per pixel (0 if none suitable). |
89 | | Greater than 64 occurs for the planar case |
90 | | which we will then return a mem_x_device */ |
91 | | static const gx_device_memory *const mem_devices[65] = { |
92 | | 0, &mem_mono_device, &mem_mapped2_device, 0, &mem_mapped4_device, |
93 | | 0, 0, 0, &mem_mapped8_device, |
94 | | 0, 0, 0, 0, 0, 0, 0, &mem_true16_device, |
95 | | 0, 0, 0, 0, 0, 0, 0, &mem_true24_device, |
96 | | 0, 0, 0, 0, 0, 0, 0, &mem_true32_device, |
97 | | 0, 0, 0, 0, 0, 0, 0, &mem_true40_device, |
98 | | 0, 0, 0, 0, 0, 0, 0, &mem_true48_device, |
99 | | 0, 0, 0, 0, 0, 0, 0, &mem_true56_device, |
100 | | 0, 0, 0, 0, 0, 0, 0, &mem_true64_device |
101 | | }; |
102 | | const gx_device_memory * |
103 | | gdev_mem_device_for_bits(int bits_per_pixel) |
104 | 202M | { |
105 | 202M | return ((uint)bits_per_pixel > 64 ? &mem_x_device : |
106 | 202M | mem_devices[bits_per_pixel]); |
107 | 202M | } |
108 | | /* Do the same for a word-oriented device. */ |
109 | | static const gx_device_memory *const mem_word_devices[65] = { |
110 | | 0, &mem_mono_device, &mem_mapped2_word_device, 0, &mem_mapped4_word_device, |
111 | | 0, 0, 0, &mem_mapped8_word_device, |
112 | | 0, 0, 0, 0, 0, 0, 0, 0 /*no 16-bit word device*/, |
113 | | 0, 0, 0, 0, 0, 0, 0, &mem_true24_word_device, |
114 | | 0, 0, 0, 0, 0, 0, 0, &mem_true32_word_device, |
115 | | 0, 0, 0, 0, 0, 0, 0, &mem_true40_word_device, |
116 | | 0, 0, 0, 0, 0, 0, 0, &mem_true48_word_device, |
117 | | 0, 0, 0, 0, 0, 0, 0, &mem_true56_word_device, |
118 | | 0, 0, 0, 0, 0, 0, 0, &mem_true64_word_device |
119 | | }; |
120 | | const gx_device_memory * |
121 | | gdev_mem_word_device_for_bits(int bits_per_pixel) |
122 | 0 | { |
123 | 0 | return ((uint)bits_per_pixel > 64 ? (const gx_device_memory *)0 : |
124 | 0 | mem_word_devices[bits_per_pixel]); |
125 | 0 | } |
126 | | |
127 | | static const gdev_mem_functions *mem_fns[65] = { |
128 | | NULL, &gdev_mem_fns_1, &gdev_mem_fns_2, NULL, |
129 | | &gdev_mem_fns_4, NULL, NULL, NULL, |
130 | | &gdev_mem_fns_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
131 | | &gdev_mem_fns_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
132 | | &gdev_mem_fns_24, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
133 | | &gdev_mem_fns_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
134 | | &gdev_mem_fns_40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
135 | | &gdev_mem_fns_48, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
136 | | &gdev_mem_fns_56, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
137 | | &gdev_mem_fns_64 |
138 | | }; |
139 | | |
140 | | const gdev_mem_functions * |
141 | | gdev_mem_functions_for_bits(int bits_per_pixel) |
142 | 345M | { |
143 | 345M | return ((uint)bits_per_pixel > 64 ? NULL : mem_fns[bits_per_pixel]); |
144 | 345M | } |
145 | | |
146 | | static const gdev_mem_functions *mem_word_fns[65] = { |
147 | | NULL, &gdev_mem_fns_1, &gdev_mem_fns_2w, NULL, |
148 | | &gdev_mem_fns_4w, NULL, NULL, NULL, |
149 | | &gdev_mem_fns_8w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
150 | | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
151 | | &gdev_mem_fns_24w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
152 | | &gdev_mem_fns_32w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
153 | | &gdev_mem_fns_40w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
154 | | &gdev_mem_fns_48w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
155 | | &gdev_mem_fns_56w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
156 | | &gdev_mem_fns_64w |
157 | | }; |
158 | | |
159 | | const gdev_mem_functions * |
160 | | gdev_mem_word_functions_for_bits(int bits_per_pixel) |
161 | 0 | { |
162 | 0 | return ((uint)bits_per_pixel > 64 ? NULL : mem_word_fns[bits_per_pixel]); |
163 | 0 | } |
164 | | |
165 | | /* Test whether a device is a memory device */ |
166 | | bool |
167 | | gs_device_is_memory(const gx_device * dev) |
168 | 433M | { |
169 | | /* |
170 | | * We use the draw_thin_line procedure to mark memory devices. |
171 | | * See gdevmem.h. |
172 | | */ |
173 | 433M | return (dev_proc(dev, draw_thin_line) == mem_draw_thin_line); |
174 | 433M | } |
175 | | |
176 | | /* Make a memory device. */ |
177 | | /* Note that the default for monobit devices is white = 0, black = 1. */ |
178 | | void |
179 | | gs_make_mem_device(gx_device_memory * dev, const gx_device_memory * mdproto, |
180 | | gs_memory_t * mem, int page_device, gx_device * target) |
181 | 161M | { |
182 | | /* Can never fail */ |
183 | 161M | (void)gx_device_init((gx_device *) dev, (const gx_device *)mdproto, |
184 | 161M | mem, true); |
185 | 161M | dev->stype = &st_device_memory; |
186 | 161M | switch (page_device) { |
187 | 4.36k | case -1: |
188 | 4.36k | set_dev_proc(dev, get_page_device, gx_default_get_page_device); |
189 | 4.36k | break; |
190 | 1.35M | case 1: |
191 | 1.35M | set_dev_proc(dev, get_page_device, gx_page_device_get_page_device); |
192 | 1.35M | break; |
193 | 161M | } |
194 | | /* Preload the black and white cache. */ |
195 | 161M | if (target == NULL) { |
196 | 3.13k | if (dev->color_info.depth == 1) { |
197 | | /* The default for black-and-white devices is inverted. */ |
198 | 0 | dev->cached_colors.black = 1; |
199 | 0 | dev->cached_colors.white = 0; |
200 | 3.13k | } else { |
201 | 3.13k | dev->cached_colors.black = 0; |
202 | 3.13k | dev->cached_colors.white = (1 << dev->color_info.depth) - 1; |
203 | 3.13k | } |
204 | 3.13k | dev->graphics_type_tag = GS_UNKNOWN_TAG; |
205 | 161M | } else { |
206 | 161M | gx_device_set_target((gx_device_forward *)dev, target); |
207 | | /* Forward the color mapping operations to the target. */ |
208 | 161M | gx_device_forward_color_procs((gx_device_forward *) dev); |
209 | 161M | gx_device_copy_color_procs((gx_device *)dev, target); |
210 | 161M | dev->color_info.separable_and_linear = target->color_info.separable_and_linear; |
211 | 161M | dev->cached_colors = target->cached_colors; |
212 | 161M | dev->graphics_type_tag = target->graphics_type_tag; /* initialize to same as target */ |
213 | | |
214 | 161M | set_dev_proc(dev, put_image, gx_forward_put_image); |
215 | 161M | } |
216 | 161M | if (dev->color_info.depth == 1) { |
217 | 49.4M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
218 | 49.4M | uchar k; |
219 | | |
220 | 49.4M | if (target != 0) { |
221 | 129M | for (k = 0; k < target->color_info.num_components; k++) { |
222 | 79.8M | cv[k] = 0; |
223 | 79.8M | } |
224 | 49.4M | } |
225 | 49.4M | gdev_mem_mono_set_inverted(dev, (target == NULL || |
226 | 49.4M | (*dev_proc(dev, encode_color))((gx_device *)dev, cv) != 0)); |
227 | 49.4M | } |
228 | 161M | set_dev_proc(dev, dev_spec_op, mem_spec_op); |
229 | 161M | check_device_separable((gx_device *)dev); |
230 | 161M | gx_device_fill_in_procs((gx_device *)dev); |
231 | 161M | dev->band_y = 0; |
232 | 161M | dev->owner = target; |
233 | 161M | } |
234 | | |
235 | | /* Make a memory device using copydevice, this should replace gs_make_mem_device. */ |
236 | | /* Note that the default for monobit devices is white = 0, black = 1. */ |
237 | | int |
238 | | gs_make_mem_device_with_copydevice(gx_device_memory ** ppdev, |
239 | | const gx_device_memory * mdproto, |
240 | | gs_memory_t * mem, |
241 | | int page_device, |
242 | | gx_device * target) |
243 | 0 | { |
244 | 0 | int code; |
245 | 0 | gx_device_memory *pdev; |
246 | |
|
247 | 0 | if (mem == NULL) |
248 | 0 | return -1; |
249 | | |
250 | 0 | code = gs_copydevice((gx_device **)&pdev, |
251 | 0 | (const gx_device *)mdproto, |
252 | 0 | mem); |
253 | 0 | if (code < 0) |
254 | 0 | return code; |
255 | | |
256 | 0 | switch (page_device) { |
257 | 0 | case -1: |
258 | 0 | set_dev_proc(pdev, get_page_device, gx_default_get_page_device); |
259 | 0 | break; |
260 | 0 | case 1: |
261 | 0 | set_dev_proc(pdev, get_page_device, gx_page_device_get_page_device); |
262 | 0 | break; |
263 | 0 | } |
264 | | /* Preload the black and white cache. */ |
265 | 0 | if (target == NULL) { |
266 | 0 | if (pdev->color_info.depth == 1) { |
267 | | /* The default for black-and-white devices is inverted. */ |
268 | 0 | pdev->cached_colors.black = 1; |
269 | 0 | pdev->cached_colors.white = 0; |
270 | 0 | } else { |
271 | 0 | pdev->cached_colors.black = 0; |
272 | 0 | pdev->cached_colors.white = (1 << pdev->color_info.depth) - 1; |
273 | 0 | } |
274 | 0 | pdev->graphics_type_tag = GS_UNKNOWN_TAG; |
275 | 0 | } else { |
276 | 0 | gx_device_set_target((gx_device_forward *)pdev, target); |
277 | | /* Forward the color mapping operations to the target. */ |
278 | 0 | gx_device_forward_color_procs((gx_device_forward *) pdev); |
279 | 0 | gx_device_copy_color_procs((gx_device *)pdev, target); |
280 | 0 | pdev->cached_colors = target->cached_colors; |
281 | 0 | pdev->graphics_type_tag = target->graphics_type_tag; /* initialize to same as target */ |
282 | 0 | } |
283 | 0 | if (pdev->color_info.depth == 1) { |
284 | 0 | gx_color_value cv[3]; |
285 | |
|
286 | 0 | cv[0] = cv[1] = cv[2] = 0; |
287 | 0 | gdev_mem_mono_set_inverted(pdev, (target == NULL || |
288 | 0 | (*dev_proc(pdev, encode_color))((gx_device *)pdev, cv) != 0)); |
289 | 0 | } |
290 | 0 | check_device_separable((gx_device *)pdev); |
291 | 0 | gx_device_fill_in_procs((gx_device *)pdev); |
292 | 0 | pdev->band_y = 0; |
293 | 0 | *ppdev = pdev; |
294 | 0 | return 0; |
295 | 0 | } |
296 | | |
297 | | /* Make a monobit memory device using copydevice */ |
298 | | int |
299 | | gs_make_mem_mono_device_with_copydevice(gx_device_memory ** ppdev, gs_memory_t * mem, |
300 | | gx_device * target) |
301 | 0 | { |
302 | 0 | int code; |
303 | 0 | gx_device_memory *pdev; |
304 | |
|
305 | 0 | if (mem == NULL) |
306 | 0 | return -1; |
307 | | |
308 | 0 | code = gs_copydevice((gx_device **)&pdev, |
309 | 0 | (const gx_device *)&mem_mono_device, |
310 | 0 | mem); |
311 | 0 | if (code < 0) |
312 | 0 | return code; |
313 | | |
314 | 0 | set_dev_proc(pdev, get_page_device, gx_default_get_page_device); |
315 | 0 | gx_device_set_target((gx_device_forward *)pdev, target); |
316 | | /* Should this be forwarding, monochrome profile, or not set? MJV. */ |
317 | 0 | set_dev_proc(pdev, get_profile, gx_forward_get_profile); |
318 | |
|
319 | 0 | gdev_mem_mono_set_inverted(pdev, true); |
320 | 0 | check_device_separable((gx_device *)pdev); |
321 | 0 | gx_device_fill_in_procs((gx_device *)pdev); |
322 | 0 | *ppdev = pdev; |
323 | 0 | return 0; |
324 | 0 | } |
325 | | |
326 | | /* Make a monobit memory device. This is never a page device. */ |
327 | | /* Note that white=0, black=1. */ |
328 | | void |
329 | | gs_make_mem_mono_device(gx_device_memory * dev, gs_memory_t * mem, |
330 | | gx_device * target) |
331 | 13.0M | { |
332 | | /* Can never fail */ |
333 | 13.0M | (void)gx_device_init((gx_device *)dev, |
334 | 13.0M | (const gx_device *)&mem_mono_device, |
335 | 13.0M | mem, true); |
336 | 13.0M | set_dev_proc(dev, get_page_device, gx_default_get_page_device); |
337 | 13.0M | gx_device_set_target((gx_device_forward *)dev, target); |
338 | 13.0M | dev->raster = gx_device_raster((gx_device *)dev, 1); |
339 | 13.0M | gdev_mem_mono_set_inverted(dev, true); |
340 | 13.0M | check_device_separable((gx_device *)dev); |
341 | 13.0M | gx_device_fill_in_procs((gx_device *)dev); |
342 | | /* Should this be forwarding, monochrome profile, or not set? MJV */ |
343 | 13.0M | set_dev_proc(dev, get_profile, gx_forward_get_profile); |
344 | 13.0M | set_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag); |
345 | 13.0M | set_dev_proc(dev, dev_spec_op, mem_spec_op); |
346 | 13.0M | dev->owner = target; |
347 | | /* initialize to same tag as target */ |
348 | 13.0M | dev->graphics_type_tag = target ? target->graphics_type_tag : GS_UNKNOWN_TAG; |
349 | 13.0M | } |
350 | | |
351 | | /* Define whether a monobit memory device is inverted (black=1). */ |
352 | | void |
353 | | gdev_mem_mono_set_inverted(gx_device_memory * dev, bool black_is_1) |
354 | 62.4M | { |
355 | 62.4M | if (black_is_1) |
356 | 46.4M | dev->palette = mem_mono_b_w_palette; |
357 | 16.0M | else |
358 | 16.0M | dev->palette = mem_mono_w_b_palette; |
359 | 62.4M | } |
360 | | |
361 | | /* |
362 | | * Compute the size of the bitmap storage, including the space for the scan |
363 | | * line pointer table. Note that scan lines are padded to a multiple of |
364 | | * align_bitmap_mod bytes, and additional padding may be needed if the |
365 | | * pointer table must be aligned to an even larger modulus. |
366 | | * |
367 | | * The computation for planar devices is a little messier. Each plane |
368 | | * must pad its scan lines, and then we must pad again for the pointer |
369 | | * tables (one table per plane). |
370 | | * |
371 | | * Return VMerror if the size exceeds max size_t |
372 | | */ |
373 | | int |
374 | | gdev_mem_bits_size(const gx_device_memory * dev, int width, int height, size_t *psize) |
375 | 23.6M | { |
376 | 23.6M | int num_planes; |
377 | 23.6M | gx_render_plane_t plane1; |
378 | 23.6M | const gx_render_plane_t *planes; |
379 | 23.6M | size_t size, alignment = bitmap_raster_pad_align(1, dev->pad, dev->log2_align_mod); |
380 | 23.6M | int pi; |
381 | | |
382 | 23.6M | if (dev->num_planar_planes > 1) { |
383 | 1.20M | num_planes = dev->num_planar_planes; |
384 | 1.20M | planes = dev->planes; |
385 | 1.20M | } else |
386 | 22.4M | planes = &plane1, plane1.depth = dev->color_info.depth, num_planes = 1; |
387 | 56.9M | for (size = 0, pi = 0; pi < num_planes; ++pi) { |
388 | 33.3M | size_t raster = bitmap_raster_pad_align((size_t)width * planes[pi].depth, dev->pad, dev->log2_align_mod); |
389 | 33.3M | if ((planes[pi].depth && width > (SIZE_MAX - alignment) / planes[pi].depth) || raster > SIZE_MAX - size) |
390 | 0 | return_error(gs_error_VMerror); |
391 | 33.3M | size += raster; |
392 | 33.3M | } |
393 | 23.6M | if (height != 0) |
394 | 23.6M | if (size > (SIZE_MAX - ARCH_ALIGN_PTR_MOD) / (ulong)height) |
395 | 0 | return_error(gs_error_VMerror); |
396 | 23.6M | size = ROUND_UP(size * height, ARCH_ALIGN_PTR_MOD); |
397 | 23.6M | if (dev->log2_align_mod > log2_align_bitmap_mod) |
398 | 0 | size += 1<<dev->log2_align_mod; |
399 | 23.6M | *psize = size; |
400 | 23.6M | return 0; |
401 | 23.6M | } |
402 | | size_t |
403 | | gdev_mem_line_ptrs_size(const gx_device_memory * dev, int width, int height) |
404 | 15.8M | { |
405 | 15.8M | int num_planes = 1; |
406 | 15.8M | if (dev->num_planar_planes > 1) |
407 | 938k | num_planes = dev->num_planar_planes; |
408 | 15.8M | return (size_t)height * sizeof(byte *) * num_planes; |
409 | 15.8M | } |
410 | | int |
411 | | gdev_mem_data_size(const gx_device_memory * dev, int width, int height, size_t *psize) |
412 | 15.5M | { |
413 | 15.5M | size_t bits_size; |
414 | 15.5M | size_t line_ptrs_size = gdev_mem_line_ptrs_size(dev, width, height); |
415 | | |
416 | 15.5M | if (gdev_mem_bits_size(dev, width, height, &bits_size) < 0 || |
417 | 15.5M | bits_size > SIZE_MAX - line_ptrs_size) |
418 | 0 | return_error(gs_error_VMerror); |
419 | 15.5M | *psize = bits_size + line_ptrs_size; |
420 | 15.5M | return 0; |
421 | 15.5M | } |
422 | | /* |
423 | | * Do the inverse computation: given a width (in pixels) and a buffer size, |
424 | | * compute the maximum height. |
425 | | */ |
426 | | int |
427 | | gdev_mem_max_height(const gx_device_memory * dev, int width, size_t size, |
428 | | bool page_uses_transparency) |
429 | 1.35M | { |
430 | 1.35M | int height; |
431 | 1.35M | size_t max_height; |
432 | 1.35M | size_t data_size = 0; |
433 | 1.35M | bool deep = device_is_deep((const gx_device *)dev); |
434 | | |
435 | 1.35M | if (page_uses_transparency) { |
436 | | /* |
437 | | * If the device is using PDF 1.4 transparency then we will need to |
438 | | * also allocate image buffers for doing the blending operations. |
439 | | * We can only estimate the space requirements. However since it |
440 | | * is only an estimate, we may exceed our desired buffer space while |
441 | | * processing the file. |
442 | | */ |
443 | | /* FIXME: For a planar device, is dev->color_info.num_components 1 ? Otherwise, aren't we |
444 | | * calculating this too large? */ |
445 | 96.6k | max_height = size / (bitmap_raster_pad_align(width |
446 | 96.6k | * dev->color_info.depth + ESTIMATED_PDF14_ROW_SPACE(width, dev->color_info.num_components, deep ? 16 : 8), |
447 | 96.6k | dev->pad, dev->log2_align_mod) + sizeof(byte *) * (dev->num_planar_planes ? dev->num_planar_planes : 1)); |
448 | 96.6k | height = (int)min(max_height, max_int); |
449 | 1.25M | } else { |
450 | | /* For non PDF 1.4 transparency, we can do an exact calculation */ |
451 | 1.25M | max_height = size / |
452 | 1.25M | (bitmap_raster_pad_align(width * dev->color_info.depth, dev->pad, dev->log2_align_mod) + |
453 | 1.25M | sizeof(byte *) * (dev->num_planar_planes ? dev->num_planar_planes : 1)); |
454 | 1.25M | height = (int)min(max_height, max_int); |
455 | | /* |
456 | | * Because of alignment rounding, the just-computed height might |
457 | | * be too large by a small amount. Adjust it the easy way. |
458 | | */ |
459 | 1.61M | do { |
460 | 1.61M | gdev_mem_data_size(dev, width, height, &data_size); |
461 | 1.61M | if (data_size <= size) |
462 | 1.25M | break; |
463 | 362k | --height; |
464 | 362k | } while (data_size > size); |
465 | 1.25M | } |
466 | 0 | return height; |
467 | 1.35M | } |
468 | | |
469 | | /* Open a memory device, allocating the data area if appropriate, */ |
470 | | /* and create the scan line table. */ |
471 | | int |
472 | | mem_open(gx_device * dev) |
473 | 6.43M | { |
474 | 6.43M | gx_device_memory *const mdev = (gx_device_memory *)dev; |
475 | | |
476 | | /* Check that we aren't trying to open a planar device as chunky. */ |
477 | 6.43M | if (mdev->num_planar_planes > 1) |
478 | 0 | return_error(gs_error_rangecheck); |
479 | 6.43M | return gdev_mem_open_scan_lines(mdev, dev->height); |
480 | 6.43M | } |
481 | | int |
482 | | gdev_mem_open_scan_lines(gx_device_memory *mdev, int setup_height) |
483 | 6.43M | { |
484 | 6.43M | return gdev_mem_open_scan_lines_interleaved(mdev, setup_height, 0); |
485 | 6.43M | } |
486 | | int |
487 | | gdev_mem_open_scan_lines_interleaved(gx_device_memory *mdev, |
488 | | int setup_height, |
489 | | int interleaved) |
490 | 6.43M | { |
491 | 6.43M | bool line_pointers_adjacent = true; |
492 | 6.43M | size_t size; |
493 | | |
494 | 6.43M | if (setup_height < 0 || setup_height > mdev->height) |
495 | 0 | return_error(gs_error_rangecheck); |
496 | 6.43M | if (mdev->bitmap_memory != NULL) { |
497 | 31.0k | int align; |
498 | | /* Allocate the data now. */ |
499 | 31.0k | if (gdev_mem_bitmap_size(mdev, &size) < 0) |
500 | 0 | return_error(gs_error_VMerror); |
501 | | |
502 | 31.0k | mdev->base = gs_alloc_bytes(mdev->bitmap_memory, size, |
503 | 31.0k | "mem_open"); |
504 | 31.0k | if (mdev->base == NULL) |
505 | 0 | return_error(gs_error_VMerror); |
506 | 31.0k | #ifdef PACIFY_VALGRIND |
507 | | /* If we end up writing the bitmap to the clist, we can get valgrind errors |
508 | | * because we write and read the padding at the end of each raster line. |
509 | | * Easiest to set the entire block. |
510 | | */ |
511 | 31.0k | memset(mdev->base, 0x00, size); |
512 | 31.0k | #endif |
513 | 31.0k | align = 1<<mdev->log2_align_mod; |
514 | 31.0k | mdev->base += (-(int)(intptr_t)mdev->base) & (align-1); |
515 | 31.0k | mdev->foreign_bits = false; |
516 | 6.40M | } else if (mdev->line_pointer_memory != NULL) { |
517 | | /* Allocate the line pointers now. */ |
518 | |
|
519 | 0 | mdev->line_ptrs = (byte **) |
520 | 0 | gs_alloc_byte_array(mdev->line_pointer_memory, mdev->height, |
521 | 0 | sizeof(byte *) * (mdev->num_planar_planes ? mdev->num_planar_planes : 1), |
522 | 0 | "gdev_mem_open_scan_lines"); |
523 | 0 | if (mdev->line_ptrs == NULL) |
524 | 0 | return_error(gs_error_VMerror); |
525 | 0 | mdev->foreign_line_pointers = false; |
526 | 0 | line_pointers_adjacent = false; |
527 | 0 | } |
528 | 6.43M | if (line_pointers_adjacent) { |
529 | 6.43M | int code; |
530 | | |
531 | 6.43M | if (mdev->base == NULL) |
532 | 0 | return_error(gs_error_rangecheck); |
533 | | |
534 | 6.43M | code = gdev_mem_bits_size(mdev, mdev->width, mdev->height, &size); |
535 | 6.43M | if (code < 0) |
536 | 0 | return code; |
537 | | |
538 | 6.43M | mdev->line_ptrs = (byte **)(mdev->base + size); |
539 | 6.43M | } |
540 | 6.43M | mdev->raster = gx_device_raster((gx_device *)mdev, 1); |
541 | 6.43M | return gdev_mem_set_line_ptrs_interleaved(mdev, NULL, 0, NULL, |
542 | 6.43M | setup_height, |
543 | 6.43M | interleaved); |
544 | 6.43M | } |
545 | | /* |
546 | | * Set up the scan line pointers of a memory device. |
547 | | * See gxdevmem.h for the detailed specification. |
548 | | * Sets or uses line_ptrs, base, raster; uses width, color_info.depth, |
549 | | * num_planes, plane_depths, plane_depth. |
550 | | */ |
551 | | int |
552 | | gdev_mem_set_line_ptrs(gx_device_memory *mdev, byte *base, int raster, |
553 | | byte **line_ptrs, int setup_height) |
554 | 163M | { |
555 | 163M | return gdev_mem_set_line_ptrs_interleaved(mdev, base, raster, line_ptrs, setup_height, 0); |
556 | 163M | } |
557 | | int |
558 | | gdev_mem_set_line_ptrs_interleaved(gx_device_memory * mdev, byte * base, |
559 | | int raster, byte **line_ptrs, |
560 | | int setup_height, int interleaved) |
561 | 169M | { |
562 | 169M | int num_planes = (mdev->num_planar_planes ? mdev->num_planar_planes : 0); |
563 | 169M | byte **pline; |
564 | 169M | byte *data; |
565 | 169M | int pi; |
566 | 169M | int plane_raster; |
567 | | |
568 | | /* If we are supplied with line_ptrs, then assume that we don't have |
569 | | * any already, and take them on. */ |
570 | 169M | if (line_ptrs) |
571 | 163M | mdev->line_ptrs = line_ptrs; |
572 | 169M | pline = mdev->line_ptrs; |
573 | | |
574 | | /* If we are supplied a base, then we are supplied a raster. Assume that |
575 | | * we don't have any buffer already, and take these on. Assume that the |
576 | | * base has been allocated with sufficient padding to allow for any |
577 | | * alignment required. */ |
578 | 169M | if (base == NULL) { |
579 | 6.43M | base = mdev->base; |
580 | 6.43M | raster = mdev->raster; |
581 | 163M | } else { |
582 | 163M | mdev->base = base; |
583 | 163M | mdev->raster = raster; |
584 | 163M | } |
585 | | |
586 | | /* Now, pad and align as required. */ |
587 | 169M | if (mdev->log2_align_mod > log2_align_bitmap_mod) { |
588 | 0 | int align = 1<<mdev->log2_align_mod; |
589 | 0 | align = (-(int)(intptr_t)base) & (align-1); |
590 | 0 | data = base + align; |
591 | 169M | } else { |
592 | 169M | data = mdev->base; |
593 | 169M | } |
594 | | |
595 | 169M | if (num_planes) { |
596 | 7.52M | if (base && !mdev->plane_depth) |
597 | 0 | return_error(gs_error_rangecheck); |
598 | 162M | } else { |
599 | 162M | num_planes = 1; |
600 | 162M | } |
601 | | |
602 | 169M | if (interleaved) |
603 | 0 | plane_raster = raster, raster *= num_planes; |
604 | 169M | else |
605 | 169M | plane_raster = raster * mdev->height; |
606 | 369M | for (pi = 0; pi < num_planes; ++pi) { |
607 | 199M | byte **pptr = pline; |
608 | 199M | byte **pend = pptr + setup_height; |
609 | 199M | byte *scan_line = data; |
610 | | |
611 | 873M | while (pptr < pend) { |
612 | 673M | *pptr++ = scan_line; |
613 | 673M | scan_line += raster; |
614 | 673M | } |
615 | 199M | data += plane_raster; |
616 | 199M | pline += setup_height; /* not mdev->height, see gxdevmem.h */ |
617 | 199M | } |
618 | | |
619 | 169M | return 0; |
620 | 169M | } |
621 | | |
622 | | /* Return the initial transformation matrix */ |
623 | | void |
624 | | mem_get_initial_matrix(gx_device * dev, gs_matrix * pmat) |
625 | 1.65M | { |
626 | 1.65M | gx_device_memory * const mdev = (gx_device_memory *)dev; |
627 | | |
628 | 1.65M | pmat->xx = mdev->initial_matrix.xx; |
629 | 1.65M | pmat->xy = mdev->initial_matrix.xy; |
630 | 1.65M | pmat->yx = mdev->initial_matrix.yx; |
631 | 1.65M | pmat->yy = mdev->initial_matrix.yy; |
632 | 1.65M | pmat->tx = mdev->initial_matrix.tx; |
633 | 1.65M | pmat->ty = mdev->initial_matrix.ty; |
634 | 1.65M | } |
635 | | |
636 | | /* Close a memory device, freeing the data area if appropriate. */ |
637 | | int |
638 | | mem_close(gx_device * dev) |
639 | 166M | { |
640 | 166M | gx_device_memory * const mdev = (gx_device_memory *)dev; |
641 | | |
642 | 166M | if (mdev->bitmap_memory != 0) { |
643 | 6.43k | gs_free_object(mdev->bitmap_memory, mdev->base, "mem_close"); |
644 | | /* |
645 | | * The following assignment is strictly for the benefit of one |
646 | | * client that is sloppy about using is_open properly. |
647 | | */ |
648 | 6.43k | mdev->base = 0; |
649 | 166M | } else if (mdev->line_pointer_memory != 0) { |
650 | 0 | gs_free_object(mdev->line_pointer_memory, mdev->line_ptrs, |
651 | 0 | "mem_close"); |
652 | 0 | mdev->line_ptrs = 0; /* ibid. */ |
653 | 0 | } |
654 | 166M | return 0; |
655 | 166M | } |
656 | | |
657 | | /* Memory devices shouldn't allow their dimensions to change */ |
658 | | static int |
659 | | mem_put_params(gx_device * dev, gs_param_list * plist) |
660 | 6 | { |
661 | 6 | int code; |
662 | 6 | int width = dev->width, height = dev->height; |
663 | 6 | float xres = dev->HWResolution[0], yres = dev->HWResolution[1]; |
664 | 6 | float medw = dev->MediaSize[0], medh = dev->MediaSize[1]; |
665 | | |
666 | 6 | code = gx_default_put_params(dev, plist); |
667 | | |
668 | 6 | dev->width = width; |
669 | 6 | dev->height = height; |
670 | 6 | dev->HWResolution[0] = xres; |
671 | 6 | dev->HWResolution[1] = yres; |
672 | 6 | dev->MediaSize[0] = medw; |
673 | 6 | dev->MediaSize[1] = medh; |
674 | | |
675 | 6 | return code; |
676 | 6 | } |
677 | | |
678 | | /* Copy bits to a client. */ |
679 | | #undef chunk |
680 | | #define chunk byte |
681 | | int |
682 | | mem_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, |
683 | | gs_get_bits_params_t * params) |
684 | 152M | { |
685 | 152M | gx_device_memory * const mdev = (gx_device_memory *)dev; |
686 | 152M | gs_get_bits_options_t options = params->options; |
687 | 152M | int x = prect->p.x, w = prect->q.x - x, y = prect->p.y, h = prect->q.y - y; |
688 | | |
689 | 152M | if (options == 0) { |
690 | 0 | params->options = |
691 | 0 | (GB_ALIGN_STANDARD | GB_ALIGN_ANY) | |
692 | 0 | (GB_RETURN_COPY | GB_RETURN_POINTER) | |
693 | 0 | (GB_OFFSET_0 | GB_OFFSET_SPECIFIED | GB_OFFSET_ANY) | |
694 | 0 | (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED | GB_RASTER_ANY) | |
695 | 0 | GB_PACKING_CHUNKY | GB_COLORS_NATIVE | GB_ALPHA_NONE; |
696 | 0 | return_error(gs_error_rangecheck); |
697 | 0 | } |
698 | 152M | if (mdev->line_ptrs == NULL) |
699 | 0 | return_error(gs_error_rangecheck); |
700 | 152M | if ((w <= 0) | (h <= 0)) { |
701 | 0 | if ((w | h) < 0) |
702 | 0 | return_error(gs_error_rangecheck); |
703 | 0 | return 0; |
704 | 0 | } |
705 | 152M | if (x < 0 || w > dev->width - x || |
706 | 152M | y < 0 || h > dev->height - y |
707 | 152M | ) |
708 | 0 | return_error(gs_error_rangecheck); |
709 | 152M | { |
710 | 152M | gs_get_bits_params_t copy_params; |
711 | 152M | byte **base = &scan_line_base(mdev, y); |
712 | 152M | int code; |
713 | | |
714 | 152M | copy_params.options = |
715 | 152M | GB_COLORS_NATIVE | GB_PACKING_CHUNKY | GB_ALPHA_NONE | |
716 | 152M | (mdev->raster == |
717 | 152M | bitmap_raster(mdev->width * mdev->color_info.depth) ? |
718 | 152M | GB_RASTER_STANDARD : GB_RASTER_SPECIFIED); |
719 | 152M | copy_params.raster = mdev->raster; |
720 | 152M | code = gx_get_bits_return_pointer(dev, x, h, params, |
721 | 152M | ©_params, base); |
722 | 152M | if (code >= 0) |
723 | 111M | return code; |
724 | 41.4M | return gx_get_bits_copy(dev, x, w, h, params, ©_params, *base, |
725 | 41.4M | gx_device_raster(dev, true)); |
726 | 152M | } |
727 | 152M | } |
728 | | |
729 | | #if !ARCH_IS_BIG_ENDIAN |
730 | | |
731 | | /* |
732 | | * Swap byte order in a rectangular subset of a bitmap. If store = true, |
733 | | * assume the rectangle will be overwritten, so don't swap any bytes where |
734 | | * it doesn't matter. The caller has already done a fit_fill or fit_copy. |
735 | | * Note that the coordinates are specified in bits, not in terms of the |
736 | | * actual device depth. |
737 | | */ |
738 | | void |
739 | | mem_swap_byte_rect(byte * base, size_t raster, int x, int w, int h, bool store) |
740 | 0 | { |
741 | 0 | int xbit = x & 31; |
742 | |
|
743 | 0 | if (store) { |
744 | 0 | if (xbit + w > 64) { /* Operation spans multiple words. */ |
745 | | /* Just swap the words at the left and right edges. */ |
746 | 0 | if (xbit != 0) |
747 | 0 | mem_swap_byte_rect(base, raster, x, 1, h, false); |
748 | 0 | x += w - 1; |
749 | 0 | xbit = x & 31; |
750 | 0 | if (xbit == 31) |
751 | 0 | return; |
752 | 0 | w = 1; |
753 | 0 | } |
754 | 0 | } |
755 | | /* Swap the entire rectangle (or what's left of it). */ |
756 | 0 | { |
757 | 0 | byte *row = base + ((x >> 5) << 2); |
758 | 0 | int nw = (xbit + w + 31) >> 5; |
759 | 0 | int ny; |
760 | |
|
761 | 0 | for (ny = h; ny > 0; row += raster, --ny) { |
762 | 0 | int nx = nw; |
763 | 0 | bits32 *pw = (bits32 *) row; |
764 | |
|
765 | 0 | do { |
766 | 0 | bits32 v = *pw; |
767 | |
|
768 | 0 | *pw++ = (v >> 24) + ((v >> 8) & 0xff00) + |
769 | 0 | ((v & 0xff00) << 8) + (v << 24); |
770 | 0 | } |
771 | 0 | while (--nx); |
772 | 0 | } |
773 | 0 | } |
774 | 0 | } |
775 | | |
776 | | /* Copy a word-oriented rectangle to the client, swapping bytes as needed. */ |
777 | | int |
778 | | mem_word_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, |
779 | | gs_get_bits_params_t * params) |
780 | 0 | { |
781 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
782 | 0 | byte *src; |
783 | 0 | size_t dev_raster = gx_device_raster(dev, 1); |
784 | 0 | int x = prect->p.x; |
785 | 0 | int w = prect->q.x - x; |
786 | 0 | int y = prect->p.y; |
787 | 0 | int h = prect->q.y - y; |
788 | 0 | int bit_x, bit_w; |
789 | 0 | int code; |
790 | |
|
791 | 0 | fit_fill_xywh(dev, x, y, w, h); |
792 | 0 | if (w <= 0 || h <= 0) { |
793 | | /* |
794 | | * It's easiest to just keep going with an empty rectangle. |
795 | | * We pass the original rectangle to mem_get_bits_rectangle. |
796 | | */ |
797 | 0 | x = y = w = h = 0; |
798 | 0 | } |
799 | 0 | bit_x = x * dev->color_info.depth; |
800 | 0 | bit_w = w * dev->color_info.depth; |
801 | |
|
802 | 0 | if(mdev->line_ptrs == NULL) |
803 | 0 | return_error(gs_error_rangecheck); |
804 | | |
805 | 0 | src = scan_line_base(mdev, y); |
806 | 0 | mem_swap_byte_rect(src, dev_raster, bit_x, bit_w, h, false); |
807 | 0 | code = mem_get_bits_rectangle(dev, prect, params); |
808 | 0 | mem_swap_byte_rect(src, dev_raster, bit_x, bit_w, h, false); |
809 | 0 | return code; |
810 | 0 | } |
811 | | |
812 | | #endif /* !ARCH_IS_BIG_ENDIAN */ |
813 | | |
814 | | /* Map a r-g-b color to a color index for a mapped color memory device */ |
815 | | /* (2, 4, or 8 bits per pixel.) */ |
816 | | /* This requires searching the palette. */ |
817 | | gx_color_index |
818 | | mem_mapped_map_rgb_color(gx_device * dev, const gx_color_value cv[]) |
819 | 0 | { |
820 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
821 | 0 | byte br = gx_color_value_to_byte(cv[0]); |
822 | |
|
823 | 0 | register const byte *pptr = mdev->palette.data; |
824 | 0 | int cnt = mdev->palette.size; |
825 | 0 | const byte *which = 0; /* initialized only to pacify gcc */ |
826 | 0 | int best = 256 * 3; |
827 | |
|
828 | 0 | if (mdev->color_info.num_components != 1) { |
829 | | /* not 1 component, assume three */ |
830 | | /* The comparison is rather simplistic, treating differences in */ |
831 | | /* all components as equal. Better choices would be 'distance' */ |
832 | | /* in HLS space or other, but these would be much slower. */ |
833 | | /* At least exact matches will be found. */ |
834 | 0 | byte bg = gx_color_value_to_byte(cv[1]); |
835 | 0 | byte bb = gx_color_value_to_byte(cv[2]); |
836 | |
|
837 | 0 | while ((cnt -= 3) >= 0) { |
838 | 0 | register int diff = *pptr - br; |
839 | |
|
840 | 0 | if (diff < 0) |
841 | 0 | diff = -diff; |
842 | 0 | if (diff < best) { /* quick rejection */ |
843 | 0 | int dg = pptr[1] - bg; |
844 | |
|
845 | 0 | if (dg < 0) |
846 | 0 | dg = -dg; |
847 | 0 | if ((diff += dg) < best) { /* quick rejection */ |
848 | 0 | int db = pptr[2] - bb; |
849 | |
|
850 | 0 | if (db < 0) |
851 | 0 | db = -db; |
852 | 0 | if ((diff += db) < best) |
853 | 0 | which = pptr, best = diff; |
854 | 0 | } |
855 | 0 | } |
856 | 0 | if (diff == 0) /* can't get any better than 0 diff */ |
857 | 0 | break; |
858 | 0 | pptr += 3; |
859 | 0 | } |
860 | 0 | } else { |
861 | | /* Gray scale conversion. The palette is made of three equal */ |
862 | | /* components, so this case is simpler. */ |
863 | 0 | while ((cnt -= 3) >= 0) { |
864 | 0 | register int diff = *pptr - br; |
865 | |
|
866 | 0 | if (diff < 0) |
867 | 0 | diff = -diff; |
868 | 0 | if (diff < best) { /* quick rejection */ |
869 | 0 | which = pptr, best = diff; |
870 | 0 | } |
871 | 0 | if (diff == 0) |
872 | 0 | break; |
873 | 0 | pptr += 3; |
874 | 0 | } |
875 | 0 | } |
876 | 0 | return (gx_color_index) ((which - mdev->palette.data) / 3); |
877 | 0 | } |
878 | | |
879 | | /* Map a color index to a r-g-b color for a mapped color memory device. */ |
880 | | int |
881 | | mem_mapped_map_color_rgb(gx_device * dev, gx_color_index color, |
882 | | gx_color_value prgb[3]) |
883 | 0 | { |
884 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
885 | 0 | const byte *pptr = mdev->palette.data; |
886 | |
|
887 | 0 | if (pptr == NULL) { |
888 | 0 | color = color * gx_max_color_value / ((1<<mdev->color_info.depth)-1); |
889 | 0 | prgb[0] = color; |
890 | 0 | prgb[1] = color; |
891 | 0 | prgb[2] = color; |
892 | 0 | } else { |
893 | 0 | pptr += (int)color * 3; |
894 | |
|
895 | 0 | prgb[0] = gx_color_value_from_byte(pptr[0]); |
896 | 0 | prgb[1] = gx_color_value_from_byte(pptr[1]); |
897 | 0 | prgb[2] = gx_color_value_from_byte(pptr[2]); |
898 | 0 | } |
899 | 0 | return 0; |
900 | 0 | } |
901 | | |
902 | | /* |
903 | | * Implement draw_thin_line using a distinguished procedure that serves |
904 | | * as the common marker for all memory devices. |
905 | | */ |
906 | | int |
907 | | mem_draw_thin_line(gx_device *dev, fixed fx0, fixed fy0, fixed fx1, fixed fy1, |
908 | | const gx_drawing_color *pdcolor, |
909 | | gs_logical_operation_t lop, |
910 | | fixed adjustx, fixed adjusty) |
911 | 12.2M | { |
912 | 12.2M | return gx_default_draw_thin_line(dev, fx0, fy0, fx1, fy1, pdcolor, lop, |
913 | 12.2M | adjustx, adjusty); |
914 | 12.2M | } |
915 | | |
916 | | void mem_initialize_device_procs(gx_device *dev) |
917 | 174M | { |
918 | 174M | set_dev_proc(dev, get_initial_matrix, mem_get_initial_matrix); |
919 | 174M | set_dev_proc(dev, sync_output, gx_default_sync_output); |
920 | 174M | set_dev_proc(dev, output_page, gx_default_output_page); |
921 | 174M | set_dev_proc(dev, close_device, mem_close); |
922 | 174M | set_dev_proc(dev, get_params, gx_default_get_params); |
923 | 174M | set_dev_proc(dev, put_params, mem_put_params); |
924 | 174M | set_dev_proc(dev, get_page_device, gx_forward_get_page_device); |
925 | 174M | set_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits); |
926 | 174M | set_dev_proc(dev, fill_path, gx_default_fill_path); |
927 | 174M | set_dev_proc(dev, stroke_path, gx_default_stroke_path); |
928 | 174M | set_dev_proc(dev, fill_mask, gx_default_fill_mask); |
929 | 174M | set_dev_proc(dev, fill_trapezoid, gx_default_fill_trapezoid); |
930 | 174M | set_dev_proc(dev, fill_parallelogram, gx_default_fill_parallelogram); |
931 | 174M | set_dev_proc(dev, fill_triangle, gx_default_fill_triangle); |
932 | 174M | set_dev_proc(dev, draw_thin_line, mem_draw_thin_line); |
933 | 174M | set_dev_proc(dev, get_clipping_box, gx_default_get_clipping_box); |
934 | 174M | set_dev_proc(dev, begin_typed_image, gx_default_begin_typed_image); |
935 | 174M | set_dev_proc(dev, composite, gx_default_composite); |
936 | 174M | set_dev_proc(dev, get_hardware_params, gx_default_get_hardware_params); |
937 | 174M | set_dev_proc(dev, text_begin, gx_default_text_begin); |
938 | 174M | set_dev_proc(dev, transform_pixel_region, mem_transform_pixel_region); |
939 | | |
940 | | /* Defaults that may well get overridden. */ |
941 | 174M | set_dev_proc(dev, open_device, mem_open); |
942 | 174M | set_dev_proc(dev, copy_alpha, gx_default_copy_alpha); |
943 | 174M | set_dev_proc(dev, map_cmyk_color, gx_default_map_cmyk_color); |
944 | 174M | set_dev_proc(dev, strip_tile_rectangle, gx_default_strip_tile_rectangle); |
945 | 174M | set_dev_proc(dev, get_bits_rectangle, mem_get_bits_rectangle); |
946 | 174M | } |
947 | | |
948 | | void mem_dev_initialize_device_procs(gx_device *dev) |
949 | 174M | { |
950 | 174M | int depth = dev->color_info.depth; |
951 | 174M | const gdev_mem_functions *fns; |
952 | | |
953 | 174M | if (dev->num_planar_planes > 1) |
954 | 0 | depth /= dev->num_planar_planes; |
955 | 174M | fns = gdev_mem_functions_for_bits(depth); |
956 | | |
957 | 174M | mem_initialize_device_procs(dev); |
958 | | |
959 | 174M | set_dev_proc(dev, map_rgb_color, fns->map_rgb_color); |
960 | 174M | set_dev_proc(dev, map_color_rgb, fns->map_color_rgb); |
961 | 174M | set_dev_proc(dev, fill_rectangle, fns->fill_rectangle); |
962 | 174M | set_dev_proc(dev, copy_mono, fns->copy_mono); |
963 | 174M | set_dev_proc(dev, copy_color, fns->copy_color); |
964 | 174M | set_dev_proc(dev, copy_alpha, fns->copy_alpha); |
965 | 174M | set_dev_proc(dev, strip_copy_rop2, fns->strip_copy_rop2); |
966 | 174M | set_dev_proc(dev, strip_tile_rectangle, fns->strip_tile_rectangle); |
967 | 174M | } |
968 | | |
969 | | void mem_word_dev_initialize_device_procs(gx_device *dev) |
970 | 0 | { |
971 | 0 | const gdev_mem_functions *fns = |
972 | 0 | gdev_mem_word_functions_for_bits(dev->color_info.depth); |
973 | |
|
974 | 0 | mem_initialize_device_procs(dev); |
975 | |
|
976 | 0 | set_dev_proc(dev, map_rgb_color, fns->map_rgb_color); |
977 | 0 | set_dev_proc(dev, map_color_rgb, fns->map_color_rgb); |
978 | 0 | set_dev_proc(dev, fill_rectangle, fns->fill_rectangle); |
979 | 0 | set_dev_proc(dev, copy_mono, fns->copy_mono); |
980 | 0 | set_dev_proc(dev, copy_color, fns->copy_color); |
981 | 0 | set_dev_proc(dev, copy_alpha, fns->copy_alpha); |
982 | 0 | set_dev_proc(dev, strip_copy_rop2, fns->strip_copy_rop2); |
983 | 0 | set_dev_proc(dev, strip_tile_rectangle, fns->strip_tile_rectangle); |
984 | 0 | } |