510 lines
11 KiB
C
510 lines
11 KiB
C
/** @file
|
|
SnapScree driver for capature screen image to BMP file.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2020, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
#include <Base.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Protocol/SimpleTextOut.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include "SnapScreen.h"
|
|
#include "SnapWin.h"
|
|
#include "SnapConOut.h"
|
|
#include "SnapTextOutHook.h"
|
|
|
|
#define CHAR_SIZE sizeof(CHAR16)
|
|
#define ATTR_SIZE sizeof(UINT8)
|
|
|
|
#define MAX_PRINT_BUFFER 256
|
|
|
|
//#define CONOUT gST->ConOut
|
|
|
|
CHAR16 mBlankLine[MAX_PRINT_BUFFER] = {
|
|
/*00*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*10*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*20*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*30*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*40*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*50*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*60*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*70*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*80*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*90*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*A0*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*B0*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*C0*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*D0*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*E0*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
/*F0*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
|
|
};
|
|
|
|
|
|
|
|
VOID
|
|
TWinClearArea (
|
|
IN TWINDOW *Win,
|
|
IN RECT *Rect,
|
|
IN UINTN Attrib
|
|
)
|
|
{
|
|
UINTN Row;
|
|
|
|
mBlankLine[Rect->Width] = 0;
|
|
|
|
// set console attribute
|
|
ScoSetAttribute (Attrib);
|
|
|
|
// clean the box Row
|
|
for (Row = 0; Row < Rect->Height; Row++) {
|
|
TWinTextOut ( Win, (INT16)Rect->X, (INT16) (Rect->Y+Row), mBlankLine);
|
|
}
|
|
|
|
mBlankLine[Rect->Width] = 0x20;
|
|
|
|
}
|
|
|
|
VOID
|
|
TWinDrawBorder (
|
|
TWINDOW *Win,
|
|
UINTN Attrib
|
|
)
|
|
{
|
|
RECT *Rect;
|
|
UINTN BoxTop, BoxBottom, BoxLeft, BoxRight;
|
|
|
|
Rect = &Win->Area;
|
|
|
|
BoxLeft = Rect->X;
|
|
BoxRight = Rect->X + Rect->Width - 1;
|
|
BoxTop = Rect->Y;
|
|
BoxBottom = Rect->Y + Rect->Height - 1;
|
|
|
|
// set console attribute
|
|
ScoSetAttribute (Attrib);
|
|
|
|
//2 Draw Horizontal line
|
|
DrawHorizontalLine( BoxLeft+1, BoxTop, Rect->Width - 2);
|
|
DrawHorizontalLine( BoxLeft+1, BoxBottom, Rect->Width - 2);
|
|
|
|
//2 Draw Vertical line
|
|
DrawVerticalLine ( BoxLeft, BoxTop+1, Rect->Height - 2);
|
|
DrawVerticalLine ( BoxRight, BoxTop+1, Rect->Height - 2);
|
|
|
|
//2 Draw box coner
|
|
ScoPrintCharAt (BoxLeft, BoxTop, BOXDRAW_DOWN_RIGHT);
|
|
ScoPrintCharAt (BoxRight, BoxTop, BOXDRAW_DOWN_LEFT);
|
|
ScoPrintCharAt (BoxLeft, BoxBottom, BOXDRAW_UP_RIGHT);
|
|
ScoPrintCharAt (BoxRight, BoxBottom, BOXDRAW_UP_LEFT);
|
|
|
|
}
|
|
|
|
VOID
|
|
TWinGetCursor (
|
|
TWINDOW *Win,
|
|
UINT16 *CursorX,
|
|
UINT16 *CursorY
|
|
)
|
|
{
|
|
*CursorX = Win->CursorX;
|
|
*CursorY = Win->CursorY;
|
|
}
|
|
|
|
VOID
|
|
TWinSetCursor (
|
|
TWINDOW *Win,
|
|
UINT16 CursorX,
|
|
UINT16 CursorY
|
|
)
|
|
{
|
|
|
|
UINTN ScrX;
|
|
UINTN ScrY;
|
|
|
|
Win->CursorX = CursorX;
|
|
Win->CursorY = CursorY;
|
|
|
|
ScrX = CursorX + Win->ClientArea.X;
|
|
ScrY = CursorY + Win->ClientArea.Y;
|
|
|
|
ScoSetCursorPosition (ScrX, ScrY);
|
|
|
|
}
|
|
|
|
VOID
|
|
TWinSetAttribue (
|
|
TWINDOW *Win,
|
|
UINTN Attribute
|
|
)
|
|
{
|
|
ScoSetAttribute (Attribute);
|
|
}
|
|
|
|
EFI_STATUS
|
|
TWinShow (
|
|
TWINDOW *Win
|
|
)
|
|
{
|
|
|
|
UINTN Attrib;
|
|
RECT Rect;
|
|
UINTN TitleLen;
|
|
UINTN ScrX;
|
|
UINTN ScrY;
|
|
|
|
Win->IsShow = TRUE;
|
|
|
|
TextGetBackground (Win->Area.X, Win->Area.Y, Win->Area.Width, Win->Area.Height, Win->TextBuffer);
|
|
GraphicsGetBackground (Win->Area.X, Win->Area.Y, Win->Area.Width, Win->Area.Height, Win->GraphicBuffer);
|
|
Attrib = EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLUE);
|
|
|
|
if (Win->Border) {
|
|
TWinDrawBorder (Win, Attrib);
|
|
}
|
|
|
|
//
|
|
// Draw Title
|
|
//
|
|
|
|
if (Win->Title) {
|
|
// clear title bar
|
|
mBlankLine[Win->ClientArea.Width] = 0;
|
|
ScrX = Win->Area.X + 1;
|
|
ScrY = Win->Area.Y + 1;
|
|
ScoSetCursorPosition (ScrX, ScrY);
|
|
ScoOutputString (mBlankLine);
|
|
mBlankLine[Win->ClientArea.Width] = 0x20;
|
|
|
|
// print title string
|
|
TitleLen = StrLen (Win->Title);
|
|
ScrX = Win->Area.X + Win->Area.Width / 2 - TitleLen /2;
|
|
ScrY = Win->Area.Y + 1;
|
|
ScoSetCursorPosition (ScrX, ScrY);
|
|
ScoOutputString (Win->Title);
|
|
|
|
// draw title horizontal line
|
|
ScrX = Win->Area.X + 1;
|
|
ScrY = Win->Area.Y + 2;
|
|
DrawHorizontalLine (ScrX, ScrY, Win->Area.Width -2);
|
|
}
|
|
|
|
Rect.X = 0;
|
|
Rect.Y = 0;
|
|
Rect.Width = Win->ClientArea.Width;
|
|
Rect.Height = Win->ClientArea.Height;
|
|
|
|
TWinClearArea (Win, &Rect, Attrib);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
TWinScrollUp (
|
|
TWINDOW *Win,
|
|
UINT16 Lines
|
|
)
|
|
{
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
TWinPrintChar (
|
|
TWINDOW *Win,
|
|
CHAR16 Ch
|
|
)
|
|
{
|
|
|
|
UINTN ScrX;
|
|
UINTN ScrY;
|
|
|
|
switch (Ch) {
|
|
|
|
case '\n' :
|
|
Win->CursorY++;
|
|
Win->CursorX = 0;
|
|
|
|
break;
|
|
|
|
default :
|
|
ScrX = Win->CursorX + Win->ClientArea.X;
|
|
ScrY = Win->CursorY + Win->ClientArea.Y;
|
|
ScoPrintCharAt(ScrX, ScrY, Ch);
|
|
Win->CursorX++;
|
|
|
|
break;
|
|
}
|
|
|
|
if (Win->CursorX >= Win->ClientArea.Width) {
|
|
Win->CursorY++;
|
|
Win->CursorX = 0;
|
|
}
|
|
|
|
if (Win->CursorY >= Win->ClientArea.Height) {
|
|
TWinScrollUp ( Win, 1);
|
|
Win->CursorY = Win->ClientArea.Height - 1;
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
TWinPrint (
|
|
TWINDOW *Win,
|
|
CHAR16 *Format,
|
|
...
|
|
)
|
|
{
|
|
|
|
CHAR16 *Buffer;
|
|
UINTN Return;
|
|
VA_LIST Marker;
|
|
CHAR16 *cptr;
|
|
|
|
Buffer = AllocateZeroPool (MAX_PRINT_BUFFER);
|
|
|
|
if (Buffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
VA_START ( Marker, Format);
|
|
Return = UnicodeVSPrint (Buffer, MAX_PRINT_BUFFER, Format, Marker);
|
|
VA_END (Marker);
|
|
|
|
cptr = Buffer;
|
|
|
|
while (*cptr != 0) {
|
|
TWinPrintChar (Win, *cptr);
|
|
cptr++;
|
|
}
|
|
|
|
FreePool (Buffer);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
TWinPrintAt (
|
|
TWINDOW *Win,
|
|
UINT16 X,
|
|
UINT16 Y,
|
|
CHAR16 *Format,
|
|
...
|
|
)
|
|
{
|
|
|
|
CHAR16 *Buffer;
|
|
UINTN Return;
|
|
VA_LIST Marker;
|
|
CHAR16 *cptr;
|
|
|
|
Buffer = AllocateZeroPool (MAX_PRINT_BUFFER);
|
|
|
|
if (Buffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
|
|
VA_START (Marker, Format);
|
|
Return = UnicodeVSPrint (Buffer, MAX_PRINT_BUFFER, Format, Marker);
|
|
VA_END (Marker);
|
|
|
|
TWinSetCursor ( Win, X, Y);
|
|
|
|
cptr = Buffer;
|
|
|
|
while (*cptr != 0) {
|
|
TWinPrintChar (Win, *cptr);
|
|
cptr++;
|
|
}
|
|
|
|
FreePool (Buffer);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
TWinClearLine (
|
|
TWINDOW *Win,
|
|
UINT16 LineNumber
|
|
)
|
|
{
|
|
|
|
TWinSetCursor( Win, 0, LineNumber);
|
|
|
|
mBlankLine[Win->ClientArea.Width] = 0;
|
|
|
|
ScoOutputString (mBlankLine);
|
|
|
|
mBlankLine[Win->ClientArea.Width] = 0x20;
|
|
|
|
}
|
|
|
|
VOID
|
|
TWinTextOut (
|
|
TWINDOW *Win,
|
|
INT16 X,
|
|
INT16 Y,
|
|
CHAR16 *Str
|
|
)
|
|
{
|
|
|
|
CHAR16 *Cptr;
|
|
UINTN StrLength;
|
|
|
|
StrLength = StrLen(Str);
|
|
Cptr = Str;
|
|
|
|
if(X == TEXTOUT_CENTER)
|
|
X = (INT16)(Win->ClientArea.Width / 2) - (INT16)(StrLength / 2);
|
|
|
|
if (Y == TEXTOUT_CENTER)
|
|
Y = Win->ClientArea.Height / 2;
|
|
|
|
if ( Y < 0 || Y >= Win->ClientArea.Height || X >= Win->ClientArea.Width)
|
|
return;
|
|
|
|
if (X < 0) {
|
|
if ((StrLength + X) <= 0)
|
|
return;
|
|
|
|
Cptr = Str + (-X);
|
|
StrLength = StrLength - (-X);
|
|
X = 0;
|
|
}
|
|
|
|
if (X + StrLength > Win->ClientArea.Width) {
|
|
Cptr[Win->ClientArea.Width - X] = 0;
|
|
}
|
|
|
|
TWinSetCursor ( Win, (UINT16)X, (UINT16)Y);
|
|
|
|
ScoOutputString (Cptr);
|
|
|
|
}
|
|
|
|
EFI_STATUS
|
|
TWinDestroy (
|
|
TWINDOW *Win
|
|
)
|
|
{
|
|
|
|
if (Win->IsShow == TRUE) {
|
|
TextPutBackground(Win->Area.X, Win->Area.Y, Win->Area.Width, Win->Area.Height, Win->TextBuffer);
|
|
GraphicsPutBackground(Win->Area.X, Win->Area.Y, Win->Area.Width, Win->Area.Height, Win->GraphicBuffer);
|
|
}
|
|
FreePool(Win);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
TWinCreate (
|
|
INT16 X,
|
|
INT16 Y,
|
|
UINT16 CWidth,
|
|
UINT16 CHeight,
|
|
BOOLEAN Border,
|
|
CHAR16 *Title,
|
|
TWINDOW **AWin
|
|
)
|
|
{
|
|
UINTN Size;
|
|
TWINDOW *Win;
|
|
UINT8 *MemPtr;
|
|
UINTN Columns;
|
|
UINTN Rows;
|
|
RECT ClientArea;
|
|
UINT16 Width;
|
|
UINT16 Height;
|
|
UINTN TitleSize = 0;
|
|
UINTN TextBufferSize;
|
|
UINTN GraphicBufferSize;
|
|
UINT16 GraphicHeight;
|
|
|
|
if (CWidth == 0 || CHeight == 0 || CWidth >= WIN_MAX_WIDTH || CHeight >= WIN_MAX_HEIGHT)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
Width = CWidth;
|
|
Height = CHeight;
|
|
|
|
if (Border == TRUE) {
|
|
Width = CWidth + 2;
|
|
Height = CHeight + 2;
|
|
}
|
|
|
|
if (Title != NULL) {
|
|
Height = Height + 2;
|
|
}
|
|
|
|
ScoQueryMode (&Columns, &Rows);
|
|
|
|
if (X == WIN_SCR_CENTER) {
|
|
X = (INT16)(Columns / 2) - (INT16)(Width /2);
|
|
}
|
|
|
|
if (Y == WIN_SCR_CENTER) {
|
|
Y = (INT16)(Rows / 2) - (INT16)(Height /2);
|
|
}
|
|
|
|
if (Border == TRUE) {
|
|
ClientArea.X = X + 1;
|
|
ClientArea.Y = Y + 1;
|
|
}
|
|
else {
|
|
ClientArea.X = X;
|
|
ClientArea.Y = Y;
|
|
}
|
|
|
|
if (Title != NULL) {
|
|
ClientArea.Y = ClientArea.Y + 2;
|
|
}
|
|
|
|
ClientArea.Width = CWidth;
|
|
ClientArea.Height = CHeight;
|
|
|
|
if (Title != NULL)
|
|
TitleSize = StrSize (Title);
|
|
|
|
TextBufferSize = Width * Height * (CHAR_SIZE + ATTR_SIZE);
|
|
GraphicHeight = ((Height * 192)/190) + 1;
|
|
GraphicBufferSize = (Width * GLYPH_WIDTH) * (GraphicHeight * GLYPH_HEIGHT) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
|
Size = sizeof(TWINDOW) + TitleSize + TextBufferSize + GraphicBufferSize;
|
|
|
|
MemPtr = AllocateZeroPool(Size);
|
|
|
|
if (MemPtr == NULL) {
|
|
DEBUG ((EFI_D_ERROR, "%s Allocate Memory Fail. Size=%d", __FUNCTION__, Size));
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Win = (TWINDOW *) MemPtr;
|
|
Win->Border = Border;
|
|
Win->Area.X = X;
|
|
Win->Area.Y = Y;
|
|
Win->Area.Width = Width;
|
|
Win->Area.Height = Height;
|
|
Win->ClientArea = ClientArea;
|
|
|
|
if (Title != NULL) {
|
|
Win->Title = (CHAR16 *)(MemPtr + sizeof(TWINDOW));
|
|
StrCpyS (Win->Title, TitleSize / sizeof(CHAR16), Title);
|
|
}
|
|
|
|
Win->TextBuffer = (CHAR16 *)(MemPtr + sizeof(TWINDOW) + TitleSize);
|
|
Win->GraphicBuffer = (CHAR16 *)(MemPtr + sizeof(TWINDOW) + TitleSize + TextBufferSize);
|
|
|
|
*AWin = Win;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|