1 /* Copyright (C) 2001-2019 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.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Fast monochrome image rendering */
18 #include "gx.h"
19 #include "memory_.h"
20 #include "gpcheck.h"
21 #include "gsbittab.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 "gxgstate.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 #include "valgrind.h"
40 
41 /* Conditionally include statistics code. */
42 #if defined(DEBUG) && !defined(GS_THREADSAFE)
43 #  define STATS
44 #endif
45 
46 /* ------ Strategy procedure ------ */
47 
48 /* Check the prototype. */
49 iclass_proc(gs_image_class_1_simple);
50 
51 /* Use special fast logic for portrait or landscape black-and-white images. */
52 static irender_proc(image_render_skip);
53 static irender_proc(image_render_simple);
54 static irender_proc(image_render_landscape);
55 
56 int
gs_image_class_1_simple(gx_image_enum * penum,irender_proc_t * render_fn)57 gs_image_class_1_simple(gx_image_enum * penum, irender_proc_t *render_fn)
58 {
59     fixed ox = dda_current(penum->dda.pixel0.x);
60     fixed oy = dda_current(penum->dda.pixel0.y);
61 
62     if (penum->use_rop || penum->spp != 1 || penum->bps != 1)
63         return 0;
64     switch (penum->posture) {
65         case image_portrait:
66             {			/* Use fast portrait algorithm. */
67                 long dev_width =
68                     fixed2long_pixround(ox + penum->x_extent.x) -
69                     fixed2long_pixround(ox);
70 
71                 if (dev_width != penum->rect.w) {
72                     /*
73                      * Add an extra align_bitmap_mod of padding so that
74                      * we can align scaled rows with the device.
75                      */
76                     long line_size =
77                         bitmap_raster(any_abs(dev_width)) + align_bitmap_mod;
78 
79                     if (penum->adjust != 0 || line_size > max_uint)
80                         return 0;
81                     /* Must buffer a scan line. */
82                     penum->line_width = any_abs(dev_width);
83                     penum->line_size = (uint) line_size;
84                     penum->line = gs_alloc_bytes(penum->memory,
85                                             penum->line_size, "image line");
86                     if (penum->line == 0) {
87                         return gs_error_VMerror;
88                     }
89                 }
90                 if_debug2m('b', penum->memory, "[b]render=simple, unpack=copy; rect.w=%d, dev_width=%ld\n",
91                            penum->rect.w, dev_width);
92                 *render_fn = image_render_simple;
93                 break;
94             }
95         case image_landscape:
96             {			/* Use fast landscape algorithm. */
97                 long dev_width =
98                     fixed2long_pixround(oy + penum->x_extent.y) -
99                     fixed2long_pixround(oy);
100                 long line_size =
101                     (dev_width = any_abs(dev_width),
102                      bitmap_raster(dev_width) * 8 +
103                      ROUND_UP(dev_width, 8) * align_bitmap_mod);
104 
105                 if ((dev_width != penum->rect.w && penum->adjust != 0) ||
106                     line_size > max_uint
107                     )
108                     return 0;
109                 /* Must buffer a group of 8N scan lines. */
110                 penum->line_width = dev_width;
111                 penum->line_size = (uint) line_size;
112                 penum->line = gs_alloc_bytes(penum->memory,
113                                              penum->line_size, "image line");
114                 if (penum->line == 0) {
115                     return gs_error_VMerror;
116                 }
117 #ifdef PACIFY_VALGRIND
118                 memset(penum->line, 0, penum->line_size); /* For the number of scan lined < 8 */
119 #endif
120                 penum->xi_next = penum->line_xy = fixed2int_var_rounded(ox);
121                 if_debug3m('b', penum->memory,
122                            "[b]render=landscape, unpack=copy; rect.w=%d, dev_width=%ld, line_size=%ld\n",
123                            penum->rect.w, dev_width, line_size);
124                 *render_fn = image_render_landscape;
125                 /* Precompute values needed for rasterizing. */
126                 penum->dxy =
127                     float2fixed(penum->matrix.xy +
128                                 fixed2float(fixed_epsilon) / 2);
129                 break;
130             }
131         default:
132             return 0;
133     }
134     /* Precompute values needed for rasterizing. */
135     penum->dxx =
136         float2fixed(penum->matrix.xx + fixed2float(fixed_epsilon) / 2);
137     /*
138      * We don't want to spread the samples, but we have to reset unpack_bps
139      * to prevent the buffer pointer from being incremented by 8 bytes per
140      * input byte.
141      */
142     penum->unpack = sample_unpack_copy;
143     penum->unpack_bps = 8;
144     if (penum->use_mask_color) {
145         /*
146          * Set the masked color as 'no_color' to make it transparent
147          *  according to the mask color range and the decoding.
148          */
149         penum->masked = true;
150         if (penum->mask_color.values[0] == 1) {
151             /* if v0 == 1, 1 is transparent since v1 must be == 1 to be a valid range */
152             set_nonclient_dev_color(penum->map[0].inverted ? penum->icolor0 : penum->icolor1,
153                         gx_no_color_index);
154         } else if (penum->mask_color.values[1] == 0) {
155             /* if v1 == 0, 0 is transparent since v0 must be == 0 to be a valid range */
156             set_nonclient_dev_color(penum->map[0].inverted ? penum->icolor1 : penum->icolor0,
157                         gx_no_color_index);
158         } else {
159             /*
160              * The only other possible in-range value is v0 = 0, v1 = 1.
161              * The image is completely transparent!
162              */
163             *render_fn = image_render_skip;
164         }
165         penum->map[0].decoding = sd_none;
166     }
167     return 0;
168 }
169 
170 /* ------ Rendering procedures ------ */
171 
172 #define DC_IS_NULL(pdc)\
173   (gx_dc_is_pure(pdc) && (pdc)->colors.pure == gx_no_color_index)
174 
175 /* Skip over a completely transparent image. */
176 static int
image_render_skip(gx_image_enum * penum,const byte * buffer,int data_x,uint w,int h,gx_device * dev)177 image_render_skip(gx_image_enum * penum, const byte * buffer, int data_x,
178                   uint w, int h, gx_device * dev)
179 {
180     return h;
181 }
182 
183 /*
184  * Scale (and possibly reverse) one scan line of a monobit image.
185  * This is used for both portrait and landscape image processing.
186  * We pass in an x offset (0 <= line_x < align_bitmap_mod * 8) so that
187  * we can align the result with the eventual device X.
188  *
189  * To be precise, the input to this routine is the w bits starting at
190  * bit data_x in buffer.  These w bits expand to abs(x_extent) bits,
191  * either inverted (zero = 0xff) or not (zero = 0), starting at bit
192  * line_x in line which corresponds to coordinate
193  * fixed2int_pixround(xcur + min(x_extent, 0)).  Note that the entire
194  * bytes containing the first and last output bits are affected: the
195  * other bits in those bytes are set to zero (i.e., the value of the
196  * 'zero' argument).
197  */
198 #ifdef STATS
199 struct stats_image_fast_s {
200     long
201          calls, all0s, all1s, runs, lbit0, byte00, byte01, byte02, byte03,
202          byte04, rbit0, lbit1, byte1, rbit1, thin, thin2, nwide, bwide,
203          nfill, bfill;
204 } stats_image_fast;
205 #  define INCS(stat) ++stats_image_fast.stat
206 #  define ADDS(stat, n) stats_image_fast.stat += n
207 #else
208 #  define INCS(stat) DO_NOTHING
209 #  define ADDS(stat, n) DO_NOTHING
210 #endif
211 static inline void
fill_row(byte * line,int line_x,uint raster,int value)212 fill_row(byte *line, int line_x, uint raster, int value)
213 {
214     memset(line + (line_x >> 3), value, raster - (line_x >> 3));
215 }
216 
217 static void
image_simple_expand(byte * line,int line_x,uint raster,const byte * buffer,int data_x,uint w,fixed xcur,fixed x_extent,byte zero)218 image_simple_expand(byte * line, int line_x, uint raster,
219                     const byte * buffer, int data_x, uint w,
220                     fixed xcur, fixed x_extent, byte zero /* 0 or 0xff */ )
221 {
222     int dbitx = data_x & 7;
223     byte sbit = 0x80 >> dbitx;
224     byte sbitmask = 0xff >> dbitx;
225     uint wx = dbitx + w;
226     gx_dda_fixed xl;
227     gx_dda_step_fixed dxx4, dxx8, dxx16, dxx24, dxx32;
228     register const byte *psrc = buffer + (data_x >> 3);
229 
230     /*
231      * The following 3 variables define the end of the input data row.
232      * We would put them in a struct, except that no compiler that we
233      * know of will optimize individual struct members as though they
234      * were simple variables (e.g., by putting them in registers).
235      *
236      * endp points to the byte that contains the bit just beyond the
237      * end of the row.  endx gives the bit number of this bit within
238      * the byte, with 0 being the *least* significant bit.  endbit is
239      * a mask for this bit.
240      */
241     const byte *endp = psrc + (wx >> 3);
242     int endx = ~wx & 7;
243     byte endbit = 1 << endx;
244 
245     /*
246      * The following 3 variables do the same for start of the last run
247      * of the input row (think of it as a pointer to just beyond the
248      * end of the next-to-last run).
249      */
250     const byte *stop = endp;
251     int stopx;
252     byte stopbit = endbit;
253     byte data;
254     byte one = ~zero;
255     fixed xl0;
256 #ifdef PACIFY_VALGRIND
257     byte vbits;
258 #endif
259 
260     if (w == 0)
261         return;
262     INCS(calls);
263 
264     /* Scan backward for the last transition. */
265     if (stopbit == 0x80)
266         --stop, stopbit = 1;
267     else
268         stopbit <<= 1;
269     /* Now (stop, stopbit) give the last bit of the row. */
270 #ifdef PACIFY_VALGRIND
271     /* Here, we are dealing with a row of bits, rather than bytes.
272      * If the width of the bits is not a multiple of 8, we don't
273      * fill out the last byte, and valgrind (correctly) tracks the
274      * bits in that last byte as being a mix of defined and undefined.
275      * When we are scanning through the row bitwise, everything works
276      * fine, but our "skip whole bytes" code can confuse valgrind.
277      * We know that we won't match the "data == 0xff" for the final
278      * byte (i.e. the undefinedness of some of the bits doesn't matter
279      * to the correctness of the routine), but valgrind is not smart
280      * enough to realise that we know this. Accordingly, we get a false
281      * positive "undefined memory read".
282      * How do we fix this? Well, one way would be to read in the
283      * partial last byte, and explicitly set the undefined bits to
284      * be 0.
285      *   *stop &= ~(stopbit-1);
286      * Unfortunately, stop is a const *, so we can't do that (we could
287      * break const, but it is just conceivable that the caller might
288      * pass the next string of bits out in a later call, and so we
289      * might be corrupting valid data).
290      * Instead, we make a call to a valgrind helper. */
291     VALGRIND_GET_VBITS(stop,&vbits,1);
292     if ((vbits & stopbit)==0) { /* At least our stop bit must be addressable already! */
293       byte zero = 0;
294       VALGRIND_SET_VBITS(stop,&zero,1);
295     }
296 #endif
297     {
298         byte stopmask = -stopbit << 1;
299         byte last = *stop;
300 
301         if (stop == psrc)	/* only 1 input byte */
302             stopmask &= sbitmask;
303         if (last & stopbit) {
304             /* The last bit is a 1: look for a 0-to-1 transition. */
305             if (~last & stopmask) {	/* Transition in last byte. */
306                 last |= stopbit - 1;
307             } else {		/* No transition in the last byte. */
308                 while (stop > psrc && stop[-1] == 0xff)
309                     --stop;
310                 if (stop == psrc ||
311                     (stop == psrc + 1 && !(~*psrc & sbitmask))
312                     ) {
313                     /* The input is all 1s.  Clear the row and exit. */
314                     INCS(all1s);
315                     fill_row(line, line_x, raster, one);
316                     goto end;
317                 }
318                 last = *--stop;
319             }
320             stopx = byte_bit_run_length_0[byte_reverse_bits[last]] - 1;
321         } else {
322             /* The last bit is a 0: look for a 1-to-0 transition. */
323             if (last & stopmask) {	/* Transition in last byte. */
324                 last &= -stopbit;
325             } else {		/* No transition in the last byte. */
326                 while (stop > psrc && stop[-1] == 0)
327                     --stop;
328                 if (stop == psrc ||
329                     (stop == psrc + 1 && !(*psrc & sbitmask))
330                     ) {
331                     /* The input is all 0s.  Clear the row and exit. */
332                     INCS(all0s);
333                     fill_row(line, line_x, raster, zero);
334                     goto end;
335                 }
336                 last = *--stop;
337             }
338             stopx = byte_bit_run_length_0[byte_reverse_bits[last ^ 0xff]] - 1;
339         }
340         if (stopx < 0)
341             stopx = 7, ++stop;
342         stopbit = 1 << stopx;
343     }
344 
345     /* Pre-clear the row. */
346     fill_row(line, line_x, raster, zero);
347 
348 
349     /* Extreme negative values of x_extent cause the xl0 calculation
350      * to explode. Workaround this here. */
351     if (x_extent < min_int + 0x100)
352       x_extent += 0x100;
353 
354     /* Set up the DDAs. */
355     xl0 =
356         (x_extent >= 0 ?
357          fixed_fraction(fixed_pre_pixround(xcur)) :
358          fixed_fraction(fixed_pre_pixround(xcur + x_extent)) - x_extent);
359     xl0 += int2fixed(line_x);
360     /* We should never get a negative x10 here. If we do, all bets are off. */
361     if (xl0 < 0)
362         xl0 = 0, x_extent = 0;
363     dda_init(xl, xl0, x_extent, w);
364     dxx4 = xl.step;
365     dda_step_add(dxx4, xl.step);
366     /* egcc - 2.91.66 generates incorrect code for
367      * dda_step_add(dxx4, dxx4);
368      * Using the temp variable.
369      */
370     dxx8 = dxx4;
371     dda_step_add(dxx4, dxx8);
372     dxx8 = dxx4;
373     dda_step_add(dxx8, dxx4);
374     dxx16 = dxx8;
375     dda_step_add(dxx16, dxx8);
376     dxx24 = dxx16;
377     dda_step_add(dxx24, dxx8);
378     dxx32 = dxx24;
379     dda_step_add(dxx32, dxx8);
380 
381     /*
382      * Loop invariants:
383      *      data = *psrc;
384      *      sbit = 1 << n, 0<=n<=7.
385      */
386     for (data = *psrc;;) {
387         int x0, n, bit;
388         byte *bp;
389         static const byte lmasks[9] = {
390             0xff, 0x7f, 0x3f, 0x1f, 0xf, 7, 3, 1, 0
391         };
392         static const byte rmasks[9] = {
393             0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
394         };
395 
396         INCS(runs);
397 
398         /* Scan a run of zeros. */
399         data ^= 0xff;		/* invert */
400         while (data & sbit) {
401             dda_next(xl);
402             sbit >>= 1;
403             INCS(lbit0);
404         }
405         if (!sbit) {		/* Scan a run of zero bytes. */
406 sw:	    if ((data = psrc[1]) != 0) {
407                 psrc++;
408                 INCS(byte00);
409             } else if ((data = psrc[2]) != 0) {
410                 dda_state_next(xl.state, dxx8);
411                 psrc += 2;
412                 INCS(byte01);
413             } else if ((data = psrc[3]) != 0) {
414                 dda_state_next(xl.state, dxx16);
415                 psrc += 3;
416                 INCS(byte02);
417             } else if ((data = psrc[4]) != 0) {
418                 dda_state_next(xl.state, dxx24);
419                 psrc += 4;
420                 INCS(byte03);
421             } else {
422                 dda_state_next(xl.state, dxx32);
423                 psrc += 4;
424                 INCS(byte04);
425                 goto sw;
426             }
427             if (data > 0xf)
428                 sbit = 0x80;
429             else {
430                 sbit = 0x08;
431                 dda_state_next(xl.state, dxx4);
432             }
433             data ^= 0xff;	/* invert */
434             while (data & sbit) {
435                 dda_next(xl);
436                 sbit >>= 1;
437                 INCS(rbit0);
438             }
439         }
440         x0 = dda_current_fixed2int(xl);
441         if (psrc >= stop && sbit == stopbit) {
442             /*
443              * We've scanned the last run of 0s.
444              * Prepare to fill the final run of 1s.
445              * Use int64_t to avoid overflow.
446              */
447             n = fixed2int((int64_t)xl0 + (int64_t)x_extent) - x0;
448         } else {		/* Scan a run of ones. */
449             /* We know the current bit is a one. */
450             data ^= 0xff;	/* un-invert */
451             do {
452                 dda_next(xl);
453                 sbit >>= 1;
454                 INCS(lbit1);
455             }
456             while (data & sbit);
457             if (!sbit) {	/* Scan a run of 0xff bytes. */
458                 while ((data = *++psrc) == 0xff) {
459                     dda_state_next(xl.state, dxx8);
460                     INCS(byte1);
461                 }
462                 if (data < 0xf0)
463                     sbit = 0x80;
464                 else {
465                     sbit = 0x08;
466                     dda_state_next(xl.state, dxx4);
467                 }
468                 while (data & sbit) {
469                     dda_next(xl);
470                     sbit >>= 1;
471                     INCS(rbit1);
472                 }
473             }
474             n = dda_current_fixed2int(xl) - x0;
475         }
476 
477         /* Fill the run in the scan line. */
478         if (n < 0)
479             x0 += n, n = -n;
480         bp = line + (x0 >> 3);
481         bit = x0 & 7;
482         if ((n += bit) <= 8) {
483             *bp ^= lmasks[bit] - lmasks[n];
484             INCS(thin);
485         } else if ((n -= 8) <= 8) {
486             *bp ^= lmasks[bit];
487             bp[1] ^= rmasks[n];
488             INCS(thin2);
489         } else {
490             *bp++ ^= lmasks[bit];
491             if (n >= 56) {
492                 int nb = n >> 3;
493 
494                 memset(bp, one, nb);
495                 bp += nb;
496                 INCS(nwide);
497                 ADDS(bwide, nb);
498             } else {
499                 ADDS(bfill, n >> 3);
500                 while ((n -= 8) >= 0)
501                     *bp++ = one;
502                 INCS(nfill);
503             }
504             *bp ^= rmasks[n & 7];
505         }
506         if (psrc >= stop && sbit == stopbit)
507             break;
508     }
509  end:
510     VALGRIND_SET_VBITS(stop,&vbits,1);
511 }
512 
513 /* Copy one rendered scan line to the device. */
514 static int
copy_portrait(gx_image_enum * penum,const byte * data,int dx,int raster,int x,int y,int w,int h,gx_device * dev)515 copy_portrait(gx_image_enum * penum, const byte * data, int dx, int raster,
516               int x, int y, int w, int h, gx_device * dev)
517 {
518     const gx_device_color *pdc0;
519     const gx_device_color *pdc1;
520     uint align = ALIGNMENT_MOD(data, align_bitmap_mod);
521 
522     /*
523      * We know that the lookup table maps 1 bit to 1 bit,
524      * so it can only have 2 states: straight-through or invert.
525      */
526     if (penum->map[0].table.lookup4x1to32[0])
527         pdc0 = penum->icolor1, pdc1 = penum->icolor0;
528     else
529         pdc0 = penum->icolor0, pdc1 = penum->icolor1;
530     data -= align;
531     dx += align << 3;
532     if (gx_dc_is_pure(pdc0) && gx_dc_is_pure(pdc1)) {
533         /* Just use copy_mono. */
534         dev_proc_copy_mono((*copy_mono)) =
535             (h == 1 || (raster & (align_bitmap_mod - 1)) == 0 ?
536              dev_proc(dev, copy_mono) : gx_copy_mono_unaligned);
537         return (*copy_mono)
538             (dev, data, dx, raster, gx_no_bitmap_id,
539              x, y, w, h, pdc0->colors.pure, pdc1->colors.pure);
540     }
541     /*
542      * At least one color isn't pure: if the other one is transparent, use
543      * the opaque color's fill_masked procedure.  Note that we use a
544      * slightly unusual representation for transparent here (per
545      * gx_begin_image1): a pure color with pixel value gx_no_color_index.
546      */
547     {
548         const gx_device_color *pdc;
549         bool invert;
550 
551         if (DC_IS_NULL(pdc1)) {
552             pdc = pdc0;
553             invert = true;
554         } else {
555             if (!DC_IS_NULL(pdc0)) {
556                 int code = gx_device_color_fill_rectangle
557                     (pdc0, x, y, w, h, dev, lop_default, NULL);
558 
559                 if (code < 0)
560                     return code;
561             }
562             pdc = pdc1;
563             invert = false;
564         }
565         return (*pdc->type->fill_masked)
566             (pdc, data, dx, raster, gx_no_bitmap_id, x, y, w, h,
567              dev, lop_default, invert);
568 
569     }
570 }
571 
572 /* Rendering procedure for a monobit image with no */
573 /* skew or rotation and pure colors. */
574 static int
image_render_simple(gx_image_enum * penum,const byte * buffer,int data_x,uint w,int h,gx_device * dev)575 image_render_simple(gx_image_enum * penum, const byte * buffer, int data_x,
576                     uint w, int h, gx_device * dev)
577 {
578     dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono);
579     const fixed dxx = penum->dxx;
580     const byte *line;
581     uint line_width, line_size;
582     int line_x;
583     fixed xcur = dda_current(penum->dda.pixel0.x);
584     int ix = fixed2int_pixround(xcur);
585     int ixr;
586     const int iy = penum->yci, ih = penum->hci;
587     gx_device_color * const pdc0 = penum->icolor0;
588     gx_device_color * const pdc1 = penum->icolor1;
589     int dy;
590     int code;
591 
592     if (h == 0)
593         return 0;
594     if ((!DC_IS_NULL(pdc0) &&
595          (code = gx_color_load(pdc0, penum->pgs, dev)) < 0) ||
596         (!DC_IS_NULL(pdc1) &&
597          (code = gx_color_load(pdc1, penum->pgs, dev)) < 0)
598         )
599         return code;
600     if (penum->line == 0) {	/* A direct BitBlt is possible. */
601         line = buffer;
602         line_size = (w + 7) >> 3;
603         line_width = w;
604         line_x = 0;
605     } else if (copy_mono == dev_proc(&mem_mono_device, copy_mono) &&
606                dxx > 0 && gx_dc_is_pure(pdc1) && gx_dc_is_pure(pdc0) &&
607                /* We know the colors must be (0,1) or (1,0). */
608                (pdc0->colors.pure ^ pdc1->colors.pure) == 1 &&
609                !penum->clip_image &&
610                /*
611                 * Even if clip_image is false, the clipping rectangle
612                 * might lie partly outside the device coordinate space
613                 * if the Margins values are non-zero.
614                 */
615                ix >= 0 &&
616                (ixr = fixed2int_pixround(xcur + penum->x_extent.x) - 1) <
617                  dev->width &&
618                iy >= 0 && iy + ih <= dev->height
619         ) {
620         /* Do the operation directly into the memory device bitmap. */
621         int line_ix;
622         int ib_left = ix >> 3, ib_right = ixr >> 3;
623         byte *scan_line = scan_line_base((gx_device_memory *) dev, iy);
624         byte save_left, save_right, mask;
625 
626         line_x = ix & (align_bitmap_mod * 8 - 1);
627         line_ix = ix - line_x;
628         line_size = (ixr >> 3) + 1 - (line_ix >> 3);
629         line_width = ixr + 1 - ix;
630         /* We must save and restore any unmodified bits in */
631         /* the two edge bytes. */
632         save_left = scan_line[ib_left];
633         save_right = scan_line[ib_right];
634         image_simple_expand(scan_line + (line_ix >> 3), line_x,
635                             line_size, buffer, data_x, w, xcur,
636                             penum->x_extent.x,
637                             (byte)((pdc0->colors.pure == 0) !=
638                              (penum->map[0].table.lookup4x1to32[0] == 0) ?
639                              0xff : 0));
640         if (ix & 7)
641             mask = (byte) (0xff00 >> (ix & 7)),
642                 scan_line[ib_left] =
643                 (save_left & mask) + (scan_line[ib_left] & ~mask);
644         if ((ixr + 1) & 7)
645             mask = (byte) (0xff00 >> ((ixr + 1) & 7)),
646                 scan_line[ib_right] =
647                 (scan_line[ib_right] & mask) + (save_right & ~mask);
648         if (ih <= 1)
649             return 1;
650         /****** MAY BE UNALIGNED ******/
651         line = scan_line + (line_ix >> 3);
652         for (dy = 1; dy < ih; dy++) {
653             int code = (*copy_mono)
654                 (dev, line, line_x, line_size, gx_no_bitmap_id,
655                  ix, iy + dy, line_width, 1,
656                  (gx_color_index)0, (gx_color_index)1);
657 
658             if (code < 0)
659                 return code;
660         }
661         return 0;
662     } else {
663         line = penum->line;
664         line_size = penum->line_size;
665         line_width = penum->line_width;
666         line_x = ix & (align_bitmap_mod * 8 - 1);
667         image_simple_expand(penum->line, line_x, line_size,
668                             buffer, data_x, w, xcur,
669                             penum->x_extent.x, 0);
670     }
671 
672     /* Finally, transfer the scan line to the device. */
673     if (dxx < 0)
674         ix -= line_width;
675     for (dy = 0; dy < ih; dy++) {
676         int code = copy_portrait(penum, line, line_x, line_size,
677                                  ix, iy + dy, line_width, 1, dev);
678 
679         if (code < 0)
680             return code;
681     }
682 
683     return 1;
684 }
685 
686 /* Rendering procedure for a 90 degree rotated monobit image */
687 /* with pure colors.  We buffer and then flip 8 scan lines at a time. */
688 static int copy_landscape(gx_image_enum *, int, int, bool, gx_device *);
689 static int
image_render_landscape(gx_image_enum * penum,const byte * buffer,int data_x,uint w,int h,gx_device * dev)690 image_render_landscape(gx_image_enum * penum, const byte * buffer, int data_x,
691                        uint w, int h, gx_device * dev)
692 {
693     byte *line = penum->line;
694     uint raster = bitmap_raster(penum->line_width);
695     int ix = penum->xci, iw = penum->wci;
696     int xinc, xmod;
697     byte *row;
698     const byte *orig_row = 0;
699     bool y_neg = penum->dxy < 0;
700 
701     if (is_fneg(penum->matrix.yx))
702         ix += iw, iw = -iw, xinc = -1;
703     else
704         xinc = 1;
705     /*
706      * Because of clipping, there may be discontinuous jumps in the values
707      * of ix (xci).  If this happens, or if we are at the end of the data or
708      * a client has requested flushing, flush the flipping buffer.
709      */
710     if (ix != penum->xi_next || h == 0) {
711         int xi = penum->xi_next;
712         int code =
713             (xinc > 0 ?
714              copy_landscape(penum, penum->line_xy, xi, y_neg, dev) :
715              copy_landscape(penum, xi, penum->line_xy, y_neg, dev));
716 
717         if (code < 0)
718             return code;
719         penum->line_xy = penum->xi_next = ix;
720         if (h == 0)
721             return code;
722     }
723     for (; iw != 0; iw -= xinc) {
724         if (xinc < 0)
725             --ix;
726         xmod = ix & 7;
727         row = line + xmod * raster;
728         if (orig_row == 0) {
729             image_simple_expand(row, 0, raster,
730                                 buffer, data_x, w,
731                                 dda_current(penum->dda.pixel0.y),
732                                 penum->x_extent.y, 0);
733             orig_row = row;
734         } else
735             memcpy(row, orig_row, raster);
736         if (xinc > 0) {
737             ++ix;
738             if (xmod == 7) {
739                 int code =
740                     copy_landscape(penum, penum->line_xy, ix, y_neg, dev);
741 
742                 if (code < 0)
743                     return code;
744                 orig_row = 0;
745                 penum->line_xy = ix;
746             }
747         } else {
748             if (xmod == 0) {
749                 int code =
750                     copy_landscape(penum, ix, penum->line_xy, y_neg, dev);
751 
752                 if (code < 0)
753                     return code;
754                 orig_row = 0;
755                 penum->line_xy = ix;
756             }
757         }
758     }
759     penum->xi_next = ix;
760     return 0;
761 }
762 
763 /* Flip and copy one group of scan lines. */
764 static int
copy_landscape(gx_image_enum * penum,int x0,int x1,bool y_neg,gx_device * dev)765 copy_landscape(gx_image_enum * penum, int x0, int x1, bool y_neg,
766                gx_device * dev)
767 {
768     byte *line = penum->line;
769     uint line_width = penum->line_width;
770     uint raster = bitmap_raster(line_width);
771     byte *flipped = line + raster * 8;
772     int w = x1 - x0;
773     int y = fixed2int_pixround(dda_current(penum->dda.pixel0.y));
774 
775     if (w == 0 || line_width == 0)
776         return 0;
777     /* Flip the buffered data from raster x 8 to align_bitmap_mod x */
778     /* line_width. */
779     if (line_width > 0) {
780         int i = (line_width-1)>>3;
781 
782 #ifdef PACIFY_VALGRIND
783         if (line_width & 7) {
784             memflip8x8_eol(line + i, raster,
785                            flipped + (i << (log2_align_bitmap_mod + 3)),
786                            align_bitmap_mod,
787                            line_width & 7);
788             i--;
789         }
790 #endif
791 
792         for (; i >= 0; --i)
793             memflip8x8(line + i, raster,
794                        flipped + (i << (log2_align_bitmap_mod + 3)),
795                        align_bitmap_mod);
796     }
797     /* Transfer the scan lines to the device. */
798     if (w < 0)
799         x0 = x1, w = -w;
800     if (y_neg)
801         y -= line_width;
802     return copy_portrait(penum, flipped, x0 & 7, align_bitmap_mod,
803                          x0, y, w, line_width, dev);
804 }
805