/* Copyright (C) 1992 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. */ /* * gdevlinux.c * * This is a driver for 386 PCs using VGALIB for graphics on the console * display. * * Written by Sigfrid Lundberg, siglun@euler.teorekol.lu.se. * * Support for all the SVGAlib video modes, MAGSTEP, XO, YO, and additions * to the gs.1 man page by Patrick Volkerding, volkerdi@mhd1.moorhead.msus.edu. * */ #include "gx.h" #include "gxdevice.h" #include "gserrors.h" #include #include extern char svgalib_detected; extern char video_resolution[25]; extern float size_multiplier; extern float adjust_xo; extern float adjust_yo; extern char xo_units; extern char yo_units; int screen_width, screen_height; int xorigin, yorigin; typedef struct gx_device_linux { gx_device_common; int fd; /* window file descriptor */ uchar *screen; /* pointer to screen image */ ushort line_size; /* size of single screen line in bytes */ ulong screen_size; /* size of screen image in bytes */ int screen_width, screen_height; /* size of screen used */ int page; /* page number */ #ifdef LINUX_PERF char *no_output, *no_fill, *no_copy; #endif } gx_device_linux; #define linuxdev ((gx_device_linux *)dev) #define XDPI 60 /* to get a more-or-less square aspect ratio */ #define YDPI 60 #ifndef A4 /*Letter size*/ #define YSIZE (20.0 * YDPI / 2.5)) #define XSIZE (8.5 / 11)*YSIZE /* 8.5 x 11 inch page, by default */ #else /* A4 paper */ #define XSIZE 8.27 #define YSIZE 11.69 #endif dev_proc_open_device(linux_open); dev_proc_close_device(linux_close); dev_proc_draw_line(linux_draw_line); dev_proc_fill_rectangle(linux_fill_rectangle); dev_proc_tile_rectangle(linux_tile_rectangle); dev_proc_map_color_rgb(linux_map_color_rgb); dev_proc_map_rgb_color(linux_map_rgb_color); dev_proc_copy_mono(linux_copy_mono); dev_proc_copy_color(linux_copy_color); private gx_device_procs linux_procs = { linux_open, gx_default_get_initial_matrix, gx_default_sync_output, gx_default_output_page, linux_close, linux_map_rgb_color, linux_map_color_rgb, linux_fill_rectangle, linux_tile_rectangle, linux_copy_mono, linux_copy_color, linux_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }; gx_device_linux gs_linux_device = { sizeof(gx_device_linux), &linux_procs, "linux", 0,0, 1,1, no_margins, dci_black_and_white, 0 }; int linux_open(gx_device *dev) { if (!strcmp(video_resolution,"320x200x16") || !strcmp(video_resolution,"1")) { vga_setmode(1); } else if (!strcmp(video_resolution,"640x200x16") || !strcmp(video_resolution,"2")) { vga_setmode(2); } else if (!strcmp(video_resolution,"640x350x16") || !strcmp(video_resolution,"3")) { vga_setmode(3); } else if (!strcmp(video_resolution,"640x480x16") || !strcmp(video_resolution,"4")) { vga_setmode(4); } else if (!strcmp(video_resolution,"320x200x256") || !strcmp(video_resolution,"5")) { vga_setmode(5); } else if (!strcmp(video_resolution,"320x240x256") || !strcmp(video_resolution,"6")) { vga_setmode(6); } else if (!strcmp(video_resolution,"320x400x256") || !strcmp(video_resolution,"7")) { vga_setmode(7); } else if (!strcmp(video_resolution,"360x480x256") || !strcmp(video_resolution,"8")) { vga_setmode(8); } else if (!strcmp(video_resolution,"640x480x2") || !strcmp(video_resolution,"9")) { vga_setmode(9); } else if (!strcmp(video_resolution,"640x480x256") || !strcmp(video_resolution,"10")) { vga_setmode(10); } else if (!strcmp(video_resolution,"800x600x256") || !strcmp(video_resolution, "11")) { vga_setmode(11); } else if (!strcmp(video_resolution,"1024x768x256") || !strcmp(video_resolution,"12")) { vga_setmode(12); } else if (!strcmp(video_resolution,"320x200x32K") || !strcmp(video_resolution,"13")) { vga_setmode(13); } else if (!strcmp(video_resolution,"320x200x64K") || !strcmp(video_resolution,"14")) { vga_setmode(14); } else if (!strcmp(video_resolution,"320x200x16M") || !strcmp(video_resolution,"15")) { vga_setmode(15); } else if (!strcmp(video_resolution,"640x480x32K") || !strcmp(video_resolution,"16")) { vga_setmode(16); } else if (!strcmp(video_resolution,"640x480x64K") || !strcmp(video_resolution,"17")) { vga_setmode(17); } else if (!strcmp(video_resolution,"640x480x16M") || !strcmp(video_resolution,"18")) { vga_setmode(18); } else if (!strcmp(video_resolution,"800x600x32K") || !strcmp(video_resolution,"19")) { vga_setmode(19); } else if (!strcmp(video_resolution,"800x600x64K") || !strcmp(video_resolution,"20")) { vga_setmode(20); } else if (!strcmp(video_resolution,"800x600x16M") || !strcmp(video_resolution,"21")) { vga_setmode(21); } else if (!strcmp(video_resolution,"1024x768x32K") || !strcmp(video_resolution,"22")) { vga_setmode(22); } else if (!strcmp(video_resolution,"1024x768x64K") || !strcmp(video_resolution,"23")) { vga_setmode(23); } else if (!strcmp(video_resolution,"1024x768x16M") || !strcmp(video_resolution,"24")) { vga_setmode(24); } else if (!strcmp(video_resolution,"1280x1024x256") || !strcmp(video_resolution,"25")) { vga_setmode(25); } else if (!strcmp(video_resolution,"1280x1024x32K") || !strcmp(video_resolution,"26")) { vga_setmode(26); } else if (!strcmp(video_resolution,"1280x1024x64K") || !strcmp(video_resolution,"27")) { vga_setmode(27); } else if (!strcmp(video_resolution,"1280x1024x16M") || !strcmp(video_resolution,"28")) { vga_setmode(28); } else if (!strcmp(video_resolution,"720x350x16") || !strcmp(video_resolution,"29")) { vga_setmode(29); } else if (!strcmp(video_resolution,"720x480x16") || !strcmp(video_resolution,"30")) { vga_setmode(30); } else { fprintf(stdout,"Sorry, but %s is not a recognized SVGAlib mode.\n\n",video_resolution); fprintf(stdout,"These are the recognized video modes, (and mode numbers):\n"); fprintf(stdout," 320x200x16 (1), 640x200x16 (2), 640x350x16 (3), 640x480x16 (4), \n"); fprintf(stdout," 320x200x256 (5), 320x240x256 (6), 320x400x256 (7), 360x480x256 (8), \n"); fprintf(stdout," 640x480x2 (9), 640x480x256 (10), 800x600x256 (11), 1024x768x256 (12), \n"); fprintf(stdout," 320x200x32K (13), 320x200x64K (14), 320x200x16M (15), 640x480x32K (16), \n"); fprintf(stdout," 640x480x64K (17), 640x480x16M (18), 800x600x32K (19), 800x600x64K (20), \n"); fprintf(stdout," 800x600x16M (21), 1024x768x32K (22), 1024x768x64K (23), 1024x768x16M (24), \n"); fprintf(stdout," 1280x1024x256 (25), 1280x1024x32K (26), 1280x1024x64K (27), \n"); fprintf(stdout," 1280x1024x16M (28), 720x350x16 (29), 720x480x16 (30), \n"); fprintf(stdout,"\n"); fprintf(stdout,"In addition to -r, these flags also work with -sDEVICE=linux:\n"); fprintf(stdout,"\n"); fprintf(stdout," -dMAGSTEP= : Change the image size. Values 0.0 < value < 1.0 shrink\n"); fprintf(stdout," the image size, while values > 1.0 expand it. The default value is 1.0.\n"); fprintf(stdout,"\n"); fprintf(stdout," -dXO=[units], -dYO=[units] : Specify a new origin. The upper-\n"); fprintf(stdout," left hand corner of the image is considered to be (0,0). You may move\n"); fprintf(stdout," the origin down and/or right using these flags. The default unit of \n"); fprintf(stdout," measurement is inches (in), but you may also use centimeters (cm), or\n"); fprintf(stdout," percent (%%) of distance from the origin (0%% - 100%%).\n"); exit(1); } fprintf(stdout,"\nSelected SVGAlib resolution: %s\n",video_resolution); vga_clear(); if ( dev->width == 0 ) dev->width = vga_getxdim() * size_multiplier; /* + 1; */ screen_width = vga_getxdim(); if ( dev->height == 0 ) dev->height = vga_getydim() * size_multiplier; /* + 1; */ screen_height = vga_getydim(); /*vgalib provides no facilities for finding out aspect ratios*/ if ( dev->y_pixels_per_inch == 1 ) { dev->y_pixels_per_inch = dev->height / 11.0; dev->x_pixels_per_inch = dev->y_pixels_per_inch; if (xo_units == 'c') adjust_xo /= 2.58; if (yo_units == 'c') adjust_yo /= 2.58; if (xo_units == '%') { if (adjust_xo < 0) adjust_xo = 0; if (adjust_xo > 100) adjust_xo = 100; adjust_xo = 8.5 * (adjust_xo/100); } if (yo_units == '%') { if (adjust_yo < 0) adjust_yo = 0; if (adjust_yo > 100) adjust_yo = 100; adjust_yo = 11 * (adjust_yo/100); } xorigin = dev->x_pixels_per_inch * adjust_xo; yorigin = dev->y_pixels_per_inch * adjust_yo; } /* Find out if the device supports color */ /* (default initialization is monochrome). */ /* We only recognize 16-color devices right now. */ if ( vga_getcolors() > 1 ) { int index,one,rgb[3]; static gx_device_color_info linux_16color = dci_color(4, 2, 3); dev->color_info = linux_16color; for(index=0;index gx_max_color_value / 4 ? 4 : 0) + (green > gx_max_color_value / 4 ? 2 : 0) + (blue > gx_max_color_value / 4 ? 1 : 0) + (red > gx_max_color_value / 4 * 3 || green > gx_max_color_value / 4 * 3 ? 8 : 0)); return (gx_color_index)index; } /* I actually don't understand what I'm doing -- the only thing I want to achieve are palettes that emulates BGI */ int linux_map_color_rgb(gx_device *dev, gx_color_index index, unsigned short rgb[3]) { int red, green, blue; gx_color_value one = (index & 8 ? gx_max_color_value : gx_max_color_value / 3); rgb[0] = (index & 4 ? one : 0); rgb[1] = (index & 2 ? one : 0); rgb[2] = (index & 1 ? one : 0); return 0; } void adj_vga_drawpixel(int x, int y) { y -= yorigin; x -= xorigin; if (x < 0 || x >= screen_width || y < 0 || y >= screen_height) return; vga_drawpixel(x,y); } void adj_vga_drawline(int x1, int y1, int x2, int y2 ) { y1 -= yorigin; y2 -= yorigin; x1 -= xorigin; x2 -= xorigin; if (x1 < 0 || x1 >= screen_width || y1 < 0 || y1 >= screen_height) return; if (x2 < 0 || x2 >= screen_width || y2 < 0 || y2 >= screen_height) return; vga_drawline(x1,y1,x2,y2); } int linux_draw_line(gx_device *dev, int x0, int y0, int x1, int y1, gx_color_index color) { if(!((x0==x1)&&(y0==y1))) { vga_setcolor((int)color); adj_vga_drawline(x0,y0,x1,y1); } return 0; } int linux_tile_rectangle(gx_device *dev, const gx_bitmap *tile, int x, int y, int w, int h, gx_color_index czero, gx_color_index cone, int px, int py) { if ( czero != gx_no_color_index && cone != gx_no_color_index ) { linux_fill_rectangle(dev, x, y, w, h, czero); czero = gx_no_color_index; } return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px, py); } int linux_fill_rectangle(gx_device *dev, int x, int y, int w, int h, gx_color_index color) { int i,j; fit_fill(dev, x, y, w, h); vga_setcolor((int)color); for(i=y;i> 3); int left_bit = 0x80 >> (sourcex & 7); int dest_y = y, end_x = x + width; int invert = 0; int color; int i; fit_copy(dev, base, sourcex, raster, id, x, y, width, height); if ( zero == gx_no_color_index ) { if ( one == gx_no_color_index ) return 0; color = (int)one; } else { if ( one == gx_no_color_index ) { color = (int)zero; invert = -1; } else { /* Pre-clear the rectangle to zero */ vga_setcolor(zero); linux_fill_rectangle(dev,x,y,width,height,zero); color = (int)one; } } vga_setcolor(color); while( height-- ) { /* for each line */ const byte *ptr_source = ptr_line; register int dest_x = x; register int bit = left_bit; while ( dest_x < end_x ) { /* for each bit in the line */ if ( (*ptr_source ^ invert) & bit ) adj_vga_drawpixel(dest_x,dest_y); dest_x++; if ( (bit >>= 1) == 0 ) bit = 0x80, ptr_source++; } dest_y++; ptr_line += raster; } return 0; } /* Copy a color pixel map. This is just like a bitmap, except that */ /* each pixel takes 4 bits instead of 1 when device driver has color. */ int linux_copy_color(gx_device *dev, const byte *base, int sourcex, int raster, gx_bitmap_id id, int x, int y, int width, int height) { fit_copy(dev, base, sourcex, raster, id, x, y, width, height); if ( gx_device_has_color(dev) ) { /* color device, four bits per pixel */ const byte *line = base + (sourcex >> 1); int dest_y = y, end_x = x + width, i; if ( width <= 0 ) return 0; while ( height-- ) { /* for each line */ const byte *source = line; register int dest_x = x; if ( sourcex & 1 ) { /* odd nibble first */ int color = *source++ & 0xf; vga_setcolor(color); adj_vga_drawpixel(dest_x,dest_y); dest_x++; } /* Now do full bytes */ while ( dest_x < end_x ) { int color = *source >> 4; vga_setcolor(color); adj_vga_drawpixel(dest_x,dest_y); dest_x++; if ( dest_x < end_x ) { color = *source++ & 0xf; vga_setcolor(color); adj_vga_drawpixel(dest_x,dest_y); dest_x++; } } dest_y++; line += raster; } } else { /* monochrome device: one bit per pixel */ /* bitmap is the same as bgi_copy_mono: one bit per pixel */ linux_copy_mono(dev, base, sourcex, raster, id, x, y, width, height, (gx_color_index)0, (gx_color_index)7); } return 0; }