~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to src/gsbitops.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
 
   All Rights Reserved.
3
 
  
4
 
   This software is provided AS-IS with no warranty, either express or
5
 
   implied.
6
 
 
7
 
   This software is distributed under license and may not be copied, modified
8
 
   or distributed except as expressly authorized under the terms of that
9
 
   license.  Refer to licensing information at http://www.artifex.com/
10
 
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11
 
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
 
*/
13
 
 
14
 
/* $Id: gsbitops.c 8022 2007-06-05 22:23:38Z giles $ */
15
 
/* Bitmap filling, copying, and transforming operations */
16
 
#include "stdio_.h"
17
 
#include "memory_.h"
18
 
#include "gdebug.h"
19
 
#include "gserror.h"
20
 
#include "gserrors.h"
21
 
#include "gstypes.h"
22
 
#include "gsbittab.h"
23
 
#include "gxbitops.h"
24
 
#include "gxcindex.h"
25
 
 
26
 
/* ---------------- Bit-oriented operations ---------------- */
27
 
 
28
 
/* Define masks for little-endian operation. */
29
 
/* masks[i] has the first i bits off and the rest on. */
30
 
#if !arch_is_big_endian
31
 
const bits16 mono_copy_masks[17] = {
32
 
    0xffff, 0xff7f, 0xff3f, 0xff1f,
33
 
    0xff0f, 0xff07, 0xff03, 0xff01,
34
 
    0xff00, 0x7f00, 0x3f00, 0x1f00,
35
 
    0x0f00, 0x0700, 0x0300, 0x0100,
36
 
    0x0000
37
 
};
38
 
const bits32 mono_fill_masks[33] = {
39
 
#define mask(n)\
40
 
  ((~0xff | (0xff >> (n & 7))) << (n & -8))
41
 
    mask( 0),mask( 1),mask( 2),mask( 3),mask( 4),mask( 5),mask( 6),mask( 7),
42
 
    mask( 8),mask( 9),mask(10),mask(11),mask(12),mask(13),mask(14),mask(15),
43
 
    mask(16),mask(17),mask(18),mask(19),mask(20),mask(21),mask(22),mask(23),
44
 
    mask(24),mask(25),mask(26),mask(27),mask(28),mask(29),mask(30),mask(31),
45
 
    0
46
 
#undef mask
47
 
};
48
 
#endif
49
 
 
50
 
/* Fill a rectangle of bits with an 8x1 pattern. */
51
 
/* The pattern argument must consist of the pattern in every byte, */
52
 
/* e.g., if the desired pattern is 0xaa, the pattern argument must */
53
 
/* have the value 0xaaaa (if ints are short) or 0xaaaaaaaa. */
54
 
#undef chunk
55
 
#define chunk mono_fill_chunk
56
 
#undef mono_masks
57
 
#define mono_masks mono_fill_masks
58
 
void
59
 
bits_fill_rectangle(byte * dest, int dest_bit, uint draster,
60
 
                    mono_fill_chunk pattern, int width_bits, int height)
61
 
