|
@@ -60,8 +60,8 @@ FontFaceHandle::FontFaceHandle()
|
|
|
|
|
|
|
|
FontFaceHandle::~FontFaceHandle()
|
|
FontFaceHandle::~FontFaceHandle()
|
|
|
{
|
|
{
|
|
|
- for (FontGlyphMap::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
|
|
|
|
|
- delete[] i->second.bitmap_data;
|
|
|
|
|
|
|
+ for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
|
|
|
|
|
+ delete[] i->bitmap_data;
|
|
|
|
|
|
|
|
for (FontLayerMap::iterator i = layers.begin(); i != layers.end(); ++i)
|
|
for (FontLayerMap::iterator i = layers.begin(); i != layers.end(); ++i)
|
|
|
delete i->second;
|
|
delete i->second;
|
|
@@ -87,13 +87,20 @@ bool FontFaceHandle::Initialise(FT_Face ft_face, const String& _charset, int _si
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // find the maximum character we are interested in
|
|
|
|
|
+ max_codepoint = 0;
|
|
|
|
|
+ for (size_t i = 0; i < charset.size(); ++i)
|
|
|
|
|
+ max_codepoint = Math::Max(max_codepoint, charset[i].max_codepoint);
|
|
|
|
|
+
|
|
|
// Construct the list of the characters specified by the charset.
|
|
// Construct the list of the characters specified by the charset.
|
|
|
|
|
+ glyphs.resize(max_codepoint+1, FontGlyph());
|
|
|
for (size_t i = 0; i < charset.size(); ++i)
|
|
for (size_t i = 0; i < charset.size(); ++i)
|
|
|
BuildGlyphMap(ft_face, charset[i]);
|
|
BuildGlyphMap(ft_face, charset[i]);
|
|
|
|
|
|
|
|
// Generate the metrics for the handle.
|
|
// Generate the metrics for the handle.
|
|
|
GenerateMetrics(ft_face);
|
|
GenerateMetrics(ft_face);
|
|
|
|
|
|
|
|
|
|
+ BuildKerning(ft_face);
|
|
|
|
|
|
|
|
// Generate the default layer and layer configuration.
|
|
// Generate the default layer and layer configuration.
|
|
|
base_layer = GenerateLayer(NULL);
|
|
base_layer = GenerateLayer(NULL);
|
|
@@ -135,7 +142,7 @@ int FontFaceHandle::GetBaseline() const
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Returns the font's glyphs.
|
|
// Returns the font's glyphs.
|
|
|
-const FontGlyphMap& FontFaceHandle::GetGlyphs() const
|
|
|
|
|
|
|
+const FontGlyphList& FontFaceHandle::GetGlyphs() const
|
|
|
{
|
|
{
|
|
|
return glyphs;
|
|
return glyphs;
|
|
|
}
|
|
}
|
|
@@ -149,15 +156,15 @@ int FontFaceHandle::GetStringWidth(const WString& string, word prior_character)
|
|
|
{
|
|
{
|
|
|
word character_code = string[i];
|
|
word character_code = string[i];
|
|
|
|
|
|
|
|
- FontGlyphMap::const_iterator iterator = glyphs.find(character_code);
|
|
|
|
|
- if (iterator == glyphs.end())
|
|
|
|
|
|
|
+ if (character_code >= glyphs.size())
|
|
|
continue;
|
|
continue;
|
|
|
|
|
+ const FontGlyph &glyph = glyphs[character_code];
|
|
|
|
|
|
|
|
// Adjust the cursor for the kerning between this character and the previous one.
|
|
// Adjust the cursor for the kerning between this character and the previous one.
|
|
|
if (prior_character != 0)
|
|
if (prior_character != 0)
|
|
|
width += GetKerning(prior_character, string[i]);
|
|
width += GetKerning(prior_character, string[i]);
|
|
|
// Adjust the cursor for this character's advance.
|
|
// Adjust the cursor for this character's advance.
|
|
|
- width += iterator->second.advance;
|
|
|
|
|
|
|
+ width += glyph.advance;
|
|
|
|
|
|
|
|
prior_character = character_code;
|
|
prior_character = character_code;
|
|
|
}
|
|
}
|
|
@@ -283,9 +290,9 @@ int FontFaceHandle::GenerateString(GeometryList& geometry, const WString& string
|
|
|
|
|
|
|
|
for (; string_iterator != string_end; string_iterator++)
|
|
for (; string_iterator != string_end; string_iterator++)
|
|
|
{
|
|
{
|
|
|
- FontGlyphMap::const_iterator iterator = glyphs.find(*string_iterator);
|
|
|
|
|
- if (iterator == glyphs.end())
|
|
|
|
|
|
|
+ if (*string_iterator >= glyphs.size())
|
|
|
continue;
|
|
continue;
|
|
|
|
|
+ const FontGlyph &glyph = glyphs[*string_iterator];
|
|
|
|
|
|
|
|
// Adjust the cursor for the kerning between this character and the previous one.
|
|
// Adjust the cursor for the kerning between this character and the previous one.
|
|
|
if (prior_character != 0)
|
|
if (prior_character != 0)
|
|
@@ -293,7 +300,7 @@ int FontFaceHandle::GenerateString(GeometryList& geometry, const WString& string
|
|
|
|
|
|
|
|
layer->GenerateGeometry(&geometry[geometry_index], *string_iterator, Vector2f(position.x + line_width, position.y), layer_colour);
|
|
layer->GenerateGeometry(&geometry[geometry_index], *string_iterator, Vector2f(position.x + line_width, position.y), layer_colour);
|
|
|
|
|
|
|
|
- line_width += iterator->second.advance;
|
|
|
|
|
|
|
+ line_width += glyph.advance;
|
|
|
prior_character = *string_iterator;
|
|
prior_character = *string_iterator;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -354,11 +361,19 @@ void FontFaceHandle::GenerateMetrics(FT_Face ft_face)
|
|
|
underline_thickness = Math::Max(underline_thickness, 1.0f);
|
|
underline_thickness = Math::Max(underline_thickness, 1.0f);
|
|
|
|
|
|
|
|
average_advance = 0;
|
|
average_advance = 0;
|
|
|
- for (FontGlyphMap::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
|
|
|
|
|
- average_advance += i->second.advance;
|
|
|
|
|
|
|
+ unsigned int num_visible_glyphs = 0;
|
|
|
|
|
+ for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (i->advance)
|
|
|
|
|
+ {
|
|
|
|
|
+ average_advance += i->advance;
|
|
|
|
|
+ num_visible_glyphs++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Bring the total advance down to the average advance, but scaled up 10%, just to be on the safe side.
|
|
// Bring the total advance down to the average advance, but scaled up 10%, just to be on the safe side.
|
|
|
- average_advance = Math::RealToInteger((float) average_advance / (glyphs.size() * 0.9f));
|
|
|
|
|
|
|
+ if (num_visible_glyphs)
|
|
|
|
|
+ average_advance = Math::RealToInteger((float) average_advance / (num_visible_glyphs * 0.9f));
|
|
|
|
|
|
|
|
// Determine the x-height of this font face.
|
|
// Determine the x-height of this font face.
|
|
|
word x = (word) 'x';
|
|
word x = (word) 'x';
|
|
@@ -486,11 +501,13 @@ void FontFaceHandle::BuildKerning(FT_Face ft_face)
|
|
|
// Compile the kerning information for this character if the font includes it.
|
|
// Compile the kerning information for this character if the font includes it.
|
|
|
if (FT_HAS_KERNING(ft_face))
|
|
if (FT_HAS_KERNING(ft_face))
|
|
|
{
|
|
{
|
|
|
|
|
+ kerning.resize(max_codepoint+1, GlyphKerningList(max_codepoint+1, 0));
|
|
|
|
|
+
|
|
|
for (size_t i = 0; i < charset.size(); ++i)
|
|
for (size_t i = 0; i < charset.size(); ++i)
|
|
|
{
|
|
{
|
|
|
for (word rhs = (word) (Math::Max< unsigned int >(charset[i].min_codepoint, 32)); rhs <= charset[i].max_codepoint; ++rhs)
|
|
for (word rhs = (word) (Math::Max< unsigned int >(charset[i].min_codepoint, 32)); rhs <= charset[i].max_codepoint; ++rhs)
|
|
|
{
|
|
{
|
|
|
- GlyphKerningMap& glyph_kerning = kerning.insert(FontKerningMap::value_type(rhs, GlyphKerningMap())).first->second;
|
|
|
|
|
|
|
+ GlyphKerningList glyph_kerning(max_codepoint+1, 0);
|
|
|
|
|
|
|
|
for (size_t j = 0; j < charset.size(); ++j)
|
|
for (size_t j = 0; j < charset.size(); ++j)
|
|
|
{
|
|
{
|
|
@@ -504,6 +521,8 @@ void FontFaceHandle::BuildKerning(FT_Face ft_face)
|
|
|
glyph_kerning[lhs] = kerning;
|
|
glyph_kerning[lhs] = kerning;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ kerning[rhs] = glyph_kerning;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -511,15 +530,14 @@ void FontFaceHandle::BuildKerning(FT_Face ft_face)
|
|
|
|
|
|
|
|
int FontFaceHandle::GetKerning(word lhs, word rhs) const
|
|
int FontFaceHandle::GetKerning(word lhs, word rhs) const
|
|
|
{
|
|
{
|
|
|
- FontKerningMap::const_iterator rhs_iterator = kerning.find(rhs);
|
|
|
|
|
- if (rhs_iterator == kerning.end())
|
|
|
|
|
|
|
+ if (rhs >= kerning.size())
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
- GlyphKerningMap::const_iterator lhs_iterator = rhs_iterator->second.find(lhs);
|
|
|
|
|
- if (lhs_iterator == rhs_iterator->second.end())
|
|
|
|
|
|
|
+ const GlyphKerningList &kerning_map = kerning[rhs];
|
|
|
|
|
+ if (lhs >= kerning_map.size())
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
- return lhs_iterator->second;
|
|
|
|
|
|
|
+ return kerning_map[lhs];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Generates (or shares) a layer derived from a font effect.
|
|
// Generates (or shares) a layer derived from a font effect.
|