⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devdraw.c

📁 神龙卡开发原代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com> * Portions Copyright (c) 1991 David I. Bell * Permission is granted to use, distribute, or modify this source, * provided that this copyright notice remains intact. * * Device-independent mid level drawing and color routines. * * These routines do the necessary range checking, clipping, and cursor * overwriting checks, and then call the lower level device dependent * routines to actually do the drawing.  The lower level routines are * only called when it is known that all the pixels to be drawn are * within the device area and are visible. *//*#define NDEBUG*/#include <stdio.h>#include <stdlib.h>#include <assert.h>#include "device.h"extern MWPIXELVAL gr_foreground;      /* current foreground color */extern MWPIXELVAL gr_background;      /* current background color */extern MWBOOL 	  gr_usebg;    	      /* TRUE if background drawn in pixmaps */extern int 	  gr_mode; 	      /* drawing mode */extern MWPALENTRY gr_palette[256];    /* current palette*/extern int	  gr_firstuserpalentry;/* first user-changable palette entry*/extern int 	  gr_nextpalentry;    /* next available palette entry*//*static*/ void drawpoint(PSD psd,MWCOORD x, MWCOORD y);/*static*/ void drawrow(PSD psd,MWCOORD x1,MWCOORD x2,MWCOORD y);static void drawcol(PSD psd,MWCOORD x,MWCOORD y1,MWCOORD y2);/* * Set the drawing mode for future calls. */intGdSetMode(int mode){	int	oldmode = gr_mode;	gr_mode = mode;	return oldmode;}/* * Set whether or not the background is used for drawing pixmaps and text. */MWBOOLGdSetUseBackground(MWBOOL flag){	MWBOOL	oldusebg = gr_usebg;	gr_usebg = flag;	return oldusebg;}/* * Set the foreground color for drawing. */MWPIXELVALGdSetForeground(MWPIXELVAL fg){	MWPIXELVAL	oldfg = gr_foreground;		gr_foreground = fg;	return oldfg;}/* * Set the background color for bitmap and text backgrounds. */MWPIXELVALGdSetBackground(MWPIXELVAL bg){	MWPIXELVAL	oldbg = gr_background;	gr_background = bg;	return oldbg;}/* * Draw a point using the current clipping region and foreground color. */voidGdPoint(PSD psd, MWCOORD x, MWCOORD y){	if (GdClipPoint(psd, x, y)) {		psd->DrawPixel(psd, x, y, gr_foreground);		GdFixCursor(psd);	}}/* * Draw an arbitrary line using the current clipping region and foreground color * If bDrawLastPoint is FALSE, draw up to but not including point x2, y2. * * This routine is the only routine that adjusts coordinates for supporting * two different types of upper levels, those that draw the last point * in a line, and those that draw up to the last point.  All other local * routines draw the last point.  This gives this routine a bit more overhead, * but keeps overall complexity down. */voidGdLine(PSD psd, MWCOORD x1, MWCOORD y1, MWCOORD x2, MWCOORD y2,	MWBOOL bDrawLastPoint){  int xdelta;			/* width of rectangle around line */  int ydelta;			/* height of rectangle around line */  int xinc;			/* increment for moving x coordinate */  int yinc;			/* increment for moving y coordinate */  int rem;			/* current remainder */  MWCOORD temp;  /* See if the line is horizontal or vertical. If so, then call   * special routines.   */  if (y1 == y2) {	/*	 * Adjust coordinates if not drawing last point.  Tricky.	 */	if(!bDrawLastPoint) {		if (x1 > x2) {			temp = x1;			x1 = x2 + 1;			x2 = temp;		} else			--x2;	}	/* call faster line drawing routine*/	drawrow(psd, x1, x2, y1);	GdFixCursor(psd);	return;  }  if (x1 == x2) {	/*	 * Adjust coordinates if not drawing last point.  Tricky.	 */	if(!bDrawLastPoint) {		if (y1 > y2) {			temp = y1;			y1 = y2 + 1;			y2 = temp;		} else			--y2;	}	/* call faster line drawing routine*/	drawcol(psd, x1, y1, y2);	GdFixCursor(psd);	return;  }  /* See if the line is either totally visible or totally invisible. If   * so, then the line drawing is easy.   */  switch (GdClipArea(psd, x1, y1, x2, y2)) {      case CLIP_VISIBLE:	/*	 * For size considerations, there's no low-level bresenham	 * line draw, so we've got to draw all non-vertical	 * and non-horizontal lines with per-point	 * clipping for the time being	psd->Line(psd, x1, y1, x2, y2, gr_foreground);	GdFixCursor(psd);	return;	 */	break;      case CLIP_INVISIBLE:	return;  }  /* The line may be partially obscured. Do the draw line algorithm   * checking each point against the clipping regions.   */  xdelta = x2 - x1;  ydelta = y2 - y1;  if (xdelta < 0) xdelta = -xdelta;  if (ydelta < 0) ydelta = -ydelta;  xinc = (x2 > x1) ? 1 : -1;  yinc = (y2 > y1) ? 1 : -1;  if (GdClipPoint(psd, x1, y1))	  psd->DrawPixel(psd, x1, y1, gr_foreground);  if (xdelta >= ydelta) {	rem = xdelta / 2;	for(;;) {		if(!bDrawLastPoint && x1 == x2)			break;		x1 += xinc;		rem += ydelta;		if (rem >= xdelta) {			rem -= xdelta;			y1 += yinc;		}		if (GdClipPoint(psd, x1, y1))			psd->DrawPixel(psd, x1, y1, gr_foreground);		if(bDrawLastPoint && x1 == x2)			break;	}  } else {	rem = ydelta / 2;	for(;;) {		if(!bDrawLastPoint && y1 == y2)			break;		y1 += yinc;		rem += xdelta;		if (rem >= ydelta) {			rem -= ydelta;			x1 += xinc;		}		if (GdClipPoint(psd, x1, y1))			psd->DrawPixel(psd, x1, y1, gr_foreground);		if(bDrawLastPoint && y1 == y2)			break;	}  }  GdFixCursor(psd);}/* Draw a point in the foreground color, applying clipping if necessary*//*static*/ voiddrawpoint(PSD psd, MWCOORD x, MWCOORD y){	if (GdClipPoint(psd, x, y))		psd->DrawPixel(psd, x, y, gr_foreground);}/* Draw a horizontal line from x1 to and including x2 in the * foreground color, applying clipping if necessary. *//*static*/ voiddrawrow(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y){  MWCOORD temp;  /* reverse endpoints if necessary*/  if (x1 > x2) {	temp = x1;	x1 = x2;	x2 = temp;  }  /* clip to physical device*/  if (x1 < 0)	  x1 = 0;  if (x2 >= psd->xvirtres)	  x2 = psd->xvirtres - 1;  /* check cursor intersect once for whole line*/  GdCheckCursor(psd, x1, y, x2, y);  while (x1 <= x2) {	if (GdClipPoint(psd, x1, y)) {		temp = MWMIN(clipmaxx, x2);		psd->DrawHorzLine(psd, x1, temp, y, gr_foreground);	} else		temp = MWMIN(clipmaxx, x2);	x1 = temp + 1;  }}/* Draw a vertical line from y1 to and including y2 in the * foreground color, applying clipping if necessary. */static voiddrawcol(PSD psd, MWCOORD x,MWCOORD y1,MWCOORD y2){  MWCOORD temp;  /* reverse endpoints if necessary*/  if (y1 > y2) {	temp = y1;	y1 = y2;	y2 = temp;  }  /* clip to physical device*/  if (y1 < 0)	  y1 = 0;  if (y2 >= psd->yvirtres)	  y2 = psd->yvirtres - 1;  /* check cursor intersect once for whole line*/  GdCheckCursor(psd, x, y1, x, y2);  while (y1 <= y2) {	if (GdClipPoint(psd, x, y1)) {		temp = MWMIN(clipmaxy, y2);		psd->DrawVertLine(psd, x, y1, temp, gr_foreground);	} else		temp = MWMIN(clipmaxy, y2);	y1 = temp + 1;  }}/* Draw a rectangle in the foreground color, applying clipping if necessary. * This is careful to not draw points multiple times in case the rectangle * is being drawn using XOR. */voidGdRect(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height){  MWCOORD maxx;  MWCOORD maxy;  if (width <= 0 || height <= 0)	  return;  maxx = x + width - 1;  maxy = y + height - 1;  drawrow(psd, x, maxx, y);  if (height > 1)	  drawrow(psd, x, maxx, maxy);  if (height < 3)	  return;  y++;  maxy--;  drawcol(psd, x, y, maxy);  if (width > 1)	  drawcol(psd, maxx, y, maxy);  GdFixCursor(psd);}/* Draw a filled in rectangle in the foreground color, applying * clipping if necessary. */voidGdFillRect(PSD psd, MWCOORD x1, MWCOORD y1, MWCOORD width, MWCOORD height){  MWCOORD x2 = x1+width-1;  MWCOORD y2 = y1+height-1;  if (width <= 0 || height <= 0)	  return;  /* See if the rectangle is either totally visible or totally   * invisible. If so, then the rectangle drawing is easy.   */  switch (GdClipArea(psd, x1, y1, x2, y2)) {      case CLIP_VISIBLE:	psd->FillRect(psd, x1, y1, x2, y2, gr_foreground);	GdFixCursor(psd);	return;      case CLIP_INVISIBLE:	return;  }  /* The rectangle may be partially obstructed. So do it line by line. */  while (y1 <= y2)	  drawrow(psd, x1, x2, y1++);  GdFixCursor(psd);}/* * Draw a rectangular area using the current clipping region and the * specified bit map.  This differs from rectangle drawing in that the * rectangle is drawn using the foreground color and possibly the background * color as determined by the bit map.  Each row of bits is aligned to the * next bitmap word boundary (so there is padding at the end of the row). * The background bit values are only written if the gr_usebg flag * is set. */voidGdBitmap(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,	MWIMAGEBITS *imagebits){  MWCOORD minx;  MWCOORD maxx;  MWPIXELVAL savecolor;		/* saved foreground color */  MWIMAGEBITS bitvalue = 0;	/* bitmap word value */  int bitcount;			/* number of bits left in bitmap word */  switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {      case CLIP_VISIBLE:	/*	 * For size considerations, there's no low-level bitmap	 * draw so we've got to draw everything with per-point	 * clipping for the time being.	if (gr_usebg)		psd->FillRect(psd, x, y, x + width - 1, y + height - 1,			gr_background);	psd->DrawBitmap(psd, x, y, width, height, imagebits, gr_foreground);	return;	*/	break;      case CLIP_INVISIBLE:	return;  }  /* The rectangle is partially visible, so must do clipping. First   * fill a rectangle in the background color if necessary.   */  if (gr_usebg) {	savecolor = gr_foreground;	gr_foreground = gr_background;	/* note: change to fillrect*/	GdFillRect(psd, x, y, width, height);	gr_foreground = savecolor;  }  minx = x;  maxx = x + width - 1;  bitcount = 0;  while (height > 0) {	if (bitcount <= 0) {		bitcount = MWIMAGE_BITSPERIMAGE;		bitvalue = *imagebits++;	}	if (MWIMAGE_TESTBIT(bitvalue) && GdClipPoint(psd, x, y))		psd->DrawPixel(psd, x, y, gr_foreground);	bitvalue = MWIMAGE_SHIFTBIT(bitvalue);	bitcount--;	if (x++ == maxx) {		x = minx;		y++;		height--;		bitcount = 0;	}  }  GdFixCursor(psd);}/* * Return true if color is in palette */MWBOOLGdColorInPalette(MWCOLORVAL cr,MWPALENTRY *palette,int palsize){	int	i;	for(i=0; i<palsize; ++i)		if(GETPALENTRY(palette, i) == cr)			return TRUE;	return FALSE;}/* * Create a MWPIXELVAL conversion table between the passed palette * and the in-use palette.  The system palette is loaded/merged according * to fLoadType. */voidGdMakePaletteConversionTable(PSD psd,MWPALENTRY *palette,int palsize,	MWPIXELVAL *convtable,int fLoadType){	int		i;	MWCOLORVAL	cr;	int		newsize, nextentry;	MWPALENTRY	newpal[256];	/*	 * Check for load palette completely, or add colors	 * from passed palette to system palette until full.	 */#if 0	if(psd->pixtype == MWPF_PALETTE) {	    switch(fLoadType) {	    case LOADPALETTE:		/* Load palette from beginning with image's palette.		 * First palette entries are Microwindows colors		 * and not changed.		 */		GdSetPalette(psd, gr_firstuserpalentry, palsize, palette);		break;	    case MERGEPALETTE:		/* get system palette*/		for(i=0; i<(int)psd->ncolors; ++i)			newpal[i] = gr_palette[i];		/* merge passed palette into system palette*/		newsize = 0;		nextentry = gr_nextpalentry;		/* if color missing and there's room, add it*/		for(i=0; i<palsize && nextentry < (int)psd->ncolors; ++i) {			cr = GETPALENTRY(palette, i);			if(!GdColorInPalette(cr, newpal, nextentry)) {				newpal[nextentry++] = palette[i];				++newsize;			}		}		/* set the new palette if any color was added*/		if(newsize) {			GdSetPalette(psd, gr_nextpalentry, newsize,				&newpal[gr_nextpalentry]);			gr_nextpalentry += newsize;		}		break;	    }	}	/*	 * Build conversion table from inuse system palette and	 * passed palette.  This will load RGB values directly	 * if running truecolor, otherwise it will find the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -