Add support for pseudo monospace with a non-monospace (proportional) font.

This commit is contained in:
retro100 2021-04-29 01:19:58 +02:00
parent 2f0567b9ef
commit aac6061671
6 changed files with 85 additions and 40 deletions

View File

@ -106,7 +106,7 @@ export OUTPUT := $(CURDIR)/$(TARGET)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
$(BUILD): $(BUILD):
@[ -d $@ ] || mkdir -p $@ @[ -d $@ ] || mkdir -p $@
@make --no-print-directory -j4 -C $(BUILD) -f $(CURDIR)/Makefile @make --no-print-directory -j4 -C $(BUILD) -f $(CURDIR)/Makefile.currentDevkitPPC
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
clean: clean:

View File

@ -34,7 +34,7 @@ void InitFreeType(uint8_t* fontBuffer, FT_Long bufferSize)
FT_New_Memory_Face(ftLibrary, (FT_Byte *)fontBuffer, bufferSize, 0, &ftFace); FT_New_Memory_Face(ftLibrary, (FT_Byte *)fontBuffer, bufferSize, 0, &ftFace);
ftSlot = ftFace->glyph; ftSlot = ftFace->glyph;
for(int i=0; i<50; i++) for(int i=0; i <= MAX_FONT_SIZE; i++)
fontSystem[i] = NULL; fontSystem[i] = NULL;
} }
@ -52,7 +52,7 @@ void ChangeFontSize(FT_UInt pixelSize)
void ClearFontData() void ClearFontData()
{ {
for(int i=0; i<50; i++) for(int i=0; i <= MAX_FONT_SIZE; i++)
{ {
if(fontSystem[i]) if(fontSystem[i])
delete fontSystem[i]; delete fontSystem[i];
@ -100,6 +100,12 @@ FreeTypeGX::FreeTypeGX(FT_UInt pixelSize, uint8_t vertexIndex)
this->setCompatibilityMode(FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE); this->setCompatibilityMode(FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE);
this->ftPointSize = pixelSize; this->ftPointSize = pixelSize;
this->ftKerningEnabled = FT_HAS_KERNING(ftFace); this->ftKerningEnabled = FT_HAS_KERNING(ftFace);
if (ftFace->size) {
this->ftMaxAdvanceX = ftFace->size->metrics.max_advance >> 6;
}
else {
this->ftMaxAdvanceX = ftFace->max_advance_width >> 6;
}
} }
/** /**
@ -391,17 +397,17 @@ int16_t FreeTypeGX::getStyleOffsetHeight(ftgxDataOffset *offset, uint16_t format
* @param textStyle Flags which specify any styling which should be applied to the rendered string. * @param textStyle Flags which specify any styling which should be applied to the rendered string.
* @return The number of characters printed. * @return The number of characters printed.
*/ */
uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color, uint16_t textStyle) uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color, uint16_t textStyle, int monoPercent)
{ {
uint16_t x_pos = x, printed = 0; int16_t x_pos = x, printed = 0;
uint16_t x_offset = 0, y_offset = 0; int16_t x_offset = 0, y_offset = 0;
GXTexObj glyphTexture; GXTexObj glyphTexture;
FT_Vector pairDelta; FT_Vector pairDelta;
ftgxDataOffset offset; ftgxDataOffset offset;
if(textStyle & FTGX_JUSTIFY_MASK) if(textStyle & FTGX_JUSTIFY_MASK)
{ {
x_offset = this->getStyleOffsetWidth(this->getWidth(text), textStyle); x_offset = this->getStyleOffsetWidth(this->getWidth(text, textStyle, monoPercent), textStyle);
} }
if(textStyle & FTGX_ALIGN_MASK) if(textStyle & FTGX_ALIGN_MASK)
{ {
@ -410,6 +416,11 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color
} }
int i = 0; int i = 0;
int x_diff = 0;
int monoAdvanceX = 0;
if (textStyle & FTGX_MONOSPACE_FAKE) {
monoAdvanceX = (int)this->ftMaxAdvanceX * monoPercent / 100;
}
while (text[i]) while (text[i])
{ {
ftgxCharData* glyphData = NULL; ftgxCharData* glyphData = NULL;
@ -424,16 +435,27 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color
if (glyphData != NULL) if (glyphData != NULL)
{ {
if (this->ftKerningEnabled && i) if (textStyle & FTGX_MONOSPACE_FAKE) {
{ x_diff = (monoAdvanceX - (int)glyphData->glyphAdvanceX) / 2;
FT_Get_Kerning(ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); x_pos += x_diff;
x_pos += pairDelta.x >> 6; }
else {
if (this->ftKerningEnabled && i)
{
FT_Get_Kerning(ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);
x_pos += pairDelta.x >> 6;
}
} }
GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE); GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
this->copyTextureToFramebuffer(&glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos + glyphData->renderOffsetX + x_offset, y - glyphData->renderOffsetY + y_offset, color); this->copyTextureToFramebuffer(&glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos + glyphData->renderOffsetX + x_offset, y - glyphData->renderOffsetY + y_offset, color);
x_pos += glyphData->glyphAdvanceX; if (textStyle & FTGX_MONOSPACE_FAKE) {
x_pos += monoAdvanceX - x_diff;
}
else {
x_pos += glyphData->glyphAdvanceX;
}
++printed; ++printed;
} }
++i; ++i;
@ -442,7 +464,7 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color
if(textStyle & FTGX_STYLE_MASK) if(textStyle & FTGX_STYLE_MASK)
{ {
this->getOffset(text, &offset); this->getOffset(text, &offset);
this->drawTextFeature(x + x_offset, y + y_offset, this->getWidth(text), &offset, textStyle, color); this->drawTextFeature(x + x_offset, y + y_offset, this->getWidth(text, textStyle, monoPercent), &offset, textStyle, color);
} }
return printed; return printed;
@ -451,9 +473,9 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color
/** /**
* \overload * \overload
*/ */
uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color, uint16_t textStyle) uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color, uint16_t textStyle, int monoPercent)
{ {
return this->drawText(x, y, (wchar_t *)text, color, textStyle); return this->drawText(x, y, (wchar_t *)text, color, textStyle, monoPercent);
} }
void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset *offsetData, uint16_t format, GXColor color) void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset *offsetData, uint16_t format, GXColor color)
@ -476,12 +498,16 @@ void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataO
* @param text NULL terminated string to calculate. * @param text NULL terminated string to calculate.
* @return The width of the text string in pixels. * @return The width of the text string in pixels.
*/ */
uint16_t FreeTypeGX::getWidth(wchar_t *text) uint16_t FreeTypeGX::getWidth(wchar_t *text, uint16_t textStyle, int monoPercent)
{ {
uint16_t strWidth = 0; uint16_t strWidth = 0;
FT_Vector pairDelta; FT_Vector pairDelta;
int i = 0; int i = 0;
int monoAdvanceX = 0;
if (textStyle & FTGX_MONOSPACE_FAKE) {
monoAdvanceX = (int)this->ftMaxAdvanceX * monoPercent / 100;
}
while (text[i]) while (text[i])
{ {
ftgxCharData* glyphData = NULL; ftgxCharData* glyphData = NULL;
@ -496,13 +522,18 @@ uint16_t FreeTypeGX::getWidth(wchar_t *text)
if (glyphData != NULL) if (glyphData != NULL)
{ {
if (this->ftKerningEnabled && (i > 0)) if (textStyle & FTGX_MONOSPACE_FAKE) {
{ strWidth += monoAdvanceX;
FT_Get_Kerning(ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);
strWidth += pairDelta.x >> 6;
} }
else {
if (this->ftKerningEnabled && (i > 0))
{
FT_Get_Kerning(ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);
strWidth += pairDelta.x >> 6;
}
strWidth += glyphData->glyphAdvanceX; strWidth += glyphData->glyphAdvanceX;
}
} }
++i; ++i;
} }
@ -513,9 +544,9 @@ uint16_t FreeTypeGX::getWidth(wchar_t *text)
* *
* \overload * \overload
*/ */
uint16_t FreeTypeGX::getWidth(wchar_t const *text) uint16_t FreeTypeGX::getWidth(wchar_t const *text, uint16_t textStyle, int monoPercent)
{ {
return this->getWidth((wchar_t *)text); return this->getWidth((wchar_t *)text, textStyle, monoPercent);
} }
/** /**

View File

@ -87,7 +87,10 @@ typedef struct ftgxDataOffset_ ftgxDataOffset;
#define FTGX_STYLE_UNDERLINE 0x1000 #define FTGX_STYLE_UNDERLINE 0x1000
#define FTGX_STYLE_STRIKE 0x2000 #define FTGX_STYLE_STRIKE 0x2000
#define FTGX_STYLE_MASK 0xf000 #define FTGX_STYLE_MASK 0x7000
#define FTGX_MONOSPACE_FAKE 0x8000
#define FTGX_MONOSPACE_MASK 0x8000
#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE 0X0001 #define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE 0X0001
#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL 0X0002 #define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL 0X0002
@ -126,6 +129,7 @@ class FreeTypeGX {
private: private:
FT_UInt ftPointSize; /**< Requested size of the rendered font. */ FT_UInt ftPointSize; /**< Requested size of the rendered font. */
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */ bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
uint16_t ftMaxAdvanceX;
uint8_t vertexIndex; /**< Vertex format descriptor index. */ uint8_t vertexIndex; /**< Vertex format descriptor index. */
uint32_t compatibilityMode; /**< Compatibility mode for default tev operations and vertex descriptors. */ uint32_t compatibilityMode; /**< Compatibility mode for default tev operations and vertex descriptors. */
std::map<wchar_t, ftgxCharData> fontData; /**< Map which holds the glyph data structures for the corresponding characters. */ std::map<wchar_t, ftgxCharData> fontData; /**< Map which holds the glyph data structures for the corresponding characters. */
@ -154,11 +158,11 @@ class FreeTypeGX {
void setVertexFormat(uint8_t vertexIndex); void setVertexFormat(uint8_t vertexIndex);
void setCompatibilityMode(uint32_t compatibilityMode); void setCompatibilityMode(uint32_t compatibilityMode);
uint16_t drawText(int16_t x, int16_t y, wchar_t *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL); uint16_t drawText(int16_t x, int16_t y, wchar_t *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL, int monospacePercentage = 100);
uint16_t drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL); uint16_t drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL, int monospacePercentage = 100);
uint16_t getWidth(wchar_t *text); uint16_t getWidth(wchar_t *text, uint16_t textStyling = FTGX_NULL, int monospacePercentage = 100);
uint16_t getWidth(wchar_t const *text); uint16_t getWidth(wchar_t const *text, uint16_t textStyling = FTGX_NULL, int monospacePercentage = 100);
uint16_t getHeight(wchar_t *text); uint16_t getHeight(wchar_t *text);
uint16_t getHeight(wchar_t const *text); uint16_t getHeight(wchar_t const *text);
void getOffset(wchar_t *text, ftgxDataOffset* offset); void getOffset(wchar_t *text, ftgxDataOffset* offset);

View File

@ -689,6 +689,7 @@ class GuiText : public GuiElement
//!Sets the FreeTypeGX style attributes //!Sets the FreeTypeGX style attributes
//!\param s Style attributes //!\param s Style attributes
void SetStyle(u16 s); void SetStyle(u16 s);
void SetPseudoMonospace(int monoPercentage);
//!Sets the text alignment //!Sets the text alignment
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE) //!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) //!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
@ -711,6 +712,7 @@ class GuiText : public GuiElement
int textScrollDelay; //!< Scrolling speed int textScrollDelay; //!< Scrolling speed
u16 style; //!< FreeTypeGX style attributes u16 style; //!< FreeTypeGX style attributes
bool wrap; //!< Wrapping toggle bool wrap; //!< Wrapping toggle
int monoPercentage;
}; };
//!Display, manage, and manipulate tooltips in the GUI //!Display, manage, and manipulate tooltips in the GUI

