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