1363 lines
37 KiB
C
1363 lines
37 KiB
C
/** @file
|
|
Support functions for Setup Mouse Protocol
|
|
|
|
;******************************************************************************
|
|
;* 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 "SetupMouse.h"
|
|
#include <Protocol/HiiFont.h>
|
|
#include <Library/UefiHiiServicesLib.h>
|
|
#include <Library/UefiLib.h>
|
|
|
|
extern EFI_HII_HANDLE mImageHiiHandle;
|
|
/**
|
|
Get setup mouse start offset.
|
|
|
|
@param [in] GraphicsOutput Pointer to EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
|
|
@param [out] OffsetX Pointer to setup mouse start x-axis.
|
|
@param [out] OffsetY Pointer to setup mouse start y-axis.
|
|
|
|
@retval EFI_INVALID_PARAMETER Some input parameters are invalid
|
|
@retval EFI_SUCCESS Get Setup mouse start offset successful.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetStartOffset (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
|
|
OUT UINTN *OffsetX,
|
|
OUT UINTN *OffsetY
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Rows;
|
|
UINTN Columns;
|
|
|
|
ASSERT (GraphicsOutput != NULL);
|
|
ASSERT (OffsetX != NULL);
|
|
ASSERT (OffsetY != NULL);
|
|
|
|
Status = gST->ConOut->QueryMode (
|
|
gST->ConOut,
|
|
gST->ConOut->Mode->Mode,
|
|
&Columns,
|
|
&Rows
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
*OffsetX = ((GraphicsOutput->Mode->Info->HorizontalResolution - Columns *EFI_GLYPH_WIDTH)) >> 1;
|
|
*OffsetY = ((GraphicsOutput->Mode->Info->VerticalResolution - Rows *EFI_GLYPH_HEIGHT)) >> 1;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Invalidate Image and update GOP invalidate region
|
|
|
|
@param [in] Private Setup mouse private data
|
|
@param [in] ImageInfo Image information
|
|
|
|
@retval N/A
|
|
|
|
**/
|
|
VOID
|
|
InvalidateImage (
|
|
IN PRIVATE_MOUSE_DATA *Private,
|
|
IN IMAGE_INFO *ImageInfo
|
|
)
|
|
|
|
{
|
|
GOP_ENTRY *GopEntry;
|
|
LIST_ENTRY *Node;
|
|
|
|
|
|
Private = mPrivate;
|
|
if (!ImageInfo->Visible) {
|
|
return ;
|
|
}
|
|
|
|
Node = GetFirstNode (&Private->GopList);
|
|
while (!IsNull (&Private->GopList, Node)) {
|
|
GopEntry = GOP_ENTRY_FROM_THIS (Node);
|
|
UnionRect (&GopEntry->InvalidateRc, &GopEntry->InvalidateRc, &ImageInfo->ImageRc);
|
|
Node = GetNextNode (&Private->GopList, Node);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Update invalidate region
|
|
|
|
@param [in] Private Setup mouse private data
|
|
@param [in] ImageInfo Image information
|
|
|
|
@retval N/A
|
|
|
|
**/
|
|
VOID
|
|
InvalidateRect (
|
|
IN PRIVATE_MOUSE_DATA *Private,
|
|
IN RECT *Rect
|
|
)
|
|
{
|
|
GOP_ENTRY *GopEntry;
|
|
LIST_ENTRY *Node;
|
|
|
|
|
|
Private = mPrivate;
|
|
|
|
Node = GetFirstNode (&Private->GopList);
|
|
while (!IsNull (&Private->GopList, Node)) {
|
|
GopEntry = GOP_ENTRY_FROM_THIS (Node);
|
|
UnionRect (&GopEntry->InvalidateRc, &GopEntry->InvalidateRc, Rect);
|
|
Node = GetNextNode (&Private->GopList, Node);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Hide Image and update GOP invalidate region
|
|
|
|
@param [in] ImageInfo Image information
|
|
|
|
@retval N/A
|
|
|
|
**/
|
|
VOID
|
|
HideImage (
|
|
IN IMAGE_INFO *ImageInfo
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = mPrivate;
|
|
ASSERT_LOCKED (&Private->SetupMouseLock);
|
|
|
|
if (!ImageInfo->Visible) {
|
|
return ;
|
|
}
|
|
|
|
//
|
|
// invalidate original image
|
|
//
|
|
InvalidateImage (Private, ImageInfo);
|
|
ImageInfo->Visible = FALSE;
|
|
}
|
|
|
|
|
|
/**
|
|
Show Image and update GOP invalidate region
|
|
|
|
@param [in] ImageInfo Image information
|
|
|
|
@retval N/A
|
|
|
|
**/
|
|
VOID
|
|
ShowImage (
|
|
IN IMAGE_INFO *ImageInfo
|
|
)
|
|
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = mPrivate;
|
|
ASSERT_LOCKED (&Private->SetupMouseLock);
|
|
if (ImageInfo->Visible) {
|
|
return ;
|
|
}
|
|
|
|
//
|
|
// invalidate original image
|
|
//
|
|
ImageInfo->Visible = TRUE;
|
|
InvalidateImage (Private, ImageInfo);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
Move Image
|
|
|
|
@param [in] ImageInfo Pointer of image
|
|
@param [in] X Image x axis
|
|
@param [in] Y Image y axis
|
|
|
|
@retval N/A
|
|
|
|
**/
|
|
VOID
|
|
MoveImage (
|
|
IN IMAGE_INFO *ImageInfo,
|
|
IN UINTN X,
|
|
IN UINTN Y
|
|
)
|
|
{
|
|
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = mPrivate;
|
|
ASSERT_LOCKED (&Private->SetupMouseLock);
|
|
|
|
//
|
|
// invalidate original image
|
|
//
|
|
if (ImageInfo->Visible) {
|
|
InvalidateImage (Private, ImageInfo);
|
|
}
|
|
|
|
OffsetRect (
|
|
&ImageInfo->ImageRc,
|
|
(INT32)(X - ImageInfo->ImageRc.left),
|
|
(INT32)(Y - ImageInfo->ImageRc.top)
|
|
);
|
|
|
|
//
|
|
// invalidate new position image
|
|
//
|
|
if (ImageInfo->Visible) {
|
|
InvalidateImage (Private, ImageInfo);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Destroy image
|
|
|
|
@param ImageInfo Image information
|
|
|
|
@retval N/A
|
|
|
|
**/
|
|
VOID
|
|
DestroyImage (
|
|
IMAGE_INFO *ImageInfo
|
|
)
|
|
{
|
|
if (ImageInfo->Image != NULL) {
|
|
FreePool (ImageInfo->Image);
|
|
ImageInfo->Image = NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Get font information, prefer TTF font
|
|
|
|
@param[in] TextColor Font text color
|
|
@param[in] BackgroundColor Font background color
|
|
@param[in] FontSize Font size
|
|
|
|
@return EFI_FONT_DISPLAY_INFO TTF font or system font
|
|
|
|
**/
|
|
STATIC
|
|
EFI_FONT_DISPLAY_INFO *
|
|
GetFontInfo (
|
|
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TextColor,
|
|
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackgroundColor,
|
|
IN UINT16 FontSize
|
|
)
|
|
|
|
{
|
|
STATIC EFI_FONT_DISPLAY_INFO *FontInfo = NULL;
|
|
EFI_FONT_HANDLE FontHandle;
|
|
EFI_STATUS Status;
|
|
|
|
if (FontInfo != NULL) {
|
|
CopyMem (&FontInfo->ForegroundColor, TextColor, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
CopyMem (&FontInfo->BackgroundColor, BackgroundColor, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
|
|
if (FontInfo->FontInfo.FontName[0] != '\0') {
|
|
FontInfo->FontInfo.FontSize = FontSize;
|
|
}
|
|
return FontInfo;
|
|
}
|
|
|
|
FontInfo = AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO) + StrSize (L"ttf") - sizeof (CHAR16));
|
|
if (FontInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
StrCpyS (FontInfo->FontInfo.FontName, sizeof(L"ttf") / sizeof(CHAR16), L"ttf");
|
|
FontInfo->FontInfoMask = EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE;
|
|
FontHandle = NULL;
|
|
Status = gHiiFont->GetFontInfo (
|
|
gHiiFont,
|
|
&FontHandle,
|
|
FontInfo,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
FontInfo->FontInfo.FontName[0] = 0;
|
|
FontInfo->FontInfo.FontSize = 19;
|
|
} else {
|
|
FontInfo->FontInfo.FontSize = FontSize;
|
|
}
|
|
CopyMem (&FontInfo->ForegroundColor, TextColor, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
CopyMem (&FontInfo->BackgroundColor, BackgroundColor, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
FontInfo->FontInfoMask = 0;
|
|
|
|
return FontInfo;
|
|
}
|
|
|
|
/**
|
|
Draw text to blt buffer by TTF font.
|
|
|
|
@param [in] String String
|
|
@param [in] Blt Output blt buffer
|
|
@param [in] BackgroundColor Background color
|
|
@param [in] String Destination LineLen
|
|
@param [in] TextRc Destination rectangle
|
|
@param [in] FontInfo Points to the string font and color information
|
|
or NULL if the string should use the default
|
|
system font and color.
|
|
|
|
@return return StringToImage status.
|
|
**/
|
|
EFI_STATUS
|
|
TrueTypeStringToImage (
|
|
IN CHAR16 *String,
|
|
EFI_FONT_DISPLAY_INFO *FontInfo,
|
|
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt,
|
|
IN UINT16 Width,
|
|
IN UINT16 Height,
|
|
IN UINT16 Delta
|
|
)
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
INTN Y;
|
|
INTN X;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer2;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Bitmap;
|
|
EFI_IMAGE_OUTPUT *Image;
|
|
UINTN BltBufferWidth;
|
|
UINT16 ImageWidth;
|
|
|
|
ASSERT (String != NULL);
|
|
ASSERT (Blt != NULL);
|
|
|
|
BltBuffer = Blt;
|
|
while (*String != 0) {
|
|
Image = NULL;
|
|
Status = gHiiFont->GetGlyph (
|
|
gHiiFont,
|
|
*String,
|
|
FontInfo,
|
|
&Image,
|
|
NULL
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
if ((Status == EFI_WARN_UNKNOWN_GLYPH) && Image != NULL) {
|
|
FreePool (Image->Image.Bitmap);
|
|
FreePool (Image);
|
|
}
|
|
String++;
|
|
continue;
|
|
}
|
|
|
|
ImageWidth = Image->Width;
|
|
if (ImageWidth >= Width) {
|
|
FreePool (Image->Image.Bitmap);
|
|
FreePool (Image);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// glyph to buffer
|
|
//
|
|
Y = Image->Height;
|
|
Bitmap = Image->Image.Bitmap;
|
|
BltBuffer2 = BltBuffer;
|
|
BltBufferWidth = ImageWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
while (--Y >= 0) {
|
|
X = Image->Width;
|
|
while (--X >= 0) {
|
|
BlendPixel (BltBuffer2 + X, Bitmap + X);
|
|
}
|
|
BltBuffer2 += Delta;
|
|
Bitmap += ImageWidth;
|
|
}
|
|
|
|
Width -= ImageWidth;
|
|
BltBuffer += ImageWidth;
|
|
String++;
|
|
|
|
FreePool (Image->Image.Bitmap);
|
|
FreePool (Image);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get the width of a unicode string.
|
|
|
|
@param[in] UnicodeChar The unicode character to be inquired
|
|
|
|
@return UINTN The width of the query string.
|
|
|
|
**/
|
|
STATIC
|
|
UINTN
|
|
SetupMouseGetStringWidth (
|
|
IN EFI_FONT_DISPLAY_INFO *FontInfo,
|
|
IN CHAR16 *String
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CHAR16 Char;
|
|
UINTN Width;
|
|
EFI_IMAGE_OUTPUT *Image;
|
|
|
|
ASSERT (FontInfo != NULL);
|
|
ASSERT (String != NULL);
|
|
|
|
if (FontInfo->FontInfo.FontName[0] == 0) {
|
|
return UnicodeStringDisplayLength (String) * EFI_GLYPH_WIDTH;
|
|
}
|
|
|
|
Width = 0;
|
|
while ((Char = *String++) != '\0') {
|
|
Image = NULL;
|
|
Status = gHiiFont->GetGlyph (
|
|
gHiiFont,
|
|
Char,
|
|
FontInfo,
|
|
&Image,
|
|
NULL
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
if ((Status == EFI_WARN_UNKNOWN_GLYPH) && Image != NULL) {
|
|
FreePool (Image->Image.Bitmap);
|
|
FreePool (Image);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
Width += Image->Width;
|
|
FreePool (Image->Image.Bitmap);
|
|
FreePool (Image);
|
|
}
|
|
|
|
return Width;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
Use HiiFont to draw text to blt buffer by font info.
|
|
|
|
@param [in] ImageInfo Destination Image
|
|
@param [in] TextColor Text Color
|
|
@param [in] BackgroundColor Background color
|
|
@param [in] String Destination LineLen
|
|
@param [in] TextRc Destination rectangle
|
|
@param [in] FontInfo Points to the string font and color information
|
|
or NULL if the string should use the default
|
|
system font and color.
|
|
|
|
@return return StringToImage status.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
SetupMouseDrawTextByFontInfo (
|
|
IN IMAGE_INFO *ImageInfo,
|
|
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TextColor,
|
|
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackgroundColor,
|
|
IN EFI_STRING String,
|
|
IN RECT *TextRc,
|
|
IN EFI_FONT_DISPLAY_INFO *FontInfo
|
|
)
|
|
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_IMAGE_OUTPUT Blt;
|
|
EFI_IMAGE_OUTPUT *BltPtr;
|
|
UINTN OffsetX;
|
|
UINTN OffsetY;
|
|
UINTN StrWidth;
|
|
|
|
BltPtr = &Blt;
|
|
ZeroMem (&Blt, sizeof (EFI_IMAGE_OUTPUT));
|
|
|
|
Blt.Image.Bitmap = ImageInfo->Image;
|
|
Blt.Width = (UINT16) (ImageInfo->ImageRc.right - ImageInfo->ImageRc.left);
|
|
Blt.Height = (UINT16) (ImageInfo->ImageRc.bottom - ImageInfo->ImageRc.top);
|
|
//
|
|
// text align: center
|
|
//
|
|
StrWidth = SetupMouseGetStringWidth (FontInfo, String);
|
|
if ((UINTN)(TextRc->right - TextRc->left) >= StrWidth) {
|
|
OffsetX = ((TextRc->right + TextRc->left) - StrWidth) / 2;
|
|
} else {
|
|
OffsetX = TextRc->left;
|
|
}
|
|
if ((UINTN)(TextRc->bottom - TextRc->top) >= FontInfo->FontInfo.FontSize) {
|
|
OffsetY = ((TextRc->bottom + TextRc->top) - FontInfo->FontInfo.FontSize) / 2;
|
|
} else {
|
|
OffsetY = TextRc->top;
|
|
}
|
|
|
|
if (FontInfo->FontInfo.FontName[0] == '\0') {
|
|
Status = gHiiFont->StringToImage (
|
|
gHiiFont,
|
|
EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_OUT_FLAG_TRANSPARENT,
|
|
String,
|
|
FontInfo,
|
|
&BltPtr,
|
|
OffsetX,
|
|
OffsetY,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
} else {
|
|
|
|
Status = TrueTypeStringToImage (
|
|
(CHAR16 *) String,
|
|
FontInfo,
|
|
Blt.Image.Bitmap + Blt.Width * OffsetY + OffsetX,
|
|
(UINT16) Blt.Width,
|
|
(UINT16) Blt.Height,
|
|
(UINT16) Blt.Width
|
|
);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Use HiiFont to draw text to blt buffer
|
|
|
|
@param [in] ImageInfo Destination Image
|
|
@param [in] TextColor Text Color
|
|
@param [in] BackgroundColor Background color
|
|
@param [in] String Destination LineLen
|
|
@param [in] TextRc Destination rectangle
|
|
|
|
@return return StringToImage status
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SetupMouseDrawText (
|
|
IN IMAGE_INFO *ImageInfo,
|
|
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TextColor,
|
|
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackgroundColor,
|
|
IN EFI_STRING String,
|
|
IN RECT *TextRc,
|
|
IN UINT16 FontSize
|
|
)
|
|
|
|
{
|
|
EFI_FONT_DISPLAY_INFO *FontInfo;
|
|
EFI_STATUS Status;
|
|
|
|
FontInfo = GetFontInfo (TextColor, BackgroundColor, FontSize);
|
|
if (FontInfo == NULL) {
|
|
FontInfo = GetFontInfo (TextColor, BackgroundColor, 19);
|
|
if (FontInfo == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
Status = SetupMouseDrawTextByFontInfo (
|
|
ImageInfo,
|
|
TextColor,
|
|
BackgroundColor,
|
|
String,
|
|
TextRc,
|
|
FontInfo
|
|
);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
#define SIGN(x) (((x) > 0) ? 1 : (((x) == 0) ? 0 : -1))
|
|
|
|
|
|
/**
|
|
Stretch image function from microwindows fblin32alpha function
|
|
|
|
@param DstBlt Destination Blt Buffer
|
|
@param SrcBlt Source Blt Buffer
|
|
@param DstLineLen Destination LineLen
|
|
@param SrcLineLen Source LineLen
|
|
@param dest_x_start Destination X
|
|
@param dest_y_start Destination Y
|
|
@param width Width
|
|
@param height Height
|
|
@param x_denominator X denominator
|
|
@param y_denominator Y denominator
|
|
@param src_x_fraction Source X fraction
|
|
@param src_y_fraction Source Y fraction
|
|
@param x_step_fraction X step fraction
|
|
@param y_step_fraction Y step fraction
|
|
@param op Directly src copy to dst
|
|
|
|
@retval N/A
|
|
|
|
**/
|
|
VOID
|
|
SetupMouseLinear32aStretchBlitEx(
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *DstBlt,
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *SrcBlt,
|
|
INT32 DstLineLen,
|
|
INT32 SrcLineLen,
|
|
INT32 dest_x_start,
|
|
INT32 dest_y_start,
|
|
INT32 width,
|
|
INT32 height,
|
|
INT32 x_denominator,
|
|
INT32 y_denominator,
|
|
INT32 src_x_fraction,
|
|
INT32 src_y_fraction,
|
|
INT32 x_step_fraction,
|
|
INT32 y_step_fraction,
|
|
INT32 op
|
|
)
|
|
{
|
|
/* Pointer to the current pixel in the source image */
|
|
UINT32 *src_ptr;
|
|
|
|
/* Pointer to x=xs1 on the next line in the source image */
|
|
UINT32 *next_src_ptr;
|
|
|
|
/* Pointer to the current pixel in the dest image */
|
|
UINT32 *dest_ptr;
|
|
|
|
/* Pointer to x=xd1 on the next line in the dest image */
|
|
UINT32 *next_dest_ptr;
|
|
|
|
/* Keep track of error in the source co-ordinates */
|
|
int x_error;
|
|
int y_error;
|
|
|
|
/* 1-unit steps "forward" through the source image, as steps in the image
|
|
* byte array.
|
|
*/
|
|
int src_x_step_one;
|
|
int src_y_step_one;
|
|
|
|
/* normal steps "forward" through the source image, as steps in the image
|
|
* byte array.
|
|
*/
|
|
int src_x_step_normal;
|
|
int src_y_step_normal;
|
|
|
|
/* 1-unit steps "forward" through the source image, as steps in the image
|
|
* byte array.
|
|
*/
|
|
int x_error_step_normal;
|
|
int y_error_step_normal;
|
|
|
|
/* Countdown to the end of the destination image */
|
|
int x_count;
|
|
int y_count;
|
|
|
|
/* Start position in source, in whole pixels */
|
|
int src_x_start;
|
|
int src_y_start;
|
|
|
|
/* Error values for start X position in source */
|
|
int x_error_start;
|
|
|
|
/* 1-unit step down dest, in bytes. */
|
|
int dest_y_step;
|
|
|
|
/*DPRINTF("Nano-X: linear32_stretchflipblit( dest=(%d,%d) %dx%d )\n",
|
|
dest_x_start, dest_y_start, width, height); */
|
|
|
|
/* We add half a dest pixel here so we're sampling from the middle of
|
|
* the dest pixel, not the top left corner.
|
|
*/
|
|
src_x_fraction += (x_step_fraction >> 1);
|
|
src_y_fraction += (y_step_fraction >> 1);
|
|
|
|
/* Seperate the whole part from the fractions.
|
|
*
|
|
* Also, We need to do lots of comparisons to see if error values are
|
|
* >= x_denominator. So subtract an extra x_denominator for speed - then
|
|
* we can just check if it's >= 0.
|
|
*/
|
|
src_x_start = src_x_fraction / x_denominator;
|
|
src_y_start = src_y_fraction / y_denominator;
|
|
x_error_start = src_x_fraction - (src_x_start + 1) * x_denominator;
|
|
y_error = src_y_fraction - (src_y_start + 1) * y_denominator;
|
|
|
|
/* precalculate various deltas */
|
|
|
|
src_x_step_normal = x_step_fraction / x_denominator;
|
|
src_x_step_one = SIGN(x_step_fraction);
|
|
x_error_step_normal = ABS(x_step_fraction) - ABS(src_x_step_normal) * x_denominator;
|
|
|
|
src_y_step_normal = y_step_fraction / y_denominator;
|
|
src_y_step_one = SIGN(y_step_fraction) * SrcLineLen;
|
|
y_error_step_normal = ABS(y_step_fraction) - ABS(src_y_step_normal) * y_denominator;
|
|
src_y_step_normal *= SrcLineLen;
|
|
|
|
/* DPRINTF("linear32alpha_stretchblitex: X: One step=%d, err-=%d; normal step=%d, err+=%d\n"
|
|
"Y: One step=%d, err-=%d; normal step=%d, err+=%d\n",
|
|
src_x_step_one, x_denominator, src_x_step_normal, x_error_step_normal,
|
|
src_y_step_one, y_denominator, src_y_step_normal, y_error_step_normal);
|
|
*/
|
|
|
|
/* Pointer to the first source pixel */
|
|
next_src_ptr = ((UINT32 *) SrcBlt) +
|
|
src_y_start * SrcLineLen + src_x_start;
|
|
|
|
/* Cache the width of a scanline in dest */
|
|
dest_y_step = DstLineLen;
|
|
|
|
/* Pointer to the first dest pixel */
|
|
next_dest_ptr = ((UINT32 *) DstBlt) + (dest_y_start * dest_y_step) + dest_x_start;
|
|
|
|
/*
|
|
* Note: The MWROP_SRC and MWROP_XOR_FGBG cases below are simple
|
|
* expansions of the default case. They can be removed without
|
|
* significant speed penalty if you need to reduce code size.
|
|
*
|
|
* The SRC_OVER case cannot be removed (since applyOp doesn't
|
|
* handle it correctly).
|
|
*
|
|
* The MWROP_CLEAR case could be removed. But it is a large
|
|
* speed increase for a small quantity of code.
|
|
*
|
|
* FIXME Porter-Duff rules other than SRC_OVER not handled!!
|
|
*/
|
|
switch (op) {
|
|
case 0:
|
|
/* Benchmarking shows that this while loop is faster than the equivalent
|
|
* for loop: for(y_count=0; y_count<height; y_count++) { ... }
|
|
*/
|
|
y_count = height;
|
|
while (--y_count >= 0) {
|
|
src_ptr = next_src_ptr;
|
|
dest_ptr = next_dest_ptr;
|
|
|
|
x_error = x_error_start;
|
|
|
|
x_count = width;
|
|
while (--x_count >= 0) {
|
|
BlendPixel ((EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) dest_ptr, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) src_ptr);
|
|
dest_ptr++;
|
|
|
|
src_ptr += src_x_step_normal;
|
|
x_error += x_error_step_normal;
|
|
|
|
if (x_error >= 0) {
|
|
src_ptr += src_x_step_one;
|
|
x_error -= x_denominator;
|
|
}
|
|
}
|
|
|
|
next_dest_ptr += dest_y_step;
|
|
next_src_ptr += src_y_step_normal;
|
|
y_error += y_error_step_normal;
|
|
|
|
if (y_error >= 0) {
|
|
next_src_ptr += src_y_step_one;
|
|
y_error -= y_denominator;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Stretch image function from microwindows fblin32alpha function
|
|
|
|
@param DstBlt Destination Blt Buffer
|
|
@param d1_x Destination X1
|
|
@param d1_y Destination Y1
|
|
@param d2_x Destination X2
|
|
@param d2_y Destination Y2
|
|
@param DstLineLen Destination LineLen
|
|
@param SrcBlt Source Blt Buffer
|
|
@param s1_x Source X1
|
|
@param s1_y Source Y1
|
|
@param s2_x Source X2
|
|
@param s2_y Source Y2
|
|
@param SrcLineLen
|
|
|
|
@retval N/A
|
|
|
|
**/
|
|
void
|
|
SetupMouseStretchBlitEx (
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL * DstBlt,
|
|
INT32 d1_x,
|
|
INT32 d1_y,
|
|
INT32 d2_x,
|
|
INT32 d2_y,
|
|
INT32 DstLineLen,
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *SrcBlt,
|
|
INT32 s1_x,
|
|
INT32 s1_y,
|
|
INT32 s2_x,
|
|
INT32 s2_y,
|
|
INT32 SrcLineLen
|
|
)
|
|
{
|
|
/* Scale factors (as fractions, numerator/denominator) */
|
|
int src_x_step_numerator;
|
|
int src_x_step_denominator;
|
|
int src_y_step_numerator;
|
|
int src_y_step_denominator;
|
|
|
|
/* Clipped dest co-ords */
|
|
INT32 c1_x;
|
|
INT32 c1_y;
|
|
INT32 c2_x;
|
|
INT32 c2_y;
|
|
|
|
/* Initial source co-ordinates, as a fraction (denominators as above) */
|
|
int src_x_start_exact;
|
|
int src_y_start_exact;
|
|
|
|
/* Sort co-ordinates so d1 is top left, d2 is bottom right. */
|
|
if (d1_x > d2_x) {
|
|
register INT32 tmp = d2_x;
|
|
d2_x = d1_x;
|
|
d1_x = tmp;
|
|
tmp = s2_x;
|
|
s2_x = s1_x;
|
|
s1_x = tmp;
|
|
}
|
|
|
|
if (d1_y > d2_y) {
|
|
register INT32 tmp = d2_y;
|
|
d2_y = d1_y;
|
|
d1_y = tmp;
|
|
tmp = s2_y;
|
|
s2_y = s1_y;
|
|
s1_y = tmp;
|
|
}
|
|
|
|
/* Need to preserve original values, so make a copy we can clip. */
|
|
c1_x = d1_x;
|
|
c1_y = d1_y;
|
|
c2_x = d2_x;
|
|
c2_y = d2_y;
|
|
|
|
/* Calculate how far in source co-ordinates is
|
|
* equivalent to one pixel in dest co-ordinates.
|
|
* This is stored as a fraction (numerator/denominator).
|
|
* The numerator may be > denominator. The numerator
|
|
* may be negative, the denominator is always positive.
|
|
*
|
|
* We need half this distance for some purposes,
|
|
* hence the *2.
|
|
*
|
|
* The +1s are because we care about *sizes*, not
|
|
* deltas. (Without the +1s it just doesn't
|
|
* work properly.)
|
|
*/
|
|
src_x_step_numerator = (s2_x - s1_x + 1) << 1;
|
|
src_x_step_denominator = (d2_x - d1_x + 1) << 1;
|
|
src_y_step_numerator = (s2_y - s1_y + 1) << 1;
|
|
src_y_step_denominator = (d2_y - d1_y + 1) << 1;
|
|
|
|
///* Clip against dest window (NOT dest clipping region). */
|
|
if (c1_x < 0)
|
|
c1_x = 0;
|
|
if (c1_y < 0)
|
|
c1_y = 0;
|
|
//if (c2_x > DstLineLen)
|
|
// c2_x = dstpsd->xvirtres;
|
|
//if (c2_y > dstpsd->yvirtres)
|
|
// c2_y = dstpsd->yvirtres;
|
|
|
|
/* Final fully-offscreen check */
|
|
if ((c1_x >= c2_x) || (c1_y >= c2_y)) {
|
|
/* DPRINTF("Nano-X: GdStretchBlitEx: CLIPPED OFF (final check)\n"); */
|
|
return;
|
|
}
|
|
|
|
/* Well, if we survived that lot, then we now have a destination
|
|
* rectangle defined in (c1_x,c1_y)-(c2_x,c2_y).
|
|
*/
|
|
|
|
/* DPRINTF("Nano-X: GdStretchBlitEx: Clipped rect: (%d,%d)-(%d,%d)\n",
|
|
(int) c1_x, (int) c1_y, (int) c2_x, (int) c2_y); */
|
|
|
|
/* Calculate the position in the source rectange that is equivalent
|
|
* to the top-left of the destination rectangle.
|
|
*/
|
|
src_x_start_exact = s1_x * src_x_step_denominator + (c1_x - d1_x) * src_x_step_numerator;
|
|
src_y_start_exact = s1_y * src_y_step_denominator + (c1_y - d1_y) * src_y_step_numerator;
|
|
|
|
/* OK, clipping so far has been against physical bounds, we now have
|
|
* to worry about user defined clip regions.
|
|
*/
|
|
|
|
/* FIXME: check cursor in src region */
|
|
/* GdCheckCursor(srcpsd, c1_x, c1_y, c2_x-1, c2_y-1); */
|
|
/* DPRINTF("Nano-X: GdStretchBlitEx: no more clipping needed\n"); */
|
|
SetupMouseLinear32aStretchBlitEx (
|
|
DstBlt,
|
|
SrcBlt,
|
|
DstLineLen,
|
|
SrcLineLen,
|
|
c1_x, c1_y,
|
|
c2_x - c1_x,
|
|
c2_y - c1_y,
|
|
src_x_step_denominator,
|
|
src_y_step_denominator,
|
|
src_x_start_exact,
|
|
src_y_start_exact,
|
|
src_x_step_numerator,
|
|
src_y_step_numerator,
|
|
0
|
|
);
|
|
|
|
|
|
}
|
|
|
|
#define ROP_TRANSPARENT 34
|
|
|
|
|
|
/**
|
|
BitBlt function from microwindows fblin32alpha function
|
|
|
|
@param DstImage Destination Image information
|
|
@param DstX Destination X
|
|
@param DstY Destination Y
|
|
@param Width Width
|
|
@param Height Height
|
|
@param SrcImage Destination LineLen
|
|
@param SrcX Source X
|
|
@param SrcY Source Y
|
|
@param Rop copy src to destinamtion or with transparent color
|
|
|
|
@retval EFI_SUCCESS BitBlt is successful
|
|
|
|
**/
|
|
VOID
|
|
SetupMouseBitBlt (
|
|
IMAGE_INFO *DstImage,
|
|
INTN DstX,
|
|
INTN DstY,
|
|
UINTN Width,
|
|
UINTN Height,
|
|
IMAGE_INFO *SrcImage,
|
|
INTN SrcX,
|
|
INTN SrcY,
|
|
UINTN Rop
|
|
)
|
|
{
|
|
UINT32 *Dst32;
|
|
UINT32 *Src32;
|
|
UINTN DstDelta;
|
|
UINTN SrcDelta;
|
|
UINTN SrcImageWidth;
|
|
UINTN DstImageWidth;
|
|
UINTN SrcImageHeight;
|
|
UINTN DstImageHeight;
|
|
INTN X;
|
|
INTN Y;
|
|
UINTN CopyBytes;
|
|
|
|
//
|
|
// Clip blit rectange to source bitmap size
|
|
//
|
|
if (SrcX < 0) {
|
|
Width += SrcX;
|
|
DstX -= SrcX;
|
|
SrcX = 0;
|
|
}
|
|
|
|
if (SrcY < 0) {
|
|
Height += SrcY;
|
|
DstY -= SrcY;
|
|
SrcY = 0;
|
|
}
|
|
|
|
Dst32 = (UINT32 *)DstImage->Image;
|
|
Src32 = (UINT32 *)SrcImage->Image;
|
|
|
|
DstImageWidth = (UINTN) DstImage->ImageRc.right - DstImage->ImageRc.left;
|
|
SrcImageWidth = (UINTN) SrcImage->ImageRc.right - SrcImage->ImageRc.left;
|
|
DstImageHeight = (UINTN) DstImage->ImageRc.bottom - DstImage->ImageRc.top;
|
|
SrcImageHeight = (UINTN) SrcImage->ImageRc.bottom - SrcImage->ImageRc.top;
|
|
DstDelta = DstImageWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
SrcDelta = SrcImageWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
|
|
|
if ((SrcX + Width) > SrcImageWidth) {
|
|
Width = SrcImageWidth - SrcX;
|
|
}
|
|
|
|
if ((SrcY + Height) > SrcImageHeight) {
|
|
Height = SrcImageHeight - SrcY;
|
|
}
|
|
|
|
|
|
|
|
ASSERT (Dst32 != NULL && Src32 != NULL);
|
|
ASSERT (DstX >= 0 && DstX <= (INTN)DstImageWidth);
|
|
ASSERT (DstY >= 0 && DstY <= (INTN)DstImageHeight);
|
|
ASSERT (Width > 0 && Height > 0);
|
|
ASSERT (SrcX >= 0 && SrcX <= (INTN)SrcImageWidth);
|
|
ASSERT (SrcY >= 0 && SrcY <= (INTN)SrcImageHeight);
|
|
ASSERT (DstX + Width <= DstImageWidth);
|
|
ASSERT (DstY + Height <= DstImageHeight);
|
|
ASSERT (SrcX + Width <= SrcImageWidth);
|
|
ASSERT (SrcY + Height <= SrcImageHeight);
|
|
|
|
Dst32 = (UINT32 *)((UINT8 *)Dst32 + DstY * DstDelta + DstX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
Src32 = (UINT32 *)((UINT8 *)Src32 + SrcY * SrcDelta + SrcX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
|
|
if (Rop == ROP_TRANSPARENT) {
|
|
DstDelta = DstDelta - Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
SrcDelta = SrcDelta - Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
|
Y = Height;
|
|
while (--Y >= 0) {
|
|
X = Width;
|
|
while (--X >= 0) {
|
|
if (*Src32 != 0) {
|
|
*Dst32 = *Src32 & 0x00FFFFFF;
|
|
}
|
|
Src32++;
|
|
Dst32++;
|
|
}
|
|
Dst32 = (UINT32 *)((UINT8 *)Dst32 + DstDelta);
|
|
Src32 = (UINT32 *)((UINT8 *)Src32 + SrcDelta);
|
|
}
|
|
} else {
|
|
DstDelta = DstDelta - Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
SrcDelta = SrcDelta - Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
CopyBytes = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
|
Y = Height;
|
|
while (--Y >= 0) {
|
|
CopyMem (Dst32, Src32, CopyBytes);
|
|
Dst32 = (UINT32 *)((UINT8 *)Dst32 + DstDelta);
|
|
Src32 = (UINT32 *)((UINT8 *)Src32 + SrcDelta);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
StretchBlt function from microwindows fblin32alpha function
|
|
|
|
@param DstX Destination X
|
|
@param DstY Destination Y
|
|
@param DstWidth Destination Width
|
|
@param DstHeight Destination Height
|
|
@param SrcBlt Source Blt buffer
|
|
@param SrcX Source X
|
|
@param SrcY Source Y
|
|
@param SrcWidth Source Width
|
|
@param SrcHeight Source Height
|
|
@param SrcDelta Source buffer LineLen
|
|
@param Rop directly copy source to destination or with transparent
|
|
|
|
@retval EFI_SUCCESS BitBlt is successful
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SetupMouseStretchBlt (
|
|
INTN DstX,
|
|
INTN DstY,
|
|
UINTN DstWidth,
|
|
UINTN DstHeight,
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *SrcBlt,
|
|
INTN SrcX,
|
|
INTN SrcY,
|
|
UINTN SrcWidth,
|
|
UINTN SrcHeight,
|
|
INT32 SrcDelta,
|
|
UINT16 Rop
|
|
)
|
|
{
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *KeyboardBlt;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *KeyboardBuffer;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
|
|
INTN X;
|
|
INTN Y;
|
|
INT32 KeyboardWidth;
|
|
INT32 KeyboardHeight;
|
|
|
|
KeyboardWidth = mPrivate->Keyboard.ImageRc.right - mPrivate->Keyboard.ImageRc.left;
|
|
KeyboardHeight = mPrivate->Keyboard.ImageRc.bottom - mPrivate->Keyboard.ImageRc.top;
|
|
|
|
if (SrcWidth != DstWidth || SrcHeight != DstHeight) {
|
|
SetupMouseStretchBlitEx (
|
|
mPrivate->Keyboard.Image,
|
|
(INT32)DstX,
|
|
(INT32)DstY,
|
|
(INT32)DstX + (INT32)DstWidth,
|
|
(INT32)DstY + (INT32)DstHeight,
|
|
(INT32)KeyboardWidth,
|
|
SrcBlt,
|
|
(INT32)SrcX,
|
|
(INT32)SrcY,
|
|
(INT32)SrcX + (INT32)SrcWidth,
|
|
(INT32)SrcY + (INT32)SrcHeight,
|
|
SrcDelta / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
|
|
);
|
|
} else {
|
|
KeyboardBuffer = mPrivate->Keyboard.Image + DstY * KeyboardWidth + DstX;
|
|
BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *) SrcBlt + SrcY * SrcDelta + SrcX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
|
|
Y = SrcHeight;
|
|
while (--Y >= 0) {
|
|
KeyboardBlt = KeyboardBuffer;
|
|
Blt = BltBuffer;
|
|
|
|
X = SrcWidth;
|
|
while (--X >= 0) {
|
|
if (*(UINT32 *)Blt != 0) {
|
|
BlendPixel (KeyboardBlt, Blt);
|
|
}
|
|
KeyboardBlt++;
|
|
Blt ++;
|
|
}
|
|
|
|
KeyboardBuffer += KeyboardWidth;
|
|
BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)BltBuffer + SrcDelta);
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Scale image by Scale9Grid algorithm
|
|
|
|
@param [in] DstRc Destination Rectangle
|
|
@param [in] Scale9Grid scale 9 grid
|
|
@param [in] ImageBlt Image Blt buffer
|
|
@param [in] ImageWidth
|
|
@param [in] ImageHeight
|
|
@param [in] ImageDelta
|
|
|
|
@retval None
|
|
|
|
**/
|
|
VOID
|
|
SetupMouseDrawImage (
|
|
IN RECT *DstRc,
|
|
IN RECT *Scale9Grid,
|
|
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ImageBlt,
|
|
IN INT32 ImageWidth,
|
|
IN INT32 ImageHeight,
|
|
IN INT32 ImageDelta
|
|
)
|
|
{
|
|
|
|
RECT DstHoldDstRc;
|
|
RECT SrcHoldDstRc;
|
|
|
|
//
|
|
//
|
|
//
|
|
DstHoldDstRc.left = DstRc->left + Scale9Grid->left;
|
|
DstHoldDstRc.top = DstRc->top + Scale9Grid->top;
|
|
DstHoldDstRc.right = DstRc->right - Scale9Grid->right;
|
|
DstHoldDstRc.bottom = DstRc->bottom - Scale9Grid->bottom;
|
|
|
|
SrcHoldDstRc.left = Scale9Grid->left;
|
|
SrcHoldDstRc.top = Scale9Grid->top;
|
|
SrcHoldDstRc.right = ImageWidth - Scale9Grid->right;
|
|
SrcHoldDstRc.bottom = ImageHeight - Scale9Grid->bottom;
|
|
|
|
//
|
|
// hold
|
|
//
|
|
SetupMouseStretchBlt (
|
|
DstHoldDstRc.left, DstHoldDstRc.top, DstHoldDstRc.right - DstHoldDstRc.left, DstHoldDstRc.bottom - DstHoldDstRc.top,
|
|
ImageBlt, SrcHoldDstRc.left, SrcHoldDstRc.top, SrcHoldDstRc.right - SrcHoldDstRc.left, SrcHoldDstRc.bottom - SrcHoldDstRc.top,
|
|
ImageDelta, 0
|
|
);
|
|
|
|
|
|
//
|
|
// left - top
|
|
//
|
|
SetupMouseStretchBlt (
|
|
DstRc->left, DstRc->top, Scale9Grid->left, Scale9Grid->top,
|
|
ImageBlt, 0, 0, Scale9Grid->left, Scale9Grid->top,
|
|
ImageDelta, 0
|
|
);
|
|
|
|
|
|
//
|
|
// right - top
|
|
//
|
|
SetupMouseStretchBlt (
|
|
DstHoldDstRc.right, DstRc->top, Scale9Grid->right, Scale9Grid->top,
|
|
ImageBlt, SrcHoldDstRc.right, 0, Scale9Grid->right, Scale9Grid->top,
|
|
ImageDelta, 0
|
|
);
|
|
|
|
//
|
|
// left - bottom
|
|
//
|
|
SetupMouseStretchBlt (
|
|
DstRc->left, DstHoldDstRc.bottom, Scale9Grid->left, Scale9Grid->bottom,
|
|
ImageBlt, 0, SrcHoldDstRc.bottom, Scale9Grid->left, Scale9Grid->bottom,
|
|
ImageDelta, 0
|
|
);
|
|
|
|
|
|
//
|
|
// right - bottom
|
|
//
|
|
SetupMouseStretchBlt (
|
|
DstHoldDstRc.right, DstHoldDstRc.bottom, Scale9Grid->right, Scale9Grid->bottom,
|
|
ImageBlt, SrcHoldDstRc.right, SrcHoldDstRc.bottom, Scale9Grid->right, Scale9Grid->bottom,
|
|
ImageDelta, 0
|
|
);
|
|
|
|
//
|
|
// top
|
|
//
|
|
SetupMouseStretchBlt (
|
|
DstHoldDstRc.left, DstRc->top, DstHoldDstRc.right - DstHoldDstRc.left, Scale9Grid->top,
|
|
ImageBlt, SrcHoldDstRc.left, 0, SrcHoldDstRc.right - SrcHoldDstRc.left, Scale9Grid->top,
|
|
ImageDelta, 0
|
|
);
|
|
|
|
|
|
//
|
|
// left
|
|
//
|
|
SetupMouseStretchBlt (
|
|
DstRc->left, DstHoldDstRc.top, Scale9Grid->left, DstHoldDstRc.bottom - DstHoldDstRc.top,
|
|
ImageBlt, 0, SrcHoldDstRc.top, Scale9Grid->left, SrcHoldDstRc.bottom - SrcHoldDstRc.top,
|
|
ImageDelta, 0
|
|
);
|
|
|
|
//
|
|
// right
|
|
//
|
|
SetupMouseStretchBlt (
|
|
DstHoldDstRc.right, DstHoldDstRc.top, Scale9Grid->right, DstHoldDstRc.bottom - DstHoldDstRc.top,
|
|
ImageBlt, SrcHoldDstRc.right, SrcHoldDstRc.top, Scale9Grid->right, SrcHoldDstRc.bottom - SrcHoldDstRc.top,
|
|
ImageDelta, 0
|
|
);
|
|
|
|
//
|
|
// bottom
|
|
//
|
|
SetupMouseStretchBlt (
|
|
DstHoldDstRc.left, DstHoldDstRc.bottom, DstHoldDstRc.right - DstHoldDstRc.left, Scale9Grid->bottom,
|
|
ImageBlt, SrcHoldDstRc.left, SrcHoldDstRc.bottom, SrcHoldDstRc.right - SrcHoldDstRc.left, Scale9Grid->bottom,
|
|
ImageDelta, 0
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
Scale image by Scale9Grid algorithm
|
|
|
|
@param DstRc Destination Rectangle
|
|
@param Scale9Grid scale 9 grid
|
|
@param ImageId
|
|
|
|
@retval None
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SetupMouseShowBitmap (
|
|
RECT *DstRc,
|
|
RECT *Scale9Grid,
|
|
UINT16 ImageId
|
|
)
|
|
{
|
|
INT32 Width;
|
|
INT32 Height;
|
|
EFI_STATUS Status;
|
|
IMAGE_INFO BitmapImage;
|
|
INT32 KeyboardWidth;
|
|
INT32 KeyboardHeight;
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
EFI_IMAGE_INPUT Image;
|
|
|
|
Private = mPrivate;
|
|
|
|
if (mImageHiiHandle == NULL) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
|
|
Status = gHiiImage->GetImage (
|
|
gHiiImage,
|
|
mImageHiiHandle,
|
|
ImageId,
|
|
&Image
|
|
);
|
|
if (EFI_ERROR (Status) || Image.Bitmap == NULL) {
|
|
return Status;
|
|
}
|
|
|
|
if ((Image.Flags & H2O_IMAGE_ALPHA_CHANNEL) != H2O_IMAGE_ALPHA_CHANNEL) {
|
|
ConvertToAlphaChannelImage (&Image);
|
|
}
|
|
|
|
Width = MIN ((DstRc->right - DstRc->left), (INT32) Image.Width);
|
|
Height = MIN ((DstRc->bottom - DstRc->top), (INT32) Image.Height);
|
|
|
|
KeyboardWidth = Private->Keyboard.ImageRc.right - Private->Keyboard.ImageRc.left;
|
|
KeyboardHeight = Private->Keyboard.ImageRc.bottom - Private->Keyboard.ImageRc.top;
|
|
BitmapImage.Image = Image.Bitmap;
|
|
SetRect (&BitmapImage.ImageRc, 0, 0, Image.Width, Image.Height);
|
|
|
|
if (Scale9Grid->left == 0 && Scale9Grid->right == 0 && Scale9Grid->top == 0 && Scale9Grid->bottom == 0) {
|
|
SetupMouseBitBlt (
|
|
&Private->Keyboard,
|
|
DstRc->left,
|
|
DstRc->top,
|
|
Width,
|
|
Height,
|
|
&BitmapImage,
|
|
0,
|
|
0,
|
|
ROP_TRANSPARENT
|
|
);
|
|
} else {
|
|
SetupMouseDrawImage (
|
|
DstRc,
|
|
Scale9Grid,
|
|
Image.Bitmap,
|
|
(INT32) Image.Width,
|
|
(INT32) Image.Height,
|
|
sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Image.Width
|
|
);
|
|
}
|
|
FreePool (Image.Bitmap);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
AcquireSetupMouseLock (
|
|
PRIVATE_MOUSE_DATA *Private
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
Status = EfiAcquireLockOrFail (&Private->SetupMouseLock);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
VOID
|
|
ReleaseSetupMouseLock (
|
|
PRIVATE_MOUSE_DATA *Private
|
|
)
|
|
{
|
|
EfiReleaseLock (&Private->SetupMouseLock);
|
|
}
|
|
|