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) 1995, 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: gxidata.c,v 1.9 2005/06/08 14:38:21 igor Exp $ */
18
/* Generic image enumeration and cleanup */
19
#include "gx.h"
20
#include "memory_.h"
21
#include "gserrors.h"
22
#include "gxdevice.h"
23
#include "gxcpath.h"
24
#include "gximage.h"
25
 
26
/* Forward declarations */
27
private void update_strip(gx_image_enum *penum);
28
private void repack_bit_planes(const gx_image_plane_t *src_planes,
29
			       const ulong *offsets, int num_planes,
30
			       byte *buffer, int width,
31
			       const sample_lookup_t * ptab, int spread);
32
private gx_device *setup_image_device(const gx_image_enum *penum);
33
 
34
/* Process the next piece of an ImageType 1 image. */
35
int
36
gx_image1_plane_data(gx_image_enum_common_t * info,
37
		     const gx_image_plane_t * planes, int height,
38
		     int *rows_used)
39
{
40
    gx_image_enum *penum = (gx_image_enum *) info;
41
    gx_device *dev;
42
    const int y = penum->y;
43
    int y_end = min(y + height, penum->rect.h);
44
    int width_spp = penum->rect.w * penum->spp;
45
    int num_planes = penum->num_planes;
46
    int num_components_per_plane = 1;
47
 
48
#define BCOUNT(plane)		/* bytes per data row */\
49
  (((penum->rect.w + (plane).data_x) * penum->spp * penum->bps / num_planes\
50
    + 7) >> 3)
51
 
52
    fixed adjust = penum->adjust;
53
    ulong offsets[gs_image_max_planes];
54
    int ignore_data_x;
55
    bool bit_planar = penum->num_planes > penum->spp;
56
    int code;
57
 
58
    if (height == 0) {
59
	*rows_used = 0;
60
	return 0;
61
    }
62
    dev = setup_image_device(penum);
63
 
64
    /* Now render complete rows. */
65
 
66
    if (penum->used.y) {
67
	/*
68
	 * Processing was interrupted by an error.  Skip over rows
69
	 * already processed.
70
	 */
71
	int px;
72
 
73
	for (px = 0; px < num_planes; ++px)
74
	    offsets[px] = planes[px].raster * penum->used.y;
75
	penum->used.y = 0;
76
    } else
77
	memset(offsets, 0, num_planes * sizeof(offsets[0]));
78
    if (num_planes == 1 && penum->plane_depths[0] != penum->bps) {
79
	/* A single plane with multiple components. */
80
	num_components_per_plane = penum->plane_depths[0] / penum->bps;
81
    }
82
    for (; penum->y < y_end; penum->y++) {
83
	int px;
84
	const byte *buffer;
85
	int sourcex;
86
	int x_used = penum->used.x;
87
 
88
	if (bit_planar) {
89
	    /* Repack the bit planes into byte-wide samples. */
90
 
91
	    buffer = penum->buffer;
92
	    sourcex = 0;
93
	    for (px = 0; px < num_planes; px += penum->bps)
94
		repack_bit_planes(planes, offsets, penum->bps, penum->buffer,
95
				  penum->rect.w, &penum->map[px].table,
96
				  penum->spread);
97
	    for (px = 0; px < num_planes; ++px)
98
		offsets[px] += planes[px].raster;
99
	} else {
100
	    /*
101
	     * Normally, we unpack the data into the buffer, but if
102
	     * there is only one plane and we don't need to expand the
103
	     * input samples, we may use the data directly.
104
	     */
105
	    sourcex = planes[0].data_x;
106
	    buffer =
107
		(*penum->unpack)(penum->buffer, &sourcex,
108
				 planes[0].data + offsets[0],
109
				 planes[0].data_x, BCOUNT(planes[0]),
110
				 &penum->map[0], penum->spread, num_components_per_plane);
111
 
112
	    offsets[0] += planes[0].raster;
113
	    for (px = 1; px < num_planes; ++px) {
114
		(*penum->unpack)(penum->buffer + (px << penum->log2_xbytes),
115
				 &ignore_data_x,
116
				 planes[px].data + offsets[px],
117
				 planes[px].data_x, BCOUNT(planes[px]),
118
				 &penum->map[px], penum->spread, 1);
119
		offsets[px] += planes[px].raster;
120
	    }
121
	}
122
#ifdef DEBUG
123
	if (gs_debug_c('b'))
124
	    dprintf1("[b]image1 y=%d\n", y);
125
	if (gs_debug_c('B')) {
126
	    int i, n = width_spp;
127
 
128
	    if (penum->bps > 8)
129
		n *= 2;
130
	    else if (penum->bps == 1 && penum->unpack_bps == 8)
131
		n = (n + 7) / 8;
132
	    dlputs("[B]row:");
133
	    for (i = 0; i < n; i++)
134
		dprintf1(" %02x", buffer[i]);
135
	    dputs("\n");
136
	}
137
#endif
138
	penum->cur.x = dda_current(penum->dda.row.x);
139
	dda_next(penum->dda.row.x);
140
	penum->cur.y = dda_current(penum->dda.row.y);
141
	dda_next(penum->dda.row.y);
142
	if (!penum->interpolate)
143
	    switch (penum->posture) {
144
		case image_portrait:
145
		    {		/* Precompute integer y and height, */
146
			/* and check for clipping. */
147
			fixed yc = penum->cur.y,
148
			    yn = dda_current(penum->dda.row.y);
149
 
150
			if (yn < yc) {
151
			    fixed temp = yn;
152
 
153
			    yn = yc;
154
			    yc = temp;
155
			}
156
			yc -= adjust;
157
			if (yc >= penum->clip_outer.q.y)
158
			    goto mt;
159
			yn += adjust;
160
			if (yn <= penum->clip_outer.p.y)
161
			    goto mt;
162
			penum->yci = fixed2int_pixround(yc);
163
			penum->hci = fixed2int_pixround(yn) - penum->yci;
164
			if (penum->hci == 0)
165
			    goto mt;
166
			if_debug2('b', "[b]yci=%d, hci=%d\n",
167
				  penum->yci, penum->hci);
168
		    }
169
		    break;
170
		case image_landscape:
171
		    {		/* Check for no pixel centers in x. */
172
			fixed xc = penum->cur.x,
173
			    xn = dda_current(penum->dda.row.x);
174
 
175
			if (xn < xc) {
176
			    fixed temp = xn;
177
 
178
			    xn = xc;
179
			    xc = temp;
180
			}
181
			xc -= adjust;
182
			if (xc >= penum->clip_outer.q.x)
183
			    goto mt;
184
			xn += adjust;
185
			if (xn <= penum->clip_outer.p.x)
186
			    goto mt;
187
			penum->xci = fixed2int_pixround(xc);
188
			penum->wci = fixed2int_pixround(xn) - penum->xci;
189
			if (penum->wci == 0)
190
			    goto mt;
191
			if_debug2('b', "[b]xci=%d, wci=%d\n",
192
				  penum->xci, penum->wci);
193
		    }
194
		    break;
195
		case image_skewed:
196
		    ;
197
	    }
198
	update_strip(penum);
199
	if (x_used) {
200
	    /*
201
	     * Processing was interrupted by an error.  Skip over pixels
202
	     * already processed.
203
	     */
204
	    dda_advance(penum->dda.pixel0.x, x_used);
205
	    dda_advance(penum->dda.pixel0.y, x_used);
206
	    penum->used.x = 0;
207
	}
208
	if_debug2('b', "[b]pixel0 x=%g, y=%g\n",
209
		  fixed2float(dda_current(penum->dda.pixel0.x)),
210
		  fixed2float(dda_current(penum->dda.pixel0.y)));
211
	code = (*penum->render)(penum, buffer, sourcex + x_used,
212
				width_spp - x_used * penum->spp, 1, dev);
213
	if (code < 0) {
214
	    /* Error or interrupt, restore original state. */
215
	    penum->used.x += x_used;
216
	    if (!penum->used.y) {
217
		dda_previous(penum->dda.row.x);
218
		dda_previous(penum->dda.row.y);
219
		dda_translate(penum->dda.strip.x,
220
			      penum->prev.x - penum->cur.x);
221
		dda_translate(penum->dda.strip.y,
222
			      penum->prev.y - penum->cur.y);
223
	    }
224
	    goto out;
225
	}
226
	penum->prev = penum->cur;
227
      mt:;
228
    }
229
    if (penum->y < penum->rect.h) {
230
	code = 0;
231
    } else {
232
	/* End of input data.  Render any left-over buffered data. */
233
	code = gx_image1_flush(info);
234
	if (code >= 0)
235
	    code = 1;
236
    }
237
out:
238
    /* Note that caller must call end_image */
239
    /* for both error and normal termination. */
240
    *rows_used = penum->y - y;
241
    return code;
242
}
243
 