{
62
 
    uint bit;
63
 
    chunk right_mask;
64
 
    int line_count = height;
65
 
    chunk *ptr;
66
 
    int last_bit;
67
 
 
68
 
#define FOR_EACH_LINE(stat)\
69
 
        do { stat } while ( inc_ptr(ptr, draster), --line_count )
70
 
 
71
 
    dest += (dest_bit >> 3) & -chunk_align_bytes;
72
 
    ptr = (chunk *) dest;
73
 
    bit = dest_bit & chunk_align_bit_mask;
74
 
    last_bit = width_bits + bit - (chunk_bits + 1);
75
 
 
76
 
    if (last_bit < 0) {         /* <=1 chunk */
77
 
        set_mono_thin_mask(right_mask, width_bits, bit);
78
 
        if (pattern == 0)
79
 
            FOR_EACH_LINE(*ptr &= ~right_mask;);
80
 
        else if (pattern == (mono_fill_chunk)(-1))
81
 
            FOR_EACH_LINE(*ptr |= right_mask;);
82
 
        else
83
 
            FOR_EACH_LINE(
84
 
                *ptr = (*ptr & ~right_mask) | (pattern & right_mask); );
85
 
    } else {
86
 
        chunk mask;
87
 
        int last = last_bit >> chunk_log2_bits;
88
 
 
89
 
        set_mono_left_mask(mask, bit);
90
 
        set_mono_right_mask(right_mask, (last_bit & chunk_bit_mask) + 1);
91
 
        switch (last) {
92
 
            case 0:             /* 2 chunks */
93
 
                if (pattern == 0)
94
 
                    FOR_EACH_LINE(*ptr &= ~mask; ptr[1] &= ~right_mask;);
95
 
                else if (pattern == (mono_fill_chunk)(-1))
96
 
                    FOR_EACH_LINE(*ptr |= mask; ptr[1] |= right_mask;);
97
 
                else
98
 
                    FOR_EACH_LINE(
99
 
                        *ptr = (*ptr & ~mask) | (pattern & mask);
100
 
                        ptr[1] = (ptr[1] & ~right_mask) | (pattern & right_mask); );
101
 
                break;
102
 
            case 1:             /* 3 chunks */
103
 
                if (pattern == 0)
104
 
                    FOR_EACH_LINE( *ptr &= ~mask;
105
 
                                   ptr[1] = 0;
106
 
                                   ptr[2] &= ~right_mask; );
107
 
                else if (pattern == (mono_fill_chunk)(-1))
108
 
                    FOR_EACH_LINE( *ptr |= mask;
109
 
                                   ptr[1] = ~(chunk) 0;
110
 
                                   ptr[2] |= right_mask; );
111
 
                else
112
 
                    FOR_EACH_LINE( *ptr = (*ptr & ~mask) | (pattern & mask);
113
 
                                    ptr[1] = pattern;
114
 
                                    ptr[2] = (ptr[2] & ~right_mask) | (pattern & right_mask); );
115
 
                break;
116
 
            default:{           /* >3 chunks */
117
 
                    uint byte_count = (last_bit >> 3) & -chunk_bytes;
118
 
 
119
 
                    if (pattern == 0)
120
 
                        FOR_EACH_LINE( *ptr &= ~mask;
121
 
                                       memset(ptr + 1, 0, byte_count);
122
 
                                       ptr[last + 1] &= ~right_mask; );
123
 
                    else if (pattern == (mono_fill_chunk)(-1))
124
 
                        FOR_EACH_LINE( *ptr |= mask;
125
 
                                       memset(ptr + 1, 0xff, byte_count);
126
 
                                       ptr[last + 1] |= right_mask; );
127
 
                    else
128
 
                        FOR_EACH_LINE(
129
 
                                *ptr = (*ptr & ~mask) | (pattern & mask);
130
 
                                memset(ptr + 1, (byte) pattern, byte_count);
131
 
                                ptr[last + 1] = (ptr[last + 1] & ~right_mask) |
132
 
                                                (pattern & right_mask);         );
133
 
                }
134
 
        }
135
 
    }
136
 
#undef FOR_EACH_LINE
137
 
}
138
 
 
139
 
/*
140
 
 * Similar to bits_fill_rectangle, but with an additional source mask.
141
 
 * The src_mask variable is 1 for those bits of the original that are
142
 
 * to be retained. The mask argument must consist of the requisite value
143
 
 * in every byte, in the same manner as the pattern.
144
 
 */
145
 
void
146
 
bits_fill_rectangle_masked(byte * dest, int dest_bit, uint draster,
147
 
                    mono_fill_chunk pattern, mono_fill_chunk src_mask,
148
 
                    int width_bits, int height)
149
 
