/** @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 #include "UiRender.h" #include "UiControls.h" #include "UiManager.h" #include "H2ODisplayEngineLocalMetro.h" #include "MetroUi.h" #include #include 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; }