/** @file Virtural Keyboard Layout Engine Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "VirtualKeyboard.h" // // 1.FullKeyboardBody // Follow below design // (1).\KeyboardLayout\CapitalLetterKeyboard.bmp // (2).\KeyboardLayout\DigitKeyboard.bmp // Based on keyboard's (startX, startY) // // Page0Font // +---+---+---+---+---+---+---+---+---+---+---+ // | q | w | e | r | t | y | u | i | o | p | | ? |F11|F12|Enter| Line 2 // +-----+---+---+---+---+---+---+---+---+---+-+ // | Esc |12#| Space | | | _ | + | | Line 3 // +-----+---+-------------------+---+---+---+-+ // // 2.Screen Corner // Follow below design // (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B // (2).\KeyboardLayout\FullIcon.bmp # Screen Corner C/D // +-+------------------------------------+-+ // |A| |C| // +-+ +-+ // | | // | | // | | // | | // | | // | | // +-+ +-+ // |B| |D| // +-+------------------------------------+-+ // VK_STRUCT mFullKeyboardBody[] = { // StartX StartY EndX EndY Page0Font Page1Font Page2Font Page3Font // Line 0 { 0x0000, 0x0000, 0x0032, 0x0032, {L'q', L'Q', L'1', L'!' }}, { 0x0032, 0x0000, 0x0064, 0x0032, {L'w', L'W', L'2', L'@' }}, { 0x0064, 0x0000, 0x0096, 0x0032, {L'e', L'E', L'3', L'#' }}, { 0x0096, 0x0000, 0x00C8, 0x0032, {L'r', L'R', L'4', L'$' }}, { 0x00C8, 0x0000, 0x00FA, 0x0032, {L't', L'T', L'5', L'%' }}, { 0x00FA, 0x0000, 0x012C, 0x0032, {L'y', L'Y', L'6', L'^' }}, { 0x012C, 0x0000, 0x015E, 0x0032, {L'u', L'U', L'7', L'&' }}, { 0x015E, 0x0000, 0x0190, 0x0032, {L'i', L'I', L'8', L'*' }}, { 0x0190, 0x0000, 0x01C2, 0x0032, {L'o', L'O', L'9', L'(' }}, { 0x01C2, 0x0000, 0x01F4, 0x0032, {L'p', L'P', L'0', L')' }}, { 0x01F4, 0x0000, 0x0226, 0x0032, {VkKeyBackspace, VkKeyBackspace, VkKeyBackspace, VkKeyBackspace }}, // Line 1 { 0x0000, 0x0032, 0x0019, 0x0064, {VkKeyNull, VkKeyNull, VkKeyNull, VkKeyNull }}, { 0x0019, 0x0032, 0x004B, 0x0064, {L'a', L'A', VkKeyF1, VkKeyF1 }}, { 0x004B, 0x0032, 0x007D, 0x0064, {L's', L'S', VkKeyF2, VkKeyF2 }}, { 0x007D, 0x0032, 0x00AF, 0x0064, {L'd', L'D', VkKeyF3, VkKeyF3 }}, { 0x00AF, 0x0032, 0x00E1, 0x0064, {L'f', L'F', VkKeyF4, VkKeyF4 }}, { 0x00E1, 0x0032, 0x0113, 0x0064, {L'g', L'G', VkKeyF5, VkKeyF5 }}, { 0x0113, 0x0032, 0x0145, 0x0064, {L'h', L'H', VkKeyF6, VkKeyF6 }}, { 0x0145, 0x0032, 0x0177, 0x0064, {L'j', L'J', VkKeyF7, VkKeyF7 }}, { 0x0177, 0x0032, 0x01A9, 0x0064, {L'k', L'K', VkKeyF8, VkKeyF8 }}, { 0x01A9, 0x0032, 0x01DB, 0x0064, {L'l', L'L', VkKeyF9, VkKeyF9 }}, { 0x01DB, 0x0032, 0x020D, 0x0064, {VkKeyF2, VkKeyF2, VkKeyF10, VkKeyF10 }}, // Line 2 { 0x0000, 0x0064, 0x004B, 0x0096, {VkKeyCapslock, VkKeyCapslock, VkKeyShift, VkKeyShift }}, { 0x004B, 0x0064, 0x007D, 0x0096, {L'z', L'Z', L'`', L'~' }}, { 0x007D, 0x0064, 0x00AF, 0x0096, {L'x', L'X', L';', L':' }}, { 0x00AF, 0x0064, 0x00E1, 0x0096, {L'c', L'C', L'\'', L'"' }}, { 0x00E1, 0x0064, 0x0113, 0x0096, {L'v', L'V', L',', L'<' }}, { 0x0113, 0x0064, 0x0145, 0x0096, {L'b', L'B', L'.', L'>' }}, { 0x0145, 0x0064, 0x0177, 0x0096, {L'n', L'N', L'/', L'?' }}, { 0x0177, 0x0064, 0x01A9, 0x0096, {L'm', L'M', VkKeyF11, VkKeyF11 }}, { 0x01A9, 0x0064, 0x01DB, 0x0096, {VkKeyUp, VkKeyUp, VkKeyF12, VkKeyF12 }}, { 0x01DB, 0x0064, 0x0226, 0x0096, {VkKeyEnter, VkKeyEnter, VkKeyEnter, VkKeyEnter }}, // Line 3 { 0x0000, 0x0096, 0x004B, 0x00C8, {VkKeyEsc, VkKeyEsc, VkKeyEsc, VkKeyEsc }}, { 0x004B, 0x0096, 0x007D, 0x00C8, {VkKeyTwoPage, VkKeyTwoPage, VkKeyTwoPage, VkKeyTwoPage }}, { 0x007D, 0x0096, 0x0177, 0x00C8, {L' ', L' ', L' ', L' ' }}, { 0x0177, 0x0096, 0x01A9, 0x00C8, {VkKeyLeft, VkKeyLeft, L'\\', L'|' }}, { 0x01A9, 0x0096, 0x01DB, 0x00C8, {VkKeyDown, VkKeyDown, L'-', L'_' }}, { 0x01DB, 0x0096, 0x020D, 0x00C8, {VkKeyRight, VkKeyRight, L'=', L'+' }}, // Screen Corner A { 0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}, // Screen Corner B { 0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}, // Screen Corner C { 0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}, // Screen Corner D { 0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}} }; // // 1.SimpleKeyboardBody // Follow below design // (1).\KeyboardLayout\SimpleKeyboard.bmp // Based on keyboard's (startX, startY) // +-----+-----+ // | Esc |Enter| Line 0 // +-----+-----+ // | Up | Down| Line 1 // +-----+-----+ // // 2.Screen Corner // Follow below design // (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B // (2).\KeyboardLayout\FullIcon.bmp # Screen Corner C/D // +-+------------------------------------+-+ // |A| |C| // +-+ +-+ // | | // | | // | | // | | // | | // | | // +-+ +-+ // |B| |D| // +-+------------------------------------+-+ // VK_STRUCT mSimpleKeyboardBody[] = { // StartX StartY EndX EndY Page0Font Page1Font Page2Font Page3Font // Line 0 { 0x0000, 0x0000, 0x0032, 0x0032, {VkKeyEsc, VkKeyEsc, VkKeyEsc, VkKeyEsc }}, { 0x0032, 0x0000, 0x0064, 0x0032, {VkKeyEnter, VkKeyEnter, VkKeyEnter, VkKeyEnter }}, // Line 1 { 0x0000, 0x0032, 0x0032, 0x0064, {VkKeyUp, VkKeyUp, VkKeyUp, VkKeyUp }}, { 0x0032, 0x0032, 0x0064, 0x0064, {VkKeyDown, VkKeyDown, VkKeyDown, VkKeyDown }}, // Screen Corner A { 0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}, // Screen Corner B { 0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}, // Screen Corner C { 0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}, // Screen Corner D { 0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}} }; /** Modify the color of key if Shift or CapsLock is pressed. @param[in] VkContext Address of an VK_CONTEXT structure. @param[in, out] BltBuffer Address of a blt buffer. @retval EFI_SUCCESS Success for the function. **/ EFI_STATUS ModifyShiftKeyColor ( IN VK_CONTEXT *VkContext, IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltBuffer ) { EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempBltBuffer; UINTN BltSize; BOOLEAN IsPressed; TempBltBuffer = *BltBuffer; BltSize = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth; IsPressed = VkContext->PageNumber <= VkPage1 ? VkContext->IsCapsLockFlag : VkContext->IsShiftKeyFlag; while (BltSize-- != 0) { // // Color gradient issue // if (((TempBltBuffer->Red - TempBltBuffer->Green) > 0x20) && ((TempBltBuffer->Red - TempBltBuffer->Blue) > 0x20)) { if (IsPressed) { TempBltBuffer->Red = 0; TempBltBuffer->Green = 255; TempBltBuffer->Blue = 255; } else { TempBltBuffer->Red = 255; TempBltBuffer->Green = 255; TempBltBuffer->Blue = 255; } } TempBltBuffer++; } return EFI_SUCCESS; } /** Make the keyboard transparent. @param[in] VkContext Address of an VK_CONTEXT structure. @param[in] IsTransparent TRUE for set keyboard transparent. @param[in] BltIn Address of keyboard blt buffer. @param[in, out] BltOut Address of output blt buffer. NULL will allocate it. @retval EFI_SUCCESS Success for the function. @retval EFI_OUT_OF_RESOURCES Allocate memory failed. **/ EFI_STATUS MakeKeyboardTransparent ( IN VK_CONTEXT *VkContext, IN BOOLEAN IsTransparent, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn, IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltOut ) { EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Keyboard; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background; UINTN BltSize; if (*BltOut == NULL) { *BltOut = AllocateZeroPool (VkContext->VkBodyBltSize); if (*BltOut == NULL) { return EFI_OUT_OF_RESOURCES; } } Compound = *BltOut; Keyboard = BltIn; Background = VkContext->VkBodyBackgroundBltBuffer; BltSize = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth; while (BltSize-- != 0) { if (IsTransparent) { Compound->Red = (Keyboard->Red * TRANSPARENCY_WEIGHT) / 100 + (Background->Red * (100 - TRANSPARENCY_WEIGHT)) / 100; Compound->Green = (Keyboard->Green * TRANSPARENCY_WEIGHT) / 100 + (Background->Green * (100 - TRANSPARENCY_WEIGHT)) / 100; Compound->Blue = (Keyboard->Blue * TRANSPARENCY_WEIGHT) / 100 + (Background->Blue * (100 - TRANSPARENCY_WEIGHT)) / 100; } else { *Compound = *Keyboard; } Compound++; Keyboard++; Background++; } return EFI_SUCCESS; } /** Save the background blt buffer. @param[in] VkContext Address of an VK_CONTEXT structure. @param[in] BltSize Size of blt. @retval EFI_SUCCESS Success for the function. @retval EFI_OUT_OF_RESOURCES Allocate memory failed. **/ EFI_STATUS EFIAPI SaveVkBodyBackgroundBltBuffer ( IN VK_CONTEXT *VkContext, IN UINTN BltSize ) { EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBuffer; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBufferSave; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBuffer; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBufferSave; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background; UINTN Size; CurrentBltBufferSave = NULL; OldBltBufferSave = NULL; // // Save original blt buffer first. // OldBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize); if (OldBltBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } if (VkContext->VkBodyBackgroundBltBuffer != NULL) { CopyMem (OldBltBuffer, VkContext->VkBodyBackgroundBltBuffer, VkContext->VkBodyBltSize); } if (VkContext->VkBodyBackgroundBltBuffer == NULL) { VkContext->VkBodyBltSize = BltSize; VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize); ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL); if (VkContext->VkBodyBackgroundBltBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } } else if (BltSize > VkContext->VkBodyBltSize) { VkContext->VkBodyBltSize = BltSize; FreePool (VkContext->VkBodyBackgroundBltBuffer); VkContext->VkBodyBackgroundBltBuffer = NULL; VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize); ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL); if (VkContext->VkBodyBackgroundBltBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } } else { ZeroMem (VkContext->VkBodyBackgroundBltBuffer, VkContext->VkBodyBltSize); } CurrentBltBuffer = NULL; if (VkContext->IsBackgroundChanged == TRUE) { // // Background changed, merge current visioning blt buffer with old background blt buffer. // Compound = VkContext->VkBodyCompoundBltBuffer; Background = VkContext->VkBodyBackgroundBltBuffer; CurrentBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize); ASSERT (CurrentBltBuffer != NULL); if (CurrentBltBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } Status = VkContext->GraphicsOutput->Blt ( VkContext->GraphicsOutput, CurrentBltBuffer, EfiBltVideoToBltBuffer, VkContext->VkBodyBltStartX, VkContext->VkBodyBltStartY, 0, 0, VkContext->VkBodyBltWidth, VkContext->VkBodyBltHeight, VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); CurrentBltBufferSave = CurrentBltBuffer; OldBltBufferSave = OldBltBuffer; Size = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth; while (Size-- != 0) { if ((Compound->Red != CurrentBltBuffer->Red) || (Compound->Green != CurrentBltBuffer->Green) || (Compound->Blue != CurrentBltBuffer->Blue)) { *Background = *CurrentBltBuffer; } else { *Background = *OldBltBuffer; } Compound++; Background++; CurrentBltBuffer++; OldBltBuffer++; } } else { // // Background NOT changed, save it to VkBodyBackgroundBltBuffer directly. // Status = VkContext->GraphicsOutput->Blt ( VkContext->GraphicsOutput, VkContext->VkBodyBackgroundBltBuffer, EfiBltVideoToBltBuffer, VkContext->VkBodyBltStartX, VkContext->VkBodyBltStartY, 0, 0, VkContext->VkBodyBltWidth, VkContext->VkBodyBltHeight, VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); } if (CurrentBltBufferSave != NULL) { FreePool (CurrentBltBufferSave); } if (OldBltBufferSave != NULL) { FreePool (OldBltBufferSave); } return Status; } /** Restore the background blt buffer. @param[in] VkContext Address of an VK_CONTEXT structure. @retval EFI_SUCCESS Success for the function. @retval EFI_UNSUPPORTED Input blt buffer is NULL. @retval Others An unexpected error occurred. **/ EFI_STATUS EFIAPI RestoreVkBodyBackgroundBltBuffer ( IN VK_CONTEXT *VkContext ) { EFI_STATUS Status; if (VkContext->VkBodyBackgroundBltBuffer == NULL) { return EFI_UNSUPPORTED; } Status = VkContext->GraphicsOutput->Blt ( VkContext->GraphicsOutput, VkContext->VkBodyBackgroundBltBuffer, EfiBltBufferToVideo, 0, 0, VkContext->VkBodyBltStartX, VkContext->VkBodyBltStartY, VkContext->VkBodyBltWidth, VkContext->VkBodyBltHeight, VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); FreePool (VkContext->VkBodyBackgroundBltBuffer); VkContext->VkBodyBackgroundBltBuffer = NULL; return Status; } /** Set the position of character. @param[in] VkContext Address of an VK_CONTEXT structure. @param[in] DestX X position. @param[in] DestY Y position. @retval EFI_SUCCESS Success for the function. @retval Others An unexpected error occurred. **/ EFI_STATUS SetCharacterPosition ( IN VK_CONTEXT *VkContext, IN UINT32 DestX, IN UINT32 DestY ) { UINTN Index; VK_STRUCT *KeyArryPtr; UINT32 KeyArrySize; switch (VkContext->TargetKeyboardDisplay) { case VkDisplayAttributeSimpleTop: case VkDisplayAttributeSimpleBottom: KeyArryPtr = mSimpleKeyboardBody; KeyArrySize = DIM (mSimpleKeyboardBody); break; case VkDisplayAttributeFullBottom: case VkDisplayAttributeFullTop: KeyArryPtr = mFullKeyboardBody; KeyArrySize = DIM (mFullKeyboardBody); break; case VkDisplayAttributeNone: KeyArryPtr = mFullKeyboardBody; KeyArrySize = DIM (mFullKeyboardBody); break; default: return EFI_UNSUPPORTED; } for (Index = 0; Index < KeyArrySize; Index++) { VkContext->KeyboardBodyPtr[Index] = KeyArryPtr[Index]; } VkContext->NumOfKeysInfo = KeyArrySize; for (Index = 0; Index < (VkContext->NumOfKeysInfo - 4); Index++) { VkContext->KeyboardBodyPtr[Index].DisStartX += (UINT16)DestX; VkContext->KeyboardBodyPtr[Index].DisStartY += (UINT16)DestY; VkContext->KeyboardBodyPtr[Index].DisEndX += (UINT16)DestX; VkContext->KeyboardBodyPtr[Index].DisEndY += (UINT16)DestY; } return EFI_SUCCESS; } /** Save the icon background blt buffer. @param[in] VkContext Address of an VK_CONTEXT structure. @param[in] IconType The icon type. @retval EFI_SUCCESS Success for the function. @retval EFI_OUT_OF_RESOURCES Allocate memory failed. @retval Others An unexpected error occurred. **/ EFI_STATUS EFIAPI SaveVkIconBackgroundBltBuffer ( IN VK_CONTEXT *VkContext, IN VK_DISPLAY_ATTRIBUTE IconType ) { EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GraphicBlt; UINTN BltSize; UINTN Height; UINTN Width; INTN StartX; INTN StartY; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempIconBackBuffer; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *IconBackBuffer; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound; UINTN Size; BOOLEAN SaveCursor; Status = EFI_SUCCESS; StartX = 0; StartY = 0; TempIconBackBuffer = NULL; IconBackBuffer = NULL; Compound = NULL; if ((IconType == VkDisplayAttributeFullTop) || (IconType == VkDisplayAttributeSimpleTop)) { return EFI_SUCCESS; } SaveCursor = gST->ConOut->Mode->CursorVisible; gST->ConOut->EnableCursor (gST->ConOut, FALSE); if (IconType == VkDisplayAttributeFullBottom) { GraphicBlt = VkContext->FullIcon->Bitmap; BltSize = VkContext->FullIcon->Height * VkContext->FullIcon->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); Height = VkContext->FullIcon->Height; Width = VkContext->FullIcon->Width; StartX = VkContext->FullIconBackStartX; StartY = VkContext->FullIconBackStartY; } else if (IconType == VkDisplayAttributeSimpleBottom) { GraphicBlt = VkContext->SmallIcon->Bitmap; BltSize = VkContext->SmallIcon->Height * VkContext->SmallIcon->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); Height = VkContext->SmallIcon->Height; Width = VkContext->SmallIcon->Width; StartX = VkContext->SimIconBackStartX; StartY = VkContext->SimIconBackStartY; } else { gST->ConOut->EnableCursor (gST->ConOut, SaveCursor); return EFI_UNSUPPORTED; } IconBackBuffer = AllocateZeroPool (BltSize); if (IconBackBuffer == NULL) { gST->ConOut->EnableCursor (gST->ConOut, SaveCursor); return EFI_OUT_OF_RESOURCES; } TempIconBackBuffer = IconBackBuffer; Status = VkContext->GraphicsOutput->Blt ( VkContext->GraphicsOutput, IconBackBuffer, EfiBltVideoToBltBuffer, StartX, StartY, 0, 0, Width, Height, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); if (IconType == VkDisplayAttributeFullBottom) { // // Store full icon background framebuffer // VkContext->FullIconBackHeight = Height; VkContext->FullIconBackWidth = Width; if (VkContext->FullIconUpdatedFlag == FALSE) { // // No icon draw, save the buffer directly. // if (VkContext->FullIconBackBuffer == NULL) { VkContext->FullIconBackBuffer = AllocateZeroPool (BltSize); VkContext->FullIconBackSize = BltSize; } CopyMem (VkContext->FullIconBackBuffer, IconBackBuffer, BltSize); VkContext->FullIconUpdatedFlag = TRUE; } else { if (CompareMem (VkContext->FullIconBackBuffer, IconBackBuffer, BltSize) != 0) { Compound = VkContext->FullIconBackBuffer; Size = Height * Width; while (Size-- != 0) { if ((GraphicBlt->Red != IconBackBuffer->Red) || (GraphicBlt->Green != IconBackBuffer->Green) || (GraphicBlt->Blue != IconBackBuffer->Blue)) { *Compound = *IconBackBuffer; } Compound++; GraphicBlt++; IconBackBuffer++; } } } } else if (IconType == VkDisplayAttributeSimpleBottom) { // // Store simple icon background framebuffer // VkContext->SimIconBackHeight = Height; VkContext->SimIconBackWidth = Width; if (VkContext->SimIconUpdatedFlag == FALSE) { // // No icon draw, save the buffer directly. // if (VkContext->SimIconBackBuffer == NULL) { VkContext->SimIconBackBuffer = AllocateZeroPool (BltSize); VkContext->SimIconBackSize = BltSize; } CopyMem (VkContext->SimIconBackBuffer, IconBackBuffer, BltSize); VkContext->SimIconUpdatedFlag = TRUE; } else { if (CompareMem (VkContext->SimIconBackBuffer, IconBackBuffer, BltSize) != 0) { Compound = VkContext->SimIconBackBuffer; Size = Height * Width; while (Size-- != 0) { if ((GraphicBlt->Red != IconBackBuffer->Red) || (GraphicBlt->Green != IconBackBuffer->Green) || (GraphicBlt->Blue != IconBackBuffer->Blue)) { *Compound = *IconBackBuffer; } Compound++; GraphicBlt++; IconBackBuffer++; } } } } if (TempIconBackBuffer != NULL) FreePool (TempIconBackBuffer); gST->ConOut->EnableCursor (gST->ConOut, SaveCursor); return Status; } /** Use to draw the keyboard icon. @param[in] VkContext Pointer to virtual keyboard's context @param[in] VkImage Image of keyboard to display on the screen. @param[in] Attribute Attribute of keyboard to display on the screen. @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard icon displayed. @retval EFI_UNSUPPORTED KeyboardFile not found @retval EFI_INVALID_PARAMETER Attribute is unknown. **/ EFI_STATUS EFIAPI DrawVkIcon ( IN VK_CONTEXT *VkContext, IN EFI_IMAGE_INPUT *VkImage, IN VK_DISPLAY_ATTRIBUTE Attribute ) { EFI_STATUS Status; UINT32 SizeOfX; UINT32 SizeOfY; INTN DestX; INTN DestY; UINTN CoordinateX; UINTN CoordinateY; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; UINTN BltSize; UINTN Height; UINTN Width; Status = EFI_SUCCESS; GraphicsOutput = VkContext->GraphicsOutput; SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; CoordinateX = 0; CoordinateY = 0; Height = VkImage->Height; Width = VkImage->Width; Blt = VkImage->Bitmap; BltSize = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width * Height); // // Calculate the display position according to Attribute. // switch (Attribute) { case VkDisplayAttributeSimpleTop: DestX = CoordinateX; DestY = CoordinateY; break; case VkDisplayAttributeFullTop: DestX = (SizeOfX - Width - CoordinateX); DestY = CoordinateY;; break; case VkDisplayAttributeFullBottom: DestX = (SizeOfX - Width - CoordinateX); DestY = (SizeOfY - Height - CoordinateY); VkContext->FullIconBackStartX = DestX; VkContext->FullIconBackStartY = DestY; break; case VkDisplayAttributeSimpleBottom: DestX = CoordinateX; DestY = (SizeOfY - Height - CoordinateY); // // Save to check icon/screen cleared // if (VkContext->IconBltBuffer == NULL) { VkContext->IconBltSize = BltSize; VkContext->IconBltWidth = Width; VkContext->IconBltHeight = Height; VkContext->IconBltBuffer = AllocateZeroPool (BltSize); } CopyMem (VkContext->IconBltBuffer, Blt, VkContext->IconBltSize); VkContext->SimIconBackStartX = DestX; VkContext->SimIconBackStartY = DestY; break; case VkDisplayAttributeNone: return EFI_SUCCESS; default: return EFI_INVALID_PARAMETER; } if ((DestX >= 0) && (DestY >= 0)) { // // Store icon background framebuffer // SaveVkIconBackgroundBltBuffer (VkContext, Attribute); Status = GraphicsOutput->Blt ( GraphicsOutput, Blt, EfiBltBufferToVideo, 0, 0, (UINTN) DestX, (UINTN) DestY, Width, Height, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); } return Status; } /** Use to draw the keyboard. @param[in] VkContext Pointer to virtual keyboard's context @param[in] VkImage Image of keyboard to display on the screen. @param[in] Attribute Attribute of keyboard to display on the screen. @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard displayed. @retval EFI_UNSUPPORTED KeyboardFile not found @retval EFI_INVALID_PARAMETER Attribute is unknown. **/ EFI_STATUS EFIAPI DrawVkBody ( IN VK_CONTEXT *VkContext, IN EFI_IMAGE_INPUT *VkImage, IN VK_DISPLAY_ATTRIBUTE Attribute ) { EFI_STATUS Status; UINT32 SizeOfX; UINT32 SizeOfY; INTN DestX; INTN DestY; UINTN BltSize; UINTN Height; UINTN Width; UINTN CoordinateY; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; Status = EFI_SUCCESS; GraphicsOutput = VkContext->GraphicsOutput; SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; CoordinateY = 0; Height = VkImage->Height; Width = VkImage->Width; BltSize = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width * Height); BltIn = AllocateCopyPool (BltSize, VkImage->Bitmap); if (BltIn == NULL) { return EFI_OUT_OF_RESOURCES; } // // Calculate the display position according to Attribute. // switch (Attribute) { case VkDisplayAttributeSimpleTop: DestX = ((SizeOfX / 2) - Width) / 4; DestY = CoordinateY; VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleTop; break; case VkDisplayAttributeSimpleBottom: DestX = ((SizeOfX / 2) - Width) / 4; DestY = (SizeOfY - Height - CoordinateY); VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleBottom; break; case VkDisplayAttributeFullTop: DestX = (SizeOfX - Width) / 2; DestY = CoordinateY; VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullTop; break; case VkDisplayAttributeFullBottom: DestX = (SizeOfX - Width) / 2; DestY = (SizeOfY - Height - CoordinateY); VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullBottom; break; case VkDisplayAttributeNone: VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone; goto DVKBODY_Exit; default: VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone; Status = EFI_INVALID_PARAMETER; goto DVKBODY_Exit; } if ((DestX >= 0) && (DestY >= 0)) { SetCharacterPosition (VkContext, (UINT32)DestX, (UINT32)DestY); // // Store current framebuffer // VkContext->VkBodyBltStartX = DestX; VkContext->VkBodyBltStartY = DestY; VkContext->VkBodyBltHeight = Height; VkContext->VkBodyBltWidth = Width; SaveVkBodyBackgroundBltBuffer (VkContext, BltSize); // // Free compound buffer first. // if (VkContext->VkBodyCompoundBltBuffer != NULL) { FreePool (VkContext->VkBodyCompoundBltBuffer); } VkContext->VkBodyCompoundBltBuffer = NULL; ModifyShiftKeyColor (VkContext, &BltIn); MakeKeyboardTransparent (VkContext, TRUE, BltIn, &(VkContext->VkBodyCompoundBltBuffer)); // // Draw keyboard body // Status = GraphicsOutput->Blt ( GraphicsOutput, VkContext->VkBodyCompoundBltBuffer, EfiBltBufferToVideo, 0, 0, (UINTN) DestX, (UINTN) DestY, Width, Height, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); } DVKBODY_Exit: if (BltIn != NULL) { FreePool (BltIn); } return Status; } /** Clear the keyboard body @param VkContext Code context. @retval EFI_SUCCESS Clear rectangle is done. **/ EFI_STATUS HideVkBody ( IN VK_CONTEXT *VkContext ) { RestoreVkBodyBackgroundBltBuffer (VkContext); VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone; return EFI_SUCCESS; } /** Clear the keyboard icon @param VkContext Code context. @retval EFI_SUCCESS Clear rectangle is done. **/ EFI_STATUS HideVkIcon ( IN VK_CONTEXT *VkContext ) { EFI_STATUS Status; if ((VkContext->FullIconBackBuffer == NULL) || (VkContext->SimIconBackBuffer == NULL)) { return EFI_UNSUPPORTED; } if ((VkContext->FullIconUpdatedFlag == FALSE) || (VkContext->SimIconUpdatedFlag == FALSE)) { return EFI_UNSUPPORTED; } Status = VkContext->GraphicsOutput->Blt ( VkContext->GraphicsOutput, VkContext->FullIconBackBuffer, EfiBltBufferToVideo, 0, 0, VkContext->FullIconBackStartX, VkContext->FullIconBackStartY, VkContext->FullIconBackWidth, VkContext->FullIconBackHeight, VkContext->FullIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); ZeroMem (VkContext->FullIconBackBuffer, VkContext->FullIconBackSize); VkContext->FullIconUpdatedFlag = FALSE; Status = VkContext->GraphicsOutput->Blt ( VkContext->GraphicsOutput, VkContext->SimIconBackBuffer, EfiBltBufferToVideo, 0, 0, VkContext->SimIconBackStartX, VkContext->SimIconBackStartY, VkContext->SimIconBackWidth, VkContext->SimIconBackHeight, VkContext->SimIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); if (!EFI_ERROR (Status)) { if (VkContext->ScreenCheckBuffer == NULL) { VkContext->ScreenCheckBufferSize = VkContext->SimIconBackHeight * VkContext->SimIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); VkContext->ScreenCheckBuffer = AllocateZeroPool (VkContext->ScreenCheckBufferSize); } CopyMem ( VkContext->ScreenCheckBuffer, VkContext->SimIconBackBuffer, (VkContext->SimIconBackHeight * VkContext->SimIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) ); } ZeroMem (VkContext->SimIconBackBuffer, VkContext->SimIconBackSize); VkContext->SimIconUpdatedFlag = FALSE; return EFI_SUCCESS; } /** Draw key board on the display @param[in] VkContext Graphic Protocol for draw the alphabet. @retval EFI_SUCCESS Draw keyboard was done. @retval EFI_UNSUPPORTED Did not get key mapping table. **/ EFI_STATUS DrawKeyboardLayout ( IN VK_CONTEXT *VkContext ) { EFI_STATUS Status; if (!VkContext->IsIconShowed) { Status = DrawVkIcon (VkContext, VkContext->SmallIcon, VkDisplayAttributeSimpleTop); ASSERT_EFI_ERROR (Status); Status = DrawVkIcon (VkContext, VkContext->SmallIcon, VkDisplayAttributeSimpleBottom); ASSERT_EFI_ERROR (Status); Status = DrawVkIcon (VkContext, VkContext->FullIcon, VkDisplayAttributeFullTop); ASSERT_EFI_ERROR (Status); Status = DrawVkIcon (VkContext, VkContext->FullIcon, VkDisplayAttributeFullBottom); ASSERT_EFI_ERROR (Status); VkContext->IsIconShowed = TRUE; } if (VkContext->TargetKeyboardDisplay != VkContext->CurrentKeyboardDisplay) { switch (VkContext->TargetKeyboardDisplay) { case VkDisplayAttributeSimpleTop: case VkDisplayAttributeSimpleBottom: DrawVkBody (VkContext, VkContext->SimKeyBody, VkContext->TargetKeyboardDisplay); break; case VkDisplayAttributeFullTop: case VkDisplayAttributeFullBottom: if (VkContext->PageNumber <= VkPage1) { DrawVkBody (VkContext, VkContext->CapLeKeyBody, VkContext->TargetKeyboardDisplay); } else { DrawVkBody (VkContext, VkContext->DigKeyBody, VkContext->TargetKeyboardDisplay); } case VkDisplayAttributeNone: break; default: break; } } return EFI_SUCCESS; } /** Set the keyboard layout. @param[in] VkContext Graphic Protocol for draw the alphabet. @param[in] Index The layout selected. @retval EFI_SUCCESS Draw keyboard was done. @retval Others An unexpected error occurred. **/ EFI_STATUS KeyboardLayoutHandler ( IN VK_CONTEXT *VkContext, IN UINT32 Index ) { EFI_STATUS Status; Status = EFI_SUCCESS; if (Index == (VkContext->NumOfKeysInfo - 4)) { // // Touch the LeftTop icon // if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeSimpleTop) { VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone; } else { VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleTop; } } else if (Index == (VkContext->NumOfKeysInfo - 3)) { // // Touch the LeftBottom icon // if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeSimpleBottom) { VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone; } else { VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleBottom; } } else if (Index == (VkContext->NumOfKeysInfo - 2)) { // // Touch the RightTop icon // if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullTop) { VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone; } else { VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullTop; } } else { // // Touch the RightBottom icon // if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullBottom) { VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone; } else { VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullBottom; } } if (VkContext->TargetKeyboardDisplay == VkDisplayAttributeNone) { // // Just hide the current keyboard // HideVkBody (VkContext); VkContext->KeyTouchedTimeOut = VK_REPEAT_TIMEOUT; } else { // // If current keyboard status is NOT none, // hide current keyboard first and then draw the target keyboard // if (VkContext->CurrentKeyboardDisplay != VkDisplayAttributeNone) { HideVkBody (VkContext); } Status = DrawKeyboardLayout (VkContext); } return Status; } /** This routine is used to check if icon has been cleared. @param[in] VkContext Pointer to virtual keyboard's context @retval EFI_SUCCESS Function completed. **/ EFI_STATUS CheckIconCleared ( IN VK_CONTEXT *VkContext ) { EFI_STATUS Status; UINT32 VerticalResolution; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; Status = EFI_SUCCESS; BltBuffer = NULL; VkContext->IconReDrawCheck++; if (VkContext->IconReDrawCheck <= 10) { // // Check it every 10 * 100ms. // return Status; } // // Check if right-bottomed region is black, if yes, clean screen happened, need to re-draw keyboard. // VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution; BltBuffer = AllocateZeroPool (VkContext->IconBltSize); if (BltBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } Status = VkContext->GraphicsOutput->Blt ( VkContext->GraphicsOutput, BltBuffer, EfiBltVideoToBltBuffer, 0, (VerticalResolution - VkContext->IconBltHeight), 0, 0, VkContext->IconBltWidth, VkContext->IconBltHeight, VkContext->IconBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); if (EFI_ERROR (Status)) { FreePool (BltBuffer); return Status; } VkContext->IsIconShowed = TRUE; if (VkContext->IconBltBuffer == NULL) { // // No icon has been drawn. // VkContext->IsIconShowed = FALSE; } else { if (CompareMem (BltBuffer, VkContext->IconBltBuffer, VkContext->IconBltSize) != 0) { // // Icon has been overridden, need to re-draw. // VkContext->IsIconShowed = FALSE; } } if (VkContext->IsIconShowed == FALSE) { if (VkContext->ScreenCheckBuffer != NULL) { if (CompareMem (BltBuffer, VkContext->ScreenCheckBuffer, VkContext->IconBltSize) == 0) { // // Icon has been overridden, force to re-draw the keyboard. // Status = DrawKeyboardLayout (VkContext); } else { // // Save blt buffer of icon position and use it to check if icon is overridden. // CopyMem (VkContext->ScreenCheckBuffer, BltBuffer, VkContext->IconBltSize); } } else { // // Draw the keyboard. // Status = DrawKeyboardLayout (VkContext); } } if (BltBuffer != NULL) { FreePool (BltBuffer); } VkContext->IconReDrawCheck = 0; return Status; } /** ConvertCoordinate - Convert the touch panel's coordinate to display's coordinate. @param[in] VkContext Virtual Keyboard context. @param[in] Point The coordinate reported from touch panel. @param[out] TouchX The coordinate X converted to display panel. @param[out] TouchY The coordinate Y converted to display panel.. @retval EFI_SUCCESS Convert success. **/ EFI_STATUS ConvertCoordinate ( IN VK_CONTEXT *VkContext, IN EFI_ABSOLUTE_POINTER_STATE Point, OUT UINT32 *TouchX, OUT UINT32 *TouchY ) { UINT64 AbsoluteMaxX; UINT64 AbsoluteMaxY; UINT32 HorizontalResolution; UINT32 VerticalResolution; AbsoluteMaxX = VkContext->AbsolutePointer->Mode->AbsoluteMaxX; AbsoluteMaxY = VkContext->AbsolutePointer->Mode->AbsoluteMaxY; HorizontalResolution = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution; VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution; *TouchX = (UINT32) MultU64x32 (Point.CurrentX, HorizontalResolution) / (UINT32) AbsoluteMaxX; *TouchY = (UINT32) MultU64x32 (Point.CurrentY, VerticalResolution) / (UINT32) AbsoluteMaxY; return EFI_SUCCESS; } /** This routine is used to check if screen has been cleared. @param[in] VkContext Pointer to virtual keyboard's context @retval EFI_SUCCESS Function completed. **/ EFI_STATUS CheckScreenCleared ( IN VK_CONTEXT *VkContext ) { EFI_STATUS Status; UINT32 HorizontalResolution; UINT32 VerticalResolution; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBufferIndex; UINTN BltSize; BOOLEAN IsScreenCleared; // // Check left-bottom side. // If IconBltBuffer is null, checking is meaningless. // if (VkContext->IconBltBuffer == NULL) { return EFI_SUCCESS; } IsScreenCleared = FALSE; Status = EFI_SUCCESS; if ((gST->ConOut->Mode->CursorColumn == 0) && (gST->ConOut->Mode->CursorRow == 0)) { // // System may call gST->ConOut->ClearScreen // HorizontalResolution = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution; VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution; BltBuffer = AllocateZeroPool (VkContext->IconBltSize); if (BltBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } BltBufferIndex = BltBuffer; Status = VkContext->GraphicsOutput->Blt ( VkContext->GraphicsOutput, BltBuffer, EfiBltVideoToBltBuffer, (HorizontalResolution - VkContext->IconBltWidth), (VerticalResolution - VkContext->IconBltHeight), 0, 0, VkContext->IconBltWidth, VkContext->IconBltHeight, VkContext->IconBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); if (EFI_ERROR (Status)) { FreePool (BltBuffer); return Status; } BltSize = VkContext->IconBltHeight * VkContext->IconBltWidth; IsScreenCleared = TRUE; while (BltSize-- != 0) { if ((BltBufferIndex->Red != 0) || (BltBufferIndex->Green != 0) || (BltBufferIndex->Blue != 0)) { IsScreenCleared = FALSE; break; } BltBufferIndex++; } FreePool (BltBuffer); } if (IsScreenCleared) { VkContext->IsIconShowed = FALSE; VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone; if (VkContext->VkBodyBackgroundBltBuffer != NULL) { FreePool (VkContext->VkBodyBackgroundBltBuffer); VkContext->VkBodyBackgroundBltBuffer = NULL; } if (VkContext->VkBodyCompoundBltBuffer != NULL) { FreePool (VkContext->VkBodyCompoundBltBuffer); VkContext->VkBodyCompoundBltBuffer = NULL; } if (VkContext->IconBltBuffer != NULL) { FreePool (VkContext->IconBltBuffer); VkContext->IconBltBuffer = NULL; } } return Status; } /** This routine is used to check if background beneath virtual keyboard has been cleared. @param[in] VkContext Pointer to virtual keyboard's context @retval EFI_SUCCESS Function completed. **/ EFI_STATUS CheckBackgroundChanged ( IN VK_CONTEXT *VkContext ) { EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; Status = EFI_SUCCESS; VkContext->IsBackgroundChanged = FALSE; if ((VkContext->CurrentKeyboardDisplay == VkDisplayAttributeNone) || (VkContext->VkBodyCompoundBltBuffer == NULL)) { return EFI_SUCCESS; } BltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize); if (BltBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } Status = VkContext->GraphicsOutput->Blt ( VkContext->GraphicsOutput, BltBuffer, EfiBltVideoToBltBuffer, VkContext->VkBodyBltStartX, VkContext->VkBodyBltStartY, 0, 0, VkContext->VkBodyBltWidth, VkContext->VkBodyBltHeight, VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); if (EFI_ERROR (Status)) { FreePool (BltBuffer); return Status; } if (CompareMem (BltBuffer, VkContext->VkBodyCompoundBltBuffer, VkContext->VkBodyBltSize) != 0) { VkContext->IsBackgroundChanged = TRUE; VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone; DrawKeyboardLayout (VkContext); } if (BltBuffer != NULL) { FreePool (BltBuffer); } return Status; } /** Get unicode by VkContext->PageNumber and VkContext->KeyboardBodyPtr. @param[in] VkContext Address of an VK_CONTEXT structure. @param[in] KeyItem Key Item. @param[out] FontPtr Follow VkContext->PageNumber to translate font unicode. @retval EFI_SUCCESS Finish translating FontPtr. @retval EFI_INVALID_PARAMETER VkContext or FontPtr is NULL. **/ EFI_STATUS VkGetMappingFont ( IN VK_CONTEXT *VkContext, IN VK_STRUCT KeyItem, OUT UINT32 *FontPtr ) { if ((VkContext == NULL) || (FontPtr == NULL) || (VkContext->PageNumber>=VkPageMaximum)) { return EFI_INVALID_PARAMETER; } *FontPtr = (UINT32) KeyItem.PageFont[VkContext->PageNumber]; return EFI_SUCCESS; }