View File

@ -22,7 +22,6 @@ static u16 presetStyle = 0;
#define TEXT_SCROLL_DELAY 8 #define TEXT_SCROLL_DELAY 8
#define TEXT_SCROLL_INITIAL_DELAY 6 #define TEXT_SCROLL_INITIAL_DELAY 6
static const char *gettext(const char *msg) static const char *gettext(const char *msg)
{ {
return msg; return msg;
@ -73,6 +72,7 @@ GuiText::GuiText(const char * t)
style = presetStyle; style = presetStyle;
maxWidth = presetMaxWidth; maxWidth = presetMaxWidth;
wrap = false; wrap = false;
monoPercentage = 100;
textDynNum = 0; textDynNum = 0;
textScroll = SCROLL_NONE; textScroll = SCROLL_NONE;
textScrollPos = 0; textScrollPos = 0;
@ -214,7 +214,7 @@ int GuiText::GetTextWidth()
currentSize = size; currentSize = size;
} }
return fontSystem[size]->getWidth(text); return fontSystem[size]->getWidth(text, style, monoPercentage);
} }
void GuiText::SetWrap(bool w, int width) void GuiText::SetWrap(bool w, int width)
@ -267,6 +267,12 @@ void GuiText::SetStyle(u16 s)
style = s; style = s;
} }
void GuiText::SetPseudoMonospace(int monoPercentage)
{
style |= FTGX_MONOSPACE_FAKE;
this->monoPercentage = monoPercentage;
}
void GuiText::SetAlignment(int hor, int vert) void GuiText::SetAlignment(int hor, int vert)
{ {
style = 0; style = 0;
@ -351,7 +357,7 @@ void GuiText::Draw()
if(maxWidth == 0) if(maxWidth == 0)
{ {
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style); fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style, monoPercentage);
this->UpdateEffects(); this->UpdateEffects();
return; return;
} }
@ -377,7 +383,7 @@ void GuiText::Draw()
if(text[ch] == ' ' || ch == textlen-1) if(text[ch] == ' ' || ch == textlen-1)
{ {
if(fontSystem[currentSize]->getWidth(textDyn[linenum]) > maxWidth) if(fontSystem[currentSize]->getWidth(textDyn[linenum], style, monoPercentage) > maxWidth)
{ {
if(lastSpace >= 0) if(lastSpace >= 0)
{ {
@ -415,7 +421,7 @@ void GuiText::Draw()
int top = this->GetTop() + voffset; int top = this->GetTop() + voffset;
for(int i=0; i < textDynNum; ++i) for(int i=0; i < textDynNum; ++i)
fontSystem[currentSize]->drawText(left, top+i*lineheight, textDyn[i], c, style); fontSystem[currentSize]->drawText(left, top+i*lineheight, textDyn[i], c, style, monoPercentage);
} }
else else
{ {
@ -425,13 +431,13 @@ void GuiText::Draw()
textDyn[0] = wcsdup(text); textDyn[0] = wcsdup(text);
int len = wcslen(textDyn[0]); int len = wcslen(textDyn[0]);
while(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) while(fontSystem[currentSize]->getWidth(textDyn[0], style, monoPercentage) > maxWidth)
textDyn[0][--len] = 0; textDyn[0][--len] = 0;
} }
if(textScroll == SCROLL_HORIZONTAL) if(textScroll == SCROLL_HORIZONTAL)
{ {
if(fontSystem[currentSize]->getWidth(text) > maxWidth && (FrameTimer % textScrollDelay == 0)) if(fontSystem[currentSize]->getWidth(text, style, monoPercentage) > maxWidth && (FrameTimer % textScrollDelay == 0))
{ {
if(textScrollInitialDelay) if(textScrollInitialDelay)
{ {
@ -457,22 +463,22 @@ void GuiText::Draw()
dynlen += 2; dynlen += 2;
} }
if(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) if(fontSystem[currentSize]->getWidth(textDyn[0], style, monoPercentage) > maxWidth)
{ {
while(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) while(fontSystem[currentSize]->getWidth(textDyn[0], style, monoPercentage) > maxWidth)
textDyn[0][--dynlen] = 0; textDyn[0][--dynlen] = 0;
} }
else else
{ {
int i = 0; int i = 0;
while(fontSystem[currentSize]->getWidth(textDyn[0]) < maxWidth && dynlen+1 < textlen) while(fontSystem[currentSize]->getWidth(textDyn[0], style, monoPercentage) < maxWidth && dynlen+1 < textlen)
{ {
textDyn[0][dynlen] = text[i++]; textDyn[0][dynlen] = text[i++];
textDyn[0][++dynlen] = 0; textDyn[0][++dynlen] = 0;
} }
if(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) if(fontSystem[currentSize]->getWidth(textDyn[0], style, monoPercentage) > maxWidth)
textDyn[0][dynlen-2] = 0; textDyn[0][dynlen-2] = 0;
else else
textDyn[0][dynlen-1] = 0; textDyn[0][dynlen-1] = 0;
@ -480,7 +486,7 @@ void GuiText::Draw()
} }
} }
} }
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn[0], c, style); fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn[0], c, style, monoPercentage);
} }
this->UpdateEffects(); this->UpdateEffects();
} }

View File

@ -395,10 +395,12 @@ void HomeMenu ()
GuiText cycleText(NULL, 20, (GXColor){255, 255, 255, 255}); GuiText cycleText(NULL, 20, (GXColor){255, 255, 255, 255});
cycleText.SetPosition(-215, -180); cycleText.SetPosition(-215, -180);
cycleText.SetPseudoMonospace(70);
updateCyclesText(&cycleText); updateCyclesText(&cycleText);
GuiText fskipText(NULL, 20, (GXColor){255, 255, 255, 255}); GuiText fskipText(NULL, 20, (GXColor){255, 255, 255, 255});
fskipText.SetPosition(-45, -180); fskipText.SetPosition(-45, -180);
fskipText.SetPseudoMonospace(70);
updateFskipText(&fskipText); updateFskipText(&fskipText);
GuiText cycleDecBtnTxt("-", 24, (GXColor){0, 0, 0, 255}); GuiText cycleDecBtnTxt("-", 24, (GXColor){0, 0, 0, 255});