📄 graphics.cpp
字号:
}
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 + -