244
/* Flush any buffered data. */
245
int
246
gx_image1_flush(gx_image_enum_common_t * info)
247
{
248
    gx_image_enum *penum = (gx_image_enum *)info;
249
    int width_spp = penum->rect.w * penum->spp;
250
    fixed adjust = penum->adjust;
251
 
252
    penum->cur.x = dda_current(penum->dda.row.x);
253
    penum->cur.y = dda_current(penum->dda.row.y);
254
    switch (penum->posture) {
255
	case image_portrait:
256
	    {
257
		fixed yc = penum->cur.y;
258
 
259
		penum->yci = fixed2int_rounded(yc - adjust);
260
		penum->hci = fixed2int_rounded(yc + adjust) - penum->yci;
261
	    }
262
	    break;
263
	case image_landscape:
264
	    {
265
		fixed xc = penum->cur.x;
266
 
267
		penum->xci = fixed2int_rounded(xc - adjust);
268
		penum->wci = fixed2int_rounded(xc + adjust) - penum->xci;
269
	    }
270
	    break;
271
	case image_skewed:	/* pacify compilers */
272
	    ;
273
    }
274
    update_strip(penum);
275
    penum->prev = penum->cur;
276
    return (*penum->render)(penum, NULL, 0, width_spp, 0,
277
			    setup_image_device(penum));
278
}
279
 
