diff options
Diffstat (limited to 'gs/base/gdevsgi.c')
-rw-r--r-- | gs/base/gdevsgi.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/gs/base/gdevsgi.c b/gs/base/gdevsgi.c new file mode 100644 index 000000000..e1b7a1b94 --- /dev/null +++ b/gs/base/gdevsgi.c @@ -0,0 +1,223 @@ +/* + * This file is distributed with Ghostscript, but its author, + * Tanmoy Bhattacharya (tanmoy@qcd.lanl.gov) hereby places it in the + * public domain. + */ + +/* $Id$*/ +/* SGI raster file driver */ +#include "gdevprn.h" +#include "gdevsgi.h" + +#define X_DPI 72 +#define Y_DPI 72 + +#define sgi_prn_device(procs, dev_name, num_comp, depth, max_gray, max_color, print_page)\ +{prn_device_body(gx_device_printer, procs, dev_name, \ + DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, X_DPI, Y_DPI, \ + 0, 0, 0, 0, \ + num_comp, depth, max_gray, max_color, max_gray+1, max_color+1, \ + print_page)} + +static dev_proc_map_rgb_color(sgi_map_rgb_color); +static dev_proc_map_color_rgb(sgi_map_color_rgb); + +static dev_proc_print_page(sgi_print_page); + +static gx_device_procs sgi_procs = + prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close, + sgi_map_rgb_color, sgi_map_color_rgb); + +const gx_device_printer far_data gs_sgirgb_device = + sgi_prn_device(sgi_procs, "sgirgb", 3, 24, 255, 255, sgi_print_page); + +static gx_color_index +sgi_map_rgb_color(gx_device * dev, const ushort cv[]) +{ ushort bitspercolor = dev->color_info.depth / 3; + ulong max_value = (1 << bitspercolor) - 1; + ushort red, green, blue; + red = cv[0]; green = cv[1]; blue = cv[2]; + + return ((red*max_value / gx_max_color_value) << (bitspercolor * 2)) + + ((green*max_value / gx_max_color_value) << bitspercolor) + + (blue*max_value / gx_max_color_value); +} + +static int +sgi_map_color_rgb(gx_device *dev, gx_color_index color, ushort prgb[3]) +{ ushort bitspercolor = dev->color_info.depth / 3; + ushort colormask = (1 << bitspercolor) - 1; + + prgb[0] = (ushort)(((color >> (bitspercolor * 2)) & colormask) * + (ulong)gx_max_color_value / colormask); + prgb[1] = (ushort)(((color >> bitspercolor) & colormask) * + (ulong)gx_max_color_value / colormask); + prgb[2] = (ushort)((color & colormask) * + (ulong)gx_max_color_value / colormask); + return 0; +} + +typedef struct sgi_cursor_s { + gx_device_printer *dev; + int bpp; + uint line_size; + byte *data; + int lnum; +} sgi_cursor; + +static int +sgi_begin_page(gx_device_printer *bdev, FILE *pstream, sgi_cursor *pcur) +{ + uint line_size = gdev_mem_bytes_per_scan_line((gx_device_printer*)bdev); + byte *data = (byte*)gs_malloc(bdev->memory, line_size, 1, "sgi_begin_page"); + IMAGE *header= (IMAGE*)gs_malloc(bdev->memory, sizeof(IMAGE),1,"sgi_begin_page"); + char filler= '\0'; + int i; + + if ((data == (byte*)0)||(header == (IMAGE*)0)) return -1; + + bzero(header,sizeof(IMAGE)); + header->imagic = IMAGIC; + header->type = RLE(1); + header->dim = 3; + header->xsize=bdev->width; + header->ysize=bdev->height; + header->zsize=3; + header->min_color = 0; + header->max_color = bdev->color_info.max_color; + header->wastebytes = 0; + strncpy(header->name,"gs picture",80); + header->colormap = CM_NORMAL; + header->dorev=0; + fwrite(header,sizeof(IMAGE),1,pstream); + for (i=0; i<512-sizeof(IMAGE); i++) fputc(filler,pstream); + pcur->dev = bdev; + pcur->bpp = bdev->color_info.depth; + pcur->line_size = line_size; + pcur->data = data; + return 0; +} + +static int +sgi_next_row(sgi_cursor *pcur) +{ if (pcur->lnum < 0) + return 1; + gdev_prn_copy_scan_lines((gx_device_printer*)pcur->dev, + pcur->lnum--, pcur->data, pcur->line_size); + return 0; +} + +#define bdev ((gx_device_printer *)pdev) + +static int +sgi_print_page(gx_device_printer *pdev, FILE *pstream) +{ sgi_cursor cur; + int code = sgi_begin_page(bdev, pstream, &cur); + uint bpe, mask; + int separation; + long *rowsizes=(long*)gs_malloc(pdev->memory, 4,3*bdev->height,"sgi_print_page"); + byte *edata ; + long lastval; + int rownumber; +#define aref2(a,b) a*bdev->height+b + edata = (byte*)gs_malloc(pdev->memory, cur.line_size, 1, "sgi_begin_page"); + if((code<0)||(rowsizes==(long*)NULL)||(edata==(byte*)NULL)) return(-1); + fwrite(rowsizes,sizeof(long),3*bdev->height,pstream); /* rowstarts */ + fwrite(rowsizes,sizeof(long),3*bdev->height,pstream); /* rowsizes */ + lastval = 512+sizeof(long)*6*bdev->height; + fseek(pstream,lastval,0); + for (separation=0; separation < 3; separation++) + { + cur.lnum = cur.dev->height-1; + rownumber = 0; + bpe = cur.bpp/3; + mask = (1<<bpe) - 1; + while ( !(code=sgi_next_row(&cur))) + { byte *bp; + uint x; + int shift; + byte *curcol=cur.data; + byte *startcol=edata; + int count; + byte todo, cc; + byte *iptr, *sptr, *optr, *ibufend; + for (bp = cur.data, x=0, shift = 8 - cur.bpp; + x < bdev->width; + ) + { ulong pixel = 0; + uint r, g, b; + switch (cur.bpp >> 3) + { + case 3: pixel = (ulong)*bp << 16; bp++; + case 2: pixel += (uint)*bp << 8; bp++; + case 1: pixel += *bp; bp++; break; + case 0: pixel = *bp >> shift; + if ((shift-=cur.bpp) < 0) + bp++, shift += 8; break; + } + ++x; + b = pixel & mask; pixel >>= bpe; + g = pixel & mask; pixel >>= bpe; + r = pixel & mask; + switch(separation) + { + case 0: *curcol++=r; break; + case 1: *curcol++=g; break; + case 2: *curcol++=b; break; + } + } + iptr=cur.data; + optr=startcol; + ibufend=curcol-1; + while(iptr<ibufend) { + sptr = iptr; + iptr += 2; + while((iptr<ibufend)&&((iptr[-2]!=iptr[-1])||(iptr[-1]!=iptr[0]))) + iptr++; + iptr -= 2; + count = iptr-sptr; + while(count) { + todo = count>126 ? 126:count; + count -= todo; + *optr++ = 0x80|todo; + while(todo--) + *optr++ = *sptr++; + } + sptr = iptr; + cc = *iptr++; + while( (iptr<ibufend) && (*iptr == cc) ) + iptr++; + count = iptr-sptr; + while(count) { + todo = count>126 ? 126:count; + count -= todo; + *optr++ = todo; + *optr++ = cc; + } + } + *optr++ = 0; + rowsizes[aref2(separation,rownumber++)] = optr-startcol; + fwrite(startcol,1,optr-startcol,pstream); + } + } + fseek(pstream,512L,0); + for(separation=0; separation<3; separation++) + for(rownumber=0; rownumber<bdev->height; rownumber++) + {fputc((char)(lastval>>24),pstream); + fputc((char)(lastval>>16),pstream); + fputc((char)(lastval>>8),pstream); + fputc((char)(lastval),pstream); + lastval+=rowsizes[aref2(separation,rownumber)];} + for(separation=0; separation<3; separation++) + for(rownumber=0; rownumber<bdev->height; rownumber++) + {lastval=rowsizes[aref2(separation,rownumber)]; + fputc((char)(lastval>>24),pstream); + fputc((char)(lastval>>16),pstream); + fputc((char)(lastval>>8),pstream); + fputc((char)(lastval),pstream);} + gs_free(pdev->memory, (char*)cur.data, cur.line_size, 1, + "sgi_print_page(done)"); + gs_free(pdev->memory, (char*)edata, cur.line_size, 1, "sgi_print_page(done)"); + gs_free(pdev->memory, (char*)rowsizes,4,3*bdev->height,"sgi_print_page(done)"); + return (code < 0 ? code : 0); +} |