1 /* Copyright (C) 1989, 1995, 1996, 1997, 1998, 2000 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16
17 */
18
19 /*$Id: gximono.c,v 1.2.6.1.2.1 2003/01/17 00:49:04 giles Exp $ */
20 /* General mono-component image rendering */
21 #include "gx.h"
22 #include "memory_.h"
23 #include "gpcheck.h"
24 #include "gserrors.h"
25 #include "gxfixed.h"
26 #include "gxarith.h"
27 #include "gxmatrix.h"
28 #include "gsccolor.h"
29 #include "gspaint.h"
30 #include "gsutil.h"
31 #include "gxdevice.h"
32 #include "gxcmap.h"
33 #include "gxdcolor.h"
34 #include "gxistate.h"
35 #include "gxdevmem.h"
36 #include "gdevmem.h" /* for mem_mono_device */
37 #include "gxcpath.h"
38 #include "gximage.h"
39 #include "gzht.h"
40
41 /* ------ Strategy procedure ------ */
42
43 /* Check the prototype. */
44 iclass_proc(gs_image_class_3_mono);
45
46 private irender_proc(image_render_mono);
47 irender_proc_t
gs_image_class_3_mono(gx_image_enum * penum)48 gs_image_class_3_mono(gx_image_enum * penum)
49 {
50 if (penum->spp == 1) {
51 /*
52 * Use the slow loop for imagemask with a halftone or a non-default
53 * logical operation.
54 */
55 penum->slow_loop =
56 (penum->masked && !color_is_pure(&penum->icolor1)) ||
57 penum->use_rop;
58 /* We can bypass X clipping for portrait mono-component images. */
59 if (!(penum->slow_loop || penum->posture != image_portrait))
60 penum->clip_image &= ~(image_clip_xmin | image_clip_xmax);
61 if_debug0('b', "[b]render=mono\n");
62 /* Precompute values needed for rasterizing. */
63 penum->dxx =
64 float2fixed(penum->matrix.xx + fixed2float(fixed_epsilon) / 2);
65 /*
66 * Scale the mask colors to match the scaling of each sample to a
67 * full byte. Also, if black or white is transparent, reset icolor0
68 * or icolor1, which are used directly in the fast case loop.
69 */
70 if (penum->use_mask_color) {
71 gx_image_scale_mask_colors(penum, 0);
72 if (penum->mask_color.values[0] <= 0)
73 color_set_null(&penum->icolor0);
74 if (penum->mask_color.values[1] >= 255)
75 color_set_null(&penum->icolor1);
76 }
77 return image_render_mono;
78 }
79 return 0;
80 }
81
82 /* ------ Rendering procedure ------ */
83
84 /* Provide a fake map_gray procedure for the DevicePixel color space. */
85 private void
no_map_gray(frac pixel,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)86 no_map_gray(frac pixel, gx_device_color * pdc, const gs_imager_state * pis,
87 gx_device * dev, gs_color_select_t select)
88 {
89 color_set_pure(pdc, frac2byte(pixel));
90 }
91
92 /*
93 * Rendering procedure for general mono-component images, dealing with
94 * multiple bit-per-sample images, general transformations, arbitrary
95 * single-component color spaces (DeviceGray, DevicePixel, CIEBasedA,
96 * Separation, Indexed), and color masking. This procedure handles a
97 * single scan line.
98 */
99 private int
image_render_mono(gx_image_enum * penum,const byte * buffer,int data_x,uint w,int h,gx_device * dev)100 image_render_mono(gx_image_enum * penum, const byte * buffer, int data_x,
101 uint w, int h, gx_device * dev)
102 {
103 const gs_imager_state *pis = penum->pis;
104 gs_logical_operation_t lop = penum->log_op;
105 const bool masked = penum->masked;
106 const gs_color_space *pcs; /* only set for non-masks */
107 cmap_proc_gray((*map_gray)); /* ditto */
108 cs_proc_remap_color((*remap_color)); /* ditto */
109 gs_client_color cc;
110 gx_device_color *pdevc = &penum->icolor1; /* color for masking */
111 /*
112 * Make sure the cache setup matches the graphics state. Also determine
113 * whether all tiles fit in the cache. We may bypass the latter check
114 * for masked images with a pure color.
115 */
116 bool tiles_fit =
117 (pis && penum->device_color ? gx_check_tile_cache(pis) : false);
118 uint mask_base = penum->mask_color.values[0];
119 uint mask_limit =
120 (penum->use_mask_color ?
121 penum->mask_color.values[1] - mask_base + 1 : 0);
122 /*
123 * Free variables of IMAGE_SET_GRAY:
124 * Read: penum, pis, dev, tiles_fit, mask_base, mask_limit
125 * Set: pdevc, code, cc
126 */
127 #define IMAGE_SET_GRAY(sample_value)\
128 BEGIN\
129 pdevc = &penum->clues[sample_value].dev_color;\
130 if (!color_is_set(pdevc)) {\
131 if ((uint)(sample_value - mask_base) < mask_limit)\
132 color_set_null(pdevc);\
133 else if (penum->device_color)\
134 (*map_gray)(byte2frac(sample_value), pdevc, pis, dev, gs_color_select_source);\
135 else {\
136 decode_sample(sample_value, cc, 0);\
137 code = (*remap_color)(&cc, pcs, pdevc, pis, dev, gs_color_select_source);\
138 if (code < 0)\
139 goto err;\
140 }\
141 } else if (!color_is_pure(pdevc)) {\
142 if (!tiles_fit) {\
143 code = gx_color_load_select(pdevc, pis, dev, gs_color_select_source);\
144 if (code < 0)\
145 goto err;\
146 }\
147 }\
148 END
149 gx_dda_fixed_point next; /* (y not used in fast loop) */
150 gx_dda_step_fixed dxx2, dxx3, dxx4; /* (not used in all loops) */
151 const byte *psrc_initial = buffer + data_x;
152 const byte *psrc = psrc_initial;
153 const byte *rsrc = psrc; /* psrc at start of run */
154 const byte *endp = psrc + w;
155 const byte *stop = endp;
156 fixed xrun; /* x at start of run */
157 byte run; /* run value */
158 int htrun = (masked ? 255 : -2); /* halftone run value */
159 int code = 0;
160
161 if (h == 0)
162 return 0;
163 next = penum->dda.pixel0;
164 xrun = dda_current(next.x);
165 if (!masked) {
166 pcs = penum->pcs; /* (may not be set for masks) */
167 if (penum->device_color)
168 map_gray =
169 (gs_color_space_get_index(pcs) ==
170 gs_color_space_index_DeviceGray ?
171 gx_get_cmap_procs(pis, dev)->map_gray :
172 no_map_gray /*DevicePixel */ );
173 else
174 remap_color = pcs->type->remap_color;
175 }
176 run = *psrc;
177 /* Find the last transition in the input. */
178 {
179 byte last = stop[-1];
180
181 while (stop > psrc && stop[-1] == last)
182 --stop;
183 }
184 if (penum->slow_loop || penum->posture != image_portrait) {
185
186 /**************************************************************
187 * Slow case (skewed, rotated, or imagemask with a halftone). *
188 **************************************************************/
189
190 fixed yrun;
191 const fixed pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
192 const fixed pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
193 dev_proc_fill_parallelogram((*fill_pgram)) =
194 dev_proc(dev, fill_parallelogram);
195
196 #define xl dda_current(next.x)
197 #define ytf dda_current(next.y)
198 yrun = ytf;
199 if (masked) {
200
201 /**********************
202 * Slow case, masked. *
203 **********************/
204
205 pdevc = &penum->icolor1;
206 code = gx_color_load(pdevc, pis, dev);
207 if (code < 0)
208 return code;
209 if (stop <= psrc)
210 goto last;
211 if (penum->posture == image_portrait) {
212
213 /********************************
214 * Slow case, masked, portrait. *
215 ********************************/
216
217 /*
218 * We don't have to worry about the Y DDA, and the fill
219 * regions are rectangles. Calculate multiples of the DDA
220 * step.
221 */
222 fixed ax =
223 (penum->matrix.xx < 0 ? -penum->adjust : penum->adjust);
224 fixed ay =
225 (pdyy < 0 ? -penum->adjust : penum->adjust);
226 fixed dyy = pdyy + (ay << 1);
227
228 yrun -= ay;
229 dda_translate(next.x, -ax);
230 ax <<= 1;
231 dxx2 = next.x.step;
232 dda_step_add(dxx2, next.x.step);
233 dxx3 = dxx2;
234 dda_step_add(dxx3, next.x.step);
235 dxx4 = dxx3;
236 dda_step_add(dxx4, next.x.step);
237 for (;;) { /* Skip a run of zeros. */
238 while (!psrc[0])
239 if (!psrc[1]) {
240 if (!psrc[2]) {
241 if (!psrc[3]) {
242 psrc += 4;
243 dda_state_next(next.x.state, dxx4);
244 continue;
245 }
246 psrc += 3;
247 dda_state_next(next.x.state, dxx3);
248 break;
249 }
250 psrc += 2;
251 dda_state_next(next.x.state, dxx2);
252 break;
253 } else {
254 ++psrc;
255 dda_next(next.x);
256 break;
257 }
258 xrun = xl;
259 if (psrc >= stop)
260 break;
261 for (; *psrc; ++psrc)
262 dda_next(next.x);
263 code = (*fill_pgram)(dev, xrun, yrun,
264 xl - xrun + ax, fixed_0, fixed_0, dyy,
265 pdevc, lop);
266 if (code < 0)
267 goto err;
268 rsrc = psrc;
269 if (psrc >= stop)
270 break;
271 }
272
273 } else if (penum->posture == image_landscape) {
274
275 /*********************************
276 * Slow case, masked, landscape. *
277 *********************************/
278
279 /*
280 * We don't have to worry about the X DDA. However, we do
281 * have to take adjustment into account. We don't bother to
282 * optimize this as heavily as the portrait case.
283 */
284 fixed ax =
285 (pdyx < 0 ? -penum->adjust : penum->adjust);
286 fixed dyx = pdyx + (ax << 1);
287 fixed ay =
288 (penum->matrix.xy < 0 ? -penum->adjust : penum->adjust);
289
290 xrun -= ax;
291 dda_translate(next.y, -ay);
292 ay <<= 1;
293 for (;;) {
294 for (; !*psrc; ++psrc)
295 dda_next(next.y);
296 yrun = ytf;
297 if (psrc >= stop)
298 break;
299 for (; *psrc; ++psrc)
300 dda_next(next.y);
301 code = (*fill_pgram)(dev, xrun, yrun, fixed_0,
302 ytf - yrun + ay, dyx, fixed_0,
303 pdevc, lop);
304 if (code < 0)
305 goto err;
306 rsrc = psrc;
307 if (psrc >= stop)
308 break;
309 }
310
311 } else {
312
313 /**************************************
314 * Slow case, masked, not orthogonal. *
315 **************************************/
316
317 for (;;) {
318 for (; !*psrc; ++psrc) {
319 dda_next(next.x);
320 dda_next(next.y);
321 }
322 yrun = ytf;
323 xrun = xl;
324 if (psrc >= stop)
325 break;
326 for (; *psrc; ++psrc) {
327 dda_next(next.x);
328 dda_next(next.y);
329 }
330 code = (*fill_pgram)(dev, xrun, yrun, xl - xrun,
331 ytf - yrun, pdyx, pdyy, pdevc, lop);
332 if (code < 0)
333 goto err;
334 rsrc = psrc;
335 if (psrc >= stop)
336 break;
337 }
338
339 }
340
341 } else if (penum->posture == image_portrait ||
342 penum->posture == image_landscape
343 ) {
344
345 /**************************************
346 * Slow case, not masked, orthogonal. *
347 **************************************/
348
349 /* In this case, we can fill runs quickly. */
350 /****** DOESN'T DO ADJUSTMENT ******/
351 if (stop <= psrc)
352 goto last;
353 for (;;) {
354 if (*psrc != run) {
355 if (run != htrun) {
356 htrun = run;
357 IMAGE_SET_GRAY(run);
358 }
359 code = (*fill_pgram)(dev, xrun, yrun, xl - xrun,
360 ytf - yrun, pdyx, pdyy,
361 pdevc, lop);
362 if (code < 0)
363 goto err;
364 yrun = ytf;
365 xrun = xl;
366 rsrc = psrc;
367 if (psrc >= stop)
368 break;
369 run = *psrc;
370 }
371 psrc++;
372 dda_next(next.x);
373 dda_next(next.y);
374 }
375 } else {
376
377 /******************************************
378 * Slow case, not masked, not orthogonal. *
379 ******************************************/
380
381 /*
382 * Since we have to check for the end after every pixel
383 * anyway, we may as well avoid the last-run code.
384 */
385 stop = endp;
386 for (;;) {
387 /* We can't skip large constant regions quickly, */
388 /* because this leads to rounding errors. */
389 /* Just fill the region between xrun and xl. */
390 if (run != htrun) {
391 htrun = run;
392 IMAGE_SET_GRAY(run);
393 }
394 code = (*fill_pgram) (dev, xrun, yrun, xl - xrun,
395 ytf - yrun, pdyx, pdyy, pdevc, lop);
396 if (code < 0)
397 goto err;
398 yrun = ytf;
399 xrun = xl;
400 rsrc = psrc;
401 if (psrc >= stop)
402 break;
403 run = *psrc++;
404 dda_next(next.x);
405 dda_next(next.y); /* harmless if no skew */
406 }
407
408 }
409 /* Fill the last run. */
410 last:if (stop < endp && (*stop || !masked)) {
411 if (!masked) {
412 IMAGE_SET_GRAY(*stop);
413 }
414 dda_advance(next.x, endp - stop);
415 dda_advance(next.y, endp - stop);
416 code = (*fill_pgram) (dev, xrun, yrun, xl - xrun,
417 ytf - yrun, pdyx, pdyy, pdevc, lop);
418 }
419 #undef xl
420 #undef ytf
421
422 } else {
423
424 /**********************************************************
425 * Fast case: no skew, and not imagemask with a halftone. *
426 **********************************************************/
427
428 const fixed adjust = penum->adjust;
429 const fixed dxx = penum->dxx;
430 fixed xa = (dxx >= 0 ? adjust : -adjust);
431 const int yt = penum->yci, iht = penum->hci;
432
433 dev_proc_fill_rectangle((*fill_proc)) =
434 dev_proc(dev, fill_rectangle);
435 dev_proc_strip_tile_rectangle((*tile_proc)) =
436 dev_proc(dev, strip_tile_rectangle);
437 dev_proc_copy_mono((*copy_mono_proc)) =
438 dev_proc(dev, copy_mono);
439 /*
440 * If each pixel is likely to fit in a single halftone tile,
441 * determine that now (tile_offset = offset of row within tile).
442 * Don't do this for band devices; they handle halftone fills
443 * more efficiently than copy_mono.
444 */
445 int bstart;
446 int phase_x;
447 int tile_offset =
448 (pis && penum->device_color &&
449 (*dev_proc(dev, get_band)) (dev, yt, &bstart) == 0 ?
450 gx_check_tile_size(pis,
451 fixed2int_ceiling(any_abs(dxx) + (xa << 1)),
452 yt, iht, gs_color_select_source, &phase_x) :
453 -1);
454 int xmin = fixed2int_pixround(penum->clip_outer.p.x);
455 int xmax = fixed2int_pixround(penum->clip_outer.q.x);
456
457 #define xl dda_current(next.x)
458 /* Fold the adjustment into xrun and xl, */
459 /* including the +0.5-epsilon for rounding. */
460 xrun = xrun - xa + (fixed_half - fixed_epsilon);
461 dda_translate(next.x, xa + (fixed_half - fixed_epsilon));
462 xa <<= 1;
463 /* Calculate multiples of the DDA step. */
464 dxx2 = next.x.step;
465 dda_step_add(dxx2, next.x.step);
466 dxx3 = dxx2;
467 dda_step_add(dxx3, next.x.step);
468 dxx4 = dxx3;
469 dda_step_add(dxx4, next.x.step);
470 if (stop > psrc)
471 for (;;) { /* Skip large constant regions quickly, */
472 /* but don't slow down transitions too much. */
473 skf:if (psrc[0] == run) {
474 if (psrc[1] == run) {
475 if (psrc[2] == run) {
476 if (psrc[3] == run) {
477 psrc += 4;
478 dda_state_next(next.x.state, dxx4);
479 goto skf;
480 } else {
481 psrc += 4;
482 dda_state_next(next.x.state, dxx3);
483 }
484 } else {
485 psrc += 3;
486 dda_state_next(next.x.state, dxx2);
487 }
488 } else {
489 psrc += 2;
490 dda_next(next.x);
491 }
492 } else
493 psrc++;
494 { /* Now fill the region between xrun and xl. */
495 int xi = fixed2int_var(xrun);
496 int wi = fixed2int_var(xl) - xi;
497 int xei, tsx;
498 const gx_strip_bitmap *tile;
499
500 if (wi <= 0) {
501 if (wi == 0)
502 goto mt;
503 xi += wi, wi = -wi;
504 }
505 if ((xei = xi + wi) > xmax || xi < xmin) { /* Do X clipping */
506 if (xi < xmin)
507 wi -= xmin - xi, xi = xmin;
508 if (xei > xmax)
509 wi -= xei - xmax;
510 if (wi <= 0)
511 goto mt;
512 }
513 switch (run) {
514 case 0:
515 if (masked)
516 goto mt;
517 if (!color_is_pure(&penum->icolor0))
518 goto ht;
519 code = (*fill_proc) (dev, xi, yt, wi, iht,
520 penum->icolor0.colors.pure);
521 break;
522 case 255: /* just for speed */
523 if (!color_is_pure(&penum->icolor1))
524 goto ht;
525 code = (*fill_proc) (dev, xi, yt, wi, iht,
526 penum->icolor1.colors.pure);
527 break;
528 default:
529 ht: /* Use halftone if needed */
530 if (run != htrun) {
531 IMAGE_SET_GRAY(run);
532 htrun = run;
533 }
534 /* We open-code gx_fill_rectangle, */
535 /* because we've done some of the work for */
536 /* halftone tiles in advance. */
537 if (color_is_pure(pdevc)) {
538 code = (*fill_proc) (dev, xi, yt, wi, iht,
539 pdevc->colors.pure);
540 } else if (!color_is_binary_halftone(pdevc)) {
541 code =
542 gx_fill_rectangle_device_rop(xi, yt, wi, iht,
543 pdevc, dev, lop);
544 } else if (tile_offset >= 0 &&
545 (tile = &pdevc->colors.binary.b_tile->tiles,
546 (tsx = (xi + phase_x) % tile->rep_width) + wi <= tile->size.x)
547 ) { /* The pixel(s) fit(s) in a single (binary) tile. */
548 byte *row = tile->data + tile_offset;
549
550 code = (*copy_mono_proc)
551 (dev, row, tsx, tile->raster, gx_no_bitmap_id,
552 xi, yt, wi, iht,
553 pdevc->colors.binary.color[0],
554 pdevc->colors.binary.color[1]);
555 } else {
556 code = (*tile_proc) (dev,
557 &pdevc->colors.binary.b_tile->tiles,
558 xi, yt, wi, iht,
559 pdevc->colors.binary.color[0],
560 pdevc->colors.binary.color[1],
561 pdevc->phase.x, pdevc->phase.y);
562 }
563 }
564 if (code < 0)
565 goto err;
566 mt:xrun = xl - xa; /* original xa << 1 */
567 rsrc = psrc - 1;
568 if (psrc > stop) {
569 --psrc;
570 break;
571 }
572 run = psrc[-1];
573 }
574 dda_next(next.x);
575 }
576 /* Fill the last run. */
577 if (*stop != 0 || !masked) {
578 int xi = fixed2int_var(xrun);
579 int wi, xei;
580
581 dda_advance(next.x, endp - stop);
582 wi = fixed2int_var(xl) - xi;
583 if (wi <= 0) {
584 if (wi == 0)
585 goto lmt;
586 xi += wi, wi = -wi;
587 }
588 if ((xei = xi + wi) > xmax || xi < xmin) { /* Do X clipping */
589 if (xi < xmin)
590 wi -= xmin - xi, xi = xmin;
591 if (xei > xmax)
592 wi -= xei - xmax;
593 if (wi <= 0)
594 goto lmt;
595 }
596 IMAGE_SET_GRAY(*stop);
597 code = gx_fill_rectangle_device_rop(xi, yt, wi, iht,
598 pdevc, dev, lop);
599 lmt:;
600 }
601
602 }
603 #undef xl
604 if (code >= 0)
605 return 1;
606 /* Save position if error, in case we resume. */
607 err:
608 penum->used.x = rsrc - psrc_initial;
609 penum->used.y = 0;
610 return code;
611 }
612