|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T g
Length: 17255 (0x4367) Types: TextFile Names: »gdevmem.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89 └─⟦ff23ba0e6⟧ »./ghostscript-1.3.tar.Z« └─⟦a24a58cd3⟧ └─⟦this⟧ »gdevmem.c«
/* Copyright (C) 1989 Aladdin Enterprises. All rights reserved. Distributed by Free Software Foundation, Inc. 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. */ /* gdevmem.c */ /* "Memory" (stored bitmap) device for GhostScript library. */ #include "gx.h" /* should be std.h, but needs gx_bitmap */ #include "gsmatrix.h" /* for gxdevice.h */ #include "gxdevice.h" #include "gxdevmem.h" typedef struct gx_device_s gx_device; /* The obvious representation for a "memory" device is simply a contiguous bitmap stored in something like the PostScript representation, i.e., each scan line (in left-to-right order), padded to a byte or word boundary, followed immediately by the next one. Unfortunately, we can't always use this representation, for two reasons: - On PCs with segmented architectures, there is no way to obtain a contiguous block of storage larger then 64K bytes, which isn't big enough for a full-screen bitmap, even in monochrome. - The representation of strings in the Ghostscript interpreter limits the size of a string to 64K-1 bytes, which means we can't simply use a string for the contents of a memory device. We get around the former problem (on PCs) by representing a memory device as an array of strings: each string holds one scan line. We get around the latter problem by making the client read out the contents of a memory device bitmap in pieces. */ #ifdef __MSDOS__ # define use_pieces 1 #else # define use_pieces 0 #endif /* ------ Generic code ------ */ /* Macro for casting gx_device argument */ #define md ((gx_device_memory *)dev) /* Macro for rectangle arguments (x,y,w,h) */ #define check_rect()\ if ( w <= 0 || h <= 0 ) return 0;\ if ( x < 0 || x > md->width - w || y < 0 || y > md->height - h )\ return -1 #define unpack_rect(dest_line, dest)\ check_rect();\ setup_rect(dest_line, dest) /* Macros for scan line access. */ /* x_to_byte is representation-specific. */ #if use_pieces # define declare_scan_ptr(line,ptr) byte **line; byte *ptr # define setup_scan(line,ptr,offset)\ line = md->line_ptrs + (y);\ ptr = *line + (offset) # define next_scan_line(line,ptr) ++line; ptr = *line + (ptr - line[-1]) #else # define declare_scan_ptr(line,ptr) int line; byte *ptr # define setup_scan(line,ptr,offset)\ line = md->raster;\ ptr = md->base + y * line + (offset) # define next_scan_line(line,ptr) ptr += line #endif #define setup_rect(line,ptr) setup_scan(line,ptr,x_to_byte(x)) /* Compute the size of the bitmap storage. */ /* This may require space for the scan line index. */ /* Note that scan lines are padded to a multiple of 4 bytes. */ uint gx_device_memory_bitmap_size(gx_device_memory *dev) { unsigned raster = ((md->width * md->bits_per_color_pixel + 31) >> 5) << 2; md->raster = raster; return #if use_pieces md->height * sizeof(byte **) + #endif raster * md->height; } /* 'Open' the memory device by creating the index table if needed. */ private int mem_open(gx_device *dev) { #if use_pieces /* ONLY FOR MS-DOS */ #include <dos.h> #define make_huge_ptr(ptr) ((byte huge *)MK_FP(FP_SEG(ptr), 0) + FP_OFF(ptr)) byte huge *scan_line = make_huge_ptr(md->base); byte **pptr = (byte **)(scan_line + (long)md->raster * md->height); byte **pend = pptr + md->height; md->line_ptrs = pptr; while ( pptr != pend ) { *pptr++ = (byte *)scan_line; scan_line += md->raster; } #endif return 0; } /* ------ Monochrome ------ */ /* Procedures */ private int mem_mono_copy_mono(P10(gx_device *, byte *, int, int, int, int, int, int, gx_color_index, gx_color_index)), mem_mono_copy_color(P8(gx_device *, byte *, int, int, int, int, int, int)), mem_mono_fill_rectangle(P6(gx_device *, int, int, int, int, gx_color_index)); /* The device descriptor. */ private gx_device_procs mem_mono_procs = { mem_open, gx_default_close_device, gx_default_map_rgb_color, gx_default_map_color_rgb, gx_default_sync_output, mem_mono_fill_rectangle, gx_default_tile_rectangle, mem_mono_copy_mono, mem_mono_copy_color, gx_default_draw_line, gx_default_fill_trapezoid, gx_default_tile_trapezoid }; /* The instance is public. */ gx_device_memory mem_mono_device = { sizeof(gx_device_memory), &mem_mono_procs, identity_matrix_body, 0, 0, /* x and y extent (filled in) */ 0, 1, 1, /* monochrome */ 1, /* bit-big-endian */ 0, /* not open yet */ 0, /* raster (filled in) */ (byte *)0, /* base (filled in) */ (byte **)0, /* line_ptrs (filled in by 'open') */ 0, /* invert (filled in) */ 0, (byte *)0 /* palette (unused) */ }; /* Convert x coordinate to byte offset in scan line. */ #define x_to_byte(x) ((x) >> 3) /* Fill a rectangle with a color. */ private int mem_mono_fill_rectangle(gx_device *dev, int x, int y, int w, int h, gx_color_index color) { int bit; byte right_mask; byte fill; declare_scan_ptr(dest_line, dest); unpack_rect(dest_line, dest); #define write_loop(stat)\ { int line_count = h;\ declare_scan_ptr(ptr_line, ptr);\ ptr_line = dest_line, ptr = dest;\ do { stat; next_scan_line(ptr_line, ptr); } while ( --line_count );\ } #define write_partial(msk)\ if ( fill ) write_loop(*ptr |= msk)\ else write_loop(*ptr &= ~msk) switch ( color ) { case 0: fill = md->invert; break; case 1: fill = ~md->invert; break; case gx_no_color_index: return 0; /* transparent */ default: return -1; /* invalid */ } bit = x & 7; if ( bit + w <= 8 ) { /* Only one word */ right_mask = ((0xff00 >> w) & 0xff) >> bit; } else { int byte_count; if ( bit ) { byte mask = 0xff >> bit; write_partial(mask); dest++; w += bit - 8; } right_mask = (0xff00 >> (w & 7)) & 0xff; if ( (byte_count = w >> 3) != 0 ) { write_loop(memset(ptr, fill, byte_count)); dest += byte_count; } } if ( right_mask ) write_partial(right_mask); return 0; } /* Copy a monochrome bitmap. */ private int mem_mono_copy_mono(gx_device *dev, byte *base, int sourcex, int raster, int x, int y, int w, int h, gx_color_index zero, gx_color_index one) { byte *line; int sleft, dleft; int mask, rmask; int invert, zmask, omask; declare_scan_ptr(dest_line, dest); if ( one == zero ) /* vacuous case */ return mem_mono_fill_rectangle(dev, x, y, w, h, zero); unpack_rect(dest_line, dest); line = base + (sourcex >> 3); sleft = 8 - (sourcex & 7); dleft = 8 - (x & 7); mask = 0xff >> (8 - dleft); if ( w < dleft ) mask -= mask >> w; else rmask = 0xff00 >> ((w - dleft) & 7); /* Macros for writing partial bytes. */ /* bits has already been inverted by xor'ing with invert. */ #define write_byte_masked(ptr, bits, mask)\ *ptr = ((bits | ~mask | zmask) & *ptr | (bits & mask & omask)) #define write_byte(ptr, bits)\ *ptr = ((bits | zmask) & *ptr | (bits & omask)) invert = (zero == 1 || one == 0 ? -1 : 0) ^ md->invert; zmask = (zero == 0 || one == 0 ? 0 : -1); omask = (zero == 1 || one == 1 ? -1 : 0); if ( sleft == dleft ) /* optimize the aligned case */ { w -= dleft; while ( --h >= 0 ) { register byte *bptr = line; int count = w; register byte *optr = dest; register int bits = *bptr ^ invert; /* first partial byte */ write_byte_masked(optr, bits, mask); /* Do full bytes. */ while ( (count -= 8) >= 0 ) { bits = *++bptr ^ invert; ++optr; write_byte(optr, bits); } /* Do last byte */ if ( count > 0 ) { bits = *++bptr ^ invert; ++optr; write_byte_masked(optr, bits, rmask); } next_scan_line(dest_line, dest); line += raster; } } else { int skew = (sleft - dleft) & 7; int cskew = 8 - skew; while ( --h >= 0 ) { byte *bptr = line; int count = w; byte *optr = dest; register int bits; /* Do the first partial byte */ if ( sleft >= dleft ) { bits = *bptr >> skew; } else /* ( sleft < dleft ) */ { bits = *bptr++ << cskew; if ( count > sleft ) bits += *bptr >> skew; } bits ^= invert; write_byte_masked(optr, bits, mask); count -= dleft; optr++; /* Do full bytes. */ while ( count >= 8 ) { bits = *bptr++ << cskew; bits += *bptr >> skew; bits ^= invert; write_byte(optr, bits); count -= 8; optr++; } /* Do last byte */ if ( count > 0 ) { bits = *bptr++ << cskew; if ( count > skew ) bits += *bptr >> skew; bits ^= invert; write_byte_masked(optr, bits, rmask); } next_scan_line(dest_line, dest); line += raster; } } return 0; } /* Copy a "color" bitmap. Since "color" is the same as monochrome, */ /* this just reduces to copying a monochrome bitmap. */ private int mem_mono_copy_color(gx_device *dev, byte *base, int sourcex, int raster, int x, int y, int w, int h) { return mem_mono_copy_mono(dev, base, sourcex, raster, x, y, w, h, (gx_color_index)0, (gx_color_index)1); } /* ------ Color (mapped or true) ------ */ /* Copy a rectangle of bytes from a source to a destination. */ private int copy_byte_rect(gx_device *dev, byte *source, int sraster, int offset, int y, int w, int h) { declare_scan_ptr(dest_line, dest); setup_scan(dest_line, dest, offset); while ( h-- > 0 ) { memcpy(dest_line, source, w); source += sraster; next_scan_line(dest_line, dest); } } /* ------ Mapped color ------ */ /* Procedures */ private gx_color_index mem_mapped_map_rgb_color(P4(gx_device *, ushort, ushort, ushort)); private int mem_mapped_map_color_rgb(P3(gx_device *, gx_color_index, ushort *)), mem_mapped_copy_mono(P10(gx_device *, byte *, int, int, int, int, int, int, gx_color_index, gx_color_index)), mem_mapped_copy_color(P8(gx_device *, byte *, int, int, int, int, int, int)), mem_mapped_fill_rectangle(P6(gx_device *, int, int, int, int, gx_color_index)); /* The device descriptor. */ private gx_device_procs mem_mapped_procs = { mem_open, gx_default_close_device, mem_mapped_map_rgb_color, mem_mapped_map_color_rgb, gx_default_sync_output, mem_mapped_fill_rectangle, gx_default_tile_rectangle, mem_mapped_copy_mono, mem_mapped_copy_color, gx_default_draw_line, gx_default_fill_trapezoid, gx_default_tile_trapezoid }; /* The instance is public. */ gx_device_memory mem_mapped_device = { sizeof(gx_device_memory), &mem_mapped_procs, identity_matrix_body, 0, 0, /* x and y extent (filled in) */ 1, 255, 8, /* 8-bit mapped color */ 1, /* bit-big-endian */ 0, /* not open yet */ 0, /* raster (filled in) */ (byte *)0, /* base (filled in) */ (byte **)0, /* line_ptrs (filled in by 'open') */ 0, /* invert (unused) */ 0, (byte *)0 /* palette (filled in) */ }; /* Convert x coordinate to byte offset in scan line. */ #undef x_to_byte #define x_to_byte(x) (x) /* Map a r-g-b color to a color index. */ /* This requires searching the palette. */ private gx_color_index mem_mapped_map_rgb_color(gx_device *dev, ushort r, ushort g, ushort b) { register byte *pptr = md->palette; int cnt = md->palette_size; byte *which; int best = 256*3; while ( cnt-- > 0 ) { register int diff = *pptr - r; if ( diff < 0 ) diff = -diff; if ( diff < best ) /* quick rejection */ { int dg = pptr[1] - g; if ( dg < 0 ) dg = -dg; if ( (diff += dg) < best ) /* quick rejection */ { int db = pptr[2] - b; if ( db < 0 ) db = -db; if ( (diff += db) < best ) which = pptr, best = diff; } } } return (gx_color_index)((which - md->palette) / 3); } /* Map a color index to a r-g-b color. */ private int mem_mapped_map_color_rgb(gx_device *dev, gx_color_index color, ushort *prgb) { byte *pptr = md->palette + (int)color * 3; prgb[0] = pptr[0]; prgb[1] = pptr[1]; prgb[2] = pptr[2]; return 0; } /* Fill a rectangle with a color. */ private int mem_mapped_fill_rectangle(gx_device *dev, int x, int y, int w, int h, gx_color_index color) { declare_scan_ptr(dest_line, dest); setup_rect(dest_line, dest); while ( h-- > 0 ) { memset(dest, (byte)color, w); next_scan_line(dest_line, dest); } } /* Copy a monochrome bitmap. */ private int mem_mapped_copy_mono(gx_device *dev, byte *base, int sourcex, int raster, int x, int y, int w, int h, gx_color_index zero, gx_color_index one) { byte *line; int first_bit; declare_scan_ptr(dest_line, dest); setup_rect(dest_line, dest); line = base + (sourcex >> 3); first_bit = 0x80 >> (sourcex & 7); while ( h-- > 0 ) { register byte *pptr = dest; 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 = (byte)one; } else { if ( zero != gx_no_color_index ) *pptr = (byte)zero; } if ( (bit >>= 1) == 0 ) bit = 0x80, sbyte = *sptr++; pptr++; } while ( --count > 0 ); line += raster; next_scan_line(dest_line, dest); } } /* Copy a color bitmap. */ private int mem_mapped_copy_color(gx_device *dev, byte *base, int sourcex, int raster, int x, int y, int w, int h) { check_rect(); return copy_byte_rect(dev, base + x_to_byte(sourcex), raster, x_to_byte(x), y, x_to_byte(w), h); } /* ------ True (32-bit) color ------ */ /* Procedures */ private gx_color_index mem_true_map_rgb_color(P4(gx_device *, ushort, ushort, ushort)); private int mem_true_map_color_rgb(P3(gx_device *, gx_color_index, ushort *)), mem_true_copy_mono(P10(gx_device *, byte *, int, int, int, int, int, int, gx_color_index, gx_color_index)), mem_true_copy_color(P8(gx_device *, byte *, int, int, int, int, int, int)), mem_true_fill_rectangle(P6(gx_device *, int, int, int, int, gx_color_index)); /* The device descriptor. */ private gx_device_procs mem_true_procs = { mem_open, gx_default_close_device, mem_true_map_rgb_color, mem_true_map_color_rgb, gx_default_sync_output, mem_true_fill_rectangle, gx_default_tile_rectangle, mem_true_copy_mono, mem_true_copy_color, gx_default_draw_line, gx_default_fill_trapezoid, gx_default_tile_trapezoid }; /* The instance is public. */ gx_device_memory mem_true_device = { sizeof(gx_device_memory), &mem_true_procs, identity_matrix_body, 0, 0, /* x and y extent (filled in) */ 1, 255, 32, /* 32-bit true color */ 1, /* bit-big-endian */ 0, /* not open yet */ 0, /* raster (filled in) */ (byte *)0, /* base (filled in) */ (byte **)0, /* line_ptrs (filled in by 'open') */ 0, /* invert (unused) */ 0, (byte *)0 /* palette (unused) */ }; /* Convert x coordinate to byte offset in scan line. */ #undef x_to_byte #define x_to_byte(x) ((x) << 2) /* Map a r-g-b color to a color index. */ private gx_color_index mem_true_map_rgb_color(gx_device *dev, ushort r, ushort g, ushort b) { return ((gx_color_index)r << 16) + (g << 8) + b; } /* Map a color index to a r-g-b color. */ private int mem_true_map_color_rgb(gx_device *dev, gx_color_index color, ushort *prgb) { prgb[0] = (color >> 16) & 0xff; prgb[1] = (color >> 8) & 0xff; prgb[2] = color & 0xff; return 0; } /* Fill a rectangle with a color. */ private int mem_true_fill_rectangle(gx_device *dev, int x, int y, int w, int h, gx_color_index color) { declare_scan_ptr(dest_line, dest); setup_rect(dest_line, dest); while ( h-- > 0 ) { gx_color_index *pptr = (gx_color_index *)dest; int cnt = w; do { *pptr++ = color; } while ( --cnt > 0 ); next_scan_line(dest_line, dest); } } /* Copy a monochrome bitmap. */ private int mem_true_copy_mono(gx_device *dev, byte *base, int sourcex, int raster, int x, int y, int w, int h, gx_color_index zero, gx_color_index one) { byte *line; int first_bit; declare_scan_ptr(dest_line, dest); setup_rect(dest_line, dest); line = base + (sourcex >> 3); first_bit = 0x80 >> (sourcex & 7); while ( h-- > 0 ) { register gx_color_index *pptr = (gx_color_index *)dest; 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 = one; } else { if ( zero != gx_no_color_index ) *pptr = zero; } if ( (bit >>= 1) == 0 ) bit = 0x80, sbyte = *sptr++; pptr++; } while ( --count > 0 ); line += raster; next_scan_line(dest_line, dest); } } /* Copy a color bitmap. */ private int mem_true_copy_color(gx_device *dev, byte *base, int sourcex, int raster, int x, int y, int w, int h) { check_rect(); return copy_byte_rect(dev, base + x_to_byte(sourcex), raster, x_to_byte(x), y, x_to_byte(w), h); }