From 3180dd627bea503937cee32fdc33dfcf398fac29 Mon Sep 17 00:00:00 2001 From: dborth Date: Fri, 21 Aug 2009 07:19:35 +0000 Subject: [PATCH] text alignment corrections --- source/ngc/FreeTypeGX.cpp | 331 +++++++++++++++++++----------------- source/ngc/FreeTypeGX.h | 45 +++-- source/ngc/gui/gui_text.cpp | 15 +- 3 files changed, 210 insertions(+), 181 deletions(-) diff --git a/source/ngc/FreeTypeGX.cpp b/source/ngc/FreeTypeGX.cpp index 125476b..5a004ed 100644 --- a/source/ngc/FreeTypeGX.cpp +++ b/source/ngc/FreeTypeGX.cpp @@ -24,7 +24,7 @@ static FT_Library ftLibrary; /**< FreeType FT_Library instance. */ static FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */ -static FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */ +static FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */ FreeTypeGX *fontSystem[MAX_FONT_SIZE+1]; @@ -81,7 +81,8 @@ wchar_t* charToWideChar(const char* strChar) * @param textureFormat Optional format (GX_TF_*) of the texture as defined by the libogc gx.h header file. If not specified default value is GX_TF_RGBA8. * @param vertexIndex Optional vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. If not specified default value is GX_VTXFMT1. */ -FreeTypeGX::FreeTypeGX(FT_UInt pixelSize, uint8_t textureFormat, uint8_t vertexIndex) { +FreeTypeGX::FreeTypeGX(FT_UInt pixelSize, uint8_t textureFormat, uint8_t vertexIndex) +{ this->textureFormat = textureFormat; this->setVertexFormat(vertexIndex); this->setCompatibilityMode(FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE); @@ -92,7 +93,8 @@ FreeTypeGX::FreeTypeGX(FT_UInt pixelSize, uint8_t textureFormat, uint8_t vertexI /** * Default destructor for the FreeTypeGX class. */ -FreeTypeGX::~FreeTypeGX() { +FreeTypeGX::~FreeTypeGX() +{ this->unloadFont(); } @@ -105,9 +107,9 @@ FreeTypeGX::~FreeTypeGX() { * * @param vertexIndex Vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. */ -void FreeTypeGX::setVertexFormat(uint8_t vertexIndex) { +void FreeTypeGX::setVertexFormat(uint8_t vertexIndex) +{ this->vertexIndex = vertexIndex; - GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_POS, GX_POS_XY, GX_S16, 0); GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); @@ -123,7 +125,8 @@ void FreeTypeGX::setVertexFormat(uint8_t vertexIndex) { * * @param compatibilityMode Compatibility descritor (FTGX_COMPATIBILITY_*) as defined in FreeTypeGX.h */ -void FreeTypeGX::setCompatibilityMode(uint32_t compatibilityMode) { +void FreeTypeGX::setCompatibilityMode(uint32_t compatibilityMode) +{ this->compatibilityMode = compatibilityMode; } @@ -133,9 +136,12 @@ void FreeTypeGX::setCompatibilityMode(uint32_t compatibilityMode) { * This function calls the GX_SetTevOp and GX_SetVtxDesc functions with the compatibility parameters specified * in setCompatibilityMode. */ -void FreeTypeGX::setDefaultMode() { - if(this->compatibilityMode) { - switch(this->compatibilityMode & 0x00FF) { +void FreeTypeGX::setDefaultMode() +{ + if(this->compatibilityMode) + { + switch(this->compatibilityMode & 0x00FF) + { case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE: GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); break; @@ -155,7 +161,8 @@ void FreeTypeGX::setDefaultMode() { break; } - switch(this->compatibilityMode & 0xFF00) { + switch(this->compatibilityMode & 0xFF00) + { case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE: GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); break; @@ -179,14 +186,12 @@ void FreeTypeGX::setDefaultMode() { * * This routine clears all members of the font map structure and frees all allocated memory back to the system. */ -void FreeTypeGX::unloadFont() { +void FreeTypeGX::unloadFont() +{ if(this->fontData.size() == 0) return; - - for( std::map::iterator i = this->fontData.begin(); i != this->fontData.end(); i++) { + for(std::map::iterator i = this->fontData.begin(); i != this->fontData.end(); i++) free(i->second.glyphDataTexture); - } - this->fontData.clear(); } @@ -199,10 +204,12 @@ void FreeTypeGX::unloadFont() { * @param textureFormat The texture format to which the data is to be converted. * @return The correctly adjusted texture width. */ -uint16_t FreeTypeGX::adjustTextureWidth(uint16_t textureWidth, uint8_t textureFormat) { +uint16_t FreeTypeGX::adjustTextureWidth(uint16_t textureWidth, uint8_t textureFormat) +{ uint16_t alignment; - switch(textureFormat) { + switch(textureFormat) + { case GX_TF_I4: /* 8x8 Tiles - 4-bit Intensity */ case GX_TF_I8: /* 8x4 Tiles - 8-bit Intensity */ case GX_TF_IA4: /* 8x4 Tiles - 4-bit Intensity, , 4-bit Alpha */ @@ -218,7 +225,6 @@ uint16_t FreeTypeGX::adjustTextureWidth(uint16_t textureWidth, uint8_t textureFo break; } return textureWidth % alignment == 0 ? textureWidth : alignment + textureWidth - (textureWidth % alignment); - } /** @@ -230,10 +236,12 @@ uint16_t FreeTypeGX::adjustTextureWidth(uint16_t textureWidth, uint8_t textureFo * @param textureFormat The texture format to which the data is to be converted. * @return The correctly adjusted texture height. */ -uint16_t FreeTypeGX::adjustTextureHeight(uint16_t textureHeight, uint8_t textureFormat) { +uint16_t FreeTypeGX::adjustTextureHeight(uint16_t textureHeight, uint8_t textureFormat) +{ uint16_t alignment; - switch(textureFormat) { + switch(textureFormat) + { case GX_TF_I4: /* 8x8 Tiles - 4-bit Intensity */ alignment = 8; break; @@ -249,7 +257,6 @@ uint16_t FreeTypeGX::adjustTextureHeight(uint16_t textureHeight, uint8_t texture break; } return textureHeight % alignment == 0 ? textureHeight : alignment + textureHeight - (textureHeight % alignment); - } /** @@ -261,7 +268,8 @@ uint16_t FreeTypeGX::adjustTextureHeight(uint16_t textureHeight, uint8_t texture * @param charCode The requested glyph's character code. * @return A pointer to the allocated font structure. */ -ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) { +ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) +{ FT_UInt gIndex; uint16_t textureWidth = 0, textureHeight = 0; @@ -276,13 +284,14 @@ ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) { textureHeight = adjustTextureHeight(glyphBitmap->rows, this->textureFormat); this->fontData[charCode] = (ftgxCharData){ + ftSlot->bitmap_left, ftSlot->advance.x >> 6, gIndex, textureWidth, textureHeight, ftSlot->bitmap_top, ftSlot->bitmap_top, - textureHeight - ftSlot->bitmap_top, + glyphBitmap->rows - ftSlot->bitmap_top, NULL }; this->loadGlyphData(glyphBitmap, &this->fontData[charCode]); @@ -290,7 +299,6 @@ ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) { return &this->fontData[charCode]; } } - return NULL; } @@ -300,19 +308,17 @@ ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) { * This routine locates each character in the configured font face and renders the glyph's bitmap. * Each bitmap and relevant information is loaded into its own quickly addressible structure within an instance-specific map. */ -uint16_t FreeTypeGX::cacheGlyphDataComplete() { +uint16_t FreeTypeGX::cacheGlyphDataComplete() +{ uint16_t i = 0; FT_UInt gIndex; FT_ULong charCode = FT_Get_First_Char( ftFace, &gIndex ); - while ( gIndex != 0 ) { - - if(this->cacheGlyphData(charCode) != NULL) { + while ( gIndex != 0 ) + { + if(this->cacheGlyphData(charCode) != NULL) i++; - } - charCode = FT_Get_Next_Char( ftFace, charCode, &gIndex ); } - return i; } @@ -325,19 +331,22 @@ uint16_t FreeTypeGX::cacheGlyphDataComplete() { * @param bmp A pointer to the most recently rendered glyph's bitmap. * @param charData A pointer to an allocated ftgxCharData structure whose data represent that of the last rendered glyph. */ -void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) { - +void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) +{ uint32_t *glyphData = (uint32_t *)memalign(32, charData->textureWidth * charData->textureHeight * 4); memset(glyphData, 0x00, charData->textureWidth * charData->textureHeight * 4); - for (uint16_t imagePosY = 0; imagePosY < bmp->rows; imagePosY++) { - for (uint16_t imagePosX = 0; imagePosX < bmp->width; imagePosX++) { + for (uint16_t imagePosY = 0; imagePosY < bmp->rows; imagePosY++) + { + for (uint16_t imagePosX = 0; imagePosX < bmp->width; imagePosX++) + { uint32_t pixel = (uint32_t) bmp->buffer[imagePosY * bmp->width + imagePosX]; glyphData[imagePosY * charData->textureWidth + imagePosX] = 0x00000000 | (pixel << 24) | (pixel << 16) | (pixel << 8) | pixel; } } - switch(this->textureFormat) { + switch(this->textureFormat) + { case GX_TF_I4: charData->glyphDataTexture = Metaphrasis::convertBufferToI4(glyphData, charData->textureWidth, charData->textureHeight); break; @@ -361,7 +370,6 @@ void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) { charData->glyphDataTexture = Metaphrasis::convertBufferToRGBA8(glyphData, charData->textureWidth, charData->textureHeight); break; } - free(glyphData); } @@ -373,18 +381,14 @@ 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) { - - if (format & FTGX_JUSTIFY_LEFT ) { +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; - } - else if (format & FTGX_JUSTIFY_RIGHT ) { - return width; - } - + else if (format & FTGX_JUSTIFY_CENTER) + return -(width >> 1); + else if (format & FTGX_JUSTIFY_RIGHT) + return -width; return 0; } @@ -396,17 +400,32 @@ 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; } @@ -423,47 +442,57 @@ uint16_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) +{ uint16_t strLength = wcslen(text); uint16_t x_pos = x, printed = 0; 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) + { + this->getOffset(text, &offset); + y_offset = this->getStyleOffsetHeight(&offset, textStyle); } - for (uint16_t i = 0; i < strLength; i++) { - + for (uint16_t i = 0; i < strLength; i++) + { ftgxCharData* glyphData = NULL; - if( this->fontData.find(text[i]) != this->fontData.end() ) { + if( this->fontData.find(text[i]) != this->fontData.end() ) + { glyphData = &this->fontData[text[i]]; } - else { + else + { glyphData = this->cacheGlyphData(text[i]); } - if(glyphData != NULL) { - - if(this->ftKerningEnabled && i) { + 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; } 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 - 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->getOffset(text, &offset); + this->drawTextFeature(x + x_offset, y + y_offset, this->getWidth(text), &offset, textStyle, color); } return printed; @@ -472,46 +501,20 @@ 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) +{ 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) { - case FTGX_ALIGN_TOP: - 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); - break; - case FTGX_ALIGN_BOTTOM: - this->copyFeatureToFramebuffer(width, featureHeight, x, y - offsetData.min, color); - break; - default: - this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color); - break; - } - } + if (format & FTGX_STYLE_UNDERLINE) + this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color); - if (format & FTGX_STYLE_STRIKE ) { - switch(format & 0x00F0) { - case FTGX_ALIGN_TOP: - this->copyFeatureToFramebuffer(width, featureHeight, x, y + ((offsetData.max + offsetData.min) >> 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); - break; - default: - this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData.max - offsetData.min) >> 1), color); - break; - } - } + if (format & FTGX_STYLE_STRIKE) + this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData->max) >> 1), color); } /** @@ -523,31 +526,35 @@ 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 strLength = wcslen(text); uint16_t strWidth = 0; FT_Vector pairDelta; - for (uint16_t i = 0; i < strLength; i++) { + for (uint16_t i = 0; i < strLength; i++) + { ftgxCharData* glyphData = NULL; - if( this->fontData.find(text[i]) != this->fontData.end() ) { + if( this->fontData.find(text[i]) != this->fontData.end() ) + { glyphData = &this->fontData[text[i]]; } - else { + else + { glyphData = this->cacheGlyphData(text[i]); } - if(glyphData != NULL) { - if(this->ftKerningEnabled && (i > 0)) { + 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; } - strWidth += glyphData->glyphAdvanceX; } } - return strWidth; } @@ -555,7 +562,8 @@ uint16_t FreeTypeGX::getWidth(wchar_t *text) { * * \overload */ -uint16_t FreeTypeGX::getWidth(wchar_t const *text) { +uint16_t FreeTypeGX::getWidth(wchar_t const *text) +{ return this->getWidth((wchar_t *)text); } @@ -568,17 +576,19 @@ uint16_t FreeTypeGX::getWidth(wchar_t const *text) { * @param text NULL terminated string to calculate. * @return The height of the text string in pixels. */ -uint16_t FreeTypeGX::getHeight(wchar_t *text) { - ftgxDataOffset offset = this->getOffset(text); - - return offset.max + offset.min; +uint16_t FreeTypeGX::getHeight(wchar_t *text) +{ + ftgxDataOffset offset; + this->getOffset(text, &offset); + return offset.max - offset.min; } /** * * \overload */ -uint16_t FreeTypeGX::getHeight(wchar_t const *text) { +uint16_t FreeTypeGX::getHeight(wchar_t const *text) +{ return this->getHeight((wchar_t *)text); } @@ -589,37 +599,46 @@ 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) { +void FreeTypeGX::getOffset(wchar_t *text, ftgxDataOffset* offset) +{ uint16_t strLength = wcslen(text); - uint16_t strMax = 0, strMin = 0; + int16_t strMax = 0, strMin = 9999; - for (uint16_t i = 0; i < strLength; i++) { + for (uint16_t i = 0; i < strLength; i++) + { ftgxCharData* glyphData = NULL; - if( this->fontData.find(text[i]) != this->fontData.end() ) { + if( this->fontData.find(text[i]) != this->fontData.end() ) + { glyphData = &this->fontData[text[i]]; } - else { + else + { glyphData = this->cacheGlyphData(text[i]); } - if(glyphData != NULL) { + 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 = ftFace->size->metrics.ascender>>6; + offset->descender = ftFace->size->metrics.descender>>6; + offset->max = strMax; + offset->min = strMin; } /** * * \overload */ -ftgxDataOffset FreeTypeGX::getOffset(wchar_t const *text) { - return this->getOffset(text); +void FreeTypeGX::getOffset(wchar_t const *text, ftgxDataOffset* offset) +{ + this->getOffset(text, offset); } /** @@ -634,8 +653,8 @@ ftgxDataOffset FreeTypeGX::getOffset(wchar_t const *text) { * @param screenY The screen Y coordinate at which to output the rendered texture. * @param color Color to apply to the texture. */ -void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, GXColor color) { - +void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, GXColor color) +{ GX_LoadTexObj(texObj, GX_TEXMAP0); GX_InvalidateTexAll(); @@ -643,21 +662,21 @@ void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 te GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); GX_Begin(GX_QUADS, this->vertexIndex, 4); - GX_Position2s16(screenX, screenY); - GX_Color4u8(color.r, color.g, color.b, color.a); - GX_TexCoord2f32(0.0f, 0.0f); + GX_Position2s16(screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(0.0f, 0.0f); - GX_Position2s16(texWidth + screenX, screenY); - GX_Color4u8(color.r, color.g, color.b, color.a); - GX_TexCoord2f32(1.0f, 0.0f); + GX_Position2s16(texWidth + screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(1.0f, 0.0f); - GX_Position2s16(texWidth + screenX, texHeight + screenY); - GX_Color4u8(color.r, color.g, color.b, color.a); - GX_TexCoord2f32(1.0f, 1.0f); + GX_Position2s16(texWidth + screenX, texHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(1.0f, 1.0f); - GX_Position2s16(screenX, texHeight + screenY); - GX_Color4u8(color.r, color.g, color.b, color.a); - GX_TexCoord2f32(0.0f, 1.0f); + GX_Position2s16(screenX, texHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(0.0f, 1.0f); GX_End(); GX_DrawDone(); @@ -675,23 +694,23 @@ void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 te * @param screenY The screen Y coordinate at which to output the quad. * @param color Color to apply to the texture. */ -void FreeTypeGX::copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color) { - +void FreeTypeGX::copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color) +{ GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); GX_SetVtxDesc (GX_VA_TEX0, GX_NONE); GX_Begin(GX_QUADS, this->vertexIndex, 4); - GX_Position2s16(screenX, screenY); - GX_Color4u8(color.r, color.g, color.b, color.a); + GX_Position2s16(screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); - GX_Position2s16(featureWidth + screenX, screenY); - GX_Color4u8(color.r, color.g, color.b, color.a); + GX_Position2s16(featureWidth + screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); - GX_Position2s16(featureWidth + screenX, featureHeight + screenY); - GX_Color4u8(color.r, color.g, color.b, color.a); + GX_Position2s16(featureWidth + screenX, featureHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); - GX_Position2s16(screenX, featureHeight + screenY); - GX_Color4u8(color.r, color.g, color.b, color.a); + GX_Position2s16(screenX, featureHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); GX_End(); GX_DrawDone(); diff --git a/source/ngc/FreeTypeGX.h b/source/ngc/FreeTypeGX.h index 4487a04..93fcab3 100644 --- a/source/ngc/FreeTypeGX.h +++ b/source/ngc/FreeTypeGX.h @@ -169,15 +169,16 @@ * Font face character glyph relevant data structure. */ typedef struct ftgxCharData_ { - uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */ - uint16_t glyphIndex; /**< Charachter glyph index in the font face. */ + 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. */ + uint16_t textureWidth; /**< Texture width in pixels/bytes. */ + uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */ - uint16_t renderOffsetY; /**< Texture Y axis bearing offset. */ - uint16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */ - uint16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */ + 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; @@ -187,23 +188,35 @@ typedef struct ftgxCharData_ { * 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. */ + 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; +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_JUSTIFY_MASK 0x000f #define FTGX_ALIGN_TOP 0x0010 #define FTGX_ALIGN_MIDDLE 0x0020 #define FTGX_ALIGN_BOTTOM 0x0040 +#define FTGX_ALIGN_BASELINE 0x0080 +#define FTGX_ALIGN_GLYPH_TOP 0x0100 +#define FTGX_ALIGN_GLYPH_MIDDLE 0x0200 +#define FTGX_ALIGN_GLYPH_BOTTOM 0x0400 +#define FTGX_ALIGN_MASK 0x0ff0 -#define FTGX_STYLE_UNDERLINE 0x0100 -#define FTGX_STYLE_STRIKE 0x0200 +#define FTGX_STYLE_UNDERLINE 0x1000 +#define FTGX_STYLE_STRIKE 0x2000 +#define FTGX_STYLE_MASK 0xf000 #define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE 0X0001 #define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL 0X0002 @@ -250,8 +263,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); @@ -260,7 +273,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); @@ -278,8 +291,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); + void getOffset(wchar_t *text, ftgxDataOffset* offset); + void getOffset(wchar_t const *text, ftgxDataOffset* offset); }; #endif /* FREETYPEGX_H_ */ diff --git a/source/ngc/gui/gui_text.cpp b/source/ngc/gui/gui_text.cpp index 2c8027c..cf6648f 100644 --- a/source/ngc/gui/gui_text.cpp +++ b/source/ngc/gui/gui_text.cpp @@ -227,11 +227,6 @@ void GuiText::Draw() currentSize = newSize; } - int voffset = 0; - - if(alignmentVert == ALIGN_MIDDLE) - voffset = -newSize/2 + 2; - if(maxWidth > 0) { char * tmpText = strdup(origText); @@ -279,7 +274,7 @@ void GuiText::Draw() } } if(textDyn) - fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop()+voffset, textDyn, c, style); + fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style); } else if(wrap) { @@ -328,8 +323,10 @@ void GuiText::Draw() i++; } + int voffset = 0; + if(alignmentVert == ALIGN_MIDDLE) - voffset = voffset - (lineheight*linenum)/2 + lineheight/2; + voffset = -(lineheight*linenum)/2 + lineheight/2; for(i=0; i < linenum; i++) { @@ -339,13 +336,13 @@ void GuiText::Draw() } else { - fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop()+voffset, textDyn, c, style); + fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style); } free(tmpText); } else { - fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style); + fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style); } this->UpdateEffects(); }