mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-26 12:05:36 +01:00
working mouse pointer and ximage.draw
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
This commit is contained in:
parent
c3103859b6
commit
6c592d8004
@ -54,13 +54,23 @@ XImage::XImage(const XImage& Image, float scale)
|
||||
{
|
||||
UINTN SrcWidth = Image.GetWidth();
|
||||
UINTN SrcHeight = Image.GetHeight();
|
||||
Width = (UINTN)(SrcWidth * scale);
|
||||
Height = (UINTN)(SrcHeight * scale);
|
||||
PixelData.CheckSize(GetWidth()*GetHeight());
|
||||
PixelData.SetLength(GetWidth()*GetHeight());
|
||||
|
||||
if (scale < 1.e-4) return;
|
||||
CopyScaled(Image, scale);
|
||||
if (scale < 1.e-4) {
|
||||
Width = SrcWidth;
|
||||
Height = SrcHeight;
|
||||
PixelData.CheckSize(GetWidth()*GetHeight());
|
||||
PixelData.SetLength(GetWidth()*GetHeight());
|
||||
for (UINTN y = 0; y < Height; ++y)
|
||||
for (UINTN x = 0; x < Width; ++x)
|
||||
PixelData[y * Width + x] = Image.GetPixel(x, y);
|
||||
|
||||
} else {
|
||||
Width = (UINTN)(SrcWidth * scale);
|
||||
Height = (UINTN)(SrcHeight * scale);
|
||||
PixelData.CheckSize(Width * Height);
|
||||
PixelData.SetLength(Width * Height);
|
||||
CopyScaled(Image, scale);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -207,7 +217,11 @@ void XImage::CopyScaled(const XImage& Image, float scale)
|
||||
}
|
||||
}
|
||||
|
||||
void XImage::Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest) //lowest image is opaque
|
||||
/* Place Top image over this image at PosX,PosY
|
||||
* Lowest means final image is opaque
|
||||
* else transparency will be multiplied
|
||||
*/
|
||||
void XImage::Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest)
|
||||
{
|
||||
UINT32 TopAlpha;
|
||||
UINT32 RevAlpha;
|
||||
@ -215,28 +229,29 @@ void XImage::Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest)
|
||||
UINT32 Temp;
|
||||
|
||||
for (UINTN y = PosY; y < Height && (y - PosY) < TopImage.GetHeight(); ++y) {
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL& CompPtr = *GetPixelPtr(PosX, y); // I assign a ref to avoid the operator ->. Compiler will produce the same anyway.
|
||||
// EFI_GRAPHICS_OUTPUT_BLT_PIXEL& CompPtr = *GetPixelPtr(PosX, y); // I assign a ref to avoid the operator ->. Compiler will produce the same anyway.
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* CompPtr = GetPixelPtr(PosX, y);
|
||||
for (UINTN x = PosX; x < Width && (x - PosX) < TopImage.GetWidth(); ++x) {
|
||||
TopAlpha = TopImage.GetPixel(x-PosX, y-PosY).Reserved;
|
||||
RevAlpha = 255 - TopAlpha;
|
||||
FinalAlpha = (255*255 - RevAlpha*(255 - CompPtr.Reserved)) / 255;
|
||||
FinalAlpha = (255*255 - RevAlpha*(255 - CompPtr->Reserved)) / 255;
|
||||
|
||||
//final alpha =(1-(1-x)*(1-y)) =(255*255-(255-topA)*(255-compA))/255
|
||||
Temp = (CompPtr.Blue * RevAlpha) + (TopImage.GetPixel(x-PosX, y-PosY).Blue * TopAlpha);
|
||||
CompPtr.Blue = (UINT8)(Temp / 255);
|
||||
Temp = (CompPtr->Blue * RevAlpha) + (TopImage.GetPixel(x-PosX, y-PosY).Blue * TopAlpha);
|
||||
CompPtr->Blue = (UINT8)(Temp / 255);
|
||||
|
||||
Temp = (CompPtr.Green * RevAlpha) + (TopImage.GetPixel(x-PosX, y-PosY).Green * TopAlpha);
|
||||
CompPtr.Green = (UINT8)(Temp / 255);
|
||||
Temp = (CompPtr->Green * RevAlpha) + (TopImage.GetPixel(x-PosX, y-PosY).Green * TopAlpha);
|
||||
CompPtr->Green = (UINT8)(Temp / 255);
|
||||
|
||||
Temp = (CompPtr.Red * RevAlpha) + (TopImage.GetPixel(x-PosX, y-PosY).Red * TopAlpha);
|
||||
CompPtr.Red = (UINT8)(Temp / 255);
|
||||
Temp = (CompPtr->Red * RevAlpha) + (TopImage.GetPixel(x-PosX, y-PosY).Red * TopAlpha);
|
||||
CompPtr->Red = (UINT8)(Temp / 255);
|
||||
|
||||
if (Lowest) {
|
||||
CompPtr.Reserved = 255;
|
||||
CompPtr->Reserved = 255;
|
||||
} else {
|
||||
CompPtr.Reserved = (UINT8)FinalAlpha;
|
||||
CompPtr->Reserved = (UINT8)FinalAlpha;
|
||||
}
|
||||
|
||||
CompPtr++; //faster way to move to next pixel
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -319,9 +334,8 @@ unsigned XImage::FromSVG(const CHAR8 *SVGData, UINTN FileDataLength, float scale
|
||||
// Screen operations
|
||||
/*
|
||||
* The function to get image from screen. Used in screenshot (full screen), Pointer (small area) and Draw (small area)
|
||||
* XImage must be created with UGAWidth, UGAHeight as egGetScreenSize(&UGAWidth, &UGAHeight); with PixelData allocated
|
||||
* egScreenWidth = GraphicsOutput->Mode->Info->HorizontalResolution;
|
||||
* egScreenHeight = GraphicsOutput->Mode->Info->VerticalResolution;
|
||||
* XImage must be created with Width, Height of Rect
|
||||
* the rect will be clipped if it intersects the screen edge
|
||||
*
|
||||
* be careful about alpha. This procedure can produce alpha = 0 which means full transparent
|
||||
*/
|
||||
@ -330,6 +344,7 @@ void XImage::GetArea(const EG_RECT& Rect)
|
||||
GetArea(Rect.XPos, Rect.YPos, Rect.Width, Rect.Height);
|
||||
}
|
||||
|
||||
|
||||
void XImage::GetArea(INTN x, INTN y, UINTN W, UINTN H)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
@ -349,49 +364,41 @@ void XImage::GetArea(INTN x, INTN y, UINTN W, UINTN H)
|
||||
if (W == 0) W = Width;
|
||||
if (H == 0) H = Height;
|
||||
|
||||
INTN AreaWidth = (x + W > (UINTN)UGAWidth) ? (UGAWidth - x) : W;
|
||||
INTN AreaHeight = (y + H > (UINTN)UGAHeight) ? ((UINTN)UGAHeight - y) : H;
|
||||
|
||||
Width = (x + W > (UINTN)UGAWidth) ? (UGAWidth - x) : W;
|
||||
Height = (y + H > (UINTN)UGAHeight) ? ((UINTN)UGAHeight - y) : H;
|
||||
// DBG("x=%d y=%d W=%d h=%d Width=%d Height=%d\n", x,y,W,H,Width,Height);
|
||||
// INTN LineBytes = Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
||||
PixelData.SetLength(Width * Height); // setLength BEFORE, so &PixelData[0]
|
||||
|
||||
if (GraphicsOutput != NULL) {
|
||||
PixelData.SetLength(AreaWidth*AreaHeight); // setLength BEFORE, so &PixelData[0]
|
||||
INTN LineBytes = GraphicsOutput->Mode->Info->HorizontalResolution * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
||||
GraphicsOutput->Blt(GraphicsOutput,
|
||||
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)&PixelData[0],
|
||||
EfiBltVideoToBltBuffer,
|
||||
x, y, 0, 0, AreaWidth, AreaHeight, LineBytes);
|
||||
x, y, 0, 0, Width, Height, 0);
|
||||
}
|
||||
else if (UgaDraw != NULL) {
|
||||
UINT32 LineWidth = 0;
|
||||
UINT32 UGAScreenHeight = 0;
|
||||
UINT32 Depth = 0;
|
||||
UINT32 RefreshRate = 60;
|
||||
Status = UgaDraw->GetMode(UgaDraw, &LineWidth, &UGAScreenHeight, &Depth, &RefreshRate);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return; // graphics not available
|
||||
}
|
||||
|
||||
PixelData.SetLength(AreaWidth*AreaHeight); // setLength BEFORE, so &PixelData[0]
|
||||
UgaDraw->Blt(UgaDraw,
|
||||
(EFI_UGA_PIXEL *)&PixelData[0],
|
||||
(EFI_UGA_PIXEL *)GetPixelPtr(0,0),
|
||||
EfiUgaVideoToBltBuffer,
|
||||
x, y, 0, 0, AreaWidth, AreaHeight, LineWidth * sizeof(EFI_UGA_PIXEL));
|
||||
x, y, 0, 0, Width, Height, 0);
|
||||
}
|
||||
|
||||
Width = AreaWidth;
|
||||
Height = AreaHeight;
|
||||
}
|
||||
|
||||
void XImage::Draw(INTN x, INTN y, float scale)
|
||||
{
|
||||
//prepare images
|
||||
DBG("1\n");
|
||||
XImage Top(*this, scale);
|
||||
XImage Background(UGAWidth, UGAHeight);
|
||||
DBG("2\n");
|
||||
XImage Background(Width, Height);
|
||||
DBG("3\n");
|
||||
Background.GetArea(x, y, Width, Height);
|
||||
|
||||
Background.Compose(0, 0, Top, false);
|
||||
DBG("4\n");
|
||||
Background.Compose(0, 0, Top, true);
|
||||
DBG("5\n");
|
||||
UINTN AreaWidth = (x + Width > (UINTN)UGAWidth) ? (UGAWidth - x) : Width;
|
||||
UINTN AreaHeight = (y + Height > (UINTN)UGAHeight) ? (UGAHeight - y) : Height;
|
||||
|
||||
DBG("area=%d,%d\n", AreaWidth, AreaHeight);
|
||||
// prepare protocols
|
||||
EFI_STATUS Status;
|
||||
EFI_GUID UgaDrawProtocolGuid = EFI_UGA_DRAW_PROTOCOL_GUID;
|
||||
@ -408,14 +415,14 @@ void XImage::Draw(INTN x, INTN y, float scale)
|
||||
}
|
||||
//output combined image
|
||||
if (GraphicsOutput != NULL) {
|
||||
GraphicsOutput->Blt(GraphicsOutput, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)Top.GetPixelPtr(0, 0),
|
||||
GraphicsOutput->Blt(GraphicsOutput, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)Background.GetPixelPtr(0, 0),
|
||||
EfiBltBufferToVideo,
|
||||
0, 0, x, y,
|
||||
AreaWidth, AreaHeight, UGAWidth * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
||||
0, 0, x, y, AreaWidth, AreaHeight, 0);
|
||||
//Background.GetWidth() * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
||||
}
|
||||
else if (UgaDraw != NULL) {
|
||||
UgaDraw->Blt(UgaDraw, (EFI_UGA_PIXEL *)Background.GetPixelPtr(0, 0), EfiUgaBltBufferToVideo,
|
||||
0, 0, x, y,
|
||||
AreaWidth, AreaHeight, UGAWidth * sizeof(EFI_UGA_PIXEL));
|
||||
0, 0, x, y, AreaWidth, AreaHeight, 0);
|
||||
// Background.GetWidth() * sizeof(EFI_UGA_PIXEL));
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,9 @@
|
||||
#define DBG(...) DebugLog(DEBUG_MOUSE, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
//extern EFI_AUDIO_IO_PROTOCOL *AudioIo;
|
||||
|
||||
// make them theme dependent? No, 32 is good value for all.
|
||||
#define POINTER_WIDTH 32
|
||||
#define POINTER_HEIGHT 32
|
||||
// Initial value, but later it will be theme dependent
|
||||
#define POINTER_WIDTH 64
|
||||
#define POINTER_HEIGHT 64
|
||||
|
||||
XPointer::XPointer()
|
||||
: PointerImage(NULL),
|
||||
@ -75,37 +73,28 @@ EFI_STATUS XPointer::MouseBirth()
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
MsgLog("No mouse!\n");
|
||||
delete PointerImage;
|
||||
PointerImage = NULL;
|
||||
if (PointerImage) {
|
||||
delete PointerImage;
|
||||
PointerImage = NULL;
|
||||
}
|
||||
MouseEvent = NoEvents;
|
||||
SimplePointerProtocol = NULL;
|
||||
gSettings.PointerEnabled = FALSE;
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ( !PointerImage->isEmpty() ) {
|
||||
//this is impossible after BuiltinIcon
|
||||
MsgLog(" pointer image! Renew it\n");
|
||||
//SimplePointerProtocol = NULL;
|
||||
//Alive = false;
|
||||
//return EFI_NOT_FOUND;
|
||||
if (PointerImage && !PointerImage->isEmpty() ) {
|
||||
delete PointerImage;
|
||||
PointerImage = nullptr;
|
||||
}
|
||||
DBG("Now update image because of other theme\n");
|
||||
// Now update image because of other theme has other image
|
||||
PointerImage = new XImage(BuiltinIcon(BUILTIN_ICON_POINTER));
|
||||
DBG("new image created\n");
|
||||
LastClickTime = 0; //AsmReadTsc();
|
||||
LastClickTime = 0;
|
||||
oldPlace.XPos = (INTN)(UGAWidth >> 2);
|
||||
oldPlace.YPos = (INTN)(UGAHeight >> 2);
|
||||
oldPlace.Width = POINTER_WIDTH;
|
||||
oldPlace.Height = POINTER_HEIGHT;
|
||||
DBG("init mouse at [%d, %d]\n", oldPlace.XPos, oldPlace.YPos);
|
||||
oldPlace.Width = PointerImage->GetWidth();
|
||||
oldPlace.Height = PointerImage->GetHeight();
|
||||
CopyMem(&newPlace, &oldPlace, sizeof(EG_RECT));
|
||||
// DBG("newPlace={%d, %d, %d, %d}\n", newPlace.XPos, newPlace.YPos, newPlace.Width, newPlace.Height);
|
||||
|
||||
//newImage->Fill(&MenuBackgroundPixel),
|
||||
// egTakeImage(oldImage, oldPlace.XPos, oldPlace.YPos,
|
||||
// POINTER_WIDTH, POINTER_HEIGHT); // DrawPointer repeats it
|
||||
Draw();
|
||||
MouseEvent = NoEvents;
|
||||
Alive = true;
|
||||
@ -115,36 +104,26 @@ EFI_STATUS XPointer::MouseBirth()
|
||||
VOID XPointer::Draw()
|
||||
{
|
||||
|
||||
// take background image
|
||||
// take background image for later to restore background
|
||||
oldImage.GetArea(newPlace);
|
||||
DBG("got area\n");
|
||||
CopyMem(&oldPlace, &newPlace, sizeof(EG_RECT)); //can we use oldPlace = newPlace; ?
|
||||
|
||||
// CopyMem(newImage->PixelData, oldImage->PixelData, (UINTN)(POINTER_WIDTH * POINTER_HEIGHT * sizeof(EG_PIXEL)));
|
||||
// newImage.CopyScaled(oldImage, 1.f);
|
||||
DBG("Draw pointer\n");
|
||||
// newImage.Compose(0, 0, PointerImage, true);
|
||||
// newImage.Draw(newPlace.XPos, newPlace.YPos, 1.f);
|
||||
PointerImage->Draw(newPlace.XPos, newPlace.YPos, 1.f);
|
||||
PointerImage->Draw(newPlace.XPos, newPlace.YPos, 0.f); //zero means no scale
|
||||
}
|
||||
|
||||
VOID XPointer::KillMouse()
|
||||
{
|
||||
// EG_PIXEL pi;
|
||||
|
||||
Alive = false;
|
||||
if (!SimplePointerProtocol) {
|
||||
return;
|
||||
}
|
||||
DBG("KillMouse\n");
|
||||
// newImage.setEmpty(); // Don't empty them, we'll need them at the next mouse birth
|
||||
// oldImage.setEmpty();
|
||||
// DBG("KillMouse\n");
|
||||
|
||||
if (PointerImage) {
|
||||
delete PointerImage;
|
||||
PointerImage = nullptr;
|
||||
}
|
||||
|
||||
|
||||
MouseEvent = NoEvents;
|
||||
SimplePointerProtocol = NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user