Coverage Report

Created: 2025-06-10 07:19

/src/ghostpdl/base/gdevm24.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 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,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
/* 24-bit-per-pixel "memory" (stored bitmap) device */
17
#include "memory_.h"
18
#include "gx.h"
19
#include "gxdevice.h"
20
#include "gxdevmem.h"   /* semi-public definitions */
21
#include "gdevmem.h"    /* private definitions */
22
23
#define mem_true24_strip_copy_rop2 mem_gray8_rgb24_strip_copy_rop2
24
25
/*
26
 * Define whether to use the library's memset.
27
 */
28
#define USE_MEMSET
29
30
/*
31
 * Define whether to use memcpy for very wide fills.
32
 */
33
/*#define USE_MEMCPY*/
34
35
/* Define debugging statistics. */
36
/* #define COLLECT_STATS_MEM24 */
37
38
#ifdef COLLECT_STATS_MEM24
39
struct stats_mem24_s {
40
    long
41
        fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
42
        fprevc[257];
43
    double ftotal;
44
} stats_mem24;
45
static int prev_count = 0;
46
static uint prev_colors[256];
47
# define INCR(v) (++(stats_mem24.v))
48
#else
49
27.7k
# define INCR(v) DO_NOTHING
50
#endif
51
52
/* ================ Standard (byte-oriented) device ================ */
53
54
#undef chunk
55
#define chunk byte
56
57
/* Procedures */
58
declare_mem_procs(mem_true24_copy_mono, mem_true24_copy_color, mem_true24_fill_rectangle);
59
static dev_proc_copy_alpha(mem_true24_copy_alpha);
60
61
/* The device descriptor. */
62
const gx_device_memory mem_true24_device =
63
    mem_device("image24", 24, 0, mem_dev_initialize_device_procs);
64
65
const gdev_mem_functions gdev_mem_fns_24 =
66
{
67
    gx_default_rgb_map_rgb_color,
68
    gx_default_rgb_map_color_rgb,
69
    mem_true24_fill_rectangle,
70
    mem_true24_copy_mono,
71
    mem_true24_copy_color,
72
    mem_true24_copy_alpha,
73
    gx_default_strip_tile_rectangle,
74
    mem_true24_strip_copy_rop2,
75
    mem_get_bits_rectangle
76
};
77
78
/* Convert x coordinate to byte offset in scan line. */
79
#undef x_to_byte
80
9.49k
#define x_to_byte(x) ((x) * 3)
81
82
/* Unpack a color into its bytes. */
83
#define declare_unpack_color(r, g, b, color)\
84
9.49k
        byte r = (byte)(color >> 16);\
85
9.49k
        byte g = (byte)((uint)color >> 8);\
86
9.49k
        byte b = (byte)color
87
/* Put a 24-bit color into the bitmap. */
88
#define put3(ptr, r, g, b)\
89
3.77k
        (ptr)[0] = r, (ptr)[1] = g, (ptr)[2] = b
90
/* Put 4 bytes of color into the bitmap. */
91
#define putw(ptr, wxyz)\
92
1.31M
        *(bits32 *)(ptr) = (wxyz)
93
/* Load the 3-word 24-bit-color cache. */
94
/* Free variables: [m]dev, rgbr, gbrg, brgb. */
95
#if ARCH_IS_BIG_ENDIAN
96
#  define set_color24_cache(crgb, r, g, b)\
97
        mdev->color24.rgbr = rgbr = ((bits32)(crgb) << 8) | (r),\
98
        mdev->color24.gbrg = gbrg = (rgbr << 8) | (g),\
99
        mdev->color24.brgb = brgb = (gbrg << 8) | (b),\
100
        mdev->color24.rgb = (crgb)
101
#else
102
#  define set_color24_cache(crgb, r, g, b)\
103
3.65k
        mdev->color24.rgbr = rgbr =\
104
3.65k
                ((bits32)(r) << 24) | ((bits32)(b) << 16) |\
105
3.65k
                ((bits16)(g) << 8) | (r),\
106
3.65k
        mdev->color24.brgb = brgb = (rgbr << 8) | (b),\