280
/* Update the strip DDA when moving to a new row. */
281
private void
282
update_strip(gx_image_enum *penum)
283
{
284
    dda_translate(penum->dda.strip.x, penum->cur.x - penum->prev.x);
285
    dda_translate(penum->dda.strip.y, penum->cur.y - penum->prev.y);
286
    penum->dda.pixel0 = penum->dda.strip;
287
}
288
 
289
/*
290
 * Repack 1 to 8 individual bit planes into 8-bit samples.
291
 * buffer is aligned, and includes padding to an 8-byte boundary.
292
 * This procedure repacks one row, so the only relevant members of
293
 * src_planes are data and data_x (not raster).
294
 */
295
private void
296
repack_bit_planes(const gx_image_plane_t *src_planes, const ulong *offsets,
297
		  int num_planes, byte *buffer, int width,
298
		  const sample_lookup_t * ptab, int spread)
299
{
300
    gx_image_plane_t planes[8];
301
    byte *zeros = 0;
302
    byte *dest = buffer;
303
    int any_data_x = 0;
304
    bool direct = (spread == 1 && ptab->lookup8[0] == 0 &&
305
		   ptab->lookup8[255] == 255);
306
    int pi, x;
307
    gx_image_plane_t *pp;
308
 
309
    /*
310
     * Set up the row pointers, taking data_x and null planes into account.
311
     * If there are any null rows, we need to create a block of zeros in
312
     * order to avoid tests in the loop.
313
     */
314
    for (pi = 0, pp = planes; pi < num_planes; ++pi, ++pp)
315
	if (src_planes[pi].data == 0) {
316
	    if (!zeros) {
317
		zeros = buffer + width - ((width + 7) >> 3);
318
	    }
319
	    pp->data = zeros;
320
	    pp->data_x = 0;
321
	} else {
322
	    int dx = src_planes[pi].data_x;
323
 
324
	    pp->data = src_planes[pi].data + (dx >> 3) + offsets[pi];
325
	    any_data_x |= (pp->data_x = dx & 7);
326
	}
327
    if (zeros)
328
	memset(zeros, 0, buffer + width - zeros);
329
 
330
    /*
331
     * Now process the data, in blocks of one input byte column
332
     * (8 output bytes).
333
     */
334
    for (x = 0; x < width; x += 8) {
335
	bits32 w0 = 0, w1 = 0;
336
#if arch_is_big_endian
337
	static const bits32 expand[16] = {
338
	    0x00000000, 0x00000001, 0x00000100, 0x00000101,
339
	    0x00010000, 0x00010001, 0x00010100, 0x00010101,
340
	    0x01000000, 0x01000001, 0x01000100, 0x01000101,
341
	    0x01010000, 0x01010001, 0x01010100, 0x01010101
342
	};
343
#else
344
	static const bits32 expand[16] = {
345
	    0x00000000, 0x01000000, 0x00010000, 0x01010000,
346
	    0x00000100, 0x01000100, 0x00010100, 0x01010100,
347
	    0x00000001, 0x01000001, 0x00010001, 0x01010001,
348
	    0x00000101, 0x01000101, 0x00010101, 0x01010101
349
	};
350
#endif
351
 
352
	if (any_data_x) {
353
	    for (pi = 0, pp = planes; pi < num_planes; ++pi, ++pp) {
354
		uint b = *(pp->data++);
355
		int dx = pp->data_x;
356
 
357
		if (dx) {
358
		    b <<= dx;
359
		    if (x + 8 - dx < width)
360
			b += *pp->data >> (8 - dx);
361
		}
362
		w0 = (w0 << 1) | expand[b >> 4];
363
		w1 = (w1 << 1) | expand[b & 0xf];
364
	    }
365
	} else {
366
	    for (pi = 0, pp = planes; pi < num_planes; ++pi, ++pp) {
367
		uint b = *(pp->data++);
368
 
369
		w0 = (w0 << 1) | expand[b >> 4];
370
		w1 = (w1 << 1) | expand[b & 0xf];
371
	    }
372
	}
373
	/*
374
	 * We optimize spread == 1 and identity ptab together, although
375
	 * we could subdivide these 2 cases into 4 if we wanted.
376
	 */
377
	if (direct) {
378
	    ((bits32 *)dest)[0] = w0;
379
	    ((bits32 *)dest)[1] = w1;
380
	    dest += 8;
381
	} else {
382
#define MAP_BYTE(v) (ptab->lookup8[(byte)(v)])
383
	    dest[0] = MAP_BYTE(w0 >> 24); dest += spread;
384
	    dest[1] = MAP_BYTE(w0 >> 16); dest += spread;
385
	    dest[2] = MAP_BYTE(w0 >> 8); dest += spread;
386
	    dest[3] = MAP_BYTE(w0); dest += spread;
387
	    dest[4] = MAP_BYTE(w1 >> 24); dest += spread;
388
	    dest[5] = MAP_BYTE(w1 >> 16); dest += spread;
389
	    dest[6] = MAP_BYTE(w1 >> 8); dest += spread;
390
	    dest[7] = MAP_BYTE(w1); dest += spread;
391
#undef MAP_BYTE
392
	}
393
    }
394
}
395
 
