refactoring text handling

Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
This commit is contained in:
Sergey Isakov 2020-04-07 22:48:36 +03:00
parent 166dcaa7ba
commit 75427f2d83
14 changed files with 633 additions and 303 deletions

View File

@ -5067,11 +5067,12 @@ InitTheme(BOOLEAN UseThemeDefinedInNVRam, EFI_TIME *Time)
}
*/
//TODO switch to XImage
if (FontImage != NULL) {
// if (FontImage != NULL) {
// DBG("free font image\n"); //raster font
egFreeImage (FontImage);
FontImage = NULL;
}
// egFreeImage (FontImage);
// FontImage = NULL;
// }
ThemeX.FontImage.setEmpty();
Rnd = ((Time != NULL) && (ThemesNum != 0)) ? Time->Second % ThemesNum : 0;
@ -5229,7 +5230,10 @@ finish:
if (ChosenTheme != NULL) {
FreePool (ChosenTheme);
}
PrepareFont();
if (!ThemeX.TypeSVG) {
ThemeX.PrepareFont();
}
ThemeX.ClearScreen();
return Status;
}
@ -5488,7 +5492,10 @@ finish:
if (ChosenTheme != NULL) {
FreePool (ChosenTheme);
}
PrepareFont();
if (!GlobalConfig.TypeSVG) {
PrepareFont();
}
return Status;
}
@ -8261,7 +8268,7 @@ GetDevices ()
snprintf (SlotDevice->SlotName, 31, "AirPort");
SlotDevice->SlotID = 0;
SlotDevice->SlotType = SlotTypePciExpressX1;
DBG(" - WIFI: Vendor=%d", Pci.Hdr.VendorId);
DBG(" - WIFI: Vendor=%d = ", Pci.Hdr.VendorId);
switch (Pci.Hdr.VendorId) {
case 0x11ab:
DBG("Marvell\n");
@ -8439,11 +8446,11 @@ SetDevices (LOADER_ENTRY *Entry)
while (Prop2) {
if (Prop2->MenuItem.BValue) {
if (AsciiStrStr(Prop2->Key, "-platform-id") != NULL) {
if (gSettings.IgPlatform == 0) {
if (gSettings.IgPlatform == 0 && Prop2->Value) {
CopyMem((UINT8*)&gSettings.IgPlatform, (UINT8*)Prop2->Value, Prop2->ValueLen);
}
devprop_add_value(device, Prop2->Key, (UINT8*)&gSettings.IgPlatform, 4);
DBG(" Add key=%s valuelen=%llu\n", Prop2->Key, Prop2->ValueLen);
DBG(" Add key=%s valuelen=%llu\n", Prop2->Key, Prop2->ValueLen);
} else if ((AsciiStrStr(Prop2->Key, "override-no-edid") || AsciiStrStr(Prop2->Key, "override-no-connect"))
&& gSettings.InjectEDID && gSettings.CustomEDID) {
// special case for EDID properties
@ -8451,7 +8458,7 @@ SetDevices (LOADER_ENTRY *Entry)
DBG(" Add key=%s from custom EDID\n", Prop2->Key);
} else {
devprop_add_value(device, Prop2->Key, (UINT8*)Prop2->Value, Prop2->ValueLen);
DBG(" Add key=%s valuelen=%llu\n", Prop2->Key, Prop2->ValueLen);
DBG(" Add key=%s valuelen=%llu\n", Prop2->Key, Prop2->ValueLen);
}
}
@ -8524,7 +8531,7 @@ SetDevices (LOADER_ENTRY *Entry)
}
//------------------
if (PCIdevice.used) {
DBG("custom properties for device %02llX:%02llX.%02llX injected\n", Bus, Device, Function);
DBG("custom properties for device %02llX:%02llX.%02llX injected\n", Bus, Device, Function);
//continue;
}
//}
@ -8565,7 +8572,7 @@ SetDevices (LOADER_ENTRY *Entry)
*(UINT32*)(gGraphics[j].Mmio + 0x6800) = 1; //EVERGREEN_GRPH_ENABLE
*(UINT32*)(gGraphics[j].Mmio + 0x6EF8) = 0; //EVERGREEN_MASTER_UPDATE_MODE
//*(UINT32*)(gGraphics[j].Mmio + R600_BIOS_0_SCRATCH) = 0x00810000;
DBG("Device %llu deinited\n", j);
DBG("Device %llu deinited\n", j);
}
}
}

View File

@ -508,7 +508,7 @@ VOID GetCPUProperties (VOID)
// MsgLog("MSR 0xE4 %08X\n", msr);
//------------
msr = AsmReadMsr64(MSR_PLATFORM_INFO); //0xCE
MsgLog("MSR 0xCE %08llX_%08llX\n", (msr>>32), msr);
MsgLog("MSR 0xCE %08llX_%08llX\n", (msr>>32), msr & 0xFFFFFFFFull);
gCPUStructure.MaxRatio = (UINT8)RShiftU64(msr, 8) & 0xff;
gCPUStructure.MinRatio = (UINT8)MultU64x32(RShiftU64(msr, 40) & 0xff, 10);
//--- Check if EIST locked
@ -1130,7 +1130,7 @@ VOID GetCPUProperties (VOID)
// DBG("Family/ExtFamily: 0x%X/0x%X\n", gCPUStructure.Family, gCPUStructure.Extfamily);
DBG("MaxDiv/MinDiv: %d.%d/%d\n", gCPUStructure.MaxRatio/10, gCPUStructure.MaxRatio%10 , gCPUStructure.MinRatio/10);
DBG("Turbo: %d/%d/%d/%d\n", gCPUStructure.Turbo4/10, gCPUStructure.Turbo3/10, gCPUStructure.Turbo2/10, gCPUStructure.Turbo1/10);
DBG("Features: 0x%08llX\n",gCPUStructure.Features);
DBG("Features: 0x%llX\n",gCPUStructure.Features);
DBG("Threads: %d\n",gCPUStructure.Threads);
DBG("Cores: %d\n",gCPUStructure.Cores);
DBG("FSB: %d MHz\n", (INT32)(DivU64x32(gCPUStructure.FSBFrequency, Mega)));
@ -1155,7 +1155,7 @@ VOID SetCPUProperties (VOID)
msr = gSettings.SavingMode;
AsmWriteMsr64(IA32_ENERGY_PERF_BIAS, msr);
msr = AsmReadMsr64(IA32_ENERGY_PERF_BIAS); //0x1B0
MsgLog("MSR 0x1B0 set to %08llX\n", msr);
MsgLog("MSR 0x1B0 set to %llX\n", msr);
}
}

View File