107
3.65k
        mdev->color24.gbrg = gbrg = (brgb << 8) | (g),\
108
3.65k
        mdev->color24.rgb = (crgb)
109
#endif
110
111
/* Fill a rectangle with a color. */
112
static int
113
mem_true24_fill_rectangle(gx_device * dev,
114
                          int x, int y, int w, int h, gx_color_index color)
115
9.49k
{
116
9.49k
    gx_device_memory * const mdev = (gx_device_memory *)dev;
117
9.49k
    declare_unpack_color(r, g, b, color);
118
9.49k
    declare_scan_ptr(dest);
119
120
9.49k
    if_debug4m('b', dev->memory,
121
9.49k
               "[b]device y=%d h=%d x=%d w=%d\n", y + mdev->band_y, h, x, w);
122
    /*
123
     * In order to avoid testing w > 0 and h > 0 twice, we defer
124
     * executing setup_rect, and use fit_fill_xywh instead of
125
     * fit_fill.
126
     */
127
9.49k
    fit_fill_xywh(dev, x, y, w, h);
128
9.49k
    INCR(fill);
129
#ifdef COLLECT_STATS_MEM24
130
    stats_mem24.ftotal += w;
131
#endif
132
9.49k
    if (w >= 5) {
133
5.10k
        if (h <= 0)
134
0
            return 0;
135
5.10k
        INCR(fwide);
136
5.10k
        setup_rect(dest);
137
5.10k
        if (r == g && r == b) {
138
#ifndef USE_MEMSET
139
            /* We think we can do better than the library's memset.... */
140
            int bcntm7 = w * 3 - 7;
141
            register bits32 cword = color | (color << 24);
142
143
            INCR(fgray[min(w, 100)]);
144
            while (h-- > 0) {
145
                register byte *pptr = dest;
146
                byte *limit = pptr + bcntm7;
147
148
                /* We want to store full words, but we have to */
149
                /* guarantee that they are word-aligned. */
150
                switch (x & 3) {
151
                    case 3:
152
                        *pptr++ = (byte) cword;
153
                    case 2:
154
                        *pptr++ = (byte) cword;
155
                    case 1:
156
                        *pptr++ = (byte) cword;
157
                    case 0:;
158
                }
159
                /* Even with w = 5, we always store at least */
160
                /* 3 full words, regardless of the starting x. */
161
                *(bits32 *) pptr =
162
                    ((bits32 *) pptr)[1] =
163
                    ((bits32 *) pptr)[2] = cword;
164
                pptr += 12;
165
                while (pptr < limit) {
166
                    *(bits32 *) pptr =
167
                        ((bits32 *) pptr)[1] = cword;
168
                    pptr += 8;
169
                }
170
                switch ((int)(pptr - limit)) {
171
                    case 0:
172
                        pptr[6] = (byte) cword;
173
                    case 1:
174
                        pptr[5] = (byte) cword;
175
                    case 2:
176
                        pptr[4] = (byte) cword;
177
                    case 3:
178
                        *(bits32 *) pptr = cword;
179
                        break;
180
                    case 4:
181
                        pptr[2] = (byte) cword;
182
                    case 5:
183
                        pptr[1] = (byte) cword;
184
                    case 6:
185
                        pptr[0] = (byte) cword;
186
                    case 7:;
187
                }
188
                inc_ptr(dest, draster);
189
            }
190
#else
191
273
            int bcnt = w * 3;
192
193
273
            INCR(fgray[min(w, 100)]);
194
11.3k
            while (h-- > 0) {
195
11.1k
                memset(dest, r, bcnt);
196
11.1k
                inc_ptr(dest, draster);
197
11.1k
            }
198
273
#endif
199
4.82k
        } else {
200
4.82k
            int x3 = -x & 3, ww = w - x3; /* we know ww >= 2 */
201
4.82k
            bits32 rgbr, gbrg, brgb;
202
203
4.82k
            if (mdev->color24.rgb == color) {
204
1.17k
                rgbr = mdev->color24.rgbr;
205
1.17k
                gbrg = mdev->color24.gbrg;
206
1.17k
                brgb = mdev->color24.brgb;
207
3.65k
            } else {
208
3.65k
                INCR(fsetc);
209
3.65k
                set_color24_cache(color, r, g, b);
210
3.65k
            }
211
#ifdef COLLECT_STATS_MEM24
212
            {
213
                int ci;
214
                for (ci = 0; ci < prev_count; ++ci)
215
                    if (prev_colors[ci] == color)
216
                        break;
217
                INCR(fprevc[ci]);
218
                if (ci == prev_count) {
219
                    if (ci < countof(prev_colors))
220
                        ++prev_count;
221
                    else
222
                        --ci;
223
                }
224
                if (ci)
225
                    memmove(&prev_colors[1], &prev_colors[0],
226
                            ci * sizeof(prev_colors[0]));
227
                prev_colors[0] = color;
228
            }
229
#endif
230
4.82k
            INCR(fcolor[min(w, 100)]);
231
18.2k
            while (h-- > 0) {
232
13.4k
                register byte *pptr = dest;
233
13.4k
                int w1 = ww;
234
235
13.4k
                switch (x3) {
236
1.89k
                    case 1:
237
1.89k
                        put3(pptr, r, g, b);
238
1.89k
                        pptr += 3;
239
1.89k
                        break;
240
1.19k
                    case 2:
241
1.19k
                        pptr[0] = r;
242
1.19k
                        pptr[1] = g;
243
1.19k
                        putw(pptr + 2, brgb);
244
1.19k
                        pptr += 6;
245
1.19k
                        break;
246
2.34k
                    case 3:
247
2.34k
                        pptr[0] = r;
248
2.34k
                        putw(pptr + 1, gbrg);
249
2.34k
                        putw(pptr + 5, brgb);
250
2.34k
                        pptr += 9;
251
2.34k
                        break;
252
8.00k
                    case 0:
253
8.00k
                        ;
254
13.4k
                }
255
#ifdef USE_MEMCPY
256
                /*
257
                 * For very wide fills, it's most efficient to fill a few
258
                 * pixels and then use memcpy to fill the rest.
259
                 */
260
                if (w1 > 16) {
261
#define PUTW4(ptr, w)\
262
  BEGIN\
263
    putw(ptr, w); putw((ptr)+12, w); putw((ptr)+24, w); putw((ptr)+36, w);\
264
  END
265
                    PUTW4(pptr, rgbr);
266
                    PUTW4(pptr + 4, gbrg);
267
                    PUTW4(pptr + 8, brgb);
268
#undef PUTW4
269
                    if (w1 > 64) {
270
                        memcpy(pptr + 48, pptr, 48);
271
                        memcpy(pptr + 96, pptr, 96);
272
                        for (pptr += 192; (w1 -= 64) >= 64; pptr += 192)
273
                            memcpy(pptr, pptr - 192, 192);
274
                    } else
275
                        pptr += 48;
276
                    for (; (w1 -= 16) >= 16; pptr += 48)
277
                        memcpy(pptr, pptr - 48, 48);
278
                }
279
#endif
280
446k
                while (w1 >= 4) {
281
432k
                    putw(pptr, rgbr);
282
432k
                    putw(pptr + 4, gbrg);
283
432k
                    putw(pptr + 8, brgb);
284
432k
                    pptr += 12;
285
432k
                    w1 -= 4;
286
432k
                }
287
13.4k
                switch (w1) {
288
1.88k
                    case 1:
289
1.88k
                        put3(pptr, r, g, b);
290
1.88k
                        break;
291
1.67k
                    case 2:
292
1.67k
                        putw(pptr, rgbr);
293
1.67k
                        pptr[4] = g;
294
1.67k
                        pptr[5] = b;
295
1.67k
                        break;
296
3.48k
                    case 3:
297
3.48k
                        putw(pptr, rgbr);
298
3.48k
                        putw(pptr + 4, gbrg);
299
3.48k
                        pptr[8] = b;
300
3.48k
                        break;
301
6.40k
                    case 0:
302
6.40k
                        ;
303
13.4k
                }
304
13.4k
                inc_ptr(dest, draster);
305
13.4k
            }
306
4.82k
        }
307
5.10k
    } else if (h > 0) {   /* w < 5 */
308
4.38k
        INCR(fnarrow[max(w, 0)]);
309
4.38k
        setup_rect(dest);
310
4.38k
        switch (w) {
311
0
            case 4:
312
0
                do {
313
0
                    dest[9] = dest[6] = dest[3] = dest[0] = r;
314
0
                    dest[10] = dest[7] = dest[4] = dest[1] = g;
315
0
                    dest[11] = dest[8] = dest[5] = dest[2] = b;
316
0
                    inc_ptr(dest, draster);
317
0
                }
318
0
                while (--h);
319
0
                break;
320
3.38k
            case 3:
321
9.38k
                do {
322
9.38k
                    dest[6] = dest[3] = dest[0] = r;
323
9.38k
                    dest[7] = dest[4] = dest[1] = g;
324
9.38k
                    dest[8] = dest[5] = dest[2] = b;
325
9.38k
                    inc_ptr(dest, draster);
326
9.38k
                }
327
9.38k
                while (--h);
328
3.38k
                break;
329
1.00k
            case 2:
330
2.78k
                do {
331
2.78k
                    dest[3] = dest[0] = r;
332
2.78k
                    dest[4] = dest[1] = g;
333
2.78k
                    dest[5] = dest[2] = b;
334
2.78k
                    inc_ptr(dest, draster);
335
2.78k
                }
336
2.78k
                while (--h);
337
1.00k
                break;
338
0
            case 1:
339
0
                do {
340
0
                    dest[0] = r, dest[1] = g, dest[2] = b;
341
0
                    inc_ptr(dest, draster);
342
0
                }
343
0
                while (--h);
344
0
                break;
345
0
            case 0:
346
0
            default:
347
0
                ;
348
4.38k
        }
349
4.38k
    }
350
9.49k
    return 0;
351
9.49k
}
352
353
/* Copy a monochrome bitmap. */
354
static int
355
mem_true24_copy_mono(gx_device * dev,
356
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
357
        int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
358
0
{
359
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
360
0
    const byte *line;
361
0
    int sbit;
362
0
    int first_bit;
363
364
0
    declare_scan_ptr(dest);
365
366
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
367
0
    setup_rect(dest);
368
0
    line = base + (sourcex >> 3);
369
0
    sbit = sourcex & 7;
370
0
    first_bit = 0x80 >> sbit;
371
0
    if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */
372
        /* (never used). */
373
0
        declare_unpack_color(r0, g0, b0, zero);
374
0
        declare_unpack_color(r1, g1, b1, one);
375
0
        while (h-- > 0) {
376
0
            register byte *pptr = dest;
377
0
            const byte *sptr = line;
378
0
            register int sbyte = *sptr++;
379
0
            register int bit = first_bit;
380
0
            int count = w;
381
382
0
            do {
383
0
                if (sbyte & bit) {
384
0
                    if (one != gx_no_color_index) {
385
0
                        put3(pptr, r1, g1, b1);
386
0
                    }
387
0
                } else {
388
0
                    put3(pptr, r0, g0, b0);
389
0
                }
390
391
0
                pptr += 3;
392
0
                count--;
393
394
0
                if (count == 0)
395
0
                    break;
396
397
0
                if ((bit >>= 1) == 0) {
398
0
                    bit = 0x80;
399
0
                    sbyte = *sptr++;
400
0
                }
401
402
0
            } while (true);
403
404
0
            line += sraster;
405
0
            inc_ptr(dest, draster);
406
0
        }
407
0
    } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */
408
        /* This is used heavily. */
409
0
        declare_unpack_color(r1, g1, b1, one);
410
0
        int first_mask = first_bit << 1;
411
0
        int first_count, first_skip;
412
413
0
        if (sbit + w > 8)
414
0
            first_mask -= 1,
415
0
                first_count = 8 - sbit;
416
0
        else
417
0
            first_mask -= first_mask >> w,
418
0
                first_count = w;
419
0
        first_skip = first_count * 3;
420
0
        while (h-- > 0) {
421
0
            register byte *pptr = dest;
422
0
            const byte *sptr = line;
423
0
            register int sbyte = *sptr++ & first_mask;
424
0
            int count = w - first_count;
425
426
0
            if (sbyte) {
427
0
                register int bit = first_bit;
428
429
0
                do {
430
0
                    if (sbyte & bit)
431
0
                        put3(pptr, r1, g1, b1);
432
0
                    pptr += 3;
433
0
                }
434
0
                while ((bit >>= 1) & first_mask);
435
0
            } else
436
0
                pptr += first_skip;
437
0
            while (count >= 8) {
438
0
                sbyte = *sptr++;
439
0
                if (sbyte & 0xf0) {
440
0
                    if (sbyte & 0x80)
441
0
                        put3(pptr, r1, g1, b1);
442
0
                    if (sbyte & 0x40)
443
0
                        put3(pptr + 3, r1, g1, b1);
444
0
                    if (sbyte & 0x20)
445
0
                        put3(pptr + 6, r1, g1, b1);
446
0
                    if (sbyte & 0x10)
447
0
                        put3(pptr + 9, r1, g1, b1);
448
0
                }
449
0
                if (sbyte & 0xf) {
450
0
                    if (sbyte & 8)
451
0
                        put3(pptr + 12, r1, g1, b1);
452
0
                    if (sbyte & 4)
453
0
                        put3(pptr + 15, r1, g1, b1);
454
0
                    if (sbyte & 2)
455
0
                        put3(pptr + 18, r1, g1, b1);
456
0
                    if (sbyte & 1)
457
0
                        put3(pptr + 21, r1, g1, b1);
458
0
                }
459
0
                pptr += 24;
460
0
                count -= 8;
461
0
            }
462
0
            if (count > 0) {
463
0
                register int bit = 0x80;
464
465
0
                sbyte = *sptr++;
466
0
                do {
467
0
                    if (sbyte & bit)
468
0
                        put3(pptr, r1, g1, b1);
469
0
                    pptr += 3;
470
0
                    bit >>= 1;
471
0
                }
472
0
                while (--count > 0);
473
0
            }
474
0
            line += sraster;
475
0
            inc_ptr(dest, draster);
476
0
        }
477
0
    }
