mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-27 12:15:19 +01:00
repaired font handling
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
This commit is contained in:
parent
790fedbdc6
commit
97d1d23eb0
@ -95,8 +95,6 @@
|
||||
A570FB0D240D626D0057F26D /* XPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A570FB0B240D626C0057F26D /* XPointer.cpp */; };
|
||||
A5716F83235968BE000CEC60 /* Nasm.inc in Sources */ = {isa = PBXBuildFile; fileRef = A5716F82235968BE000CEC60 /* Nasm.inc */; };
|
||||
A571C28D240574DA00B6A2C5 /* XImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A571C28B240574D900B6A2C5 /* XImage.cpp */; };
|
||||
A57CF7B52419F4F9006DE51E /* XUINTN.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7B32419F4F8006DE51E /* XUINTN.cpp */; };
|
||||
A57CF7B82419F51B006DE51E /* XUINTN_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7B72419F51A006DE51E /* XUINTN_test.cpp */; };
|
||||
A57CF7BB241A8A13006DE51E /* XTheme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7B9241A8A12006DE51E /* XTheme.cpp */; };
|
||||
A57CF7C6241BE0A4006DE51E /* strcmp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7BF241BE0A4006DE51E /* strcmp.cpp */; };
|
||||
A57CF7C8241BE0A4006DE51E /* strlen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A57CF7C3241BE0A4006DE51E /* strlen.cpp */; };
|
||||
@ -2508,10 +2506,6 @@
|
||||
A571C28A240574BB00B6A2C5 /* remove_ref.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = remove_ref.h; sourceTree = "<group>"; };
|
||||
A571C28B240574D900B6A2C5 /* XImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XImage.cpp; sourceTree = "<group>"; };
|
||||
A571C28C240574D900B6A2C5 /* XImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XImage.h; sourceTree = "<group>"; };
|
||||
A57CF7B32419F4F8006DE51E /* XUINTN.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XUINTN.cpp; sourceTree = "<group>"; };
|
||||
A57CF7B42419F4F8006DE51E /* XUINTN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XUINTN.h; sourceTree = "<group>"; };
|
||||
A57CF7B62419F51A006DE51E /* XUINTN_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XUINTN_test.h; sourceTree = "<group>"; };
|
||||
A57CF7B72419F51A006DE51E /* XUINTN_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XUINTN_test.cpp; sourceTree = "<group>"; };
|
||||
A57CF7B9241A8A12006DE51E /* XTheme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XTheme.cpp; sourceTree = "<group>"; };
|
||||
A57CF7BA241A8A13006DE51E /* XTheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XTheme.h; sourceTree = "<group>"; };
|
||||
A57CF7BD241BE0A4006DE51E /* stdlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdlib.h; sourceTree = "<group>"; };
|
||||
@ -8307,8 +8301,6 @@
|
||||
A5D12C35243A0BE500DFA98A /* XStringWP.h */,
|
||||
A571C2772405749900B6A2C5 /* XToolsCommon.cpp */,
|
||||
A571C2702405749900B6A2C5 /* XToolsCommon.h */,
|
||||
A57CF7B32419F4F8006DE51E /* XUINTN.cpp */,
|
||||
A57CF7B42419F4F8006DE51E /* XUINTN.h */,
|
||||
);
|
||||
path = cpp_foundation;
|
||||
sourceTree = "<group>";
|
||||
@ -8349,8 +8341,6 @@
|
||||
A571C27F240574A100B6A2C5 /* XStringWArray_test.cpp */,
|
||||
A571C283240574A100B6A2C5 /* XStringW_test.h */,
|
||||
A571C289240574A100B6A2C5 /* XStringW_test.cpp */,
|
||||
A57CF7B72419F51A006DE51E /* XUINTN_test.cpp */,
|
||||
A57CF7B62419F51A006DE51E /* XUINTN_test.h */,
|
||||
);
|
||||
path = cpp_unit_test;
|
||||
sourceTree = "<group>";
|
||||
@ -16607,7 +16597,6 @@
|
||||
A5AAFBC6237F13B3009CD413 /* Variable.c in Sources */,
|
||||
A5AAFB3A237F13B3009CD413 /* SmramProfileRecord.c in Sources */,
|
||||
A5AA0571237F13C1009CD413 /* WriteMsr64.c in Sources */,
|
||||
A57CF7B52419F4F9006DE51E /* XUINTN.cpp in Sources */,
|
||||
A5AAFC37237F13B3009CD413 /* Vtutf8.c in Sources */,
|
||||
A5AAFD2D237F13B4009CD413 /* DebugAgentLibNull.c in Sources */,
|
||||
A5816DED24180F4D003BA66C /* panic.cpp in Sources */,
|
||||
@ -17096,7 +17085,6 @@
|
||||
A5AAFC1A237F13B3009CD413 /* X64Entry.c in Sources */,
|
||||
A5AAFB33237F13B3009CD413 /* Page.c in Sources */,
|
||||
A5AA06D4237F13C2009CD413 /* SmmPeriodicSmiLib.c in Sources */,
|
||||
A57CF7B82419F51B006DE51E /* XUINTN_test.cpp in Sources */,
|
||||
A5AAFC45237F13B3009CD413 /* SdHci.c in Sources */,
|
||||
A5AAFC0C237F13B3009CD413 /* Database.c in Sources */,
|
||||
A5AAFC5D237F13B3009CD413 /* PciIo.c in Sources */,
|
||||
|
@ -4239,27 +4239,14 @@ XTheme::GetThemeTagSettings (void* DictP)
|
||||
FontFileName.takeValueFrom(Dict2->string);
|
||||
}
|
||||
}
|
||||
#if USE_XTHEME
|
||||
Dict2 = GetProperty (Dict, "CharWidth");
|
||||
ThemeX.CharWidth = (UINTN)GetPropertyInteger (Dict2, ThemeX.CharWidth);
|
||||
if (ThemeX.CharWidth & 1) {
|
||||
MsgLog("Warning! Character width %lld should be even!\n", ThemeX.CharWidth);
|
||||
}
|
||||
|
||||
Dict2 = GetProperty (Dict, "Proportional");
|
||||
ThemeX.Proportional = IsPropertyTrue (Dict2);
|
||||
|
||||
#else
|
||||
Dict2 = GetProperty (Dict, "CharWidth");
|
||||
CharWidth = (UINTN)GetPropertyInteger (Dict2, CharWidth);
|
||||
if (GlobalConfig.CharWidth & 1) {
|
||||
if (CharWidth & 1) {
|
||||
MsgLog("Warning! Character width %lld should be even!\n", CharWidth);
|
||||
}
|
||||
|
||||
Dict2 = GetProperty (Dict, "Proportional");
|
||||
GlobalConfig.Proportional = IsPropertyTrue (Dict2);
|
||||
|
||||
#endif
|
||||
Proportional = IsPropertyTrue (Dict2);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1498,7 +1498,7 @@ INTN REFIT_MENU_SCREEN::DrawTextXY(IN const XStringW& Text, IN INTN XPos, IN INT
|
||||
* so make a place to be large enoungh
|
||||
*/
|
||||
ThemeX.MeasureText(Text, &TextWidth, NULL); //NULL means we already know Height
|
||||
|
||||
// DBG("drawXY=%ls width=%lld\n", Text.wc_str(), TextWidth);
|
||||
if (XAlign == X_IS_LEFT) {
|
||||
TextWidth = UGAWidth - XPos - 1;
|
||||
XText = XPos;
|
||||
@ -2563,20 +2563,20 @@ VOID REFIT_MENU_SCREEN::DrawTextCorner(UINTN TextC, UINT8 Align)
|
||||
// Display Clover boot volume
|
||||
if (SelfVolume->VolLabel && SelfVolume->VolLabel[0] != L'#') {
|
||||
// Text = PoolPrint(L"%s, booted from %s", gFirmwareRevision, SelfVolume->VolLabel);
|
||||
Text = XStringW() + gFirmwareRevision + L", booted from " + SelfVolume->VolLabel;
|
||||
Text = XStringW() + gFirmwareRevision + L", booted from "_XSW + SelfVolume->VolLabel;
|
||||
}
|
||||
if (Text.isEmpty()) {
|
||||
Text = XStringW() + gFirmwareRevision + L" " + SelfVolume->VolName;
|
||||
Text = XStringW() + gFirmwareRevision + L" "_XSW + SelfVolume->VolName;
|
||||
}
|
||||
break;
|
||||
case TEXT_CORNER_HELP:
|
||||
Text = XStringW() + L"F1:Help";
|
||||
Text = L"F1:Help"_XSW;
|
||||
break;
|
||||
case TEXT_CORNER_OPTIMUS:
|
||||
if (gGraphics[0].Vendor != Intel) {
|
||||
Text = XStringW() + L"Discrete";
|
||||
Text = L"Discrete"_XSW;
|
||||
} else {
|
||||
Text = XStringW() + L"Intel";
|
||||
Text = L"Intel"_XSW;
|
||||
}
|
||||
// Text = (NGFX == 2)?L"Intel":L"Discrete";
|
||||
break;
|
||||
@ -3171,10 +3171,13 @@ VOID REFIT_MENU_SCREEN::MainMenuStyle(IN UINTN Function, IN CONST CHAR16 *ParamT
|
||||
DrawMainMenuLabel(Entries[ScrollState.CurrentSelection].Title,
|
||||
(UGAWidth >> 1), textPosY);
|
||||
}
|
||||
|
||||
// DBG("draw TEXT_CORNER_HELP\n");
|
||||
DrawTextCorner(TEXT_CORNER_HELP, X_IS_LEFT);
|
||||
// DBG("draw TEXT_CORNER_OPTIMUS\n");
|
||||
DrawTextCorner(TEXT_CORNER_OPTIMUS, X_IS_CENTER);
|
||||
// DBG("draw TEXT_CORNER_REVISION\n");
|
||||
DrawTextCorner(TEXT_CORNER_REVISION, X_IS_RIGHT);
|
||||
// DBG("MouseBirth\n");
|
||||
Status = MouseBirth();
|
||||
if(EFI_ERROR(Status)) {
|
||||
DBG("can't bear mouse at all! Status=%s\n", strerror(Status));
|
||||
|
@ -7,3 +7,8 @@
|
||||
//
|
||||
|
||||
#include "XCinema.h"
|
||||
|
||||
void FILM::Advance()
|
||||
{
|
||||
CurrentFrame = ++CurrentFrame % Count;
|
||||
}
|
||||
|
@ -25,23 +25,30 @@ typedef struct FRAME {
|
||||
|
||||
class FILM
|
||||
{
|
||||
public:
|
||||
bool RunOnce;
|
||||
protected:
|
||||
INTN Id; //enumeration value but keep it to be int for extensibility
|
||||
INTN FrameTime; //usually 50, 100, 200 ms
|
||||
XString Path; //user defined name for folder and files Path/Path_002.png etc
|
||||
XArray<FRAME> Frames;
|
||||
INTN Count; // it is not Frames.size(), it is last index
|
||||
XObjArray<FRAME> Frames; //Frames can be not sorted
|
||||
INTN LastIndex; // it is not Frames.size(), it is last index inclusive, so frames 0,1,2,5,8 be LastIndex = 8
|
||||
EG_RECT FilmPlace;
|
||||
INTN CurrentFrame; // like a static value will be increase between 0..LastIndex
|
||||
|
||||
public:
|
||||
FILM();
|
||||
FILM(INTN Id);
|
||||
FILM(INTN Id) : RunOnce(false), Id(Id), FrameTime(0), Path(), Frames(),
|
||||
LastIndex(0), FilmPlace(), CurrentFrame(0) {};
|
||||
~FILM();
|
||||
|
||||
const XImage& GetImage(INTN Index);
|
||||
void AddImage(const XImage& Image, INTN Index);
|
||||
void AddFrame(const FRAME& Frame, INTN Index);
|
||||
size_t Size() { return Frames.size(); }
|
||||
INTN LastFrame() { return Count; }
|
||||
INTN LastFrame() { return LastIndex; }
|
||||
void GetFilm(const XStringW& Path); //read from Theme
|
||||
void SetPlace(const EG_RECT& Rect);
|
||||
void Advance() { ++CurrentFrame %= (LastIndex + 1); }
|
||||
|
||||
};
|
||||
|
||||
@ -55,11 +62,17 @@ public:
|
||||
// Each Screen contains a pointer to FILM. And moreover titleFilm, or BackgroundFilm or even entryFilm
|
||||
// Next problem is a timeout between frames.
|
||||
// A theme contains images with indexes 1,2,5,6 for one Id.
|
||||
// This Id contains fixed timeout between frames
|
||||
// This Id contains fixed timeout between frames. Then next updateAnime Index will be compared with current tick
|
||||
// if yes then update. Static index?
|
||||
//
|
||||
// in the far future I'll plan to make dynamic SVG: parse SVGIcon with a variable argument
|
||||
// and then rasterize it. Real SVG contains constants only so it will be dynamicSVG.
|
||||
// then Entry->Image should be reparsed each time it created or contains flag to update every frameTime
|
||||
|
||||
class XCinema
|
||||
{
|
||||
protected:
|
||||
XArray<FILM> Cinema;
|
||||
XObjArray<FILM> Cinema;
|
||||
|
||||
|
||||
public:
|
||||
|
@ -277,43 +277,45 @@ void XImage::Compose(INTN PosX, INTN PosY, const XImage& TopImage, bool Lowest)
|
||||
Area.YPos = 0;
|
||||
Area.Width = TopImage.GetWidth();
|
||||
Area.Height = TopImage.GetHeight();
|
||||
Compose(OutPlace, Area, TopImage, Lowest);
|
||||
Compose(OutPlace, Area, TopImage, Lowest, 0.f);
|
||||
}
|
||||
void XImage::Compose(const EG_RECT& OutPlace, const EG_RECT& InPlace, const XImage& TopImage, bool Lowest)
|
||||
// TopScale is for scaling TopImage. = 0.f means no scale or = 1.f
|
||||
// InPlace is a place in TopImage before scaling
|
||||
void XImage::Compose(const EG_RECT& OutPlace, const EG_RECT& InPlace, const XImage& TopImage, bool Lowest, float TopScale)
|
||||
{
|
||||
|
||||
//sample
|
||||
/*
|
||||
INTN Dx = OwnPlace.XPos - InputRect.XPos;
|
||||
INTN Dy = OwnPlace.YPos - InputRect.YPos;
|
||||
INTN W = MIN(OwnPlace.Width, InputRect.Width);
|
||||
INTN H = MIN(OwnPlace.Height, InputRect.Height);
|
||||
for (INTN y = OwnPlace.YPos; y - OwnPlace.YPos < H && y < GetHeight() && (y - Dy) < Image.GetHeight(); ++y) {
|
||||
for (INTN x = OwnPlace.XPos; x - OwnPlace.XPos < W && x < GetWidth() && (x - Dx) < Image.GetWidth(); ++x) {
|
||||
PixelData[y * Width + x] = Image.GetPixel(x - Dx, y - Dy);
|
||||
}
|
||||
}
|
||||
*/
|
||||
INTN PosX = InPlace.XPos;
|
||||
INTN PosY = InPlace.YPos;
|
||||
INTN WArea = InPlace.Width;
|
||||
INTN HArea = InPlace.Height;
|
||||
XImage Top2;
|
||||
if (TopScale != 0.f && TopScale != 1.f) {
|
||||
Top2.setSizeInPixels((UINTN)(TopImage.GetWidth() * TopScale), (UINTN)(TopImage.GetHeight() * TopScale));
|
||||
Top2.CopyScaled(TopImage, TopScale);
|
||||
PosX = (int)(PosX * TopScale);
|
||||
PosY = (int)(PosY * TopScale);
|
||||
WArea = (int)(WArea * TopScale);
|
||||
HArea = (int)(HArea * TopScale);
|
||||
}
|
||||
const XImage& Top = (TopScale != 0.f && TopScale != 1.f) ? Top2 : TopImage; //this is a link, not copy
|
||||
|
||||
//assumed Area.Width == OutPlace.Width
|
||||
// if not choose min
|
||||
INTN WArea = MIN(InPlace.Width, OutPlace.Width);
|
||||
WArea = MIN(WArea, OutPlace.Width);
|
||||
if (OutPlace.XPos + WArea > GetWidth()) { //coordinate in this image - OutPlace
|
||||
WArea = GetWidth() - OutPlace.XPos;
|
||||
}
|
||||
INTN HArea = MIN(InPlace.Height, OutPlace.Height);
|
||||
HArea = MIN(HArea, OutPlace.Height);
|
||||
if (OutPlace.YPos + HArea > GetHeight()) {
|
||||
HArea = GetHeight() - OutPlace.YPos;
|
||||
}
|
||||
//change only affected pixels
|
||||
for (INTN y = 0; y < HArea && (y + PosY) < TopImage.GetHeight(); ++y) {
|
||||
for (INTN y = 0; y < HArea && (y + PosY) < Top.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(OutPlace.XPos, OutPlace.YPos + y);
|
||||
for (INTN x = 0; x < WArea && (x + PosX) < TopImage.GetWidth(); ++x) {
|
||||
for (INTN x = 0; x < WArea && (x + PosX) < Top.GetWidth(); ++x) {
|
||||
//------
|
||||
// test compAlpha = 255; TopAlpha = 0 -> only Comp, TopAplha = 255 -> only Top
|
||||
UINT32 TopAlpha = TopImage.GetPixel(x + PosX, y + PosY).Reserved & 0xFF; //0, 255
|
||||
UINT32 TopAlpha = Top.GetPixel(x + PosX, y + PosY).Reserved & 0xFF; //0, 255
|
||||
UINT32 CompAlpha = CompPtr->Reserved & 0xFF; //255
|
||||
UINT32 RevAlpha = 255 - TopAlpha; //2<<8; 255, 0
|
||||
UINT32 TempAlpha = CompAlpha * RevAlpha; //2<<16; 255*255, 0
|
||||
@ -322,13 +324,13 @@ void XImage::Compose(const EG_RECT& OutPlace, const EG_RECT& InPlace, const XIma
|
||||
//final alpha =(1-(1-x)*(1-y)) =(255*255-(255-topA)*(255-compA))/255 = topA+compA*(1-topA)
|
||||
|
||||
if (FinalAlpha != 0) {
|
||||
UINT32 Temp = (CompPtr->Blue * TempAlpha) + (TopImage.GetPixel(x + PosX, y + PosY).Blue * TopAlpha);
|
||||
UINT32 Temp = (CompPtr->Blue * TempAlpha) + (Top.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) + (Top.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) + (Top.GetPixel(x + PosX, y + PosY).Red * TopAlpha);
|
||||
CompPtr->Red = (UINT8)(Temp / FinalAlpha);
|
||||
}
|
||||
|
||||
|
@ -88,7 +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(const EG_RECT& OwnPlace, const EG_RECT& InputRect, const XImage& TopImage, bool Lowest, float TopScale = 0.f);
|
||||
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);
|
||||
|
@ -132,10 +132,10 @@ public:
|
||||
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);
|
||||
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType, float textScale = 0.f);
|
||||
//overload for UTF8 text
|
||||
INTN RenderText(IN const XString& Text, OUT XImage* CompImage_ptr,
|
||||
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType);
|
||||
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType, float textScale = 0.f);
|
||||
VOID MeasureText(IN const XStringW& Text, OUT INTN *Width, OUT INTN *Height);
|
||||
|
||||
|
||||
|
@ -84,11 +84,16 @@ NSVGfontChain *fontsDB = NULL;
|
||||
// so one more parameter is TextStyle
|
||||
VOID XTheme::MeasureText(IN const XStringW& Text, OUT INTN *Width, OUT INTN *Height)
|
||||
{
|
||||
INTN ScaledWidth = (INTN)(CharWidth * Scale);
|
||||
INTN ScaledWidth = CharWidth;
|
||||
INTN ScaledHeight = FontHeight;
|
||||
if (Scale != 0.f) {
|
||||
ScaledWidth = (INTN)(CharWidth * Scale);
|
||||
ScaledHeight = (INTN)(FontHeight * Scale);
|
||||
}
|
||||
if (Width != NULL)
|
||||
*Width = Text.length() * ((FontWidth > ScaledWidth) ? FontWidth : ScaledWidth);
|
||||
*Width = StrLen(Text.wc_str()) * ((FontWidth > ScaledWidth) ? FontWidth : ScaledWidth);
|
||||
if (Height != NULL)
|
||||
*Height = FontHeight;
|
||||
*Height = ScaledHeight;
|
||||
}
|
||||
#else
|
||||
|
||||
@ -118,31 +123,38 @@ void XTheme::LoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
|
||||
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
|
||||
Status = 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
|
||||
if (!EFI_ERROR(Status)) {
|
||||
CharWidth = 22; //standard for korean
|
||||
} else {
|
||||
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()) {
|
||||
if (EFI_ERROR(Status)) {
|
||||
//not loaded, use common
|
||||
Rows = 16; //standard for english
|
||||
Cols = 16;
|
||||
Status = NewImage.LoadXImage(ThemeDir, FontFileName);
|
||||
}
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
//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
|
||||
//else use embedded even if it is not embedded
|
||||
if (EFI_ERROR(Status)) {
|
||||
NewImage.FromPNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data));
|
||||
Status = NewImage.FromPNG(ACCESS_EMB_DATA(emb_font_data), ACCESS_EMB_SIZE(emb_font_data));
|
||||
}
|
||||
if (EFI_ERROR(Status)) {
|
||||
MsgLog("No font found!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,9 +170,9 @@ void XTheme::LoadFontImage(IN BOOLEAN UseEmbedded, IN INTN Rows, IN INTN Cols)
|
||||
FontWidth = ImageWidth / Cols;
|
||||
FontHeight = ImageHeight / Rows;
|
||||
TextHeight = FontHeight + (int)(TEXT_YMARGIN * 2 * Scale);
|
||||
if (!isKorean) {
|
||||
CharWidth = FontWidth;
|
||||
}
|
||||
// if (!isKorean) {
|
||||
// CharWidth = FontWidth; //there is default value anyway
|
||||
// }
|
||||
|
||||
FirstPixel = *PixelPtr;
|
||||
for (INTN y = 0; y < Rows; y++) {
|
||||
@ -447,53 +459,62 @@ INTN GetEmpty(EG_PIXEL *Ptr, EG_PIXEL *FirstPixel, INTN MaxWidth, INTN Step, INT
|
||||
|
||||
#if USE_XTHEME
|
||||
INTN XTheme::RenderText(IN const XString& Text, OUT XImage* CompImage_ptr,
|
||||
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType)
|
||||
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType, float textScale)
|
||||
{
|
||||
const XStringW& UTF16Text = XStringW().takeValueFrom(Text.c_str());
|
||||
return RenderText(UTF16Text, CompImage_ptr, PosX, PosY, Cursor, textType);
|
||||
return RenderText(UTF16Text, CompImage_ptr, PosX, PosY, Cursor, textType, textScale);
|
||||
}
|
||||
|
||||
INTN XTheme::RenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
|
||||
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType)
|
||||
IN INTN PosX, IN INTN PosY, IN INTN Cursor, INTN textType, float textScale)
|
||||
{
|
||||
XImage& CompImage = *CompImage_ptr;
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FontPixel;
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FirstPixel;
|
||||
INTN TextLength;
|
||||
INTN Shift = 0;
|
||||
UINTN Cho = 0, Jong = 0, Joong = 0;
|
||||
INTN TextLength;
|
||||
UINTN Cho = 0, Jong = 0, Joong = 0;
|
||||
INTN LeftSpace, RightSpace;
|
||||
INTN RealWidth = 0;
|
||||
|
||||
if (TypeSVG) {
|
||||
return renderSVGtext(&CompImage, PosX, PosY, textType, Text, Cursor);
|
||||
}
|
||||
|
||||
if (textScale == 0.f) {
|
||||
textScale = 1.f;
|
||||
}
|
||||
INTN CharScaledWidth = (INTN)(CharWidth * textScale);
|
||||
INTN FontScaledWidth = (INTN)(FontWidth * textScale); //FontWidth should be scaled as well?
|
||||
// clip the text
|
||||
TextLength = Text.size();
|
||||
DBG("text to render %ls length %lld\n", Text.wc_str(), Text.size());
|
||||
// TextLength = StrLenInWChar(Text.wc_str()); //it must be UTF16 length
|
||||
TextLength = StrLen(Text.wc_str());
|
||||
DBG("text to render %ls length %lld\n", Text.wc_str(), TextLength);
|
||||
if (FontImage.isEmpty()) {
|
||||
PrepareFont(); //at the boot screen there is embedded font
|
||||
}
|
||||
|
||||
// DBG("TextLength =%d PosX=%d PosY=%d\n", TextLength, PosX, PosY);
|
||||
DBG("TextLength =%lld PosX=%lld PosY=%lld\n", TextLength, PosX, PosY);
|
||||
FirstPixel = CompImage.GetPixel(0,0);
|
||||
FontPixel = FontImage.GetPixel(0,0);
|
||||
UINT16 c0 = 0;
|
||||
RealWidth = CharWidth;
|
||||
UINT16 c0 = 0x20;
|
||||
INTN RealWidth = CharScaledWidth;
|
||||
INTN Shift = (FontScaledWidth - CharScaledWidth) / 2;
|
||||
if (Shift < 0) {
|
||||
Shift = 0;
|
||||
}
|
||||
DBG("FontWidth=%lld, CharWidth=%lld\n", FontWidth, RealWidth);
|
||||
EG_RECT Area;
|
||||
|
||||
EG_RECT Area; //area is scaled
|
||||
Area.YPos = PosY; // not sure
|
||||
Area.Height = FontHeight;
|
||||
EG_RECT Bukva;
|
||||
Area.Height = TextHeight;
|
||||
EG_RECT Bukva; //bukva is not scaled place
|
||||
Bukva.YPos = 0;
|
||||
Bukva.Width = FontWidth;
|
||||
Bukva.Height = FontHeight;
|
||||
DBG("codepage=%llx, asciiPage=%x\n", GlobalConfig.Codepage, AsciiPageSize);
|
||||
for (INTN i = 0; i < TextLength; i++) {
|
||||
UINT16 c = Text[i];
|
||||
// DBG("initial char to render 0x%x\n", c); //good
|
||||
for (INTN i = 0; i < TextLength && c0 != 0; i++) {
|
||||
UINT16 c = Text[i]; //including UTF8 -> UTF16 conversion
|
||||
DBG("initial char to render 0x%x\n", c); //good
|
||||
if (gLanguage != korean) { //russian Codepage = 0x410
|
||||
if (c >= 0x410 && c < 0x450) {
|
||||
//we have russian raster fonts with chars at 0xC0
|
||||
@ -512,39 +533,41 @@ INTN XTheme::RenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
|
||||
}
|
||||
if (c <= 0x20) { //new space will be half font width
|
||||
RightSpace = 1;
|
||||
RealWidth = (FontWidth >> 1) + 1;
|
||||
RealWidth = (CharScaledWidth >> 1) + 1;
|
||||
} else {
|
||||
RightSpace = GetEmpty(FontImage, FontPixel, c * FontWidth, 1);
|
||||
RightSpace = GetEmpty(FontImage, FontPixel, c * FontWidth, 1); //not scaled yet
|
||||
if (RightSpace >= FontWidth) {
|
||||
RightSpace = 0; //empty place for invisible characters
|
||||
}
|
||||
RealWidth = FontWidth - RightSpace; //a part of char
|
||||
RealWidth = CharScaledWidth - (int)(RightSpace * textScale); //a part of char
|
||||
}
|
||||
|
||||
} else {
|
||||
LeftSpace = 2;
|
||||
RightSpace = 0;
|
||||
RightSpace = Shift;
|
||||
}
|
||||
// DBG(" RealWidth = %lld LeftSpace = %lld RightSpace = %lld\n", RealWidth, LeftSpace, RightSpace);
|
||||
c0 = c; //old value
|
||||
LeftSpace = (int)(LeftSpace * textScale); //was not scaled yet
|
||||
//RightSpace will not be scaled
|
||||
// RealWidth are scaled now
|
||||
DBG(" RealWidth = %lld LeftSpace = %lld RightSpace = %lld\n", RealWidth, LeftSpace, RightSpace);
|
||||
c0 = c; //remember old value
|
||||
if (PosX + RealWidth > CompImage.GetWidth()) {
|
||||
//no more place for character
|
||||
DBG("no more place for character\n");
|
||||
break;
|
||||
}
|
||||
|
||||
Area.XPos = PosX + 2 - LeftSpace;
|
||||
Area.Width = RealWidth;
|
||||
Bukva.XPos = c * FontWidth + RightSpace;
|
||||
// DBG("place [%lld,%lld,%lld,%lld], bukva [%lld,%lld,%lld,%lld]\n",
|
||||
// Area.XPos, Area.YPos, Area.Width, Area.Height,
|
||||
// Bukva.XPos, Bukva.YPos, Bukva.Width, Bukva.Height);
|
||||
// Bukva.YPos
|
||||
CompImage.Compose(Area, Bukva, FontImage, false);
|
||||
DBG("place [%lld,%lld,%lld,%lld], bukva [%lld,%lld,%lld,%lld]\n",
|
||||
Area.XPos, Area.YPos, Area.Width, Area.Height,
|
||||
Bukva.XPos, Bukva.YPos, Bukva.Width, Bukva.Height);
|
||||
|
||||
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
|
||||
// CompImage.CopyRect(FontImage, Area, Bukva);
|
||||
if (i == Cursor) {
|
||||
c = 0x5F;
|
||||
Bukva.XPos = c * FontWidth + RightSpace;
|
||||
CompImage.Compose(Area, Bukva, FontImage, false);
|
||||
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
|
||||
}
|
||||
PosX += RealWidth - LeftSpace + 2; //next char position
|
||||
} else {
|
||||
@ -581,29 +604,29 @@ INTN XTheme::RenderText(IN const XStringW& Text, OUT XImage* CompImage_ptr,
|
||||
if (Shift == 18) {
|
||||
Bukva.XPos = Cho * FontWidth + 4;
|
||||
Bukva.YPos = 1;
|
||||
CompImage.Compose(Area, Bukva, FontImage, false);
|
||||
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
|
||||
} else {
|
||||
Area.YPos = PosY + 3;
|
||||
Bukva.XPos = Cho * FontWidth + 2;
|
||||
Bukva.YPos = 0;
|
||||
CompImage.Compose(Area, Bukva, FontImage, false);
|
||||
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
|
||||
}
|
||||
if (i == Cursor) {
|
||||
c = 99;
|
||||
Bukva.XPos = c * FontWidth + 2;
|
||||
CompImage.Compose(Area, Bukva, FontImage, false);
|
||||
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
|
||||
}
|
||||
if (Shift == 18) {
|
||||
Area.XPos = PosX + 9;
|
||||
Area.YPos = PosY;
|
||||
Bukva.XPos = Joong * FontWidth + 6;
|
||||
Bukva.YPos = 0;
|
||||
CompImage.Compose(Area, Bukva, FontImage, false);
|
||||
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
|
||||
|
||||
Area.XPos = PosX;
|
||||
Area.YPos = PosY + 9;
|
||||
Bukva.XPos = Jong * FontWidth + 1;
|
||||
CompImage.Compose(Area, Bukva, FontImage, false);
|
||||
CompImage.Compose(Area, Bukva, FontImage, false, textScale);
|
||||
}
|
||||
|
||||
PosX += CharWidth; //Shift;
|
||||
|
Loading…
Reference in New Issue
Block a user