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