{
150
 
    uint bit;
151
 
    chunk right_mask;
152
 
    int line_count = height;
153
 
    chunk *ptr;
154
 
    int last_bit;
155
 
 
156
 
#define FOR_EACH_LINE(stat)\
157
 
        do { stat } while ( inc_ptr(ptr, draster), --line_count )
158
 
 
159
 
    dest += (dest_bit >> 3) & -chunk_align_bytes;
160
 
    ptr = (chunk *) dest;
161
 
    bit = dest_bit & chunk_align_bit_mask;
162
 
    last_bit = width_bits + bit - (chunk_bits + 1);
163
 
 
164
 
    if (last_bit < 0) {         /* <=1 chunk */
165
 
        set_mono_thin_mask(right_mask, width_bits, bit);
166
 
        right_mask &= ~src_mask;
167
 
        if (pattern == 0)
168
 
            FOR_EACH_LINE(*ptr &= ~right_mask;);
169
 
        else if (pattern == (mono_fill_chunk)(-1))
170
 
            FOR_EACH_LINE(*ptr |= right_mask;);
171
 
        else
172
 
            FOR_EACH_LINE(
173
 
                *ptr = (*ptr & ~right_mask) | (pattern & right_mask); );
174
 
    } else {
175
 
        chunk mask;
176
 
        int last = last_bit >> chunk_log2_bits;
177
 
 
178
 
        set_mono_left_mask(mask, bit);
179
 
        set_mono_right_mask(right_mask, (last_bit & chunk_bit_mask) + 1);
180
 
        mask &= ~src_mask;
181
 
        right_mask &= ~src_mask;
182
 
        switch (last) {
183
 
            case 0:             /* 2 chunks */
184
 
                if (pattern == 0)
185
 
                    FOR_EACH_LINE(*ptr &= ~mask; ptr[1] &= ~right_mask;);
186
 
                else if (pattern == (mono_fill_chunk)(-1))
187
 
                    FOR_EACH_LINE(*ptr |= mask; ptr[1] |= right_mask;);
188
 
                else
189
 
                    FOR_EACH_LINE(
190
 
                        *ptr = (*ptr & ~mask) | (pattern & mask);
191
 
                        ptr[1] = (ptr[1] & ~right_mask) | (pattern & right_mask); );
192
 
                break;
193
 
            case 1:             /* 3 chunks */
194
 
                if (pattern == 0)
195
 
                    FOR_EACH_LINE( *ptr &= ~mask;
196
 
                                   ptr[1] &= src_mask;
197
 
                                   ptr[2] &= ~right_mask; );
198
 
                else if (pattern == (mono_fill_chunk)(-1))
199
 
                    FOR_EACH_LINE( *ptr |= mask;
200
 
                                   ptr[1] |= ~src_mask;
201
 
                                   ptr[2] |= right_mask; );
202
 
                else
203
 
                    FOR_EACH_LINE( *ptr = (*ptr & ~mask) | (pattern & mask);
204
 
                                    ptr[1] =(ptr[1] & src_mask) | pattern;
205
 
                                    ptr[2] = (ptr[2] & ~right_mask) | (pattern & right_mask); );
206
 
                break;
207
 
            default:{           /* >3 chunks */
208
 
                    int     i;
209
 
 
210
 
                    if (pattern == 0)
211
 
                        FOR_EACH_LINE( *ptr++ &= ~mask;
212
 
                                       for (i = 0; i < last; i++)
213
 
                                           *ptr++ &= src_mask;
214
 
                                       *ptr &= ~right_mask; );
215
 
                    else if (pattern == (mono_fill_chunk)(-1))
216
 
                        FOR_EACH_LINE( *ptr++ |= mask;
217
 
                                       for (i = 0; i < last; i++)
218
 
                                           *ptr++ |= ~src_mask;
219
 
                                        *ptr |= right_mask; );
220
 
                    else
221
 
                        FOR_EACH_LINE(
222
 
                            /* note: we know (pattern & ~src_mask) == pattern */
223
 
                            *ptr = (*ptr & ~mask) | (pattern & mask);
224
 
                            ++ptr;
225
 
                            for (i = 0; i < last; i++, ptr++)
226
 
                                *ptr = (*ptr & src_mask) | pattern;
227
 
                                *ptr = (*ptr & ~right_mask) | (pattern & right_mask); );
228
 
                }
229
 
        }
230
 
    }
231
 
#undef FOR_EACH_LINE
232
 
}
233
 
 
234
 
/* Replicate a bitmap horizontally in place. */
235
 
void
236
 
bits_replicate_horizontally(byte * data, uint width, uint height,
237
 
                 uint raster, uint replicated_width, uint replicated_raster)
238
 
