1 /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises, 2001 Artifex Software. All rights reserved. 2 3 This software is provided AS-IS with no warranty, either express or 4 implied. 5 6 This software is distributed under license and may not be copied, 7 modified or distributed except as expressly authorized under the terms 8 of the license contained in the file LICENSE in this distribution. 9 10 For more information about licensing, please refer to 11 http://www.ghostscript.com/licensing/. For information on 12 commercial licensing, go to http://www.artifex.com/licensing/ or 13 contact Artifex Software, Inc., 101 Lucas Valley Road #110, 14 San Rafael, CA 94903, U.S.A., +1(415)492-9861. 15 */ 16 17 /*$Id: gdevm56.c,v 1.3 2004/08/30 21:45:48 dan Exp $ */ 18 /* 56-bit-per-pixel "memory" (stored bitmap) device */ 19 #include "memory_.h" 20 #include "gx.h" 21 #include "gxdevice.h" 22 #include "gxdevmem.h" /* semi-public definitions */ 23 #include "gdevmem.h" /* private definitions */ 24 25 /* Define debugging statistics. */ 26 #ifdef DEBUG 27 struct stats_mem56_s { 28 long 29 fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5], 30 fprevc[257]; 31 double ftotal; 32 } stats_mem56; 33 static int prev_count; 34 static gx_color_index prev_colors[256]; 35 # define INCR(v) (++(stats_mem56.v)) 36 #else 37 # define INCR(v) DO_NOTHING 38 #endif 39 40 41 /* ================ Standard (byte-oriented) device ================ */ 42 43 #undef chunk 44 #define chunk byte 45 #define PIXEL_SIZE 7 46 47 /* Procedures */ 48 declare_mem_procs(mem_true56_copy_mono, mem_true56_copy_color, mem_true56_fill_rectangle); 49 50 /* The device descriptor. */ 51 const gx_device_memory mem_true56_device = 52 mem_full_alpha_device("image56", 56, 0, mem_open, 53 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb, 54 mem_true56_copy_mono, mem_true56_copy_color, mem_true56_fill_rectangle, 55 gx_default_map_cmyk_color, gx_default_copy_alpha, 56 gx_default_strip_tile_rectangle, mem_default_strip_copy_rop, 57 mem_get_bits_rectangle); 58 59 /* Convert x coordinate to byte offset in scan line. */ 60 #undef x_to_byte 61 #define x_to_byte(x) ((x) * PIXEL_SIZE) 62 63 /* Unpack a color into its bytes. */ 64 #define declare_unpack_color(a, b, c, d, e, f, g, color)\ 65 byte a = (byte)(color >> 48);\ 66 byte b = (byte)(color >> 40);\ 67 byte c = (byte)(color >> 32);\ 68 byte d = (byte)((uint)color >> 24);\ 69 byte e = (byte)((uint)color >> 16);\ 70 byte f = (byte)((uint)color >> 8);\ 71 byte g = (byte)color 72 /* Put a 56-bit color into the bitmap. */ 73 #define put7(ptr, a, b, c, d, e, f, g)\ 74 (ptr)[0] = a, (ptr)[1] = b, (ptr)[2] = c, (ptr)[3] = d, (ptr)[4] = e, \ 75 (ptr)[5] = f, (ptr)[6] = g 76 /* Put 4 bytes of color into the bitmap. */ 77 #define putw(ptr, wxyz)\ 78 *(bits32 *)(ptr) = (wxyz) 79 /* Load the 7-word 56-bit-color cache. */ 80 /* Free variables: [m]dev, abcd, bcde, cdea, deab, earc. */ 81 #if arch_is_big_endian 82 # define set_color56_cache(color, a, b, c, d, e, f, g)\ 83 mdev->color56.abcd = abcd = (color) >> 24, \ 84 mdev->color56.bcde = bcde = (abcd << 8) | (e),\ 85 mdev->color56.cdef = cdef = (bcde << 8) | (f),\ 86 mdev->color56.defg = defg = (cdef << 8) | (g),\ 87 mdev->color56.efga = efga = (defg << 8) | (a),\ 88 mdev->color56.fgab = fgab = (efga << 8) | (b),\ 89 mdev->color56.gabc = gabc = (fgab << 8) | (c),\ 90 mdev->color56.abcdefg = (color) 91 #else 92 # define set_color56_cache(color, a, b, c, d, e, f, g)\ 93 mdev->color56.abcd = abcd =\ 94 ((bits32)(d) << 24) | ((bits32)(c) << 16) |\ 95 ((bits16)(b) << 8) | (a),\ 96 mdev->color56.gabc = gabc = (abcd << 8) | (g),\ 97 mdev->color56.fgab = fgab = (gabc << 8) | (f),\ 98 mdev->color56.efga = efga = (fgab << 8) | (e),\ 99 mdev->color56.defg = defg = (efga << 8) | (d),\ 100 mdev->color56.cdef = cdef = (defg << 8) | (c),\ 101 mdev->color56.bcde = bcde = (cdef << 8) | (b),\ 102 mdev->color56.abcdefg = (color) 103 #endif 104 105 /* Fill a rectangle with a color. */ 106 private int 107 mem_true56_fill_rectangle(gx_device * dev, 108 int x, int y, int w, int h, gx_color_index color) 109 { 110 gx_device_memory * const mdev = (gx_device_memory *)dev; 111 declare_unpack_color(a, b, c, d, e, f, g, color); 112 declare_scan_ptr(dest); 113 114 /* 115 * In order to avoid testing w > 0 and h > 0 twice, we defer 116 * executing setup_rect, and use fit_fill_xywh instead of 117 * fit_fill. 118 */ 119 fit_fill_xywh(dev, x, y, w, h); 120 INCR(fill); 121 #ifdef DEBUG 122 stats_mem56.ftotal += w; 123 #endif 124 if (w >= 5) { 125 if (h <= 0) 126 return 0; 127 INCR(fwide); 128 setup_rect(dest); 129 if (a == b && b == c && c == d && d == e && e == f && f == g) { 130 int bcnt = w * PIXEL_SIZE; 131 132 INCR(fgray[min(w, 100)]); 133 while (h-- > 0) { 134 memset(dest, a, bcnt); 135 inc_ptr(dest, draster); 136 } 137 } else { 138 int x3 = -x & 3, ww = w - x3; /* we know ww >= 2 */ 139 bits32 abcd, bcde, cdef, defg, efga, fgab, gabc; 140 141 if (mdev->color56.abcdefg == color) { 142 abcd = mdev->color56.abcd; 143 bcde = mdev->color56.bcde; 144 cdef = mdev->color56.cdef; 145 defg = mdev->color56.defg; 146 efga = mdev->color56.efga; 147 fgab = mdev->color56.fgab; 148 gabc = mdev->color56.gabc; 149 } else { 150 INCR(fsetc); 151 set_color56_cache(color, a, b, c, d, e, f, g); 152 } 153 #ifdef DEBUG 154 { 155 int ci; 156 for (ci = 0; ci < prev_count; ++ci) 157 if (prev_colors[ci] == color) 158 break; 159 INCR(fprevc[ci]); 160 if (ci == prev_count) { 161 if (ci < countof(prev_colors)) 162 ++prev_count; 163 else 164 --ci; 165 } 166 if (ci) { 167 memmove(&prev_colors[1], &prev_colors[0], 168 ci * sizeof(prev_colors[0])); 169 prev_colors[0] = color; 170 } 171 } 172 #endif 173 INCR(fcolor[min(w, 100)]); 174 while (h-- > 0) { 175 register byte *pptr = dest; 176 int w1 = ww; 177 178 switch (x3) { 179 case 1: 180 pptr[0] = a; 181 pptr[1] = b; 182 pptr[2] = c; 183 putw(pptr + 3, defg); 184 pptr += PIXEL_SIZE; 185 break; 186 case 2: 187 pptr[0] = a; 188 pptr[1] = b; 189 putw(pptr + 2, cdef); 190 putw(pptr + 6, gabc); 191 putw(pptr + 10, defg); 192 pptr += 2 * PIXEL_SIZE; 193 break; 194 case 3: 195 pptr[0] = a; 196 putw(pptr + 1, bcde); 197 putw(pptr + 5, fgab); 198 putw(pptr + 9, cdef); 199 putw(pptr + 13, gabc); 200 putw(pptr + 17, defg); 201 pptr += 3 * PIXEL_SIZE; 202 break; 203 case 0: 204 ; 205 } 206 while (w1 >= 4) { 207 putw(pptr, abcd); 208 putw(pptr + 4, efga); 209 putw(pptr + 8, bcde); 210 putw(pptr + 12, fgab); 211 putw(pptr + 16, cdef); 212 putw(pptr + 20, gabc); 213 putw(pptr + 24, defg); 214 pptr += 4 * PIXEL_SIZE; 215 w1 -= 4; 216 } 217 switch (w1) { 218 case 1: 219 putw(pptr, abcd); 220 pptr[4] = e; 221 pptr[5] = f; 222 pptr[6] = g; 223 break; 224 case 2: 225 putw(pptr, abcd); 226 putw(pptr + 4, efga); 227 putw(pptr + 8, bcde); 228 pptr[12] = f; 229 pptr[13] = g; 230 break; 231 case 3: 232 putw(pptr, abcd); 233 putw(pptr + 4, efga); 234 putw(pptr + 8, bcde); 235 putw(pptr + 12, fgab); 236 putw(pptr + 16, cdef); 237 pptr[20] = g; 238 break; 239 case 0: 240 ; 241 } 242 inc_ptr(dest, draster); 243 } 244 } 245 } else if (h > 0) { /* w < 5 */ 246 INCR(fnarrow[max(w, 0)]); 247 setup_rect(dest); 248 switch (w) { 249 case 4: 250 do { 251 dest[21] = dest[14] = dest[7] = dest[0] = a; 252 dest[22] = dest[15] = dest[8] = dest[1] = b; 253 dest[23] = dest[16] = dest[9] = dest[2] = c; 254 dest[24] = dest[17] = dest[10] = dest[3] = d; 255 dest[25] = dest[18] = dest[11] = dest[4] = e; 256 dest[26] = dest[19] = dest[12] = dest[5] = f; 257 dest[27] = dest[20] = dest[13] = dest[6] = g; 258 inc_ptr(dest, draster); 259 } 260 while (--h); 261 break; 262 case 3: 263 do { 264 dest[14] = dest[7] = dest[0] = a; 265 dest[15] = dest[8] = dest[1] = b; 266 dest[16] = dest[9] = dest[2] = c; 267 dest[17] = dest[10] = dest[3] = d; 268 dest[18] = dest[11] = dest[4] = e; 269 dest[19] = dest[12] = dest[5] = f; 270 dest[20] = dest[13] = dest[6] = g; 271 inc_ptr(dest, draster); 272 } 273 while (--h); 274 break; 275 case 2: 276 do { 277 dest[7] = dest[0] = a; 278 dest[8] = dest[1] = b; 279 dest[9] = dest[2] = c; 280 dest[10] = dest[3] = d; 281 dest[11] = dest[4] = e; 282 dest[12] = dest[5] = f; 283 dest[13] = dest[6] = g; 284 inc_ptr(dest, draster); 285 } 286 while (--h); 287 break; 288 case 1: 289 do { 290 dest[0] = a; dest[1] = b; dest[2] = c; dest[3] = d; 291 dest[4] = e; dest[5] = f; dest[6] = g; 292 inc_ptr(dest, draster); 293 } 294 while (--h); 295 break; 296 case 0: 297 default: 298 ; 299 } 300 } 301 return 0; 302 } 303 304 /* Copy a monochrome bitmap. */ 305 private int 306 mem_true56_copy_mono(gx_device * dev, 307 const byte * base, int sourcex, int sraster, gx_bitmap_id id, 308 int x, int y, int w, int h, gx_color_index zero, gx_color_index one) 309 { 310 gx_device_memory * const mdev = (gx_device_memory *)dev; 311 const byte *line; 312 int sbit; 313 int first_bit; 314 315 declare_scan_ptr(dest); 316 317 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); 318 setup_rect(dest); 319 line = base + (sourcex >> 3); 320 sbit = sourcex & 7; 321 first_bit = 0x80 >> sbit; 322 if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */ 323 /* (never used). */ 324 declare_unpack_color(a0, b0, c0, d0, e0, f0, g0, zero); 325 declare_unpack_color(a1, b1, c1, d1, e1, f1, g1, one); 326 while (h-- > 0) { 327 register byte *pptr = dest; 328 const byte *sptr = line; 329 register int sbyte = *sptr++; 330 register int bit = first_bit; 331 int count = w; 332 333 do { 334 if (sbyte & bit) { 335 if (one != gx_no_color_index) 336 put7(pptr, a1, b1, c1, d1, e1, f1, g1); 337 } else 338 put7(pptr, a0, b0, c0, d0, e0, f0, g0); 339 pptr += PIXEL_SIZE; 340 if ((bit >>= 1) == 0) 341 bit = 0x80, sbyte = *sptr++; 342 } 343 while (--count > 0); 344 line += sraster; 345 inc_ptr(dest, draster); 346 } 347 } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */ 348 /* This is used heavily. */ 349 declare_unpack_color(a1, b1, c1, d1, e1, f1, g1, one); 350 int first_mask = first_bit << 1; 351 int first_count, first_skip; 352 353 if (sbit + w > 8) 354 first_mask -= 1, 355 first_count = 8 - sbit; 356 else 357 first_mask -= first_mask >> w, 358 first_count = w; 359 first_skip = first_count * PIXEL_SIZE; 360 while (h-- > 0) { 361 register byte *pptr = dest; 362 const byte *sptr = line; 363 register int sbyte = *sptr++ & first_mask; 364 int count = w - first_count; 365 366 if (sbyte) { 367 register int bit = first_bit; 368 369 do { 370 if (sbyte & bit) 371 put7(pptr, a1, b1, c1, d1, e1, f1, g1); 372 pptr += PIXEL_SIZE; 373 } 374 while ((bit >>= 1) & first_mask); 375 } else 376 pptr += first_skip; 377 while (count >= 8) { 378 sbyte = *sptr++; 379 if (sbyte & 0xf0) { 380 if (sbyte & 0x80) 381 put7(pptr, a1, b1, c1, d1, e1, f1, g1); 382 if (sbyte & 0x40) 383 put7(pptr + 7, a1, b1, c1, d1, e1, f1, g1); 384 if (sbyte & 0x20) 385 put7(pptr + 14, a1, b1, c1, d1, e1, f1, g1); 386 if (sbyte & 0x10) 387 put7(pptr + 21, a1, b1, c1, d1, e1, f1, g1); 388 } 389 if (sbyte & 0xf) { 390 if (sbyte & 8) 391 put7(pptr + 28, a1, b1, c1, d1, e1, f1, g1); 392 if (sbyte & 4) 393 put7(pptr + 35, a1, b1, c1, d1, e1, f1, g1); 394 if (sbyte & 2) 395 put7(pptr + 42, a1, b1, c1, d1, e1, f1, g1); 396 if (sbyte & 1) 397 put7(pptr + 49, a1, b1, c1, d1, e1, f1, g1); 398 } 399 pptr += 8 * PIXEL_SIZE; 400 count -= 8; 401 } 402 if (count > 0) { 403 register int bit = 0x80; 404 405 sbyte = *sptr++; 406 do { 407 if (sbyte & bit) 408 put7(pptr, a1, b1, c1, d1, e1, f1, g1); 409 pptr += PIXEL_SIZE; 410 bit >>= 1; 411 } 412 while (--count > 0); 413 } 414 line += sraster; 415 inc_ptr(dest, draster); 416 } 417 } 418 return 0; 419 } 420 421 /* Copy a color bitmap. */ 422 private int 423 mem_true56_copy_color(gx_device * dev, 424 const byte * base, int sourcex, int sraster, gx_bitmap_id id, 425 int x, int y, int w, int h) 426 { 427 gx_device_memory * const mdev = (gx_device_memory *)dev; 428 429 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); 430 mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h); 431 return 0; 432 } 433 434 /* ================ "Word"-oriented device ================ */ 435 436 /* Note that on a big-endian machine, this is the same as the */ 437 /* standard byte-oriented-device. */ 438 439 #if !arch_is_big_endian 440 441 /* Procedures */ 442 declare_mem_procs(mem56_word_copy_mono, mem56_word_copy_color, mem56_word_fill_rectangle); 443 444 /* Here is the device descriptor. */ 445 const gx_device_memory mem_true56_word_device = 446 mem_full_device("image56w", 56, 0, mem_open, 447 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb, 448 mem56_word_copy_mono, mem56_word_copy_color, mem56_word_fill_rectangle, 449 gx_default_map_cmyk_color, gx_default_strip_tile_rectangle, 450 gx_no_strip_copy_rop, mem_word_get_bits_rectangle); 451 452 /* Fill a rectangle with a color. */ 453 private int 454 mem56_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h, 455 gx_color_index color) 456 { 457 gx_device_memory * const mdev = (gx_device_memory *)dev; 458 byte *base; 459 uint raster; 460 461 fit_fill(dev, x, y, w, h); 462 base = scan_line_base(mdev, y); 463 raster = mdev->raster; 464 mem_swap_byte_rect(base, raster, x * 56, w * 56, h, true); 465 mem_true56_fill_rectangle(dev, x, y, w, h, color); 466 mem_swap_byte_rect(base, raster, x * 56, w * 56, h, false); 467 return 0; 468 } 469 470 /* Copy a bitmap. */ 471 private int 472 mem56_word_copy_mono(gx_device * dev, 473 const byte * base, int sourcex, int sraster, gx_bitmap_id id, 474 int x, int y, int w, int h, gx_color_index zero, gx_color_index one) 475 { 476 gx_device_memory * const mdev = (gx_device_memory *)dev; 477 byte *row; 478 uint raster; 479 bool store; 480 481 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); 482 row = scan_line_base(mdev, y); 483 raster = mdev->raster; 484 store = (zero != gx_no_color_index && one != gx_no_color_index); 485 mem_swap_byte_rect(row, raster, x * 56, w * 56, h, store); 486 mem_true56_copy_mono(dev, base, sourcex, sraster, id, 487 x, y, w, h, zero, one); 488 mem_swap_byte_rect(row, raster, x * 56, w * 56, h, false); 489 return 0; 490 } 491 492 /* Copy a color bitmap. */ 493 private int 494 mem56_word_copy_color(gx_device * dev, 495 const byte * base, int sourcex, int sraster, gx_bitmap_id id, 496 int x, int y, int w, int h) 497 { 498 gx_device_memory * const mdev = (gx_device_memory *)dev; 499 byte *row; 500 uint raster; 501 502 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); 503 row = scan_line_base(mdev, y); 504 raster = mdev->raster; 505 mem_swap_byte_rect(row, raster, x * 56, w * 56, h, true); 506 bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE, 507 sraster, w * PIXEL_SIZE, h); 508 mem_swap_byte_rect(row, raster, x * 56, w * 56, h, false); 509 return 0; 510 } 511 512 #endif /* !arch_is_big_endian */ 513