478
0
    return 0;
479
0
}
480
481
/* Copy a color bitmap. */
482
static int
483
mem_true24_copy_color(gx_device * dev,
484
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
485
                      int x, int y, int w, int h)
486
0
{
487
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
488
489
0
    if_debug1m('w', dev->memory, "[w]device y=%d:\n",
490
0
               y + mdev->band_y); /* See siscale.c about 'w'. */
491
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
492
0
    mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
493
0
    return 0;
494
0
}
495
496
/* Copy an alpha map. */
497
static int
498
mem_true24_copy_alpha(gx_device * dev, const byte * base, int sourcex,
499
                   int sraster, gx_bitmap_id id, int x, int y, int w, int h,
500
                      gx_color_index color, int depth)
501
0
{
502
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
503
0
    const byte *line;
504
505
0
    declare_scan_ptr(dest);
506
0
    declare_unpack_color(r, g, b, color);
507
508
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
509
0
    setup_rect(dest);
510
0
    line = base;
511
0
    while (h-- > 0) {
512
0
        register byte *pptr = dest;
513
0
        int sx;
514
515
0
        for (sx = sourcex; sx < sourcex + w; ++sx, pptr += 3) {
516
0
            int alpha2, alpha;
517
518
0
            switch(depth)
519
0
            {
520
0
            case 2: /* map 0 - 3 to 0 - 255 */
521
0
                alpha =
522
0
                    ((line[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 85;
523
0
                break;
524
0
            case 4:
525
0
                alpha2 = line[sx >> 1];
526
0
                alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4) * 17;
527
0
                break;
528
0
            case 8:
529
0
                alpha = line[sx];
530
0
                break;
531
0
            default:
532
0
                return_error(gs_error_rangecheck);
533
0
            }
534
0
            if (alpha == 255) { /* Just write the new color. */
535
0
                put3(pptr, r, g, b);
536
0
            } else if (alpha != 0) { /* Blend RGB values. */
537
0
                alpha += alpha>>7;
538
0
#define make_shade(old, clr, alpha) \
539
0
  ((((old)<<8) + ((int)(clr) - (int)(old)) * (alpha))>>8)
540
0
                pptr[0] = make_shade(pptr[0], r, alpha);
541
0
                pptr[1] = make_shade(pptr[1], g, alpha);
542
0
                pptr[2] = make_shade(pptr[2], b, alpha);
543
0
#undef make_shade
544
0
            }
545
0
        }
546
0
        line += sraster;
547
0
        inc_ptr(dest, draster);
548
0
    }
549
0
    return 0;
550
0
}
551
552
/* ================ "Word"-oriented device ================ */
553
554
/* Note that on a big-endian machine, this is the same as the */
555
/* standard byte-oriented-device. */
556
557
#if !ARCH_IS_BIG_ENDIAN
558
559
/* Procedures */
560
declare_mem_procs(mem24_word_copy_mono, mem24_word_copy_color, mem24_word_fill_rectangle);
561
562
/* Here is the device descriptor. */
563
const gx_device_memory mem_true24_word_device =
564
    mem_device("image24w", 24, 0, mem_word_dev_initialize_device_procs);
565
566
const gdev_mem_functions gdev_mem_fns_24w =
567
{
568
    gx_default_rgb_map_rgb_color,
569
    gx_default_rgb_map_color_rgb,
570
    mem24_word_fill_rectangle,
571
    mem24_word_copy_mono,
572
    mem24_word_copy_color,
573
    gx_default_copy_alpha,
574
    gx_default_strip_tile_rectangle,
575
    gx_no_strip_copy_rop2,
576
    mem_word_get_bits_rectangle
577
};
578
579
/* Fill a rectangle with a color. */
580
static int
581
mem24_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
582
                          gx_color_index color)
583
0
{
584
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
585
0
    byte *base;
586
0
    size_t raster;
587
588
0
    fit_fill(dev, x, y, w, h);
589
0
    base = scan_line_base(mdev, y);
590
0
    raster = mdev->raster;
591
0
    mem_swap_byte_rect(base, raster, x * 24, w * 24, h, true);
592
0
    mem_true24_fill_rectangle(dev, x, y, w, h, color);
593
0
    mem_swap_byte_rect(base, raster, x * 24, w * 24, h, false);
594
0
    return 0;
595
0
}
596
597
/* Copy a bitmap. */
598
static int
599
mem24_word_copy_mono(gx_device * dev,
600
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
601
        int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
602
0
{
603
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
604
0
    byte *row;
605
0
    size_t raster;
606
0
    bool store;
607
608
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
609
0
    row = scan_line_base(mdev, y);
610
0
    raster = mdev->raster;
611
0
    store = (zero != gx_no_color_index && one != gx_no_color_index);
612
0
    mem_swap_byte_rect(row, raster, x * 24, w * 24, h, store);
613
0
    mem_true24_copy_mono(dev, base, sourcex, sraster, id,
614
0
                         x, y, w, h, zero, one);
615
0
    mem_swap_byte_rect(row, raster, x * 24, w * 24, h, false);
616
0
    return 0;
617
0
}
618
619
/* Copy a color bitmap. */
620
static int
621
mem24_word_copy_color(gx_device * dev,
622
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
623
                      int x, int y, int w, int h)
624
0
{
625
0
    gx_device_memory * const mdev = (gx_device_memory *)dev;
626
0
    byte *row;
627
0
    size_t raster;
628
629
0
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
630
0
    row = scan_line_base(mdev, y);
631
0
    raster = mdev->raster;
632
0
    mem_swap_byte_rect(row, raster, x * 24, w * 24, h, true);
633
0
    bytes_copy_rectangle(row + x * 3, raster, base + sourcex * 3, sraster,
634
0
                         w * 3, h);
635
0
    mem_swap_byte_rect(row, raster, x * 24, w * 24, h, false);
636
0
    return 0;
637
0
}
638
639
#endif /* !ARCH_IS_BIG_ENDIAN */