Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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