From 75427f2d83c73fadfe5d66cac5c7fa9d2ce2f213 Mon Sep 17 00:00:00 2001 From: Sergey Isakov Date: Tue, 7 Apr 2020 22:48:36 +0300 Subject: [PATCH] refactoring text handling Signed-off-by: Sergey Isakov --- rEFIt_UEFI/Platform/Settings.cpp | 31 +- rEFIt_UEFI/Platform/cpu.cpp | 6 +- rEFIt_UEFI/cpp_foundation/XArray.h | 8 +- rEFIt_UEFI/entry_scan/loader.cpp | 45 +- rEFIt_UEFI/gui/REFIT_MENU_SCREEN.cpp | 95 ++-- rEFIt_UEFI/libeg/VectorGraphics.cpp | 2 - rEFIt_UEFI/libeg/XImage.cpp | 42 +- rEFIt_UEFI/libeg/XImage.h | 1 + rEFIt_UEFI/libeg/XTheme.cpp | 4 + rEFIt_UEFI/libeg/XTheme.h | 14 + rEFIt_UEFI/libeg/image.cpp | 2 + rEFIt_UEFI/libeg/libegint.h | 7 +- rEFIt_UEFI/libeg/text.cpp | 674 +++++++++++++++++++-------- rEFIt_UEFI/refit/lib.h | 5 +- 14 files changed, 633 insertions(+), 303 deletions(-) diff --git a/rEFIt_UEFI/Platform/Settings.cpp b/rEFIt_UEFI/Platform/Settings.cpp index 635433c04..83d24a2bf 100644 --- a/rEFIt_UEFI/Platform/Settings.cpp +++ b/rEFIt_UEFI/Platform/Settings.cpp @@ -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); } } } diff --git a/rEFIt_UEFI/Platform/cpu.cpp b/rEFIt_UEFI/Platform/cpu.cpp index 557c331c5..998ebd827 100644 --- a/rEFIt_UEFI/Platform/cpu.cpp +++ b/rEFIt_UEFI/Platform/cpu.cpp @@ -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); } } diff --git a/rEFIt_UEFI/cpp_foundation/XArray.h b/rEFIt_UEFI/cpp_foundation/XArray.h index b1a307c0b..6b167da00 100755 --- a/rEFIt_UEFI/cpp_foundation/XArray.h +++ b/rEFIt_UEFI/cpp_foundation/XArray.h @@ -242,11 +242,11 @@ template TYPE &XArray::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 const TYPE& XArray::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 diff --git a/rEFIt_UEFI/entry_scan/loader.cpp b/rEFIt_UEFI/entry_scan/loader.cpp index 618e69cdd..c2ea1514b 100644 --- a/rEFIt_UEFI/entry_scan/loader.cpp +++ b/rEFIt_UEFI/entry_scan/loader.cpp @@ -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); } } diff --git a/rEFIt_UEFI/gui/REFIT_MENU_SCREEN.cpp b/rEFIt_UEFI/gui/REFIT_MENU_SCREEN.cpp index 1f57684c6..cee968303 100644 --- a/rEFIt_UEFI/gui/REFIT_MENU_SCREEN.cpp +++ b/rEFIt_UEFI/gui/REFIT_MENU_SCREEN.cpp @@ -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 { diff --git a/rEFIt_UEFI/libeg/VectorGraphics.cpp b/rEFIt_UEFI/libeg/VectorGraphics.cpp index fdb69bb11..bdfebc7c2 100755 --- a/rEFIt_UEFI/libeg/VectorGraphics.cpp +++ b/rEFIt_UEFI/libeg/VectorGraphics.cpp @@ -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) diff --git a/rEFIt_UEFI/libeg/XImage.cpp b/rEFIt_UEFI/libeg/XImage.cpp index 5c188bb83..7971e4f54 100644 --- a/rEFIt_UEFI/libeg/XImage.cpp +++ b/rEFIt_UEFI/libeg/XImage.cpp @@ -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; diff --git a/rEFIt_UEFI/libeg/XImage.h b/rEFIt_UEFI/libeg/XImage.h index 12c300b31..1b618fa77 100644 --- a/rEFIt_UEFI/libeg/XImage.h +++ b/rEFIt_UEFI/libeg/XImage.h @@ -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); diff --git a/rEFIt_UEFI/libeg/XTheme.cpp b/rEFIt_UEFI/libeg/XTheme.cpp index f5ef3d802..202bd3e2e 100644 --- a/rEFIt_UEFI/libeg/XTheme.cpp +++ b/rEFIt_UEFI/libeg/XTheme.cpp @@ -292,6 +292,10 @@ void XTheme::Init() row0TileSize = 144; row1TileSize = 64; + + FontWidth = 9; + FontHeight = 18; + TextHeight = 19; } /* diff --git a/rEFIt_UEFI/libeg/XTheme.h b/rEFIt_UEFI/libeg/XTheme.h index 5c48a4ebd..1cea2b8d4 100644 --- a/rEFIt_UEFI/libeg/XTheme.h +++ b/rEFIt_UEFI/libeg/XTheme.h @@ -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(); diff --git a/rEFIt_UEFI/libeg/image.cpp b/rEFIt_UEFI/libeg/image.cpp index e9b5bfc44..36f6b3867 100644 --- a/rEFIt_UEFI/libeg/image.cpp +++ b/rEFIt_UEFI/libeg/image.cpp @@ -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) diff --git a/rEFIt_UEFI/libeg/libegint.h b/rEFIt_UEFI/libeg/libegint.h index 0d6d6c4a3..dfe83bcce 100644 --- a/rEFIt_UEFI/libeg/libegint.h +++ b/rEFIt_UEFI/libeg/libegint.h @@ -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 diff --git a/rEFIt_UEFI/libeg/text.cpp b/rEFIt_UEFI/libeg/text.cpp index 63b3aa1a7..0696c9c66 100644 --- a/rEFIt_UEFI/libeg/text.cpp +++ b/rEFIt_UEFI/libeg/text.cpp @@ -35,6 +35,10 @@ */ //Slice 2011 - 2016 numerous improvements +extern "C" { +#include +} + #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 */ diff --git a/rEFIt_UEFI/refit/lib.h b/rEFIt_UEFI/refit/lib.h index 7bd7e6533..37a780a6e 100644 --- a/rEFIt_UEFI/refit/lib.h +++ b/rEFIt_UEFI/refit/lib.h @@ -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