3.x port of localized font caching and then some
This commit is contained in:
parent
d3d6b09516
commit
d1adabf7d5
18 changed files with 487 additions and 169 deletions
|
@ -12,23 +12,27 @@ public:
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
std::size_t expected_count = mapnik::freetype_engine::face_names().size();
|
std::size_t expected_count = mapnik::freetype_engine::face_names().size();
|
||||||
mapnik::freetype_engine engine;
|
mapnik::freetype_engine engine;
|
||||||
|
mapnik::freetype_engine::font_file_mapping_type font_file_mapping;
|
||||||
|
mapnik::freetype_engine::font_memory_cache_type font_cache;
|
||||||
for (std::string const& name : mapnik::freetype_engine::face_names())
|
for (std::string const& name : mapnik::freetype_engine::face_names())
|
||||||
{
|
{
|
||||||
mapnik::face_ptr f = engine.create_face(name);
|
mapnik::face_ptr f = engine.create_face(name,font_file_mapping,font_cache);
|
||||||
if (f) ++count;
|
if (f) ++count;
|
||||||
}
|
}
|
||||||
return count == expected_count;
|
return count == expected_count;
|
||||||
}
|
}
|
||||||
void operator()() const
|
void operator()() const
|
||||||
{
|
{
|
||||||
mapnik::freetype_engine engine;
|
|
||||||
std::size_t expected_count = mapnik::freetype_engine::face_names().size();
|
std::size_t expected_count = mapnik::freetype_engine::face_names().size();
|
||||||
for (unsigned i=0;i<iterations_;++i)
|
for (unsigned i=0;i<iterations_;++i)
|
||||||
{
|
{
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
|
mapnik::freetype_engine engine;
|
||||||
|
mapnik::freetype_engine::font_file_mapping_type font_file_mapping;
|
||||||
|
mapnik::freetype_engine::font_memory_cache_type font_cache;
|
||||||
for (std::string const& name : mapnik::freetype_engine::face_names())
|
for (std::string const& name : mapnik::freetype_engine::face_names())
|
||||||
{
|
{
|
||||||
mapnik::face_ptr f = engine.create_face(name);
|
mapnik::face_ptr f = engine.create_face(name,font_file_mapping,font_cache);
|
||||||
if (f) ++count;
|
if (f) ++count;
|
||||||
}
|
}
|
||||||
if (count != expected_count) {
|
if (count != expected_count) {
|
||||||
|
|
|
@ -321,7 +321,7 @@ public:
|
||||||
void glyph_path(unsigned long index, pixel_position const& pos);
|
void glyph_path(unsigned long index, pixel_position const& pos);
|
||||||
void add_text(glyph_positions_ptr pos,
|
void add_text(glyph_positions_ptr pos,
|
||||||
cairo_face_manager & manager,
|
cairo_face_manager & manager,
|
||||||
face_manager<freetype_engine> & font_manager,
|
face_manager_freetype & font_manager,
|
||||||
composite_mode_e comp_op = src_over,
|
composite_mode_e comp_op = src_over,
|
||||||
composite_mode_e halo_comp_op = src_over,
|
composite_mode_e halo_comp_op = src_over,
|
||||||
double scale_factor = 1.0);
|
double scale_factor = 1.0);
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <mapnik/config.hpp>
|
#include <mapnik/config.hpp>
|
||||||
#include <mapnik/font_set.hpp>
|
#include <mapnik/font_set.hpp>
|
||||||
#include <mapnik/noncopyable.hpp>
|
#include <mapnik/noncopyable.hpp>
|
||||||
|
#include <mapnik/util/font_library.hpp>
|
||||||
|
|
||||||
// stl
|
// stl
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -38,8 +39,6 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct FT_LibraryRec_;
|
|
||||||
struct FT_MemoryRec_;
|
|
||||||
namespace boost { template <class T> class optional; }
|
namespace boost { template <class T> class optional; }
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
|
@ -52,10 +51,11 @@ using face_set_ptr = std::shared_ptr<font_face_set>;
|
||||||
class font_face;
|
class font_face;
|
||||||
using face_ptr = std::shared_ptr<font_face>;
|
using face_ptr = std::shared_ptr<font_face>;
|
||||||
|
|
||||||
|
|
||||||
class MAPNIK_DECL freetype_engine
|
class MAPNIK_DECL freetype_engine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using font_file_mapping_type = std::map<std::string,std::pair<int,std::string>>;
|
||||||
|
using font_memory_cache_type = std::map<std::string, std::pair<std::unique_ptr<char[]>, std::size_t>>;
|
||||||
static bool is_font_file(std::string const& file_name);
|
static bool is_font_file(std::string const& file_name);
|
||||||
/*! \brief register a font file
|
/*! \brief register a font file
|
||||||
* @param file_name path to a font file.
|
* @param file_name path to a font file.
|
||||||
|
@ -69,50 +69,64 @@ public:
|
||||||
*/
|
*/
|
||||||
static bool register_fonts(std::string const& dir, bool recurse = false);
|
static bool register_fonts(std::string const& dir, bool recurse = false);
|
||||||
static std::vector<std::string> face_names();
|
static std::vector<std::string> face_names();
|
||||||
static std::map<std::string, std::pair<int,std::string> > const& get_mapping();
|
static font_file_mapping_type const& get_mapping();
|
||||||
face_ptr create_face(std::string const& family_name);
|
static face_ptr create_face(std::string const& family_name,
|
||||||
|
util::font_library & library,
|
||||||
|
font_file_mapping_type const& font_file_mapping,
|
||||||
|
freetype_engine::font_memory_cache_type const& font_cache);
|
||||||
stroker_ptr create_stroker();
|
stroker_ptr create_stroker();
|
||||||
virtual ~freetype_engine();
|
virtual ~freetype_engine();
|
||||||
freetype_engine();
|
freetype_engine();
|
||||||
|
static bool register_font_impl(std::string const& file_name,
|
||||||
|
util::font_library & libary,
|
||||||
|
font_file_mapping_type & font_file_mapping);
|
||||||
|
static bool register_fonts_impl(std::string const& dir,
|
||||||
|
util::font_library & libary,
|
||||||
|
font_file_mapping_type & font_file_mapping,
|
||||||
|
bool recurse = false);
|
||||||
|
util::font_library & get_library()
|
||||||
|
{
|
||||||
|
return library_;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
static bool register_font_impl(std::string const& file_name, FT_LibraryRec_ * library);
|
util::font_library library_;
|
||||||
static bool register_fonts_impl(std::string const& dir, FT_LibraryRec_ * library, bool recurse = false);
|
|
||||||
FT_LibraryRec_ * library_;
|
|
||||||
std::unique_ptr<FT_MemoryRec_> memory_;
|
|
||||||
#ifdef MAPNIK_THREADSAFE
|
#ifdef MAPNIK_THREADSAFE
|
||||||
static std::mutex mutex_;
|
static std::mutex mutex_;
|
||||||
#endif
|
#endif
|
||||||
static std::map<std::string, std::pair<int,std::string> > name2file_;
|
static font_file_mapping_type global_font_file_mapping_;
|
||||||
static std::map<std::string, std::pair<std::unique_ptr<char[]>, std::size_t> > memory_fonts_;
|
static font_memory_cache_type global_memory_fonts_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class MAPNIK_DECL face_manager : private mapnik::noncopyable
|
class MAPNIK_DECL face_manager : private mapnik::noncopyable
|
||||||
{
|
{
|
||||||
using font_engine_type = T;
|
|
||||||
using face_ptr_cache_type = std::map<std::string, face_ptr>;
|
using face_ptr_cache_type = std::map<std::string, face_ptr>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
face_manager(T & engine)
|
face_manager(freetype_engine & engine,
|
||||||
|
freetype_engine::font_file_mapping_type const& font_file_mapping,
|
||||||
|
freetype_engine::font_memory_cache_type const& font_cache)
|
||||||
: engine_(engine),
|
: engine_(engine),
|
||||||
stroker_(engine_.create_stroker()),
|
stroker_(engine_.create_stroker()),
|
||||||
face_ptr_cache_() {}
|
face_ptr_cache_(),
|
||||||
|
library_(engine_.get_library()),
|
||||||
|
font_file_mapping_(font_file_mapping),
|
||||||
|
font_memory_cache_(font_cache) {}
|
||||||
|
|
||||||
face_ptr get_face(std::string const& name);
|
face_ptr get_face(std::string const& name);
|
||||||
face_set_ptr get_face_set(std::string const& name);
|
face_set_ptr get_face_set(std::string const& name);
|
||||||
face_set_ptr get_face_set(font_set const& fset);
|
face_set_ptr get_face_set(font_set const& fset);
|
||||||
face_set_ptr get_face_set(std::string const& name, boost::optional<font_set> fset);
|
face_set_ptr get_face_set(std::string const& name, boost::optional<font_set> fset);
|
||||||
|
|
||||||
|
|
||||||
inline stroker_ptr get_stroker() { return stroker_; }
|
inline stroker_ptr get_stroker() { return stroker_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
font_engine_type & engine_;
|
freetype_engine & engine_;
|
||||||
stroker_ptr stroker_;
|
stroker_ptr stroker_;
|
||||||
face_ptr_cache_type face_ptr_cache_;
|
face_ptr_cache_type face_ptr_cache_;
|
||||||
|
util::font_library & library_;
|
||||||
|
freetype_engine::font_file_mapping_type const& font_file_mapping_;
|
||||||
|
freetype_engine::font_memory_cache_type const& font_memory_cache_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using face_manager_freetype = face_manager<freetype_engine>;
|
using face_manager_freetype = face_manager;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <mapnik/params.hpp>
|
#include <mapnik/params.hpp>
|
||||||
#include <mapnik/well_known_srs.hpp>
|
#include <mapnik/well_known_srs.hpp>
|
||||||
#include <mapnik/image_compositing.hpp>
|
#include <mapnik/image_compositing.hpp>
|
||||||
|
#include <mapnik/font_engine_freetype.hpp>
|
||||||
|
|
||||||
// boost
|
// boost
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
@ -97,6 +98,9 @@ private:
|
||||||
boost::optional<box2d<double> > maximum_extent_;
|
boost::optional<box2d<double> > maximum_extent_;
|
||||||
std::string base_path_;
|
std::string base_path_;
|
||||||
parameters extra_params_;
|
parameters extra_params_;
|
||||||
|
boost::optional<std::string> font_directory_;
|
||||||
|
freetype_engine::font_file_mapping_type font_file_mapping_;
|
||||||
|
freetype_engine::font_memory_cache_type font_memory_cache_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -209,6 +213,14 @@ public:
|
||||||
*/
|
*/
|
||||||
std::map<std::string,font_set> & fontsets();
|
std::map<std::string,font_set> & fontsets();
|
||||||
|
|
||||||
|
/*! \brief register fonts.
|
||||||
|
*/
|
||||||
|
bool register_fonts(std::string const& dir, bool recurse);
|
||||||
|
|
||||||
|
/*! \brief cache registered fonts.
|
||||||
|
*/
|
||||||
|
bool load_fonts();
|
||||||
|
|
||||||
/*! \brief Get number of all layers.
|
/*! \brief Get number of all layers.
|
||||||
*/
|
*/
|
||||||
size_t layer_count() const;
|
size_t layer_count() const;
|
||||||
|
@ -437,6 +449,36 @@ public:
|
||||||
*/
|
*/
|
||||||
void set_extra_parameters(parameters& params);
|
void set_extra_parameters(parameters& params);
|
||||||
|
|
||||||
|
boost::optional<std::string> const& font_directory() const
|
||||||
|
{
|
||||||
|
return font_directory_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_font_directory(std::string const& dir)
|
||||||
|
{
|
||||||
|
font_directory_ = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
freetype_engine::font_file_mapping_type const& get_font_file_mapping() const
|
||||||
|
{
|
||||||
|
return font_file_mapping_;
|
||||||
|
}
|
||||||
|
|
||||||
|
freetype_engine::font_file_mapping_type & get_font_file_mapping()
|
||||||
|
{
|
||||||
|
return font_file_mapping_;
|
||||||
|
}
|
||||||
|
|
||||||
|
freetype_engine::font_memory_cache_type const& get_font_memory_cache() const
|
||||||
|
{
|
||||||
|
return font_memory_cache_;
|
||||||
|
}
|
||||||
|
|
||||||
|
freetype_engine::font_memory_cache_type & get_font_memory_cache()
|
||||||
|
{
|
||||||
|
return font_memory_cache_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend void swap(Map & rhs, Map & lhs);
|
friend void swap(Map & rhs, Map & lhs);
|
||||||
void fixAspectRatio();
|
void fixAspectRatio();
|
||||||
|
|
|
@ -56,8 +56,8 @@ struct renderer_common : private mapnik::noncopyable
|
||||||
attributes vars_;
|
attributes vars_;
|
||||||
// TODO: dirty hack for cairo renderer, figure out how to remove this
|
// TODO: dirty hack for cairo renderer, figure out how to remove this
|
||||||
std::shared_ptr<freetype_engine> shared_font_engine_;
|
std::shared_ptr<freetype_engine> shared_font_engine_;
|
||||||
freetype_engine &font_engine_;
|
freetype_engine & font_engine_;
|
||||||
face_manager<freetype_engine> font_manager_;
|
face_manager_freetype font_manager_;
|
||||||
box2d<double> query_extent_;
|
box2d<double> query_extent_;
|
||||||
view_transform t_;
|
view_transform t_;
|
||||||
std::shared_ptr<label_collision_detector4> detector_;
|
std::shared_ptr<label_collision_detector4> detector_;
|
||||||
|
|
|
@ -71,7 +71,7 @@ struct virtual_renderer_common : private mapnik::noncopyable
|
||||||
// TODO: dirty hack for cairo renderer, figure out how to remove this
|
// TODO: dirty hack for cairo renderer, figure out how to remove this
|
||||||
std::shared_ptr<freetype_engine> & shared_font_engine_;
|
std::shared_ptr<freetype_engine> & shared_font_engine_;
|
||||||
freetype_engine & font_engine_;
|
freetype_engine & font_engine_;
|
||||||
face_manager<freetype_engine> & font_manager_;
|
face_manager_freetype & font_manager_;
|
||||||
box2d<double> & query_extent_;
|
box2d<double> & query_extent_;
|
||||||
view_transform & t_;
|
view_transform & t_;
|
||||||
std::shared_ptr<label_collision_detector4> detector_;
|
std::shared_ptr<label_collision_detector4> detector_;
|
||||||
|
|
|
@ -97,7 +97,7 @@ public:
|
||||||
void add_child(text_layout_ptr const& child_layout);
|
void add_child(text_layout_ptr const& child_layout);
|
||||||
|
|
||||||
inline text_layout_vector const& get_child_layouts() const { return child_layout_list_; }
|
inline text_layout_vector const& get_child_layouts() const { return child_layout_list_; }
|
||||||
inline face_manager<freetype_engine> & get_font_manager() const { return font_manager_; }
|
inline face_manager_freetype & get_font_manager() const { return font_manager_; }
|
||||||
inline double get_scale_factor() const { return scale_factor_; }
|
inline double get_scale_factor() const { return scale_factor_; }
|
||||||
inline text_layout_properties const& get_layout_properties() const { return properties_; }
|
inline text_layout_properties const& get_layout_properties() const { return properties_; }
|
||||||
|
|
||||||
|
|
91
include/mapnik/util/file_io.hpp
Normal file
91
include/mapnik/util/file_io.hpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAPNIK_FILE_IO_HPP
|
||||||
|
#define MAPNIK_FILE_IO_HPP
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/utils.hpp>
|
||||||
|
#include <mapnik/make_unique.hpp>
|
||||||
|
#include <mapnik/noncopyable.hpp>
|
||||||
|
//#include <mapnik/config.hpp>
|
||||||
|
|
||||||
|
// stl
|
||||||
|
#include <cstdio>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace mapnik { namespace util {
|
||||||
|
|
||||||
|
class file : public noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using file_ptr = std::unique_ptr<std::FILE, int (*)(std::FILE *)>;
|
||||||
|
|
||||||
|
explicit file(std::string const& filename)
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
: file_(_wfopen(mapnik::utf8_to_utf16(filename).c_str(), L"rb"), std::fclose),
|
||||||
|
#else
|
||||||
|
: file_(std::fopen(filename.c_str(),"rb"), std::fclose),
|
||||||
|
#endif
|
||||||
|
size_(0)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (file_)
|
||||||
|
{
|
||||||
|
std::fseek(file_.get(), 0, SEEK_END);
|
||||||
|
size_ = std::ftell(file_.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool open() const
|
||||||
|
{
|
||||||
|
return file_ ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::FILE * get() const
|
||||||
|
{
|
||||||
|
return file_.get();;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t size() const
|
||||||
|
{
|
||||||
|
return size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::unique_ptr<char[]> data() const
|
||||||
|
{
|
||||||
|
if (!size_) return nullptr;
|
||||||
|
std::fseek(file_.get(), 0, SEEK_SET);
|
||||||
|
std::unique_ptr<char[]> buffer(new char[size_]);
|
||||||
|
std::fread(buffer.get(), size_, 1, file_.get());
|
||||||
|
return std::move(buffer);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
file_ptr file_;
|
||||||
|
std::size_t size_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FILE_IO
|
59
include/mapnik/util/font_library.hpp
Normal file
59
include/mapnik/util/font_library.hpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAPNIK_FONT_LIBRARY_HPP
|
||||||
|
#define MAPNIK_FONT_LIBRARY_HPP
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/config.hpp>
|
||||||
|
#include <mapnik/noncopyable.hpp>
|
||||||
|
|
||||||
|
// stl
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct FT_LibraryRec_;
|
||||||
|
struct FT_MemoryRec_;
|
||||||
|
|
||||||
|
namespace mapnik {
|
||||||
|
|
||||||
|
class font_face;
|
||||||
|
using face_ptr = std::shared_ptr<font_face>;
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
|
||||||
|
class MAPNIK_DECL font_library : public noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit font_library();
|
||||||
|
~font_library();
|
||||||
|
FT_LibraryRec_ * get();
|
||||||
|
face_ptr face_from_memory(const char * buffer,
|
||||||
|
std::size_t size,
|
||||||
|
int index);
|
||||||
|
private:
|
||||||
|
FT_LibraryRec_ * library_;
|
||||||
|
std::unique_ptr<FT_MemoryRec_> memory_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif // MAPNIK_FONT_LIBRARY_HPP
|
|
@ -142,6 +142,7 @@ else: # unix, non-macos
|
||||||
|
|
||||||
source = Split(
|
source = Split(
|
||||||
"""
|
"""
|
||||||
|
font_library.cpp
|
||||||
expression_grammar.cpp
|
expression_grammar.cpp
|
||||||
fs.cpp
|
fs.cpp
|
||||||
request.cpp
|
request.cpp
|
||||||
|
|
|
@ -432,7 +432,7 @@ void cairo_context::glyph_path(unsigned long index, pixel_position const &pos)
|
||||||
|
|
||||||
void cairo_context::add_text(glyph_positions_ptr path,
|
void cairo_context::add_text(glyph_positions_ptr path,
|
||||||
cairo_face_manager & manager,
|
cairo_face_manager & manager,
|
||||||
face_manager<freetype_engine> & font_manager,
|
face_manager_freetype & font_manager,
|
||||||
composite_mode_e comp_op,
|
composite_mode_e comp_op,
|
||||||
composite_mode_e halo_comp_op,
|
composite_mode_e halo_comp_op,
|
||||||
double scale_factor)
|
double scale_factor)
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <mapnik/pixel_position.hpp>
|
#include <mapnik/pixel_position.hpp>
|
||||||
#include <mapnik/text/face.hpp>
|
#include <mapnik/text/face.hpp>
|
||||||
#include <mapnik/util/fs.hpp>
|
#include <mapnik/util/fs.hpp>
|
||||||
|
#include <mapnik/util/file_io.hpp>
|
||||||
#include <mapnik/utils.hpp>
|
#include <mapnik/utils.hpp>
|
||||||
|
|
||||||
// boost
|
// boost
|
||||||
|
@ -36,7 +37,6 @@
|
||||||
// stl
|
// stl
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
// freetype2
|
// freetype2
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -47,45 +47,14 @@ extern "C"
|
||||||
#include FT_MODULE_H
|
#include FT_MODULE_H
|
||||||
}
|
}
|
||||||
|
|
||||||
void* _Alloc_Func(FT_Memory memory, long size)
|
|
||||||
{
|
|
||||||
return std::malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _Free_Func(FT_Memory memory, void *block)
|
|
||||||
{
|
|
||||||
std::free(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* _Realloc_Func(FT_Memory memory, long cur_size, long new_size, void* block)
|
|
||||||
{
|
|
||||||
return std::realloc(block, new_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
|
|
||||||
void init_freetype(FT_Memory memory, FT_Library & library)
|
|
||||||
{
|
|
||||||
memory->alloc = _Alloc_Func;
|
|
||||||
memory->free = _Free_Func;
|
|
||||||
memory->realloc = _Realloc_Func;
|
|
||||||
FT_Error error = FT_New_Library(memory, &library );
|
|
||||||
if (error) throw std::runtime_error("can not initalise FreeType2 library");
|
|
||||||
FT_Add_Default_Modules(library);
|
|
||||||
}
|
|
||||||
|
|
||||||
freetype_engine::freetype_engine()
|
freetype_engine::freetype_engine()
|
||||||
: library_(nullptr),
|
: library_() {}
|
||||||
memory_(new FT_MemoryRec_)
|
|
||||||
{
|
|
||||||
init_freetype(&*memory_, library_);
|
|
||||||
}
|
|
||||||
|
|
||||||
freetype_engine::~freetype_engine()
|
freetype_engine::~freetype_engine() {}
|
||||||
{
|
|
||||||
FT_Done_Library(library_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool freetype_engine::is_font_file(std::string const& file_name)
|
bool freetype_engine::is_font_file(std::string const& file_name)
|
||||||
{
|
{
|
||||||
|
@ -116,37 +85,27 @@ bool freetype_engine::register_font(std::string const& file_name)
|
||||||
#ifdef MAPNIK_THREADSAFE
|
#ifdef MAPNIK_THREADSAFE
|
||||||
mapnik::scoped_lock lock(mutex_);
|
mapnik::scoped_lock lock(mutex_);
|
||||||
#endif
|
#endif
|
||||||
|
util::font_library library;
|
||||||
FT_Library library = 0;
|
return register_font_impl(file_name, library, global_font_file_mapping_);
|
||||||
std::unique_ptr<FT_MemoryRec_> memory(new FT_MemoryRec_);
|
|
||||||
init_freetype(&*memory, library);
|
|
||||||
bool result = register_font_impl(file_name, library);
|
|
||||||
FT_Done_Library(library);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool freetype_engine::register_font_impl(std::string const& file_name, FT_LibraryRec_ * library)
|
bool freetype_engine::register_font_impl(std::string const& file_name,
|
||||||
|
util::font_library & library,
|
||||||
|
freetype_engine::font_file_mapping_type & font_file_mapping)
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_DEBUG(font_engine_freetype) << "registering: " << file_name;
|
MAPNIK_LOG_DEBUG(font_engine_freetype) << "registering: " << file_name;
|
||||||
#ifdef _WINDOWS
|
mapnik::util::file file(file_name);
|
||||||
FILE * file = _wfopen(mapnik::utf8_to_utf16(file_name).c_str(), L"rb");
|
if (!file.open()) return false;
|
||||||
#else
|
|
||||||
FILE * file = std::fopen(file_name.c_str(),"rb");
|
|
||||||
#endif
|
|
||||||
if (file == nullptr) return false;
|
|
||||||
|
|
||||||
FT_Face face = 0;
|
FT_Face face = 0;
|
||||||
FT_Open_Args args;
|
FT_Open_Args args;
|
||||||
FT_StreamRec streamRec;
|
FT_StreamRec streamRec;
|
||||||
memset(&args, 0, sizeof(args));
|
memset(&args, 0, sizeof(args));
|
||||||
memset(&streamRec, 0, sizeof(streamRec));
|
memset(&streamRec, 0, sizeof(streamRec));
|
||||||
fseek(file, 0, SEEK_END);
|
|
||||||
std::size_t file_size = std::ftell(file);
|
|
||||||
fseek(file, 0, SEEK_SET);
|
|
||||||
streamRec.base = 0;
|
streamRec.base = 0;
|
||||||
streamRec.pos = 0;
|
streamRec.pos = 0;
|
||||||
streamRec.size = file_size;
|
streamRec.size = file.size();
|
||||||
streamRec.descriptor.pointer = file;
|
streamRec.descriptor.pointer = file.get();
|
||||||
streamRec.read = ft_read_cb;
|
streamRec.read = ft_read_cb;
|
||||||
streamRec.close = NULL;
|
streamRec.close = NULL;
|
||||||
args.flags = FT_OPEN_STREAM;
|
args.flags = FT_OPEN_STREAM;
|
||||||
|
@ -159,7 +118,7 @@ bool freetype_engine::register_font_impl(std::string const& file_name, FT_Librar
|
||||||
for ( int i = 0; face == 0 || i < num_faces; ++i )
|
for ( int i = 0; face == 0 || i < num_faces; ++i )
|
||||||
{
|
{
|
||||||
// if face is null then this is the first face
|
// if face is null then this is the first face
|
||||||
FT_Error error = FT_Open_Face(library, &args, i, &face);
|
FT_Error error = FT_Open_Face(library.get(), &args, i, &face);
|
||||||
if (error) break;
|
if (error) break;
|
||||||
// store num_faces locally, after FT_Done_Face it can not be accessed any more
|
// store num_faces locally, after FT_Done_Face it can not be accessed any more
|
||||||
if (num_faces == 0)
|
if (num_faces == 0)
|
||||||
|
@ -173,10 +132,10 @@ bool freetype_engine::register_font_impl(std::string const& file_name, FT_Librar
|
||||||
if (!boost::algorithm::starts_with(name,"."))
|
if (!boost::algorithm::starts_with(name,"."))
|
||||||
{
|
{
|
||||||
// http://stackoverflow.com/a/24795559/2333354
|
// http://stackoverflow.com/a/24795559/2333354
|
||||||
auto range = name2file_.equal_range(name);
|
auto range = font_file_mapping.equal_range(name);
|
||||||
if (range.first == range.second) // the key was previously absent; insert a pair
|
if (range.first == range.second) // the key was previously absent; insert a pair
|
||||||
{
|
{
|
||||||
name2file_.emplace_hint(range.first,name,std::move(std::make_pair(i,file_name)));
|
font_file_mapping.emplace_hint(range.first,name,std::move(std::make_pair(i,file_name)));
|
||||||
}
|
}
|
||||||
else // the key was present, replace the associated value
|
else // the key was present, replace the associated value
|
||||||
{ /* some action with value range.first->second about to be overwritten here */
|
{ /* some action with value range.first->second about to be overwritten here */
|
||||||
|
@ -200,7 +159,6 @@ bool freetype_engine::register_font_impl(std::string const& file_name, FT_Librar
|
||||||
}
|
}
|
||||||
if (face) FT_Done_Face(face);
|
if (face) FT_Done_Face(face);
|
||||||
}
|
}
|
||||||
std::fclose(file);
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,15 +167,14 @@ bool freetype_engine::register_fonts(std::string const& dir, bool recurse)
|
||||||
#ifdef MAPNIK_THREADSAFE
|
#ifdef MAPNIK_THREADSAFE
|
||||||
mapnik::scoped_lock lock(mutex_);
|
mapnik::scoped_lock lock(mutex_);
|
||||||
#endif
|
#endif
|
||||||
std::unique_ptr<FT_MemoryRec_> memory(new FT_MemoryRec_);
|
util::font_library library;
|
||||||
FT_Library library = 0;
|
return register_fonts_impl(dir, library, global_font_file_mapping_, recurse);
|
||||||
init_freetype(&*memory, library);
|
|
||||||
bool result = register_fonts_impl(dir, library, recurse);
|
|
||||||
FT_Done_Library(library);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool freetype_engine::register_fonts_impl(std::string const& dir, FT_LibraryRec_ * library, bool recurse)
|
bool freetype_engine::register_fonts_impl(std::string const& dir,
|
||||||
|
util::font_library & library,
|
||||||
|
freetype_engine::font_file_mapping_type & font_file_mapping,
|
||||||
|
bool recurse)
|
||||||
{
|
{
|
||||||
if (!mapnik::util::exists(dir))
|
if (!mapnik::util::exists(dir))
|
||||||
{
|
{
|
||||||
|
@ -225,7 +182,7 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, FT_LibraryRec_
|
||||||
}
|
}
|
||||||
if (!mapnik::util::is_directory(dir))
|
if (!mapnik::util::is_directory(dir))
|
||||||
{
|
{
|
||||||
return mapnik::freetype_engine::register_font_impl(dir, library);
|
return register_font_impl(dir, library, font_file_mapping);
|
||||||
}
|
}
|
||||||
bool success = false;
|
bool success = false;
|
||||||
try
|
try
|
||||||
|
@ -251,7 +208,7 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, FT_LibraryRec_
|
||||||
#endif
|
#endif
|
||||||
if (boost::filesystem::is_directory(*itr) && recurse)
|
if (boost::filesystem::is_directory(*itr) && recurse)
|
||||||
{
|
{
|
||||||
if (register_fonts_impl(file_name, library, true))
|
if (register_fonts_impl(file_name, library, font_file_mapping, true))
|
||||||
{
|
{
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
@ -267,7 +224,7 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, FT_LibraryRec_
|
||||||
mapnik::util::is_regular_file(file_name) &&
|
mapnik::util::is_regular_file(file_name) &&
|
||||||
is_font_file(file_name))
|
is_font_file(file_name))
|
||||||
{
|
{
|
||||||
if (mapnik::freetype_engine::register_font_impl(file_name, library))
|
if (register_font_impl(file_name, library, font_file_mapping))
|
||||||
{
|
{
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
@ -286,37 +243,58 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, FT_LibraryRec_
|
||||||
std::vector<std::string> freetype_engine::face_names ()
|
std::vector<std::string> freetype_engine::face_names ()
|
||||||
{
|
{
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
for (auto const& kv : name2file_)
|
for (auto const& kv : global_font_file_mapping_)
|
||||||
{
|
{
|
||||||
names.push_back(kv.first);
|
names.push_back(kv.first);
|
||||||
}
|
}
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string,std::pair<int,std::string> > const& freetype_engine::get_mapping()
|
freetype_engine::font_file_mapping_type const& freetype_engine::get_mapping()
|
||||||
{
|
{
|
||||||
return name2file_;
|
return global_font_file_mapping_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
face_ptr freetype_engine::create_face(std::string const& family_name)
|
face_ptr freetype_engine::create_face(std::string const& family_name,
|
||||||
|
util::font_library & library,
|
||||||
|
freetype_engine::font_file_mapping_type const& font_file_mapping,
|
||||||
|
freetype_engine::font_memory_cache_type const& font_cache)
|
||||||
{
|
{
|
||||||
auto itr = name2file_.find(family_name);
|
bool found_font_file = false;
|
||||||
if (itr != name2file_.end())
|
font_file_mapping_type::const_iterator itr = font_file_mapping.find(family_name);
|
||||||
|
if (itr != font_file_mapping.end())
|
||||||
{
|
{
|
||||||
FT_Face face;
|
found_font_file = true;
|
||||||
|
auto mem_font_itr = font_cache.find(itr->second.second);
|
||||||
auto mem_font_itr = memory_fonts_.find(itr->second.second);
|
if (mem_font_itr != font_cache.end()) // memory font
|
||||||
|
|
||||||
if (mem_font_itr != memory_fonts_.end()) // memory font
|
|
||||||
{
|
{
|
||||||
FT_Error error = FT_New_Memory_Face(library_,
|
face_ptr face = library.face_from_memory(mem_font_itr->second.first.get(),
|
||||||
reinterpret_cast<FT_Byte const*>(mem_font_itr->second.first.get()), // data
|
mem_font_itr->second.second,
|
||||||
static_cast<FT_Long>(mem_font_itr->second.second), // size
|
itr->second.first);
|
||||||
itr->second.first, // face index
|
if (face)
|
||||||
&face);
|
{
|
||||||
|
return face;
|
||||||
if (!error) return std::make_shared<font_face>(face);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
itr = global_font_file_mapping_.find(family_name);
|
||||||
|
if (itr != global_font_file_mapping_.end())
|
||||||
|
{
|
||||||
|
found_font_file = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found_font_file)
|
||||||
|
{
|
||||||
|
auto mem_font_itr = global_memory_fonts_.find(itr->second.second);
|
||||||
|
if (mem_font_itr != global_memory_fonts_.end()) // memory font
|
||||||
|
{
|
||||||
|
face_ptr face = library.face_from_memory(mem_font_itr->second.first.get(),
|
||||||
|
mem_font_itr->second.second,
|
||||||
|
itr->second.first);
|
||||||
|
if (face) return face;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -325,41 +303,29 @@ face_ptr freetype_engine::create_face(std::string const& family_name)
|
||||||
mapnik::scoped_lock lock(mutex_);
|
mapnik::scoped_lock lock(mutex_);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
mapnik::util::file file(itr->second.second);
|
||||||
std::unique_ptr<std::FILE, int (*)(std::FILE *)> file(_wfopen(mapnik::utf8_to_utf16(itr->second.second).c_str(), L"rb"), fclose);
|
if (file.open())
|
||||||
#else
|
|
||||||
std::unique_ptr<std::FILE, int (*)(std::FILE *)> file(std::fopen(itr->second.second.c_str(),"rb"), std::fclose);
|
|
||||||
#endif
|
|
||||||
if (file != nullptr)
|
|
||||||
{
|
{
|
||||||
std::fseek(file.get(), 0, SEEK_END);
|
auto result = global_memory_fonts_.emplace(itr->second.second, std::make_pair(std::move(file.data()),file.size()));
|
||||||
std::size_t file_size = std::ftell(file.get());
|
face_ptr face = library.face_from_memory(result.first->second.first.get(),
|
||||||
std::fseek(file.get(), 0, SEEK_SET);
|
result.first->second.second,
|
||||||
std::unique_ptr<char[]> buffer(new char[file_size]);
|
itr->second.first);
|
||||||
std::fread(buffer.get(), file_size, 1, file.get());
|
if (!face)
|
||||||
auto result = memory_fonts_.emplace(itr->second.second, std::make_pair(std::move(buffer),file_size));
|
|
||||||
FT_Error error = FT_New_Memory_Face (library_,
|
|
||||||
reinterpret_cast<FT_Byte const*>(result.first->second.first.get()),
|
|
||||||
static_cast<FT_Long>(result.first->second.second),
|
|
||||||
itr->second.first,
|
|
||||||
&face);
|
|
||||||
if (!error) return std::make_shared<font_face>(face);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// we can't load font, erase it.
|
// we can't load font, erase it.
|
||||||
memory_fonts_.erase(result.first);
|
global_memory_fonts_.erase(result.first);
|
||||||
}
|
}
|
||||||
|
return face;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return face_ptr();
|
return face_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stroker_ptr freetype_engine::create_stroker()
|
stroker_ptr freetype_engine::create_stroker()
|
||||||
{
|
{
|
||||||
FT_Stroker s;
|
FT_Stroker s;
|
||||||
FT_Error error = FT_Stroker_New(library_, &s);
|
FT_Error error = FT_Stroker_New(library_.get(), &s);
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
return std::make_shared<stroker>(s);
|
return std::make_shared<stroker>(s);
|
||||||
|
@ -367,10 +333,7 @@ stroker_ptr freetype_engine::create_stroker()
|
||||||
return stroker_ptr();
|
return stroker_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
face_ptr face_manager::get_face(std::string const& name)
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
face_ptr face_manager<T>::get_face(std::string const& name)
|
|
||||||
{
|
{
|
||||||
auto itr = face_ptr_cache_.find(name);
|
auto itr = face_ptr_cache_.find(name);
|
||||||
if (itr != face_ptr_cache_.end())
|
if (itr != face_ptr_cache_.end())
|
||||||
|
@ -379,7 +342,7 @@ face_ptr face_manager<T>::get_face(std::string const& name)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
face_ptr face = engine_.create_face(name);
|
face_ptr face = engine_.create_face(name,library_,font_file_mapping_,font_memory_cache_);
|
||||||
if (face)
|
if (face)
|
||||||
{
|
{
|
||||||
face_ptr_cache_.emplace(name,face);
|
face_ptr_cache_.emplace(name,face);
|
||||||
|
@ -388,8 +351,7 @@ face_ptr face_manager<T>::get_face(std::string const& name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
face_set_ptr face_manager::get_face_set(std::string const& name)
|
||||||
face_set_ptr face_manager<T>::get_face_set(std::string const& name)
|
|
||||||
{
|
{
|
||||||
face_set_ptr face_set = std::make_shared<font_face_set>();
|
face_set_ptr face_set = std::make_shared<font_face_set>();
|
||||||
if (face_ptr face = get_face(name))
|
if (face_ptr face = get_face(name))
|
||||||
|
@ -399,8 +361,7 @@ face_set_ptr face_manager<T>::get_face_set(std::string const& name)
|
||||||
return face_set;
|
return face_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
face_set_ptr face_manager::get_face_set(font_set const& fset)
|
||||||
face_set_ptr face_manager<T>::get_face_set(font_set const& fset)
|
|
||||||
{
|
{
|
||||||
std::vector<std::string> const& names = fset.get_face_names();
|
std::vector<std::string> const& names = fset.get_face_names();
|
||||||
face_set_ptr face_set = std::make_shared<font_face_set>();
|
face_set_ptr face_set = std::make_shared<font_face_set>();
|
||||||
|
@ -423,8 +384,7 @@ face_set_ptr face_manager<T>::get_face_set(font_set const& fset)
|
||||||
return face_set;
|
return face_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
face_set_ptr face_manager::get_face_set(const std::string &name, boost::optional<font_set> fset)
|
||||||
face_set_ptr face_manager<T>::get_face_set(const std::string &name, boost::optional<font_set> fset)
|
|
||||||
{
|
{
|
||||||
if (fset && fset->size() > 0)
|
if (fset && fset->size() > 0)
|
||||||
{
|
{
|
||||||
|
@ -439,8 +399,7 @@ face_set_ptr face_manager<T>::get_face_set(const std::string &name, boost::optio
|
||||||
#ifdef MAPNIK_THREADSAFE
|
#ifdef MAPNIK_THREADSAFE
|
||||||
std::mutex freetype_engine::mutex_;
|
std::mutex freetype_engine::mutex_;
|
||||||
#endif
|
#endif
|
||||||
std::map<std::string,std::pair<int,std::string> > freetype_engine::name2file_;
|
freetype_engine::font_file_mapping_type freetype_engine::global_font_file_mapping_;
|
||||||
std::map<std::string,std::pair<std::unique_ptr<char[]>,std::size_t> > freetype_engine::memory_fonts_;
|
std::map<std::string,std::pair<std::unique_ptr<char[]>,std::size_t> > freetype_engine::global_memory_fonts_;
|
||||||
template class face_manager<freetype_engine>;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
99
src/font_library.cpp
Normal file
99
src/font_library.cpp
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/util/font_library.hpp>
|
||||||
|
#include <mapnik/text/face.hpp>
|
||||||
|
|
||||||
|
// stl
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
// freetype2
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_MODULE_H
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void* _Alloc_Func(FT_Memory memory, long size)
|
||||||
|
{
|
||||||
|
return std::malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _Free_Func(FT_Memory memory, void *block)
|
||||||
|
{
|
||||||
|
std::free(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* _Realloc_Func(FT_Memory memory, long cur_size, long new_size, void* block)
|
||||||
|
{
|
||||||
|
return std::realloc(block, new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mapnik {
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
|
||||||
|
font_library::font_library()
|
||||||
|
: library_(nullptr),
|
||||||
|
memory_(new FT_MemoryRec_)
|
||||||
|
{
|
||||||
|
memory_->alloc = _Alloc_Func;
|
||||||
|
memory_->free = _Free_Func;
|
||||||
|
memory_->realloc = _Realloc_Func;
|
||||||
|
FT_Error error = FT_New_Library(&*memory_, &library_);
|
||||||
|
if (error) throw std::runtime_error("can not initalize FreeType2 library");
|
||||||
|
FT_Add_Default_Modules(library_);
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Library font_library::get() {
|
||||||
|
return library_;
|
||||||
|
}
|
||||||
|
|
||||||
|
face_ptr font_library::face_from_memory(const char * buffer,
|
||||||
|
std::size_t size,
|
||||||
|
int index)
|
||||||
|
{
|
||||||
|
FT_Face face;
|
||||||
|
FT_Error error = FT_New_Memory_Face(library_,
|
||||||
|
reinterpret_cast<FT_Byte const*>(buffer), // data
|
||||||
|
static_cast<FT_Long>(size), // size
|
||||||
|
index, // face index
|
||||||
|
&face);
|
||||||
|
if (!error) return std::make_shared<font_face>(face);
|
||||||
|
return face_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
font_library::~font_library() {
|
||||||
|
FT_Done_Library(library_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace util
|
||||||
|
|
||||||
|
} // end namespace mapnik
|
|
@ -84,10 +84,10 @@ constexpr unsigned name2int(const char *str, int off = 0)
|
||||||
class map_parser : mapnik::noncopyable
|
class map_parser : mapnik::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
map_parser(bool strict, std::string const& filename = "") :
|
map_parser(Map & map, bool strict, std::string const& filename = "") :
|
||||||
strict_(strict),
|
strict_(strict),
|
||||||
filename_(filename),
|
filename_(filename),
|
||||||
font_manager_(font_engine_),
|
font_manager_(font_engine_,map.get_font_file_mapping(),map.get_font_memory_cache()),
|
||||||
xml_base_path_()
|
xml_base_path_()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ private:
|
||||||
std::string filename_;
|
std::string filename_;
|
||||||
std::map<std::string,parameters> datasource_templates_;
|
std::map<std::string,parameters> datasource_templates_;
|
||||||
freetype_engine font_engine_;
|
freetype_engine font_engine_;
|
||||||
face_manager<freetype_engine> font_manager_;
|
face_manager_freetype font_manager_;
|
||||||
std::map<std::string,std::string> file_sources_;
|
std::map<std::string,std::string> file_sources_;
|
||||||
std::map<std::string,font_set> fontsets_;
|
std::map<std::string,font_set> fontsets_;
|
||||||
std::string xml_base_path_;
|
std::string xml_base_path_;
|
||||||
|
@ -143,7 +143,7 @@ void load_map(Map & map, std::string const& filename, bool strict, std::string b
|
||||||
xml_tree tree("utf8");
|
xml_tree tree("utf8");
|
||||||
tree.set_filename(filename);
|
tree.set_filename(filename);
|
||||||
read_xml(filename, tree.root());
|
read_xml(filename, tree.root());
|
||||||
map_parser parser(strict, filename);
|
map_parser parser(map, strict, filename);
|
||||||
parser.parse_map(map, tree.root(), base_path);
|
parser.parse_map(map, tree.root(), base_path);
|
||||||
//dump_xml(tree.root());
|
//dump_xml(tree.root());
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ void load_map_string(Map & map, std::string const& str, bool strict, std::string
|
||||||
{
|
{
|
||||||
read_xml_string(str, tree.root(), map.base_path()); // FIXME - this value is not fully known yet
|
read_xml_string(str, tree.root(), map.base_path()); // FIXME - this value is not fully known yet
|
||||||
}
|
}
|
||||||
map_parser parser(strict, base_path);
|
map_parser parser(map, strict, base_path);
|
||||||
parser.parse_map(map, tree.root(), base_path);
|
parser.parse_map(map, tree.root(), base_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +262,9 @@ void map_parser::parse_map(Map & map, xml_node const& node, std::string const& b
|
||||||
optional<std::string> font_directory = map_node.get_opt_attr<std::string>("font-directory");
|
optional<std::string> font_directory = map_node.get_opt_attr<std::string>("font-directory");
|
||||||
if (font_directory)
|
if (font_directory)
|
||||||
{
|
{
|
||||||
if (!freetype_engine::register_fonts(ensure_relative_to_xml(font_directory), false))
|
map.set_font_directory(*font_directory);
|
||||||
|
if (!map.register_fonts(ensure_relative_to_xml(font_directory), false))
|
||||||
|
//if (!freetype_engine::register_fonts(ensure_relative_to_xml(font_directory), false))
|
||||||
{
|
{
|
||||||
if (strict_)
|
if (strict_)
|
||||||
{
|
{
|
||||||
|
|
59
src/map.cpp
59
src/map.cpp
|
@ -38,8 +38,9 @@
|
||||||
#include <mapnik/scale_denominator.hpp>
|
#include <mapnik/scale_denominator.hpp>
|
||||||
#include <mapnik/config_error.hpp>
|
#include <mapnik/config_error.hpp>
|
||||||
#include <mapnik/config.hpp> // for PROJ_ENVELOPE_POINTS
|
#include <mapnik/config.hpp> // for PROJ_ENVELOPE_POINTS
|
||||||
|
#include <mapnik/util/font_library.hpp>
|
||||||
// boost
|
#include <mapnik/util/file_io.hpp>
|
||||||
|
#include <mapnik/font_engine_freetype.hpp>
|
||||||
|
|
||||||
// stl
|
// stl
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -70,7 +71,11 @@ Map::Map()
|
||||||
background_image_comp_op_(src_over),
|
background_image_comp_op_(src_over),
|
||||||
background_image_opacity_(1.0),
|
background_image_opacity_(1.0),
|
||||||
aspectFixMode_(GROW_BBOX),
|
aspectFixMode_(GROW_BBOX),
|
||||||
base_path_("") {}
|
base_path_(""),
|
||||||
|
extra_params_(),
|
||||||
|
font_directory_(),
|
||||||
|
font_file_mapping_(),
|
||||||
|
font_memory_cache_() {}
|
||||||
|
|
||||||
Map::Map(int width,int height, std::string const& srs)
|
Map::Map(int width,int height, std::string const& srs)
|
||||||
: width_(width),
|
: width_(width),
|
||||||
|
@ -80,7 +85,11 @@ Map::Map(int width,int height, std::string const& srs)
|
||||||
background_image_comp_op_(src_over),
|
background_image_comp_op_(src_over),
|
||||||
background_image_opacity_(1.0),
|
background_image_opacity_(1.0),
|
||||||
aspectFixMode_(GROW_BBOX),
|
aspectFixMode_(GROW_BBOX),
|
||||||
base_path_("") {}
|
base_path_(""),
|
||||||
|
extra_params_(),
|
||||||
|
font_directory_(),
|
||||||
|
font_file_mapping_(),
|
||||||
|
font_memory_cache_() {}
|
||||||
|
|
||||||
Map::Map(Map const& rhs)
|
Map::Map(Map const& rhs)
|
||||||
: width_(rhs.width_),
|
: width_(rhs.width_),
|
||||||
|
@ -98,7 +107,11 @@ Map::Map(Map const& rhs)
|
||||||
current_extent_(rhs.current_extent_),
|
current_extent_(rhs.current_extent_),
|
||||||
maximum_extent_(rhs.maximum_extent_),
|
maximum_extent_(rhs.maximum_extent_),
|
||||||
base_path_(rhs.base_path_),
|
base_path_(rhs.base_path_),
|
||||||
extra_params_(rhs.extra_params_) {}
|
extra_params_(rhs.extra_params_),
|
||||||
|
font_directory_(rhs.font_directory_),
|
||||||
|
font_file_mapping_(rhs.font_file_mapping_),
|
||||||
|
// on copy discard memory cache
|
||||||
|
font_memory_cache_() {}
|
||||||
|
|
||||||
|
|
||||||
Map::Map(Map && rhs)
|
Map::Map(Map && rhs)
|
||||||
|
@ -117,11 +130,13 @@ Map::Map(Map && rhs)
|
||||||
current_extent_(std::move(rhs.current_extent_)),
|
current_extent_(std::move(rhs.current_extent_)),
|
||||||
maximum_extent_(std::move(rhs.maximum_extent_)),
|
maximum_extent_(std::move(rhs.maximum_extent_)),
|
||||||
base_path_(std::move(rhs.base_path_)),
|
base_path_(std::move(rhs.base_path_)),
|
||||||
extra_params_(std::move(rhs.extra_params_)) {}
|
extra_params_(std::move(rhs.extra_params_)),
|
||||||
|
font_directory_(std::move(rhs.font_directory_)),
|
||||||
|
font_file_mapping_(std::move(rhs.font_file_mapping_)),
|
||||||
|
font_memory_cache_(std::move(rhs.font_memory_cache_)) {}
|
||||||
|
|
||||||
Map::~Map() {}
|
Map::~Map() {}
|
||||||
|
|
||||||
|
|
||||||
Map& Map::operator=(Map rhs)
|
Map& Map::operator=(Map rhs)
|
||||||
{
|
{
|
||||||
swap(*this, rhs);
|
swap(*this, rhs);
|
||||||
|
@ -147,9 +162,11 @@ void swap (Map & lhs, Map & rhs)
|
||||||
std::swap(lhs.maximum_extent_, rhs.maximum_extent_);
|
std::swap(lhs.maximum_extent_, rhs.maximum_extent_);
|
||||||
std::swap(lhs.base_path_, rhs.base_path_);
|
std::swap(lhs.base_path_, rhs.base_path_);
|
||||||
std::swap(lhs.extra_params_, rhs.extra_params_);
|
std::swap(lhs.extra_params_, rhs.extra_params_);
|
||||||
|
std::swap(lhs.font_directory_,rhs.font_directory_);
|
||||||
|
std::swap(lhs.font_file_mapping_,rhs.font_file_mapping_);
|
||||||
|
std::swap(lhs.font_memory_cache_,rhs.font_memory_cache_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Map::operator==(Map const& rhs) const
|
bool Map::operator==(Map const& rhs) const
|
||||||
{
|
{
|
||||||
return (width_ == rhs.width_) &&
|
return (width_ == rhs.width_) &&
|
||||||
|
@ -167,7 +184,10 @@ bool Map::operator==(Map const& rhs) const
|
||||||
(current_extent_ == rhs.current_extent_) &&
|
(current_extent_ == rhs.current_extent_) &&
|
||||||
(maximum_extent_ == rhs.maximum_extent_) &&
|
(maximum_extent_ == rhs.maximum_extent_) &&
|
||||||
(base_path_ == rhs.base_path_) &&
|
(base_path_ == rhs.base_path_) &&
|
||||||
(extra_params_ == rhs.extra_params_);
|
(extra_params_ == rhs.extra_params_) &&
|
||||||
|
(font_directory_ == rhs.font_directory_) &&
|
||||||
|
(font_file_mapping_ == rhs.font_file_mapping_) &&
|
||||||
|
(font_memory_cache_ == rhs.font_memory_cache_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string,feature_type_style> const& Map::styles() const
|
std::map<std::string,feature_type_style> const& Map::styles() const
|
||||||
|
@ -247,6 +267,27 @@ std::map<std::string,font_set> & Map::fontsets()
|
||||||
return fontsets_;
|
return fontsets_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Map::register_fonts(std::string const& dir, bool recurse)
|
||||||
|
{
|
||||||
|
util::font_library library;
|
||||||
|
return freetype_engine::register_fonts_impl(dir, library, font_file_mapping_, recurse);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Map::load_fonts()
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
for (auto const& kv : font_file_mapping_)
|
||||||
|
{
|
||||||
|
mapnik::util::file file(kv.second.second);
|
||||||
|
if (file.open())
|
||||||
|
{
|
||||||
|
auto item = font_memory_cache_.emplace(kv.second.second, std::make_pair(std::move(file.data()),file.size()));
|
||||||
|
if (item.second) result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
size_t Map::layer_count() const
|
size_t Map::layer_count() const
|
||||||
{
|
{
|
||||||
return layers_.size();
|
return layers_.size();
|
||||||
|
|
|
@ -38,7 +38,7 @@ renderer_common::renderer_common(Map const& map, unsigned width, unsigned height
|
||||||
vars_(vars),
|
vars_(vars),
|
||||||
shared_font_engine_(std::make_shared<freetype_engine>()),
|
shared_font_engine_(std::make_shared<freetype_engine>()),
|
||||||
font_engine_(*shared_font_engine_),
|
font_engine_(*shared_font_engine_),
|
||||||
font_manager_(font_engine_),
|
font_manager_(font_engine_,map.get_font_file_mapping(),map.get_font_memory_cache()),
|
||||||
query_extent_(),
|
query_extent_(),
|
||||||
t_(t),
|
t_(t),
|
||||||
detector_(detector)
|
detector_(detector)
|
||||||
|
|
|
@ -625,6 +625,12 @@ void serialize_map(ptree & pt, Map const& map, bool explicit_defaults)
|
||||||
set_attr( map_node, "background-color", * c );
|
set_attr( map_node, "background-color", * c );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional<std::string> const& font_directory = map.font_directory();
|
||||||
|
if ( font_directory )
|
||||||
|
{
|
||||||
|
set_attr( map_node, "font-directory", *font_directory );
|
||||||
|
}
|
||||||
|
|
||||||
optional<std::string> const& image_filename = map.background_image();
|
optional<std::string> const& image_filename = map.background_image();
|
||||||
if ( image_filename )
|
if ( image_filename )
|
||||||
{
|
{
|
||||||
|
|
|
@ -341,7 +341,7 @@ template text_symbolizer_helper::text_symbolizer_helper(
|
||||||
unsigned height,
|
unsigned height,
|
||||||
double scale_factor,
|
double scale_factor,
|
||||||
view_transform const& t,
|
view_transform const& t,
|
||||||
face_manager<freetype_engine> &font_manager,
|
face_manager_freetype & font_manager,
|
||||||
label_collision_detector4 &detector,
|
label_collision_detector4 &detector,
|
||||||
box2d<double> const& query_extent,
|
box2d<double> const& query_extent,
|
||||||
agg::trans_affine const&);
|
agg::trans_affine const&);
|
||||||
|
@ -355,7 +355,7 @@ template text_symbolizer_helper::text_symbolizer_helper(
|
||||||
unsigned height,
|
unsigned height,
|
||||||
double scale_factor,
|
double scale_factor,
|
||||||
view_transform const& t,
|
view_transform const& t,
|
||||||
face_manager<freetype_engine> &font_manager,
|
face_manager_freetype & font_manager,
|
||||||
label_collision_detector4 &detector,
|
label_collision_detector4 &detector,
|
||||||
box2d<double> const& query_extent,
|
box2d<double> const& query_extent,
|
||||||
agg::trans_affine const&);
|
agg::trans_affine const&);
|
||||||
|
|
Loading…
Reference in a new issue