{
239
 
    /* The current algorithm is extremely inefficient! */
240
 
    const byte *orig_row = data + (height - 1) * raster;
241
 
    byte *tile_row = data + (height - 1) * replicated_raster;
242
 
    uint y;
243
 
 
244
 
    if (!(width & 7)) {
245
 
        uint src_bytes = width >> 3;
246
 
        uint dest_bytes = replicated_width >> 3;
247
 
 
248
 
        for (y = height; y-- > 0;
249
 
             orig_row -= raster, tile_row -= replicated_raster
250
 
             ) {
251
 
            uint move = src_bytes;
252
 
            const byte *from = orig_row;
253
 
            byte *to = tile_row + dest_bytes - src_bytes;
254
 
 
255
 
            memmove(to, from, move);
256
 
            while (to - tile_row >= move) {
257
 
                from = to;
258
 
                to -= move;
259
 
                memmove(to, from, move);
260
 
                move <<= 1;
261
 
            }
262
 
            if (to != tile_row)
263
 
                memmove(tile_row, to, to - tile_row);
264
 
        }
265
 
    } else {
266
 
        /*
267
 
         * This algorithm is inefficient, but probably not worth improving.
268
 
         */
269
 
        uint bit_count = width & (uint)(-(int)width);  /* lowest bit: 1, 2, or 4 */
270
 
        uint left_mask = (0xff00 >> bit_count) & 0xff;
271
 
 
272
 
        for (y = height; y-- > 0;
273
 
             orig_row -= raster, tile_row -= replicated_raster
274
 
             ) {
275
 
            uint sx;
276
 
 
277
 
            for (sx = width; sx > 0;) {
278
 
                uint bits, dx;
279
 
 
280
 
                sx -= bit_count;
281
 
                bits = (orig_row[sx >> 3] << (sx & 7)) & left_mask;
282
 
                for (dx = sx + replicated_width; dx >= width;) {
283
 
                    byte *dp;
284
 
                    int dbit;
285
 
 
286
 
                    dx -= width;
287
 
                    dbit = dx & 7;
288
 
                    dp = tile_row + (dx >> 3);
289
 
                    *dp = (*dp & ~(left_mask >> dbit)) | (bits >> dbit);
290
 
                }
291
 
            }
292
 
        }
293
 
    }
294
 
}
295
 
 
296
 
/* Replicate a bitmap vertically in place. */
297
 
void
298
 
bits_replicate_vertically(byte * data, uint height, uint raster,
299
 
                          uint replicated_height)
300
 
{
301
 
    byte *dest = data;
302
 
    uint h = replicated_height;
303
 
    uint size = raster * height;
304
 
 
305
 
    while (h > height) {
306
 
        memcpy(dest + size, dest, size);
307
 
        dest += size;
308
 
        h -= height;
309
 
    }
310
 
}
311
 
 
312
 
/* Find the bounding box of a bitmap. */
313
 
/* Assume bits beyond the width are zero. */
314
 
void
315
 
bits_bounding_box(const byte * data, uint height, uint raster,
316
 
                  gs_int_rect * pbox)
317
 
