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

📄 graphics.cpp

📁 由一个古老的BASIC解释器改进而成, 保留了ANSI C固有的艺术美感.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		}
		actualmode= mode;
		return;
	}

	#endif

	if (mode != actualmode || mode == user_mode)
	{
		if (window_created)
			destroy_window ();
		if (mode != text_mode)
			create_window (width, height);
	}
	else
	{
		if (mode != text_mode)
		{
                        graphics::setcolor (0);
                        graphics::setdrawmode (0);
			reinit_pixmap ();
			reinit_window ();
		}

		#ifdef _Windows
		else
			if (actualmode != text_mode)
			// REVISAR: ESTO NO PARECE VALIDO.
				destroy_thread ();
		#endif
	}

        actualmode= mode;

	if (mode != text_mode)
	{
                setmaxtext ();
		tcol= trow= 0;
		lastx= lasty= 0;
		#if defined (BLASSIC_USE_WINDOWS) || defined (BLASSIC_USE_X)
		//pforeground= & xcBlack;
		//pbackground= & xcWhite;
		pforeground= default_foreground;
		pbackground= default_background;
		#endif
		recreate_windows ();
	}
}

} // namespace

void graphics::cls ()
{
	requiregraphics ();

	#ifdef BLASSIC_USE_SVGALIB

	if (svgalib)
	{
		// PENDIENTE
		return;
	}

	#endif

        tcol= trow= 0;
	//reinit_pixmap ();

	#ifdef BLASSIC_USE_WINDOWS
	RECT r= { 0, 0, screenwidth, screenheight };
        LOGPEN logpen;
        GetObject (* pbackground, sizeof (LOGPEN), & logpen);
        HBRUSH hbrush= CreateSolidBrush (logpen.lopnColor);
	if (! fSynchro)
		FillRect (hdc, & r, hbrush);
        FillRect (hdcPixmap, & r, hbrush);
        DeleteObject (hbrush);
	#endif

	#ifdef BLASSIC_USE_X
	activecolor (pbackground);
	XSetFunction (display, gc, drawmode_copy);
	XSetFunction (display, gcp, drawmode_copy);
	if (! fSynchro)
		XFillRectangle (display, window, gc,
			0, 0, screenwidth, screenheight);
	XFillRectangle (display, pixmap, gcp,
		0, 0, screenwidth, screenheight);
	activecolor (pforeground);
	XSetFunction (display, gc, drawmode);
	XSetFunction (display, gcp, drawmode);
	#endif

}

void graphics::setmode (int width, int height, bool inverty)
{
	default_foreground= & xcBlack;
	default_background= & xcWhite;
	::setmode (width, height, user_mode);
	if (inverty)
		activetransform= TransformInvertY;
}

void graphics::setmode (int mode)
{
	if (! inited)
		throw ErrFunctionCall;
	lastx= lasty= 0;

	int width, height;
	switch (mode) {
	case 1:
		width= 320; height= 200; break;
	case 2:
		width= 640; height= 200; break;
	case 5:
		width= 320; height= 200; break;
	case 10:
		width= 640; height= 480; break;
	case 11:
		width= 800; height= 600; break;
	default:
                width= 0; height= 0;
	}
	if (mode != 0 && width == 0)
		throw ErrFunctionCall;

	default_foreground= & xcBlack;
	default_background= & xcWhite;
	::setmode (width, height, mode);
}

void graphics::setmode (const std::string & mode)
{
	if (mode == "spectrum")
	{
		// Revisar colores.
		default_foreground= & xcBlack;
		default_background= & xcWhite;
		::setmode (256, 176, user_mode);
		activetransform= TransformInvertY;
	}
	#if 0
	// Pendiente de pensarlo mejor.
	else if (mode == "cpc0")
	{
		::setmode (160, 400, user_mode);
		activetransform= TransformInvertY;
	}
	else if (mode == "cpc1")
	{
		::setmode (320, 400, user_mode);
		activetransform= TransformInvertY;
	}
	#endif
	else if (mode == "cpc2")
	{
		default_foreground= & xcYellow;
		default_background= & xcBlue;
		::setmode (640, 400, user_mode);
		activetransform= TransformInvertY;
	}
	else
		throw ErrFunctionCall;
}

bool graphics::ingraphicsmode ()
{
        return actualmode != text_mode;
}

namespace {

inline pcolor mapcolor (int color)
{
	switch (color)
	{
	case  0: return & xcBlack;
	case  1: return & xcBlue;
	case  2: return & xcGreen;
	case  3: return & xcCyan;
	case  4: return & xcRed;
	case  5: return & xcMagenta;
	case  6: return & xcBrown;
	case  7: return & xcLightGrey;
	case  8: return & xcDarkGrey;
	case  9: return & xcLightBlue;
	case 10: return & xcLightGreen;
	case 11: return & xcLightCyan;
	case 12: return & xcLightRed;
	case 13: return & xcLightMagenta;
	case 14: return & xcYellow;
	case 15: return & xcWhite;
	default: return & xcBlack;
	}
}

} // namespace

