📄 vga16.c
字号:
/*** $Id: vga16.c,v 1.21 2003/11/21 12:44:01 weiym Exp $**** vga16.c: VGA 16-color GAL engine built on SVGALib**** Copyright (C) 2003 Feynman Software.** Copyright (C) 2001, 2002 Wei Yongming.**** Create by Wei Yongming, 2001/09/21*//*** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <unistd.h>#include <fcntl.h>#include "common.h"#include "minigui.h"#include "gdi.h"#include "window.h"#include "gal.h"#ifdef _VGA16_GAL#include <sys/io.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <vga.h>#include "vga16.h"#ifdef _LITE_VERSION#include "ourhdr.h"#include "client.h"#include "sharedres.h"static int __mg_saved_clip_minx, __mg_saved_clip_miny, __mg_saved_clip_maxx, __mg_saved_clip_maxy;static int set_effective_clip_rect (GC_VGA16* gc){ if (__mg_saved_clip_minx < SHAREDRES_CLI_SCR_LX) gc->clipminx = SHAREDRES_CLI_SCR_LX; else gc->clipminx = __mg_saved_clip_minx; if (__mg_saved_clip_miny < SHAREDRES_CLI_SCR_TY) gc->clipminy = SHAREDRES_CLI_SCR_TY; else gc->clipminy = __mg_saved_clip_miny; if (__mg_saved_clip_maxx > (SHAREDRES_CLI_SCR_RX + 1)) gc->clipmaxx = SHAREDRES_CLI_SCR_RX; else gc->clipmaxx = __mg_saved_clip_maxx; if (__mg_saved_clip_maxy > (SHAREDRES_CLI_SCR_BY + 1)) gc->clipmaxy = SHAREDRES_CLI_SCR_BY; else gc->clipmaxy = __mg_saved_clip_maxy; if (gc->clipmaxx < gc->clipminx) return -1; else if (gc->clipmaxy < gc->clipminy) return -1; gc->clipmaxx ++; gc->clipmaxy ++; return 0;}#define BLOCK_DRAW_SEM \ if (!mgIsServer && cur_gfx->phygc.gc_vga16 == gc.gc_vga16) \ lock_draw_sem (); \ if (((!mgIsServer && (SHAREDRES_TOPMOST_LAYER != __mg_layer)) || __mg_switch_away)) \ goto leave_drawing; \ if (!mgIsServer && cur_gfx->phygc.gc_vga16 == gc.gc_vga16) \ if (set_effective_clip_rect (gc.gc_vga16)) \ goto leave_drawing;#define UNBLOCK_DRAW_SEM \ if (!mgIsServer && cur_gfx->phygc.gc_vga16 == gc.gc_vga16) \leave_drawing: \ unlock_draw_sem ()#else#define BLOCK_DRAW_SEM#define UNBLOCK_DRAW_SEM#endif/* * Low Level Graphics Operations */static int bytesperpixel (GAL_GC gc) { return 1;}static int bitsperpixel (GAL_GC gc) { return 4;}static int width (GAL_GC gc) { return gc.gc_vga16->xres; }static int height (GAL_GC gc) { return gc.gc_vga16->yres; }static int colors (GAL_GC gc) { return 16;}static int setclipping (GAL_GC gc, int x1, int y1, int x2, int y2){ GC_VGA16* mygc; mygc = gc.gc_vga16; if (x1 < 0) x1 = 0; if (y1 < 0) y1 = 0; if (x2 > mygc->xres - 1) x2 = mygc->xres - 1; if (y2 > mygc->yres - 1) y2 = mygc->yres - 1; mygc->doclip = 1;#ifdef _LITE_VERSION if (!mgIsServer && mygc == cur_gfx->phygc.gc_vga16) { __mg_saved_clip_minx = x1; __mg_saved_clip_miny = y1; __mg_saved_clip_maxx = x2; __mg_saved_clip_maxy = y2; } else {#endif mygc->clipminx = x1; mygc->clipminy = y1; mygc->clipmaxx = x2 + 1; mygc->clipmaxy = y2 + 1;#ifdef _LITE_VERSION }#endif return 0;}static void enableclipping (GAL_GC gc){ GC_VGA16* mygc = gc.gc_vga16; setclipping (gc, 0, 0, mygc->xres - 1, mygc->yres - 1);}static void disableclipping (GAL_GC gc){ gc.gc_vga16->doclip = 0;}static int getclipping (GAL_GC gc, int* x1, int* y1, int* x2, int* y2){ GC_VGA16* mygc; mygc = gc.gc_vga16;#ifdef _LITE_VERSION if (!mgIsServer && mygc == cur_gfx->phygc.gc_vga16) { *x1 = __mg_saved_clip_minx; *y1 = __mg_saved_clip_miny; *x2 = __mg_saved_clip_maxx; *y2 = __mg_saved_clip_maxy; } else {#endif *x1 = mygc->clipminx; *y1 = mygc->clipminy; *x2 = mygc->clipmaxx - 1; *y2 = mygc->clipmaxy - 1; #ifdef _LITE_VERSION }#endif return 0;}/* * Allocation and release of graphics context */static int allocategc (GAL_GC gc, int width, int height, int depth, GAL_GC* newgc){ GC_VGA16* mygc; if (!(newgc->gc_vga16 = (GC_VGA16*)malloc (sizeof (GC_VGA16)))) return -1; mygc = newgc->gc_vga16; mygc->xres = width; mygc->yres = height; mygc->pitch = width; mygc->gr_background = 0; mygc->gr_foreground = 15; enableclipping (*newgc); if (!(mygc->fb_buff = calloc (1, mygc->pitch * height))) { free (mygc); return -1; } return 0;}static void freegc (GAL_GC gc){ GC_VGA16* mygc; mygc = gc.gc_vga16; free (mygc->fb_buff); free (mygc);}/* * Background and foreground colors */static int getbgcolor (GAL_GC gc, gal_pixel* color){ GC_VGA16* mygc = gc.gc_vga16; *color = mygc->gr_background; return 0;}static int setbgcolor (GAL_GC gc, gal_pixel color){ GC_VGA16* mygc = gc.gc_vga16; mygc->gr_background = color; return 0;}static int getfgcolor (GAL_GC gc, gal_pixel* color){ GC_VGA16* mygc = gc.gc_vga16; *color = mygc->gr_foreground; return 0;}static int setfgcolor (GAL_GC gc, gal_pixel color){ GC_VGA16* mygc = gc.gc_vga16; mygc->gr_foreground = color; if (mygc->fb_buff == 0) { vga_setcolor (color & 0x0F); } return 0;}/* * Convertion between GAL_Color and gal_pixel * borrowed from gl lib. */static gal_pixel mapcolor (GAL_GC gc, GAL_Color *color){ unsigned int v; /* Now this is real fun. Map to standard EGA palette. */ v = 0; if (color->b >= 64) v += 1; if (color->g >= 64) v += 2; if (color->r >= 64) v += 4; if (color->b >= 192 || color->g >= 192 || color->r >= 192) v += 8; return v;}static int unmappixel (GAL_GC gc, gal_pixel pixel, GAL_Color* color){ color->r = SysPixelColor [pixel].r; color->g = SysPixelColor [pixel].g; color->b = SysPixelColor [pixel].b; return 0;}/* * Palette operations */static int getpalette (GAL_GC gc, int s, int len, GAL_Color* cmap){ int i; int r, g, b; if (gc.gc_vga16 != cur_gfx->phygc.gc_vga16) return 0; for (i = 0; i < len; i++) { vga_getpalette (i + s, &r, &g, &b); cmap [i].r = r << 2; cmap [i].g = g << 2; cmap [i].b = b << 2; } return 0;}static int setpalette (GAL_GC gc, int s, int len, GAL_Color* cmap){ int i; if (gc.gc_vga16 != cur_gfx->phygc.gc_vga16) return 0; for (i = s; i < s + len; i++) { vga_setpalette (i, cmap->r >> 2, cmap->g >> 2, cmap->b >> 2); cmap ++; } return 0;}/* * Specical functions work for <=8 bit color mode. */static int setcolorfulpalette (GAL_GC gc){ int i; if (gc.gc_vga16 != cur_gfx->phygc.gc_vga16) return 0; for (i = 0; i < 16; i++) { vga_setpalette (i, SysPixelColor[i].r >> 2, SysPixelColor[i].g >> 2, SysPixelColor[i].b >> 2); } return 0;}/* * Box operations */static size_t boxsize (GAL_GC gc, int w, int h){ if ((w <= 0) || (h <= 0)) return -1; return w * h;}#define CLIP_INVISIBLE 0#define CLIP_VISIBLE 1#define CLIP_PARTIAL 2static int vga16_clippoint (PGC_VGA16 gc, int x ,int y){ if (gc->doclip) { if ((x >= gc->clipminx) && (x < gc->clipmaxx) && (y >= gc->clipminy) && (y < gc->clipmaxy)) return CLIP_VISIBLE; } else { if ((x >= 0) && (x < gc->xres) && (y >= 0) && (y < gc->yres)) return CLIP_VISIBLE; } return CLIP_INVISIBLE;}static int vga16_cliphline (PGC_VGA16 gc,int * px,int * py, int * pw){ if (gc->doclip) { if ( (*px >= gc->clipmaxx) || (*py >= gc->clipmaxy) || (*px + *pw - 1 < gc->clipminx) || (*py < gc->clipminy) ) return CLIP_INVISIBLE; if ( (*px >= gc->clipminx) && (*py >= gc->clipminy) && (*px + *pw -1 < gc->clipmaxx) && (*py < gc->clipmaxy) ) return CLIP_VISIBLE; if (*px < gc->clipminx) { *pw -= gc->clipminx - *px; *px = gc->clipminx; } if (*px + *pw - 1 >= gc->clipmaxx) *pw = gc->clipmaxx - *px; } else { if ( (*px >= gc->xres) || (*py >= gc->yres) || (*px + *pw - 1 < 0) || (*py < 0) ) return CLIP_INVISIBLE; if ( (*px >= 0) && (*py >= 0) && (*px + *pw -1 < gc->xres) && (*py < gc->yres) ) return CLIP_VISIBLE; if (*px < 0) { *pw += *px; *px = 0; } if (*px + *pw - 1 >= gc->xres) *pw = gc->xres - *px; } if (*pw <= 0) return CLIP_INVISIBLE; return CLIP_PARTIAL; }static int vga16_clipvline(PGC_VGA16 gc,int * px,int * py, int *ph){ if (gc->doclip) { if ( (*px >= gc->clipmaxx) || (*py >= gc->clipmaxy) || (*px < gc->clipminx) || (*py + *ph - 1 < gc->clipminy) ) return CLIP_INVISIBLE; if ( (*px >= gc->clipminx) && (*py >= gc->clipminy) && (*px < gc->clipmaxx) && (*py + *ph - 1 < gc->clipmaxy) ) return CLIP_VISIBLE; if (*py < gc->clipminy) { *ph -= gc->clipminy - *py; *py = gc->clipminy; } if (*py + *ph - 1 >= gc->clipmaxy) *ph = gc->clipmaxy - *py; } else { if ( (*py >= gc->yres) || (*px >= gc->xres) || (*py + *ph - 1 < 0) || (*px < 0) ) return CLIP_INVISIBLE; if ( (*py >= 0) && (*px >= 0) && (*py + *ph -1 < gc->yres) && (*px < gc->xres) ) return CLIP_VISIBLE; if (*py < 0) { *ph += *py; *py = 0; } if (*py + *ph - 1 >= gc->yres) *ph = gc->yres - *py; } if (*ph <= 0) return CLIP_INVISIBLE; return CLIP_PARTIAL; }#define OC_LEFT 1#define OC_RIGHT 2#define OC_TOP 4#define OC_BOTTOM 8/* Outcodes:+-> x| | | V 0101 | 0100 | 0110y --------------------- 0001 | 0000 | 0010 --------------------- 1001 | 1000 | 1010 | | */#define outcode(code, xx, yy) \{\ code = 0;\ if (xx < tempclipminx)\ code |= OC_LEFT;\ else if (xx > tempclipmaxx)\ code |= OC_RIGHT;\ if (yy < tempclipminy)\ code |= OC_TOP;\ else if (yy>tempclipmaxy)\ code |= OC_BOTTOM;\}/* Calculates |_ a/b _| with mathematically correct floor */static int FloorDiv(int a, int b){ int floor; if (b>0) { if (a>0) { return a /b; } else { floor = -((-a)/b); if ((-a)%b != 0) floor--; } return floor; } else { if (a>0) { floor = -(a/(-b)); if (a%(-b) != 0) floor--; return floor; } else { return (-a)/(-b); } }}/* Calculates |^ a/b ^| with mathamatically correct floor */static int CeilDiv(int a,int b){ if (b>0) return FloorDiv(a-1,b)+1; else return FloorDiv(-a-1,-b)+1;}static int cs_clipline (PGC_VGA16 gc,int *_x0, int *_y0, int *_x1, int *_y1, int *clip_first, int *clip_last){ int first,last, code; int x0,y0,x1,y1; int x,y; int dx,dy; int xmajor; int slope; int tempclipminx,tempclipminy,tempclipmaxx,tempclipmaxy; if (gc->doclip) { tempclipminx = gc->clipminx; tempclipminy = gc->clipminy; tempclipmaxx = gc->clipmaxx; tempclipmaxy = gc->clipmaxy; } else { tempclipminx = 0; tempclipminy = 0; tempclipmaxx = gc->xres - 1; tempclipmaxy = gc->yres - 1; } first = 0; last = 0; outcode(first,*_x0,*_y0); outcode(last,*_x1,*_y1); if ((first | last) == 0) { return CLIP_VISIBLE; /* Trivially accepted! */ } if ((first & last) != 0) { return CLIP_INVISIBLE; /* Trivially rejected! */ } x0=*_x0; y0=*_y0; x1=*_x1; y1=*_y1; dx = x1 - x0; dy = y1 - y0; xmajor = (abs(dx) > abs(dy)); slope = ((dx>=0) && (dy>=0)) || ((dx<0) && (dy<0)); for (;;) { code = first; if (first==0) code = last; if (code&OC_LEFT) { x = tempclipminx; if (xmajor) { y = *_y0 + FloorDiv(dy*(x - *_x0)*2 + dx, 2*dx);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -