home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved.
-
- This file is part of Ghostscript.
-
- Ghostscript is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
- to anyone for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing. Refer
- to the Ghostscript General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- Ghostscript, but only under the conditions described in the Ghostscript
- General Public License. A copy of this license is supposed to have been
- given to you along with Ghostscript so you can know your rights and
- responsibilities. It should be in a file named COPYING. Among other
- things, the copyright notice and this notice must be preserved on all
- copies. */
-
- /* gdevmem2.c */
- /* 8-and-more-bit-per-pixel "memory" (stored bitmap) devices */
- /* for Ghostscript library. */
- #include "memory_.h"
- #include "gx.h"
- #include "gxdevice.h"
- #include "gxdevmem.h" /* semi-public definitions */
- #include "gdevmem.h" /* private definitions */
-
- /* ------ Generic procedures ------ */
-
- /* Copy a rectangle of bytes from a source to a destination. */
- #undef chunk
- #define chunk byte
- private int
- copy_byte_rect(gx_device_memory *dev, const byte *source, int sraster,
- int offset, int y, int byte_count, int h)
- { uint draster = dev->raster;
- byte *dest = scan_line_base(dev, y) + offset;
- while ( h-- > 0 )
- { memcpy(dest, source, byte_count);
- source += sraster;
- dest += draster;
- }
- return 0;
- }
-
- /* Map a r-g-b color to a color index. */
- /* This requires searching the palette. */
- gx_color_index
- mem_mapped_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g,
- gx_color_value b)
- { byte br = gx_color_value_to_byte(r);
- byte bg = gx_color_value_to_byte(g);
- byte bb = gx_color_value_to_byte(b);
- register byte *pptr = mdev->palette;
- int cnt = mdev->palette_size;
- byte *which;
- int best = 256*3;
- while ( cnt-- > 0 )
- { register int diff = *pptr - br;
- if ( diff < 0 ) diff = -diff;
- if ( diff < best ) /* quick rejection */
- { int dg = pptr[1] - bg;
- if ( dg < 0 ) dg = -dg;
- if ( (diff += dg) < best ) /* quick rejection */
- { int db = pptr[2] - bb;
- if ( db < 0 ) db = -db;
- if ( (diff += db) < best )
- which = pptr, best = diff;
- }
- }
- pptr += 3;
- }
- return (gx_color_index)((which - mdev->palette) / 3);
- }
-
- /* Map a color index to a r-g-b color. */
- int
- mem_mapped_map_color_rgb(gx_device *dev, gx_color_index color,
- gx_color_value prgb[3])
- { byte *pptr = mdev->palette + (int)color * 3;
- prgb[0] = gx_color_value_from_byte(pptr[0]);
- prgb[1] = gx_color_value_from_byte(pptr[1]);
- prgb[2] = gx_color_value_from_byte(pptr[2]);
- return 0;
- }
-
- /* ------ Mapped 8-bit color ------ */
-
- /* Procedures */
- declare_mem_procs(mem_mapped8_copy_mono, mem_mapped8_copy_color, mem_mapped8_fill_rectangle);
-
- /* The device descriptor. */
- private gx_device_procs mem_mapped8_procs =
- mem_procs(mem_mapped_map_rgb_color, mem_mapped_map_color_rgb,
- mem_mapped8_copy_mono, mem_mapped8_copy_color, mem_mapped8_fill_rectangle);
-
- /* The instance is public. */
- const gx_device_memory mem_mapped8_color_device =
- mem_device("image(8)", 8, mem_mapped8_procs);
-
- /* Convert x coordinate to byte offset in scan line. */
- #undef x_to_byte
- #define x_to_byte(x) (x)
-
- /* Fill a rectangle with a color. */
- private int
- mem_mapped8_fill_rectangle(gx_device *dev,
- int x, int y, int w, int h, gx_color_index color)
- { declare_scan_ptr(dest);
- fit_fill(dev, x, y, w, h);
- setup_rect(dest);
- while ( h-- > 0 )
- { memset(dest, (byte)color, w);
- inc_chunk_ptr(dest, draster);
- }
- return 0;
- }
-
- /* Copy a monochrome bitmap. */
- private int
- mem_mapped8_copy_mono(gx_device *dev,
- const byte *base, int sourcex, int sraster, gx_bitmap_id id,
- int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
- { const byte *line;
- int first_bit;
- declare_scan_ptr(dest);
- fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
- setup_rect(dest);
- line = base + (sourcex >> 3);
- first_bit = 0x80 >> (sourcex & 7);
- while ( h-- > 0 )
- { register byte *pptr = dest;
- const byte *sptr = line;
- register int sbyte = *sptr;
- register uint bit = first_bit;
- int count = w;
- #define is_color(c) ((int)(c) != (int)gx_no_color_index)
- #define next_bit()\
- if ( (bit >>= 1) == 0 ) bit = 0x80, sbyte = *++sptr;\
- pptr++
- if ( is_color(one) )
- { if ( is_color(zero) )
- { /* Optimize halftone coloring */
- do
- { *pptr = (sbyte & bit ? (byte)one :
- (byte)zero);
- next_bit();
- }
- while ( --count > 0 );
- }
- else
- { /* Optimize stenciling */
- do
- { if ( sbyte & bit )
- *pptr = (byte)one;
- next_bit();
- }
- while ( --count > 0 );
- }
- }
- else if ( is_color(zero) )
- { do
- { if ( !(sbyte & bit) )
- *pptr = (byte)zero;
- next_bit();
- }
- while ( --count > 0 );
- }
- #undef next_bit
- #undef is_color
- line += sraster;
- inc_chunk_ptr(dest, draster);
- }
- return 0;
- }
-
- /* Copy a color bitmap. */
- private int
- mem_mapped8_copy_color(gx_device *dev,
- const byte *base, int sourcex, int sraster, gx_bitmap_id id,
- int x, int y, int w, int h)
- { fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
- return copy_byte_rect(mdev, base + x_to_byte(sourcex), sraster,
- x_to_byte(x), y, x_to_byte(w), h);
- }
-
- /* ------ 16-bit true color ------ */
- /* The 16 bits are divided 5 for red, 6 for green, and 5 for blue. */
- /* Note that the bits must always be kept in big-endian order. */
-
- /* Procedures */
- declare_mem_map_procs(mem_true16_map_rgb_color, mem_true16_map_color_rgb);
- declare_mem_procs(mem_true16_copy_mono, mem_true16_copy_color, mem_true16_fill_rectangle);
-
- /* The device descriptor. */
- private gx_device_procs mem_true16_procs =
- mem_procs(mem_true16_map_rgb_color, mem_true16_map_color_rgb,
- mem_true16_copy_mono, mem_true16_copy_color, mem_true16_fill_rectangle);
-
- /* The instance is public. */
- const gx_device_memory mem_true16_color_device =
- mem_device("image(16)", 16, mem_true16_procs);
-
- /* Map a r-g-b color to a color index. */
- private gx_color_index
- mem_true16_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g,
- gx_color_value b)
- { return ((r >> (gx_color_value_bits - 5)) << 11) +
- ((g >> (gx_color_value_bits - 6)) << 5) +
- (b >> (gx_color_value_bits - 5));
- }
-
- /* Map a color index to a r-g-b color. */
- private int
- mem_true16_map_color_rgb(gx_device *dev, gx_color_index color,
- gx_color_value prgb[3])
- { ushort value;
- value = color >> 11;
- prgb[0] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
- value = (color >> 6) & 0x7f;
- prgb[1] = ((value << 10) + (value << 4) + (value >> 2)) >> (16 - gx_color_value_bits);
- value = color & 0x3f;
- prgb[2] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
- return 0;
- }
-
- /* Convert x coordinate to byte offset in scan line. */
- #undef x_to_byte
- #define x_to_byte(x) ((x) << 1)
-
- /* Fill a rectangle with a color. */
- private int
- mem_true16_fill_rectangle(gx_device *dev,
- int x, int y, int w, int h, gx_color_index color)
- {
- #if arch_is_big_endian
- # define color16 ((ushort)color)
- #else
- ushort color16 = ((uint)(byte)color << 8) + ((ushort)color >> 8);
- #endif
- declare_scan_ptr(dest);
- fit_fill(dev, x, y, w, h);
- setup_rect(dest);
- while ( h-- > 0 )
- { ushort *pptr = (ushort *)dest;
- int cnt = w;
- do { *pptr++ = color16; } while ( --cnt > 0 );
- inc_chunk_ptr(dest, draster);
- }
- return 0;
- #undef color16
- }
-
- /* Copy a monochrome bitmap. */
- private int
- mem_true16_copy_mono(gx_device *dev,
- const byte *base, int sourcex, int sraster, gx_bitmap_id id,
- int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
- {
- #if arch_is_big_endian
- # define zero16 ((ushort)zero)
- # define one16 ((ushort)one)
- #else
- ushort zero16 = ((uint)(byte)zero << 8) + ((ushort)zero >> 8);
- ushort one16 = ((uint)(byte)one << 8) + ((ushort)one >> 8);
- #endif
- const byte *line;
- int first_bit;
- declare_scan_ptr(dest);
- fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
- setup_rect(dest);
- line = base + (sourcex >> 3);
- first_bit = 0x80 >> (sourcex & 7);
- while ( h-- > 0 )
- { register ushort *pptr = (ushort *)dest;
- const byte *sptr = line;
- register int sbyte = *sptr++;
- register int bit = first_bit;
- int count = w;
- do
- { if ( sbyte & bit )
- { if ( one != gx_no_color_index )
- *pptr = one16;
- }
- else
- { if ( zero != gx_no_color_index )
- *pptr = zero16;
- }
- if ( (bit >>= 1) == 0 )
- bit = 0x80, sbyte = *sptr++;
- pptr++;
- }
- while ( --count > 0 );
- line += sraster;
- inc_chunk_ptr(dest, draster);
- }
- return 0;
- #undef zero16
- #undef one16
- }
-
- /* Copy a color bitmap. */
- private int
- mem_true16_copy_color(gx_device *dev,
- const byte *base, int sourcex, int sraster, gx_bitmap_id id,
- int x, int y, int w, int h)
- { fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
- return copy_byte_rect(mdev, base + x_to_byte(sourcex), sraster,
- x_to_byte(x), y, x_to_byte(w), h);
- }
-
- /* ------ 24- or 32-bit true color ------ */
-
- /* Procedures */
- declare_mem_map_procs(mem_true_map_rgb_color, mem_true_map_color_rgb);
-
- /* The device descriptor. */
- #define mem_true_procs(copy_mono, copy_color, fill_rectangle)\
- mem_procs(mem_true_map_rgb_color, mem_true_map_color_rgb,\
- copy_mono, copy_color, fill_rectangle)
-
- /* Map a r-g-b color to a color index. */
- private gx_color_index
- mem_true_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g,
- gx_color_value b)
- { return gx_color_value_to_byte(b) +
- ((uint)gx_color_value_to_byte(g) << 8) +
- ((ulong)gx_color_value_to_byte(r) << 16);
- }
-
- /* Map a color index to a r-g-b color. */
- private int
- mem_true_map_color_rgb(gx_device *dev, gx_color_index color,
- gx_color_value prgb[3])
- { prgb[0] = gx_color_value_from_byte(color >> 16);
- prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
- prgb[2] = gx_color_value_from_byte(color & 0xff);
- return 0;
- }
-
- /* ------ 24-bit color ------ */
- /* 24-bit takes less space than 32-bit, but is slower. */
-
- /* Procedures */
- declare_mem_procs(mem_true24_copy_mono, mem_true24_copy_color, mem_true24_fill_rectangle);
-
- /* The device descriptor. */
- private gx_device_procs mem_true24_procs =
- mem_true_procs(mem_true24_copy_mono, mem_true24_copy_color,
- mem_true24_fill_rectangle);
- const gx_device_memory mem_true24_color_device =
- mem_device("image(24)", 24, mem_true24_procs);
-
- /* Convert x coordinate to byte offset in scan line. */
- #undef x_to_byte
- #define x_to_byte(x) ((x) * 3)
-
- /* Unpack a color into its bytes. */
- #define declare_unpack_color(r, g, b, color)\
- byte r = (byte)(color >> 16);\
- byte g = (byte)((uint)color >> 8);\
- byte b = (byte)color
- #define put3(ptr, r, g, b)\
- ptr[0] = r, ptr[1] = g, ptr[2] = b
-
- /* Fill a rectangle with a color. */
- private int
- mem_true24_fill_rectangle(gx_device *dev,
- int x, int y, int w, int h, gx_color_index color)
- { declare_unpack_color(r, g, b, color);
- declare_scan_ptr(dest);
- fit_fill(dev, x, y, w, h);
- setup_rect(dest);
- if ( w >= 5 && r == g && g == b)
- { /* Just fill the bits. */
- int bcnt = w * 3;
- while ( h-- > 0 )
- { memset(dest, r, bcnt);
- inc_chunk_ptr(dest, draster);
- }
- }
- else
- { while ( h-- > 0 )
- { register int cnt = w;
- register byte *pptr = dest;
- do { put3(pptr, r, g, b); pptr += 3; }
- while ( --cnt > 0 );
- inc_chunk_ptr(dest, draster);
- }
- }
- return 0;
- }
-
- /* Copy a monochrome bitmap. */
- private int
- mem_true24_copy_mono(gx_device *dev,
- const byte *base, int sourcex, int sraster, gx_bitmap_id id,
- int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
- { const byte *line;
- int first_bit;
- declare_unpack_color(r0, g0, b0, zero);
- declare_unpack_color(r1, g1, b1, one);
- declare_scan_ptr(dest);
- fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
- setup_rect(dest);
- line = base + (sourcex >> 3);
- first_bit = 0x80 >> (sourcex & 7);
- while ( h-- > 0 )
- { register byte *pptr = dest;
- const byte *sptr = line;
- register int sbyte = *sptr++;
- register int bit = first_bit;
- int count = w;
- do
- { if ( sbyte & bit )
- { if ( one != gx_no_color_index )
- put3(pptr, r1, g1, b1);
- }
- else
- { if ( zero != gx_no_color_index )
- put3(pptr, r0, g0, b0);
- }
- pptr += 3;
- if ( (bit >>= 1) == 0 )
- bit = 0x80, sbyte = *sptr++;
- }
- while ( --count > 0 );
- line += sraster;
- inc_chunk_ptr(dest, draster);
- }
- return 0;
- }
-
- /* Copy a color bitmap. */
- private int
- mem_true24_copy_color(gx_device *dev,
- const byte *base, int sourcex, int sraster, gx_bitmap_id id,
- int x, int y, int w, int h)
- { fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
- return copy_byte_rect(mdev, base + x_to_byte(sourcex), sraster,
- x_to_byte(x), y, x_to_byte(w), h);
- }
-
- /* ------ 32-bit color ------ */
-
- /* Procedures */
- declare_mem_procs(mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle);
-
- /* The device descriptor. */
- private gx_device_procs mem_true32_procs =
- mem_true_procs(mem_true32_copy_mono, mem_true32_copy_color,
- mem_true32_fill_rectangle);
- const gx_device_memory mem_true32_color_device =
- mem_device("image(32)", 32, mem_true32_procs);
-
- /* Convert x coordinate to byte offset in scan line. */
- #undef x_to_byte
- #define x_to_byte(x) ((x) << 2)
-
- /* Swap the bytes of a color if needed. */
- #if arch_is_big_endian
- # define arrange_bytes(color) (color)
- #else
- # define arrange_bytes(color)\
- (((color) >> 24) + (((color) >> 8) & 0xff00) +\
- (((color) & 0xff00) << 8) + ((color) << 24))
- #endif
-
- /* Fill a rectangle with a color. */
- private int
- mem_true32_fill_rectangle(gx_device *dev,
- int x, int y, int w, int h, gx_color_index color)
- { gx_color_index a_color = arrange_bytes(color);
- declare_scan_ptr(dest);
- fit_fill(dev, x, y, w, h);
- setup_rect(dest);
- while ( h-- > 0 )
- { gx_color_index *pptr = (gx_color_index *)dest;
- int cnt = w;
- do { *pptr++ = a_color; } while ( --cnt > 0 );
- inc_chunk_ptr(dest, draster);
- }
- return 0;
- }
-
- /* Copy a monochrome bitmap. */
- private int
- mem_true32_copy_mono(gx_device *dev,
- const byte *base, int sourcex, int sraster, gx_bitmap_id id,
- int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
- { gx_color_index a_zero = arrange_bytes(zero);
- gx_color_index a_one = arrange_bytes(one);
- const byte *line;
- int first_bit;
- declare_scan_ptr(dest);
- fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
- setup_rect(dest);
- line = base + (sourcex >> 3);
- first_bit = 0x80 >> (sourcex & 7);
- while ( h-- > 0 )
- { register gx_color_index *pptr = (gx_color_index *)dest;
- const byte *sptr = line;
- register int sbyte = *sptr++;
- register int bit = first_bit;
- int count = w;
- do
- { if ( sbyte & bit )
- { if ( one != gx_no_color_index )
- *pptr = a_one;
- }
- else
- { if ( zero != gx_no_color_index )
- *pptr = a_zero;
- }
- if ( (bit >>= 1) == 0 )
- bit = 0x80, sbyte = *sptr++;
- pptr++;
- }
- while ( --count > 0 );
- line += sraster;
- inc_chunk_ptr(dest, draster);
- }
- return 0;
- }
-
- /* Copy a color bitmap. */
- private int
- mem_true32_copy_color(gx_device *dev,
- const byte *base, int sourcex, int sraster, gx_bitmap_id id,
- int x, int y, int w, int h)
- { fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
- return copy_byte_rect(mdev, base + x_to_byte(sourcex), sraster,
- x_to_byte(x), y, x_to_byte(w), h);
- }
-