aboutsummaryrefslogtreecommitdiff
path: root/src/irrlicht_changes/CGUITTFont.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/irrlicht_changes/CGUITTFont.cpp')
-rw-r--r--src/irrlicht_changes/CGUITTFont.cpp117
1 files changed, 85 insertions, 32 deletions
diff --git a/src/irrlicht_changes/CGUITTFont.cpp b/src/irrlicht_changes/CGUITTFont.cpp
index bd4e700de..e785ea837 100644
--- a/src/irrlicht_changes/CGUITTFont.cpp
+++ b/src/irrlicht_changes/CGUITTFont.cpp
@@ -103,7 +103,7 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide
// Load the monochrome data in.
const u32 image_pitch = image->getPitch() / sizeof(u16);
- u16* image_data = (u16*)image->lock();
+ u16* image_data = (u16*)image->getData();
u8* glyph_data = bits.buffer;
for (s32 y = 0; y < (s32)bits.rows; ++y)
@@ -119,7 +119,6 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide
}
image_data += image_pitch;
}
- image->unlock();
break;
}
@@ -133,7 +132,7 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide
// Load the grayscale data in.
const float gray_count = static_cast<float>(bits.num_grays);
const u32 image_pitch = image->getPitch() / sizeof(u32);
- u32* image_data = (u32*)image->lock();
+ u32* image_data = (u32*)image->getData();
u8* glyph_data = bits.buffer;
for (s32 y = 0; y < (s32)bits.rows; ++y)
{
@@ -145,7 +144,6 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide
}
glyph_data += bits.pitch;
}
- image->unlock();
break;
}
default:
@@ -277,7 +275,8 @@ CGUITTFont* CGUITTFont::create(IrrlichtDevice *device, const io::path& filename,
//! Constructor.
CGUITTFont::CGUITTFont(IGUIEnvironment *env)
: use_monochrome(false), use_transparency(true), use_hinting(true), use_auto_hinting(true),
-batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
+batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0),
+shadow_offset(0), shadow_alpha(0), fallback(0)
{
#ifdef _DEBUG
setDebugName("CGUITTFont");
@@ -548,12 +547,12 @@ void CGUITTFont::setFontHinting(const bool enable, const bool enable_auto_hintin
void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
{
- draw(EnrichedString(std::wstring(text.c_str()), color), position, color, hcenter, vcenter, clip);
+ draw(EnrichedString(std::wstring(text.c_str()), color), position, hcenter, vcenter, clip);
}
-void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
+void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& position, bool hcenter, bool vcenter, const core::rect<s32>* clip)
{
- std::vector<video::SColor> colors = text.getColors();
+ const std::vector<video::SColor> &colors = text.getColors();
if (!Driver)
return;
@@ -563,6 +562,7 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& positio
{
Glyph_Pages[i]->render_positions.clear();
Glyph_Pages[i]->render_source_rects.clear();
+ Glyph_Pages[i]->render_colors.clear();
}
// Set up some variables.
@@ -591,7 +591,6 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& positio
u32 n;
uchar32_t previousChar = 0;
core::ustring::const_iterator iter(utext);
- std::vector<video::SColor> applied_colors;
while (!iter.atEnd())
{
uchar32_t currentChar = *iter;
@@ -637,12 +636,36 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& positio
CGUITTGlyphPage* const page = Glyph_Pages[glyph.glyph_page];
page->render_positions.push_back(core::position2di(offset.X + offx, offset.Y + offy));
page->render_source_rects.push_back(glyph.source_rect);
+ if (iter.getPos() < colors.size())
+ page->render_colors.push_back(colors[iter.getPos()]);
+ else
+ page->render_colors.push_back(video::SColor(255,255,255,255));
Render_Map.set(glyph.glyph_page, page);
- u32 current_color = iter.getPos();
- if (current_color < colors.size())
- applied_colors.push_back(colors[current_color]);
}
- offset.X += getWidthFromCharacter(currentChar);
+ if (n > 0)
+ {
+ offset.X += getWidthFromCharacter(currentChar);
+ }
+ else if (fallback != 0)
+ {
+ // Let the fallback font draw it, this isn't super efficient but hopefully that doesn't matter
+ wchar_t l1[] = { (wchar_t) currentChar, 0 }, l2 = (wchar_t) previousChar;
+
+ if (visible)
+ {
+ // Apply kerning.
+ offset.X += fallback->getKerningWidth(l1, &l2);
+ offset.Y += fallback->getKerningHeight();
+
+ u32 current_color = iter.getPos();
+ fallback->draw(core::stringw(l1),
+ core::rect<s32>({offset.X-1, offset.Y-1}, position.LowerRightCorner), // ???
+ current_color < colors.size() ? colors[current_color] : video::SColor(255, 255, 255, 255),
+ false, false, clip);
+ }
+
+ offset.X += fallback->getDimension(l1).Width;
+ }
previousChar = currentChar;
++iter;
@@ -666,16 +689,24 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& positio
for (size_t i = 0; i < page->render_positions.size(); ++i)
page->render_positions[i] -= core::vector2di(shadow_offset, shadow_offset);
}
+ // render runs of matching color in batch
+ size_t ibegin;
+ video::SColor colprev;
for (size_t i = 0; i < page->render_positions.size(); ++i) {
- irr::video::SColor col;
- if (!applied_colors.empty()) {
- col = applied_colors[i < applied_colors.size() ? i : 0];
- } else {
- col = irr::video::SColor(255, 255, 255, 255);
- }
+ ibegin = i;
+ colprev = page->render_colors[i];
+ do
+ ++i;
+ while (i < page->render_positions.size() && page->render_colors[i] == colprev);
+ core::array<core::vector2di> tmp_positions;
+ core::array<core::recti> tmp_source_rects;
+ tmp_positions.set_pointer(&page->render_positions[ibegin], i - ibegin, false, false); // no copy
+ tmp_source_rects.set_pointer(&page->render_source_rects[ibegin], i - ibegin, false, false);
+ --i;
+
if (!use_transparency)
- col.color |= 0xff000000;
- Driver->draw2DImage(page->texture, page->render_positions[i], page->render_source_rects[i], clip, col, true);
+ colprev.color |= 0xff000000;
+ Driver->draw2DImageBatch(page->texture, tmp_positions, tmp_source_rects, clip, colprev, true);
}
}
}
@@ -768,6 +799,12 @@ inline u32 CGUITTFont::getWidthFromCharacter(uchar32_t c) const
int w = Glyphs[n-1].advance.x / 64;
return w;
}
+ if (fallback != 0)
+ {
+ wchar_t s[] = { (wchar_t) c, 0 };
+ return fallback->getDimension(s).Width;
+ }
+
if (c >= 0x2000)
return (font_metrics.ascender / 64);
else return (font_metrics.ascender / 64) / 2;
@@ -791,6 +828,12 @@ inline u32 CGUITTFont::getHeightFromCharacter(uchar32_t c) const
s32 height = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y + Glyphs[n-1].source_rect.getHeight();
return height;
}
+ if (fallback != 0)
+ {
+ wchar_t s[] = { (wchar_t) c, 0 };
+ return fallback->getDimension(s).Height;
+ }
+
if (c >= 0x2000)
return (font_metrics.ascender / 64);
else return (font_metrics.ascender / 64) / 2;
@@ -806,9 +849,9 @@ u32 CGUITTFont::getGlyphIndexByChar(uchar32_t c) const
// Get the glyph.
u32 glyph = FT_Get_Char_Index(tt_face, c);
- // Check for a valid glyph. If it is invalid, attempt to use the replacement character.
+ // Check for a valid glyph.
if (glyph == 0)
- glyph = FT_Get_Char_Index(tt_face, core::unicode::UTF_REPLACEMENT_CHARACTER);
+ return 0;
// If our glyph is already loaded, don't bother doing any batch loading code.
if (glyph != 0 && Glyphs[glyph - 1].isLoaded)
@@ -924,13 +967,26 @@ core::vector2di CGUITTFont::getKerning(const uchar32_t thisLetter, const uchar32
core::vector2di ret(GlobalKerningWidth, GlobalKerningHeight);
+ u32 n = getGlyphIndexByChar(thisLetter);
+
+ // If we don't have this glyph, ask fallback font
+ if (n == 0)
+ {
+ if (fallback != 0) {
+ wchar_t l1 = (wchar_t) thisLetter, l2 = (wchar_t) previousLetter;
+ ret.X = fallback->getKerningWidth(&l1, &l2);
+ ret.Y = fallback->getKerningHeight();
+ }
+ return ret;
+ }
+
// If we don't have kerning, no point in continuing.
if (!FT_HAS_KERNING(tt_face))
return ret;
// Get the kerning information.
FT_Vector v;
- FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), getGlyphIndexByChar(thisLetter), FT_KERNING_DEFAULT, &v);
+ FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), n, FT_KERNING_DEFAULT, &v);
// If we have a scalable font, the return value will be in font points.
if (FT_IS_SCALABLE(tt_face))
@@ -962,6 +1018,9 @@ void CGUITTFont::setInvisibleCharacters(const core::ustring& s)
video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch)
{
u32 n = getGlyphIndexByChar(ch);
+ if (n == 0)
+ n = getGlyphIndexByChar((uchar32_t) core::unicode::UTF_REPLACEMENT_CHARACTER);
+
const SGUITTGlyph& glyph = Glyphs[n-1];
CGUITTGlyphPage* page = Glyph_Pages[glyph.glyph_page];
@@ -971,11 +1030,7 @@ video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch)
video::ITexture* tex = page->texture;
// Acquire a read-only lock of the corresponding page texture.
- #if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR>=8
void* ptr = tex->lock(video::ETLM_READ_ONLY);
- #else
- void* ptr = tex->lock(true);
- #endif
video::ECOLOR_FORMAT format = tex->getColorFormat();
core::dimension2du tex_size = tex->getOriginalSize();
@@ -1132,11 +1187,7 @@ core::array<scene::ISceneNode*> CGUITTFont::addTextSceneNode(const wchar_t* text
// Now we copy planes corresponding to the letter size.
IMeshManipulator* mani = smgr->getMeshManipulator();
IMesh* meshcopy = mani->createMeshCopy(shared_plane_ptr_);
- #if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR>=8
mani->scale(meshcopy, vector3df((f32)letter_size.Width, (f32)letter_size.Height, 1));
- #else
- mani->scaleMesh(meshcopy, vector3df((f32)letter_size.Width, (f32)letter_size.Height, 1));
- #endif
ISceneNode* current_node = smgr->addMeshSceneNode(meshcopy, parent, -1, current_pos);
meshcopy->drop();
@@ -1149,6 +1200,8 @@ core::array<scene::ISceneNode*> CGUITTFont::addTextSceneNode(const wchar_t* text
container.push_back(current_node);
}
offset.X += getWidthFromCharacter(current_char);
+ // Note that fallback font handling is missing here (Minetest never uses this)
+
previous_char = current_char;
++text;
}