diff --git a/benchmark/test_face_ptr_creation.cpp b/benchmark/test_face_ptr_creation.cpp index 186b2ee0f..0123fffc2 100644 --- a/benchmark/test_face_ptr_creation.cpp +++ b/benchmark/test_face_ptr_creation.cpp @@ -10,39 +10,39 @@ public: bool validate() const { std::size_t count = 0; - std::size_t expected_count = mapnik::freetype_engine::face_names().size(); + std::size_t expected_count = mapnik::freetype_engine::instance().face_names().size(); mapnik::freetype_engine::font_file_mapping_type font_file_mapping; mapnik::freetype_engine::font_memory_cache_type font_cache; mapnik::font_library library; - for (std::string const& name : mapnik::freetype_engine::face_names()) + for (std::string const& name : mapnik::freetype_engine::instance().face_names()) { - mapnik::face_ptr f = mapnik::freetype_engine::create_face(name, + mapnik::face_ptr f = mapnik::freetype_engine::instance().create_face(name, library, font_file_mapping, font_cache, - mapnik::freetype_engine::get_mapping(), - mapnik::freetype_engine::get_cache()); + mapnik::freetype_engine::instance().get_mapping(), + mapnik::freetype_engine::instance().get_cache()); if (f) ++count; } return count == expected_count; } bool operator()() const { - std::size_t expected_count = mapnik::freetype_engine::face_names().size(); + std::size_t expected_count = mapnik::freetype_engine::instance().face_names().size(); for (unsigned i=0;i +#include +#include #include #include -#include // stl #include @@ -51,53 +52,55 @@ using face_set_ptr = std::unique_ptr; class font_face; using face_ptr = std::shared_ptr; -class MAPNIK_DECL freetype_engine +class MAPNIK_DECL freetype_engine : public singleton, + private util::noncopyable { + friend class CreateUsingNew; public: using font_file_mapping_type = std::map>; using font_memory_cache_type = std::map, std::size_t>>; - static bool is_font_file(std::string const& file_name); + bool is_font_file(std::string const& file_name); /*! \brief register a font file * @param file_name path to a font file. * @return bool - true if at least one face was successfully registered in the file. */ - static bool register_font(std::string const& file_name); + bool register_font(std::string const& file_name); /*! \brief register a font files * @param dir - path to a directory containing fonts or subdirectories. * @param recurse - default false, whether to search for fonts in sub directories. * @return bool - true if at least one face was successfully registered. */ - static bool register_fonts(std::string const& dir, bool recurse = false); - static std::vector face_names(); - static font_file_mapping_type const& get_mapping(); - static font_memory_cache_type & get_cache(); - static bool can_open(std::string const& face_name, + bool register_fonts(std::string const& dir, bool recurse = false); + std::vector face_names(); + font_file_mapping_type const& get_mapping(); + font_memory_cache_type & get_cache(); + bool can_open(std::string const& face_name, font_library & library, font_file_mapping_type const& font_file_mapping, font_file_mapping_type const& global_font_file_mapping); - static face_ptr create_face(std::string const& face_name, + face_ptr create_face(std::string const& face_name, font_library & library, font_file_mapping_type const& font_file_mapping, freetype_engine::font_memory_cache_type const& font_cache, font_file_mapping_type const& global_font_file_mapping, freetype_engine::font_memory_cache_type & global_memory_fonts); - static bool register_font_impl(std::string const& file_name, + bool register_font_impl(std::string const& file_name, font_library & libary, font_file_mapping_type & font_file_mapping); - static bool register_fonts_impl(std::string const& dir, + bool register_fonts_impl(std::string const& dir, font_library & libary, font_file_mapping_type & font_file_mapping, bool recurse = false); virtual ~freetype_engine(); freetype_engine(); private: - static bool register_font_impl(std::string const& file_name, FT_LibraryRec_ * library); - static bool register_fonts_impl(std::string const& dir, FT_LibraryRec_ * library, bool recurse = false); + bool register_font_impl(std::string const& file_name, FT_LibraryRec_ * library); + bool register_fonts_impl(std::string const& dir, FT_LibraryRec_ * library, bool recurse = false); #ifdef MAPNIK_THREADSAFE - static std::mutex mutex_; + std::mutex mutex_; #endif - static font_file_mapping_type global_font_file_mapping_; - static font_memory_cache_type global_memory_fonts_; + font_file_mapping_type global_font_file_mapping_; + font_memory_cache_type global_memory_fonts_; }; class MAPNIK_DECL face_manager @@ -124,7 +127,7 @@ private: }; using face_manager_freetype = face_manager; - +extern template class MAPNIK_DECL singleton; } #endif // MAPNIK_FONT_ENGINE_FREETYPE_HPP diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index 9721d70bf..16da563e0 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -51,6 +51,7 @@ extern "C" namespace mapnik { +template class MAPNIK_DECL singleton; freetype_engine::freetype_engine() {} freetype_engine::~freetype_engine() {} @@ -382,12 +383,12 @@ face_ptr face_manager::get_face(std::string const& name) } else { - face_ptr face = freetype_engine::create_face(name, + face_ptr face = freetype_engine::instance().create_face(name, library_, font_file_mapping_, font_memory_cache_, - freetype_engine::get_mapping(), - freetype_engine::get_cache()); + freetype_engine::instance().get_mapping(), + freetype_engine::instance().get_cache()); if (face) { face_cache_->emplace(name, face); @@ -442,9 +443,9 @@ face_set_ptr face_manager::get_face_set(std::string const& name, boost::optional } #ifdef MAPNIK_THREADSAFE -std::mutex freetype_engine::mutex_; +//std::mutex freetype_engine::mutex_; #endif -freetype_engine::font_file_mapping_type freetype_engine::global_font_file_mapping_; -freetype_engine::font_memory_cache_type freetype_engine::global_memory_fonts_; +//freetype_engine::font_file_mapping_type freetype_engine::global_font_file_mapping_; +//freetype_engine::font_memory_cache_type freetype_engine::global_memory_fonts_; } diff --git a/src/load_map.cpp b/src/load_map.cpp index 8969ce5c7..6491b424c 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -536,10 +536,10 @@ bool map_parser::parse_font(font_set & fset, xml_node const& f) } else { - found = freetype_engine::can_open(face_name, + found = freetype_engine::instance().can_open(face_name, font_library_, font_file_mapping_, - freetype_engine::get_mapping()); + freetype_engine::instance().get_mapping()); font_name_cache_.emplace(face_name,found); } if (found) @@ -1599,10 +1599,10 @@ void map_parser::ensure_font_face(std::string const& face_name) } else { - found = freetype_engine::can_open(face_name, + found = freetype_engine::instance().can_open(face_name, font_library_, font_file_mapping_, - freetype_engine::get_mapping()); + freetype_engine::instance().get_mapping()); font_name_cache_.emplace(face_name,found); } if (!found) diff --git a/src/map.cpp b/src/map.cpp index ec0d9f83e..b9b6a16c7 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -285,16 +285,16 @@ std::map & Map::fontsets() bool Map::register_fonts(std::string const& dir, bool recurse) { font_library library; - return freetype_engine::register_fonts_impl(dir, library, font_file_mapping_, recurse); + return freetype_engine::instance().register_fonts_impl(dir, library, font_file_mapping_, recurse); } bool Map::load_fonts() { bool result = false; - auto const& global_mapping = freetype_engine::get_mapping(); + auto const& global_mapping = freetype_engine::instance().get_mapping(); for (auto const& kv : font_file_mapping_) // for every face-name -> idx/filepath { - auto const& file_path = kv.second.second; + auto const& file_path = kv.second.second; // do not attemp to re-cache in memory if (font_memory_cache_.find(file_path) != font_memory_cache_.end()) { diff --git a/test/standalone/font_registration_test.cpp b/test/standalone/font_registration_test.cpp index a5ba0b271..a40e7d4bd 100644 --- a/test/standalone/font_registration_test.cpp +++ b/test/standalone/font_registration_test.cpp @@ -20,8 +20,8 @@ SECTION("registration") { mapnik::logger::severity_type original_severity = logger.get_severity(); // grab references to global statics of registered/cached fonts - auto const& global_mapping = mapnik::freetype_engine::get_mapping(); - auto const& global_cache = mapnik::freetype_engine::get_cache(); + auto const& global_mapping = mapnik::freetype_engine::instance().get_mapping(); + auto const& global_cache = mapnik::freetype_engine::instance().get_cache(); // mapnik.Map object has parallel structure for localized fonts mapnik::Map m(1,1); @@ -62,11 +62,11 @@ SECTION("registration") { std::vector face_names; std::string foo("foo"); // fake directories - REQUIRE( !mapnik::freetype_engine::register_fonts(foo , true ) ); - face_names = mapnik::freetype_engine::face_names(); + REQUIRE( !mapnik::freetype_engine::instance().register_fonts(foo , true ) ); + face_names = mapnik::freetype_engine::instance().face_names(); REQUIRE( face_names.size() == 0 ); - REQUIRE( !mapnik::freetype_engine::register_fonts(foo) ); - face_names = mapnik::freetype_engine::face_names(); + REQUIRE( !mapnik::freetype_engine::instance().register_fonts(foo) ); + face_names = mapnik::freetype_engine::instance().face_names(); REQUIRE( face_names.size() == 0 ); // directories without fonts @@ -76,31 +76,31 @@ SECTION("registration") { // an empty directory will not return true // we need to register at least one font and not fail on any // to return true - REQUIRE( mapnik::freetype_engine::register_font(src) == false ); - REQUIRE( mapnik::freetype_engine::register_fonts(src, true) == false ); - REQUIRE( mapnik::freetype_engine::face_names().size() == 0 ); + REQUIRE( mapnik::freetype_engine::instance().register_font(src) == false ); + REQUIRE( mapnik::freetype_engine::instance().register_fonts(src, true) == false ); + REQUIRE( mapnik::freetype_engine::instance().face_names().size() == 0 ); // bogus, emtpy file that looks like font - REQUIRE( mapnik::freetype_engine::register_font("test/data/fonts/fake.ttf") == false ); - REQUIRE( mapnik::freetype_engine::register_fonts("test/data/fonts/fake.ttf") == false ); - REQUIRE( mapnik::freetype_engine::face_names().size() == 0 ); + REQUIRE( mapnik::freetype_engine::instance().register_font("test/data/fonts/fake.ttf") == false ); + REQUIRE( mapnik::freetype_engine::instance().register_fonts("test/data/fonts/fake.ttf") == false ); + REQUIRE( mapnik::freetype_engine::instance().face_names().size() == 0 ); - REQUIRE( mapnik::freetype_engine::register_font("test/data/fonts/intentionally-broken.ttf") == false ); - REQUIRE( mapnik::freetype_engine::register_fonts("test/data/fonts/intentionally-broken.ttf") == false ); - REQUIRE( mapnik::freetype_engine::face_names().size() == 0 ); + REQUIRE( mapnik::freetype_engine::instance().register_font("test/data/fonts/intentionally-broken.ttf") == false ); + REQUIRE( mapnik::freetype_engine::instance().register_fonts("test/data/fonts/intentionally-broken.ttf") == false ); + REQUIRE( mapnik::freetype_engine::instance().face_names().size() == 0 ); // now restore the original severity logger.set_severity(original_severity); // single dejavu font in separate location std::string dejavu_bold_oblique("test/data/fonts/DejaVuSansMono-BoldOblique.ttf"); - REQUIRE( mapnik::freetype_engine::register_font(dejavu_bold_oblique) ); - face_names = mapnik::freetype_engine::face_names(); + REQUIRE( mapnik::freetype_engine::instance().register_font(dejavu_bold_oblique) ); + face_names = mapnik::freetype_engine::instance().face_names(); REQUIRE( face_names.size() == 1 ); // now, inspect font mapping and confirm the correct 'DejaVu Sans Mono Bold Oblique' is registered using font_file_mapping = std::map >; - font_file_mapping const& name2file = mapnik::freetype_engine::get_mapping(); + font_file_mapping const& name2file = mapnik::freetype_engine::instance().get_mapping(); bool found_dejavu = false; for (auto const& item : name2file) { @@ -114,8 +114,8 @@ SECTION("registration") { REQUIRE( found_dejavu ); // recurse to find all dejavu fonts - REQUIRE( mapnik::freetype_engine::register_fonts(fontdir, true) ); - face_names = mapnik::freetype_engine::face_names(); + REQUIRE( mapnik::freetype_engine::instance().register_fonts(fontdir, true) ); + face_names = mapnik::freetype_engine::instance().face_names(); REQUIRE( face_names.size() == 22 ); // we should have re-registered 'DejaVu Sans Mono Bold Oblique' again, @@ -148,21 +148,21 @@ SECTION("registration") { // check that we can correctly read a .ttc containing // multiple valid faces // https://github.com/mapnik/mapnik/issues/2274 - REQUIRE( mapnik::freetype_engine::register_font("test/data/fonts/NotoSans-Regular.ttc") ); - face_names = mapnik::freetype_engine::face_names(); + REQUIRE( mapnik::freetype_engine::instance().register_font("test/data/fonts/NotoSans-Regular.ttc") ); + face_names = mapnik::freetype_engine::instance().face_names(); REQUIRE( face_names.size() == 24 ); // now blindly register as many system fonts as possible // the goal here to make sure we don't crash // linux - mapnik::freetype_engine::register_fonts("/usr/share/fonts/", true); - mapnik::freetype_engine::register_fonts("/usr/local/share/fonts/", true); + mapnik::freetype_engine::instance().register_fonts("/usr/share/fonts/", true); + mapnik::freetype_engine::instance().register_fonts("/usr/local/share/fonts/", true); // osx - mapnik::freetype_engine::register_fonts("/Library/Fonts/", true); - mapnik::freetype_engine::register_fonts("/System/Library/Fonts/", true); + mapnik::freetype_engine::instance().register_fonts("/Library/Fonts/", true); + mapnik::freetype_engine::instance().register_fonts("/System/Library/Fonts/", true); // windows - mapnik::freetype_engine::register_fonts("C:\\Windows\\Fonts", true); - face_names = mapnik::freetype_engine::face_names(); + mapnik::freetype_engine::instance().register_fonts("C:\\Windows\\Fonts", true); + face_names = mapnik::freetype_engine::instance().face_names(); REQUIRE( face_names.size() > 22 ); } catch (std::exception const & ex) diff --git a/test/visual/run.cpp b/test/visual/run.cpp index 587727906..f935307f4 100644 --- a/test/visual/run.cpp +++ b/test/visual/run.cpp @@ -174,7 +174,7 @@ int main(int argc, char** argv) } #endif - mapnik::freetype_engine::register_fonts(vm["fonts"].as(), true); + mapnik::freetype_engine::instance().register_fonts(vm["fonts"].as(), true); mapnik::datasource_cache::instance().register_datasources(vm["plugins"].as()); boost::filesystem::path output_dir(vm["output-dir"].as()); diff --git a/utils/mapnik-render/mapnik-render.cpp b/utils/mapnik-render/mapnik-render.cpp index c172995c7..e6ce02590 100644 --- a/utils/mapnik-render/mapnik-render.cpp +++ b/utils/mapnik-render/mapnik-render.cpp @@ -104,7 +104,7 @@ int main (int argc,char** argv) } mapnik::datasource_cache::instance().register_datasources("./plugins/input/"); - mapnik::freetype_engine::register_fonts("./fonts",true); + mapnik::freetype_engine::instance().register_fonts("./fonts",true); mapnik::Map map(600,400); mapnik::load_map(map,xml_file,true); map.zoom_all();