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) 1999, 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: gxhtbit.c,v 1.5 2002/02/21 22:24:53 giles Exp $ */
18
/* Halftone bit updating for imaging library */
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsbitops.h"
23
#include "gscdefs.h"
24
#include "gxbitmap.h"
25
#include "gxhttile.h"
26
#include "gxtmap.h"
27
#include "gxdht.h"
28
#include "gxdhtres.h"
29
 
30
extern_gx_device_halftone_list();
31
 
32
/*
33
 * Construct a standard-representation order from a threshold array.
34
 */
35
private int
36
construct_ht_order_default(gx_ht_order *porder, const byte *thresholds)
37
{
38
    gx_ht_bit *bits = (gx_ht_bit *)porder->bit_data;
39
    uint i;
40
 
41
    for (i = 0; i < porder->num_bits; i++)
42
	bits[i].mask = max(1, thresholds[i]);
43
    gx_ht_complete_threshold_order(porder);
44
    return 0;
45
}
46
 
47
/*
48
 * Construct a short-representation order from a threshold array.
49
 * Uses porder->width, num_levels, num_bits, levels, bit_data;
50
 * sets porder->levels[], bit_data[].
51
 */
52
private int
53
construct_ht_order_short(gx_ht_order *porder, const byte *thresholds)
54
{
55
    uint size = porder->num_bits;
56
    uint i;
57
    ushort *bits = (ushort *)porder->bit_data;
58
    uint *levels = porder->levels;
59
    uint num_levels = porder->num_levels;
60
 
61
    memset(levels, 0, num_levels * sizeof(*levels));
62
    /* Count the number of threshold elements with each value. */
63
    for (i = 0; i < size; i++) {
64
	uint value = max(1, thresholds[i]);
65
 
66
	if (value + 1 < num_levels)
67
	    levels[value + 1]++;
68
    }
69
    for (i = 2; i < num_levels; ++i)
70
	levels[i] += levels[i - 1];
71
    /* Now construct the actual order. */
72
    {
73
	uint width = porder->width;
74
	uint padding = bitmap_raster(width) * 8 - width;
75
 
76
	for (i = 0; i < size; i++) {
77
	    uint value = max(1, thresholds[i]);
78
 
79
	    /* Adjust the bit index to account for padding. */
80
	    bits[levels[value]++] = i + (i / width * padding);
81
	}
82
    }
83
 
84
    /* Check whether this is a predefined halftone. */
85
    {
86
	const gx_dht_proc *phtrp = gx_device_halftone_list;
87
 
88
	for (; *phtrp; ++phtrp) {
89
	    const gx_device_halftone_resource_t *const *pphtr = (*phtrp)();
90
	    const gx_device_halftone_resource_t *phtr;
91
 
92
	    while ((phtr = *pphtr++) != 0) {
93
		if (phtr->Width == porder->width &&
94
		    phtr->Height == porder->height &&
95
		    phtr->elt_size == sizeof(ushort) &&
96
		    !memcmp(phtr->levels, levels, num_levels * sizeof(*levels)) &&
97
		    !memcmp(phtr->bit_data, porder->bit_data,
98
			    size * phtr->elt_size)
99
		    ) {
100
		    /*
101
		     * This is a predefined halftone.  Free the levels and
102
		     * bit_data arrays, replacing them with the built-in ones.
103
		     */
104
		    if (porder->data_memory) {
105
			gs_free_object(porder->data_memory, porder->bit_data,
106
				       "construct_ht_order_short(bit_data)");
107
			gs_free_object(porder->data_memory, porder->levels,
108
				       "construct_ht_order_short(levels)");
109
		    }
110
		    porder->data_memory = 0;
111
		    porder->levels = (uint *)phtr->levels; /* actually const */
112
		    porder->bit_data = (void *)phtr->bit_data; /* actually const */
113
		    goto out;
114
		}
115
	    }
116
	}
117
    }
118
 out:
119
    return 0;
120
}
121
 
122
/* Return the bit coordinate using the standard representation. */
123
private int
124
ht_bit_index_default(const gx_ht_order *porder, uint index, gs_int_point *ppt)
125
{
126
    const gx_ht_bit *phtb = &((const gx_ht_bit *)porder->bit_data)[index];
127
    uint offset = phtb->offset;
128
    int bit = 0;
129
 
130
    while (!(((const byte *)&phtb->mask)[bit >> 3] & (0x80 >> (bit & 7))))
131
	++bit;
132
    ppt->x = (offset % porder->raster * 8) + bit;
133
    ppt->y = offset / porder->raster;
134
    return 0;
135
}
136
 
137
/* Return the bit coordinate using the short representation. */
138
private int
139
ht_bit_index_short(const gx_ht_order *porder, uint index, gs_int_point *ppt)
140
{
141
    uint bit_index = ((const ushort *)porder->bit_data)[index];
142
    uint bit_raster = porder->raster * 8;
143
 
144
    ppt->x = bit_index % bit_raster;
145
    ppt->y = bit_index / bit_raster;
146
    return 0;
147
}
148
 