{
318
 
    register const ulong *lp;
319
 
    static const byte first_1[16] = {
320
 
        4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
321
 
    };
322
 
    static const byte last_1[16] = {
323
 
        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4
324
 
    };
325
 
 
326
 
    /* Count trailing blank rows. */
327
 
    /* Since the raster is a multiple of sizeof(long), */
328
 
    /* we don't need to scan by bytes, only by longs. */
329
 
 
330
 
    lp = (const ulong *)(data + raster * height);
331
 
    while ((const byte *)lp > data && !lp[-1])
332
 
        --lp;
333
 
    if ((const byte *)lp == data) {
334
 
        pbox->p.x = pbox->q.x = pbox->p.y = pbox->q.y = 0;
335
 
        return;
336
 
    }
337
 
    pbox->q.y = height = ((const byte *)lp - data + raster - 1) / raster;
338
 
 
339
 
    /* Count leading blank rows. */
340
 
 
341
 
    lp = (const ulong *)data;
342
 
    while (!*lp)
343
 
        ++lp;
344
 
    {
345
 
        uint n = ((const byte *)lp - data) / raster;
346
 
 
347
 
        pbox->p.y = n;
348
 
        if (n)
349
 
            height -= n, data += n * raster;
350
 
    }
351
 
 
352
 
    /* Find the left and right edges. */
353
 
    /* We know that the first and last rows are non-blank. */
354
 
 
355
 
    {
356
 
        uint raster_longs = raster >> arch_log2_sizeof_long;
357
 
        uint left = raster_longs - 1, right = 0;
358
 
        ulong llong = 0, rlong = 0;
359
 
        const byte *q;
360
 
        uint h, n;
361
 
 
362
 
        for (q = data, h = height; h-- > 0; q += raster) {      /* Work from the left edge by longs. */
363
 
            for (lp = (const ulong *)q, n = 0;
364
 
                 n < left && !*lp; lp++, n++
365
 
                );
366
 
            if (n < left)
367
 
                left = n, llong = *lp;
368
 
            else
369
 
                llong |= *lp;
370
 
            /* Work from the right edge by longs. */
371
 
            for (lp = (const ulong *)(q + raster - sizeof(long)),
372
 
                 n = raster_longs - 1;
373
 
 
374
 
                 n > right && !*lp; lp--, n--
375
 
                );
376
 
            if (n > right)
377
 
                right = n, rlong = *lp;
378
 
            else
379
 
                rlong |= *lp;
380
 
        }
381
 
 
382
 
        /* Do binary subdivision on edge longs.  We assume that */
383
 
        /* sizeof(long) = 4 or 8. */
384
 
#if arch_sizeof_long > 8
385
 
        Error_longs_are_too_large();
386
 
#endif
387
 
 
388
 
#if arch_is_big_endian
389
 
#  define last_bits(n) ((1L << (n)) - 1)
390
 
#  define shift_out_last(x,n) ((x) >>= (n))
391
 
#  define right_justify_last(x,n) DO_NOTHING
392
 
#else
393
 
#  define last_bits(n) (-1L << ((arch_sizeof_long * 8) - (n)))
394
 
#  define shift_out_last(x,n) ((x) <<= (n))
395
 
#  define right_justify_last(x,n) (x) >>= ((arch_sizeof_long * 8) - (n))
396
 
#endif
397
 
 
398
 
        left <<= arch_log2_sizeof_long + 3;
399
 
#if arch_sizeof_long == 8
400
 
        if (llong & ~last_bits(32))
401
 
            shift_out_last(llong, 32);
402
 
        else
403
 
            left += 32;
404
 
#endif
405
 
        if (llong & ~last_bits(16))
406
 
            shift_out_last(llong, 16);
407
 
        else
408
 
            left += 16;
409
 
        if (llong & ~last_bits(8))
410
 
            shift_out_last(llong, 8);
411
 
        else
412
 
            left += 8;
413
 
        right_justify_last(llong, 8);
414
 
        if (llong & 0xf0)
415
 
            left += first_1[(byte) llong >> 4];
416
 
        else
417
 
            left += first_1[(byte) llong] + 4;
418
 
 
419
 
        right <<= arch_log2_sizeof_long + 3;
420
 
#if arch_sizeof_long == 8
421
 
        if (!(rlong & last_bits(32)))
422
 
            shift_out_last(rlong, 32);
423
 
        else
424
 
            right += 32;
425
 
#endif
426
 
        if (!(rlong & last_bits(16)))
427
 
            shift_out_last(rlong, 16);
428
 
        else
429
 
            right += 16;
430
 
        if (!(rlong & last_bits(8)))
431
 
            shift_out_last(rlong, 8);
432
 
        else
433
 
            right += 8;
434
 
        right_justify_last(rlong, 8);
435
 
        if (!(rlong & 0xf))
436
 
            right += last_1[(byte) rlong >> 4];
437
 
        else
438
 
            right += last_1[(uint) rlong & 0xf] + 4;
439
 
 
440
 
        pbox->p.x = left;
441
 
        pbox->q.x = right;
442
 
    }
443
 
}
444
 
 
445
 
/* Extract a plane from a pixmap. */
446
 
int
447
 
bits_extract_plane(const bits_plane_t *dest /*write*/,
448
 
    const bits_plane_t *source /*read*/, int shift, int width, int height)
449
 
