Font rendering

- implemented rest of CText interface excluding some minor features
dev-ui
Piotr Dziwinski 2012-08-06 20:20:50 +02:00
parent 61bfb22f27
commit f7e78b21e9
7 changed files with 523 additions and 171 deletions

View File

@ -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;
}

View File

@ -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<Gfx::FontMetaChar> 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 */

View File

@ -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();

View File

@ -150,118 +150,254 @@ void Gfx::CText::FlushCache()
}
void Gfx::CText::DrawText(const std::string &text, const std::vector<FontMetaChar> &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<FontMetaChar> &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<FontMetaChar> &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<Gfx::FontType>(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<FontMetaChar> &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<Gfx::FontType>(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;
}
int Gfx::CText::Detect(const std::string &text, const std::vector<FontMetaChar> &format,
float size, float offset)
{
// TODO
return 0;
}
int Gfx::CText::Detect(const std::string &text, Gfx::FontType font, float size, float offset)
{
// TODO
return 0;
}
void Gfx::CText::DrawString(const std::string &text, const std::vector<FontMetaChar> &format,
float size, Math::Point pos, float width, int eol)
{
// TODO
}
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);
m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true);
m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA);
assert(font != Gfx::FONT_BUTTON);
float pos = 0.0f;
int cut = 0;
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 +409,231 @@ void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font,
index += len;
DrawChar(ch, font, size, screenPos);
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<FontMetaChar> &format,
float size, float offset)
{
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<Gfx::FontType>(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)
{
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<FontMetaChar> &format,
float size, Math::Point pos, float width, int eol)
{
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<Gfx::FontType>(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<Gfx::FontHighlight>(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)
{
assert(font != Gfx::FONT_BUTTON);
m_engine->SetState(Gfx::ENG_RSTATE_TEXT);
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;
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];
int icon = -1;
switch (color)
// TODO: switch to alpha factors
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;
break;
case Gfx::FONT_COLOR_TYPE:
icon = 5;
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_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;
if ( color == COLOR_LINK )
{
m_engine->SetState(D3DSTATENORMAL);
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;
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;
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;
m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false);
dp = 0.5f/256.0f;
u1 += dp;
v1 += dp;
u2 -= dp;
v2 -= dp;
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)

View File

@ -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<Gfx::FontMetaChar> &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<Gfx::FontMetaChar> &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<Gfx::FontMetaChar> &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<Gfx::FontMetaChar> &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;

View File

@ -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

View File

@ -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;