396
/* Set up the device for drawing an image. */
397
private gx_device *
398
setup_image_device(const gx_image_enum *penum)
399
{
400
    gx_device *dev = penum->dev;
401
 
402
    if (penum->clip_dev) {
403
	gx_device_clip *cdev = penum->clip_dev;
404
 
405
	gx_device_set_target((gx_device_forward *)cdev, dev);
406
	dev = (gx_device *) cdev;
407
    }
408
    if (penum->rop_dev) {
409
	gx_device_rop_texture *rtdev = penum->rop_dev;
410
 
411
	gx_device_set_target((gx_device_forward *)rtdev, dev);
412
	dev = (gx_device *) rtdev;
413
    }
414
    return dev;
415
}
416
 
417
/* Clean up by releasing the buffers. */
418
/* Currently we ignore draw_last. */
419
int
420
gx_image1_end_image(gx_image_enum_common_t * info, bool draw_last)
421
{
422
    gx_image_enum *penum = (gx_image_enum *) info;
423
    gs_memory_t *mem = penum->memory;
424
    stream_image_scale_state *scaler = penum->scaler;
425
 
426
    if_debug2('b', "[b]%send_image, y=%d\n",
427
	      (penum->y < penum->rect.h ? "premature " : ""), penum->y);
428
    if (draw_last) {
429
	int code = gx_image_flush(info);
430
 
431
	if (code < 0)
432
	    return code;
433
    }
434
    gs_free_object(mem, penum->rop_dev, "image RasterOp");
435
    gs_free_object(mem, penum->clip_dev, "image clipper");
436
    if (scaler != 0) {
437
	(*scaler->template->release) ((stream_state *) scaler);
438
	gs_free_object(mem, scaler, "image scaler state");
439
    }
440
    gs_free_object(mem, penum->line, "image line");
441
    gs_free_object(mem, penum->buffer, "image buffer");
442
    gs_free_object(mem, penum, "gx_default_end_image");
443
    return 0;
444
}