diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/CORE_DXE/UefiHii/HiiFontEx.c | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'Core/CORE_DXE/UefiHii/HiiFontEx.c')
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiiFontEx.c | 1332 |
1 files changed, 1332 insertions, 0 deletions
diff --git a/Core/CORE_DXE/UefiHii/HiiFontEx.c b/Core/CORE_DXE/UefiHii/HiiFontEx.c new file mode 100644 index 0000000..32557da --- /dev/null +++ b/Core/CORE_DXE/UefiHii/HiiFontEx.c @@ -0,0 +1,1332 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFontEx.c 2 9/17/13 10:19p Thomaschen $ +// +// $Revision: 2 $ +// +// $Date: 9/17/13 10:19p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFontEx.c $ +// +// 2 9/17/13 10:19p Thomaschen +// Update for EIP105534 and EIP126176. +// +// 1 11/21/12 4:08a Wesleychen +// Update rev.6 for EIP105534. +// 11 5/16/13 5:01p Artems +// [TAG] EIP123904 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] HiiFont and HiiConfig SCT tests are failed +// [RootCause] Regression bugs when implementing new features or spec +// updates +// [Solution] Fixed code logic +// [Files] HiiConfig.c HiiFontEx.c +// +// 10 5/02/13 1:52p Artems +// [TAG] EIP121673 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Incorrect line width returned by function StringToImage +// [RootCause] When determine line width function ignored flag +// "IGNORE_IF_NO_GLYPH" +// so line width was bigger if some glyphs were absent +// [Solution] Modified code logic to not count width of absent glyphs +// [Files] HiiFontEx.c +// +// 9 5/02/13 1:43p Artems +// [TAG] EIP113105 +// [Category] Spec Update +// [Severity] Important +// [Description] Wording for proportional font display was vague. After +// clarification +// code logic was slightly changed +// [Files] HiiFontEx.c HiiPrivate.h +// +// 8 3/26/13 3:18p Artems +// [TAG] EIP119250 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] System hang on Setup entry +// [RootCause] Incorrect boundaries checking in HiiFontEx.c function +// CheckVisible() +// [Solution] Changed checking condition +// [Files] HiiFontEx.c +// +// 7 2/25/13 4:44p Artems +// [TAG] EIP101673 +// [Category] New Feature +// [Description] Add support for AMI custom large fixed font +// [Files] HiiDatabase.c HiiFontEx.c HiiPrivate.h UefiHiiUtils.c GC.c +// new LargeFont Core modulePart +// +// 6 11/14/12 6:03p Artems +// [TAG] EIP105534 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] system hangs during SCT execution +// [RootCause] Incorrect handling of FORM_FEED escape character in +// StringToImage function +// [Solution] Graphics console - added flag to ignore line breaks +// HiiFont - fixed multiline drawing logic +// [Files] Gc.c HiiFont.c HiiFontEx.c +// +// 5 8/24/12 5:34p Artems +// [TAG] EIP N/A +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] One character is not displayed properly +// [RootCause] Never accounted for the case, where character is +// completely below base line +// [Solution] added check that character height is less than OffsetY +// [Files] HiiFontEx.c +// +// 4 6/15/12 12:21p Artems +// [TAG] EIP N/A +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] doesn't build in 32-bit mode +// [RootCause] Signed/Unsigned mismatch reported by 32-bit compiler +// [Solution] typecasted one parameter to INTN +// [Files] HiiFont.c HiiFontEx.c +// +// 3 6/14/12 6:32p Artems +// [TAG] EIP83593 +// [Category] New Feature +// [Description] Proportional font support for Aptio fixed SCT reported +// bugs +// [Files] HiiFont.c HiiFontEx.c +// +// 2 5/24/12 3:00p Artems +// [TAG] EIP83593 +// [Category] Bug Fix +// [Severity] Critical +// [Symptom] system dead loops in HiiGetFontInfo function +// [RootCause] When loop through linked list of installed fonts pointer +// was not updated +// [Solution] Added pointer update +// [Files] HiiFontEx.c +// +// 1 5/22/12 3:29p Artems +// [TAG] EIP83593 +// [Category] New Feature +// [Description] Proportional font support +// [Files] HiiFontEx.c HiiFont.c HiiDatabase.c HiiString.c HiiPrivate.h +// UefiHii.h +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: HiiFontEx.c +// +// Description: Proportional font support +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <UefiHii.h> +#include <AmiDxeLib.h> +#include "HiiPrivate.h" + +#define LOOSE_SIZE_MARGIN 4 + +extern HII_DATABASE_PRIVATE_DATA PrivateData; +extern SIMPLE_FONT DefaultFont[]; +extern EFI_FONT_HANDLE CurFont; //font to use +extern CHAR16 *DrawString; //string to draw +extern EFI_HII_OUT_FLAGS DrawFlags; +extern DLIST DrawLines; +extern UINTN ImageWidth; +extern UINTN ImageHeight; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefForegroundColor; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefBackgroundColor; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DuplicateGlyph +// +// Description: +// This function duplicates glyph from Origin and assigns it to the Char +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// IN CHAR16 Char - character to assign glyph to +// IN CHAR16 Origin - character to assign glyph from +// +// Output: +// EFI_NOT_FOUND - glyph for Origin character not found +// EFI_SUCCESS - glyph created successfully +// EFI_OUT_OF_RESOURCES - not enough memory to duplicate glyph +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DuplicateGlyph( + IN OUT FONT_LINK *Font, + IN CHAR16 Char, + IN CHAR16 Origin +) +{ + EFI_STATUS Status; + GLYPH_LINK *Link = (GLYPH_LINK *)Font->Glyphs.pHead; + GLYPH_LINK *New; + + while(Link != NULL) { + if(Link->Char == Origin) + break; + Link = (GLYPH_LINK *) Link->Link.pNext; + } + + if(Link == NULL) + return EFI_NOT_FOUND; + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(GLYPH_LINK), &New); + if(!EFI_ERROR(Status)) { + New->Char = Char; + New->Cell = Link->Cell; + New->GlyphBlock = Link->GlyphBlock; + DListAdd(&(Font->Glyphs), (DLINK *)New); + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AddGlyphs +// +// Description: +// This function adds glyphs to specified font +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// IN EFI_HII_GLYPH_INFO Cell - variable that contains font dimensions +// IN UINT8 *GlyphBlock - pointer to glyph block +// IN UINT16 Count - number of glyphs to add +// IN CHAR16 Char - first character to assign glyph to +// OUT UINTN *BytesProcessed - number of bytes from glyph block that were assigned +// +// Output: +// EFI_SUCCESS - glyph created successfully +// EFI_OUT_OF_RESOURCES - not enough memory to add glyphs +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AddGlyphs( + IN OUT FONT_LINK *Font, + IN EFI_HII_GLYPH_INFO Cell, + IN UINT8 *GlyphBlock, + IN UINT16 Count, + IN CHAR16 Char, + OUT UINTN *BytesProcessed +) +{ + EFI_STATUS Status; + GLYPH_LINK *Glyph; + UINTN Bytes = ((Cell.Width + 7) / 8) * Cell.Height; + UINTN i; + + for(i = 0; i < Count; i++) { + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(GLYPH_LINK), &Glyph); + if(EFI_ERROR(Status)) + return Status; + + Glyph->Cell = Cell; + Glyph->Char = Char; + Char++; + Glyph->GlyphBlock = GlyphBlock; + GlyphBlock += Bytes; + DListAdd(&(Font->Glyphs), (DLINK *)Glyph); + } + + *BytesProcessed = Bytes * Count; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ParseGlyphs +// +// Description: +// This function parses packed glyphs and creates glyphs for characters +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// +// Output: +// EFI_ERROR - some error was encountered during parsing +// EFI_SUCCESS - glyph created successfully +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ParseGlyphs( + IN OUT FONT_LINK *Font +) +{ + EFI_STATUS Status; + CHAR16 Current = 1; + EFI_HII_GLYPH_INFO Default = Font->FontPackage->Cell; + EFI_HII_GLYPH_INFO CurCell; + UINT8 *Walker = (UINT8 *)Font->FontPackage; + UINT8 *EndMarker; + UINTN Bytes; + UINT16 CurCount; + static const EFI_HII_GLYPH_INFO ZeroCell = { 0, 0, 0, 0, 0 }; + EFI_HII_GLYPH_INFO ChangeCell; + UINTN BelowBaseLine; + UINTN AboveBaseLine; + UINTN MaxBelowBaseLine = 0; + UINTN MaxAboveBaseLine = 0; + + EndMarker = Walker + Font->FontPackage->Header.Length; + Walker += Font->FontPackage->GlyphBlockOffset; + ChangeCell = Default; + + do { + switch (*Walker) { + case EFI_HII_GIBT_SKIP1: + Current += ((EFI_HII_GIBT_SKIP1_BLOCK *)Walker)->SkipCount; + Walker += sizeof(EFI_HII_GIBT_SKIP1_BLOCK); + break; + case EFI_HII_GIBT_SKIP2: + Current += ((EFI_HII_GIBT_SKIP2_BLOCK *)Walker)->SkipCount; + Walker += sizeof(EFI_HII_GIBT_SKIP2_BLOCK); + break; + case EFI_HII_GIBT_EXT1: + Walker += sizeof(EFI_HII_GIBT_EXT1_BLOCK); + break; + case EFI_HII_GIBT_EXT2: + Walker += sizeof(EFI_HII_GIBT_EXT2_BLOCK); + break; + case EFI_HII_GIBT_EXT4: + Walker += sizeof(EFI_HII_GIBT_EXT4_BLOCK); + break; + case EFI_HII_GIBT_DEFAULTS: + Default = ((EFI_HII_GIBT_DEFAULTS_BLOCK *)Walker)->Cell; + ChangeCell = Default; + Walker += sizeof(EFI_HII_GIBT_DEFAULTS_BLOCK); + break; + case EFI_HII_GIBT_END: + break; + case EFI_HII_GIBT_GLYPH: + CurCell = ((EFI_HII_GIBT_GLYPH_BLOCK *)Walker)->Cell; + ChangeCell = CurCell; + Walker += sizeof(EFI_HII_GIBT_GLYPH_BLOCK); + Status = AddGlyphs(Font, CurCell, Walker, 1, Current, &Bytes); + if(EFI_ERROR(Status)) + return Status; + Walker += Bytes; + Current++; + break; + case EFI_HII_GIBT_GLYPH_DEFAULT: + Walker += sizeof(EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK); + Status = AddGlyphs(Font, Default, Walker, 1, Current, &Bytes); + if(EFI_ERROR(Status)) + return Status; + Walker += Bytes; + Current++; + break; + case EFI_HII_GIBT_GLYPHS: + CurCell = ((EFI_HII_GIBT_GLYPHS_BLOCK *)Walker)->Cell; + CurCount = ((EFI_HII_GIBT_GLYPHS_BLOCK *)Walker)->Count; + ChangeCell = CurCell; + Walker += sizeof(EFI_HII_GIBT_GLYPHS_BLOCK); + Status = AddGlyphs(Font, CurCell, Walker, CurCount, Current, &Bytes); + if(EFI_ERROR(Status)) + return Status; + Walker += Bytes; + Current += CurCount; + break; + case EFI_HII_GIBT_GLYPHS_DEFAULT: + CurCount = ((EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK *)Walker)->Count; + Walker += sizeof(EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK); + Status = AddGlyphs(Font, Default, Walker, CurCount, Current, &Bytes); + if(EFI_ERROR(Status)) + return Status; + Walker += Bytes; + Current += CurCount; + break; + case EFI_HII_GIBT_DUPLICATE: + Status = DuplicateGlyph(Font, Current, ((EFI_HII_GIBT_DUPLICATE_BLOCK *)Walker)->CharValue); + if(EFI_ERROR(Status)) + return Status; + Walker += sizeof(EFI_HII_GIBT_DUPLICATE_BLOCK); + Current++; + break; + default: + return EFI_NOT_FOUND; + } + + if(MemCmp(&ChangeCell, (VOID *)&ZeroCell, sizeof(EFI_HII_GLYPH_INFO))) { + if(ChangeCell.OffsetY < 0) { + BelowBaseLine = (UINTN)(0 - ChangeCell.OffsetY); + AboveBaseLine = (ChangeCell.Height > BelowBaseLine) ? (ChangeCell.Height - BelowBaseLine) : 0; + } else { + AboveBaseLine = ChangeCell.Height + ChangeCell.OffsetY; + BelowBaseLine = 0; + } + MaxBelowBaseLine = (MaxBelowBaseLine >= BelowBaseLine) ? MaxBelowBaseLine : BelowBaseLine; + MaxAboveBaseLine = (MaxAboveBaseLine >= AboveBaseLine) ? MaxAboveBaseLine : AboveBaseLine; + ChangeCell = ZeroCell; + } + + } while(*Walker != 0 && Walker <= EndMarker); + + Font->FontHeight = MaxBelowBaseLine + MaxAboveBaseLine; + Font->FontBaseLine = MaxAboveBaseLine; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: RepackGlyphBlock +// +// Description: +// This function repacks glyph block of AMI custom font package to be similar +// to proportional font glyph block for easier processing +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// +// Output: +// EFI_ERROR - some error was encountered during parsing +// EFI_SUCCESS - glyph created successfully +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS RepackGlyphBlock( + IN UINT8 *GlyphBlock, + IN UINT16 Width, + IN UINT16 Height +) +{ + EFI_STATUS Status; + UINTN Size; + UINT8 *Tmp; + UINT16 Line; + UINT16 i, j, k = 0; + + Line = (Width + 7) / 8; //how many bytes describe one line of glyph + Size = Line * Height; + Status = pBS->AllocatePool(EfiBootServicesData, Size, &Tmp); + if(EFI_ERROR(Status)) + return Status; + + for(i = 0; i < Height; i++) { + for(j = 0; j < Line; j++) { + Tmp[k] = GlyphBlock[i + j * Height]; + k++; + } + } + MemCpy(GlyphBlock, Tmp, Size); + pBS->FreePool(Tmp); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ParseAmiGlyphs +// +// Description: +// This function parses custom AMI packed glyphs and creates glyphs for characters +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// +// Output: +// EFI_ERROR - some error was encountered during parsing +// EFI_SUCCESS - glyph created successfully +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ParseAmiGlyphs( + IN OUT FONT_LINK *Font +) +{ + EFI_STATUS Status; + EFI_NARROW_GLYPH *Walker; + EFI_HII_GLYPH_INFO CurCell; + AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *AmiHdr; + UINT16 i; + UINTN Bytes; + + AmiHdr = (AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *)Font->FontPackage; + CurCell.Width = AmiHdr->Width; + CurCell.Height = AmiHdr->Height; + CurCell.OffsetX = 0; + CurCell.OffsetY = 0; + Walker = (EFI_NARROW_GLYPH *)(AmiHdr + 1); + for(i = 0; i < AmiHdr->NumberOfNarrowGlyphs; i++) { + CurCell.AdvanceX = (Walker->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : CurCell.Width; + Status = RepackGlyphBlock(Walker->GlyphCol1, CurCell.Width, CurCell.Height); + if(EFI_ERROR(Status)) + return Status; + Status = AddGlyphs(Font, CurCell, Walker->GlyphCol1, 1, Walker->UnicodeWeight, &Bytes); + if(EFI_ERROR(Status)) + return Status; + + Walker = (EFI_NARROW_GLYPH *)(Walker->GlyphCol1 + Bytes); + } + + Font->FontHeight = AmiHdr->Height; + Font->FontBaseLine = AmiHdr->Height; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ParseFontsPackage +// +// Description: +// This function parses font package +// +// Input: +// IN EFI_HII_FONT_PACKAGE_HDR *Package - pointer to font package +// +// Output: +// EFI_ERROR - some error was encountered during parsing +// EFI_SUCCESS - glyph created successfully +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ParseFontsPackage( + IN EFI_HII_FONT_PACKAGE_HDR *Package +) +{ + EFI_STATUS Status; + EFI_HII_FONT_PACKAGE_HDR *Copy; + FONT_LINK *Font; + +/* first make global copy of the package */ + Status = pBS->AllocatePool(EfiBootServicesData, Package->Header.Length, &Copy); + if(EFI_ERROR(Status)) + return Status; + MemCpy(Copy, Package, Package->Header.Length); + +/* create Font link */ + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(FONT_LINK), &Font); + if(EFI_ERROR(Status)) + return Status; + +/* initialize font link */ + Font->FontPackage = Copy; + DListInit(&(Font->Glyphs)); + + if(Package->Header.Type == AMI_HII_PACKAGE_FONTS) + Status = ParseAmiGlyphs(Font); + else + Status = ParseGlyphs(Font); + + if(!EFI_ERROR(Status)) + DListAdd(&(PrivateData.FontList), (DLINK *)Font); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MatchName +// +// Description: +// This function checks whether passed name matches name of the passed font +// +// Input: +// IN FONT_LINK *Font - pointer to font +// IN CHAR16 *FontName - pointer to font name to match with +// IN FONT_MATCH_MASK Mask - matching rules +// +// Output: +// TRUE - names are matched +// FALSE - names are not matched +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MatchName( + IN FONT_LINK *Font, + IN CHAR16 *FontName, + IN FONT_MATCH_MASK Mask +) +{ + UINT8 *Walker; + + if(Mask.MatchName == MATCH_INGNORE) + return TRUE; + + if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS && + !Wcscmp(FontName, L"Ami font")) + return TRUE; + + Walker = (UINT8 *)Font->FontPackage; + Walker += sizeof(EFI_HII_FONT_PACKAGE_HDR); + /* now Walker points to font name */ + if(Wcscmp(FontName, (CHAR16 *)Walker)) + return FALSE; + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MatchStyle +// +// Description: +// This function checks whether passed style matches style of the passed font +// +// Input: +// IN FONT_LINK *Font - pointer to font +// IN EFI_HII_FONT_STYLE FontStyle - font style to match with +// IN FONT_MATCH_MASK Mask - matching rules +// +// Output: +// TRUE - styles are matched +// FALSE - styles are not matched +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MatchStyle( + IN FONT_LINK *Font, + IN EFI_HII_FONT_STYLE FontStyle, + IN FONT_MATCH_MASK Mask +) +{ + EFI_HII_FONT_STYLE Cur; + + if(Mask.MatchStyle == MATCH_INGNORE) + return TRUE; + + if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS) + Cur = EFI_HII_FONT_STYLE_NORMAL; + else + Cur = Font->FontPackage->FontStyle; + + if(FontStyle == Cur) + return TRUE; + +/* when restyle is ordered we support interchange between Normal, Bold and Italic styles */ + if(Mask.MatchStyle == MATCH_LOOSE && + FontStyle <= 3 && + Cur <= 3) + return TRUE; + + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MatchSize +// +// Description: +// This function checks whether passed size matches size of the passed font +// +// Input: +// IN FONT_LINK *Font - pointer to font +// IN UINT16 FontSize - font size to match with +// IN FONT_MATCH_MASK Mask - matching rules +// +// Output: +// TRUE - sizes are matched +// FALSE - sizes are not matched +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MatchSize( + IN FONT_LINK *Font, + IN UINT16 FontSize, + IN FONT_MATCH_MASK Mask +) +{ + UINT16 Cur; + + if(Mask.MatchSize == MATCH_INGNORE) + return TRUE; + + if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS) + Cur = ((AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *)Font->FontPackage)->Height; + else + Cur = Font->FontPackage->Cell.Height; + + if(FontSize == Cur) + return TRUE; + +/* when resize is ordered we support interchange sizes within +/- LOOSE_SIZE_MARGIN from given size */ + if(Mask.MatchSize == MATCH_LOOSE && + Cur <= FontSize + LOOSE_SIZE_MARGIN && + Cur >= FontSize - LOOSE_SIZE_MARGIN) + return TRUE; + + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindGlyph +// +// Description: +// This function checks whether glyph for passed character is present, and returns it +// if necessary +// +// Input: +// IN DLIST Glyphs - linked list of glyphs to search within +// IN CHAR16 Char - character value to return glyph for +// OUT GLYPH_LINK **Match OPTIONAL - pointer to store returned glyph +// +// Output: +// TRUE - glyph found +// FALSE - glyph not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN FindGlyph( + IN DLIST Glyphs, + IN CHAR16 Char, + OUT GLYPH_LINK **Match OPTIONAL +) +{ + GLYPH_LINK *Link = (GLYPH_LINK *)Glyphs.pHead; + + while(Link != NULL) { + if(Link->Char == Char) { + if(Match != NULL) + *Match = Link; + return TRUE; + } + Link = (GLYPH_LINK *)Link->Link.pNext; + } + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MatchString +// +// Description: +// This function checks whether all character glyphs are present for given string +// +// Input: +// IN FONT_LINK *Font - pointer to the font +// IN CONST EFI_STRING String - pointer to the string to check +// +// Output: +// TRUE - all glyphs are present +// FALSE - some glyphs are missing +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MatchString( + IN FONT_LINK *Font, + IN CONST EFI_STRING String +) +{ + CHAR16 *Tst; + + if(String == NULL) + return TRUE; + + Tst = String; + + while(*Tst != 0) { + if(!FindGlyph(Font->Glyphs, *Tst, NULL)) + return FALSE; + Tst++; + } + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindFont +// +// Description: +// This function tries to find font in database, that meets the criteria +// +// Input: +// IN OUT EFI_FONT_HANDLE *FontHandle - handle in database to start search from +// IN CHAR16 *FontName - pointer to the font name +// IN EFI_HII_FONT_STYLE FontStyle - font style +// IN UINT16 FontSize - font size +// IN FONT_MATCH_MASK Mask - matching rules +// IN CONST EFI_STRING String - pointer to string to verify glyphs presence +// +// Output: +// EFI_SUCCESS - font found +// EFI_NOT_FOUND - font not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FindFont( + IN OUT EFI_FONT_HANDLE *FontHandle, + IN CHAR16 *FontName, + IN EFI_HII_FONT_STYLE FontStyle, + IN UINT16 FontSize, + IN FONT_MATCH_MASK Mask, + IN CONST EFI_STRING String +) +{ + FONT_LINK *Font; + + if(PrivateData.FontList.Size == 0) + /* no fonts in database */ + return EFI_NOT_FOUND; + + Font = (FONT_LINK *)PrivateData.FontList.pHead; + +/* check if handle passed is not NULL or dummy default font handle */ + if((UINTN)(*FontHandle) != NULL && (UINTN)(*FontHandle) != DEFAULT_FONT_HANDLE) { + while(Font != NULL) { + if((VOID *)Font == *FontHandle) + break; + Font = (FONT_LINK *)Font->Link.pNext; + } + if(Font == NULL) { + /* end of font list - no matches */ + *FontHandle = NULL; + return EFI_NOT_FOUND; + } + + /* match found, it was last returned font, move to the next */ + Font = (FONT_LINK *)Font->Link.pNext; + if(Font == NULL) { + /* end of font list, last returned font was last indeed */ + *FontHandle = NULL; + return EFI_NOT_FOUND; + } + } + + while(Font != NULL) { + /* loop through font list to find the match */ + if(MatchName(Font, FontName, Mask) && + MatchStyle(Font, FontStyle, Mask) && + MatchSize(Font, FontSize, Mask) && + MatchString(Font, String)) { + /* match is found */ + *FontHandle = (EFI_FONT_HANDLE)Font; + return EFI_SUCCESS; + } + Font = (FONT_LINK *)Font->Link.pNext; + } + *FontHandle = NULL; + return EFI_NOT_FOUND; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FillFontInfo +// +// Description: +// This function returns EFI_FONT_DISPLAY_INFO data for given font +// +// Input: +// IN EFI_FONT_HANDLE FontHandle - font handle to return info about +// OUT EFI_FONT_DISPLAY_INFO **StringInfoOut - pointer where to store returned info +// +// Output: +// EFI_SUCCESS - info returned +// EFI_OUT_OF_RESOURCES - not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FillFontInfo( + IN EFI_FONT_HANDLE FontHandle, + OUT EFI_FONT_DISPLAY_INFO **StringInfoOut +) +{ + UINTN NameSize; + EFI_FONT_DISPLAY_INFO *Ret; + FONT_LINK *Font; + UINT8 *Walker; + EFI_STATUS Status; + static CHAR16 DefaultFontName[] = L"System font"; + + Font = (FONT_LINK *)FontHandle; + if((UINTN)Font != DEFAULT_FONT_HANDLE) { + Walker = (UINT8 *)Font->FontPackage; + Walker += sizeof(EFI_HII_FONT_PACKAGE_HDR); + } else { + Walker = (UINT8 *)DefaultFontName; + } + + NameSize = Wcslen((CHAR16 *)Walker) * sizeof(CHAR16); + +/* font display info structure includes font info structure, where one CHAR16 already reserved + that's why Wcslen used instead fo Wcssize - null-terminator already accounted for */ + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(EFI_FONT_DISPLAY_INFO) + NameSize, &Ret); + if(!EFI_ERROR(Status)) { + if((UINTN)Font != DEFAULT_FONT_HANDLE) { + if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS) { + Ret->FontInfo.FontStyle = EFI_HII_FONT_STYLE_NORMAL; + Ret->FontInfo.FontSize = ((AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *)Font->FontPackage)->Height; + } else { + Ret->FontInfo.FontStyle = Font->FontPackage->FontStyle; + Ret->FontInfo.FontSize = Font->FontPackage->Cell.Height; + } + } else { + Ret->FontInfo.FontStyle = EFI_HII_FONT_STYLE_NORMAL; + Ret->FontInfo.FontSize = EFI_GLYPH_HEIGHT; + } + Wcscpy(Ret->FontInfo.FontName, (CHAR16 *)Walker); + *StringInfoOut = Ret; + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IntGetGlyph +// +// Description: +// This function returns glyph for given charactef from given font +// +// Input: +// IN EFI_FONT_HANDLE FontHandle - font handle of the desired font +// IN CHAR16 Char - character to return glyph for +// OUT EFI_HII_GLYPH_INFO *Cell - pointer to store info about glyph dimensions +// OUT UINT8 **GlyphBlock OPTIONAL - pointer to store glyph +// OUT BOOLEAN *Free - pointer to return flag was memory allocated for glyph and +// should be freed by caller +// +// Output: +// EFI_SUCCESS - glyph returned +// EFI_NOT_FOUND - glyph not found +// EFI_OUT_OF_RESOURCES - not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS IntGetGlyph( + IN EFI_FONT_HANDLE FontHandle, + IN CHAR16 Char, + OUT EFI_HII_GLYPH_INFO *Cell, + OUT UINT8 **GlyphBlock OPTIONAL, + OUT BOOLEAN *Free +) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_STATUS AllocStatus; + FONT_LINK *Font; + GLYPH_LINK *GlyphLink; + BOOLEAN Found; + SIMPLE_FONT Glyph; + UINT8 *WideGlyphBlock; + UINTN i; + + *Free = FALSE; + Font = (FONT_LINK *)FontHandle; + + if((UINTN)Font != DEFAULT_FONT_HANDLE) { + Found = FindGlyph(Font->Glyphs, Char, &GlyphLink); + if(!Found) { + Status = EFI_WARN_UNKNOWN_GLYPH; + Found = FindGlyph(Font->Glyphs, 0xfffd, &GlyphLink); + } + if(Found) { + *Cell = GlyphLink->Cell; + if(GlyphBlock) + *GlyphBlock = GlyphLink->GlyphBlock; + return Status; + } + Glyph = DefaultFont[0xfffd]; + } else { + /* Default font requested */ + Glyph = DefaultFont[(UINTN)Char]; + if(Glyph.NarrowGlyph == NULL && Glyph.WideGlyph == NULL) { + Glyph = DefaultFont[0xfffd]; + Status = EFI_WARN_UNKNOWN_GLYPH; + } + } +/* if we're here we use system font - either because it was requested, or +because supplied font doesn't have requested character or 0xfffd character +!!!! It is assumed that system font always have 0xfffd character font */ + Cell->Height = EFI_GLYPH_HEIGHT; + Cell->OffsetX = 0; + Cell->OffsetY = 0; + if(Glyph.NarrowGlyph != NULL) { + Cell->Width = EFI_GLYPH_WIDTH; + Cell->AdvanceX = ((Glyph.NarrowGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDTH; + if(GlyphBlock) + *GlyphBlock = (Glyph.NarrowGlyph)->GlyphCol1; + } else if(Glyph.WideGlyph != NULL) { + Cell->Width = EFI_GLYPH_WIDE_WIDTH; + Cell->AdvanceX = ((Glyph.WideGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDE_WIDTH; + if(GlyphBlock) { + AllocStatus = pBS->AllocatePool(EfiBootServicesData, sizeof(UINT8) * 2 * EFI_GLYPH_HEIGHT, &WideGlyphBlock); + if(EFI_ERROR(AllocStatus)) + return AllocStatus; + for(i = 0; i < EFI_GLYPH_HEIGHT; i++) { + WideGlyphBlock[2 * i] = (Glyph.WideGlyph)->GlyphCol1[i]; + WideGlyphBlock[2 * i + 1] = (Glyph.WideGlyph)->GlyphCol2[i]; + } + *GlyphBlock = WideGlyphBlock; + *Free = TRUE; + } + } else { + Cell->AdvanceX = 0; + return EFI_NOT_FOUND; + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: UpdateLineSize +// +// Description: +// This function updates dimensions in pixels of given line based on glyphs of current font +// +// Input: +// IN OUT DRAW_LINE *Line - pointer to the line structure +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID UpdateLineSize( + IN OUT DRAW_LINE *Line +) +{ + EFI_STATUS Status; + UINTN Width = 0; + UINTN i; + EFI_HII_GLYPH_INFO Cell; + BOOLEAN Dummy; + + for(i = Line->StartIndex; i <= Line->EndIndex; i++) { + if((DrawFlags & EFI_HII_IGNORE_LINE_BREAK) && IsLineBreak(DrawString[i])) + continue; + + Status = IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy); + if(Status == EFI_WARN_UNKNOWN_GLYPH && (DrawFlags & EFI_HII_IGNORE_IF_NO_GLYPH)) + continue; + + Width = (Cell.AdvanceX < 0) ? Width : Width + (UINT16)Cell.AdvanceX; + } + Line->LineWidth = Width; + Line->LineHeight = ((UINTN)CurFont == DEFAULT_FONT_HANDLE) ? Cell.Height : ((FONT_LINK *)CurFont)->FontHeight; + Line->BaseLineOffset = ((UINTN)CurFont == DEFAULT_FONT_HANDLE) ? Cell.Height : ((FONT_LINK *)CurFont)->FontBaseLine; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ClipLine +// +// Description: +// This function updates dimensions in pixels of given line to fit given width +// +// Input: +// IN OUT DRAW_LINE *Line - pointer to the line structure +// IN UINTN Width - width to fit +// IN BOOLEAN ClipClean - clipping mode +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID ClipLine( + IN OUT DRAW_LINE *Line, + IN UINTN Width, + IN BOOLEAN ClipClean +) +{ + UINTN Excess; + UINTN i; + EFI_HII_GLYPH_INFO Cell; + BOOLEAN Dummy; + + Excess = Line->LineWidth - Width; + + for(i = Line->EndIndex; i >= Line->StartIndex; i--) { + IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy); + if ((INTN)Excess <= Cell.AdvanceX) + break; + Excess -= Cell.AdvanceX; + Line->LineWidth -= Cell.AdvanceX; + } + + if(Excess == Cell.AdvanceX || ClipClean) { + /* remove excess character */ + i--; + Line->LineWidth -= Cell.AdvanceX; + IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy); + if(Cell.AdvanceX == 0) + /* the previous character is non-spacing -remove it also */ + i--; + } else { + /* perform partial clipping */ + Line->LineWidth -= Excess; + } + Line->EndIndex = i; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: WrapLine +// +// Description: +// This function updates dimensions in pixels of given line to fit given width +// and creates additional line if necessary +// +// Input: +// IN OUT DRAW_LINE *Line - pointer to the line structure +// IN UINTN Width - width to fit +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS WrapLine( + IN OUT DRAW_LINE *Line, + IN UINTN Width +) +{ + UINTN Excess; + UINTN i; + UINTN NewEnd; + UINTN NewStart; + DRAW_LINE *NewLine; + EFI_HII_GLYPH_INFO Cell; + BOOLEAN Dummy; + UINTN Save; + + Excess = Line->LineWidth - Width; + + for(i = Line->EndIndex; (i >= Line->StartIndex && i != 0); i--) { + IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy); + if ((INTN)Excess <= Cell.AdvanceX) + break; + Excess -= Cell.AdvanceX; + } + if(i == 0 || i == Line->StartIndex) { + Line->EndIndex = i; + Line->LineWidth = 0; + return EFI_SUCCESS; + } else { + Save = i; //save index of first excess character + } //we will you it if no break opp arises for clip_clean operation + +/* we skipped excessed characters - start search for line break opp */ + for(; (i >= Line->StartIndex && i != 0); i--) { + if(IsLineBreakOpp(DrawString[i])) { + /* we found line break opportunity */ + NewEnd = Line->EndIndex; + NewStart = i + 1; + Line->EndIndex = i; + UpdateLineSize(Line); + if(Line->LineWidth > Width) + /* case when line-break opp character is partially visible - skip it */ + Line->EndIndex--; + /* add a new line */ + NewLine = (DRAW_LINE *)CreateNewLink(sizeof(UINTN) * 5); + if(NewLine == NULL) + return EFI_OUT_OF_RESOURCES; + NewLine->StartIndex = NewStart; + NewLine->EndIndex = NewEnd; + UpdateLineSize(NewLine); + DListInsert(&DrawLines, (DLINK *)NewLine, (DLINK *)Line); + return EFI_SUCCESS; + } + } +/* if we're here, no line break opp present, use clip clean */ + Line->EndIndex = Save - 1; + UpdateLineSize(Line); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetDrawImageSize +// +// Description: +// This function returns size of image necessary to fit processing string +// including all wraps and clips +// +// Input: +// OUT UINTN *Width - pointer to store required width +// OUT UINTN *Height - pointer to store required height +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID GetDrawImageSize( + OUT UINTN *Width, + OUT UINTN *Height +) +{ + DRAW_LINE *Link; + UINTN MaxWidth = 0; + UINTN MaxHeight = 0; + + Link = (DRAW_LINE *)(DrawLines.pHead); + while(Link != NULL) + { + MaxWidth = (MaxWidth < Link->LineWidth) ? Link->LineWidth : MaxWidth; + MaxHeight += Link->LineHeight; + Link = (DRAW_LINE *)Link->Link.pNext; + } + *Width = MaxWidth; + *Height = MaxHeight; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PixelSet +// +// Description: +// This function checks whether pixel with given coordinates is set in given glyph +// +// Input: +// IN UINTN PosX - X coordinate of pixel +// IN UINTN PosY - Y coordinate of pixel +// IN UINT8 *GlyphBlock - pointer to glyph array +// IN UINT16 CharWidth - width of character described by glyph +// +// Output: +// TRUE - pixel is set +// FALSE - pixel is not set +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN PixelSet( + IN UINTN PosX, + IN UINTN PosY, + IN UINT8 *GlyphBlock, + IN UINT16 CharWidth +) +{ + UINTN Step; + UINTN Index; + UINT8 Bit; + + Step = (CharWidth + 7) / 8; + Index = (PosY * Step) + (PosX / 8); + + Bit = (0x80 >> (PosX % 8)); + + return (Bit & GlyphBlock[Index]); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DrawGlyph +// +// Description: +// This function draws given glyph on given bitmap +// +// Input: +// IN UINTN StartX - start X coordinate of glyph +// IN UINTN StartY - start Y coordinate of glyph +// IN UINTN SizeX - width of glyph +// IN UINTN SizeY - height of glyph +// IN UINT8 *GlyphBlock - pointer to glyph array +// IN BOOLEAN Transparent - flag if image should be transparent +// IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt - bitmap to draw on +// IN UINT16 CharWidth - width of character described by glyph +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID DrawGlyph( + IN UINTN StartX, + IN UINTN StartY, + IN UINTN SizeX, + IN UINTN SizeY, + IN UINT8 *GlyphBlock, + IN BOOLEAN Transparent, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt, + IN UINT16 CharWidth +) +{ + UINTN i; + UINTN j; + UINTN Index; + UINTN Base; + + Base = StartX + StartY * ImageWidth; + for(i = 0; i < SizeY; i++ ) { + for(j = 0; j < SizeX; j++) { + Index = Base + i * ImageWidth + j; + if(PixelSet(j, i, GlyphBlock, CharWidth)) { + Blt[Index] = DefForegroundColor; + } else if (!Transparent) { + Blt[Index] = DefBackgroundColor; + } + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CheckVisible +// +// Description: +// This function checks whether glyph is withing given image rectangle, +// and clips glyph rectangle if necessary +// +// Input: +// IN OUT RECT_COORD *Glyph - pointer to glyph rectangle +// IN RECT_COORD *Image - pointer to image rectangle +// +// Output: +// TRUE - glyph is visible (at least partially) +// FALSE - glyph is out of image boundaries +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN CheckVisible( + IN OUT RECT_COORD *Glyph, + IN RECT_COORD *Image +) +{ + UINTN delta_x; + UINTN delta_y; + +/* check whether glyph within given image rectangle */ + if(Glyph->st->x >= (Image->st->x + Image->size->x) || + Glyph->st->y >= (Image->st->y + Image->size->y)) + return FALSE; + +/* clip glyph size if necessary */ + delta_x = (Image->st->x < Glyph->st->x) ? Glyph->st->x - Image->st->x : 0; + delta_y = (Image->st->y < Glyph->st->y) ? Glyph->st->y - Image->st->y : 0; + + if(Glyph->size->x > (Image->size->x - delta_x)) + Glyph->size->x = Image->size->x - delta_x; + + if(Glyph->size->y > (Image->size->y - delta_y)) + Glyph->size->y = Image->size->y - delta_y; + return TRUE; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |