]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/irrlicht_changes/CGUITTFont.cpp
Remove unused header includes
[dragonfireclient.git] / src / irrlicht_changes / CGUITTFont.cpp
index bd4e700dec7bbbd3b75698499f0669278d825532..e785ea8373fcd7243b3eca814368ffe1a3ebd539 100644 (file)
@@ -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;
                }