From f7e78b21e9655604ba6fba1d068a9bf7f00b85a5 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Mon, 6 Aug 2012 20:20:50 +0200 Subject: Font rendering - implemented rest of CText interface excluding some minor features --- src/common/stringutils.cpp | 10 +- src/graphics/engine/engine.cpp | 37 ++- src/graphics/engine/engine.h | 8 +- src/graphics/engine/text.cpp | 516 ++++++++++++++++++++++++++++++++--------- src/graphics/engine/text.h | 67 +++--- src/math/intpoint.h | 6 +- src/math/intsize.h | 6 +- 7 files changed, 501 insertions(+), 149 deletions(-) diff --git a/src/common/stringutils.cpp b/src/common/stringutils.cpp index 585bb46..12a3179 100644 --- a/src/common/stringutils.cpp +++ b/src/common/stringutils.cpp @@ -135,15 +135,11 @@ int StrUtils::Utf8CharSizeAt(const std::string &str, unsigned int pos) size_t StrUtils::Utf8StringLength(const std::string &str) { size_t result = 0; - for (unsigned int i = 0; i < str.size(); ++i) + unsigned int i = 0; + while (i < str.size()) { - char ch = str[i]; - if ((ch & 0x80) == 0) + i += Utf8CharSizeAt(str, i); ++result; - else if ((ch & 0xC0) == 0xC0) - result += 2; - else - result += 3; } return result; } diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 345a15c..c5d2a1d 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -447,6 +447,19 @@ void Gfx::CEngine::SetState(int state, Gfx::Color color) m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/ } + else if (state & Gfx::ENG_RSTATE_TEXT) + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + + m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + } else // normal ? { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); @@ -607,11 +620,33 @@ bool Gfx::CEngine::DrawInterface() DrawMouse(); - m_text->DrawString("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, 0); + std::vector format; + for (int i = 0; i < 10; ++i) + format.push_back(Gfx::FONT_COLOBOT_BOLD | Gfx::FONT_HIGHLIGHT_CONST); + for (int i = 0; i < 10; ++i) + format.push_back(Gfx::FONT_COLOBOT_ITALIC | Gfx::FONT_HIGHLIGHT_KEY); + for (int i = 0; i < 10; ++i) + format.push_back(Gfx::FONT_COURIER | Gfx::FONT_HIGHLIGHT_LINK); + for (int i = 0; i < 5; ++i) + format.push_back(Gfx::FONT_COURIER_BOLD | Gfx::FONT_HIGHLIGHT_REM); + + m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); + float h = m_text->GetHeight(Gfx::FONT_COLOBOT, 15.0f); + m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", format, 13.0f, Math::Point(0.25f, 0.2f - h), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); return true; } +Math::IntSize Gfx::CEngine::GetWindowSize() +{ + return m_size; +} + +Math::IntSize Gfx::CEngine::GetLastWindowSize() +{ + return m_lastSize; +} + /** Conversion of the position of the mouse from window coords to interface coords: - x: 0=left, 1=right - y: 0=down, 1=up */ diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 79844c6..3f7f4f2 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -408,7 +408,9 @@ enum EngineRenderState //! The transparent color (black = no) ENG_RSTATE_TCOLOR_BLACK = (1<<16), //! The transparent color (white = no) - ENG_RSTATE_TCOLOR_WHITE = (1<<17) + ENG_RSTATE_TCOLOR_WHITE = (1<<17), + //! Mode for rendering text + ENG_RSTATE_TEXT = (1<<18) }; @@ -776,8 +778,8 @@ public: Math::Vector GetLookatPt(); float GetEyeDirH(); float GetEyeDirV(); - Math::IntPoint GetViewportSize(); - Math::IntPoint GetLastViewportSize(); + Math::IntSize GetWindowSize(); + Math::IntSize GetLastWindowSize(); void UpdateMatProj(); void ApplyChange(); diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index eea9fdb..77515ad 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -150,118 +150,421 @@ void Gfx::CText::FlushCache() } void Gfx::CText::DrawText(const std::string &text, const std::vector &format, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol) + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol) { - // TODO + float sw = 0.0f; + + if (align == Gfx::TEXT_ALIGN_CENTER) + { + sw = GetStringWidth(text, format, size); + if (sw > width) sw = width; + pos.x -= sw / 2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + sw = GetStringWidth(text, format, size); + if (sw > width) sw = width; + pos.x -= sw; + } + + DrawString(text, format, size, pos, width, eol); } void Gfx::CText::DrawText(const std::string &text, Gfx::FontType font, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol) + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol) { - // TODO + float sw = 0.0f; + + if (align == Gfx::TEXT_ALIGN_CENTER) + { + sw = GetStringWidth(text, font, size); + if (sw > width) sw = width; + pos.x -= sw / 2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + sw = GetStringWidth(text, font, size); + if (sw > width) sw = width; + pos.x -= sw; + } + + DrawString(text, font, size, pos, width, eol); } void Gfx::CText::SizeText(const std::string &text, const std::vector &format, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end) { - // TODO + start = end = pos; + + float sw = GetStringWidth(text, format, size); + end.x += sw; + if (align == Gfx::TEXT_ALIGN_CENTER) + { + start.x -= sw/2.0f; + end.x -= sw/2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + start.x -= sw; + end.x -= sw; + } + + start.y -= GetDescent(Gfx::FONT_COLOBOT, size); + end.y += GetAscent(Gfx::FONT_COLOBOT, size); } void Gfx::CText::SizeText(const std::string &text, Gfx::FontType font, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end) { - // TODO + start = end = pos; + + float sw = GetStringWidth(text, font, size); + end.x += sw; + if (align == Gfx::TEXT_ALIGN_CENTER) + { + start.x -= sw/2.0f; + end.x -= sw/2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + start.x -= sw; + end.x -= sw; + } + + start.y -= GetDescent(font, size); + end.y += GetAscent(font, size); } float Gfx::CText::GetAscent(Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + wndSize.h = TTF_FontAscent(cf->font); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.h; } float Gfx::CText::GetDescent(Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + wndSize.h = TTF_FontDescent(cf->font); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.h; } float Gfx::CText::GetHeight(Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + wndSize.h = TTF_FontHeight(cf->font); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.h; } float Gfx::CText::GetStringWidth(const std::string &text, const std::vector &format, float size) { - // TODO - return 0.0f; + assert(StrUtils::Utf8StringLength(text) == format.size()); + + float width = 0.0f; + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + Gfx::FontType font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + width += GetCharWidth(ch, font, size, width); + + index += len; + fmtIndex++; + } + + return width; } float Gfx::CText::GetStringWidth(const std::string &text, Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + // TODO: special chars? + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + TTF_SizeUTF8(cf->font, text.c_str(), &wndSize.w, &wndSize.h); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.w; } -float Gfx::CText::GetCharWidth(int character, Gfx::FontType font, float size, float offset) +float Gfx::CText::GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, float offset) { - // TODO - return 0.0f; + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) return 0.0f; + + // TODO: special chars? + // TODO: tab sizing + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + + Gfx::CharTexture tex; + auto it = cf->cache.find(ch); + if (it != cf->cache.end()) + tex = (*it).second; + else + tex = CreateCharTexture(ch, cf); + + return tex.charSize.w; } int Gfx::CText::Justify(const std::string &text, const std::vector &format, float size, float width) { - // TODO - return 0; + assert(StrUtils::Utf8StringLength(text) == format.size()); + + float pos = 0.0f; + int cut = 0; + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + Gfx::FontType font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + if (font != Gfx::FONT_BUTTON) + { + if (ch.c1 == '\n') + return index+1; + if (ch.c1 == ' ') + cut = index+1; + } + + pos += GetCharWidth(ch, font, size, pos); + if (pos > width) + { + if (cut == 0) return index; + else return cut; + } + + index += len; + fmtIndex++; + } + + return index; } int Gfx::CText::Justify(const std::string &text, Gfx::FontType font, float size, float width) { - // TODO - return 0; + assert(font != Gfx::FONT_BUTTON); + + float pos = 0.0f; + int cut = 0; + unsigned int index = 0; + while (index < text.length()) + { + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + index += len; + + if (ch.c1 == '\n') + return index+1; + + if (ch.c1 == ' ' ) + cut = index+1; + + pos += GetCharWidth(ch, font, size, pos); + if (pos > width) + { + if (cut == 0) return index; + else return cut; + } + } + + return index; } int Gfx::CText::Detect(const std::string &text, const std::vector &format, float size, float offset) { - // TODO - return 0; + assert(StrUtils::Utf8StringLength(text) == format.size()); + + float pos = 0.0f; + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + Gfx::FontType font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) continue; + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + if (ch.c1 == '\n') + return index; + + float width = GetCharWidth(ch, font, size, pos); + if (offset <= pos + width/2.0f) + return index; + + pos += width; + index += len; + fmtIndex++; + } + + return index; } int Gfx::CText::Detect(const std::string &text, Gfx::FontType font, float size, float offset) { - // TODO - return 0; + assert(font != Gfx::FONT_BUTTON); + + float pos = 0.0f; + unsigned int index = 0; + while (index < text.length()) + { + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + index += len; + + if (ch.c1 == '\n') + return index; + + float width = GetCharWidth(ch, font, size, pos); + if (offset <= pos + width/2.0f) + return index; + + pos += width; + } + + return index; } void Gfx::CText::DrawString(const std::string &text, const std::vector &format, float size, Math::Point pos, float width, int eol) { - // TODO + assert(StrUtils::Utf8StringLength(text) == format.size()); + + m_engine->SetState(Gfx::ENG_RSTATE_TEXT); + + Gfx::FontType font = Gfx::FONT_COLOBOT; + float start = pos.x; + + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) continue; + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + float offset = pos.x - start; + float cw = GetCharWidth(ch, font, size, offset); + if (offset + cw > width) // exceeds the maximum width? + { + // TODO: special end-of-line char + break; + } + + Gfx::FontHighlight hl = static_cast(format[fmtIndex] & Gfx::FONT_MASK_HIGHLIGHT); + if (hl != Gfx::FONT_HIGHLIGHT_NONE) + { + Math::Size charSize; + charSize.w = GetCharWidth(ch, font, size, offset); + charSize.h = GetHeight(font, size); + DrawHighlight(hl, pos, charSize); + } + + DrawChar(ch, font, size, pos); + + index += len; + fmtIndex++; + } + + // TODO: eol } void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, float size, Math::Point pos, float width, int eol) { - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); - m_device->SetTextureEnabled(0, true); + assert(font != Gfx::FONT_BUTTON); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + m_engine->SetState(Gfx::ENG_RSTATE_TEXT); unsigned int index = 0; - Math::Point screenPos = pos; while (index < text.length()) { - UTF8Char ch; + Gfx::UTF8Char ch; int len = StrUtils::Utf8CharSizeAt(text, index); if (len >= 1) @@ -273,56 +576,64 @@ void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, index += len; - DrawChar(ch, font, size, screenPos); + DrawChar(ch, font, size, pos); } } -void Gfx::CText::DrawColor(int color, float size, Math::Point pos, float width) +void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size) { - // TODO !!! - /* - float h, u1, u2, v1, v2, dp; - int icon; + // Gradient colors + Gfx::Color grad[4]; + + // TODO: switch to alpha factors - int icon = -1; - switch (color) + switch (hl) { - case Gfx::FONT_COLOR_LINK: - icon = 9; + case Gfx::FONT_HIGHLIGHT_LINK: + grad[0] = grad[1] = grad[2] = grad[3] = Gfx::Color(0.0f, 0.0f, 1.0f, 0.5f); break; - case Gfx::FONT_COLOR_TOKEN: - icon = 4; + + case Gfx::FONT_HIGHLIGHT_TOKEN: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(248.0f / 256.0f, 220.0f / 256.0f, 188.0f / 256.0f, 0.5f); break; - case Gfx::FONT_COLOR_TYPE: - icon = 5; + + case Gfx::FONT_HIGHLIGHT_TYPE: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(169.0f / 256.0f, 234.0f / 256.0f, 169.0f / 256.0f, 0.5f); break; - } - icon = -1; - if ( color == COLOR_LINK ) icon = 9; // blue - if ( color == COLOR_TOKEN ) icon = 4; // orange - if ( color == COLOR_TYPE ) icon = 5; // green - if ( color == COLOR_CONST ) icon = 8; // red - if ( color == COLOR_REM ) icon = 6; // magenta - if ( color == COLOR_KEY ) icon = 10; // gray - if ( icon == -1 ) return; + case Gfx::FONT_HIGHLIGHT_CONST: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(248.0f / 256.0f, 176.0f / 256.0f, 169.0f / 256.0f, 0.5f); + break; - if ( color == COLOR_LINK ) - { - m_engine->SetState(D3DSTATENORMAL); + case Gfx::FONT_HIGHLIGHT_REM: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(248.0f / 256.0f, 169.0f / 256.0f, 248.0f / 256.0f, 0.5f); + break; + + case Gfx::FONT_HIGHLIGHT_KEY: + grad[0] = grad[1] = grad[2] = grad[3] = + Gfx::Color(192.0f / 256.0f, 192.0f / 256.0f, 192.0f / 256.0f, 0.5f); + break; + + default: + return; } - Math::IntSize vsize = m_engine->GetViewportSize(); - if (vsize.h <= 768.0f) // 1024x768 or less? - h = 1.01f / dim.y; // 1 pixel - else // more than 1024x768? - h = 2.0f / dim.y; // 2 pixels + Math::IntSize vsize = m_engine->GetWindowSize(); + float h = 0.0f; + if (vsize.h <= 768.0f) // 1024x768 or less? + h = 1.01f / vsize.h; // 1 pixel + else // more than 1024x768? + h = 2.0f / vsize.h; // 2 pixels Math::Point p1, p2; p1.x = pos.x; - p2.x = pos.x + width; + p2.x = pos.x + size.w; - if (color == Gfx::FONT_COLOR_LINK) + if (hl == Gfx::FONT_HIGHLIGHT_LINK) { p1.y = pos.y; p2.y = pos.y + h; // just emphasized @@ -330,45 +641,38 @@ void Gfx::CText::DrawColor(int color, float size, Math::Point pos, float width) else { p1.y = pos.y; - p2.y = pos.y + (16.0f/256.0f)*(size/20.0f); + p2.y = pos.y + size.h; } - u1 = (16.0f/256.0f)*(icon%16); - v1 = (240.0f/256.0f); - u2 = (16.0f/256.0f)+u1; - v2 = (16.0f/256.0f)+v1; - - dp = 0.5f/256.0f; - u1 += dp; - v1 += dp; - u2 -= dp; - v2 -= dp; + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); - Math::Vector n(0.0f, 0.0f, -1.0f); // normal - - Gfx::Vertex quad[] = + Gfx::VertexCol quad[] = { - Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), - Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), - Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), - Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)), + Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), grad[3]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), grad[2]), + Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), grad[0]), + Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), grad[1]) }; m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); m_engine->AddStatisticTriangle(2); - if (color == Gfx::FONT_COLOR_LINK) - m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE);*/ + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); } -void Gfx::CText::DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos) +void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math::Point &pos) { + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) return; + + // TODO: special chars? + CachedFont* cf = GetOrOpenFont(font, size); if (cf == nullptr) return; - auto it = cf->cache.find(character); + auto it = cf->cache.find(ch); CharTexture tex; if (it != cf->cache.end()) { @@ -376,31 +680,32 @@ void Gfx::CText::DrawChar(UTF8Char character, Gfx::FontType font, float size, Ma } else { - char str[] = { character.c1, character.c2, character.c3, '\0' }; - tex = CreateCharTexture(str, cf); + tex = CreateCharTexture(ch, cf); if (tex.id == 0) // invalid return; - cf->cache[character] = tex; + cf->cache[ch] = tex; } + m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); + + Math::Point p1(pos.x, pos.y + tex.charSize.h - tex.texSize.h); + Math::Point p2(pos.x + tex.texSize.w, pos.y + tex.charSize.h); + Math::Vector n(0.0f, 0.0f, -1.0f); // normal Gfx::Vertex quad[4] = { - Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h, 0.0f), - n, Math::Point(0.0f, 0.0f)), - Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), - n, Math::Point(0.0f, 1.0f)), - Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h, 0.0f), - n, Math::Point(1.0f, 0.0f)), - Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), - n, Math::Point(1.0f, 1.0f)) + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(0.0f, 1.0f)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(1.0f, 1.0f)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(1.0f, 0.0f)) }; m_device->SetTexture(0, tex.id); m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + m_engine->AddStatisticTriangle(2); pos.x += tex.charSize.w; } @@ -446,12 +751,13 @@ Gfx::CachedFont* Gfx::CText::GetOrOpenFont(Gfx::FontType font, float size) return m_lastCachedFont; } -Gfx::CharTexture Gfx::CText::CreateCharTexture(const char* str, Gfx::CachedFont* font) +Gfx::CharTexture Gfx::CText::CreateCharTexture(Gfx::UTF8Char ch, Gfx::CachedFont* font) { CharTexture texture; SDL_Surface* textSurface = nullptr; SDL_Color white = {255, 255, 255, 0}; + char str[] = { ch.c1, ch.c2, ch.c3, '\0' }; textSurface = TTF_RenderUTF8_Blended(font->font, str, white); if (textSurface == nullptr) diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index 19d9882..6209c39 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -38,9 +38,9 @@ const float FONT_SIZE_SMALL = 10.0f; const float FONT_SIZE_BIG = 15.0f; /** - \enum TextAlignType + \enum TextAlign \brief Type of text alignment */ -enum JustifyType +enum TextAlign { TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT, @@ -86,6 +86,8 @@ enum FontType \enum FontTitle \brief Size of font title + Used internally by CEdit + Bitmask in 2 bits left shifted 4 (mask 0x030) */ enum FontTitle { @@ -95,19 +97,20 @@ enum FontTitle }; /** - \enum FontColor - \brief Font color type (?) + \enum FontHighlight + \brief Type of color highlight for text Bitmask in 3 bits left shifted 6 (mask 0x1c0) */ -enum FontColor +enum FontHighlight { - FONT_COLOR_LINK = 0x01 << 6, - FONT_COLOR_TOKEN = 0x02 << 6, - FONT_COLOR_TYPE = 0x03 << 6, - FONT_COLOR_CONST = 0x04 << 6, - FONT_COLOR_REM = 0x05 << 6, - FONT_COLOR_KEY = 0x06 << 6, - FONT_COLOR_TABLE = 0x07 << 6, + FONT_HIGHLIGHT_NONE = 0x00 << 6, + FONT_HIGHLIGHT_LINK = 0x01 << 6, + FONT_HIGHLIGHT_TOKEN = 0x02 << 6, + FONT_HIGHLIGHT_TYPE = 0x03 << 6, + FONT_HIGHLIGHT_CONST = 0x04 << 6, + FONT_HIGHLIGHT_REM = 0x05 << 6, + FONT_HIGHLIGHT_KEY = 0x06 << 6, + FONT_HIGHLIGHT_TABLE = 0x07 << 6, }; /** @@ -119,9 +122,9 @@ enum FontMask FONT_MASK_FONT = 0x00f, //! Mask for FontTitle FONT_MASK_TITLE = 0x030, - //! Mask for FontColor - FONT_MASK_COLOR = 0x1c0, - //! Mask for image bit + //! Mask for FontHighlight + FONT_MASK_HIGHLIGHT = 0x1c0, + //! Mask for image bit (TODO: not used?) FONT_MASK_IMAGE = 0x200 }; @@ -190,7 +193,17 @@ struct MultisizeFont \class CText \brief Text rendering engine - ... */ + CText is responsible for drawing text in 2D interface. Font rendering is done using + textures generated by SDL_ttf from TTF font files. + + All functions rendering text are divided into two types: + - single font - function takes a single Gfx::FontType argument that (along with size) + determines the font to be used for all characters, + - multi-font - function takes the text as one argument and a std::vector of FontMetaChar + with per-character formatting information (font, highlights and some other info used by CEdit) + + All font rendering is done in UTF-8. +*/ class CText { public: @@ -213,20 +226,20 @@ public: //! Draws text (multi-format) void DrawText(const std::string &text, const std::vector &format, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol); + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol); //! Draws text (one font) void DrawText(const std::string &text, Gfx::FontType font, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol); + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol); //! Calculates dimensions for text (multi-format) void SizeText(const std::string &text, const std::vector &format, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end); //! Calculates dimensions for text (one font) void SizeText(const std::string &text, Gfx::FontType font, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end); //! Returns the ascent font metric @@ -242,7 +255,7 @@ public: //! Returns width of string (single font) float GetStringWidth(const std::string &text, Gfx::FontType font, float size); //! Returns width of single character - float GetCharWidth(int character, Gfx::FontType font, float size, float offset); + float GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, float offset); //! Justifies a line of text (multi-format) int Justify(const std::string &text, const std::vector &format, @@ -256,16 +269,16 @@ public: //! Returns the most suitable position to a given offset (one font) int Detect(const std::string &text, Gfx::FontType font, float size, float offset); -public: // for testing! +protected: Gfx::CachedFont* GetOrOpenFont(Gfx::FontType type, float size); - Gfx::CharTexture CreateCharTexture(const char* utf8Char, Gfx::CachedFont* font); + Gfx::CharTexture CreateCharTexture(Gfx::UTF8Char ch, Gfx::CachedFont* font); void DrawString(const std::string &text, const std::vector &format, float size, Math::Point pos, float width, int eol); void DrawString(const std::string &text, Gfx::FontType font, float size, Math::Point pos, float width, int eol); - void DrawColor(int color, float size, Math::Point pos, float width); - void DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos); + void DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size); + void DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math::Point &pos); protected: CInstanceManager* m_iMan; diff --git a/src/math/intpoint.h b/src/math/intpoint.h index a760bc2..476e67b 100644 --- a/src/math/intpoint.h +++ b/src/math/intpoint.h @@ -32,11 +32,11 @@ namespace Math { struct IntPoint { //! X coord - long x; + int x; //! Y coord - long y; + int y; - IntPoint(long aX = 0, long aY = 0) : x(aX), y(aY) {} + IntPoint(int aX = 0, int aY = 0) : x(aX), y(aY) {} }; /* @} */ // end of group diff --git a/src/math/intsize.h b/src/math/intsize.h index d53de85..c88f09b 100644 --- a/src/math/intsize.h +++ b/src/math/intsize.h @@ -34,9 +34,9 @@ namespace Math struct IntSize { //! Width - long w; + int w; //! Height - long h; + int h; //! Constructs a zero size: (0,0) inline IntSize() @@ -45,7 +45,7 @@ struct IntSize } //! Constructs a size from given dimensions: (w,h) - inline explicit IntSize(long w, long h) + inline explicit IntSize(int w, int h) { this->w = w; this->h = h; -- cgit v1.2.3-1-g7c22