继续改进代码,增加了一些绘制扇形之类的函数。
示例代码:
/** @file
EasyX UEFI 图形库演示程序(阶段 P0–P4)。
先绘制静态场景(线/矩形/圆/椭圆/文字/图像),然后进入
键盘交互:方向键移动“画笔”绘线,空格切换颜色,ESC 退出。
本演示不依赖鼠标。
**/
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h>
#include "easyx.h"
/**
程序入口。
**/
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
INT32 W;
INT32 H;
INT32 PenX;
INT32 PenY;
IMAGE Sprite = { 0, 0, NULL }; // 使用前必须清零
IMAGE Grabbed = { 0, 0, NULL }; // getimage 会读取 Buffer 判断是否需释放
ExMessage Msg;
BOOLEAN Running;
UINTN ColorIndex;
CHAR8 StatusBuf[96];
CONST COLORREF Palette[] = {
LIGHTRED, LIGHTGREEN, LIGHTCYAN, YELLOW, LIGHTMAGENTA, WHITE
};
//
// 初始化绘图设备(跟随 GOP 最大分辨率模式)。
//
Status = initgraph (0, 0);
if (EFI_ERROR (Status)) {
Print (L"initgraph 失败: %r\n", Status);
return Status;
}
W = getwidth ();
H = getheight ();
//
// 批量绘图,减少刷新次数。
//
BeginBatchDraw ();
//
// 背景填充深蓝。
//
setbkcolor (RGB (16, 16, 48));
cleardevice ();
//
// 直线:不同颜色/线宽/线型。
//
setlinecolor (WHITE);
setlinestyle (PS_SOLID, 1);
line (20, 20, W - 20, 20);
setlinecolor (LIGHTGREEN);
setlinestyle (PS_SOLID, 3);
line (20, 40, W - 20, 60);
setlinecolor (YELLOW);
setlinestyle (PS_DASH, 1);
line (20, 80, W - 20, 80);
setlinecolor (LIGHTCYAN);
setlinestyle (PS_DOT, 1);
line (20, 100, W - 20, 100);
//
// 矩形。
//
setlinestyle (PS_SOLID, 1);
setlinecolor (LIGHTRED);
rectangle (40, 140, 200, 260);
setfillcolor (RGB (40, 120, 200));
setlinecolor (WHITE);
fillrectangle (240, 140, 400, 260);
setfillcolor (LIGHTMAGENTA);
solidrectangle (440, 140, 600, 260);
//
// 圆。
//
setlinecolor (WHITE);
circle (110, 360, 60);
setfillcolor (RGB (220, 160, 40));
setlinecolor (WHITE);
fillcircle (320, 360, 60);
setfillcolor (LIGHTGREEN);
solidcircle (520, 360, 60);
//
// 椭圆。
//
setlinecolor (LIGHTCYAN);
ellipse (40, 440, 260, 540);
setfillcolor (RGB (200, 60, 120));
setlinecolor (WHITE);
fillellipse (300, 440, 560, 540);
//
// 文字(P2):不同颜色/大小/背景模式。
//
settextcolor (WHITE);
settextstyle (16, 8);
outtextxy (620, 150, "EasyX for UEFI");
settextcolor (YELLOW);
settextstyle (24, 0); // 高 24,宽按比例
outtextxy (620, 180, "Hello, GOP!");
settextcolor (LIGHTGREEN);
settextstyle (32, 16);
setbkmode (TRANSPARENT);
outtextxy (620, 220, "0123456789");
settextcolor (BLACK);
setbkcolor (LIGHTGRAY);
setbkmode (OPAQUE);
settextstyle (16, 8);
outtextxy (620, 270, " OPAQUE text mode ");
setbkmode (TRANSPARENT);
settextcolor (LIGHTRED);
settextstyle (20, 10);
outtextxy (620, 320, "The quick brown fox");
outtextxy (620, 345, "jumps over lazy dog.");
//
// 图像(P3)。
//
// 1) 用 SetWorkingImage 把绘图重定向到内存图像,绘制一个“精灵”。
//
if (!EFI_ERROR (CreateImage (&Sprite, 80, 80))) {
SetWorkingImage (&Sprite);
setbkcolor (RGB (20, 20, 20));
cleardevice ();
setfillcolor (RGB (240, 200, 40));
solidcircle (40, 40, 34);
setfillcolor (BLACK);
solidcircle (28, 32, 5);
solidcircle (52, 32, 5);
setlinecolor (BLACK);
setlinestyle (PS_SOLID, 2);
line (24, 54, 56, 54);
SetWorkingImage (NULL); // 恢复到屏幕
// 2) 直接覆盖绘制到屏幕多个位置。
putimage (620, 400, &Sprite);
putimage (710, 400, &Sprite);
// 3) 透明贴图:跳过图像四角的深灰背景色。
putimagetrans (800, 400, &Sprite, RGB (20, 20, 20));
}
//
// 4) getimage:抓取屏幕左上角一块区域,复制到别处。
//
if (!EFI_ERROR (getimage (&Grabbed, 40, 140, 160, 120))) {
putimage (620, 500, &Grabbed);
DeleteImage (&Grabbed);
}
DeleteImage (&Sprite);
//
// 高级图形(P5):底部一条演示带(先清出干净背景)。
//
{
INT32 Y0 = H - 150;
setfillcolor (RGB (16, 16, 48));
solidrectangle (0, Y0 - 10, W - 1, Y0 + 100);
// 圆角矩形(边框 + 填充)
setlinestyle (PS_SOLID, 1);
setlinecolor (WHITE);
setfillcolor (RGB (40, 120, 200));
fillroundrect (30, Y0, 150, Y0 + 90, 40, 40);
// 扇形(吃豆人)
setfillcolor (YELLOW);
fillpie (170, Y0, 290, Y0 + 90, 35, 300);
// 圆弧
setlinecolor (LIGHTCYAN);
arc (310, Y0, 430, Y0 + 90, 0, 200);
// 多边形(三角形,边框 + 填充)
setlinecolor (WHITE);
setfillcolor (LIGHTGREEN);
{
POINT Tri[3] = {
{ 450, Y0 + 90 },
{ 510, Y0 },
{ 570, Y0 + 90 }
};
fillpolygon (Tri, 3);
}
// 折线(锯齿)
setlinecolor (LIGHTMAGENTA);
setlinestyle (PS_SOLID, 2);
{
POINT Zig[5] = {
{ 590, Y0 + 90 },
{ 610, Y0 },
{ 630, Y0 + 90 },
{ 650, Y0 },
{ 670, Y0 + 90 }
};
polyline (Zig, 5);
}
// 区域填充:先画空心矩形,再对内部 floodfill
setlinestyle (PS_SOLID, 1);
setlinecolor (WHITE);
rectangle (700, Y0, 800, Y0 + 90);
setfillcolor (RGB (220, 80, 160));
floodfill (750, Y0 + 45, RGB (16, 16, 48));
}
//
// 键盘操作提示。
//
setbkmode (TRANSPARENT);
settextcolor (WHITE);
settextstyle (16, 8);
outtextxy (20, H - 24, "Arrow keys=draw, Space=color, ESC=exit");
//
// 一次性刷新并结束批量绘图。
//
EndBatchDraw ();
//
// 键盘交互循环(P4):方向键移动画笔绘线。
//
PenX = W / 2;
PenY = H / 2;
Running = TRUE;
ColorIndex = 0;
while (Running) {
INT32 NewX;
INT32 NewY;
getmessage (&Msg, EX_KEY);
if (Msg.message != WM_KEYDOWN) {
continue;
}
NewX = PenX;
NewY = PenY;
switch (Msg.vkcode) {
case VK_LEFT: NewX -= 8; break;
case VK_RIGHT: NewX += 8; break;
case VK_UP: NewY -= 8; break;
case VK_DOWN: NewY += 8; break;
case VK_SPACE: ColorIndex++; break;
case VK_ESCAPE: Running = FALSE; break;
default: break;
}
if (!Running) {
break;
}
//
// 夹取到屏幕范围内。
//
if (NewX < 0) {
NewX = 0;
}
if (NewY < 0) {
NewY = 0;
}
if (NewX > W - 1) {
NewX = W - 1;
}
if (NewY > H - 1) {
NewY = H - 1;
}
//
// 从旧位置到新位置画一段线。
//
setlinecolor (Palette[ColorIndex % (sizeof (Palette) / sizeof (Palette[0]))]);
setlinestyle (PS_SOLID, 2);
line (PenX, PenY, NewX, NewY);
PenX = NewX;
PenY = NewY;
//
// 底部显示当前画笔位置与按键(先用背景色清除旧文字)。
//
setfillcolor (RGB (16, 16, 48));
solidrectangle (20, H - 48, 420, H - 28);
AsciiSPrint (
StatusBuf,
sizeof (StatusBuf),
"Pen: (%d, %d) vkcode=0x%02x",
PenX,
PenY,
Msg.vkcode
);
setbkmode (TRANSPARENT);
settextcolor (LIGHTCYAN);
settextstyle (16, 8);
outtextxy (20, H - 46, StatusBuf);
}
closegraph ();
//
// 恢复文本控制台。
//
gST->ConOut->ClearScreen (gST->ConOut);
Print (L"EasyX UEFI Demo 结束。分辨率: %d x %d\n", W, H);
return EFI_SUCCESS;
}
代码运行结果(新增的在最下面)

完整代码和编译后的 EFI下载: