X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fcguittfont%2FCGUITTFont.cpp;h=c2d37c6c0dda0b3f61666d65810f52326e1bdfab;hb=3955f512538ca7c6f2d2187f22d5a696da8e84d3;hp=fb8199e2104791f7644a4cdddf9b6073015f0eba;hpb=30b9a4d6b479ecfcb84d4803f5d15ee9b6c7edd6;p=oweals%2Fminetest.git diff --git a/src/cguittfont/CGUITTFont.cpp b/src/cguittfont/CGUITTFont.cpp index fb8199e21..c2d37c6c0 100644 --- a/src/cguittfont/CGUITTFont.cpp +++ b/src/cguittfont/CGUITTFont.cpp @@ -1,6 +1,7 @@ /* CGUITTFont FreeType class for Irrlicht Copyright (c) 2009-2010 John Norman + Copyright (c) 2016 Nathanaël Courant This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -29,6 +30,7 @@ */ #include +#include #include "CGUITTFont.h" namespace irr @@ -64,8 +66,24 @@ scene::SMesh CGUITTFont::shared_plane_; // +/** Checks that no dimension of the FT_BitMap object is negative. If either is + * negative, abort execution. + */ +inline void checkFontBitmapSize(const FT_Bitmap &bits) +{ + if ((s32)bits.rows < 0 || (s32)bits.width < 0) { + std::cout << "Insane font glyph size. File: " + << __FILE__ << " Line " << __LINE__ + << std::endl; + abort(); + } +} + video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const { + // Make sure our casts to s32 in the loops below will not cause problems + checkFontBitmapSize(bits); + // Determine what our texture size should be. // Add 1 because textures are inclusive-exclusive. core::dimension2du d(bits.width + 1, bits.rows + 1); @@ -87,10 +105,11 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide const u32 image_pitch = image->getPitch() / sizeof(u16); u16* image_data = (u16*)image->lock(); u8* glyph_data = bits.buffer; - for (s32 y = 0; y < bits.rows; ++y) + + for (s32 y = 0; y < (s32)bits.rows; ++y) { u16* row = image_data; - for (s32 x = 0; x < bits.width; ++x) + for (s32 x = 0; x < (s32)bits.width; ++x) { // Monochrome bitmaps store 8 pixels per byte. The left-most pixel is the bit 0x80. // So, we go through the data each bit at a time. @@ -116,10 +135,10 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide const u32 image_pitch = image->getPitch() / sizeof(u32); u32* image_data = (u32*)image->lock(); u8* glyph_data = bits.buffer; - for (s32 y = 0; y < bits.rows; ++y) + for (s32 y = 0; y < (s32)bits.rows; ++y) { u8* row = glyph_data; - for (s32 x = 0; x < bits.width; ++x) + for (s32 x = 0; x < (s32)bits.width; ++x) { image_data[y * image_pitch + x] |= static_cast(255.0f * (static_cast(*row++) / gray_count)) << 24; //data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24); @@ -199,7 +218,7 @@ void SGUITTGlyph::unload() ////////////////////// -CGUITTFont* CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias, const bool transparency) +CGUITTFont* CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias, const bool transparency, const u32 shadow, const u32 shadow_alpha) { if (!c_libraryLoaded) { @@ -216,6 +235,9 @@ CGUITTFont* CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path& filen return 0; } + font->shadow_offset = shadow; + font->shadow_alpha = shadow_alpha; + return font; } @@ -524,6 +546,13 @@ void CGUITTFont::setFontHinting(const bool enable, const bool enable_auto_hintin void CGUITTFont::draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip) { + draw(EnrichedString(std::wstring(text.c_str()), color), position, color, hcenter, vcenter, clip); +} + +void CGUITTFont::draw(const EnrichedString &text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip) +{ + std::vector colors = text.getColors(); + if (!Driver) return; @@ -551,7 +580,7 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect& position } // Convert to a unicode string. - core::ustring utext(text); + core::ustring utext = text.getString(); // Set up our render map. core::map Render_Map; @@ -560,37 +589,38 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect& position u32 n; uchar32_t previousChar = 0; core::ustring::const_iterator iter(utext); + std::vector applied_colors; while (!iter.atEnd()) { uchar32_t currentChar = *iter; n = getGlyphIndexByChar(currentChar); bool visible = (Invisible.findFirst(currentChar) == -1); - if (n > 0 && visible) + bool lineBreak=false; + if (currentChar == L'\r') // Mac or Windows breaks { - bool lineBreak=false; - if (currentChar == L'\r') // Mac or Windows breaks - { - lineBreak = true; - if (*(iter + 1) == (uchar32_t)'\n') // Windows line breaks. - currentChar = *(++iter); - } - else if (currentChar == (uchar32_t)'\n') // Unix breaks - { - lineBreak = true; - } + lineBreak = true; + if (*(iter + 1) == (uchar32_t)'\n') // Windows line breaks. + currentChar = *(++iter); + } + else if (currentChar == (uchar32_t)'\n') // Unix breaks + { + lineBreak = true; + } - if (lineBreak) - { - previousChar = 0; - offset.Y += font_metrics.ascender / 64; - offset.X = position.UpperLeftCorner.X; + if (lineBreak) + { + previousChar = 0; + offset.Y += font_metrics.height / 64; + offset.X = position.UpperLeftCorner.X; - if (hcenter) - offset.X += (position.getWidth() - textDimension.Width) >> 1; - ++iter; - continue; - } + if (hcenter) + offset.X += (position.getWidth() - textDimension.Width) >> 1; + ++iter; + continue; + } + if (n > 0 && visible) + { // Calculate the glyph offset. s32 offx = Glyphs[n-1].offset.X; s32 offy = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y; @@ -606,6 +636,9 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect& position page->render_positions.push_back(core::position2di(offset.X + offx, offset.Y + offy)); page->render_source_rects.push_back(glyph.source_rect); 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); @@ -624,8 +657,24 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect& position CGUITTGlyphPage* page = n->getValue(); - if (!use_transparency) color.color |= 0xff000000; - Driver->draw2DImageBatch(page->texture, page->render_positions, page->render_source_rects, clip, color, true); + if (shadow_offset) { + for (size_t i = 0; i < page->render_positions.size(); ++i) + page->render_positions[i] += core::vector2di(shadow_offset, shadow_offset); + Driver->draw2DImageBatch(page->texture, page->render_positions, page->render_source_rects, clip, video::SColor(shadow_alpha,0,0,0), true); + for (size_t i = 0; i < page->render_positions.size(); ++i) + page->render_positions[i] -= core::vector2di(shadow_offset, shadow_offset); + } + 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); + } + if (!use_transparency) + col.color |= 0xff000000; + Driver->draw2DImage(page->texture, page->render_positions[i], page->render_source_rects[i], clip, col, true); + } } }