void graphics::setcolor (int color)
{
	//if (! inited) return;

        #ifdef BLASSIC_USE_SVGALIB

	if (svgalib) {
		vga_setcolor (color);
		return;
	}

	#endif

	pcolor pxc= mapcolor (color);

	#if 0

	#ifdef BLASSIC_USE_X
	XSetForeground (display, gcp, pxc->pixel);
	XSetForeground (display, gc, pxc->pixel);
	#endif

	#ifdef BLASSIC_USE_WINDOWS
	//HDC hdc= GetDC (window);
	SelectObject (hdc, * pxc);
	SelectObject (hdcPixmap, *pxc);
	//ReleaseDC (window, hdc);
	#endif

	#else

	activecolor (pxc);

	#endif

	#if defined (BLASSIC_USE_WINDOWS) || defined (BLASSIC_USE_X)
	pforeground= pxc;
	#endif
}

void graphics::setbackground (int color)
{
	//if (! inited) return;
	pcolor pxc= mapcolor (color);
	pbackground= pxc;
}

void graphics::settransparent (int transpmode)
{
	if (! inited) return;
	opaquemode= ! (transpmode & 1);
}

void graphics::setdrawmode (int mode)
{
	if (! inited) return;

	// Draw modes:
	// 0: normal copy mode.
	// 1: XOR
	// 2: AND
	// 3: OR
	// 0 to 3 are Amstrad CPC modes.
	// 4: INVERT, NOT.
	static int modes []= { drawmode_copy, drawmode_xor,
		drawmode_and, drawmode_or, drawmode_invert };

        if (mode < 0 || size_t (mode) >= util::dim_array (modes) )
                return;
        drawmode= modes [mode];

        #ifdef BLASSIC_USE_X
	XSetFunction (display, gc, drawmode);
	XSetFunction (display, gcp, drawmode);
        #endif

        #ifdef BLASSIC_USE_WINDOWS
        //HDC hdc= GetDC (window);
        SetROP2 (hdc, drawmode);
        //ReleaseDC (window, hdc);
        SetROP2 (hdcPixmap, drawmode);
        #endif
}

namespace {

void do_line_unmasked (int x, int y)
{
	int prevx= lastx, prevy= lasty;
	lastx= x; lasty= y;

	transform_y (y); transform_y (prevy);

	activecolor (pforeground);

	#ifdef BLASSIC_USE_SVGALIB
	if (svgalib)
	{
		vga_drawline (prevx, prevy, x, y);
		return;
	}
	#endif

	#ifdef BLASSIC_USE_X
	if (! fSynchro)
		XDrawLine (display, window, gc, prevx, prevy, x, y);
	XDrawLine (display, pixmap, gcp, prevx, prevy, x, y);
	XFlush (display);
	#endif

        #ifdef BLASSIC_USE_WINDOWS
        //HDC hdc= GetDC (window);

        //SetROP2 (hdc, drawmode);
	if (! fSynchro)
	{
		MoveToEx (hdc, prevx, prevy, 0);
		LineTo (hdc, x, y);
	}

        //ReleaseDC (window, hdc);

        //SetROP2 (hdcPixmap, drawmode);
        MoveToEx (hdcPixmap, prevx, prevy, 0);
        LineTo (hdcPixmap, x, y);
        #endif

	//idle ();
}

const unsigned char maskvaluedefault= '\xFF';
unsigned char maskvalue= maskvaluedefault;
bool maskdrawfirst= true;
unsigned maskpos= 0;
unsigned char auxmask []= { 1, 2, 4, 8, 16, 32, 64, 128 };

inline void impl_plot_mask (int x, int y)
{
	if (maskvalue == maskvaluedefault)
		do_plot (x, y);
	else
	{
		if (maskvalue & auxmask [maskpos] )
			do_plot (x, y);
		if (++maskpos == 8) maskpos= 0;
	}
}

void do_line_mask (int x, int y)
{
	int prevx= lastx, prevy= lasty;
	lastx= x; lasty= y;

	transform_y (prevy); transform_y (y);

	activecolor (pforeground);

	int px= x - prevx;
	int py= y - prevy;
	int d1x= px < 0 ? -1 : px > 0 ? 1 : 0;
	int d1y= py < 0 ? -1 : py > 0 ? 1 : 0;
	int d2x= d1x;
	int d2y= 0;
	int m= abs (px);
	int n= abs (py);
	if (m <= n)
	{
		d2x= 0;
		d2y= d1y;
		m= abs (py);
		n= abs (px);
	}
	int s= m / 2;
	for (int i= 0; i <= m; ++i)
	{
		if (i != 0 || maskdrawfirst)
		{
			//if (maskvalue & auxmask [maskpos] )
			//	do_plot (prevx, prevy);
			//if (++maskpos == 8) maskpos= 0;
			impl_plot_mask (prevx, prevy);
		}
		s+= n;
		if (s >= m)
		{
			s-= m;
			prevx+= d1x;
			prevy+= d1y;
		}
		else
		{
			prevx+= d2x;
			prevy+= d2y;
		}
	}
}

inline void do_line (int x, int y)
{
	if (maskvalue == maskvaluedefault && maskdrawfirst)
		do_line_unmasked (x, y);
	else
		do_line_mask (x, y);
}

} // namespace

