Add color emoji
This commit is contained in:
parent
89e3bcd11b
commit
28cc2838a8
@ -544,7 +544,8 @@
|
||||
using industry standard nowadays...
|
||||
-->
|
||||
<fonts-list normal-ttf="Cantarell-Regular.otf wqy-microhei.ttf NotoSansThai-Regular.ttf NotoSansHebrew-Regular.ttf NotoNaskhArabicUI-Regular.ttf"
|
||||
digit-ttf="SigmarOne.otf" />
|
||||
digit-ttf="SigmarOne.otf"
|
||||
color-emoji-ttf="NotoColorEmoji.ttf"/>
|
||||
|
||||
<!-- Maximum bones from all animated meshes in each frame to be uploaded for
|
||||
hardware skinning, For gles 3.0 the specification guarantees at least 2048, for
|
||||
|
@ -3,7 +3,7 @@ wqyMicroHei is released under the GPLv3 with font embedding exception and Apache
|
||||
Copyright (C) 2008-2009 The WenQuanYi Project Board of Trustees
|
||||
Copyright (C) 2007 Google Corporation
|
||||
|
||||
Noto Sans Thai, Noto Sans Hebrew and Noto Naskh Arabic UI are released under SIL open font license 1.1 ( https://www.google.com/get/noto/ )
|
||||
Noto Sans Thai, Noto Sans Hebrew, Noto Naskh Arabic UI and Noto Color Emoji are released under SIL open font license 1.1 ( https://www.google.com/get/noto/ )
|
||||
|
||||
Noto is a trademark of Google Inc. Noto fonts are open source. All Noto fonts are published under the SIL Open Font License, Version 1.1. Language data and some sample texts are from the Unicode CLDR project.
|
||||
|
||||
|
BIN
data/ttf/NotoColorEmoji.ttf
Normal file
BIN
data/ttf/NotoColorEmoji.ttf
Normal file
Binary file not shown.
@ -23,7 +23,8 @@ GLF_RTL_LINE = 1, /* This line from this glyph is RTL. */
|
||||
GLF_RTL_CHAR = 2, /* This character(s) from this glyph is RTL. */
|
||||
GLF_BREAKABLE = 4, /* This glyph is breakable when line breaking. */
|
||||
GLF_QUICK_DRAW = 8, /* This glyph is not created by libraqm, which get x_advance_x directly from font. */
|
||||
GLF_NEWLINE = 16 /* This glyph will start a newline. */
|
||||
GLF_NEWLINE = 16, /* This glyph will start a newline. */
|
||||
GLF_COLORED = 32 /* This glyph is a colored one (for example emoji). */
|
||||
};
|
||||
|
||||
enum GlyphLayoutDraw
|
||||
|
@ -505,6 +505,7 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
{
|
||||
fonts_list->get("normal-ttf", &m_normal_ttf);
|
||||
fonts_list->get("digit-ttf", &m_digit_ttf );
|
||||
fonts_list->get("color-emoji-ttf", &m_color_emoji_ttf);
|
||||
}
|
||||
|
||||
if (const XMLNode *skinning = root->getNode("skinning"))
|
||||
|
@ -209,6 +209,7 @@ public:
|
||||
/** Lists of TTF files used in STK. */
|
||||
std::vector<std::string> m_normal_ttf;
|
||||
std::vector<std::string> m_digit_ttf;
|
||||
std::string m_color_emoji_ttf;
|
||||
|
||||
/** Configurable values used in SmoothNetworkBody class. */
|
||||
float m_snb_min_adjust_length, m_snb_max_adjust_length,
|
||||
|
@ -17,6 +17,8 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "font/bold_face.hpp"
|
||||
#include "font/font_manager.hpp"
|
||||
#include "font/regular_face.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor of BoldFace.
|
||||
@ -33,10 +35,10 @@ void BoldFace::init()
|
||||
// Reserve some space for characters added later
|
||||
m_font_max_height = m_glyph_max_height * 3 / 2;
|
||||
|
||||
/* Use FT_Outline_Embolden for now, no more fallback font
|
||||
setFallbackFont(font_manager->getFont<RegularFace>());
|
||||
setFallbackFontScale(2.0f);*/
|
||||
|
||||
// Fallback font for emoji
|
||||
RegularFace* rf = font_manager->getFont<RegularFace>();
|
||||
setFallbackFont(rf);
|
||||
setFallbackFontScale((float)getDPI() / (float)rf->getDPI());
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -368,8 +368,11 @@ void FontManager::shape(const std::u32string& text,
|
||||
break;
|
||||
}
|
||||
}
|
||||
checkFTError(FT_Set_Pixel_Sizes(cur_face, 0,
|
||||
m_shaping_dpi), "setting DPI");
|
||||
if (!FT_HAS_COLOR(cur_face))
|
||||
{
|
||||
checkFTError(FT_Set_Pixel_Sizes(cur_face, 0,
|
||||
m_shaping_dpi), "setting DPI");
|
||||
}
|
||||
if (!raqm_set_freetype_face_range(rq, cur_face, i, 1))
|
||||
{
|
||||
Log::error("FontManager",
|
||||
@ -409,6 +412,8 @@ void FontManager::shape(const std::u32string& text,
|
||||
gl.flags |= gui::GLF_RTL_CHAR;
|
||||
if (breakable[glyphs[idx].cluster])
|
||||
gl.flags |= gui::GLF_BREAKABLE;
|
||||
if (FT_HAS_COLOR(glyphs[idx].ftface))
|
||||
gl.flags |= gui::GLF_COLORED;
|
||||
cur_line.push_back(gl);
|
||||
}
|
||||
// Sort glyphs in logical order
|
||||
@ -489,6 +494,33 @@ void FontManager::initGlyphLayouts(const core::stringw& text,
|
||||
shape(StringUtils::wideToUtf32(text), cached_gls);
|
||||
gls = cached_gls;
|
||||
} // initGlyphLayouts
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
FT_Face FontManager::loadColorEmoji()
|
||||
{
|
||||
if (stk_config->m_color_emoji_ttf.empty())
|
||||
return NULL;
|
||||
FT_Face face = NULL;
|
||||
const std::string loc = file_manager->getAssetChecked(FileManager::TTF,
|
||||
stk_config->m_color_emoji_ttf.c_str(), true);
|
||||
font_manager->checkFTError(FT_New_Face(
|
||||
m_ft_library, loc.c_str(), 0, &face), loc + " is loaded");
|
||||
|
||||
if (!FT_HAS_COLOR(face) || face->num_fixed_sizes == 0)
|
||||
{
|
||||
Log::error("FontManager", "Bad %s color emoji, ignored.",
|
||||
stk_config->m_color_emoji_ttf.c_str());
|
||||
checkFTError(FT_Done_Face(face), "removing faces for emoji");
|
||||
return NULL;
|
||||
}
|
||||
// Use the largest size available, it will be scaled to regular face ttf
|
||||
// when loading the glyph, so it can reduce the blurring effect
|
||||
m_shaping_dpi = face->available_sizes[face->num_fixed_sizes - 1].height;
|
||||
checkFTError(FT_Select_Size(face, face->num_fixed_sizes - 1),
|
||||
"setting color emoji size");
|
||||
return face;
|
||||
} // loadColorEmoji
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -499,11 +531,25 @@ void FontManager::loadFonts()
|
||||
#ifndef SERVER_ONLY
|
||||
// First load the TTF files required by each font
|
||||
std::vector<FT_Face> normal_ttf = loadTTF(stk_config->m_normal_ttf);
|
||||
// We use 16bit face idx in GlyphLayout class
|
||||
if (normal_ttf.size() > 65535)
|
||||
normal_ttf.resize(65535);
|
||||
for (uint16_t i = 0; i < normal_ttf.size(); i++)
|
||||
m_ft_faces_to_index[normal_ttf[i]] = i;
|
||||
std::vector<FT_Face> bold_ttf = normal_ttf;
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
assert(!normal_ttf.empty());
|
||||
FT_Face color_emoji = loadColorEmoji();
|
||||
if (!normal_ttf.empty() && color_emoji != NULL)
|
||||
{
|
||||
// Put color emoji after 1st default font so can use it before wqy
|
||||
// font
|
||||
normal_ttf.insert(normal_ttf.begin() + 1, color_emoji);
|
||||
// We don't use color emoji in bold font
|
||||
bold_ttf.insert(bold_ttf.begin() + 1, NULL);
|
||||
}
|
||||
// We use 16bit face idx in GlyphLayout class
|
||||
if (normal_ttf.size() > 65535)
|
||||
normal_ttf.resize(65535);
|
||||
for (uint16_t i = 0; i < normal_ttf.size(); i++)
|
||||
m_ft_faces_to_index[normal_ttf[i]] = i;
|
||||
}
|
||||
|
||||
std::vector<FT_Face> digit_ttf = loadTTF(stk_config->m_digit_ttf);
|
||||
if (!digit_ttf.empty())
|
||||
@ -522,7 +568,7 @@ void FontManager::loadFonts()
|
||||
|
||||
BoldFace* bold = new BoldFace();
|
||||
#ifndef SERVER_ONLY
|
||||
bold->getFaceTTF()->loadTTF(normal_ttf);
|
||||
bold->getFaceTTF()->loadTTF(bold_ttf);
|
||||
#endif
|
||||
bold->init();
|
||||
m_fonts.push_back(bold);
|
||||
|
@ -118,6 +118,8 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
std::vector<FT_Face> loadTTF(const std::vector<std::string>& ttf_list);
|
||||
// ------------------------------------------------------------------------
|
||||
FT_Face loadColorEmoji();
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned getShapingDPI() const { return m_shaping_dpi; }
|
||||
// ------------------------------------------------------------------------
|
||||
void shape(const std::u32string& text,
|
||||
|
@ -154,7 +154,7 @@ void FontWithFace::createNewGlyphPage()
|
||||
return;
|
||||
|
||||
uint8_t* data = new uint8_t[getGlyphPageSize() * getGlyphPageSize() *
|
||||
(CVS->isARBTextureSwizzleUsable() ? 1 : 4)]();
|
||||
(CVS->isARBTextureSwizzleUsable() && !useColorGlyphPage() ? 1 : 4)]();
|
||||
#else
|
||||
uint8_t* data = NULL;
|
||||
#endif
|
||||
@ -165,7 +165,7 @@ void FontWithFace::createNewGlyphPage()
|
||||
StringUtils::toString(m_spritebank->getTextureCount()),
|
||||
getGlyphPageSize(),
|
||||
#ifndef SERVER_ONLY
|
||||
CVS->isARBTextureSwizzleUsable()
|
||||
CVS->isARBTextureSwizzleUsable() && !useColorGlyphPage()
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
@ -189,23 +189,41 @@ void FontWithFace::insertGlyph(unsigned font_number, unsigned glyph_index)
|
||||
FT_Face cur_face = m_face_ttf->getFace(font_number);
|
||||
FT_GlyphSlot slot = cur_face->glyph;
|
||||
|
||||
// Same face may be shared across the different FontWithFace,
|
||||
// so reset dpi each time
|
||||
font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()),
|
||||
"setting DPI");
|
||||
if (FT_HAS_COLOR(cur_face))
|
||||
{
|
||||
font_manager->checkFTError(FT_Load_Glyph(cur_face, glyph_index,
|
||||
FT_LOAD_DEFAULT | FT_LOAD_COLOR), "loading a glyph");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Same face may be shared across the different FontWithFace,
|
||||
// so reset dpi each time
|
||||
font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()),
|
||||
"setting DPI");
|
||||
|
||||
font_manager->checkFTError(FT_Load_Glyph(cur_face, glyph_index,
|
||||
FT_LOAD_DEFAULT), "loading a glyph");
|
||||
font_manager->checkFTError(FT_Load_Glyph(cur_face, glyph_index,
|
||||
FT_LOAD_DEFAULT), "loading a glyph");
|
||||
|
||||
font_manager->checkFTError(shapeOutline(&(slot->outline)),
|
||||
"shaping outline");
|
||||
font_manager->checkFTError(shapeOutline(&(slot->outline)),
|
||||
"shaping outline");
|
||||
|
||||
font_manager->checkFTError(FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL),
|
||||
"rendering a glyph to bitmap");
|
||||
font_manager->checkFTError(FT_Render_Glyph(slot,
|
||||
FT_RENDER_MODE_NORMAL), "rendering a glyph to bitmap");
|
||||
}
|
||||
|
||||
// Convert to an anti-aliased bitmap
|
||||
FT_Bitmap* bits = &(slot->bitmap);
|
||||
core::dimension2du texture_size(bits->width + 1, bits->rows + 1);
|
||||
float scale_ratio = 1.0f;
|
||||
unsigned cur_glyph_width = bits->width;
|
||||
unsigned cur_glyph_height = bits->rows;
|
||||
if (bits->pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||
{
|
||||
scale_ratio =
|
||||
(float)getDPI() / (float)font_manager->getShapingDPI();
|
||||
cur_glyph_width = (unsigned)(bits->width * scale_ratio);
|
||||
cur_glyph_height = (unsigned)(bits->rows * scale_ratio);
|
||||
}
|
||||
core::dimension2du texture_size(cur_glyph_width + 1, cur_glyph_height + 1);
|
||||
if ((m_used_width + texture_size.Width > getGlyphPageSize() &&
|
||||
m_used_height + m_current_height + texture_size.Height >
|
||||
getGlyphPageSize()) ||
|
||||
@ -223,29 +241,63 @@ void FontWithFace::insertGlyph(unsigned font_number, unsigned glyph_index)
|
||||
m_current_height = 0;
|
||||
}
|
||||
|
||||
const unsigned int cur_tex = m_spritebank->getTextureCount() -1;
|
||||
const unsigned int cur_tex = m_spritebank->getTextureCount() - 1;
|
||||
if (bits->buffer != NULL && !ProfileWorld::isNoGraphics())
|
||||
{
|
||||
video::ITexture* tex = m_spritebank->getTexture(cur_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName());
|
||||
assert(bits->pixel_mode == FT_PIXEL_MODE_GRAY);
|
||||
if (CVS->isARBTextureSwizzleUsable())
|
||||
if (bits->pixel_mode == FT_PIXEL_MODE_GRAY)
|
||||
{
|
||||
if (CVS->isARBTextureSwizzleUsable() && !useColorGlyphPage())
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
|
||||
bits->width, bits->rows, GL_RED, GL_UNSIGNED_BYTE,
|
||||
bits->buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned int size = bits->width * bits->rows;
|
||||
uint8_t* image_data = new uint8_t[size * 4];
|
||||
memset(image_data, 255, size * 4);
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
image_data[4 * i + 3] = bits->buffer[i];
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
|
||||
bits->width, bits->rows, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data);
|
||||
delete[] image_data;
|
||||
}
|
||||
}
|
||||
else if (bits->pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||
{
|
||||
assert(useColorGlyphPage());
|
||||
// Scale it to normal font dpi
|
||||
video::IImage* unscaled = irr_driver->getVideoDriver()
|
||||
->createImageFromData(video::ECF_A8R8G8B8,
|
||||
{ bits->width, bits->rows },
|
||||
bits->buffer, true/*ownForeignMemory*/, false/*deleteMemory*/);
|
||||
assert(unscaled);
|
||||
video::IImage* scaled = irr_driver
|
||||
->getVideoDriver()->createImage(video::ECF_A8R8G8B8,
|
||||
{ cur_glyph_width , cur_glyph_height});
|
||||
assert(scaled);
|
||||
unscaled->copyToScalingBoxFilter(scaled);
|
||||
uint8_t* scaled_data = (uint8_t*)scaled->lock();
|
||||
for (unsigned int i = 0; i < cur_glyph_width * cur_glyph_height;
|
||||
i++)
|
||||
{
|
||||
uint8_t tmp_val = scaled_data[i * 4];
|
||||
scaled_data[i * 4] = scaled_data[i * 4 + 2];
|
||||
scaled_data[i * 4 + 2] = tmp_val;
|
||||
}
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
|
||||
bits->width, bits->rows, GL_RED, GL_UNSIGNED_BYTE,
|
||||
bits->buffer);
|
||||
cur_glyph_width, cur_glyph_height, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
scaled_data);
|
||||
unscaled->drop();
|
||||
scaled->drop();
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned int size = bits->width * bits->rows;
|
||||
uint8_t* image_data = new uint8_t[size * 4];
|
||||
memset(image_data, 255, size * 4);
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
image_data[4 * i + 3] = bits->buffer[i];
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
|
||||
bits->width, bits->rows, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data);
|
||||
delete[] image_data;
|
||||
assert(false && "Invalid pixel mode");
|
||||
}
|
||||
if (tex->hasMipMaps())
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
@ -256,7 +308,7 @@ void FontWithFace::insertGlyph(unsigned font_number, unsigned glyph_index)
|
||||
gui::SGUISpriteFrame f;
|
||||
gui::SGUISprite s;
|
||||
core::rect<s32> rectangle(m_used_width, m_used_height,
|
||||
m_used_width + bits->width, m_used_height + bits->rows);
|
||||
m_used_width + cur_glyph_width, m_used_height + cur_glyph_height);
|
||||
f.rectNumber = m_spritebank->getPositions().size();
|
||||
f.textureNumber = cur_tex;
|
||||
|
||||
@ -268,11 +320,14 @@ void FontWithFace::insertGlyph(unsigned font_number, unsigned glyph_index)
|
||||
|
||||
// Save glyph metrics
|
||||
FontArea a;
|
||||
a.advance_x = cur_face->glyph->advance.x / BEARING;
|
||||
a.bearing_x = cur_face->glyph->metrics.horiBearingX / BEARING;
|
||||
const int cur_height = (cur_face->glyph->metrics.height / BEARING);
|
||||
a.advance_x = (int)
|
||||
(cur_face->glyph->advance.x / BEARING * scale_ratio);
|
||||
a.bearing_x = (int)
|
||||
(cur_face->glyph->metrics.horiBearingX / BEARING * scale_ratio);
|
||||
const int cur_height =
|
||||
(int)(cur_face->glyph->metrics.height / BEARING * scale_ratio);
|
||||
const int cur_offset_y = cur_height -
|
||||
(cur_face->glyph->metrics.horiBearingY / BEARING);
|
||||
(int)(cur_face->glyph->metrics.horiBearingY / BEARING * scale_ratio);
|
||||
a.offset_y = m_glyph_max_height - cur_height + cur_offset_y;
|
||||
a.offset_y_bt = -cur_offset_y;
|
||||
a.spriteno = f.rectNumber;
|
||||
@ -571,7 +626,7 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
|
||||
// Collect character locations
|
||||
const unsigned int text_size = gl.size();
|
||||
core::array<s32> indices(text_size);
|
||||
std::vector<std::pair<s32, bool> > indices;
|
||||
core::array<core::position2d<float>> offsets(text_size);
|
||||
std::vector<bool> fallback(text_size);
|
||||
core::array<core::position2d<float>> gld_offsets;
|
||||
@ -675,7 +730,8 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
offset.Y -= glyph_offset_y;
|
||||
}
|
||||
|
||||
indices.push_back(area->spriteno);
|
||||
indices.emplace_back(area->spriteno,
|
||||
(glyph_layout.flags & gui::GLF_COLORED) != 0);
|
||||
if ((glyph_layout.flags & gui::GLF_QUICK_DRAW) != 0)
|
||||
{
|
||||
offset.X += glyph_layout.x_advance * scale;
|
||||
@ -740,10 +796,10 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
|
||||
for (int n = 0; n < indice_amount; n++)
|
||||
{
|
||||
const int sprite_id = indices[n];
|
||||
const int sprite_id = indices[n].first;
|
||||
if (!fallback[n] && (sprite_id < 0 || sprite_id >= sprite_amount))
|
||||
continue;
|
||||
if (indices[n] == -1) continue;
|
||||
if (indices[n].first == -1) continue;
|
||||
|
||||
const int tex_id = (fallback[n] ?
|
||||
(*fallback_sprites)[sprite_id].Frames[0].textureNumber :
|
||||
@ -783,12 +839,33 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
}
|
||||
}
|
||||
|
||||
std::array<video::SColor, 4> white =
|
||||
{ {
|
||||
video::SColor(-1), video::SColor(-1),
|
||||
video::SColor(-1), video::SColor(-1)
|
||||
} };
|
||||
video::SColor top = GUIEngine::getSkin()->getColor("font::top");
|
||||
video::SColor bottom = GUIEngine::getSkin()->getColor("font::bottom");
|
||||
top.setAlpha(color.getAlpha());
|
||||
bottom.setAlpha(color.getAlpha());
|
||||
|
||||
std::array<video::SColor, 4> title_colors;
|
||||
if (CVS->isGLSL())
|
||||
title_colors = { { top, bottom, top, bottom } };
|
||||
else
|
||||
title_colors = { { bottom, top, top, bottom } };
|
||||
|
||||
video::SColor text_marked = GUIEngine::getSkin()->getColor(
|
||||
"text_field::background_marked");
|
||||
video::SColor text_neutral = GUIEngine::getSkin()->getColor(
|
||||
"text_field::neutral");
|
||||
|
||||
for (int n = 0; n < indice_amount; n++)
|
||||
{
|
||||
const int sprite_id = indices[n];
|
||||
const int sprite_id = indices[n].first;
|
||||
if (!fallback[n] && (sprite_id < 0 || sprite_id >= sprite_amount))
|
||||
continue;
|
||||
if (indices[n] == -1) continue;
|
||||
if (indices[n].first == -1) continue;
|
||||
|
||||
const int tex_id = (fallback[n] ?
|
||||
(*fallback_sprites)[sprite_id].Frames[0].textureNumber :
|
||||
@ -810,44 +887,33 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
m_fallback_font->m_spritebank->getTexture(tex_id) :
|
||||
m_spritebank->getTexture(tex_id));
|
||||
|
||||
if (fallback[n] || isBold())
|
||||
const bool is_colored = indices[n].second;
|
||||
if (isBold())
|
||||
{
|
||||
video::SColor top = GUIEngine::getSkin()->getColor("font::top");
|
||||
video::SColor bottom = GUIEngine::getSkin()
|
||||
->getColor("font::bottom");
|
||||
top.setAlpha(color.getAlpha());
|
||||
bottom.setAlpha(color.getAlpha());
|
||||
|
||||
std::array<video::SColor, 4> title_colors;
|
||||
if (CVS->isGLSL())
|
||||
{
|
||||
title_colors = { { top, bottom, top, bottom } };
|
||||
}
|
||||
else
|
||||
{
|
||||
title_colors = { { bottom, top, top, bottom } };
|
||||
}
|
||||
if (char_collector != NULL)
|
||||
{
|
||||
char_collector->collectChar(texture, dest, source,
|
||||
title_colors.data());
|
||||
is_colored ? white.data() : title_colors.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
draw2DImage(texture, dest, source, clip, title_colors.data(),
|
||||
true);
|
||||
draw2DImage(texture, dest, source, clip,
|
||||
is_colored ? white.data() : title_colors.data(), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (char_collector != NULL)
|
||||
{
|
||||
video::SColor colors[] = {color, color, color, color};
|
||||
char_collector->collectChar(texture, dest, source, colors);
|
||||
std::array<video::SColor, 4> single_color =
|
||||
{ {color, color, color, color} };
|
||||
char_collector->collectChar(texture, dest, source,
|
||||
is_colored ? white.data() : single_color.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
draw2DImage(texture, dest, source, clip, color, true);
|
||||
draw2DImage(texture, dest, source, clip,
|
||||
is_colored ? video::SColor(-1) : color, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -858,18 +924,16 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
core::rect<s32> gld((s32)gld_offsets[i].X, (s32)gld_offsets[i].Y,
|
||||
(s32)gld_offsets[i + 1].X,
|
||||
(s32)(gld_offsets[i + 1].Y + m_font_max_height * scale));
|
||||
GL32_draw2DRectangle(GUIEngine::getSkin()->getColor(
|
||||
"text_field::background_marked"), gld, clip);
|
||||
GL32_draw2DRectangle(text_marked, gld, clip);
|
||||
}
|
||||
else if (df_used == gui::GLD_COMPOSING)
|
||||
{
|
||||
float line1 = m_font_max_height * scale * 0.88f;
|
||||
float line2 = m_font_max_height * scale * 0.92f;
|
||||
core::rect<s32> gld((s32)gld_offsets[i].X, (s32)gld_offsets[i].Y + line1,
|
||||
(s32)gld_offsets[i + 1].X,
|
||||
core::rect<s32> gld((s32)gld_offsets[i].X,
|
||||
(s32)gld_offsets[i].Y + line1, (s32)gld_offsets[i + 1].X,
|
||||
(s32)(gld_offsets[i + 1].Y + line2));
|
||||
GL32_draw2DRectangle(GUIEngine::getSkin()->getColor(
|
||||
"text::neutral"), gld, clip);
|
||||
GL32_draw2DRectangle(text_neutral, gld, clip);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -305,6 +305,8 @@ public:
|
||||
virtual bool disableTextShaping() const { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
float getInverseShaping() const { return m_inverse_shaping; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool useColorGlyphPage() const { return false; }
|
||||
}; // FontWithFace
|
||||
|
||||
#endif
|
||||
|
@ -43,6 +43,8 @@ public:
|
||||
virtual void init() OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void reset() OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool useColorGlyphPage() const OVERRIDE { return true; }
|
||||
|
||||
}; // RegularFace
|
||||
|
||||
|
@ -1031,6 +1031,7 @@ void CGUIEditBox::setText(const wchar_t* text)
|
||||
updateGlyphLayouts();
|
||||
m_mark_begin = m_mark_end = m_cursor_pos = getTextCount();
|
||||
m_scroll_pos = 0;
|
||||
calculateScrollPos();
|
||||
#ifdef ANDROID
|
||||
if (GUIEngine::ScreenKeyboard::shouldUseScreenKeyboard() &&
|
||||
irr_driver->getDevice()->hasOnScreenKeyboard() &&
|
||||
@ -1502,6 +1503,7 @@ void CGUIEditBox::fromAndroidEditText(const std::u32string& text, int start,
|
||||
m_composing_start = composing_start;
|
||||
m_composing_end = composing_end;
|
||||
}
|
||||
calculateScrollPos();
|
||||
}
|
||||
|
||||
void CGUIEditBox::updateGlyphLayouts()
|
||||
|
Loading…
Reference in New Issue
Block a user