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):
@[ -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:

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);
ftSlot = ftFace->glyph;
for(int i=0; i<50; i++)
for(int i=0; i <= MAX_FONT_SIZE; i++)
fontSystem[i] = NULL;
}
@ -52,7 +52,7 @@ void ChangeFontSize(FT_UInt pixelSize)
void ClearFontData()
{
for(int i=0; i<50; i++)
for(int i=0; i <= MAX_FONT_SIZE; i++)
{
if(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->ftPointSize = pixelSize;
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.
* @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;
uint16_t x_offset = 0, y_offset = 0;
int16_t x_pos = x, printed = 0;
int16_t x_offset = 0, y_offset = 0;
GXTexObj glyphTexture;
FT_Vector pairDelta;
ftgxDataOffset offset;
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)
{
@ -410,6 +416,11 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color
}
int i = 0;
int x_diff = 0;
int monoAdvanceX = 0;
if (textStyle & FTGX_MONOSPACE_FAKE) {
monoAdvanceX = (int)this->ftMaxAdvanceX * monoPercent / 100;
}
while (text[i])
{
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 (this->ftKerningEnabled && i)
{
FT_Get_Kerning(ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);
x_pos += pairDelta.x >> 6;
if (textStyle & FTGX_MONOSPACE_FAKE) {
x_diff = (monoAdvanceX - (int)glyphData->glyphAdvanceX) / 2;
x_pos += x_diff;
}
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);
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;
}
++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)
{
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;
@ -451,9 +473,9 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color
/**
* \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)
@ -476,12 +498,16 @@ void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataO
* @param text NULL terminated string to calculate.
* @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;
FT_Vector pairDelta;
int i = 0;
int monoAdvanceX = 0;
if (textStyle & FTGX_MONOSPACE_FAKE) {
monoAdvanceX = (int)this->ftMaxAdvanceX * monoPercent / 100;
}
while (text[i])
{
ftgxCharData* glyphData = NULL;
@ -496,13 +522,18 @@ uint16_t FreeTypeGX::getWidth(wchar_t *text)
if (glyphData != NULL)
{
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;
if (textStyle & FTGX_MONOSPACE_FAKE) {
strWidth += monoAdvanceX;
}
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;
}
@ -513,9 +544,9 @@ uint16_t FreeTypeGX::getWidth(wchar_t *text)
*
* \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_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_DECAL 0X0002
@ -126,6 +129,7 @@ class FreeTypeGX {
private:
FT_UInt ftPointSize; /**< Requested size of the rendered font. */
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
uint16_t ftMaxAdvanceX;
uint8_t vertexIndex; /**< Vertex format descriptor index. */
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. */
@ -154,11 +158,11 @@ class FreeTypeGX {
void setVertexFormat(uint8_t vertexIndex);
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 const *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, int monospacePercentage = 100);
uint16_t getWidth(wchar_t *text);
uint16_t getWidth(wchar_t const *text);
uint16_t getWidth(wchar_t *text, uint16_t textStyling = FTGX_NULL, int monospacePercentage = 100);
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 const *text);
void getOffset(wchar_t *text, ftgxDataOffset* offset);

View File

@ -689,6 +689,7 @@ class GuiText : public GuiElement
//!Sets the FreeTypeGX style attributes
//!\param s Style attributes
void SetStyle(u16 s);
void SetPseudoMonospace(int monoPercentage);
//!Sets the text alignment
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
@ -711,6 +712,7 @@ class GuiText : public GuiElement
int textScrollDelay; //!< Scrolling speed
u16 style; //!< FreeTypeGX style attributes
bool wrap; //!< Wrapping toggle
int monoPercentage;
};
//!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_INITIAL_DELAY 6
static const char *gettext(const char *msg)
{
return msg;
@ -73,6 +72,7 @@ GuiText::GuiText(const char * t)
style = presetStyle;
maxWidth = presetMaxWidth;
wrap = false;
monoPercentage = 100;
textDynNum = 0;
textScroll = SCROLL_NONE;
textScrollPos = 0;
@ -214,7 +214,7 @@ int GuiText::GetTextWidth()
currentSize = size;
}
return fontSystem[size]->getWidth(text);
return fontSystem[size]->getWidth(text, style, monoPercentage);
}
void GuiText::SetWrap(bool w, int width)
@ -267,6 +267,12 @@ void GuiText::SetStyle(u16 s)
style = s;
}
void GuiText::SetPseudoMonospace(int monoPercentage)
{
style |= FTGX_MONOSPACE_FAKE;
this->monoPercentage = monoPercentage;
}
void GuiText::SetAlignment(int hor, int vert)
{
style = 0;
@ -351,7 +357,7 @@ void GuiText::Draw()
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();
return;
}
@ -377,7 +383,7 @@ void GuiText::Draw()
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)
{
@ -415,7 +421,7 @@ void GuiText::Draw()
int top = this->GetTop() + voffset;
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
{
@ -425,13 +431,13 @@ void GuiText::Draw()
textDyn[0] = wcsdup(text);
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;
}
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)
{
@ -457,22 +463,22 @@ void GuiText::Draw()
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;
}
else
{
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] = 0;
}
if(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth)
if(fontSystem[currentSize]->getWidth(textDyn[0], style, monoPercentage) > maxWidth)
textDyn[0][dynlen-2] = 0;
else
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();
}

View File

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