/* * This file is distributed with Ghostscript, but its author, * Tanmoy Bhattacharya (tanmoy@qcd.lanl.gov) hereby places it in the * public domain. */ /* $Id: gdevsgi.c,v 1.6 2004/08/10 13:02:36 stefan Exp $*/ /* 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)} private dev_proc_map_rgb_color(sgi_map_rgb_color); private dev_proc_map_color_rgb(sgi_map_color_rgb); private dev_proc_print_page(sgi_print_page); private 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); private 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); } private 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; private 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; } private 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) private 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<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(iptr126 ? 126:count; count -= todo; *optr++ = 0x80|todo; while(todo--) *optr++ = *sptr++; } sptr = iptr; cc = *iptr++; while( (iptr126 ? 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; rownumberheight; 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; rownumberheight; 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); }