📄 c_cmd_drawing.inc
字号:
//Resolve array argument
ArgV[2] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[2]));
ArgV[3] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[3]));
cCmdClearScreenIfNeeded(*(ULONG*)ArgV[4]);
//Open the file in memory map mode. return if failure.
LStatus = pMapLoader->pFunc(OPENREADLINEAR, ArgV[2], (UBYTE*)(&pImage), &DataSize);
ImageHandle = LOADER_HANDLE(LStatus);
//If error opening file, give up and write loader status back to user.
if (LOADER_ERR(LStatus) != SUCCESS || pImage == NULL)
{
*pReturnVal = (SBYTE)(LOADER_ERR_BYTE(LStatus));
return (NO_ERR);
}
//Else, start interpretting the file
else
{
// Read the ArgV params, Clear the data table.
Pt = *(IMG_PT*)ArgV[1];
gpPassedImgVars = (SLONG*)ArgV[3];
memset(gpImgData,0,sizeof(gpImgData));
// Run through the op codes.
while(!IS_ERR(DStatus))
{
// Setup to look at an opcode, make sure it looke reasonable.
if (DataSize < sizeof(IMG_OP_CORE))
{
DStatus = ERR_FILE;
break; // Too small to look at, somethings wrong.
}
OpSize = pImage->Core.OpSize + sizeof(UWORD);
if (OpSize & 0x01)
{
DStatus = ERR_FILE;
break; // Odd sizes not allowed.
}
switch(pImage->Core.OpCode)
{
case IMG_SPRITE_ID:
{
if (OpSize >= sizeof(IMG_OP_SPRITE))
cCmdSetIMGData(pImage->Sprite.DataAddr, pImage);
}
break;
case IMG_VARMAP_ID:
{
if (OpSize >= sizeof(IMG_OP_VARMAP))
cCmdSetIMGData(pImage->VarMap.DataAddr, pImage);
}
break;
case IMG_COPYBITS_ID:
{
if (OpSize >= sizeof(IMG_OP_COPYBITS))
{
IMG_OP_COPYBITS * pCB = &(pImage->CopyBits);
cCmdCopyBitMapBits(
(cCmdResolveValue(pCB->Dst.X) + Pt.X),
(cCmdResolveValue(pCB->Dst.Y) + Pt.Y),
cCmdResolveValue((pCB->Src.Pt.X)),
cCmdResolveValue((pCB->Src.Pt.Y)),
cCmdResolveValue((pCB->Src.Width)),
cCmdResolveValue((pCB->Src.Height)),
(IMG_OP_SPRITE*)cCmdGetIMGData(cCmdResolveValue(pCB->DataAddr)));
}
}
break;
case IMG_LINE_ID:
{
if (OpSize >= sizeof(IMG_OP_LINE))
{
IMG_OP_LINE * pL = &(pImage->Line);
cCmdDrawLine(
(cCmdResolveValue(pL->Pt1.X)+Pt.X),
(cCmdResolveValue(pL->Pt1.Y)+Pt.Y),
(cCmdResolveValue(pL->Pt2.X)+Pt.X),
(cCmdResolveValue(pL->Pt2.Y)+Pt.Y)
);
}
}
break;
case IMG_RECTANGLE_ID:
{
if (OpSize >= sizeof(IMG_OP_LINE))
{
IMG_OP_RECT * pL = &(pImage->Rect);
cCmdDrawRect(
(SWORD)(cCmdResolveValue(pL->Pt.X)+Pt.X),
(SWORD)(cCmdResolveValue(pL->Pt.Y)+Pt.Y),
(SWORD)(cCmdResolveValue(pL->Width)),
(SWORD)(cCmdResolveValue(pL->Height))
);
}
}
break;
case IMG_PIXEL_ID:
{
if (OpSize >= sizeof(IMG_OP_LINE))
{
cCmdSetPixel(
(cCmdResolveValue(pImage->Pixel.Pt.X) + Pt.X),
(cCmdResolveValue(pImage->Pixel.Pt.Y) + Pt.Y),
TRUE);
}
}
break;
case IMG_NUMBOX_ID:
{
if (OpSize >= sizeof(IMG_OP_NUMBOX))
{
UBYTE NumStr[20];
IMG_OP_NUMBOX * pNB = &(pImage->NumBox);
sprintf((PSZ)NumStr, "%d", cCmdResolveValue(pNB->Value));
cCmdDrawString(
NumStr,
(UBYTE) (cCmdResolveValue(pNB->Pt.X) + Pt.X),
(UBYTE) (cCmdResolveValue(pNB->Pt.Y) + Pt.Y));
}
}
break;
case IMG_DESCRIPTION_ID:
{
//No-op
}
break;
default:
{
//Unrecognized opcode, pass an error back to the user.
DStatus = ERR_FILE;
}
break;
}
DataSize -= OpSize;
pImage = (IMG_OP_UNION*) ((UBYTE*)pImage + OpSize);
}
pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
}
// Set return value, close file and return
*pReturnVal = DStatus;
pMapLoader->pFunc(CLOSE, &ImageHandle, NULL, NULL);
return (NO_ERR);
}
//-----------------------------------------------------------------
// cCmdDrawLine - draw a line. All clipping is done by the set pixel function.
void cCmdDrawLine(
SLONG x1,
SLONG y1,
SLONG x2,
SLONG y2)
{
SLONG d,x,y,ax,ay,sx,sy,dx,dy;
// Initialize variables
dx = x2-x1; ax = ABS(dx)<<1; sx = SGN(dx);
dy = y2-y1; ay = ABS(dy)<<1; sy = SGN(dy);
x = x1;
y = y1;
if (ax>ay)
{ /* x dominant */
d = ay-(ax>>1);
for (;;)
{
cCmdSetPixel(x, y, TRUE);
if (x==x2)
return;
if (d>=0)
{
y += sy;
d -= ax;
}
x += sx;
d += ay;
}
}
else
{ /* y dominant */
d = ax-(ay>>1);
for (;;)
{
cCmdSetPixel(x, y, TRUE);
if (y==y2)
return;
if (d>=0)
{
x += sx;
d -= ay;
}
y += sy;
d += ax;
}
}
}
//-----------------------------------------------------------------
// cCmdDrawLine - draw a line. All clipping is done by the set pixel function.
void cCmdDrawRect(
SLONG left,
SLONG bottom,
SLONG width,
SLONG height)
{
SLONG right = left + width;
SLONG top = bottom + height;
// Draw the four line segments
cCmdDrawLine(left, top, right, top);
cCmdDrawLine(right, top, right, bottom);
cCmdDrawLine(right, bottom, left, bottom);
cCmdDrawLine(left, bottom, left, top);
}
#ifndef DISPLAY_REALWIDTH
#define DISPLAY_REALWIDTH DISPLAY_WIDTH
#endif
//-----------------------------------------------------------------
//cCmdCopyBitMapBits
void cCmdCopyBitMapBits(
SLONG dst_x, // left pixel on LCD
SLONG dst_y, // bottom pixel on LCD
SLONG src_x, // starting pixel x coordinate from source map
SLONG src_y, // starting pixel y coordinate from source map
SLONG src_width, // width in pixels to the right (negative implies to the left)
SLONG src_height, // height in pixels down (negative implies down)
IMG_OP_SPRITE * pSprite)
{
SLONG dy; // Location in the destination pixmap , the screen that is
SLONG sx;
SLONG sy; // Location in the source pixmap.
SLONG trim, last_x, last_y, rowbytes;
UBYTE *pSrcByte;
UBYTE *pDstBytes;
UBYTE *pDstByte, *pFirstDstByte;
UBYTE *pLastDstByte;
UBYTE bit_y, not_bit_y;
UBYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
// Data in the image file is row major 8 pixels per byte.top row first.
// src and dst coordinates treat the bottom left most pixel as (0,0)
if (!pSprite || pSprite->OpCode!=IMG_SPRITE_ID)
return;
pDstBytes = DISP_BUFFER_P;
// Clip the edges. Modify the source and width as well.
if (dst_x < 0) { // bounds check start of x
trim = (0 - dst_x);
dst_x = 0;
src_x += trim;
src_width -= trim;
}
last_x = dst_x + src_width;
if (last_x > DISPLAY_WIDTH) // bound check end of x
last_x = DISPLAY_WIDTH;
if (dst_y < 0) { // bound check start of y
trim = (0 - dst_y);
dst_y = 0;
src_y += trim; // fix up source as well since we are clipping the start of the loop
src_height -= trim;
}
last_y = dst_y + src_height;
if (last_y > DISPLAY_HEIGHT) // bound check end of y
last_y = DISPLAY_HEIGHT;
// Convert the 0,0 bottom left origin to the top left 0,0 used by the actual
// buffer
last_y = TRANSLATE_Y(last_y);
dst_y = TRANSLATE_Y(dst_y);
// The last row is the top most scan line in the LCD Buffer
// so limit if the copy would copy into memory before the buffer.
// The first row copied will be the one closest to the bottom of the LCD
// If that is off screen then limit as well and adjust the start point on the start
// Copy bits top to top moving down.
sy = src_y;
rowbytes = pSprite->RowBytes;
pSrcByte = pSprite->Bytes + ((pSprite->Rows - 1 - sy) * rowbytes);
pFirstDstByte = pDstBytes + ((dst_y >> 3) * DISPLAY_REALWIDTH) + dst_x;
for (dy = dst_y; dy > last_y; dy--)
{
sx = src_x;
bit_y = masks[7 - (dy & 0x07)];
not_bit_y = ~ bit_y;
pDstByte = pFirstDstByte;
pLastDstByte = pDstByte + (last_x - dst_x);
for (; pDstByte < pLastDstByte; pDstByte++)
{
if ( *(pSrcByte + (sx >> 3)) & masks[sx & 0x07] ){
*pDstByte |= bit_y;
} else {
*pDstByte &= not_bit_y;
}
sx ++;
}
pSrcByte -= rowbytes;
sy ++;
if ((dy & 0x07) == 0) // bump back the scan line start point at rollover
pFirstDstByte -= DISPLAY_REALWIDTH;
}
}
//-----------------------------------------------------------------
// cCmdSetPixel - Set or clear a pixel based on Val
void cCmdSetPixel(SLONG X, SLONG Y, ULONG Val)
{
Y = TRANSLATE_Y(Y);
pMapDisplay->pFunc(DISPLAY_PIXEL, (UBYTE)Val, (UBYTE)X, (UBYTE)Y, 0, 0);
}
//-----------------------------------------------------------------
//cCmdWrapSetScreenMode
//ArgV[0]: (Function return) Status code, SBYTE
//ArgV[1]: ScreenMode ULONG
NXT_STATUS cCmdWrapSetScreenMode(UBYTE * ArgV[])
{
ULONG ScreenMode = (ULONG)(*ArgV[1]);
if (ScreenMode == RESTORE_NXT_SCREEN) {
cCmdRestoreDefaultScreen();
}
// Set return value
*(SBYTE*)(ArgV[0]) = NO_ERR;
return NO_ERR;
}
//------------------------------------------------------------------
// cCmdClearScreenIfNeeded - Clear entire sceen buffer if explicitly requested or implicitly required.
void cCmdClearScreenIfNeeded(ULONG DrawOptions)
{
//If we are the first drawing command, clear the screen and record that we've done so
if (VarsCmd.DirtyDisplay == FALSE)
{
VarsCmd.DirtyDisplay = TRUE;
pMapUi->Flags &= ~UI_ENABLE_STATUS_UPDATE;
//Override DrawOptions because we have to clear anyway
DrawOptions = DRAW_OPT_CLEAR_WHOLE_SCREEN;
}
if (DRAW_OPT_CLEAR_MODE(DrawOptions))
{
pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0);
//Clear UpdateMask to kill any pending updates
pMapDisplay->UpdateMask = 0;
}
return;
}
//------------------------------------------------------------------
// cCmdDrawString - Draw string to display buffer
// Properly uses 'Normal' display buffer to avoid conflicts with popup buffer
// Clips text at bottom and right hand edges of the screen buffer
//!!! Function copied and modified from cDisplayString
void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y)
{
UBYTE *pSource;
UBYTE *pDestination;
FONT *pFont;
ULONG FontWidth;
ULONG Items;
ULONG Item;
ULONG Line;
//Get current font information
pFont = pMapDisplay->pFont;
Items = pFont->ItemsX * pFont->ItemsY;
//Invert Y coordinate to match display buffer
Y = TRANSLATE_Y(Y);
Line = (Y & 0xF8) / 8;
//If text line is out of bounds, do nothing.
if (Line >= TEXTLINES)
return;
//Calculate pointer to first byte of drawing destination
pDestination = &(DISP_BUFFER_P[Line * DISPLAY_WIDTH + X]);
while (*pString)
{
FontWidth = pFont->ItemPixelsX;
//Calculate X coordinate of the right edge of this character.
//If it will extend past the right edge, clip the string.
X += FontWidth;
if (X >= DISPLAY_WIDTH)
break;
//If Item is defined by the font, display it. Else, ignore it.
Item = *pString - ' ';
if (Item < Items)
{
pSource = (UBYTE*)&(pFont->Data[Item * FontWidth]);
while (FontWidth--)
{
*pDestination = *pSource;
pDestination++;
pSource++;
}
}
pString++;
}
}
//------------------------------------------------------------------
// cCmdRestoreDefaultScreen - Restore to Default 'Running' screen
void cCmdRestoreDefaultScreen(void)
{
//If this program has taken over the display, reset it for the UI
if (VarsCmd.DirtyDisplay == TRUE)
{
VarsCmd.DirtyDisplay = FALSE;
pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0);
pMapDisplay->UpdateMask = SCREEN_BIT(SCREEN_BACKGROUND);
pMapUi->Flags |= UI_ENABLE_STATUS_UPDATE | UI_REDRAW_STATUS;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -