From 516baef59f2ce047a492b34b96a022aeeed0b998 Mon Sep 17 00:00:00 2001 From: "ardi@ist-einmalig.de" Date: Tue, 26 May 2009 21:54:30 +0000 Subject: [PATCH] * some bugfixes in FreeTypeGX (no springing text by scrolling) * add 4 FTGX_ALIGN_... Modes * scrolling now pixel by pixel (softscrolling) --- source/FreeTypeGX.cpp | 132 +++++++++++++++++------- source/FreeTypeGX.h | 63 +++++------ source/libwiigui/gui.h | 23 +++-- source/libwiigui/gui_gamebrowser.cpp | 8 +- source/libwiigui/gui_text.cpp | 108 ++++++++++++------- source/menu.cpp | 149 +++++++++++++-------------- 6 files changed, 280 insertions(+), 203 deletions(-) diff --git a/source/FreeTypeGX.cpp b/source/FreeTypeGX.cpp index 1ad81855..dc8670b4 100644 --- a/source/FreeTypeGX.cpp +++ b/source/FreeTypeGX.cpp @@ -26,6 +26,37 @@ #include "main.h" #include "cfg.h" +/*! \struct ftgxCharData_ + * + * Font face character glyph relevant data structure. + */ +typedef struct ftgxCharData_ { + int16_t renderOffsetX; /**< Texture X axis bearing offset. */ + uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */ + uint16_t glyphIndex; /**< Charachter glyph index in the font face. */ + + uint16_t textureWidth; /**< Texture width in pixels/bytes. */ + uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */ + + int16_t renderOffsetY; /**< Texture Y axis bearing offset. */ + int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */ + int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */ + + uint32_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */ +} ftgxCharData; + +/*! \struct ftgxDataOffset_ + * + * Offset structure which hold both a maximum and minimum value. + */ +typedef struct ftgxDataOffset_ { + int16_t ascender; /**< Maximum data offset. */ + int16_t descender; /**< Minimum data offset. */ + int16_t max; /**< Maximum data offset. */ + int16_t min; /**< Minimum data offset. */ +} ftgxDataOffset; + + /** * Default constructor for the FreeTypeGX class. * @@ -406,16 +437,16 @@ void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) { * @param width Current pixel width of the string. * @param format Positional format of the string. */ -uint16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format) { +int16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format) { if (format & FTGX_JUSTIFY_LEFT ) { return 0; } else if (format & FTGX_JUSTIFY_CENTER ) { - return width >> 1; + return -(width >> 1); } else if (format & FTGX_JUSTIFY_RIGHT ) { - return width; + return -width; } return 0; @@ -429,15 +460,31 @@ uint16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format) { * @param offset Current pixel offset data of the string. * @param format Positional format of the string. */ -uint16_t FreeTypeGX::getStyleOffsetHeight(ftgxDataOffset offset, uint16_t format) { - if (format & FTGX_ALIGN_TOP ) { - return -offset.max; - } - else if (format & FTGX_ALIGN_MIDDLE ) { - return -offset.max; - } - else if (format & FTGX_ALIGN_BOTTOM ) { - return offset.min; +int16_t FreeTypeGX::getStyleOffsetHeight(ftgxDataOffset *offset, uint16_t format) +{ + switch(format & FTGX_ALIGN_MASK) + { + case FTGX_ALIGN_TOP: + return offset->ascender; + + default: + case FTGX_ALIGN_MIDDLE: + return (offset->ascender + offset->descender + 1) >> 1; + + case FTGX_ALIGN_BOTTOM: + return offset->descender; + + case FTGX_ALIGN_BASELINE: + return 0; + + case FTGX_ALIGN_GLYPH_TOP: + return offset->max; + + case FTGX_ALIGN_GLYPH_MIDDLE: + return (offset->max + offset->min + 1) >> 1; + + case FTGX_ALIGN_GLYPH_BOTTOM: + return offset->min; } return 0; @@ -462,12 +509,13 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color uint16_t x_offset = 0, y_offset = 0; GXTexObj glyphTexture; FT_Vector pairDelta; + ftgxDataOffset offset; - if(textStyle & 0x000F) { + if(textStyle & FTGX_JUSTIFY_MASK) { x_offset = this->getStyleOffsetWidth(this->getWidth(text), textStyle); } - if(textStyle & 0x00F0) { - y_offset = this->getStyleOffsetHeight(this->getOffset(text), textStyle); + if(textStyle & FTGX_ALIGN_MASK) { + y_offset = this->getStyleOffsetHeight(this->getOffset(text, &offset), textStyle); } for (uint16_t i = 0; i < strLength; i++) { @@ -488,15 +536,15 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color } GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, this->textureFormat, 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; printed++; } } - if(textStyle & 0x0F00) { - this->drawTextFeature(x - x_offset, y, this->getWidth(text), this->getOffset(text), textStyle, color); + if(textStyle & FTGX_STYLE_MASK) { + this->drawTextFeature(x + x_offset, y + y_offset, this->getWidth(text), this->getOffset(text, &offset), textStyle, color); } return printed; @@ -509,20 +557,22 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t const *text, GXColor return this->drawText(x, y, (wchar_t *)text, color, textStyle); } -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) { uint16_t featureHeight = this->ftPointSize >> 4 > 0 ? this->ftPointSize >> 4 : 1; if (format & FTGX_STYLE_UNDERLINE ) { - switch(format & 0x00F0) { + switch(format & FTGX_ALIGN_MASK) { +/* case FTGX_ALIGN_TOP: - this->copyFeatureToFramebuffer(width, featureHeight, x, y + offsetData.max + 1, color); + this->copyFeatureToFramebuffer(width, featureHeight, x, y + offsetData->max + 1, color); break; case FTGX_ALIGN_MIDDLE: - this->copyFeatureToFramebuffer(width, featureHeight, x, y + ((offsetData.max - offsetData.min) >> 1) + 1, color); + this->copyFeatureToFramebuffer(width, featureHeight, x, y + ((offsetData->max - offsetData->min + 1) >> 1), color); break; case FTGX_ALIGN_BOTTOM: - this->copyFeatureToFramebuffer(width, featureHeight, x, y - offsetData.min, color); + this->copyFeatureToFramebuffer(width, featureHeight, x, y - offsetData->min, color); break; +*/ default: this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color); break; @@ -530,18 +580,21 @@ void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataO } if (format & FTGX_STYLE_STRIKE ) { - switch(format & 0x00F0) { + switch(format & FTGX_ALIGN_MASK) { +/* case FTGX_ALIGN_TOP: - this->copyFeatureToFramebuffer(width, featureHeight, x, y + ((offsetData.max + offsetData.min) >> 1), color); + this->copyFeatureToFramebuffer(width, featureHeight, x, y + ((offsetData->max - offsetData->min + 1) >> 1), color); break; case FTGX_ALIGN_MIDDLE: this->copyFeatureToFramebuffer(width, featureHeight, x, y, color); break; case FTGX_ALIGN_BOTTOM: - this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData.max + offsetData.min) >> 1), color); + this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData->max + offsetData->min) >> 1), color); break; +*/ default: - this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData.max - offsetData.min) >> 1), color); +// this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData->max - offsetData->min) >> 1), color); + this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData->max) >> 1), color); break; } } @@ -602,9 +655,10 @@ uint16_t FreeTypeGX::getWidth(wchar_t const *text) { * @return The height of the text string in pixels. */ uint16_t FreeTypeGX::getHeight(wchar_t *text) { - ftgxDataOffset offset = this->getOffset(text); + ftgxDataOffset offset; + this->getOffset(text, &offset); - return offset.max + offset.min; + return offset.max - offset.min; } /** @@ -622,11 +676,12 @@ uint16_t FreeTypeGX::getHeight(wchar_t const *text) { * pixel height below the font origin line and returns the values in an addressible structure. * * @param text NULL terminated string to calculate. - * @return The max and min values above and below the font origin line. + * @param offset returns the max and min values above and below the font origin line + * */ -ftgxDataOffset FreeTypeGX::getOffset(wchar_t *text) { +ftgxDataOffset* FreeTypeGX::getOffset(wchar_t *text, ftgxDataOffset* offset) { uint16_t strLength = wcslen(text); - int16_t strMax = 0, strMin = 0; + int16_t strMax = 0, strMin = 9999; for (uint16_t i = 0; i < strLength; i++) { @@ -640,19 +695,22 @@ ftgxDataOffset FreeTypeGX::getOffset(wchar_t *text) { if(glyphData != NULL) { strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax; - strMin = glyphData->renderOffsetMin > strMin ? glyphData->renderOffsetMin : strMin; + strMin = glyphData->renderOffsetMin < strMin ? glyphData->renderOffsetMin : strMin; } } - - return (ftgxDataOffset){strMax, strMin}; + offset->ascender = this->ftFace->size->metrics.ascender>>6; + offset->descender = this->ftFace->size->metrics.descender>>6; + offset->max = strMax; + offset->min = strMin; + return offset; } /** * * \overload */ -ftgxDataOffset FreeTypeGX::getOffset(wchar_t const *text) { - return this->getOffset(text); +ftgxDataOffset* FreeTypeGX::getOffset(wchar_t const *text, ftgxDataOffset* offset) { + return this->getOffset(text, offset); } /** diff --git a/source/FreeTypeGX.h b/source/FreeTypeGX.h index fb6998e5..1b86bbd6 100644 --- a/source/FreeTypeGX.h +++ b/source/FreeTypeGX.h @@ -161,47 +161,32 @@ #include #include -/*! \struct ftgxCharData_ +/*! forward deklaration of private structures * - * Font face character glyph relevant data structure. */ -typedef struct ftgxCharData_ { - int16_t renderOffsetX; /**< Texture X axis bearing offset. */ - uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */ - uint16_t glyphIndex; /**< Charachter glyph index in the font face. */ - - uint16_t textureWidth; /**< Texture width in pixels/bytes. */ - uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */ - - int16_t renderOffsetY; /**< Texture Y axis bearing offset. */ - int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */ - int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */ - - uint32_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */ -} ftgxCharData; - -/*! \struct ftgxDataOffset_ - * - * Offset structure which hold both a maximum and minimum value. - */ -typedef struct ftgxDataOffset_ { - int16_t max; /**< Maximum data offset. */ - int16_t min; /**< Minimum data offset. */ -} ftgxDataOffset; +typedef struct ftgxCharData_ ftgxCharData; +typedef struct ftgxDataOffset_ ftgxDataOffset; #define _TEXT(t) L ## t /**< Unicode helper macro. */ -#define FTGX_NULL 0x0000 -#define FTGX_JUSTIFY_LEFT 0x0001 -#define FTGX_JUSTIFY_CENTER 0x0002 -#define FTGX_JUSTIFY_RIGHT 0x0004 +#define FTGX_NULL 0x0000 +#define FTGX_JUSTIFY_LEFT 0x0001 +#define FTGX_JUSTIFY_CENTER 0x0002 +#define FTGX_JUSTIFY_RIGHT 0x0003 +#define FTGX_JUSTIFY_MASK 0x000f -#define FTGX_ALIGN_TOP 0x0010 -#define FTGX_ALIGN_MIDDLE 0x0020 -#define FTGX_ALIGN_BOTTOM 0x0040 +#define FTGX_ALIGN_TOP 0x0010 +#define FTGX_ALIGN_MIDDLE 0x0020 +#define FTGX_ALIGN_BOTTOM 0x0030 +#define FTGX_ALIGN_BASELINE 0x0040 +#define FTGX_ALIGN_GLYPH_TOP 0x0050 +#define FTGX_ALIGN_GLYPH_MIDDLE 0x0060 +#define FTGX_ALIGN_GLYPH_BOTTOM 0x0070 +#define FTGX_ALIGN_MASK 0x00f0 -#define FTGX_STYLE_UNDERLINE 0x0100 -#define FTGX_STYLE_STRIKE 0x0200 +#define FTGX_STYLE_UNDERLINE 0x0100 +#define FTGX_STYLE_STRIKE 0x0200 +#define FTGX_STYLE_MASK 0x0f00 #define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE 0X0001 #define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL 0X0002 @@ -246,8 +231,8 @@ class FreeTypeGX { static uint16_t adjustTextureWidth(uint16_t textureWidth, uint8_t textureFormat); static uint16_t adjustTextureHeight(uint16_t textureHeight, uint8_t textureFormat); - static uint16_t getStyleOffsetWidth(uint16_t width, uint16_t format); - static uint16_t getStyleOffsetHeight(ftgxDataOffset offset, uint16_t format); + static int16_t getStyleOffsetWidth(uint16_t width, uint16_t format); + static int16_t getStyleOffsetHeight(ftgxDataOffset *offset, uint16_t format); void unloadFont(); ftgxCharData *cacheGlyphData(wchar_t charCode); @@ -256,7 +241,7 @@ class FreeTypeGX { void setDefaultMode(); - void drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset offsetData, uint16_t format, GXColor color); + void drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset *offsetData, uint16_t format, GXColor color); void copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, GXColor color); void copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color); @@ -280,8 +265,8 @@ class FreeTypeGX { uint16_t getWidth(wchar_t const *text); uint16_t getHeight(wchar_t *text); uint16_t getHeight(wchar_t const *text); - ftgxDataOffset getOffset(wchar_t *text); - ftgxDataOffset getOffset(wchar_t const *text); + ftgxDataOffset* getOffset(wchar_t *text, ftgxDataOffset* offset); + ftgxDataOffset* getOffset(wchar_t const *text, ftgxDataOffset* offset); }; #endif /* FREETYPEGX_H_ */ diff --git a/source/libwiigui/gui.h b/source/libwiigui/gui.h index c7a54a59..89e29112 100644 --- a/source/libwiigui/gui.h +++ b/source/libwiigui/gui.h @@ -64,7 +64,7 @@ enum ALIGN_BOTTOM, ALIGN_MIDDLE }; - +#define ALIGN_CENTER ALIGN_CENTRE enum { STATE_DEFAULT, @@ -631,23 +631,32 @@ class GuiText : public GuiElement //!\param sz Font size //!\param c Font color //!\param w Maximum width of texture image (for text wrapping) - //!\param s Font size + //!\param wrap Wrapmode when w>0 + //!\param s Font style //!\param h Text alignment (horizontal) //!\param v Text alignment (vertical) - void SetPresets(int sz, GXColor c, int w, u16 s, int h, int v); + static void SetPresets(int sz, GXColor c, int w, int wrap, u16 s, int h, int v); //!Sets the font size //!\param s Font size void SetFontSize(int s); //!Sets the maximum width of the drawn texture image //!If the text exceeds this, it is wrapped to the next line //!\param w Maximum width + //!\param m WrapMode + enum { + WRAP, + DOTTED, + SCROLL, + MARQUEE + }; void SetMaxWidth(int w, short m=GuiText::WRAP); //!Sets the font color //!\param c Font color void SetColor(GXColor c); //!Sets the FreeTypeGX style attributes //!\param s Style attributes - void SetStyle(u16 s); + //!\param m Style-Mask attributes + void SetStyle(u16 s, u16 m=0xffff); //!Sets the text alignment //!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE) //!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) @@ -661,11 +670,6 @@ class GuiText : public GuiElement void SetWidescreen(bool w); //!Constantly called to draw the text void Draw(); - enum { - WRAP, - DOTTED, - SCROLL - }; protected: wchar_t* text; //!< Unicode text value int size; //!< Font size @@ -673,6 +677,7 @@ class GuiText : public GuiElement short wrapMode; short scrollPos1; short scrollPos2; + short scrollOffset; u32 scrollDelay; u16 style; //!< FreeTypeGX style attributes GXColor color; //!< Font color diff --git a/source/libwiigui/gui_gamebrowser.cpp b/source/libwiigui/gui_gamebrowser.cpp index e64487f2..f5f03f21 100644 --- a/source/libwiigui/gui_gamebrowser.cpp +++ b/source/libwiigui/gui_gamebrowser.cpp @@ -300,10 +300,10 @@ void GuiGameBrowser::Draw() } if(scrollbaron == 1) { - scrollbarImg->Draw(); - arrowUpBtn->Draw(); - arrowDownBtn->Draw(); - scrollbarBoxBtn->Draw(); + scrollbarImg->Draw(); + arrowUpBtn->Draw(); + arrowDownBtn->Draw(); + scrollbarBoxBtn->Draw(); } this->UpdateEffects(); } diff --git a/source/libwiigui/gui_text.cpp b/source/libwiigui/gui_text.cpp index d31c12d4..ce29e1fa 100644 --- a/source/libwiigui/gui_text.cpp +++ b/source/libwiigui/gui_text.cpp @@ -13,12 +13,12 @@ static int currentSize = 0; static int currentWidescreen = 0; static int presetSize = 0; +static GXColor presetColor = (GXColor){255, 255, 255, 255}; static int presetMaxWidth = 0; -static int presetWrapMode = GuiText::WRAP; +static int presetWrapMode = 0; +static u16 presetStyle = 0; static int presetAlignmentHor = 0; static int presetAlignmentVert = 0; -static u16 presetStyle = 0; -static GXColor presetColor = (GXColor){255, 255, 255, 255}; /** * Constructor for the GuiText class. @@ -35,14 +35,14 @@ GuiText::GuiText(const char * t, int s, GXColor c) scrollPos1 = 0; scrollPos2 = 0; scrollDelay = 0; - font = NULL; + font = fontSystem; widescreen = 0; //added alignmentHor = ALIGN_CENTRE; alignmentVert = ALIGN_MIDDLE; if(t) - text = fontSystem->charToWideChar((char *)t); + text = FreeTypeGX::charToWideChar((char *)t); } /** @@ -60,14 +60,14 @@ GuiText::GuiText(const char * t) scrollPos1 = 0; scrollPos2 = 0; scrollDelay = 0; - font = NULL; + font = fontSystem; widescreen = 0; //added alignmentHor = presetAlignmentHor; alignmentVert = presetAlignmentVert; if(t) - text = fontSystem->charToWideChar((char *)t); + text = FreeTypeGX::charToWideChar((char *)t); } /** @@ -90,17 +90,18 @@ void GuiText::SetText(const char * t) text = NULL; if(t) - text = fontSystem->charToWideChar((char *)t); + text = FreeTypeGX::charToWideChar((char *)t); scrollPos2 = 0; scrollDelay = 0; } -void GuiText::SetPresets(int sz, GXColor c, int w, u16 s, int h, int v) +void GuiText::SetPresets(int sz, GXColor c, int w, int wrap, u16 s, int h, int v) { presetSize = sz; presetColor = c; - presetStyle = s; presetMaxWidth = w; + presetWrapMode = wrap; + presetStyle = s; presetAlignmentHor = h; presetAlignmentVert = v; } @@ -125,16 +126,17 @@ void GuiText::SetColor(GXColor c) alpha = c.a; } -void GuiText::SetStyle(u16 s) +void GuiText::SetStyle(u16 s, u16 m/*=0xffff*/) { LOCK(this); - style = s; + style &= ~m; + style |= s & m; } void GuiText::SetAlignment(int hor, int vert) { LOCK(this); - style = 0; + style = FTGX_NULL; switch(hor) { @@ -170,7 +172,7 @@ void GuiText::SetAlignment(int hor, int vert) void GuiText::SetFont(FreeTypeGX *f) { LOCK(this); - font = f; + font = f ? f : fontSystem; } int GuiText::GetTextWidth() @@ -180,12 +182,11 @@ int GuiText::GetTextWidth() if(newSize != currentSize || currentWidescreen != widescreen) { - //fontSystem->changeSize(newSize); - (font ? font : fontSystem)->changeSize(newSize, widescreen ? newSize*0.8 : 0); + font->changeSize(newSize, widescreen ? newSize*0.8 : 0); currentSize = newSize; currentWidescreen = widescreen; } - return (font ? font : fontSystem)->getWidth(text); + return font->getWidth(text); } void GuiText::SetWidescreen(bool w) @@ -212,18 +213,17 @@ void GuiText::Draw() if(newSize != currentSize || currentWidescreen != widescreen) { - //fontSystem->changeSize(newSize); - (font ? font : fontSystem)->changeSize(newSize, widescreen ? newSize*0.8 : 0); + font->changeSize(newSize, widescreen ? newSize*0.8 : 0); currentSize = newSize; currentWidescreen = widescreen; } int voffset = 0; - if(alignmentVert == ALIGN_MIDDLE) - voffset = -newSize/2 + 2; +// if(alignmentVert == ALIGN_MIDDLE) +// voffset = -newSize/2 + 2; - if(maxWidth > 0 && (font ? font : fontSystem)->getWidth(text) > maxWidth) + if(maxWidth > 0 && font->getWidth(text) > maxWidth) { if(wrapMode == GuiText::WRAP) // text wrapping { @@ -246,8 +246,7 @@ void GuiText::Draw() if(text[ch] == ' ' || ch == strlen-1) { - if((font ? font : fontSystem)->getWidth(tmptext[linenum]) >= maxWidth) - //if(fontSystem->getWidth(tmptext[linenum]) >= maxWidth) + if(font->getWidth(tmptext[linenum]) >= maxWidth) { if(lastSpace >= 0) { @@ -278,7 +277,7 @@ void GuiText::Draw() for(i=0; i < linenum; i++) { - (font ? font : fontSystem)->drawText(this->GetLeft(), this->GetTop()+voffset+i*lineheight, tmptext[i], c, style); + font->drawText(this->GetLeft(), this->GetTop()+voffset+i*lineheight, tmptext[i], c, style); delete tmptext[i]; } } @@ -296,9 +295,9 @@ void GuiText::Draw() save[i] = text[dotPos+i]; text[dotPos+i] = (i != 3 ? _TEXT('.') : 0); } - if(((font ? font : fontSystem)->getWidth(text)) <= maxWidth) + if((font->getWidth(text)) <= maxWidth) { - (font ? font : fontSystem)->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style); + font->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style); drawed = true; } @@ -307,7 +306,7 @@ void GuiText::Draw() dotPos--; } if(!drawed) - (font ? font : fontSystem)->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style); + font->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style); } else if(wrapMode == GuiText::SCROLL) // text scroller { @@ -316,11 +315,12 @@ void GuiText::Draw() if(scrollPos2 == 0 || frameCount > scrollDelay+5) { scrollPos1 = 0; + scrollOffset = 0; for(scrollPos2 = wcslen(text); scrollPos2 > 1; scrollPos2--) { save = text[scrollPos2]; // save Pos2 text[scrollPos2] = 0; - int textWidth = (font ? font : fontSystem)->getWidth(text); + int textWidth = font->getWidth(text); text[scrollPos2] = save; // restore Pos2 if(textWidth <= maxWidth) break; @@ -329,15 +329,22 @@ void GuiText::Draw() } else if(scrollPos2 > 0 && frameCount >= scrollDelay) { - scrollPos1++; + + if(--scrollOffset < 0) + { + wchar_t tmp[] = { text[scrollPos1], text[scrollPos1+1], 0 }; + scrollOffset += font->getWidth(tmp) - font->getWidth(tmp+1); + scrollPos1++; + } + int strlen = wcslen(text); for(; scrollPos2 < strlen; scrollPos2++) { save = text[scrollPos2+1]; // save Pos2 text[scrollPos2+1] = 0; - int textWidth = (font ? font : fontSystem)->getWidth(&text[scrollPos1]); + int textWidth = font->getWidth(&text[scrollPos1]); text[scrollPos2+1] = save; // restore Pos2 - if(textWidth > maxWidth) + if(textWidth+scrollOffset > maxWidth) break; } if(scrollPos2 == strlen) @@ -346,20 +353,28 @@ void GuiText::Draw() scrollDelay = frameCount+25; // when dir-change wait 25 Frames } else - scrollDelay = frameCount+10; // wait 10 Frames + scrollDelay = frameCount+1; // wait 1 Frames } else if(frameCount >= scrollDelay) { scrollPos2 = -scrollPos2; + + scrollOffset++; + wchar_t tmp[] = { text[scrollPos1-1], text[scrollPos1], 0 }; + int tmpOffset = font->getWidth(tmp) - font->getWidth(tmp+1); + if(scrollOffset >= tmpOffset) + { + scrollOffset -= tmpOffset; + scrollPos1--; + } - scrollPos1--; for(; scrollPos2 > scrollPos1; scrollPos2--) { save = text[scrollPos2]; // save Pos2 text[scrollPos2] = 0; - int textWidth = (font ? font : fontSystem)->getWidth(&text[scrollPos1]); + int textWidth = font->getWidth(&text[scrollPos1]); text[scrollPos2] = save; // restore Pos2 - if(textWidth <= maxWidth) + if(textWidth+scrollOffset <= maxWidth) break; } if(scrollPos1 == 0) @@ -368,19 +383,34 @@ void GuiText::Draw() scrollDelay = frameCount+25; // when dir-change wait 25 Frames } else - scrollDelay = frameCount+10; // wait 10 Frames + scrollDelay = frameCount+1; // wait 10 Frames scrollPos2 = -scrollPos2; } + + uint16_t drawStyle = style; + uint16_t drawX = this->GetLeft() + scrollOffset; + + if((drawStyle & FTGX_JUSTIFY_MASK) == FTGX_JUSTIFY_CENTER) + { + drawStyle = (drawStyle & ~FTGX_JUSTIFY_MASK) | FTGX_JUSTIFY_LEFT; + drawX -= maxWidth >> 1; + } + else if((drawStyle & FTGX_JUSTIFY_MASK) == FTGX_JUSTIFY_RIGHT) + { + drawStyle = (drawStyle & ~FTGX_JUSTIFY_MASK) | FTGX_JUSTIFY_LEFT; + drawX -= maxWidth; + } + save = text[abs(scrollPos2)]; // save Pos2 text[abs(scrollPos2)] = 0; - (font ? font : fontSystem)->drawText(this->GetLeft(), this->GetTop()+voffset, &text[scrollPos1], c, style); + font->drawText(drawX, this->GetTop()+voffset, &text[scrollPos1], c, drawStyle); text[abs(scrollPos2)] = save; // restore Pos2 } } else { - (font ? font : fontSystem)->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style); + font->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style); } this->UpdateEffects(); } diff --git a/source/menu.cpp b/source/menu.cpp index 33b09dea..cdc5771f 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -43,7 +43,6 @@ #include "fatmounter.h" #define MAX_CHARACTERS 38 - extern FreeTypeGX *fontClock; //CLOCK static GuiImage * coverImg = NULL; @@ -84,7 +83,7 @@ static int datag = 0; int datagB =0; int dataed = -1; int cosa=0,sina=0,offa=0; -u8 dispFave=0; +u8 dispFave=0; //downloadvariables static char missingFiles[500][12]; //fixed @@ -227,7 +226,7 @@ static void WindowCredits(void * ptr) txt[i] = new GuiText(LANGUAGE.OfficialSite, 20, (GXColor){255, 255, 255, 255}); txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(-180,y); i++; y+=28; - txt[i]->SetPresets(22, (GXColor){255, 255, 255, 255}, 0, + GuiText::SetPresets(22, (GXColor){255, 255, 255, 255}, 0, GuiText::WRAP, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_TOP, ALIGN_LEFT, ALIGN_TOP); txt[i] = new GuiText("Coding:"); @@ -987,7 +986,7 @@ int GameWindowPrompt() f32 size = 0.0; char ID[4]; char IDFull[7]; - u8 faveChoice = 0; + u8 faveChoice = 0; u16 playCount = 0; GuiWindow promptWindow(472,320); @@ -999,10 +998,10 @@ int GameWindowPrompt() char imgPath[100]; snprintf(imgPath, sizeof(imgPath), "%sbutton_dialogue_box.png", CFG.theme_path); GuiImageData btnOutline(imgPath, button_dialogue_box_png); - - snprintf(imgPath, sizeof(imgPath), "%sfavorite.png", CFG.theme_path); - GuiImageData imgFavorite(imgPath, favorite_png); - snprintf(imgPath, sizeof(imgPath), "%snot_favorite.png", CFG.theme_path); + + snprintf(imgPath, sizeof(imgPath), "%sfavorite.png", CFG.theme_path); + GuiImageData imgFavorite(imgPath, favorite_png); + snprintf(imgPath, sizeof(imgPath), "%snot_favorite.png", CFG.theme_path); GuiImageData imgNotFavorite(imgPath, not_favorite_png); snprintf(imgPath, sizeof(imgPath), "%sstartgame_arrow_left.png", CFG.theme_path); @@ -1066,11 +1065,11 @@ int GameWindowPrompt() diskImg2.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); diskImg2.SetPosition(0, -20); diskImg2.SetAngle(angle); - diskImg2.SetBeta(180); - + diskImg2.SetBeta(180); + char PlayCnt[25] = ""; - GuiText playcntTxt(PlayCnt, 18, (GXColor){THEME.info_r, THEME.info_g, THEME.info_b, 255}); - playcntTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + GuiText playcntTxt(PlayCnt, 18, (GXColor){THEME.info_r, THEME.info_g, THEME.info_b, 255}); + playcntTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); playcntTxt.SetPosition(-115,45); GuiButton btn1(160, 160); @@ -1125,17 +1124,17 @@ int GameWindowPrompt() btn3.SetSoundClick(&btnClick); btn3.SetTrigger(&trigA); btn3.SetEffectGrow(); - - GuiImage btnFavoriteImg; - btnFavoriteImg.SetWidescreen(CFG.widescreen); - GuiButton btnFavorite(imgFavorite.GetWidth(), imgFavorite.GetHeight()); - btnFavorite.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - btnFavorite.SetPosition(-125, -60); - btnFavorite.SetImage(&btnFavoriteImg); - btnFavorite.SetSoundOver(&btnSoundOver); - btnFavorite.SetSoundClick(&btnClick); - btnFavorite.SetTrigger(&trigA); - btnFavorite.SetEffectGrow(); + + GuiImage btnFavoriteImg; + btnFavoriteImg.SetWidescreen(CFG.widescreen); + GuiButton btnFavorite(imgFavorite.GetWidth(), imgFavorite.GetHeight()); + btnFavorite.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + btnFavorite.SetPosition(-125, -60); + btnFavorite.SetImage(&btnFavoriteImg); + btnFavorite.SetSoundOver(&btnSoundOver); + btnFavorite.SetSoundClick(&btnClick); + btnFavorite.SetTrigger(&trigA); + btnFavorite.SetEffectGrow(); GuiImage btnLeftImg(&imgLeft); if (Settings.wsprompt == yes) @@ -1169,13 +1168,13 @@ int GameWindowPrompt() promptWindow.Append(&dialogBoxImg); promptWindow.Append(&nameBtn); - promptWindow.Append(&sizeTxt); + promptWindow.Append(&sizeTxt); promptWindow.Append(&playcntTxt); // promptWindow.Append(&btn1); // move down at last apended promptWindow.Append(&btn2); promptWindow.Append(&btnLeft); - promptWindow.Append(&btnRight); - promptWindow.Append(&btnFavorite); + promptWindow.Append(&btnRight); + promptWindow.Append(&btnFavorite); //check if unlocked if (CFG.godmode == 1) @@ -1288,18 +1287,18 @@ int GameWindowPrompt() diskImg.SetImage(diskCover); sizeTxt.SetText(sizeText); nameTxt.SetText(get_title(header)); - + struct Game_NUM* game_num = CFG_get_game_num(header->id); if (game_num) { - playCount = game_num->count; + playCount = game_num->count; faveChoice = game_num->favorite; - } else { - playCount = 0; - faveChoice = 0; - } - sprintf(PlayCnt,"%s: %i",LANGUAGE.Plays, playCount); - playcntTxt.SetText(PlayCnt); - btnFavoriteImg.SetImage(faveChoice ? &imgFavorite : &imgNotFavorite); + } else { + playCount = 0; + faveChoice = 0; + } + sprintf(PlayCnt,"%s: %i",LANGUAGE.Plays, playCount); + playcntTxt.SetText(PlayCnt); + btnFavoriteImg.SetImage(faveChoice ? &imgFavorite : &imgNotFavorite); nameTxt.SetPosition(0, 1); @@ -1367,23 +1366,23 @@ int GameWindowPrompt() choice = 3; promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); } - - else if(btnFavorite.GetState() == STATE_CLICKED){//switch favorite - if(isSdInserted()) { - faveChoice = !faveChoice; - btnFavoriteImg.SetImage(faveChoice ? &imgFavorite : &imgNotFavorite); - extern u8 favorite; + + else if(btnFavorite.GetState() == STATE_CLICKED){//switch favorite + if(isSdInserted()) { + faveChoice = !faveChoice; + btnFavoriteImg.SetImage(faveChoice ? &imgFavorite : &imgNotFavorite); + extern u8 favorite; extern u8 count; struct Game_NUM* game_num = CFG_get_game_num(header->id); if (game_num) { - favorite = game_num->favorite; + favorite = game_num->favorite; count = game_num->count; - } + } favorite = faveChoice; CFG_save_game_num(header->id); - } - btnFavorite.ResetState(); - } + } + btnFavorite.ResetState(); + } // this next part is long because nobody could agree on what the left/right buttons should do else if((btnRight.GetState() == STATE_CLICKED) && (Settings.xflip == no)){//next game @@ -2406,9 +2405,9 @@ s32 __Menu_GetEntries(void) /* Get header list */ ret = WBFS_GetHeaders(buffer, cnt, sizeof(struct discHdr)); - if (ret < 0) { + if (ret < 0) { if(buffer) free(buffer); - return ret; + return ret; } /* Filters */ @@ -2434,17 +2433,17 @@ s32 __Menu_GetEntries(void) memcpy((buffer2 + cnt2), (buffer + i), sizeof(struct discHdr)); cnt2++; } - } + } if (buffer2) { free(buffer); buffer = buffer2; - buffer2 = NULL; - } else { - memset(buffer, 0, len); + buffer2 = NULL; + } else { + memset(buffer, 0, len); } cnt = cnt2; } - + if (CFG.parentalcontrol && !CFG.godmode) { u32 cnt3 = 0; @@ -2463,22 +2462,22 @@ s32 __Menu_GetEntries(void) memcpy((buffer2 + cnt3), (buffer + i), sizeof(struct discHdr)); cnt3++; } - } + } if (buffer2) { free(buffer); buffer = buffer2; - buffer2 = NULL; - } else { - memset(buffer, 0, len); + buffer2 = NULL; + } else { + memset(buffer, 0, len); } cnt = cnt3; - } - - if (Settings.sort==pcount) { - qsort(buffer, cnt, sizeof(struct discHdr), __Menu_EntryCmpCount); } - else { - qsort(buffer, cnt, sizeof(struct discHdr), __Menu_EntryCmp); + + if (Settings.sort==pcount) { + qsort(buffer, cnt, sizeof(struct discHdr), __Menu_EntryCmpCount); + } + else { + qsort(buffer, cnt, sizeof(struct discHdr), __Menu_EntryCmp); } /* Free memory */ @@ -2486,7 +2485,7 @@ s32 __Menu_GetEntries(void) free(gameList); /* Set values */ - gameList = buffer; + gameList = buffer; buffer = NULL; gameCnt = cnt; @@ -2824,7 +2823,7 @@ static int MenuDiscList() GuiImageData batteryRed(imgPath, battery_red_png); snprintf(imgPath, sizeof(imgPath), "%sbattery_bar.png", CFG.theme_path); GuiImageData batteryBar(imgPath, battery_bar_png); - + snprintf(imgPath, sizeof(imgPath), "%sfavIcon.png", CFG.theme_path); GuiImageData imgfavIcon(imgPath, favIcon_png); snprintf(imgPath, sizeof(imgPath), "%sfavIcon_gray.png", CFG.theme_path); @@ -3042,7 +3041,7 @@ static int MenuDiscList() carosselleBtn.SetTrigger(&trigA); carosselleBtn.SetEffectGrow(); carosselleBtn.SetAlpha(180); - + if (Settings.fave) { favoriteBtn.SetImage(&favoriteBtnImg); @@ -3269,7 +3268,7 @@ static int MenuDiscList() else if(sdcardBtn.GetState() == STATE_CLICKED) { - SDCard_deInit(); + SDCard_deInit(); SDCard_Init(); if (Settings.gameDisplay==list){ startat = gameBrowser.GetSelectedOption(); @@ -3365,7 +3364,7 @@ static int MenuDiscList() gameBrowser.Reload(gameList, gameCnt);} else if (Settings.gameDisplay==grid){ gameGrid.Reload(gameList, gameCnt);} - gameBrowser.Reload(gameList, gameCnt); +// gameBrowser.Reload(gameList, gameCnt); sprintf(GamesCnt,"%s: %i",LANGUAGE.Games, gameCnt); gamecntTxt.SetText(GamesCnt); selectedold = 1; @@ -3375,7 +3374,7 @@ static int MenuDiscList() else if(abcBtn.GetState() == STATE_CLICKED) { - if(Settings.sort != all) { + if(Settings.sort != all) { Settings.sort=all; if(isSdInserted()) { cfg_save_global(); @@ -3385,19 +3384,19 @@ static int MenuDiscList() gameBrowser.Reload(gameList, gameCnt);} else if (Settings.gameDisplay==grid){ gameGrid.Reload(gameList, gameCnt);} - selectedold = 1; + selectedold = 1; abcBtn.SetImage(&abcBtnImg); abcBtn.SetAlpha(255); countBtn.SetImage(&countBtnImg_g); - countBtn.SetAlpha(180); + countBtn.SetAlpha(180); } abcBtn.ResetState(); } else if(countBtn.GetState() == STATE_CLICKED) { - if(Settings.sort != pcount) { - Settings.sort=pcount; + if(Settings.sort != pcount) { + Settings.sort=pcount; if(isSdInserted()) { cfg_save_global(); } @@ -3406,11 +3405,11 @@ static int MenuDiscList() gameBrowser.Reload(gameList, gameCnt);} else if (Settings.gameDisplay==grid){ gameGrid.Reload(gameList, gameCnt);} - selectedold = 1; + selectedold = 1; abcBtn.SetImage(&abcBtnImg_g); abcBtn.SetAlpha(180); countBtn.SetImage(&countBtnImg); - countBtn.SetAlpha(255); + countBtn.SetAlpha(255); } countBtn.ResetState();