void graphics::line (int x, int y)
{
	requiregraphics ();
	do_line (x, y);
}

void graphics::liner (int x, int y)
{
	line (lastx + x, lasty + y);
}

void graphics::rectangle (Point org, Point dest)
{
	int x1= org.x;
	int y1= org.y;
	int x2= dest.x;
	int y2= dest.y;
	lastx= x2; lasty= y2;
	transform_y (y1); transform_y (y2);
	if (x1 > x2) std::swap (x1, x2);
	if (y1 > y2) std::swap (y1, y2);

        #ifdef BLASSIC_USE_WINDOWS
        Rectangle (hdcPixmap, x1, y1, x2 + 1, y2 + 1);
        if (! fSynchro)
                Rectangle (hdc, x1, y1, x2 + 1, y2 + 1);
        #endif

        #ifdef BLASSIC_USE_X
	XDrawRectangle (display, pixmap, gcp,
		x1, y1, x2 - x1, y2 - y1);
	if (! fSynchro)
		XDrawRectangle (display, window, gc,
			x1, y1, x2 - x1, y2 - y1);
	#endif
}

void graphics::rectanglefilled (Point org, Point dest)
{
	int x1= org.x;
	int y1= org.y;
	int x2= dest.x;
	int y2= dest.y;
	lastx= x2; lasty= y2;
	transform_y (y1); transform_y (y2);
	if (x1 > x2) std::swap (x1, x2);
	if (y1 > y2) std::swap (y1, y2);

        #ifdef BLASSIC_USE_WINDOWS
        RECT r = { x1, y1, x2 + 1, y2 + 1 };
	LOGPEN logpen;
	GetObject (* pforeground, sizeof (LOGPEN), & logpen);
	HBRUSH hbrush= CreateSolidBrush (logpen.lopnColor);
        FillRect (hdcPixmap, & r, hbrush);
        if (! fSynchro)
                FillRect (hdc, & r, hbrush);
        DeleteObject (hbrush);
        #endif

        #ifdef BLASSIC_USE_X
	XFillRectangle (display, pixmap, gcp,
		x1, y1, x2 - x1 + 1, y2 - y1 + 1);
	if (! fSynchro)
		XFillRectangle (display, window, gc,
			x1, y1, x2 - x1 + 1, y2 - y1 + 1);
	#endif
}

void graphics::move (int x, int y)
{
	requiregraphics ();
	lastx= x; lasty= y;
	//idle ();
}

void graphics::mover (int x, int y)
{
	requiregraphics ();
	lastx+= x; lasty+= y;
	//idle ();
}

void graphics::plot (int x, int y)
{
	requiregraphics ();
	lastx= x; lasty= y;

	transform_y (y);

	#if 0

	#ifdef BLASSIC_USE_SVGALIB

	if (svgalib) {
		vga_drawpixel (x, y);
		return;
	}

	#endif

	#ifdef BLASSIC_USE_X

	if (! fSynchro)
		XDrawPoint (display, window, gc, x, y);
	XDrawPoint (display, pixmap, gcp, x, y);

	#endif

        #ifdef BLASSIC_USE_WINDOWS

        //HDC hdc= GetDC (window);

        //SetROP2 (hdc, drawmode);
	if (! fSynchro)
	{
		MoveToEx (hdc, x, y, 0);
		LineTo (hdc, x + 1, y);
	}

        //ReleaseDC (window, hdc);

        //SetROP2 (hdcPixmap, drawmode);
        MoveToEx (hdcPixmap, x, y, 0);
        LineTo (hdcPixmap, x + 1, y);

        #endif

	#else

	activecolor (pforeground);
	do_plot (x, y);

	#endif

	//idle ();
}

void graphics::plotr (int x, int y)
{
	plot (lastx + x, lasty + y);
}

namespace {

void line_to_point (const graphics::Point & p)
{
	graphics::line (p.x, p.y);
}

} // namespace

void graphics::plot (std::vector <Point> & points)
{
	requiregraphics ();
	ASSERT (points.size () != 0);
	lastx= points [0].x;
	lasty= points [0].y;
	std::for_each (points.begin () + 1, points.end (), line_to_point);
}

//#define DEBUG_CIRCLE

#ifdef DEBUG_CIRCLE

#include <unistd.h>

namespace { inline void pausec () { usleep (100000); } }

#else

namespace { inline void pausec () { } }

⌨️ 快捷键说明

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