{
450
 
    int source_depth = source->depth;
451
 
    int source_bit = source->x * source_depth;
452
 
    const byte *source_row = source->data.read + (source_bit >> 3);
453
 
    int dest_depth = dest->depth;
454
 
    uint plane_mask = (1 << dest_depth) - 1;
455
 
    int dest_bit = dest->x * dest_depth;
456
 
    byte *dest_row = dest->data.write + (dest_bit >> 3);
457
 
    enum {
458
 
        EXTRACT_SLOW = 0,
459
 
        EXTRACT_4_TO_1,
460
 
        EXTRACT_32_TO_8
461
 
    } loop_case = EXTRACT_SLOW;
462
 
    int y;
463
 
 
464
 
    source_bit &= 7;
465
 
    dest_bit &= 7;
466
 
    /* Check for the fast CMYK cases. */
467
 
    if (!(source_bit | dest_bit)) {
468
 
        switch (source_depth) {
469
 
        case 4:
470
 
            loop_case =
471
 
                (dest_depth == 1 && !(source->raster & 3) &&
472
 
                 !(source->x & 1) ? EXTRACT_4_TO_1 :
473
 
                 EXTRACT_SLOW);
474
 
            break;
475
 
        case 32:
476
 
            if (dest_depth == 8 && !(shift & 7)) {
477
 
                loop_case = EXTRACT_32_TO_8;
478
 
                source_row += 3 - (shift >> 3);
479
 
            }
480
 
            break;
481
 
        }
482
 
    }
483
 
    for (y = 0; y < height;
484
 
         ++y, source_row += source->raster, dest_row += dest->raster
485
 
        ) {
486
 
        int x;
487
 
 
488
 
        switch (loop_case) {
489
 
        case EXTRACT_4_TO_1: {
490
 
            const byte *source = source_row;
491
 
            byte *dest = dest_row;
492
 
 
493
 
            /* Do groups of 8 pixels. */
494
 
            for (x = width; x >= 8; source += 4, x -= 8) {
495
 
                bits32 sword =
496
 
                    (*(const bits32 *)source >> shift) & 0x11111111;
497
 
 
498
 
                *dest++ =
499
 
                    byte_acegbdfh_to_abcdefgh[(
500
 
#if arch_is_big_endian
501
 
                    (sword >> 21) | (sword >> 14) | (sword >> 7) | sword
502
 
#else
503
 
                    (sword << 3) | (sword >> 6) | (sword >> 15) | (sword >> 24)
504
 
#endif
505
 
                                        ) & 0xff];
506
 
            }
507
 
            if (x) {
508
 
                /* Do the final 1-7 pixels. */
509
 
                uint test = 0x10 << shift, store = 0x80;
510
 
 
511
 
                do {
512
 
                    *dest = (*source & test ? *dest | store : *dest & ~store);
513
 
                    if (test >= 0x10)
514
 
                        test >>= 4;
515
 
                    else
516
 
                        test <<= 4, ++source;
517
 
                    store >>= 1;
518
 
                } while (--x > 0);
519
 
            }
520
 
            break;
521
 
        }
522
 
        case EXTRACT_32_TO_8: {
523
 
            const byte *source = source_row;
524
 
            byte *dest = dest_row;
525
 
 
526
 
            for (x = width; x > 0; source += 4, --x)
527
 
                *dest++ = *source;
528
 
            break;
529
 
        }
530
 
        default: {
531
 
            sample_load_declare_setup(sptr, sbit, source_row, source_bit,
532
 
                                      source_depth);
533
 
            sample_store_declare_setup(dptr, dbit, dbbyte, dest_row, dest_bit,
534
 
                                       dest_depth);
535
 
 
536
 
            sample_store_preload(dbbyte, dptr, dbit, dest_depth);
537
 
            for (x = width; x > 0; --x) {
538
 
                gx_color_index color;
539
 
                uint pixel;
540
 
 
541
 
                sample_load_next_any(color, sptr, sbit, source_depth);
542
 
                pixel = (color >> shift) & plane_mask;
543
 
                sample_store_next8(pixel, dptr, dbit, dest_depth, dbbyte);
544
 
            }
545
 
            sample_store_flush(dptr, dbit, dest_depth, dbbyte);
546
 
        }
547
 
        }
548
 
    }
549
 
    return 0;
550
 
}
551
 
 
552
 
/* Expand a plane into a pixmap. */
553
 
int
554
 
bits_expand_plane(const bits_plane_t *dest /*write*/,
555
 
    const bits_plane_t *source /*read*/, int shift, int width, int height)
