void Font_Impl::load_font( Canvas &canvas, Sprite &sprite, const std::string &glyph_list, int spacelen, bool monospace, const FontMetrics &metrics) { free_font(); font_engine = new FontEngine_Sprite(); glyph_cache.anti_alias = true; glyph_cache.enable_subpixel = false; glyph_cache.font_metrics = metrics; const int length = StringHelp::utf8_length(glyph_list); if ((length > sprite.get_frame_count()) || (length == 0)) { throw Exception(string_format("Font error: Letter characters: %1, Available font glyphs: %2", length, sprite.get_frame_count())); } //If monospace font requested, find the width of the widest glyph //Then set the fixed_width var to that width //Also set space to that width, if unset int fixed_width = 0; if (monospace) { for (int i=0; i < length; ++i) { int glyph_width = sprite.get_frame_size(i).width; if (glyph_width > fixed_width) fixed_width = glyph_width; } if (spacelen) spacelen = fixed_width; } //If not monospace, and space width not specified, then use average width as space width else if (spacelen <= 0) { std::string::size_type space_pos = glyph_list.find(' '); if (space_pos != std::string::npos) { //If there is a character for space, then use it spacelen = sprite.get_frame_size((int)space_pos).width; } else { //Make the space size the average of all character sizes spacelen = 0; for (int pos = 0; pos < length; ++pos) { spacelen += sprite.get_frame_size((int)(pos)).width; } spacelen /= length; } } int height = 0; for (int i=0; i < length; ++i) { int glyph_height = sprite.get_frame_size(i).height; if (glyph_height > height) height = glyph_height; } // Setup char to glyph map: UTF8_Reader reader(glyph_list.data(), glyph_list.length()); int sprite_index = 0; while(!reader.is_end()) { unsigned int glyph = reader.get_char(); reader.next(); const Sprite_Impl::SpriteFrame &sprite_frame = sprite.impl->frames[sprite_index]; Subtexture sub_texture(sprite_frame.texture, sprite_frame.position); Point increment; if (fixed_width) { increment.x = fixed_width; } else { increment.x = sprite_frame.position.get_width(); } Point offset(sprite_frame.offset); offset.y -= glyph_cache.font_metrics.get_ascent(); glyph_cache.insert_glyph(canvas, glyph, sub_texture, offset, increment); sprite_index++; } // Did the glyphs not contain a space? std::string::size_type space_pos = glyph_list.find(' '); if (space_pos == std::string::npos) { FontPixelBuffer pb; pb.empty_buffer = true; pb.increment.x = spacelen; pb.glyph = ' '; glyph_cache.insert_glyph(canvas, pb); } float average_character_width=0.0f; float max_character_width=0.0f; if (monospace) { average_character_width = fixed_width; max_character_width = fixed_width; } else { for (int i=0; i < length; ++i) { int glyph_width = sprite.get_frame_size(i).width; average_character_width += glyph_width; if (glyph_width > max_character_width) max_character_width = glyph_width; } if (length) average_character_width /= length; } if (glyph_cache.font_metrics.get_max_character_width() == 0.0f) { glyph_cache.font_metrics.set_max_character_width(max_character_width); } if (glyph_cache.font_metrics.get_average_character_width() == 0.0f) { glyph_cache.font_metrics.set_average_character_width(average_character_width); } if (glyph_cache.font_metrics.get_height() == 0) { glyph_cache.font_metrics.set_height(height); } }
void FontFamily_Impl::font_face_load(Canvas &canvas, Sprite &sprite, const std::string &glyph_list, float spacelen, bool monospace, const FontMetrics &metrics) { FontMetrics font_metrics = metrics; const int length = StringHelp::utf8_length(glyph_list); if ((length > sprite.get_frame_count()) || (length == 0)) { throw Exception(string_format("Font error: Letter characters: %1, Available font glyphs: %2", length, sprite.get_frame_count())); } //If monospace font requested, find the width of the widest glyph //Then set the fixed_width var to that width //Also set space to that width, if unset int fixed_width = 0; if (monospace) { for (int i = 0; i < length; ++i) { int glyph_width = sprite.get_frame_size(i).width; if (glyph_width > fixed_width) fixed_width = glyph_width; } if (spacelen) spacelen = fixed_width; } //If not monospace, and space width not specified, then use average width as space width else if (spacelen <= 0) { std::string::size_type space_pos = glyph_list.find(' '); if (space_pos != std::string::npos) { //If there is a character for space, then use it spacelen = sprite.get_frame_size((int)space_pos).width; } else { //Make the space size the average of all character sizes spacelen = 0; for (int pos = 0; pos < length; ++pos) { spacelen += sprite.get_frame_size((int)(pos)).width; } spacelen /= length; } } int height = 0; for (int i = 0; i < length; ++i) { int glyph_height = sprite.get_frame_size(i).height; if (glyph_height > height) height = glyph_height; } if (font_metrics.get_height() == 0) { font_metrics = FontMetrics( height, font_metrics.get_ascent(), font_metrics.get_descent(), font_metrics.get_internal_leading(), font_metrics.get_external_leading(), font_metrics.get_line_height()); } FontDescription desc; desc.set_height(height); std::shared_ptr<FontEngine> engine = std::make_shared<FontEngine_Sprite>(desc, font_metrics); Font_Cache sprite_engine(engine); font_cache.push_back(sprite_engine); GlyphCache *glyph_cache = sprite_engine.glyph_cache.get(); // Setup char to glyph map: UTF8_Reader reader(glyph_list.data(), glyph_list.length()); int sprite_index = 0; while (!reader.is_end()) { unsigned int glyph = reader.get_char(); reader.next(); const Sprite_Impl::SpriteFrame &sprite_frame = sprite.impl->frames[sprite_index]; Point increment; if (fixed_width) { increment.x = fixed_width; } else { increment.x = sprite_frame.position.get_width(); } Pointf offset(sprite_frame.offset); offset.y -= font_metrics.get_ascent(); Sizef size = sprite_frame.position.get_size(); Subtexture sub_texture(sprite_frame.texture, sprite_frame.position); glyph_cache->insert_glyph(canvas, glyph, sub_texture, offset, size, GlyphMetrics(Pointf(offset.x, offset.y), Sizef(increment.x, increment.y), Sizef(increment.x, increment.y))); sprite_index++; } // Did the glyphs not contain a space? std::string::size_type space_pos = glyph_list.find(' '); if (space_pos == std::string::npos) { FontPixelBuffer pb; pb.empty_buffer = true; pb.metrics.advance.width = spacelen; pb.metrics.bbox_size.width = spacelen; pb.glyph = ' '; glyph_cache->insert_glyph(canvas, pb); } float average_character_width = 0.0f; float max_character_width = 0.0f; if (monospace) { average_character_width = fixed_width; max_character_width = fixed_width; } else { for (int i = 0; i < length; ++i) { int glyph_width = sprite.get_frame_size(i).width; average_character_width += glyph_width; if (glyph_width > max_character_width) max_character_width = glyph_width; } if (length) average_character_width /= length; } }