@ -242,11 +242,11 @@ template<class TYPE>
TYPE &XArray<TYPE>::ElementAt(int index)
{
// #ifdef _DEBUG
if ( index < 0 ) {
if ( index < 0 ) {
panic("XArray::ElementAt(int) -> Operator [] : index < 0");
}
if ( (unsigned int)index >= m_len ) { // cast safe, index > 0
DebugLog(2, "XArray::ElementAt(xsize) -> Operator [] : index > m_len");
DebugLog(2, "XArray::ElementAt(int) -> Operator [] : index > m_len");
panic();
}
// #endif
@ -258,11 +258,11 @@ template<class TYPE>
const TYPE& XArray<TYPE>::ElementAt(int index) const
{
// #ifdef _DEBUG
if ( index < 0 ) {
if ( index < 0 ) {
panic("XArray::ElementAt(int) const -> Operator [] : index < 0");
}
if ( (unsigned int)index >= m_len ) { // cast ok as index > 0. Ideally cast would be like '(unsigned __typeof__(index))'
DebugLog(2, "XArray::ElementAt(xsize) const -> Operator [] : index > m_len");
DebugLog(2, "XArray::ElementAt(int) const -> Operator [] : index > m_len");
panic();
}
// #endif

View File

@ -142,6 +142,29 @@ STATIC LINUX_PATH_DATA LinuxEntryData[] = {
#endif
{ L"\\EFI\\SuSe\\elilo.efi", L"OpenSuse EFI boot menu", L"suse,linux" },
};
/* TODO
DirIterOpen (SelfRootDir, L"\\EFI", &DirIter);
while (DirIterNext(&DirIter, 1, L"*", &DirEntry)) {
if (DirEntry->FileName[0] == '.') {
//DBG("Skip folder: %ls\n", DirEntry->FileName);
continue;
}
XStringW OSName = SWPrintf(L"%s", DirEntry->FileName);
XStringW File = SWPrintf(L"EFI\\%s\\grubx64.efi", DirEntry->FileName);
// if exist the linux = DirEntry->FileName
OSIconName = OSName + L",linux"
}
DirIterClose (&DirIter);
CONST CHAR16 *Path; -- File
CONST CHAR16 *Title; -- OSName + L" OS EFI boot menu"
CONST CHAR16 *Icon; -- OSName + L",linux"
CONST CHAR8 *Issue; -- OSName
*/
STATIC CONST UINTN LinuxEntryDataCount = (sizeof(LinuxEntryData) / sizeof(LINUX_PATH_DATA));
#if defined(ANDX86)
@ -1380,12 +1403,7 @@ VOID ScanLoader(VOID)
if (Path != NULL) {
XString Options = LinuxKernelOptions(Iter.DirHandle, Basename(Path) + LINUX_LOADER_PATH.length(), PartUUID, ""_XS);
// Add the entry
#if USE_XTHEME
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#else
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#endif
FreePool(Path);
}
@ -1470,11 +1488,7 @@ VOID ScanLoader(VOID)
if (Path != NULL) {
XString Options = LinuxKernelOptions(Iter.DirHandle, XStringW().takeValueFrom(Basename(Path) + LINUX_LOADER_PATH.length()).wc_str(), PartUUID, ""_XS);
// Add the entry
#if USE_XTHEME
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#else
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#endif
FreePool(Path);
}
break;
@ -1505,11 +1519,8 @@ VOID ScanLoader(VOID)
if (Path != NULL) {
XString Options = LinuxKernelOptions(Iter.DirHandle, XStringW().takeValueFrom(Basename(Path) + LINUX_LOADER_PATH.length()).wc_str(), PartUUID, ""_XS);
// Add the entry
#if USE_XTHEME
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#else
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#endif
FreePool(Path);
}
break;
@ -1539,11 +1550,7 @@ VOID ScanLoader(VOID)
}
if (Path != NULL) {
XString Options = LinuxKernelOptions(Iter.DirHandle, Basename(Path) + LINUX_LOADER_PATH.length(), PartUUID, ""_XS);
#if USE_XTHEME
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#else
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#endif
FreePool(Path);
}
break;
@ -1558,11 +1565,7 @@ VOID ScanLoader(VOID)
if (Path != NULL) {
XString Options = LinuxKernelOptions(Iter.DirHandle, Basename(Path) + LINUX_LOADER_PATH.length(), PartUUID, ""_XS);
// Add the entry
#if USE_XTHEME
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#else
AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS);
#endif
FreePool(Path);
}
}

View File

@ -392,7 +392,7 @@ VOID REFIT_MENU_SCREEN::UpdateScroll(IN UINTN Movement)
ScrollbarOldPointerPlace.XPos = ScrollbarNewPointerPlace.XPos;
ScrollbarOldPointerPlace.YPos = ScrollbarNewPointerPlace.YPos;
Lines = ScrollbarYMovement * ScrollState.MaxIndex / ScrollbarBackground.Height;
ScrollbarYMovement = ScrollbarYMovement - Lines * (ScrollState.MaxVisible * TextHeight - 16 - 1) / ScrollState.MaxIndex;
ScrollbarYMovement = ScrollbarYMovement - Lines * (ScrollState.MaxVisible * ThemeX.TextHeight - 16 - 1) / ScrollState.MaxIndex;
if (Lines < 0) {
Lines = -Lines;
ScrollMovement = SCROLL_SCROLL_UP;
@ -882,13 +882,13 @@ UINTN REFIT_MENU_SCREEN::RunGenericMenu(IN MENU_STYLE_FUNC StyleFunc, IN OUT INT
TextStyle = 1;
} else {
DBG("no valid text style\n");
textFace[TextStyle].size = TextHeight - 4;
textFace[TextStyle].size = ThemeX.TextHeight - 4;
}
}
if (textFace[TextStyle].valid) {
// TextHeight = (int)((textFace[TextStyle].size + 4) * GlobalConfig.Scale);
//clovy - row height / text size factor
TextHeight = (int)((textFace[TextStyle].size * RowHeightFromTextHeight) * ThemeX.Scale);
ThemeX.TextHeight = (int)((textFace[TextStyle].size * RowHeightFromTextHeight) * ThemeX.Scale);
}
}
#else
@ -1505,15 +1505,15 @@ INTN REFIT_MENU_SCREEN::DrawTextXY(IN const XStringW& Text, IN INTN XPos, IN INT
}
if (!isBootScreen && ThemeX.TypeSVG) {
TextWidth += TextHeight * 2; //give more place for buffer
TextWidth += ThemeX.TextHeight * 2; //give more place for buffer
if (!textFace[TextXYStyle].valid) {
DBG("no vaid text face for message!\n");
Height = TextHeight;
Height = ThemeX.TextHeight;
} else {
Height = (int)(textFace[TextXYStyle].size * RowHeightFromTextHeight * ThemeX.Scale);
}
} else {
Height = TextHeight;
Height = ThemeX.TextHeight;
}
// TextBufferXY = egCreateFilledImage(TextWidth, Height, TRUE, &MenuBackgroundPixel);
@ -1521,7 +1521,7 @@ INTN REFIT_MENU_SCREEN::DrawTextXY(IN const XStringW& Text, IN INTN XPos, IN INT
// TextBufferXY.Fill(MenuBackgroundPixel);
// render the text
INTN TextWidth2 = egRenderText(Text, &TextBufferXY, 0, 0, 0xFFFF, TextXYStyle);
INTN TextWidth2 = ThemeX.RenderText(Text, &TextBufferXY, 0, 0, 0xFFFF, TextXYStyle);
// there is real text width but we already have an array with Width = TextWidth
//
// TextBufferXY.EnsureImageSize(TextWidth2, Height); //assume color = MenuBackgroundPixel
@ -1595,8 +1595,8 @@ VOID REFIT_MENU_SCREEN::DrawBCSText(IN CONST CHAR16 *Text, IN INTN XPos, IN INTN
#if USE_XTHEME
VOID REFIT_MENU_SCREEN::DrawMenuText(IN XStringW& Text, IN INTN SelectedWidth, IN INTN XPos, IN INTN YPos, IN INTN Cursor)
{
XImage TextBufferX(UGAWidth-XPos, TextHeight);
XImage SelectionBar(UGAWidth-XPos, TextHeight);
XImage TextBufferX(UGAWidth-XPos, ThemeX.TextHeight);
XImage SelectionBar(UGAWidth-XPos, ThemeX.TextHeight);
/*
if (Cursor == 0xFFFF) { //InfoLine = 0xFFFF
TextBufferX.Fill(MenuBackgroundPixel);
@ -1609,7 +1609,7 @@ VOID REFIT_MENU_SCREEN::DrawMenuText(IN XStringW& Text, IN INTN SelectedWidth, I
// fill selection bar background
EG_RECT TextRect;
TextRect.Width = SelectedWidth;
TextRect.Height = TextHeight;
TextRect.Height = ThemeX.TextHeight;
TextBufferX.FillArea(SelectionBackgroundPixel, TextRect);
// SelectionBar.Fill(SelectionBackgroundPixel);
}
@ -1619,11 +1619,11 @@ VOID REFIT_MENU_SCREEN::DrawMenuText(IN XStringW& Text, IN INTN SelectedWidth, I
// render the text
if (ThemeX.TypeSVG) {
//clovy - text vertically centred on Height
egRenderText(Text, &TextBufferX, 0,
(INTN)((TextHeight - (textFace[TextStyle].size * ThemeX.Scale)) / 2),
ThemeX.RenderText(Text, &TextBufferX, 0,
(INTN)((ThemeX.TextHeight - (textFace[TextStyle].size * ThemeX.Scale)) / 2),
Cursor, TextStyle);
} else {
egRenderText(Text, &TextBufferX, TEXT_XMARGIN, TEXT_YMARGIN, Cursor, TextStyle);
ThemeX.RenderText(Text, &TextBufferX, TEXT_XMARGIN, TEXT_YMARGIN, Cursor, TextStyle);
}
SelectionBar.Compose(0, 0, TextBufferX, false);
// TextBufferX.DrawWithoutCompose(XPos, YPos);
@ -1789,9 +1789,9 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
InitAnime();
SwitchToGraphicsAndClear();
EntriesPosY = ((UGAHeight - (int)(LAYOUT_TOTAL_HEIGHT * ThemeX.Scale)) >> 1) + (int)(ThemeX.LayoutBannerOffset * ThemeX.Scale) + (TextHeight << 1);
EntriesPosY = ((UGAHeight - (int)(LAYOUT_TOTAL_HEIGHT * ThemeX.Scale)) >> 1) + (int)(ThemeX.LayoutBannerOffset * ThemeX.Scale) + (ThemeX.TextHeight << 1);
VisibleHeight = ((UGAHeight - EntriesPosY) / TextHeight) - InfoLines.size() - 2;/* - GlobalConfig.PruneScrollRows; */
VisibleHeight = ((UGAHeight - EntriesPosY) / ThemeX.TextHeight) - InfoLines.size() - 2;/* - GlobalConfig.PruneScrollRows; */
//DBG("MENU_FUNCTION_INIT 1 EntriesPosY=%d VisibleHeight=%d\n", EntriesPosY, VisibleHeight);
if ( Entries[0].getREFIT_INPUT_DIALOG() ) {
REFIT_INPUT_DIALOG& entry = (REFIT_INPUT_DIALOG&)Entries[0];
@ -1824,12 +1824,12 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
} else {
EntriesPosX = (UGAWidth - MenuWidth) >> 1;
}
TimeoutPosY = EntriesPosY + (Entries.size() + 1) * TextHeight;
TimeoutPosY = EntriesPosY + (Entries.size() + 1) * ThemeX.TextHeight;
// initial painting
egMeasureText(Title.data(), &ItemWidth, NULL);
if (!(ThemeX.HideUIFlags & HIDEUI_FLAG_MENU_TITLE)) {
DrawTextXY(Title, (UGAWidth >> 1), EntriesPosY - TextHeight * 2, X_IS_CENTER);
DrawTextXY(Title, (UGAWidth >> 1), EntriesPosY - ThemeX.TextHeight * 2, X_IS_CENTER);
}
if (!TitleImage.isEmpty()) {
@ -1852,9 +1852,9 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
//EraseTextXY(); //but we should make it complementare to DrawMenuText
for (UINTN i = 0; i < InfoLines.size(); i++) {
DrawMenuText(InfoLines[i], 0, EntriesPosX, EntriesPosY, 0xFFFF);
EntriesPosY += TextHeight;
EntriesPosY += ThemeX.TextHeight;
}
EntriesPosY += TextHeight; // also add a blank line
EntriesPosY += ThemeX.TextHeight; // also add a blank line
}
ThemeX.InitBar();
@ -1868,8 +1868,8 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
{
// DBG("PAINT_ALL: EntriesPosY=%lld MaxVisible=%lld\n", EntriesPosY, ScrollState.MaxVisible);
// DBG("DownButton.Height=%lld TextHeight=%lld MenuWidth=%lld\n", DownButton.Height, TextHeight, MenuWidth);
t2 = EntriesPosY + (ScrollState.MaxVisible + 1) * TextHeight - DownButton.Height;
t1 = EntriesPosX + TextHeight + MenuWidth + (INTN)((TEXT_XMARGIN + 16) * ThemeX.Scale);
t2 = EntriesPosY + (ScrollState.MaxVisible + 1) * ThemeX.TextHeight - DownButton.Height;
t1 = EntriesPosX + ThemeX.TextHeight + MenuWidth + (INTN)((TEXT_XMARGIN + 16) * ThemeX.Scale);
// DBG("PAINT_ALL: X=%lld Y=%lld\n", t1, t2);
SetBar(t1, EntriesPosY, t2, &ScrollState); //823 302 554
/*
@ -1886,12 +1886,12 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
TitleLen = StrLen(Entry->Title);
Entry->Place.XPos = EntriesPosX;
Entry->Place.YPos = EntriesPosY + j * TextHeight;
Entry->Place.YPos = EntriesPosY + j * ThemeX.TextHeight;
Entry->Place.Width = TitleLen * ScaledWidth;
Entry->Place.Height = (UINTN)TextHeight;
Entry->Place.Height = (UINTN)ThemeX.TextHeight;
ResultString = Entry->Title; //create a copy to modify later
PlaceCentre = (INTN)((TextHeight - (INTN)(ThemeX.Buttons[2].GetHeight())) * ThemeX.Scale / 2);
PlaceCentre1 = (INTN)((TextHeight - (INTN)(ThemeX.Buttons[0].GetHeight())) * ThemeX.Scale / 2);
PlaceCentre = (INTN)((ThemeX.TextHeight - (INTN)(ThemeX.Buttons[2].GetHeight())) * ThemeX.Scale / 2);
PlaceCentre1 = (INTN)((ThemeX.TextHeight - (INTN)(ThemeX.Buttons[0].GetHeight())) * ThemeX.Scale / 2);
// clovy
if (ThemeX.TypeSVG)
@ -1920,7 +1920,7 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
Entry->Place.YPos, TitleLen + Entry->Row);
}
} else if (Entry->getREFIT_MENU_CHECKBIT()) {
ThemeX.FillRectAreaOfScreen(ctrlTextX, Entry->Place.YPos, MenuWidth, TextHeight);
ThemeX.FillRectAreaOfScreen(ctrlTextX, Entry->Place.YPos, MenuWidth, ThemeX.TextHeight);
DrawMenuText(ResultString, (i == ScrollState.CurrentSelection) ? (MenuWidth) : 0,
ctrlTextX,
Entry->Place.YPos, 0xFFFF);
@ -1965,8 +1965,8 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
//clovy//PlaceCentre = (TextHeight - (INTN)(Buttons[2]->Height * GlobalConfig.Scale)) / 2;
//clovy//PlaceCentre = (PlaceCentre>0)?PlaceCentre:0;
//clovy//PlaceCentre1 = (TextHeight - (INTN)(Buttons[0]->Height * GlobalConfig.Scale)) / 2;
PlaceCentre = (INTN)((TextHeight - (INTN)(ThemeX.Buttons[2].GetHeight())) * ThemeX.Scale / 2);
PlaceCentre1 = (INTN)((TextHeight - (INTN)(ThemeX.Buttons[0].GetHeight())) * ThemeX.Scale / 2);
PlaceCentre = (INTN)((ThemeX.TextHeight - (INTN)(ThemeX.Buttons[2].GetHeight())) * ThemeX.Scale / 2);
PlaceCentre1 = (INTN)((ThemeX.TextHeight - (INTN)(ThemeX.Buttons[0].GetHeight())) * ThemeX.Scale / 2);
// clovy
if (ThemeX.TypeSVG)
@ -1989,7 +1989,7 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
ResultString += (((REFIT_INPUT_DIALOG*)(EntryL))->Item->SValue + ((REFIT_INPUT_DIALOG*)(EntryL))->Item->LineShift);
ResultString += L" ";
DrawMenuText(ResultString, 0, EntriesPosX,
EntriesPosY + (ScrollState.LastSelection - ScrollState.FirstVisible) * TextHeight,
EntriesPosY + (ScrollState.LastSelection - ScrollState.FirstVisible) * ThemeX.TextHeight,
TitleLen + EntryL->Row);
}
} else if (EntryL->getREFIT_MENU_SWITCH()) { //radio buttons 0,1
@ -2006,7 +2006,7 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
// clovy
DrawMenuText(ResultString, 0, ctrlTextX,
EntriesPosY + (ScrollState.LastSelection - ScrollState.FirstVisible) * TextHeight, 0xFFFF);
EntriesPosY + (ScrollState.LastSelection - ScrollState.FirstVisible) * ThemeX.TextHeight, 0xFFFF);
ThemeX.Buttons[(EntryL->Row == OldChosenItem)?1:0].DrawOnBack(ctrlX, EntryL->Place.YPos + PlaceCentre1, ThemeX.Background);
} else if (EntryL->getREFIT_MENU_CHECKBIT()) {
// clovy
@ -2015,7 +2015,7 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
ThemeX.Buttons[(EntryL->getREFIT_MENU_CHECKBIT()->Item->IValue & EntryL->Row) ?3:2].DrawOnBack(ctrlX, EntryL->Place.YPos + PlaceCentre, ThemeX.Background);
} else {
DrawMenuText(EntryL->Title, 0, EntriesPosX,
EntriesPosY + (ScrollState.LastSelection - ScrollState.FirstVisible) * TextHeight, 0xFFFF);
EntriesPosY + (ScrollState.LastSelection - ScrollState.FirstVisible) * ThemeX.TextHeight, 0xFFFF);
}
// current selection
@ -2045,13 +2045,13 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
inputDialogEntry->Item->LineShift);
ResultString += L" ";
DrawMenuText(ResultString, MenuWidth, EntriesPosX,
EntriesPosY + (ScrollState.CurrentSelection - ScrollState.FirstVisible) * TextHeight,
EntriesPosY + (ScrollState.CurrentSelection - ScrollState.FirstVisible) * ThemeX.TextHeight,
TitleLen + inputDialogEntry->Row);
}
} else if (EntryC->getREFIT_MENU_SWITCH()) { //radio
DrawMenuText(EntryC->Title, MenuWidth,
ctrlTextX,
EntriesPosY + (ScrollState.CurrentSelection - ScrollState.FirstVisible) * TextHeight,
EntriesPosY + (ScrollState.CurrentSelection - ScrollState.FirstVisible) * ThemeX.TextHeight,
0xFFFF);
ThemeX.Buttons[(EntryC->Row == OldChosenItem)?1:0].DrawOnBack(ctrlX, EntryC->Place.YPos + PlaceCentre1, ThemeX.Background);
} else if (EntryC->getREFIT_MENU_CHECKBIT()) {
@ -2061,7 +2061,7 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
ThemeX.Buttons[(EntryC->getREFIT_MENU_CHECKBIT()->Item->IValue & EntryC->Row)?3:2].DrawOnBack(ctrlX, EntryC->Place.YPos + PlaceCentre, ThemeX.Background);
}else{
DrawMenuText(EntryC->Title, MenuWidth, EntriesPosX,
EntriesPosY + (ScrollState.CurrentSelection - ScrollState.FirstVisible) * TextHeight,
EntriesPosY + (ScrollState.CurrentSelection - ScrollState.FirstVisible) * ThemeX.TextHeight,
0xFFFF);
}
@ -2444,11 +2444,6 @@ VOID REFIT_MENU_SCREEN::GraphicsMenuStyle(IN UINTN Function, IN CONST CHAR16 *Pa
/**
* Draw entries for GUI.
*/
#if USE_XTHEME
#else
#endif
#if USE_XTHEME
VOID REFIT_MENU_SCREEN::DrawMainMenuLabel(IN CONST XStringW& Text, IN INTN XPos, IN INTN YPos)
@ -2460,7 +2455,7 @@ VOID REFIT_MENU_SCREEN::DrawMainMenuLabel(IN CONST XStringW& Text, IN INTN XPos,
//Clear old text
// if (OldTextWidth > TextWidth) {
ThemeX.FillRectAreaOfScreen(OldX, OldY, OldTextWidth, TextHeight);
ThemeX.FillRectAreaOfScreen(OldX, OldY, OldTextWidth, ThemeX.TextHeight);
// }
if (!(ThemeX.BootCampStyle)
@ -2469,7 +2464,7 @@ VOID REFIT_MENU_SCREEN::DrawMainMenuLabel(IN CONST XStringW& Text, IN INTN XPos,
) {
//Clear badge
ThemeX.FillRectAreaOfScreen((OldX - (OldTextWidth >> 1) - (BadgeDim + 16)),
(OldY - ((BadgeDim - TextHeight) >> 1)), 128, 128);
(OldY - ((BadgeDim - ThemeX.TextHeight) >> 1)), 128, 128);
}
// XStringW TextX;
// TextX.takeValueFrom(Text);
@ -2481,7 +2476,7 @@ VOID REFIT_MENU_SCREEN::DrawMainMenuLabel(IN CONST XStringW& Text, IN INTN XPos,
(Entries[ScrollState.CurrentSelection].Row == 0)) {
// Display Inline Badge: small icon before the text
Entries[ScrollState.CurrentSelection].Image.Draw((XPos - (TextWidth >> 1) - (BadgeDim + 16)),
(YPos - ((BadgeDim - TextHeight) >> 1)));
(YPos - ((BadgeDim - ThemeX.TextHeight) >> 1)));
}
OldX = XPos;
@ -2591,10 +2586,10 @@ VOID REFIT_MENU_SCREEN::DrawTextCorner(UINTN TextC, UINT8 Align)
switch (Align) {
case X_IS_LEFT:
Xpos = (INTN)(TextHeight * 0.75f);
Xpos = (INTN)(ThemeX.TextHeight * 0.75f);
break;
case X_IS_RIGHT:
Xpos = UGAWidth - (INTN)(TextHeight * 0.75f);//2
Xpos = UGAWidth - (INTN)(ThemeX.TextHeight * 0.75f);//2
break;
case X_IS_CENTER:
Xpos = UGAWidth >> 1;
@ -2605,7 +2600,7 @@ VOID REFIT_MENU_SCREEN::DrawTextCorner(UINTN TextC, UINT8 Align)
}
// DBG("draw text %ls at (%d, %d)\n", Text, Xpos, UGAHeight - 5 - TextHeight),
// clovy DrawTextXY(Text, Xpos, UGAHeight - 5 - TextHeight, Align);
DrawTextXY(Text, Xpos, UGAHeight - (INTN)(TextHeight * 1.5f), Align);
DrawTextXY(Text, Xpos, UGAHeight - (INTN)(ThemeX.TextHeight * 1.5f), Align);
}
#else
@ -2721,7 +2716,7 @@ VOID REFIT_MENU_SCREEN::DrawMainMenuEntry(REFIT_ABSTRACT_MENU_ENTRY *Entry, BOOL
// &MenuBackgroundPixel, Scale);
TopImage = ThemeX.SelectionImages[4 + (selected ? 0 : 1)];
TopImage.Draw(XPos + (ThemeX.row0TileSize / 2) - (INTN)(INDICATOR_SIZE * 0.5f * ThemeX.Scale),
row0PosY + ThemeX.row0TileSize + TextHeight + (INTN)((BCSMargin * 2) * ThemeX.Scale), fScale, false);
row0PosY + ThemeX.row0TileSize + ThemeX.TextHeight + (INTN)((BCSMargin * 2) * ThemeX.Scale), fScale, false);
}
}
@ -2743,7 +2738,7 @@ VOID REFIT_MENU_SCREEN::MainMenuVerticalStyle(IN UINTN Function, IN CONST CHAR16
if (ThemeX.TypeSVG && textFace[1].valid) {
MessageHeight = (INTN)(textFace[1].size * RowHeightFromTextHeight * ThemeX.Scale);
} else {
MessageHeight = (INTN)(TextHeight * RowHeightFromTextHeight * ThemeX.Scale);
MessageHeight = (INTN)(ThemeX.TextHeight * RowHeightFromTextHeight * ThemeX.Scale);
}
switch (Function) {
@ -2872,7 +2867,7 @@ VOID REFIT_MENU_SCREEN::MainMenuVerticalStyle(IN UINTN Function, IN CONST CHAR16
HidePointer();
if (!(ThemeX.HideUIFlags & HIDEUI_FLAG_LABEL)) {
ThemeX.FillRectAreaOfScreen((UGAWidth >> 1), textPosY + hi,
OldTimeoutTextWidth, TextHeight);
OldTimeoutTextWidth, ThemeX.TextHeight);
XStringW TextX;
TextX.takeValueFrom(ParamText);
OldTimeoutTextWidth = DrawTextXY(TextX, (UGAWidth >> 1), textPosY + hi, X_IS_CENTER);
@ -3048,7 +3043,7 @@ VOID REFIT_MENU_SCREEN::MainMenuStyle(IN UINTN Function, IN CONST CHAR16 *ParamT
if (ThemeX.TypeSVG && textFace[1].valid) {
MessageHeight = (INTN)(textFace[1].size * RowHeightFromTextHeight * ThemeX.Scale);
} else {
MessageHeight = (INTN)(TextHeight * RowHeightFromTextHeight * ThemeX.Scale);
MessageHeight = (INTN)(ThemeX.TextHeight * RowHeightFromTextHeight * ThemeX.Scale);
}
switch (Function) {
@ -3079,7 +3074,7 @@ VOID REFIT_MENU_SCREEN::MainMenuStyle(IN UINTN Function, IN CONST CHAR16 *ParamT
row1PosX = (UGAWidth + 8 - (ThemeX.row1TileSize + (INTN)(8.0f * ThemeX.Scale)) * row1Count) >> 1;
if (ThemeX.BootCampStyle && !(ThemeX.HideUIFlags & HIDEUI_FLAG_LABEL)) {
row1PosY = row0PosY + ThemeX.row0TileSize + (INTN)((BCSMargin * 2) * ThemeX.Scale) + TextHeight +
row1PosY = row0PosY + ThemeX.row0TileSize + (INTN)((BCSMargin * 2) * ThemeX.Scale) + ThemeX.TextHeight +
(INTN)(INDICATOR_SIZE * ThemeX.Scale) +
(INTN)((ThemeX.LayoutButtonOffset + ThemeX.TileYSpace) * ThemeX.Scale);
} else {

View File

@ -861,8 +861,6 @@ INTN renderSVGtext(XImage* TextBufferXY_ptr, INTN posX, INTN posY, INTN textType
// nsvg__deleteParser(p);
nsvgDelete(p->image);
return (INTN)RealWidth; //x;
}
#else
INTN renderSVGtext(EG_IMAGE* TextBufferXY, INTN posX, INTN posY, INTN textType, CONST CHAR16* string, UINTN Cursor)

View File

@ -265,6 +265,21 @@ void XImage::CopyScaled(const XImage& Image, float scale)
* else transparency will be multiplied
*/
void XImage::Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest)
{
EG_RECT OutPlace;
OutPlace.XPos = PosX;
OutPlace.YPos = PosY;
OutPlace.Width = GetWidth();
OutPlace.Height = GetHeight();
EG_RECT Area;
Area.XPos = 0;
Area.YPos = 0;
Area.Width = TopImage.GetWidth();
Area.Height = TopImage.GetHeight();
Compose(OutPlace, Area, TopImage, Lowest);
}
void XImage::Compose(const EG_RECT& OutPlace, const EG_RECT& Area, const XImage& TopImage, bool Lowest)
{
UINT32 TopAlpha;
UINT32 RevAlpha;
@ -272,14 +287,26 @@ void XImage::Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest)
UINT32 CompAlpha;
UINT32 TempAlpha;
UINT32 Temp;
INTN PosX = Area.XPos;
INTN PosY = Area.YPos;
//assumed Area.Width == OutPlace.Width
// if not choose min
INTN WArea = MIN(Area.Width, OutPlace.Width);
if (PosX + WArea > GetWidth()) {
WArea = GetWidth() - PosX;
}
INTN HArea = MIN(Area.Height, OutPlace.Height);
if (PosY + HArea > GetHeight()) {
HArea = GetHeight() - PosY;
}
//change only affected pixels
for (INTN y = PosY; y < GetHeight() && (y - PosY) < TopImage.GetHeight(); ++y) {
for (INTN y = 0; y < HArea && y < TopImage.GetHeight(); ++y) {
// EFI_GRAPHICS_OUTPUT_BLT_PIXEL& CompPtr = *GetPixelPtr(PosX, y); // I assign a ref to avoid the operator ->. Compiler will produce the same anyway.
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* CompPtr = GetPixelPtr(PosX, y);
for (INTN x = PosX; x < GetWidth() && (x - PosX) < TopImage.GetWidth(); ++x) {
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* CompPtr = GetPixelPtr(OutPlace.XPos, OutPlace.YPos + y);
for (INTN x = 0; x < WArea && x < TopImage.GetWidth(); ++x) {
//------
// test compAlpha = 255; TopAlpha = 0 -> only Comp, TopAplha = 255 -> only Top
TopAlpha = TopImage.GetPixel(x-PosX, y-PosY).Reserved & 0xFF; //0, 255
TopAlpha = TopImage.GetPixel(x + PosX, y + PosY).Reserved & 0xFF; //0, 255
CompAlpha = CompPtr->Reserved & 0xFF; //255
RevAlpha = 255 - TopAlpha; //2<<8; 255, 0
TempAlpha = CompAlpha * RevAlpha; //2<<16; 255*255, 0
@ -288,13 +315,13 @@ void XImage::Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest)
//final alpha =(1-(1-x)*(1-y)) =(255*255-(255-topA)*(255-compA))/255 = topA+compA*(1-topA)
if (FinalAlpha != 0) {
Temp = (CompPtr->Blue * TempAlpha) + (TopImage.GetPixel(x-PosX, y-PosY).Blue * TopAlpha);
Temp = (CompPtr->Blue * TempAlpha) + (TopImage.GetPixel(x + PosX, y + PosY).Blue * TopAlpha);
CompPtr->Blue = (UINT8)(Temp / FinalAlpha);
Temp = (CompPtr->Green * TempAlpha) + (TopImage.GetPixel(x-PosX, y-PosY).Green * TopAlpha);
Temp = (CompPtr->Green * TempAlpha) + (TopImage.GetPixel(x + PosX, y + PosY).Green * TopAlpha);
CompPtr->Green = (UINT8)(Temp / FinalAlpha);
Temp = (CompPtr->Red * TempAlpha) + (TopImage.GetPixel(x-PosX, y-PosY).Red * TopAlpha);
Temp = (CompPtr->Red * TempAlpha) + (TopImage.GetPixel(x + PosX, y + PosY).Red * TopAlpha);
CompPtr->Red = (UINT8)(Temp / FinalAlpha);
}
@ -589,6 +616,7 @@ EFI_STATUS XImage::LoadXImage(EFI_FILE *BaseDir, const wchar_t* LIconName)
return LoadXImage(BaseDir, XStringW().takeValueFrom(LIconName));
}
//dont call this procedure for SVG theme BaseDir == NULL?
//it can be used for other files
EFI_STATUS XImage::LoadXImage(EFI_FILE *BaseDir, const XStringW& IconName)
{
EFI_STATUS Status = EFI_NOT_FOUND;

View File

@ -88,6 +88,7 @@ public:
void CopyScaled(const XImage& Image, float scale);
void CopyRect(const XImage& Image, INTN X, INTN Y);
void CopyRect(const XImage& Image, const EG_RECT& OwnPlace, const EG_RECT& InputRect);
void Compose(const EG_RECT& OwnPlace, const EG_RECT& InputRect, const XImage& TopImage, bool Lowest);
void Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest); //instead of compose we often can Back.Draw(...) + Top.Draw(...)
void FlipRB();
EFI_STATUS FromPNG(const UINT8 * Data, UINTN Lenght);

View File

@ -292,6 +292,10 @@ void XTheme::Init()
row0TileSize = 144;
row1TileSize = 64;
FontWidth = 9;
FontHeight = 18;
TextHeight = 19;
}
/*

View File

@ -95,6 +95,10 @@ public:
INTN ScrollScrollDecorationsHeight;
INTN FontWidth;
INTN FontHeight;
INTN TextHeight;
BOOLEAN Daylight;
XImage Background; //Background and Banner will not be in array as they live own life
@ -111,6 +115,8 @@ public:
XImage UpButtonImage;
XImage DownButtonImage;
XImage FontImage;
EG_RECT BannerPlace;
//fill the theme
@ -121,6 +127,14 @@ public:
const XImage& LoadOSIcon(const CHAR16* OSIconName); //TODO make XString provider
const XImage& LoadOSIcon(const XString& Full);
//fonts
void LoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols);
void PrepareFont();
INTN GetEmpty(const XImage& Buffer, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL& FirstPixel, INTN Start, INTN Step);
INTN RenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType);
// void AddIcon(Icon& NewIcon); //return EFI_STATUS?
void FillByEmbedded();
void FillByDir();

View File

@ -712,6 +712,8 @@ VOID egRawCopy(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr,
}
}
//will be replace by
// CompBase.Compose(
VOID egRawCompose(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr,
IN INTN Width, IN INTN Height,
IN INTN CompLineOffset, IN INTN TopLineOffset)

View File

@ -94,7 +94,7 @@ DECLARE_EMB_EXTERN_WITH_SIZE(emb_radio_button)
DECLARE_EMB_EXTERN_WITH_SIZE(emb_checkbox)
DECLARE_EMB_EXTERN_WITH_SIZE(emb_checkbox_checked)
DECLARE_EMB_EXTERN_WITH_SIZE(emb_dark_font_data)
//DECLARE_EMB_EXTERN_WITH_SIZE(emb_dark_font_data) //not exists
//DECLARE_EMB_EXTERN_WITH_SIZE(emb_dark_pointer)
DECLARE_EMB_EXTERN_WITH_SIZE(emb_dark_func_about)
DECLARE_EMB_EXTERN_WITH_SIZE(emb_dark_func_clover)
@ -182,8 +182,9 @@ EG_IMAGE * egDecodePNG(IN const UINT8 *FileData, IN UINTN FileDataLength, IN BOO
//VOID egEncodeBMP(IN EG_IMAGE *Image, OUT UINT8 **FileData, OUT UINTN *FileDataLength);
#if USE_XTHEME
INTN egRenderText(IN const XStringW& Text, OUT XImage* CompImage,
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType);
// now it is in XTHEME
//INTN egRenderText(IN const XStringW& Text, OUT XImage* CompImage,
// IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType);
#else
INTN egRenderText(IN CONST CHAR16 *Text, IN OUT EG_IMAGE *CompImage, IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType);
#endif

View File

@ -35,6 +35,10 @@
*/
//Slice 2011 - 2016 numerous improvements
extern "C" {
#include <Protocol/GraphicsOutput.h>
}
#include "libegint.h"
#include "nanosvg.h"
#include "VectorGraphics.h"
@ -55,27 +59,36 @@
#define DBG(...) DebugLog(DEBUG_TEXT, __VA_ARGS__)
#endif
#if USE_XTHEME
const EFI_GRAPHICS_OUTPUT_BLT_PIXEL SemiWhitePixel = {0xFF, 0xFF, 0xFF, 0xD2}; //semitransparent white
#else
EG_IMAGE *FontImage = NULL; //theme member
CONST EG_PIXEL SemiWhitePixel = {255, 255, 255, 210}; //semitransparent
#endif
#if USE_XTHEME
#else
EG_IMAGE *FontImage = NULL;
INTN FontWidth = 9; //local variable
INTN FontHeight = 18;
INTN TextHeight = 19;
#endif
NSVGfontChain *fontsDB = NULL;
CONST EG_PIXEL SemiWhitePixel = {255, 255, 255, 210}; //semitransparent
//
// Text rendering
//
#if USE_XTHEME
//it is not good for vector theme
//it will be better to sum each letter width for the chosen font
// so one more parameter is TextStyle
VOID egMeasureText(IN CONST CHAR16 *Text, OUT INTN *Width, OUT INTN *Height)
{
INTN ScaledWidth = (INTN)(ThemeX.CharWidth * ThemeX.Scale);
if (Width != NULL)
*Width = StrLen(Text) * ((FontWidth > ScaledWidth)?FontWidth:ScaledWidth);
*Width = StrLen(Text) * ((ThemeX.FontWidth > ScaledWidth)?ThemeX.FontWidth:ScaledWidth);
if (Height != NULL)
*Height = FontHeight;
*Height = ThemeX.FontHeight;
}
#else
@ -90,6 +103,87 @@ VOID egMeasureText(IN CONST CHAR16 *Text, OUT INTN *Width, OUT INTN *Height)
}
#endif
#if USE_XTHEME
void XTheme::LoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
{
EFI_STATUS Status = EFI_NOT_FOUND;
XImage NewImage; //tempopary image from file
INTN ImageWidth, ImageHeight;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *PixelPtr;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FontPtr;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FirstPixel;
BOOLEAN isKorean = (gLanguage == korean);
XStringW fontFilePath;
const XStringW& commonFontDir = L"EFI\\CLOVER\\font"_XSW;
if (IsEmbeddedTheme() && !isKorean) { //or initial screen before theme init
NewImage.FromPNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data)); //always success
MsgLog("Using embedded font\n");
} else if (isKorean){
Status = NewImage.LoadXImage(ThemeDir, L"FontKorean.png"_XSW);
MsgLog("Loading korean font from ThemeDir: %s\n", strerror(Status));
if (EFI_ERROR(Status)) {
//no korean font, use common
MsgLog("...using english\n");
gLanguage = english;
Rows = 16; //standard for english
Cols = 16;
Status = NewImage.LoadXImage(ThemeDir, FontFileName);
} else {
CharWidth = 22; //standard for korean
}
}
if (NewImage.isEmpty()) {
//then take from common font folder
// fontFilePath = SWPrintf(L"%s\\%s", commonFontDir, isKorean ? L"FontKorean.png" : ThemeX.FontFileName.data());
fontFilePath = commonFontDir + FontFileName;
Status = NewImage.LoadXImage(SelfRootDir, fontFilePath);
//else use embedded
if (EFI_ERROR(Status)) {
NewImage.FromPNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data));
}
}
ImageWidth = NewImage.GetWidth();
// DBG("ImageWidth=%lld\n", ImageWidth);
ImageHeight = NewImage.GetHeight();
// DBG("ImageHeight=%lld\n", ImageHeight);
PixelPtr = NewImage.GetPixelPtr(0,0);
FontImage.setSizeInPixels(ImageWidth * Rows, ImageHeight / Rows);
FontPtr = FontImage.GetPixelPtr(0,0);
FontWidth = ImageWidth / Cols;
FontHeight = ImageHeight / Rows;
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * Scale);
if (!isKorean) {
CharWidth = FontWidth;
}
FirstPixel = *PixelPtr;
for (INTN y = 0; y < Rows; y++) {
for (INTN j = 0; j < FontHeight; j++) {
INTN Ypos = ((j * Rows) + y) * ImageWidth;
for (INTN x = 0; x < ImageWidth; x++) {
if (
//First pixel is accounting as "blue key"
(PixelPtr->Blue == FirstPixel.Blue) &&
(PixelPtr->Green == FirstPixel.Green) &&
(PixelPtr->Red == FirstPixel.Red)
) {
PixelPtr->Reserved = 0; //if a pixel has same color as first pixel then it will be transparent
} else if (ThemeX.DarkEmbedded) {
*PixelPtr = SemiWhitePixel; //special case to change a text to semi white, not blue pixels
}
FontPtr[Ypos + x] = *PixelPtr++; //not (x, YPos) !!!
}
}
}
}
#else
//should be rewritten to use XImage and XStringW
EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
{
@ -99,20 +193,11 @@ EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
BOOLEAN isKorean = (gLanguage == korean);
CHAR16 *fontFilePath = NULL;
CONST CHAR16 *commonFontDir = L"EFI\\CLOVER\\font";
if (IsEmbeddedTheme() && !isKorean) { //or initial screen before theme init
NewImage = egDecodePNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data), TRUE);
MsgLog("Using embedded font: %s\n", NewImage ? "Success" : "Error");
} else {
#if USE_XTHEME
if (!ThemeX.TypeSVG) {
NewImage = egLoadImage(ThemeX.ThemeDir, isKorean ? L"FontKorean.png" : ThemeX.FontFileName.data(), TRUE);
MsgLog("Loading font from ThemeDir: %s\n", NewImage ? "Success" : "Error");
} else {
MsgLog("Using SVG font\n");
return FontImage;
}
#else
if (!GlobalConfig.TypeSVG) {
NewImage = egLoadImage(ThemeDir, isKorean ? L"FontKorean.png" : GlobalConfig.FontFileName, TRUE);
MsgLog("Loading font from ThemeDir: %s\n", NewImage ? "Success" : "Error");
@ -120,17 +205,12 @@ EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
MsgLog("Using SVG font\n");
return FontImage;
}
#endif
}
if (!NewImage) {
//then take from common font folder
#if USE_XTHEME
fontFilePath = PoolPrint(L"%s\\%s", commonFontDir, isKorean ? L"FontKorean.png" : ThemeX.FontFileName.data());
#else
fontFilePath = PoolPrint(L"%s\\%s", commonFontDir, isKorean ? L"FontKorean.png" : GlobalConfig.FontFileName);
#endif
NewImage = egLoadImage(SelfRootDir, fontFilePath, TRUE);
//else use embedded
if (!NewImage) {
@ -144,14 +224,14 @@ EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
}
FreePool(fontFilePath);
}
ImageWidth = NewImage->Width;
// DBG("ImageWidth=%lld\n", ImageWidth);
// DBG("ImageWidth=%lld\n", ImageWidth);
ImageHeight = NewImage->Height;
// DBG("ImageHeight=%lld\n", ImageHeight);
// DBG("ImageHeight=%lld\n", ImageHeight);
PixelPtr = NewImage->PixelData;
NewFontImage = egCreateImage(ImageWidth * Rows, ImageHeight / Rows, TRUE);
if (NewFontImage == NULL) {
DBG("Can't create new font image!\n");
if (NewImage) {
@ -159,15 +239,11 @@ EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
}
return NULL;
}
FontWidth = ImageWidth / Cols;
FontHeight = ImageHeight / Rows;
#if USE_XTHEME
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * ThemeX.Scale);
#else
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * GlobalConfig.Scale);
#endif
FirstPixel = *PixelPtr;
for (y = 0; y < Rows; y++) {
for (j = 0; j < FontHeight; j++) {
@ -180,40 +256,69 @@ EG_IMAGE * egLoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
(PixelPtr->r == FirstPixel.r)
) {
PixelPtr->a = 0; //if a pixel has same color as first pixel then it will be transparent
#if USE_XTHEME
} else if (ThemeX.DarkEmbedded) {
*PixelPtr = SemiWhitePixel; //specail case to change a text to semi white
#else
} else if (GlobalConfig.DarkEmbedded) {
*PixelPtr = SemiWhitePixel;
#endif
}
NewFontImage->PixelData[Ypos + x] = *PixelPtr++;
}
}
}
egFreeImage(NewImage);
return NewFontImage;
}
#endif
#if USE_XTHEME
VOID XTheme::PrepareFont()
{
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *p;
INTN Width, Height;
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * Scale);
if (TypeSVG) {
return;
}
// load the font
if (FontImage.isEmpty()){
DBG("load font image type %d\n", Font);
LoadFontImage(TRUE, 16, 16); //anyway success
}
if (!FontImage.isEmpty()) {
if (Font == FONT_GRAY) {
//invert the font. embedded is dark
p = FontImage.GetPixelPtr(0,0);
for (Height = 0; Height < FontImage.GetHeight(); Height++){
for (Width = 0; Width < FontImage.GetWidth(); Width++, p++){
p->Blue ^= 0xFF;
p->Green ^= 0xFF;
p->Red ^= 0xFF;
//p->a = 0xFF; //huh! dont invert opacity
}
}
}
DBG("Font %d prepared WxH=%lldx%lld CharWidth=%lld\n", Font, FontWidth, FontHeight, CharWidth);
} else {
DBG("Failed to load font\n");
}
}
#else
VOID PrepareFont()
{
EG_PIXEL *p;
INTN Width, Height;
#if USE_XTHEME
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * ThemeX.Scale);
if (ThemeX.TypeSVG) {
return;
}
#else
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * GlobalConfig.Scale);
if (GlobalConfig.TypeSVG) {
// FontImage = RenderSVGfont();
return;
}
#endif
if (FontImage) {
egFreeImage(FontImage);
@ -223,12 +328,7 @@ VOID PrepareFont()
if (gLanguage == korean) {
FontImage = egLoadFontImage(FALSE, 10, 28);
if (FontImage) {
#if USE_XTHEME
ThemeX.CharWidth = 22;
#else
GlobalConfig.CharWidth = 22;
#endif
MsgLog("Using Korean font matrix\n");
return;
} else {
@ -236,35 +336,14 @@ VOID PrepareFont()
gLanguage = english;
}
}
// load the font
if (FontImage == NULL){
#if USE_XTHEME
DBG("load font image type %d\n", ThemeX.Font);
#else
DBG("load font image type %d\n", GlobalConfig.Font);
#endif
DBG("load font image type %d\n", GlobalConfig.Font);
FontImage = egLoadFontImage(TRUE, 16, 16); //anyway success
}
if (FontImage) {
#if USE_XTHEME
if (ThemeX.Font == FONT_GRAY) {
//invert the font. embedded is dark
p = FontImage->PixelData;
for (Height = 0; Height < FontImage->Height; Height++){
for (Width = 0; Width < FontImage->Width; Width++, p++){
p->b ^= 0xFF;
p->g ^= 0xFF;
p->r ^= 0xFF;
//p->a = 0xFF; //huh!
}
}
}
DBG("Font %d prepared WxH=%lldx%lld CharWidth=%lld\n", ThemeX.Font, FontWidth, FontHeight, ThemeX.CharWidth);
#else
if (FontImage) {
if (GlobalConfig.Font == FONT_GRAY) {
//invert the font. embedded is dark
p = FontImage->PixelData;
@ -279,14 +358,61 @@ VOID PrepareFont()
}
DBG("Font %d prepared WxH=%lldx%lld CharWidth=%lld\n", GlobalConfig.Font, FontWidth, FontHeight, GlobalConfig.CharWidth);
#endif
// TextHeight = FontHeight + TEXT_YMARGIN * 2;
// TextHeight = FontHeight + TEXT_YMARGIN * 2;
} else {
DBG("Failed to load font\n");
}
}
#endif
//search pixel similar to first
#if USE_XTHEME
inline bool SamePix(const EFI_GRAPHICS_OUTPUT_BLT_PIXEL& Ptr, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL& FirstPixel)
{
//compare with first pixel of the array top-left point [0][0]
return ((Ptr.Red >= FirstPixel.Red - (FirstPixel.Red >> 2)) &&
(Ptr.Red <= FirstPixel.Red + (FirstPixel.Red >> 2)) &&
(Ptr.Green >= FirstPixel.Green - (FirstPixel.Green >> 2)) &&
(Ptr.Green <= FirstPixel.Green + (FirstPixel.Green >> 2)) &&
(Ptr.Blue >= FirstPixel.Blue - (FirstPixel.Blue >> 2)) &&
(Ptr.Blue <= FirstPixel.Blue + (FirstPixel.Blue >> 2)) &&
(Ptr.Reserved == FirstPixel.Reserved)); //hack for transparent fonts
}
//used for proportional fonts in raster themes
//search empty column from begin Step=1 or from end Step=-1 in the input buffer
// empty means similar to FirstPixel
INTN XTheme::GetEmpty(const XImage& Buffer, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL& FirstPixel, INTN Start, INTN Step)
{
INTN m, i;
// INTN Shift = (Step > 0)?0:1;
// EFI_GRAPHICS_OUTPUT_BLT_PIXEL ThePixel;
m = FontWidth;
if (Step == 1) {
for (INTN j = 0; j < FontHeight; j++) {
for (i = 0; i < FontWidth; i++) {
if (!SamePix(Buffer.GetPixel(Start + i,j), FirstPixel)) { //found not empty pixel
break;
}
}
m = MIN(m, i); //for each line to find minimum
if (m == 0) break;
}
} else { // go back
m = 0;
for (INTN j = 0; j < FontHeight; j++) {
for (i = FontWidth - 1; i >= 0; --i) {
if (!SamePix(Buffer.GetPixel(Start + i,j), FirstPixel)) { //found not empty pixel
break;
}
}
m = MAX(m, i); //for each line to find minimum
}
}
return m;
}
#else
static inline BOOLEAN EmptyPix(EG_PIXEL *Ptr, EG_PIXEL *FirstPixel)
{
@ -319,18 +445,195 @@ INTN GetEmpty(EG_PIXEL *Ptr, EG_PIXEL *FirstPixel, INTN MaxWidth, INTN Step, INT
}
return m;
}
#endif
#if USE_XTHEME
INTN egRenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
INTN XTheme::RenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType)
{
XImage& CompImage = *CompImage_ptr;
// EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BufferPtr;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FontPixel;
// EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FirstPixelBuf;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FirstPixel;
// INTN BufferLineWidth; //, BufferLineOffset, FontLineOffset;
INTN TextLength /*, NewTextLength = 0 */;
UINT16 c, c1, c0;
INTN Shift = 0;
UINTN Cho = 0, Jong = 0, Joong = 0;
INTN LeftSpace, RightSpace;
INTN RealWidth = 0;
// INTN ScaledWidth = (INTN)(CharWidth * Scale); //real char width in pixels
// but raster theme Scale=1 while SVG theme has own render
if (TypeSVG) {
return renderSVGtext(&CompImage, PosX, PosY, textType, Text, Cursor);
}
// clip the text
TextLength = Text.size();
if (FontImage.isEmpty()) {
// GlobalConfig.Font = FONT_ALFA;
PrepareFont(); //at the boot screen there is embedded font
}
// DBG("TextLength =%d PosX=%d PosY=%d\n", TextLength, PosX, PosY);
// render it
// BufferPtr = CompImage.GetPixelPtr(0,0);
// BufferLineOffset = CompImage.GetWidth();
// BufferLineWidth = CompImage.GetWidth() - PosX; // width from PosX to buffer end
// BufferPtr += PosX + PosY * BufferLineOffset; //how to avoid pointer arithmetics?
// BufferPtr = CompImage.GetPixelPtr(PosX, PosY); //a place to write the text
// FirstPixelBuf = BufferPtr;
FirstPixel = CompImage.GetPixel(0,0);
FontPixel = FontImage.GetPixel(0,0);
// FontLineOffset = FontImage.GetWidth();
// DBG("BufferLineOffset=%d FontLineOffset=%d\n", BufferLineOffset, FontLineOffset);
// if (ScaledWidth < FontWidth) {
// Shift = (FontWidth - ScaledWidth) >> 1;
// }
c0 = 0;
RealWidth = CharWidth;
// DBG("FontWidth=%d, CharWidth=%d\n", FontWidth, RealWidth);
EG_RECT Area;
Area.YPos = PosY; // not sure
Area.Height = FontHeight;
EG_RECT Bukva;
Bukva.YPos = 0;
Bukva.Width = FontWidth;
Bukva.Height = FontHeight;
for (INTN i = 0; i < TextLength; i++) {
c = Text.wc_str()[i];
if (gLanguage != korean) {
c1 = (((c >= Codepage) ? (c - (Codepage - AsciiPageSize)) : c) & 0xff); //International letters
c = c1;
if (Proportional) {
//find spaces {---buffer--__left__|__right__--char---}
if (c0 <= 0x20) { // space before or at buffer edge
LeftSpace = 2;
} else {
LeftSpace = GetEmpty(CompImage, FirstPixel, PosX, -1);
}
if (c <= 0x20) { //new space will be half font width
RightSpace = 1;
RealWidth = (FontWidth >> 1) + 1;
} else {
RightSpace = GetEmpty(FontImage, FontPixel, c * FontWidth, 1);
if (RightSpace >= FontWidth) {
RightSpace = 0; //empty place for invisible characters
}
RealWidth = FontWidth - RightSpace; //a part of char
}
} else {
LeftSpace = 2;
RightSpace = 0;
}
c0 = c; //old value
if (PosX + RealWidth > CompImage.GetWidth()) {
//no more place for character
break;
}
Area.XPos = PosX + 2 - LeftSpace;
Area.Width = RealWidth;
Bukva.XPos = c * FontWidth + RightSpace;
// Bukva.YPos
CompImage.Compose(Area, Bukva, FontImage, false);
if (i == Cursor) {
c = 0x5F;
Bukva.XPos = c * FontWidth + RightSpace;
CompImage.Compose(Area, Bukva, FontImage, false);
}
PosX += RealWidth - LeftSpace + 2; //next char position
} else {
//
//Slice - I am not sure in any of this digits
//someone knowning korean should revise this
//
if ((c >= 0x20) && (c <= 0x7F)) {
c1 = ((c - 0x20) >> 4) * 28 + (c & 0x0F);
Cho = c1;
Shift = 12;
} else if ((c < 0x20) || ((c > 0x7F) && (c < 0xAC00))) {
Cho = 0x0E; //just a dot
Shift = 8;
} else if ((c >= 0xAC00) && (c <= 0xD638)) {
//korean
Shift = 18;
c -= 0xAC00;
c1 = c / 28;
Jong = c % 28;
Cho = c1 / 21;
Joong = c1 % 21;
Cho += 28 * 7;
Joong += 28 * 8;
Jong += 28 * 9;
}
Area.XPos = PosX;
Area.Width = CharWidth;
// DBG("Cho=%d Joong=%d Jong=%d\n", Cho, Joong, Jong);
if (Shift == 18) {
Bukva.XPos = Cho * FontWidth + 4;
Bukva.YPos = 1;
CompImage.Compose(Area, Bukva, FontImage, false);
// egRawCompose(BufferPtr, FontPixelData + Cho * FontWidth + 4 + FontLineOffset,
// ScaledWidth, FontHeight,
// BufferLineOffset, FontLineOffset);
} else {
Area.YPos = PosY + 3;
Bukva.XPos = Cho * FontWidth + 2;
Bukva.YPos = 0;
// egRawCompose(BufferPtr + BufferLineOffset * 3, FontPixelData + Cho * FontWidth + 2,
// ScaledWidth, FontHeight,
// BufferLineOffset, FontLineOffset);
}
if (i == Cursor) {
c = 99;
Bukva.XPos = c * FontWidth + 2;
CompImage.Compose(Area, Bukva, FontImage, false);
// egRawCompose(BufferPtr, FontPixelData + c * FontWidth + 2,
// ScaledWidth, FontHeight,
// BufferLineOffset, FontLineOffset);
}
if (Shift == 18) {
Area.XPos = PosX + 9;
Area.YPos = PosY;
Bukva.XPos = Joong * FontWidth + 6;
Bukva.YPos = 0;
CompImage.Compose(Area, Bukva, FontImage, false);
// egRawCompose(BufferPtr + 9, FontPixelData + Joong * FontWidth + 6, //9 , 4 are tunable
// ScaledWidth - 8, FontHeight,
// BufferLineOffset, FontLineOffset);
Area.XPos = PosX;
Area.YPos = PosY + 9;
Bukva.XPos = Jong * FontWidth + 1;
// Bukva.YPos = 0;
// Area.Width = CharWidth;
// egRawCompose(BufferPtr + BufferLineOffset * 9, FontPixelData + Jong * FontWidth + 1,
// ScaledWidth, FontHeight - 3,
// BufferLineOffset, FontLineOffset);
CompImage.Compose(Area, Bukva, FontImage, false);
}
PosX += CharWidth; //Shift;
}
}
return PosX;
}
#else
INTN egRenderText(IN CONST CHAR16 *Text, IN OUT EG_IMAGE *CompImage,
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType)
#endif
{
#if USE_XTHEME
XImage& CompImage = *CompImage_ptr;
#endif
EG_PIXEL *BufferPtr;
EG_PIXEL *FontPixelData;
EG_PIXEL *FirstPixelBuf;
@ -343,157 +646,130 @@ INTN egRenderText(IN CONST CHAR16 *Text, IN OUT EG_IMAGE *CompImage,
UINTN LeftSpace, RightSpace;
INTN RealWidth = 0;
#if USE_XTHEME
INTN ScaledWidth = (INTN)(ThemeX.CharWidth * ThemeX.Scale);
if (ThemeX.TypeSVG) {
return renderSVGtext(&CompImage, PosX, PosY, textType, Text, Cursor);
}
#else
INTN ScaledWidth = (INTN)(GlobalConfig.CharWidth * GlobalConfig.Scale);
INTN ScaledWidth = (INTN)(GlobalConfig.CharWidth * GlobalConfig.Scale);
if (GlobalConfig.TypeSVG) {
return renderSVGtext(CompImage, PosX, PosY, textType, Text, Cursor);
}
#endif
// clip the text
#if USE_XTHEME
TextLength = Text.size();
#else
TextLength = StrLen(Text);
#endif
if (!FontImage) {
// GlobalConfig.Font = FONT_ALFA;
PrepareFont();
// GlobalConfig.Font = FONT_ALFA;
PrepareFont(); //at the boot screen there is embedded font
}
// DBG("TextLength =%d PosX=%d PosY=%d\n", TextLength, PosX, PosY);
// DBG("TextLength =%d PosX=%d PosY=%d\n", TextLength, PosX, PosY);
// render it
#if USE_XTHEME
BufferPtr = (EG_PIXEL*)CompImage.GetPixelPtr(0,0);
BufferLineOffset = CompImage.GetWidth();
#else
BufferPtr = CompImage->PixelData;
BufferLineOffset = CompImage->Width;
#endif
BufferLineWidth = BufferLineOffset - PosX; // remove indent from drawing width
BufferPtr += PosX + PosY * BufferLineOffset;
FirstPixelBuf = BufferPtr;
FontPixelData = FontImage->PixelData;
FontLineOffset = FontImage->Width;
// DBG("BufferLineOffset=%d FontLineOffset=%d\n", BufferLineOffset, FontLineOffset);
// DBG("BufferLineOffset=%d FontLineOffset=%d\n", BufferLineOffset, FontLineOffset);
if (ScaledWidth < FontWidth) {
Shift = (FontWidth - ScaledWidth) >> 1;
}
c0 = 0;
RealWidth = ScaledWidth;
// DBG("FontWidth=%d, CharWidth=%d\n", FontWidth, RealWidth);
// DBG("FontWidth=%d, CharWidth=%d\n", FontWidth, RealWidth);
for (i = 0; i < TextLength; i++) {
#if USE_XTHEME
c = Text.data()[i];
#else
c = Text[i];
#endif
if (gLanguage != korean) {
#if USE_XTHEME
c1 = (((c >= ThemeX.Codepage) ? (c - (ThemeX.Codepage - AsciiPageSize)) : c) & 0xff); //International letters
c = c1;
c1 = (((c >= GlobalConfig.Codepage) ? (c - (GlobalConfig.Codepage - AsciiPageSize)) : c) & 0xff); //International letters
c = c1;
if (ThemeX.Proportional) {
#else
c1 = (((c >= GlobalConfig.Codepage) ? (c - (GlobalConfig.Codepage - AsciiPageSize)) : c) & 0xff); //International letters
c = c1;
if (GlobalConfig.Proportional) {
#endif
if (c0 <= 0x20) { // space before or at buffer edge
LeftSpace = 2;
} else {
LeftSpace = GetEmpty(BufferPtr, FirstPixelBuf, ScaledWidth, -1, BufferLineOffset);
}
if (c <= 0x20) { //new space will be half width
RightSpace = 1;
RealWidth = (ScaledWidth >> 1) + 1;
} else {
RightSpace = GetEmpty(FontPixelData + c * FontWidth, FontPixelData, FontWidth, 1, FontLineOffset);
if (RightSpace >= ScaledWidth + Shift) {
RightSpace = 0; //empty place for invisible characters
if (GlobalConfig.Proportional) {
if (c0 <= 0x20) { // space before or at buffer edge
LeftSpace = 2;
} else {
LeftSpace = GetEmpty(BufferPtr, FirstPixelBuf, ScaledWidth, -1, BufferLineOffset);
}
if (c <= 0x20) { //new space will be half width
RightSpace = 1;
RealWidth = (ScaledWidth >> 1) + 1;
} else {
RightSpace = GetEmpty(FontPixelData + c * FontWidth, FontPixelData, FontWidth, 1, FontLineOffset);
if (RightSpace >= ScaledWidth + Shift) {
RightSpace = 0; //empty place for invisible characters
}
RealWidth = FontWidth - RightSpace;
}
RealWidth = FontWidth - RightSpace;
}
} else {
LeftSpace = 2;
RightSpace = Shift;
}
c0 = c; //old value
if ((UINTN)BufferPtr + RealWidth * 4 > (UINTN)FirstPixelBuf + BufferLineWidth * 4) {
break;
}
egRawCompose(BufferPtr - LeftSpace + 2, FontPixelData + c * FontWidth + RightSpace,
RealWidth, FontHeight,
BufferLineOffset, FontLineOffset);
if (i == Cursor) {
c = 0x5F;
} else {
LeftSpace = 2;
RightSpace = Shift;
}
c0 = c; //old value
if ((UINTN)BufferPtr + RealWidth * 4 > (UINTN)FirstPixelBuf + BufferLineWidth * 4) {
break;
}
egRawCompose(BufferPtr - LeftSpace + 2, FontPixelData + c * FontWidth + RightSpace,
RealWidth, FontHeight,
BufferLineOffset, FontLineOffset);
}
BufferPtr += RealWidth - LeftSpace + 2;
} else {
//
if ((c >= 0x20) && (c <= 0x7F)) {
c1 = ((c - 0x20) >> 4) * 28 + (c & 0x0F);
Cho = c1;
Shift = 12;
} else if ((c < 0x20) || ((c > 0x7F) && (c < 0xAC00))) {
Cho = 0x0E; //just a dot
Shift = 8;
} else if ((c >= 0xAC00) && (c <= 0xD638)) {
//korean
Shift = 18;
c -= 0xAC00;
c1 = c / 28;
Jong = c % 28;
Cho = c1 / 21;
Joong = c1 % 21;
Cho += 28 * 7;
Joong += 28 * 8;
Jong += 28 * 9;
}
// DBG("Cho=%d Joong=%d Jong=%d\n", Cho, Joong, Jong);
if (Shift == 18) {
egRawCompose(BufferPtr, FontPixelData + Cho * FontWidth + 4 + FontLineOffset,
ScaledWidth, FontHeight,
BufferLineOffset, FontLineOffset);
if (i == Cursor) {
c = 0x5F;
egRawCompose(BufferPtr - LeftSpace + 2, FontPixelData + c * FontWidth + RightSpace,
RealWidth, FontHeight,
BufferLineOffset, FontLineOffset);
}
BufferPtr += RealWidth - LeftSpace + 2;
} else {
egRawCompose(BufferPtr + BufferLineOffset * 3, FontPixelData + Cho * FontWidth + 2,
ScaledWidth, FontHeight,
BufferLineOffset, FontLineOffset);
}
if (i == Cursor) {
c = 99;
egRawCompose(BufferPtr, FontPixelData + c * FontWidth + 2,
ScaledWidth, FontHeight,
BufferLineOffset, FontLineOffset);
}
if (Shift == 18) {
egRawCompose(BufferPtr + 9, FontPixelData + Joong * FontWidth + 6, //9 , 4 are tunable
ScaledWidth - 8, FontHeight,
BufferLineOffset, FontLineOffset);
egRawCompose(BufferPtr + BufferLineOffset * 9, FontPixelData + Jong * FontWidth + 1,
ScaledWidth, FontHeight - 3,
BufferLineOffset, FontLineOffset);
//
if ((c >= 0x20) && (c <= 0x7F)) {
c1 = ((c - 0x20) >> 4) * 28 + (c & 0x0F);
Cho = c1;
Shift = 12;
} else if ((c < 0x20) || ((c > 0x7F) && (c < 0xAC00))) {
Cho = 0x0E; //just a dot
Shift = 8;
} else if ((c >= 0xAC00) && (c <= 0xD638)) {
//korean
Shift = 18;
c -= 0xAC00;
c1 = c / 28;
Jong = c % 28;
Cho = c1 / 21;
Joong = c1 % 21;
Cho += 28 * 7;
Joong += 28 * 8;
Jong += 28 * 9;
}
// DBG("Cho=%d Joong=%d Jong=%d\n", Cho, Joong, Jong);
if (Shift == 18) {
egRawCompose(BufferPtr, FontPixelData + Cho * FontWidth + 4 + FontLineOffset,
ScaledWidth, FontHeight,
BufferLineOffset, FontLineOffset);
} else {
egRawCompose(BufferPtr + BufferLineOffset * 3, FontPixelData + Cho * FontWidth + 2,
ScaledWidth, FontHeight,
BufferLineOffset, FontLineOffset);
}
if (i == Cursor) {
c = 99;
egRawCompose(BufferPtr, FontPixelData + c * FontWidth + 2,
ScaledWidth, FontHeight,
BufferLineOffset, FontLineOffset);
}
if (Shift == 18) {
egRawCompose(BufferPtr + 9, FontPixelData + Joong * FontWidth + 6, //9 , 4 are tunable
ScaledWidth - 8, FontHeight,
BufferLineOffset, FontLineOffset);
egRawCompose(BufferPtr + BufferLineOffset * 9, FontPixelData + Jong * FontWidth + 1,
ScaledWidth, FontHeight - 3,
BufferLineOffset, FontLineOffset);
}
}
BufferPtr += Shift;
}
BufferPtr += Shift;
}
}
return ((INTN)BufferPtr - (INTN)FirstPixelBuf) / sizeof(EG_PIXEL);
}
#endif
/* EOF */

View File

@ -430,9 +430,9 @@ extern EG_IMAGE *Banner;
extern EG_IMAGE *BigBack;
extern EG_IMAGE *SelectionImages[];
extern EG_IMAGE *Buttons[];
extern EG_IMAGE *FontImage; //not yet converted to XImage
#endif
extern EG_IMAGE *FontImage; //not yet converted to XImage
extern BOOLEAN gThemeChanged;
//extern BOOLEAN gBootArgsChanged;
extern BOOLEAN gBootChanged;
@ -513,10 +513,11 @@ EFI_STATUS InitializeUnicodeCollationProtocol (VOID);
// local variables
//extern INTN FontWidth;
//extern INTN FontHeight;
extern INTN TextHeight;
#if !USE_XTHEME
extern INTN row0TileSize;
extern INTN row1TileSize;
extern INTN TextHeight;
#endif
extern const INTN BCSMargin;
#if USE_XTHEME