149
/* Update a halftone tile using the default order representation. */
150
private int
151
render_ht_default(gx_ht_tile *pbt, int level, const gx_ht_order *porder)
152
{
153
    int old_level = pbt->level;
154
    register const gx_ht_bit *p =
155
	(const gx_ht_bit *)porder->bit_data + old_level;
156
    register byte *data = pbt->tiles.data;
157
 
158
    /*
159
     * Invert bits between the two levels.  Note that we can use the same
160
     * loop to turn bits either on or off, using xor.  The Borland compiler
161
     * generates truly dreadful code if we don't use a temporary, and it
162
     * doesn't hurt better compilers, so we always use one.
163
     */
164
#define INVERT_DATA(i)\
165
     BEGIN\
166
       ht_mask_t *dp = (ht_mask_t *)&data[p[i].offset];\
167
       *dp ^= p[i].mask;\
168
     END
169
#ifdef DEBUG
170
#  define INVERT(i)\
171
     BEGIN\
172
       if_debug3('H', "[H]invert level=%d offset=%u mask=0x%x\n",\
173
	         (int)(p + i - (const gx_ht_bit *)porder->bit_data),\
174
		 p[i].offset, p[i].mask);\
175
       INVERT_DATA(i);\
176
     END
177
#else
178
#  define INVERT(i) INVERT_DATA(i)
179
#endif
180
  sw:switch (level - old_level) {
181
	default:
182
	    if (level > old_level) {
183
		INVERT(0); INVERT(1); INVERT(2); INVERT(3);
184
		p += 4; old_level += 4;
185
	    } else {
186
		INVERT(-1); INVERT(-2); INVERT(-3); INVERT(-4);
187
		p -= 4; old_level -= 4;
188
	    }
189
	    goto sw;
190
	case 7: INVERT(6);
191
	case 6: INVERT(5);
192
	case 5: INVERT(4);
193
	case 4: INVERT(3);
194
	case 3: INVERT(2);
195
	case 2: INVERT(1);
196
	case 1: INVERT(0);
197
	case 0: break;		/* Shouldn't happen! */
198
	case -7: INVERT(-7);
199
	case -6: INVERT(-6);
200
	case -5: INVERT(-5);
201
	case -4: INVERT(-4);
202
	case -3: INVERT(-3);
203
	case -2: INVERT(-2);
204
	case -1: INVERT(-1);
205
    }
206
#undef INVERT_DATA
207
#undef INVERT
208
    return 0;
209
}
210
 
211
/* Update a halftone tile using the short representation. */
212
private int
213
render_ht_short(gx_ht_tile *pbt, int level, const gx_ht_order *porder)
214
{
215
    int old_level = pbt->level;
216
    register const ushort *p = (const ushort *)porder->bit_data + old_level;
217
    register byte *data = pbt->tiles.data;
218
 
219
    /* Invert bits between the two levels. */
220
#define INVERT_DATA(i)\
221
     BEGIN\
222
       uint bit_index = p[i];\
223
       byte *dp = &data[bit_index >> 3];\
224
       *dp ^= 0x80 >> (bit_index & 7);\
225
     END
226
#ifdef DEBUG
227
#  define INVERT(i)\
228
     BEGIN\
229
       if_debug3('H', "[H]invert level=%d offset=%u mask=0x%x\n",\
230
	         (int)(p + i - (const ushort *)porder->bit_data),\
231
		 p[i] >> 3, 0x80 >> (p[i] & 7));\
232
       INVERT_DATA(i);\
233
     END
234
#else
235
#  define INVERT(i) INVERT_DATA(i)
236
#endif
237
  sw:switch (level - old_level) {
238
	default:
239
	    if (level > old_level) {
240
		INVERT(0); INVERT(1); INVERT(2); INVERT(3);
241
		p += 4; old_level += 4;
242
	    } else {
243
		INVERT(-1); INVERT(-2); INVERT(-3); INVERT(-4);
244
		p -= 4; old_level -= 4;
245
	    }
246
	    goto sw;
247
	case 7: INVERT(6);
248
	case 6: INVERT(5);
249
	case 5: INVERT(4);
250
	case 4: INVERT(3);
251
	case 3: INVERT(2);
252
	case 2: INVERT(1);
253
	case 1: INVERT(0);
254
	case 0: break;		/* Shouldn't happen! */
255
	case -7: INVERT(-7);
256
	case -6: INVERT(-6);
257
	case -5: INVERT(-5);
258
	case -4: INVERT(-4);
259
	case -3: INVERT(-3);
260
	case -2: INVERT(-2);
261
	case -1: INVERT(-1);
262
    }
263
#undef INVERT_DATA
264
#undef INVERT
265
    return 0;
266
}
267
 
268
/* Define the procedure vectors for the order data implementations. */
269
const gx_ht_order_procs_t ht_order_procs_table[2] = {
270
    { sizeof(gx_ht_bit), construct_ht_order_default, ht_bit_index_default,
271
      render_ht_default },
272
    { sizeof(ushort), construct_ht_order_short, ht_bit_index_short,
273
      render_ht_short }
274
};