556
 
{
557
 
    /*
558
 
     * Eventually we will optimize this just like bits_extract_plane.
559
 
     */
560
 
    int source_depth = source->depth;
561
 
    int source_bit = source->x * source_depth;
562
 
    const byte *source_row = source->data.read + (source_bit >> 3);
563
 
    int dest_depth = dest->depth;
564
 
    int dest_bit = dest->x * dest_depth;
565
 
    byte *dest_row = dest->data.write + (dest_bit >> 3);
566
 
    enum {
567
 
        EXPAND_SLOW = 0,
568
 
        EXPAND_1_TO_4,
569
 
        EXPAND_8_TO_32
570
 
    } loop_case = EXPAND_SLOW;
571
 
    int y;
572
 
 
573
 
    source_bit &= 7;
574
 
    /* Check for the fast CMYK cases. */
575
 
    if (!(source_bit || (dest_bit & 31) || (dest->raster & 3))) {
576
 
        switch (dest_depth) {
577
 
        case 4:
578
 
            if (source_depth == 1)
579
 
                loop_case = EXPAND_1_TO_4;
580
 
            break;
581
 
        case 32:
582
 
            if (source_depth == 8 && !(shift & 7))
583
 
                loop_case = EXPAND_8_TO_32;
584
 
            break;
585
 
        }
586
 
    }
587
 
    dest_bit &= 7;
588
 
    switch (loop_case) {
589
 
 
590
 
    case EXPAND_8_TO_32: {
591
 
#if arch_is_big_endian
592
 
#  define word_shift (shift)
593
 
#else
594
 
        int word_shift = 24 - shift;
595
 
#endif
596
 
        for (y = 0; y < height;
597
 
             ++y, source_row += source->raster, dest_row += dest->raster
598
 
             ) {
599
 
            int x;
600
 
            const byte *source = source_row;
601
 
            bits32 *dest = (bits32 *)dest_row;
602
 
 
603
 
            for (x = width; x > 0; --x)
604
 
                *dest++ = (bits32)(*source++) << word_shift;
605
 
        }
606
 
#undef word_shift
607
 
    }
608
 
        break;
609
 
 
610
 
    case EXPAND_1_TO_4:
611
 
    default:
612
 
        for (y = 0; y < height;
613
 
             ++y, source_row += source->raster, dest_row += dest->raster
614
 
             ) {
615
 
            int x;
616
 
            sample_load_declare_setup(sptr, sbit, source_row, source_bit,
617
 
                                      source_depth);
618
 
            sample_store_declare_setup(dptr, dbit, dbbyte, dest_row, dest_bit,
619
 
                                       dest_depth);
620
 
 
621
 
            sample_store_preload(dbbyte, dptr, dbit, dest_depth);
622
 
            for (x = width; x > 0; --x) {
623
 
                uint color;
624
 
                gx_color_index pixel;
625
 
 
626
 
                sample_load_next8(color, sptr, sbit, source_depth);
627
 
                pixel = color << shift;
628
 
                sample_store_next_any(pixel, dptr, dbit, dest_depth, dbbyte);
629
 
            }
630
 
            sample_store_flush(dptr, dbit, dest_depth, dbbyte);
631
 
        }
632
 
        break;
633
 
 
634
 
    }
635
 
    return 0;
636
 
}
637
 
 
638
 
/* ---------------- Byte-oriented operations ---------------- */
639
 
 
640
 
/* Fill a rectangle of bytes. */
641
 
void
642
 
bytes_fill_rectangle(byte * dest, uint raster,
643
 
                     byte value, int width_bytes, int height)
644
 
{
645
 
    while (height-- > 0) {
646
 
        memset(dest, value, width_bytes);
647
 
        dest += raster;
648
 
    }
649
 
}
650
 
 
651
 
/* Copy a rectangle of bytes. */
652
 
void
653
 
bytes_copy_rectangle(byte * dest, uint dest_raster,
654
 
             const byte * src, uint src_raster, int width_bytes, int height)
655
 
{
656
 
    while (height-- > 0) {
657
 
        memcpy(dest, src, width_bytes);
658
 
        src += src_raster;
659
 
        dest += dest_raster;
660
 
    }
661
 
}