879 lines
23 KiB
C
879 lines
23 KiB
C
/** @file
|
|
UI Render
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2018, 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 <Protocol/H2OWindow.h>
|
|
#include "UiRender.h"
|
|
#include "UiControls.h"
|
|
#include "UiManager.h"
|
|
#include "H2ODisplayEngineLocalMetro.h"
|
|
#include "MetroUi.h"
|
|
|
|
#include <Protocol/SimpleFileSystem.h>
|
|
#include <Library/UefiHiiServicesLib.h>
|
|
|
|
CHAR16 *
|
|
AppendEllipsisStr (
|
|
IN HDC Hdc,
|
|
IN CHAR16 *String,
|
|
IN UINTN StringLen,
|
|
IN UINTN LimitWidth
|
|
)
|
|
{
|
|
SIZE Size;
|
|
UINTN EllipsisStrIndex;
|
|
CHAR16 EllipsisStr[] = L"...";
|
|
CHAR16 *ResultStr;
|
|
|
|
if (String == NULL ||
|
|
StringLen < (sizeof (EllipsisStr) / sizeof (CHAR16) - 1) ||
|
|
LimitWidth < (sizeof (EllipsisStr) / sizeof (CHAR16) - 1)) {
|
|
return NULL;
|
|
}
|
|
|
|
ResultStr = AllocateZeroPool (StringLen * sizeof (CHAR16) + sizeof (EllipsisStr));
|
|
if (ResultStr == NULL) {
|
|
return NULL;
|
|
}
|
|
EllipsisStrIndex = StringLen;
|
|
CopyMem (ResultStr , String , StringLen * sizeof (CHAR16));
|
|
CopyMem (ResultStr + EllipsisStrIndex, EllipsisStr, sizeof (EllipsisStr));
|
|
|
|
while (TRUE) {
|
|
Size.cx = 0;
|
|
GetTextExtentPoint32 (Hdc, ResultStr, (int) StrLen (ResultStr), &Size);
|
|
if (Size.cx == 0) {
|
|
break;
|
|
}
|
|
|
|
if (Size.cx <= (GDICOORD) LimitWidth) {
|
|
return ResultStr;
|
|
}
|
|
|
|
if (EllipsisStrIndex == 0) {
|
|
break;
|
|
}
|
|
|
|
EllipsisStrIndex--;
|
|
CopyMem (ResultStr + EllipsisStrIndex, EllipsisStr, sizeof (EllipsisStr));
|
|
}
|
|
|
|
FreePool (ResultStr);
|
|
return NULL;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
UiFastFillRect (
|
|
IN HDC Hdc,
|
|
IN RECT *Rc,
|
|
IN COLORREF Color
|
|
)
|
|
{
|
|
|
|
MwFastFillRect (Hdc, Rc, Color);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
UiPaintGradient (
|
|
IN HDC Hdc,
|
|
RECT *Rc,
|
|
COLORREF Color1,
|
|
COLORREF Color2,
|
|
BOOLEAN Vertical,
|
|
UINT32 Steps
|
|
)
|
|
{
|
|
UINT32 Shift;
|
|
UINT32 Lines;
|
|
UINT8 R, G, B;
|
|
UINTN i;
|
|
|
|
HBRUSH hBrush;
|
|
HBRUSH hOldBrush;
|
|
RECT Rc2;
|
|
|
|
|
|
Shift = 1;
|
|
// Determine how many shades
|
|
if( Steps >= 64 ) Shift = 6;
|
|
else if( Steps >= 32 ) Shift = 5;
|
|
else if( Steps >= 16 ) Shift = 4;
|
|
else if( Steps >= 8 ) Shift = 3;
|
|
else if( Steps >= 4 ) Shift = 2;
|
|
|
|
Lines = 1 << Shift;
|
|
|
|
hBrush = GetStockObject (DC_BRUSH);
|
|
hOldBrush = SelectObject (Hdc, hBrush);
|
|
|
|
for(i = 0; i < Lines; i++ ) {
|
|
// Do a little alpha blending
|
|
R = (UINT8)((GetRValue (Color1) * (Lines - i) + GetRValue (Color2) * i) >> Shift);
|
|
G = (UINT8)((GetGValue (Color1) * (Lines - i) + GetGValue (Color2) * i) >> Shift);
|
|
B = (UINT8)((GetBValue (Color1) * (Lines - i) + GetBValue (Color2) * i) >> Shift);
|
|
// ... then paint with the resulting color
|
|
SetDCBrushColor (Hdc, RGB (R, G, B));
|
|
Rc2 = *Rc;
|
|
|
|
if( Vertical ) {
|
|
Rc2.bottom = Rc->bottom - (((UINT32)i * (Rc->bottom - Rc->top)) >> Shift);
|
|
Rc2.top = Rc->bottom - (((UINT32)(i + 1) * (Rc->bottom - Rc->top)) >> Shift);
|
|
if((Rc2.bottom - Rc2.top) > 0) {
|
|
FillRect (Hdc, &Rc2, hBrush);
|
|
}
|
|
}
|
|
else {
|
|
Rc2.left = Rc->right - (((UINT32)(i + 1) * (Rc->right - Rc->left)) >> Shift);
|
|
Rc2.right = Rc->right - (((UINT32)i * (Rc->right - Rc->left)) >> Shift);
|
|
if((Rc2.right - Rc2.left) > 0) {
|
|
FillRect (Hdc, &Rc2, hBrush);
|
|
}
|
|
}
|
|
}
|
|
|
|
SelectObject (Hdc, hOldBrush);
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
INT32
|
|
EFIAPI
|
|
UiPaintText (
|
|
IN HDC Hdc,
|
|
IN UINT32 FontSize,
|
|
RECT *Rc,
|
|
CHAR16 *String,
|
|
COLORREF TextColor,
|
|
COLORREF BackColor,
|
|
UINT32 Style
|
|
)
|
|
{
|
|
BOOLEAN bDraw;
|
|
POINT pt;
|
|
UINT32 cyline;
|
|
HDC TempHdc;
|
|
UINT8 ColorIndex;
|
|
COLORREF ColorArray[10];
|
|
COLORREF Color;
|
|
|
|
UINT8 FontSizeIndex;
|
|
UINT32 FontSizeArray[10];
|
|
UINT32 CurrentFontSize;
|
|
INT32 Offset;
|
|
BOOLEAN IsHtmlText;
|
|
|
|
ColorIndex = 0;
|
|
FontSizeIndex = 0;
|
|
IsHtmlText = (BOOLEAN)((Style & DT_HTML_TEXT) != 0);
|
|
|
|
if(IsRectEmpty(Rc)) return 0;
|
|
|
|
ASSERT (((Style & DT_CALCRECT) != 0) || Hdc != NULL);
|
|
if (((Style & DT_CALCRECT) == 0) && Hdc == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
TempHdc = NULL;
|
|
if (((Style & DT_CALCRECT) != 0) && Hdc == NULL) {
|
|
TempHdc = CreateCompatibleDC (NULL);
|
|
Hdc = TempHdc;
|
|
}
|
|
|
|
Hdc->font->FontSize = FontSize;
|
|
|
|
bDraw = ((Style & DT_CALCRECT) == 0);
|
|
// If the drawstyle includes an alignment, we'll need to first determine the text-size so
|
|
// we can draw it at the correct position...
|
|
if( (Style & DT_SINGLELINE) != 0 && (Style & DT_VCENTER) != 0 && (Style & DT_CALCRECT) == 0 ) {
|
|
RECT rcText = { 0, 0, 9999, 100 };
|
|
UiPaintText (Hdc, FontSize, &rcText, String, TextColor, BackColor, Style | DT_CALCRECT);
|
|
Rc->top = Rc->top + ((Rc->bottom - Rc->top) / 2) - ((rcText.bottom - rcText.top) / 2);
|
|
Rc->bottom = Rc->top + (rcText.bottom - rcText.top);
|
|
}
|
|
if( (Style & DT_SINGLELINE) != 0 && (Style & DT_CENTER) != 0 && (Style & DT_CALCRECT) == 0 ) {
|
|
RECT rcText = { 0, 0, 9999, 100 };
|
|
UiPaintText (Hdc, FontSize, &rcText, String, TextColor, BackColor, Style | DT_CALCRECT);
|
|
Offset = (Rc->right - Rc->left) / 2 - (rcText.right - rcText.left) / 2;
|
|
if (Offset < 0) {
|
|
OffsetRect (Rc, 0, 0);
|
|
} else {
|
|
OffsetRect (Rc, Offset, 0);
|
|
}
|
|
}
|
|
if( (Style & DT_SINGLELINE) != 0 && (Style & DT_RIGHT) != 0 && (Style & DT_CALCRECT) == 0 ) {
|
|
RECT rcText = { 0, 0, 9999, 100 };
|
|
UiPaintText (Hdc, FontSize, &rcText, String, TextColor, BackColor, Style | DT_CALCRECT);
|
|
Rc->left = ((rcText.right - rcText.left) < (Rc->right - Rc->left)) ? Rc->right - (rcText.right - rcText.left) : Rc->left;
|
|
}
|
|
|
|
if( (Style & DT_SINGLELINE) != 0 && (Style & DT_BOTTOM) != 0 && (Style & DT_CALCRECT) == 0 ) {
|
|
RECT rcText;
|
|
SetRect (&rcText, 0, 0, Rc->right, 9999);
|
|
UiPaintText (Hdc, FontSize, &rcText, String, TextColor, BackColor, Style | DT_CALCRECT);
|
|
Rc->top = Rc->bottom - (rcText.bottom - rcText.top);
|
|
}
|
|
|
|
if ((Style & DT_CALCRECT) == 0) {
|
|
SetBkMode(Hdc, TRANSPARENT);
|
|
SetTextColor (Hdc, TextColor);
|
|
if (BackColor != INVALID_COLOR) {
|
|
UiFastFillRect (Hdc, Rc, BackColor);
|
|
}
|
|
}
|
|
|
|
pt.x = Rc->left;
|
|
pt.y = Rc->top;
|
|
cyline = Hdc->font->FontSize;
|
|
|
|
while (*String != '\0') {
|
|
|
|
if (pt.x >= Rc->right || *String == '\n') {
|
|
//
|
|
// \n or word wrap
|
|
//
|
|
if ((Style & DT_SINGLELINE) != 0) break;
|
|
if ((Style & DT_END_ELLIPSIS) != 0 && ((pt.y + (INT32 )cyline) >= Rc->bottom)) break;
|
|
if (*String == '\n') {
|
|
String++;
|
|
}
|
|
pt.x = Rc->left;
|
|
pt.y += cyline;
|
|
if (pt.x >= Rc->right) {
|
|
break;
|
|
}
|
|
|
|
cyline = Hdc->font->FontSize;
|
|
|
|
while (*String == ' ') String++;
|
|
|
|
} else if (IsHtmlText && ((*String == '<') &&
|
|
(*(String + 1) >= 'a' && *(String + 1) <= 'z') &&
|
|
(*(String + 2) == ' ' || *(String + 2) == '>'))) {
|
|
|
|
String++;
|
|
|
|
switch (*String) {
|
|
|
|
case 'f':
|
|
String++;
|
|
CurrentFontSize = 19;
|
|
while (*String > '\0' && *String <= ' ') String++;
|
|
if (isdigit(*String)) {
|
|
CurrentFontSize = wcstol (String, &String, 10);
|
|
}
|
|
while (*String > '\0' && *String <= ' ') String++;
|
|
|
|
ASSERT (FontSizeIndex < (sizeof (FontSizeArray) / sizeof (FontSizeArray[0])));
|
|
FontSizeArray[FontSizeIndex++] = Hdc->font->FontSize;
|
|
|
|
Hdc->font->FontSize = CurrentFontSize;
|
|
|
|
cyline = MAX (cyline, CurrentFontSize);
|
|
break;
|
|
|
|
case 'c':
|
|
String++;
|
|
while (*String > '\0' && *String <= ' ') String++;
|
|
Color = wcstoul (String, &String, 16);
|
|
|
|
ASSERT (ColorIndex < (sizeof (ColorArray) / sizeof (ColorArray[0])));
|
|
ColorArray[ColorIndex++] = GetTextColor (Hdc);
|
|
SetTextColor (Hdc, Color);
|
|
break;
|
|
}
|
|
|
|
while (*String != '\0' && *String != '>') {
|
|
String++;
|
|
}
|
|
if (*String == '>') {
|
|
String++;
|
|
}
|
|
} else if(IsHtmlText && ((*String == '<') && (*(String + 1) == '/') &&
|
|
(*(String + 2) == 'f' || *(String + 2) == 'c') &&
|
|
(*(String + 3) == '>'))) {
|
|
|
|
String++;
|
|
String++;
|
|
switch(*String) {
|
|
|
|
case 'f':
|
|
ASSERT (FontSizeIndex > 0);
|
|
if (FontSizeIndex == 0) {
|
|
if (TempHdc != NULL) {
|
|
DeleteDC (TempHdc);
|
|
}
|
|
return 0;
|
|
}
|
|
CurrentFontSize = FontSizeArray[--FontSizeIndex];
|
|
Hdc->font->FontSize = CurrentFontSize;
|
|
cyline = MAX (cyline, Hdc->font->FontSize);
|
|
break;
|
|
|
|
case 'c':
|
|
ASSERT (ColorIndex > 0);
|
|
if (ColorIndex == 0) {
|
|
if (TempHdc != NULL) {
|
|
DeleteDC (TempHdc);
|
|
}
|
|
return 0;
|
|
}
|
|
SetTextColor (Hdc, ColorArray[--ColorIndex]);
|
|
break;
|
|
}
|
|
|
|
String += 2;
|
|
} else {
|
|
|
|
POINT ptPos = pt;
|
|
int cchChars = 0;
|
|
CHAR16 *ModifiedStr;
|
|
int cchLastGoodWord = 0;
|
|
CHAR16 *p = (CHAR16 *)String;
|
|
SIZE szText = { 0 };
|
|
SIZE Size;
|
|
INT32 CharMaxWidth;
|
|
INT32 LineWidth;
|
|
|
|
|
|
if(IsHtmlText && (*p == '<')) {
|
|
p++, cchChars++;
|
|
}
|
|
|
|
CharMaxWidth = cyline;
|
|
while (*p != '\0' && *p != '\n' && ((*p != '<') || !IsHtmlText)) {
|
|
cchChars++;
|
|
|
|
szText.cx = cchChars * CharMaxWidth;
|
|
if (pt.x + szText.cx >= Rc->right) {
|
|
GetTextExtentPoint32 (Hdc, String, cchChars, &Size);
|
|
szText.cx = Size.cx;
|
|
}
|
|
|
|
if(pt.x + szText.cx > Rc->right ) {
|
|
if( (Style & DT_WORDBREAK) != 0) {
|
|
if (cchLastGoodWord > 0 ) {
|
|
cchChars = cchLastGoodWord;
|
|
pt.x = Rc->right;
|
|
} else {
|
|
cchChars--;
|
|
p--;
|
|
pt.x = Rc->right;
|
|
}
|
|
} else {
|
|
cchChars--;
|
|
p--;
|
|
pt.x = Rc->right;
|
|
}
|
|
break;
|
|
}
|
|
if( *p == ' ' ) cchLastGoodWord = cchChars;
|
|
p++;
|
|
}
|
|
|
|
if (cchChars > 0) {
|
|
GetTextExtentPoint32 (Hdc, String, cchChars, &Size);
|
|
if (bDraw) {
|
|
if (((Style & DT_CENTER) != 0) && ((Style & DT_SINGLELINE) == 0)) {
|
|
LineWidth = Rc->right - Rc->left;
|
|
LineWidth -= Size.cx;
|
|
if (LineWidth != 0) {
|
|
LineWidth /= 2;
|
|
}
|
|
TextOut (Hdc, ptPos.x + LineWidth, ptPos.y, String, cchChars);
|
|
} else {
|
|
if ((Style & DT_SINGLELINE) != 0 && (Style & DT_END_ELLIPSIS) != 0 && (pt.x == Rc->right) ||
|
|
((Style & DT_SINGLELINE) == 0 && (Style & DT_END_ELLIPSIS) != 0 && (pt.x == Rc->right) && (pt.y + (INT32 )cyline) >= Rc->bottom)) {
|
|
ModifiedStr = AppendEllipsisStr (Hdc, String, cchChars, (UINTN) (Rc->right - Rc->left));
|
|
if (ModifiedStr != NULL) {
|
|
TextOut (Hdc, ptPos.x, ptPos.y, ModifiedStr, (int) StrLen (ModifiedStr));
|
|
FreePool (ModifiedStr);
|
|
} else {
|
|
TextOut (Hdc, ptPos.x, ptPos.y, String, cchChars);
|
|
}
|
|
} else {
|
|
TextOut (Hdc, ptPos.x, ptPos.y, String, cchChars);
|
|
}
|
|
}
|
|
}
|
|
pt.x += Size.cx;
|
|
String += cchChars;
|
|
}
|
|
}
|
|
}
|
|
|
|
if((Style & DT_CALCRECT) != 0) {
|
|
Rc->bottom = pt.y + cyline;
|
|
if (Rc->right >= 9999) {
|
|
if (StrLen ((CHAR16 *)String) > 0) pt.x += 3;
|
|
Rc->right = pt.x;
|
|
}
|
|
Rc->right = pt.x;
|
|
}
|
|
|
|
if((Style & DT_CALCRECT) == 0) {
|
|
// SelectClipRgn(Hdc, OldRgn);
|
|
// DeleteObject(OldRgn);
|
|
// DeleteObject(NewRgn);
|
|
}
|
|
|
|
if (TempHdc != NULL) {
|
|
DeleteDC (TempHdc);
|
|
}
|
|
|
|
return (pt.y == 0) ? pt.x : Rc->right;
|
|
|
|
}
|
|
/*
|
|
EFI_STATUS
|
|
LoadDataFromFile (
|
|
CHAR16 *FileName,
|
|
UINT8 **Data,
|
|
UINTN *Length
|
|
)
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN NumberOfHandles;
|
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFile;
|
|
UINTN Index;
|
|
EFI_FILE *Root, *File;
|
|
UINT64 Pos;
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiSimpleFileSystemProtocolGuid,
|
|
NULL,
|
|
&NumberOfHandles,
|
|
&HandleBuffer
|
|
);
|
|
|
|
*Data = NULL;
|
|
|
|
for (Index = 0; Index < NumberOfHandles; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiSimpleFileSystemProtocolGuid,
|
|
(VOID **) &SimpleFile
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = SimpleFile->OpenVolume (SimpleFile, &Root);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = Root->Open (Root, &File, FileName, EFI_FILE_MODE_READ, 0);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = File->SetPosition (File, (UINT64)-1);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
File->GetPosition (File, &Pos);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
File->SetPosition (File, 0);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
*Length = (UINTN) Pos;
|
|
|
|
*Data = AllocatePool (*Length);
|
|
|
|
File->Read (File, Length, *Data);
|
|
File->Close (File);
|
|
Root->Close (Root);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}*/
|
|
|
|
VOID
|
|
UiDrawImage (
|
|
IN PSD psd,
|
|
IN RECT *Rc,
|
|
IN RECT *Scale9Grid,
|
|
IN PSD pmd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Scale image by Scale9Grid algorithm
|
|
|
|
Arguments:
|
|
This - Ui render
|
|
Hwnd - window handle
|
|
Hdc - window device content
|
|
Rc - window rect
|
|
Scale9Grid - scale 9 grid
|
|
Image - image
|
|
ImageDC - image dc
|
|
|
|
Returns:
|
|
None
|
|
|
|
--*/
|
|
{
|
|
|
|
RECT DstHoldRc;
|
|
RECT SrcHoldRc;
|
|
|
|
DstHoldRc.left = Rc->left + Scale9Grid->left;
|
|
DstHoldRc.top = Rc->top + Scale9Grid->top;
|
|
DstHoldRc.right = Rc->right - Scale9Grid->right;
|
|
DstHoldRc.bottom = Rc->bottom - Scale9Grid->bottom;
|
|
|
|
SrcHoldRc.left = Scale9Grid->left;
|
|
SrcHoldRc.top = Scale9Grid->top;
|
|
SrcHoldRc.right = pmd->xvirtres - Scale9Grid->right;
|
|
SrcHoldRc.bottom = pmd->yvirtres - Scale9Grid->bottom;
|
|
|
|
//
|
|
// hold
|
|
//
|
|
if (SrcHoldRc.right != SrcHoldRc.left && SrcHoldRc.bottom != SrcHoldRc.top) {
|
|
GdDrawImagePartToFit (
|
|
psd,
|
|
DstHoldRc.left, DstHoldRc.top, DstHoldRc.right - DstHoldRc.left, DstHoldRc.bottom - DstHoldRc.top,
|
|
SrcHoldRc.left, SrcHoldRc.top, SrcHoldRc.right - SrcHoldRc.left, SrcHoldRc.bottom - SrcHoldRc.top,
|
|
pmd
|
|
);
|
|
}
|
|
|
|
//
|
|
// left - top
|
|
//
|
|
if (Scale9Grid->left != 0 && Scale9Grid->top != 0) {
|
|
GdDrawImagePartToFit (
|
|
psd,
|
|
Rc->left, Rc->top, Scale9Grid->left, Scale9Grid->top,
|
|
0, 0, Scale9Grid->left, Scale9Grid->top,
|
|
pmd
|
|
);
|
|
}
|
|
|
|
//
|
|
// right - top
|
|
//
|
|
if (Scale9Grid->right != 0 && Scale9Grid->top != 0) {
|
|
GdDrawImagePartToFit (
|
|
psd,
|
|
DstHoldRc.right, Rc->top, Scale9Grid->right, Scale9Grid->top,
|
|
SrcHoldRc.right, 0, Scale9Grid->right, Scale9Grid->top,
|
|
pmd
|
|
);
|
|
}
|
|
|
|
//
|
|
// left - bottom
|
|
//
|
|
if (Scale9Grid->left != 0 && Scale9Grid->bottom != 0) {
|
|
GdDrawImagePartToFit (
|
|
psd,
|
|
Rc->left, DstHoldRc.bottom, Scale9Grid->left, Scale9Grid->bottom,
|
|
0, SrcHoldRc.bottom, Scale9Grid->left, Scale9Grid->bottom,
|
|
pmd
|
|
);
|
|
}
|
|
|
|
//
|
|
// right - bottom
|
|
//
|
|
if (Scale9Grid->right != 0 && Scale9Grid->bottom != 0) {
|
|
GdDrawImagePartToFit (
|
|
psd,
|
|
DstHoldRc.right, DstHoldRc.bottom, Scale9Grid->right, Scale9Grid->bottom,
|
|
SrcHoldRc.right, SrcHoldRc.bottom, Scale9Grid->right, Scale9Grid->bottom,
|
|
pmd
|
|
);
|
|
}
|
|
|
|
//
|
|
// top
|
|
//
|
|
if (SrcHoldRc.right != SrcHoldRc.left && Scale9Grid->top != 0) {
|
|
GdDrawImagePartToFit (
|
|
psd,
|
|
DstHoldRc.left, Rc->top, DstHoldRc.right - DstHoldRc.left, Scale9Grid->top,
|
|
SrcHoldRc.left, 0, SrcHoldRc.right - SrcHoldRc.left, Scale9Grid->top,
|
|
pmd
|
|
);
|
|
}
|
|
|
|
//
|
|
// left
|
|
//
|
|
if (SrcHoldRc.left != 0 && SrcHoldRc.bottom != SrcHoldRc.top) {
|
|
GdDrawImagePartToFit (
|
|
psd,
|
|
Rc->left, DstHoldRc.top, Scale9Grid->left, DstHoldRc.bottom - DstHoldRc.top,
|
|
0, SrcHoldRc.top, Scale9Grid->left, SrcHoldRc.bottom - SrcHoldRc.top,
|
|
pmd
|
|
);
|
|
}
|
|
|
|
//
|
|
// right
|
|
//
|
|
if (Scale9Grid->right != 0 && SrcHoldRc.bottom != SrcHoldRc.top) {
|
|
GdDrawImagePartToFit (
|
|
psd,
|
|
DstHoldRc.right, DstHoldRc.top, Scale9Grid->right, DstHoldRc.bottom - DstHoldRc.top,
|
|
SrcHoldRc.right, SrcHoldRc.top, Scale9Grid->right, SrcHoldRc.bottom - SrcHoldRc.top,
|
|
pmd
|
|
);
|
|
}
|
|
|
|
//
|
|
// bottom
|
|
//
|
|
if (SrcHoldRc.right != SrcHoldRc.left && Scale9Grid->bottom != 0) {
|
|
GdDrawImagePartToFit (
|
|
psd,
|
|
DstHoldRc.left, DstHoldRc.bottom, DstHoldRc.right - DstHoldRc.left, Scale9Grid->bottom,
|
|
SrcHoldRc.left, SrcHoldRc.bottom, SrcHoldRc.right - SrcHoldRc.left, Scale9Grid->bottom,
|
|
pmd
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
EFI_IMAGE_INPUT *
|
|
CreateHsvAdjustImage (
|
|
IN CONST EFI_IMAGE_INPUT *ImageIn,
|
|
IN CONST HSV_DIFF_VALUE *HsvDiff
|
|
)
|
|
{
|
|
EFI_IMAGE_INPUT *Image;
|
|
UINTN BufferLen;
|
|
INTN Index;
|
|
HSV_VALUE Hsv;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitmapIn;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitmapOut;
|
|
|
|
|
|
|
|
ASSERT (ImageIn != NULL && HsvDiff != NULL);
|
|
if (ImageIn == NULL || HsvDiff == NULL) {
|
|
return NULL;
|
|
}
|
|
if (HsvDiff->HueDiff == 0 && HsvDiff->SaturationDiff == 0 && HsvDiff->ValueDiff == 0) {
|
|
return NULL;
|
|
}
|
|
Image = AllocateCopyPool (sizeof (EFI_IMAGE_INPUT), ImageIn);
|
|
ASSERT (Image != NULL);
|
|
if (Image == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
BufferLen = ImageIn->Width * ImageIn->Height;
|
|
Image->Bitmap = AllocatePool (BufferLen * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
ASSERT (Image->Bitmap != NULL);
|
|
if (Image->Bitmap == NULL) {
|
|
FreePool (Image);
|
|
return NULL;
|
|
}
|
|
|
|
Index = BufferLen;
|
|
BitmapIn = ImageIn->Bitmap;
|
|
BitmapOut = Image->Bitmap;
|
|
|
|
while (--Index >= 0) {
|
|
if (BitmapIn->Reserved != 0) {
|
|
RGB2HSV (BitmapIn, &Hsv);
|
|
if (Hsv.Hue + HsvDiff->HueDiff < 0) {
|
|
Hsv.Hue = (UINT16) Hsv.Hue + HsvDiff->HueDiff + 360;
|
|
} else {
|
|
Hsv.Hue = (UINT16) (Hsv.Hue + HsvDiff->HueDiff);
|
|
Hsv.Hue = Hsv.Hue > 360 ? Hsv.Hue - 360 : Hsv.Hue;
|
|
}
|
|
Hsv.Saturation = (UINT8) (Hsv.Saturation + HsvDiff->SaturationDiff);
|
|
Hsv.Saturation = Hsv.Saturation > 100 ? 100 : Hsv.Saturation;
|
|
Hsv.Value = (UINT8) (Hsv.Value + HsvDiff->ValueDiff);
|
|
Hsv.Value = Hsv.Value > 100 ? 100 : Hsv.Value;
|
|
HSV2RGB (&Hsv, BitmapOut);
|
|
BitmapOut->Reserved = BitmapIn->Reserved;
|
|
} else {
|
|
*(UINT32 *)BitmapOut = 0;
|
|
}
|
|
++BitmapIn;
|
|
++BitmapOut;
|
|
}
|
|
|
|
return Image;
|
|
}
|
|
|
|
EFI_IMAGE_INPUT *
|
|
CreateStyleAdjustImage (
|
|
IN CONST EFI_IMAGE_INPUT *ImageIn,
|
|
IN CONST UINT32 Style
|
|
)
|
|
{
|
|
EFI_IMAGE_INPUT *Image;
|
|
UINTN BufferLen;
|
|
INTN Index;
|
|
UINT32 *BitmapIn;
|
|
UINT32 *BitmapOut;
|
|
|
|
ASSERT (ImageIn != NULL);
|
|
ASSERT ((Style & (DT_GRAY | DT_LIGHT)) != (DT_GRAY | DT_LIGHT));
|
|
if ((Style & (DT_GRAY | DT_LIGHT)) == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
Image = AllocateCopyPool (sizeof (EFI_IMAGE_INPUT), ImageIn);
|
|
ASSERT (Image != NULL);
|
|
if (Image == NULL) {
|
|
return NULL;
|
|
}
|
|
BufferLen = ImageIn->Width * ImageIn->Height;
|
|
Image->Bitmap = AllocatePool (BufferLen * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
ASSERT (Image->Bitmap != NULL);
|
|
if (Image->Bitmap == NULL) {
|
|
FreePool (Image);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
Index = BufferLen;
|
|
BitmapIn = (UINT32 *)ImageIn->Bitmap;
|
|
BitmapOut = (UINT32 *)Image->Bitmap;
|
|
|
|
|
|
if (Style & DT_GRAY) {
|
|
while (--Index >= 0) {
|
|
*(BitmapOut++) = 0x00D6D6D6 + (*(BitmapIn++) & 0xFF000000);
|
|
}
|
|
} else {
|
|
while (--Index >= 0) {
|
|
*(BitmapOut++) = 0x00FFFFFF + (*(BitmapIn++) & 0xFF000000);
|
|
}
|
|
}
|
|
|
|
return Image;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
UiShowBitmap (
|
|
HWND hwnd,
|
|
HDC hdc,
|
|
RECT *Rc,
|
|
RECT *Scale9Grid,
|
|
EFI_IMAGE_INPUT *ImageIn,
|
|
UINT32 Style,
|
|
HSV_DIFF_VALUE *HsvDiff
|
|
)
|
|
{
|
|
INT32 Width;
|
|
INT32 Height;
|
|
PSD pmd;
|
|
MWCOORD ImageOffsetX;
|
|
MWCOORD ImageOffsetY;
|
|
INT32 DstWidth;
|
|
INT32 DstHeight;
|
|
EFI_IMAGE_INPUT *TempImageIn;
|
|
|
|
ASSERT (ImageIn != NULL);
|
|
if (ImageIn == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
TempImageIn = NULL;
|
|
if (HsvDiff != NULL && (HsvDiff->HueDiff != 0 || HsvDiff->SaturationDiff != 0 || HsvDiff->ValueDiff != 0)) {
|
|
TempImageIn = CreateHsvAdjustImage (ImageIn, HsvDiff);
|
|
ASSERT (TempImageIn != NULL);
|
|
pmd = GdLoadImageFromBuffer (TempImageIn);
|
|
} else if (Style & (DT_GRAY | DT_LIGHT)) {
|
|
TempImageIn = CreateStyleAdjustImage (ImageIn, Style);
|
|
ASSERT (TempImageIn != NULL);
|
|
pmd = GdLoadImageFromBuffer (TempImageIn);
|
|
} else {
|
|
pmd = GdLoadImageFromBuffer (ImageIn);
|
|
}
|
|
if (pmd == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Width = MIN ((Rc->right - Rc->left), pmd->xvirtres);
|
|
Height = MIN ((Rc->bottom - Rc->top), pmd->yvirtres);
|
|
DstWidth = Width;
|
|
DstHeight = Height;
|
|
|
|
//
|
|
// center image
|
|
//
|
|
ImageOffsetX = 0;
|
|
ImageOffsetY = 0;
|
|
|
|
if (Style & DT_STRETCH) {
|
|
ASSERT ((Style & (DT_CENTER | DT_VCENTER)) == 0);
|
|
ASSERT (Scale9Grid->left == 0 && Scale9Grid->right == 0 && Scale9Grid->top == 0 && Scale9Grid->bottom == 0);
|
|
|
|
Width = pmd->xvirtres;
|
|
Height = pmd->yvirtres;
|
|
DstWidth = Rc->right - Rc->left;
|
|
DstHeight = Rc->bottom - Rc->top;
|
|
} else {
|
|
|
|
if (Style & DT_CENTER) {
|
|
if ((Rc->right - Rc->left) > pmd->xvirtres) {
|
|
Rc->left = (Rc->right + Rc->left - pmd->xvirtres) / 2;
|
|
}
|
|
if (Width <= pmd->xvirtres) {
|
|
ImageOffsetX = (pmd->xvirtres - Width) / 2;
|
|
}
|
|
} else if (Style & DT_VCENTER) {
|
|
if ((Rc->bottom - Rc->top) > pmd->yvirtres) {
|
|
Rc->top = (Rc->bottom + Rc->top - pmd->yvirtres) / 2;
|
|
}
|
|
if (Height < pmd->yvirtres) {
|
|
ImageOffsetY = (pmd->yvirtres - Height) / 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Scale9Grid->left == 0 && Scale9Grid->right == 0 && Scale9Grid->top == 0 && Scale9Grid->bottom == 0) {
|
|
GdDrawImagePartToFit (hdc->psd, Rc->left, Rc->top, DstWidth, DstHeight, ImageOffsetX, ImageOffsetY, Width, Height, pmd);
|
|
} else {
|
|
UiDrawImage (hdc->psd, Rc, Scale9Grid, pmd);
|
|
}
|
|
|
|
pmd->FreeMemGC(pmd);
|
|
if (TempImageIn != NULL) {
|
|
FreePool (TempImageIn->Bitmap);
|
|
FreePool (TempImageIn);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|