Merge branch 'master' of github.com:mapnik/mapnik into layer-opacity
Conflicts: src/layer.cpp
This commit is contained in:
commit
dc5b9202ac
41 changed files with 778 additions and 301 deletions
20
.travis.yml
20
.travis.yml
|
@ -17,21 +17,22 @@ before_install:
|
|||
- sudo apt-get -qq purge postgis* postgresql*
|
||||
- sudo apt-add-repository -y ppa:cartodb/postgresql-9.3
|
||||
- sudo apt-add-repository -y ppa:cartodb/gis
|
||||
# grab harfbuzz from ppa
|
||||
- sudo apt-add-repository -y ppa:fontforge/fontforge
|
||||
# we need at least g++-4.7 for c++11 features
|
||||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
# upgrade boost
|
||||
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||
# enable to test against latest boost rather that v1.48
|
||||
#- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||
- sudo rm -Rf /var/lib/postgresql /etc/postgresql
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -q postgresql-9.3-postgis-2.1
|
||||
- sudo apt-get install -q postgresql-contrib-9.3
|
||||
- sudo apt-get install -q gdal-bin libgdal-dev
|
||||
- sudo apt-get install -q libharfbuzz-dev postgresql-9.3-postgis-2.1 postgresql-contrib-9.3 gdal-bin libgdal-dev
|
||||
- echo -e "local\tall\tall\ttrust\nhost\tall\tall\t127.0.0.1/32\ttrust\nhost\tall\tall\t::1/128\ttrust" |sudo tee /etc/postgresql/9.3/main/pg_hba.conf
|
||||
- sudo service postgresql restart
|
||||
|
||||
install:
|
||||
#- sudo apt-get install -y libboost-python1.48-dev libboost-thread1.48-dev libboost-filesystem1.48-dev libboost-regex1.48-dev libboost-program-options1.48-dev
|
||||
- sudo apt-get install -y boost1.55
|
||||
# enable to test against boost ppa
|
||||
#- sudo apt-get install -y boost1.55
|
||||
- sudo apt-get install -y libboost-python1.48-dev libboost-thread1.48-dev libboost-filesystem1.48-dev libboost-regex1.48-dev libboost-program-options1.48-dev
|
||||
- sudo apt-get install -y ttf-wqy-microhei make libstdc++6 libstdc++-4.8-dev valgrind python-nose libicu-dev libproj-dev libcairo-dev python-cairo-dev libcairo-dev python-cairo-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libsqlite3-dev
|
||||
|
||||
before_script:
|
||||
|
@ -39,11 +40,6 @@ before_script:
|
|||
- psql -U postgres -c 'create extension postgis' -d template_postgis
|
||||
- if [[ "${CXX}" == 'g++' ]]; then export JOBS=2; sudo apt-get install gcc-4.8 g++-4.8; export CXX="$(which g++-4.8)"; export CC="$(which gcc-4.8)"; fi;
|
||||
- if [[ "${CXX}" == 'clang++' ]]; then export JOBS=4; export CXX="$(which clang++)"; export CC="$(which clang)"; fi;
|
||||
- wget http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-0.9.35.tar.bz2
|
||||
- tar xf harfbuzz-0.9.35.tar.bz2
|
||||
- cd harfbuzz-0.9.35
|
||||
- ./configure --prefix=/usr --with-icu --with-cairo=no --with-glib=no --with-gobject=no --with-graphite2=no --with-freetype --with-uniscribe=no --with-coretext=no && make -j2 && sudo make -j2 install
|
||||
- cd ../
|
||||
|
||||
script:
|
||||
- ./configure CXX="${CXX}" CC="${CC}" CUSTOM_CXXFLAGS="${CUSTOM_CXXFLAGS}" CUSTOM_LDFLAGS="${CUSTOM_LDFLAGS}" XML_PARSER="${XML_PARSER}" ENABLE_LOG="${ENABLE_LOG}" DEBUG="${DEBUG}" DEMO="${DEMO}" BENCHMARK="${BENCHMARK}" CPP_TESTS=True CAIRO=True FAST=True || cat config.log
|
||||
|
|
|
@ -50,7 +50,7 @@ For troubleshooting help see https://github.com/mapnik/mapnik/wiki/InstallationT
|
|||
|
||||
Build system dependencies are:
|
||||
|
||||
* C++ compiler (like g++ or clang++)
|
||||
* C++ compiler supporting `-std=c++11` (like >= g++ 4.8 or >= clang++ 3.4)
|
||||
* >= 2 GB RAM (> 5 GB for g++)
|
||||
* Python 2.4-2.7
|
||||
* Scons (a copy is bundled)
|
||||
|
|
|
@ -11,24 +11,38 @@ public:
|
|||
{
|
||||
std::size_t count = 0;
|
||||
std::size_t expected_count = mapnik::freetype_engine::face_names().size();
|
||||
mapnik::freetype_engine engine;
|
||||
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())
|
||||
{
|
||||
mapnik::face_ptr f = engine.create_face(name);
|
||||
mapnik::face_ptr f = mapnik::freetype_engine::create_face(name,
|
||||
library,
|
||||
font_file_mapping,
|
||||
font_cache,
|
||||
mapnik::freetype_engine::get_mapping(),
|
||||
mapnik::freetype_engine::get_cache());
|
||||
if (f) ++count;
|
||||
}
|
||||
return count == expected_count;
|
||||
}
|
||||
void operator()() const
|
||||
{
|
||||
mapnik::freetype_engine engine;
|
||||
std::size_t expected_count = mapnik::freetype_engine::face_names().size();
|
||||
for (unsigned i=0;i<iterations_;++i)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
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())
|
||||
{
|
||||
mapnik::face_ptr f = engine.create_face(name);
|
||||
mapnik::face_ptr f = mapnik::freetype_engine::create_face(name,
|
||||
library,
|
||||
font_file_mapping,
|
||||
font_cache,
|
||||
mapnik::freetype_engine::get_mapping(),
|
||||
mapnik::freetype_engine::get_cache());
|
||||
if (f) ++count;
|
||||
}
|
||||
if (count != expected_count) {
|
||||
|
|
|
@ -78,18 +78,18 @@ void check_object_status_and_throw_exception(T const& object)
|
|||
class cairo_face : private mapnik::noncopyable
|
||||
{
|
||||
public:
|
||||
cairo_face(std::shared_ptr<freetype_engine> const& engine, face_ptr const& face);
|
||||
cairo_face(std::shared_ptr<font_library> const& library, face_ptr const& face);
|
||||
~cairo_face();
|
||||
cairo_font_face_t * face() const;
|
||||
private:
|
||||
class handle
|
||||
{
|
||||
public:
|
||||
handle(std::shared_ptr<freetype_engine> const& engine, face_ptr const& face)
|
||||
: engine_(engine), face_(face) {}
|
||||
handle(std::shared_ptr<font_library> const& library, face_ptr const& face)
|
||||
: library_(library), face_(face) {}
|
||||
|
||||
private:
|
||||
std::shared_ptr<freetype_engine> engine_;
|
||||
std::shared_ptr<font_library> library_;
|
||||
face_ptr face_;
|
||||
};
|
||||
|
||||
|
@ -109,12 +109,12 @@ using cairo_face_ptr = std::shared_ptr<cairo_face>;
|
|||
class cairo_face_manager : private mapnik::noncopyable
|
||||
{
|
||||
public:
|
||||
cairo_face_manager(std::shared_ptr<freetype_engine> engine);
|
||||
cairo_face_manager(std::shared_ptr<font_library> library);
|
||||
cairo_face_ptr get_face(face_ptr face);
|
||||
|
||||
private:
|
||||
using cairo_face_cache = std::map<face_ptr,cairo_face_ptr>;
|
||||
std::shared_ptr<freetype_engine> font_engine_;
|
||||
std::shared_ptr<font_library> font_library_;
|
||||
cairo_face_cache cache_;
|
||||
};
|
||||
|
||||
|
@ -321,7 +321,7 @@ public:
|
|||
void glyph_path(unsigned long index, pixel_position const& pos);
|
||||
void add_text(glyph_positions_ptr pos,
|
||||
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 halo_comp_op = src_over,
|
||||
double scale_factor = 1.0);
|
||||
|
|
|
@ -68,7 +68,7 @@ public:
|
|||
// ctor
|
||||
feature_type_style();
|
||||
feature_type_style(feature_type_style const& rhs);
|
||||
feature_type_style(feature_type_style &&) = default;
|
||||
feature_type_style(feature_type_style && rhs);
|
||||
feature_type_style& operator=(feature_type_style rhs);
|
||||
|
||||
// comparison
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
// mapnik
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/font_set.hpp>
|
||||
#include <mapnik/text/font_library.hpp>
|
||||
#include <mapnik/noncopyable.hpp>
|
||||
|
||||
// stl
|
||||
|
@ -38,8 +39,6 @@
|
|||
#include <mutex>
|
||||
#endif
|
||||
|
||||
struct FT_LibraryRec_;
|
||||
struct FT_MemoryRec_;
|
||||
namespace boost { template <class T> class optional; }
|
||||
|
||||
namespace mapnik
|
||||
|
@ -48,14 +47,15 @@ namespace mapnik
|
|||
class stroker;
|
||||
using stroker_ptr = std::shared_ptr<stroker>;
|
||||
class font_face_set;
|
||||
using face_set_ptr = std::shared_ptr<font_face_set>;
|
||||
using face_set_ptr = std::unique_ptr<font_face_set>;
|
||||
class font_face;
|
||||
using face_ptr = std::shared_ptr<font_face>;
|
||||
|
||||
|
||||
class MAPNIK_DECL freetype_engine
|
||||
{
|
||||
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);
|
||||
/*! \brief register a font file
|
||||
* @param file_name path to a font file.
|
||||
|
@ -69,50 +69,59 @@ public:
|
|||
*/
|
||||
static bool register_fonts(std::string const& dir, bool recurse = false);
|
||||
static std::vector<std::string> face_names();
|
||||
static std::map<std::string, std::pair<int,std::string> > const& get_mapping();
|
||||
face_ptr create_face(std::string const& family_name);
|
||||
stroker_ptr create_stroker();
|
||||
static font_file_mapping_type const& get_mapping();
|
||||
static font_memory_cache_type & get_cache();
|
||||
static 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,
|
||||
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,
|
||||
font_library & libary,
|
||||
font_file_mapping_type & font_file_mapping);
|
||||
static 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);
|
||||
FT_LibraryRec_ * library_;
|
||||
std::unique_ptr<FT_MemoryRec_> memory_;
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
static std::mutex mutex_;
|
||||
#endif
|
||||
static std::map<std::string, std::pair<int,std::string> > name2file_;
|
||||
static std::map<std::string, std::pair<std::unique_ptr<char[]>, std::size_t> > memory_fonts_;
|
||||
static font_file_mapping_type global_font_file_mapping_;
|
||||
static font_memory_cache_type global_memory_fonts_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MAPNIK_DECL face_manager : private mapnik::noncopyable
|
||||
{
|
||||
using font_engine_type = T;
|
||||
using face_ptr_cache_type = std::map<std::string, face_ptr>;
|
||||
|
||||
public:
|
||||
face_manager(T & engine)
|
||||
: engine_(engine),
|
||||
stroker_(engine_.create_stroker()),
|
||||
face_ptr_cache_() {}
|
||||
|
||||
face_manager(font_library & library,
|
||||
freetype_engine::font_file_mapping_type const& font_file_mapping,
|
||||
freetype_engine::font_memory_cache_type const& font_cache);
|
||||
face_ptr get_face(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(std::string const& name, boost::optional<font_set> fset);
|
||||
|
||||
|
||||
inline stroker_ptr get_stroker() { return stroker_; }
|
||||
|
||||
private:
|
||||
font_engine_type & engine_;
|
||||
stroker_ptr stroker_;
|
||||
face_ptr_cache_type face_ptr_cache_;
|
||||
font_library & library_;
|
||||
freetype_engine::font_file_mapping_type const& font_file_mapping_;
|
||||
freetype_engine::font_memory_cache_type const& font_memory_cache_;
|
||||
stroker_ptr stroker_;
|
||||
};
|
||||
|
||||
using face_manager_freetype = face_manager<freetype_engine>;
|
||||
using face_manager_freetype = face_manager;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
// mapnik
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/feature_style_processor.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
#include <mapnik/noncopyable.hpp>
|
||||
#include <mapnik/rule.hpp> // for rule, symbolizers
|
||||
|
|
|
@ -40,7 +40,7 @@ using bound_box = box2d<double>;
|
|||
|
||||
struct group_layout_manager
|
||||
{
|
||||
group_layout_manager(const group_layout &layout)
|
||||
group_layout_manager(group_layout const& layout)
|
||||
: layout_(layout),
|
||||
input_origin_(0, 0),
|
||||
member_boxes_(vector<bound_box>()),
|
||||
|
@ -49,7 +49,7 @@ struct group_layout_manager
|
|||
{
|
||||
}
|
||||
|
||||
group_layout_manager(const group_layout &layout, const pixel_position &input_origin)
|
||||
group_layout_manager(group_layout const& layout, pixel_position const& input_origin)
|
||||
: layout_(layout),
|
||||
input_origin_(input_origin),
|
||||
member_boxes_(vector<bound_box>()),
|
||||
|
@ -58,8 +58,8 @@ struct group_layout_manager
|
|||
{
|
||||
}
|
||||
|
||||
group_layout_manager(const group_layout &layout, const pixel_position &input_origin,
|
||||
const vector<bound_box> &item_boxes)
|
||||
group_layout_manager(group_layout const& layout, pixel_position const& input_origin,
|
||||
vector<bound_box> const& item_boxes)
|
||||
: layout_(layout),
|
||||
input_origin_(input_origin),
|
||||
member_boxes_(item_boxes),
|
||||
|
@ -68,19 +68,19 @@ struct group_layout_manager
|
|||
{
|
||||
}
|
||||
|
||||
inline void set_layout(const group_layout &layout)
|
||||
inline void set_layout(group_layout const& layout)
|
||||
{
|
||||
layout_ = layout;
|
||||
update_layout_ = true;
|
||||
}
|
||||
|
||||
inline void add_member_bound_box(const bound_box &member_box)
|
||||
inline void add_member_bound_box(bound_box const& member_box)
|
||||
{
|
||||
member_boxes_.push_back(member_box);
|
||||
update_layout_ = true;
|
||||
}
|
||||
|
||||
inline const pixel_position &offset_at(size_t i)
|
||||
inline pixel_position const& offset_at(size_t i)
|
||||
{
|
||||
handle_update();
|
||||
return member_offsets_.at(i);
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
unsigned width,
|
||||
unsigned height,
|
||||
double scale_factor,
|
||||
view_transform const &t,
|
||||
view_transform const& t,
|
||||
DetectorType &detector,
|
||||
box2d<double> const& query_extent);
|
||||
|
||||
|
@ -89,10 +89,10 @@ private:
|
|||
/** Check if a point placement fits at given position */
|
||||
bool check_point_placement(pixel_position const& pos);
|
||||
/** Checks for collision. */
|
||||
bool collision(box2d<double> const& box, const value_unicode_string &repeat_key = "") const;
|
||||
bool collision(box2d<double> const& box, value_unicode_string const& repeat_key = "") const;
|
||||
double get_spacing(double path_length) const;
|
||||
|
||||
DetectorType &detector_;
|
||||
DetectorType & detector_;
|
||||
|
||||
/** Boxes and repeat keys to take into account when finding placement.
|
||||
* Boxes are relative to starting point of current placement.
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <mapnik/params.hpp>
|
||||
#include <mapnik/well_known_srs.hpp>
|
||||
#include <mapnik/image_compositing.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/optional.hpp>
|
||||
|
@ -97,6 +98,9 @@ private:
|
|||
boost::optional<box2d<double> > maximum_extent_;
|
||||
std::string base_path_;
|
||||
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:
|
||||
|
||||
|
@ -166,13 +170,21 @@ public:
|
|||
*/
|
||||
style_iterator end_styles();
|
||||
|
||||
/*! \brief Insert a style in the map.
|
||||
/*! \brief Insert a style in the map by copying.
|
||||
* @param name The name of the style.
|
||||
* @param style The style to insert.
|
||||
* @return true If success.
|
||||
* false If no success.
|
||||
*/
|
||||
bool insert_style(std::string const& name,feature_type_style style);
|
||||
bool insert_style(std::string const& name,feature_type_style const& style);
|
||||
|
||||
/*! \brief Insert a style in the map by moving..
|
||||
* @param name The name of the style.
|
||||
* @param style The style to insert.
|
||||
* @return true If success.
|
||||
* false If no success.
|
||||
*/
|
||||
bool insert_style(std::string const& name,feature_type_style && style);
|
||||
|
||||
/*! \brief Remove a style from the map.
|
||||
* @param name The name of the style.
|
||||
|
@ -185,13 +197,21 @@ public:
|
|||
*/
|
||||
boost::optional<feature_type_style const&> find_style(std::string const& name) const;
|
||||
|
||||
/*! \brief Insert a fontset into the map.
|
||||
/*! \brief Insert a fontset into the map by copying.
|
||||
* @param name The name of the fontset.
|
||||
* @param fontset The fontset to insert.
|
||||
* @return true If success.
|
||||
* false If failure.
|
||||
*/
|
||||
bool insert_fontset(std::string const& name, font_set fontset);
|
||||
bool insert_fontset(std::string const& name, font_set const& fontset);
|
||||
|
||||
/*! \brief Insert a fontset into the map by moving.
|
||||
* @param name The name of the fontset.
|
||||
* @param fontset The fontset to insert.
|
||||
* @return true If success.
|
||||
* false If failure.
|
||||
*/
|
||||
bool insert_fontset(std::string const& name, font_set && fontset);
|
||||
|
||||
/*! \brief Find a fontset.
|
||||
* @param name The name of the fontset.
|
||||
|
@ -209,14 +229,27 @@ public:
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
size_t layer_count() const;
|
||||
|
||||
/*! \brief Add a layer to the map.
|
||||
/*! \brief Add a layer to the map by copying it.
|
||||
* @param l The layer to add.
|
||||
*/
|
||||
void add_layer(layer l);
|
||||
void add_layer(layer const& l);
|
||||
|
||||
/*! \brief Add a layer to the map by moving it.
|
||||
* @param l The layer to add.
|
||||
*/
|
||||
void add_layer(layer && l);
|
||||
|
||||
/*! \brief Get a layer.
|
||||
* @param index layer number.
|
||||
|
@ -437,6 +470,36 @@ public:
|
|||
*/
|
||||
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:
|
||||
friend void swap(Map & rhs, Map & lhs);
|
||||
void fixAspectRatio();
|
||||
|
|
|
@ -32,9 +32,8 @@
|
|||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <mapnik/graphics.hpp>
|
||||
#endif
|
||||
#include <mapnik/image_data.hpp>
|
||||
#include <mapnik/image_view.hpp>
|
||||
|
||||
/* miniz.c porting issues:
|
||||
- duplicate symbols in python bindings require moving miniz.c include to just cpp file
|
||||
|
@ -84,14 +83,12 @@ private:
|
|||
static const unsigned char IEND_tpl[];
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
template MAPNIK_DECL void PNGWriter::writeIDAT<image_data_8>(image_data_8 const& image);
|
||||
template MAPNIK_DECL void PNGWriter::writeIDAT<image_view<image_data_8> >(image_view<image_data_8> const& image);
|
||||
template MAPNIK_DECL void PNGWriter::writeIDAT<image_data_32>(image_data_32 const& image);
|
||||
template MAPNIK_DECL void PNGWriter::writeIDAT<image_view<image_data_32> >(image_view<image_data_32> const& image);
|
||||
template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_data_32>(image_data_32 const& image);
|
||||
template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_view<image_data_32> >(image_view<image_data_32> const& image);
|
||||
#endif
|
||||
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_data_8>(image_data_8 const& image);
|
||||
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_view<image_data_8> >(image_view<image_data_8> const& image);
|
||||
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_data_32>(image_data_32 const& image);
|
||||
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_view<image_data_32> >(image_view<image_data_32> const& image);
|
||||
extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_data_32>(image_data_32 const& image);
|
||||
extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_view<image_data_32> >(image_view<image_data_32> const& image);
|
||||
|
||||
}}
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ struct renderer_common : private mapnik::noncopyable
|
|||
double scale_factor_;
|
||||
attributes vars_;
|
||||
// TODO: dirty hack for cairo renderer, figure out how to remove this
|
||||
std::shared_ptr<freetype_engine> shared_font_engine_;
|
||||
freetype_engine &font_engine_;
|
||||
face_manager<freetype_engine> font_manager_;
|
||||
std::shared_ptr<font_library> shared_font_library_;
|
||||
font_library & font_library_;
|
||||
face_manager_freetype font_manager_;
|
||||
box2d<double> query_extent_;
|
||||
view_transform t_;
|
||||
std::shared_ptr<label_collision_detector4> detector_;
|
||||
|
|
|
@ -57,8 +57,8 @@ struct virtual_renderer_common : private mapnik::noncopyable
|
|||
height_(common.height_),
|
||||
scale_factor_(common.scale_factor_),
|
||||
vars_(common.vars_),
|
||||
shared_font_engine_(common.shared_font_engine_),
|
||||
font_engine_(*shared_font_engine_),
|
||||
shared_font_library_(common.shared_font_library_),
|
||||
font_library_(*shared_font_library_),
|
||||
font_manager_(common.font_manager_),
|
||||
query_extent_(common.query_extent_),
|
||||
t_(common.t_),
|
||||
|
@ -69,9 +69,9 @@ struct virtual_renderer_common : private mapnik::noncopyable
|
|||
double & scale_factor_;
|
||||
attributes & vars_;
|
||||
// TODO: dirty hack for cairo renderer, figure out how to remove this
|
||||
std::shared_ptr<freetype_engine> & shared_font_engine_;
|
||||
freetype_engine & font_engine_;
|
||||
face_manager<freetype_engine> & font_manager_;
|
||||
std::shared_ptr<font_library> & shared_font_library_;
|
||||
font_library & font_library_;
|
||||
face_manager_freetype & font_manager_;
|
||||
box2d<double> & query_extent_;
|
||||
view_transform & t_;
|
||||
std::shared_ptr<label_collision_detector4> detector_;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
// mapnik
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/feature_style_processor.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
#include <mapnik/svg/output/svg_generator.hpp>
|
||||
#include <mapnik/svg/output/svg_output_attributes.hpp>
|
||||
#include <mapnik/noncopyable.hpp>
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
private:
|
||||
std::vector<face_ptr> faces_;
|
||||
};
|
||||
using face_set_ptr = std::shared_ptr<font_face_set>;
|
||||
using face_set_ptr = std::unique_ptr<font_face_set>;
|
||||
|
||||
|
||||
// FT_Stroker wrapper
|
||||
|
|
51
include/mapnik/text/font_library.hpp
Normal file
51
include/mapnik/text/font_library.hpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* 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 <memory>
|
||||
|
||||
struct FT_LibraryRec_;
|
||||
struct FT_MemoryRec_;
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
class MAPNIK_DECL font_library : public noncopyable
|
||||
{
|
||||
public:
|
||||
explicit font_library();
|
||||
~font_library();
|
||||
FT_LibraryRec_ * get();
|
||||
private:
|
||||
FT_LibraryRec_ * library_;
|
||||
std::unique_ptr<FT_MemoryRec_> memory_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MAPNIK_FONT_LIBRARY_HPP
|
|
@ -47,6 +47,7 @@ public:
|
|||
boost::optional<symbolizer_base::value_type> jalign;
|
||||
boost::optional<symbolizer_base::value_type> text_ratio;
|
||||
boost::optional<symbolizer_base::value_type> wrap_width;
|
||||
boost::optional<symbolizer_base::value_type> wrap_char;
|
||||
boost::optional<symbolizer_base::value_type> wrap_before;
|
||||
boost::optional<symbolizer_base::value_type> repeat_wrap_char;
|
||||
boost::optional<symbolizer_base::value_type> rotate_displacement;
|
||||
|
|
|
@ -97,7 +97,7 @@ public:
|
|||
void add_child(text_layout_ptr const& child_layout);
|
||||
|
||||
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 text_layout_properties const& get_layout_properties() const { return properties_; }
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <mapnik/pixel_position.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/noncopyable.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_basics.h"
|
||||
|
@ -39,10 +40,10 @@ namespace mapnik
|
|||
{
|
||||
|
||||
class vertex_cache;
|
||||
using vertex_cache_ptr = std::shared_ptr<vertex_cache>;
|
||||
using vertex_cache_ptr = std::unique_ptr<vertex_cache>;
|
||||
|
||||
// Caches all path points and their lengths. Allows easy moving in both directions.
|
||||
class MAPNIK_DECL vertex_cache
|
||||
class MAPNIK_DECL vertex_cache : noncopyable
|
||||
{
|
||||
struct segment
|
||||
{
|
||||
|
|
92
include/mapnik/util/file_io.hpp
Normal file
92
include/mapnik/util/file_io.hpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* 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 *)>;
|
||||
using data_type = std::unique_ptr<char[]>;
|
||||
|
||||
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 data_type data() const
|
||||
{
|
||||
if (!size_) return nullptr;
|
||||
std::fseek(file_.get(), 0, SEEK_SET);
|
||||
data_type 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
|
|
@ -203,6 +203,7 @@ source = Split(
|
|||
svg/svg_transform_parser.cpp
|
||||
warp.cpp
|
||||
css_color_grammar.cpp
|
||||
text/font_library.cpp
|
||||
text/vertex_cache.cpp
|
||||
text/text_layout.cpp
|
||||
text/text_line.cpp
|
||||
|
|
|
@ -32,12 +32,12 @@
|
|||
#include <valarray>
|
||||
namespace mapnik {
|
||||
|
||||
cairo_face::cairo_face(std::shared_ptr<freetype_engine> const& engine, face_ptr const& face)
|
||||
cairo_face::cairo_face(std::shared_ptr<font_library> const& library, face_ptr const& face)
|
||||
: face_(face)
|
||||
{
|
||||
static cairo_user_data_key_t key;
|
||||
c_face_ = cairo_ft_font_face_create_for_ft_face(face->get_face(), FT_LOAD_NO_HINTING);
|
||||
cairo_font_face_set_user_data(c_face_, &key, new handle(engine, face), destroy);
|
||||
cairo_font_face_set_user_data(c_face_, &key, new handle(library, face), destroy);
|
||||
}
|
||||
|
||||
cairo_face::~cairo_face()
|
||||
|
@ -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,
|
||||
cairo_face_manager & manager,
|
||||
face_manager<freetype_engine> & font_manager,
|
||||
face_manager_freetype & font_manager,
|
||||
composite_mode_e comp_op,
|
||||
composite_mode_e halo_comp_op,
|
||||
double scale_factor)
|
||||
|
@ -508,8 +508,8 @@ void cairo_context::add_text(glyph_positions_ptr path,
|
|||
|
||||
}
|
||||
|
||||
cairo_face_manager::cairo_face_manager(std::shared_ptr<freetype_engine> font_engine)
|
||||
: font_engine_(font_engine)
|
||||
cairo_face_manager::cairo_face_manager(std::shared_ptr<font_library> font_library)
|
||||
: font_library_(font_library)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -524,7 +524,7 @@ cairo_face_ptr cairo_face_manager::get_face(face_ptr face)
|
|||
}
|
||||
else
|
||||
{
|
||||
entry = std::make_shared<cairo_face>(font_engine_, face);
|
||||
entry = std::make_shared<cairo_face>(font_library_, face);
|
||||
cache_.emplace(face, entry);
|
||||
}
|
||||
return entry;
|
||||
|
|
|
@ -58,7 +58,7 @@ cairo_renderer<T>::cairo_renderer(Map const& m,
|
|||
m_(m),
|
||||
context_(cairo),
|
||||
common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor),
|
||||
face_manager_(common_.shared_font_engine_)
|
||||
face_manager_(common_.shared_font_library_)
|
||||
{
|
||||
setup(m);
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ cairo_renderer<T>::cairo_renderer(Map const& m,
|
|||
m_(m),
|
||||
context_(cairo),
|
||||
common_(m, req, vars, offset_x, offset_y, req.width(), req.height(), scale_factor),
|
||||
face_manager_(common_.shared_font_engine_)
|
||||
face_manager_(common_.shared_font_library_)
|
||||
{
|
||||
setup(m);
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ cairo_renderer<T>::cairo_renderer(Map const& m,
|
|||
m_(m),
|
||||
context_(cairo),
|
||||
common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor, detector),
|
||||
face_manager_(common_.shared_font_engine_)
|
||||
face_manager_(common_.shared_font_library_)
|
||||
{
|
||||
setup(m);
|
||||
}
|
||||
|
|
|
@ -56,9 +56,16 @@ feature_type_style::feature_type_style(feature_type_style const& rhs)
|
|||
direct_filters_(rhs.direct_filters_),
|
||||
comp_op_(rhs.comp_op_),
|
||||
opacity_(rhs.opacity_),
|
||||
image_filters_inflate_(rhs.image_filters_inflate_)
|
||||
{
|
||||
}
|
||||
image_filters_inflate_(rhs.image_filters_inflate_) {}
|
||||
|
||||
feature_type_style::feature_type_style(feature_type_style && rhs)
|
||||
: rules_(std::move(rhs.rules_)),
|
||||
filter_mode_(std::move(rhs.filter_mode_)),
|
||||
filters_(std::move(rhs.filters_)),
|
||||
direct_filters_(std::move(rhs.direct_filters_)),
|
||||
comp_op_(std::move(rhs.comp_op_)),
|
||||
opacity_(std::move(rhs.opacity_)),
|
||||
image_filters_inflate_(std::move(rhs.image_filters_inflate_)) {}
|
||||
|
||||
feature_type_style& feature_type_style::operator=(feature_type_style rhs)
|
||||
{
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
#include <mapnik/pixel_position.hpp>
|
||||
#include <mapnik/text/face.hpp>
|
||||
#include <mapnik/util/fs.hpp>
|
||||
#include <mapnik/util/file_io.hpp>
|
||||
#include <mapnik/utils.hpp>
|
||||
#include <mapnik/make_unique.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
@ -36,7 +38,6 @@
|
|||
// stl
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
|
||||
// freetype2
|
||||
extern "C"
|
||||
|
@ -47,45 +48,12 @@ extern "C"
|
|||
#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
|
||||
{
|
||||
|
||||
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()
|
||||
: library_(nullptr),
|
||||
memory_(new FT_MemoryRec_)
|
||||
{
|
||||
init_freetype(&*memory_, library_);
|
||||
}
|
||||
|
||||
freetype_engine::~freetype_engine()
|
||||
{
|
||||
FT_Done_Library(library_);
|
||||
}
|
||||
freetype_engine::freetype_engine() {}
|
||||
freetype_engine::~freetype_engine() {}
|
||||
|
||||
bool freetype_engine::is_font_file(std::string const& file_name)
|
||||
{
|
||||
|
@ -116,37 +84,27 @@ bool freetype_engine::register_font(std::string const& file_name)
|
|||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
#endif
|
||||
|
||||
FT_Library library = 0;
|
||||
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;
|
||||
font_library library;
|
||||
return register_font_impl(file_name, library, global_font_file_mapping_);
|
||||
}
|
||||
|
||||
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,
|
||||
font_library & library,
|
||||
freetype_engine::font_file_mapping_type & font_file_mapping)
|
||||
{
|
||||
MAPNIK_LOG_DEBUG(font_engine_freetype) << "registering: " << file_name;
|
||||
#ifdef _WINDOWS
|
||||
FILE * file = _wfopen(mapnik::utf8_to_utf16(file_name).c_str(), L"rb");
|
||||
#else
|
||||
FILE * file = std::fopen(file_name.c_str(),"rb");
|
||||
#endif
|
||||
if (file == nullptr) return false;
|
||||
mapnik::util::file file(file_name);
|
||||
if (!file.open()) return false;
|
||||
|
||||
FT_Face face = 0;
|
||||
FT_Open_Args args;
|
||||
FT_StreamRec streamRec;
|
||||
memset(&args, 0, sizeof(args));
|
||||
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.pos = 0;
|
||||
streamRec.size = file_size;
|
||||
streamRec.descriptor.pointer = file;
|
||||
streamRec.size = file.size();
|
||||
streamRec.descriptor.pointer = file.get();
|
||||
streamRec.read = ft_read_cb;
|
||||
streamRec.close = NULL;
|
||||
args.flags = FT_OPEN_STREAM;
|
||||
|
@ -159,7 +117,7 @@ bool freetype_engine::register_font_impl(std::string const& file_name, FT_Librar
|
|||
for ( int i = 0; face == 0 || i < num_faces; ++i )
|
||||
{
|
||||
// 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;
|
||||
// store num_faces locally, after FT_Done_Face it can not be accessed any more
|
||||
if (num_faces == 0)
|
||||
|
@ -173,10 +131,10 @@ bool freetype_engine::register_font_impl(std::string const& file_name, FT_Librar
|
|||
if (!boost::algorithm::starts_with(name,"."))
|
||||
{
|
||||
// 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
|
||||
{
|
||||
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
|
||||
{ /* some action with value range.first->second about to be overwritten here */
|
||||
|
@ -200,7 +158,6 @@ bool freetype_engine::register_font_impl(std::string const& file_name, FT_Librar
|
|||
}
|
||||
if (face) FT_Done_Face(face);
|
||||
}
|
||||
std::fclose(file);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -209,15 +166,14 @@ bool freetype_engine::register_fonts(std::string const& dir, bool recurse)
|
|||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
#endif
|
||||
std::unique_ptr<FT_MemoryRec_> memory(new FT_MemoryRec_);
|
||||
FT_Library library = 0;
|
||||
init_freetype(&*memory, library);
|
||||
bool result = register_fonts_impl(dir, library, recurse);
|
||||
FT_Done_Library(library);
|
||||
return result;
|
||||
font_library library;
|
||||
return register_fonts_impl(dir, library, global_font_file_mapping_, recurse);
|
||||
}
|
||||
|
||||
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,
|
||||
font_library & library,
|
||||
freetype_engine::font_file_mapping_type & font_file_mapping,
|
||||
bool recurse)
|
||||
{
|
||||
if (!mapnik::util::exists(dir))
|
||||
{
|
||||
|
@ -225,7 +181,7 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, FT_LibraryRec_
|
|||
}
|
||||
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;
|
||||
try
|
||||
|
@ -251,7 +207,7 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, FT_LibraryRec_
|
|||
#endif
|
||||
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;
|
||||
}
|
||||
|
@ -267,7 +223,7 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, FT_LibraryRec_
|
|||
mapnik::util::is_regular_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;
|
||||
}
|
||||
|
@ -286,91 +242,160 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, FT_LibraryRec_
|
|||
std::vector<std::string> freetype_engine::face_names ()
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
for (auto const& kv : name2file_)
|
||||
for (auto const& kv : global_font_file_mapping_)
|
||||
{
|
||||
names.push_back(kv.first);
|
||||
}
|
||||
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)
|
||||
freetype_engine::font_memory_cache_type & freetype_engine::get_cache()
|
||||
{
|
||||
auto itr = name2file_.find(family_name);
|
||||
if (itr != name2file_.end())
|
||||
return global_memory_fonts_;
|
||||
}
|
||||
|
||||
bool freetype_engine::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)
|
||||
{
|
||||
bool found_font_file = false;
|
||||
font_file_mapping_type::const_iterator itr = font_file_mapping.find(face_name);
|
||||
if (itr != font_file_mapping.end())
|
||||
{
|
||||
found_font_file = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
itr = global_font_file_mapping.find(face_name);
|
||||
if (itr != global_font_file_mapping.end())
|
||||
{
|
||||
found_font_file = true;
|
||||
}
|
||||
}
|
||||
if (!found_font_file) return false;
|
||||
mapnik::util::file file(itr->second.second);
|
||||
if (!file.open()) return false;
|
||||
FT_Face face = 0;
|
||||
FT_Open_Args args;
|
||||
FT_StreamRec streamRec;
|
||||
memset(&args, 0, sizeof(args));
|
||||
memset(&streamRec, 0, sizeof(streamRec));
|
||||
streamRec.base = 0;
|
||||
streamRec.pos = 0;
|
||||
streamRec.size = file.size();
|
||||
streamRec.descriptor.pointer = file.get();
|
||||
streamRec.read = ft_read_cb;
|
||||
streamRec.close = NULL;
|
||||
args.flags = FT_OPEN_STREAM;
|
||||
args.stream = &streamRec;
|
||||
// -1 is used to quickly check if the font file appears valid without iterating each face
|
||||
FT_Error error = FT_Open_Face(library.get(), &args, -1, &face);
|
||||
if (face) FT_Done_Face(face);
|
||||
if (error) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
face_ptr freetype_engine::create_face(std::string const& family_name,
|
||||
font_library & library,
|
||||
freetype_engine::font_file_mapping_type const& font_file_mapping,
|
||||
freetype_engine::font_memory_cache_type const& font_cache,
|
||||
freetype_engine::font_file_mapping_type const& global_font_file_mapping,
|
||||
freetype_engine::font_memory_cache_type & global_memory_fonts)
|
||||
{
|
||||
bool found_font_file = false;
|
||||
font_file_mapping_type::const_iterator itr = font_file_mapping.find(family_name);
|
||||
// look for font registered on specific map
|
||||
if (itr != font_file_mapping.end())
|
||||
{
|
||||
auto mem_font_itr = font_cache.find(itr->second.second);
|
||||
// if map has font already in memory, use it
|
||||
if (mem_font_itr != font_cache.end())
|
||||
{
|
||||
FT_Face face;
|
||||
|
||||
auto mem_font_itr = memory_fonts_.find(itr->second.second);
|
||||
|
||||
if (mem_font_itr != memory_fonts_.end()) // memory font
|
||||
{
|
||||
FT_Error error = FT_New_Memory_Face(library_,
|
||||
FT_Error error = FT_New_Memory_Face(library.get(),
|
||||
reinterpret_cast<FT_Byte const*>(mem_font_itr->second.first.get()), // data
|
||||
static_cast<FT_Long>(mem_font_itr->second.second), // size
|
||||
itr->second.first, // face index
|
||||
&face);
|
||||
|
||||
if (!error) return std::make_shared<font_face>(face);
|
||||
}
|
||||
// we don't add to cache here because the map and its font_cache
|
||||
// must be immutable during rendering for predictable thread safety
|
||||
found_font_file = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// load font into memory
|
||||
// otherwise search global registry
|
||||
itr = global_font_file_mapping.find(family_name);
|
||||
if (itr != global_font_file_mapping.end())
|
||||
{
|
||||
auto mem_font_itr = global_memory_fonts_.find(itr->second.second);
|
||||
// if font already in memory, use it
|
||||
if (mem_font_itr != global_memory_fonts_.end())
|
||||
{
|
||||
FT_Face face;
|
||||
FT_Error error = FT_New_Memory_Face(library.get(),
|
||||
reinterpret_cast<FT_Byte const*>(mem_font_itr->second.first.get()), // data
|
||||
static_cast<FT_Long>(mem_font_itr->second.second), // size
|
||||
itr->second.first, // face index
|
||||
&face);
|
||||
if (!error) return std::make_shared<font_face>(face);
|
||||
}
|
||||
found_font_file = true;
|
||||
}
|
||||
}
|
||||
// if we found file file but it is not yet in memory
|
||||
if (found_font_file)
|
||||
{
|
||||
mapnik::util::file file(itr->second.second);
|
||||
if (file.open())
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS
|
||||
std::unique_ptr<std::FILE, int (*)(std::FILE *)> file(_wfopen(mapnik::utf8_to_utf16(itr->second.second).c_str(), L"rb"), fclose);
|
||||
#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);
|
||||
std::size_t file_size = std::ftell(file.get());
|
||||
std::fseek(file.get(), 0, SEEK_SET);
|
||||
std::unique_ptr<char[]> buffer(new char[file_size]);
|
||||
std::fread(buffer.get(), file_size, 1, file.get());
|
||||
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,
|
||||
auto result = global_memory_fonts_.emplace(itr->second.second, std::make_pair(std::move(file.data()),file.size()));
|
||||
FT_Face face;
|
||||
FT_Error error = FT_New_Memory_Face(library.get(),
|
||||
reinterpret_cast<FT_Byte const*>(result.first->second.first.get()), // data
|
||||
static_cast<FT_Long>(result.first->second.second), // size
|
||||
itr->second.first, // face index
|
||||
&face);
|
||||
if (!error) return std::make_shared<font_face>(face);
|
||||
else
|
||||
if (error)
|
||||
{
|
||||
// we can't load font, erase it.
|
||||
memory_fonts_.erase(result.first);
|
||||
}
|
||||
global_memory_fonts_.erase(result.first);
|
||||
return face_ptr();
|
||||
}
|
||||
return std::make_shared<font_face>(face);
|
||||
}
|
||||
}
|
||||
return face_ptr();
|
||||
}
|
||||
|
||||
|
||||
stroker_ptr freetype_engine::create_stroker()
|
||||
{
|
||||
face_manager::face_manager(font_library & library,
|
||||
freetype_engine::font_file_mapping_type const& font_file_mapping,
|
||||
freetype_engine::font_memory_cache_type const& font_cache)
|
||||
: face_ptr_cache_(),
|
||||
library_(library),
|
||||
font_file_mapping_(font_file_mapping),
|
||||
font_memory_cache_(font_cache)
|
||||
{
|
||||
FT_Stroker s;
|
||||
FT_Error error = FT_Stroker_New(library_, &s);
|
||||
FT_Error error = FT_Stroker_New(library_.get(), &s);
|
||||
if (!error)
|
||||
{
|
||||
return std::make_shared<stroker>(s);
|
||||
stroker_ = std::make_shared<stroker>(s);
|
||||
}
|
||||
}
|
||||
return stroker_ptr();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
face_ptr face_manager<T>::get_face(std::string const& name)
|
||||
face_ptr face_manager::get_face(std::string const& name)
|
||||
{
|
||||
auto itr = face_ptr_cache_.find(name);
|
||||
if (itr != face_ptr_cache_.end())
|
||||
|
@ -379,7 +404,12 @@ face_ptr face_manager<T>::get_face(std::string const& name)
|
|||
}
|
||||
else
|
||||
{
|
||||
face_ptr face = engine_.create_face(name);
|
||||
face_ptr face = freetype_engine::create_face(name,
|
||||
library_,
|
||||
font_file_mapping_,
|
||||
font_memory_cache_,
|
||||
freetype_engine::get_mapping(),
|
||||
freetype_engine::get_cache());
|
||||
if (face)
|
||||
{
|
||||
face_ptr_cache_.emplace(name,face);
|
||||
|
@ -388,10 +418,9 @@ face_ptr face_manager<T>::get_face(std::string const& name)
|
|||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
face_set_ptr face_manager<T>::get_face_set(std::string const& name)
|
||||
face_set_ptr face_manager::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_unique<font_face_set>();
|
||||
if (face_ptr face = get_face(name))
|
||||
{
|
||||
face_set->add(face);
|
||||
|
@ -399,11 +428,10 @@ face_set_ptr face_manager<T>::get_face_set(std::string const& name)
|
|||
return face_set;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
face_set_ptr face_manager<T>::get_face_set(font_set const& fset)
|
||||
face_set_ptr face_manager::get_face_set(font_set const& fset)
|
||||
{
|
||||
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_unique<font_face_set>();
|
||||
for (auto const& name : names)
|
||||
{
|
||||
face_ptr face = get_face(name);
|
||||
|
@ -423,8 +451,7 @@ face_set_ptr face_manager<T>::get_face_set(font_set const& fset)
|
|||
return face_set;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
face_set_ptr face_manager<T>::get_face_set(const std::string &name, boost::optional<font_set> fset)
|
||||
face_set_ptr face_manager::get_face_set(std::string const& name, boost::optional<font_set> fset)
|
||||
{
|
||||
if (fset && fset->size() > 0)
|
||||
{
|
||||
|
@ -439,8 +466,7 @@ face_set_ptr face_manager<T>::get_face_set(const std::string &name, boost::optio
|
|||
#ifdef MAPNIK_THREADSAFE
|
||||
std::mutex freetype_engine::mutex_;
|
||||
#endif
|
||||
std::map<std::string,std::pair<int,std::string> > freetype_engine::name2file_;
|
||||
std::map<std::string,std::pair<std::unique_ptr<char[]>,std::size_t> > freetype_engine::memory_fonts_;
|
||||
template class face_manager<freetype_engine>;
|
||||
freetype_engine::font_file_mapping_type freetype_engine::global_font_file_mapping_;
|
||||
freetype_engine::font_memory_cache_type freetype_engine::global_memory_fonts_;
|
||||
|
||||
}
|
||||
|
|
|
@ -44,9 +44,9 @@ struct process_layout : public util::static_visitor<>
|
|||
// and the offset values should position them around (0,0)
|
||||
pixel_position const& input_origin_;
|
||||
|
||||
process_layout(const vector<bound_box> &member_bboxes,
|
||||
process_layout(vector<bound_box> const& member_bboxes,
|
||||
vector<pixel_position> &member_offsets,
|
||||
const pixel_position &input_origin)
|
||||
pixel_position const& input_origin)
|
||||
: member_boxes_(member_bboxes),
|
||||
member_offsets_(member_offsets),
|
||||
input_origin_(input_origin)
|
||||
|
@ -140,7 +140,7 @@ private:
|
|||
// stores corresponding offset, and returns modified bounding box
|
||||
bound_box box_offset_align(size_t i, double x, double y, int x_dir, int y_dir) const
|
||||
{
|
||||
const bound_box &box = member_boxes_[i];
|
||||
bound_box const& box = member_boxes_[i];
|
||||
pixel_position offset((x_dir == 0 ? x - input_origin_.x : x - (x_dir < 0 ? box.maxx() : box.minx())),
|
||||
(y_dir == 0 ? y - input_origin_.y : y - (y_dir < 0 ? box.maxy() : box.miny())));
|
||||
|
||||
|
@ -152,8 +152,8 @@ private:
|
|||
bound_box group_layout_manager::offset_box_at(size_t i)
|
||||
{
|
||||
handle_update();
|
||||
const pixel_position &offset = member_offsets_.at(i);
|
||||
const bound_box &box = member_boxes_.at(i);
|
||||
pixel_position const& offset = member_offsets_.at(i);
|
||||
bound_box const& box = member_boxes_.at(i);
|
||||
return box2d<double>(box.minx() + offset.x, box.miny() + offset.y,
|
||||
box.maxx() + offset.x, box.maxy() + offset.y);
|
||||
}
|
||||
|
|
|
@ -38,12 +38,12 @@
|
|||
namespace mapnik {
|
||||
|
||||
group_symbolizer_helper::group_symbolizer_helper(
|
||||
const group_symbolizer &sym, const feature_impl &feature,
|
||||
group_symbolizer const& sym, feature_impl const& feature,
|
||||
attributes const& vars,
|
||||
const proj_transform &prj_trans,
|
||||
proj_transform const& prj_trans,
|
||||
unsigned width, unsigned height, double scale_factor,
|
||||
const view_transform &t, DetectorType &detector,
|
||||
const box2d<double> &query_extent)
|
||||
view_transform const& t, DetectorType & detector,
|
||||
box2d<double> const& query_extent)
|
||||
: base_symbolizer_helper(sym, feature, vars, prj_trans, width, height, scale_factor, t, query_extent),
|
||||
detector_(detector)
|
||||
{}
|
||||
|
@ -154,7 +154,7 @@ bool group_symbolizer_helper::check_point_placement(pixel_position const& pos)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool group_symbolizer_helper::collision(const box2d<double> &box, const value_unicode_string &repeat_key) const
|
||||
bool group_symbolizer_helper::collision(box2d<double> const& box, value_unicode_string const& repeat_key) const
|
||||
{
|
||||
if (!detector_.extent().intersects(box)
|
||||
||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
layer::layer(std::string const& name, std::string const& srs)
|
||||
: name_(name),
|
||||
srs_(srs),
|
||||
|
@ -39,8 +40,11 @@ layer::layer(std::string const& name, std::string const& srs)
|
|||
queryable_(false),
|
||||
clear_label_cache_(false),
|
||||
cache_features_(false),
|
||||
group_by_(""),
|
||||
group_by_(),
|
||||
styles_(),
|
||||
ds_(),
|
||||
buffer_size_(),
|
||||
maximum_extent_()
|
||||
opacity_(1.0f) {}
|
||||
|
||||
layer::layer(layer const& rhs)
|
||||
|
@ -235,7 +239,6 @@ void layer::reset_buffer_size()
|
|||
buffer_size_.reset();
|
||||
}
|
||||
|
||||
|
||||
box2d<double> layer::envelope() const
|
||||
{
|
||||
if (ds_) return ds_->envelope();
|
||||
|
|
|
@ -84,12 +84,15 @@ constexpr unsigned name2int(const char *str, int off = 0)
|
|||
class map_parser : mapnik::noncopyable
|
||||
{
|
||||
public:
|
||||
map_parser(bool strict, std::string const& filename = "") :
|
||||
map_parser(Map & map, bool strict, std::string const& filename = "") :
|
||||
strict_(strict),
|
||||
filename_(filename),
|
||||
font_manager_(font_engine_),
|
||||
xml_base_path_()
|
||||
{}
|
||||
font_library_(),
|
||||
font_file_mapping_(map.get_font_file_mapping()),
|
||||
font_name_cache_(),
|
||||
file_sources_(),
|
||||
fontsets_(),
|
||||
xml_base_path_() {}
|
||||
|
||||
void parse_map(Map & map, xml_node const& node, std::string const& base_path);
|
||||
private:
|
||||
|
@ -129,8 +132,9 @@ private:
|
|||
bool strict_;
|
||||
std::string filename_;
|
||||
std::map<std::string,parameters> datasource_templates_;
|
||||
freetype_engine font_engine_;
|
||||
face_manager<freetype_engine> font_manager_;
|
||||
font_library font_library_;
|
||||
freetype_engine::font_file_mapping_type & font_file_mapping_;
|
||||
std::map<std::string,bool> font_name_cache_;
|
||||
std::map<std::string,std::string> file_sources_;
|
||||
std::map<std::string,font_set> fontsets_;
|
||||
std::string xml_base_path_;
|
||||
|
@ -143,7 +147,7 @@ void load_map(Map & map, std::string const& filename, bool strict, std::string b
|
|||
xml_tree tree("utf8");
|
||||
tree.set_filename(filename);
|
||||
read_xml(filename, tree.root());
|
||||
map_parser parser(strict, filename);
|
||||
map_parser parser(map, strict, filename);
|
||||
parser.parse_map(map, tree.root(), base_path);
|
||||
//dump_xml(tree.root());
|
||||
}
|
||||
|
@ -160,7 +164,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
|
||||
}
|
||||
map_parser parser(strict, base_path);
|
||||
map_parser parser(map, strict, base_path);
|
||||
parser.parse_map(map, tree.root(), base_path);
|
||||
}
|
||||
|
||||
|
@ -262,7 +266,8 @@ 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");
|
||||
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 (strict_)
|
||||
{
|
||||
|
@ -511,21 +516,34 @@ void map_parser::parse_fontset(Map & map, xml_node const& node)
|
|||
}
|
||||
}
|
||||
|
||||
bool map_parser::parse_font(font_set &fset, xml_node const& f)
|
||||
bool map_parser::parse_font(font_set & fset, xml_node const& f)
|
||||
{
|
||||
optional<std::string> face_name = f.get_opt_attr<std::string>("face-name");
|
||||
if (face_name)
|
||||
optional<std::string> has_face_name = f.get_opt_attr<std::string>("face-name");
|
||||
if (has_face_name)
|
||||
{
|
||||
face_ptr face = font_manager_.get_face(*face_name);
|
||||
if (face)
|
||||
std::string face_name = *has_face_name;
|
||||
bool found = false;
|
||||
auto itr = font_name_cache_.find(face_name);
|
||||
if (itr != font_name_cache_.end())
|
||||
{
|
||||
fset.add_face_name(*face_name);
|
||||
found = itr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
found = freetype_engine::can_open(face_name,
|
||||
font_library_,
|
||||
font_file_mapping_,
|
||||
freetype_engine::get_mapping());
|
||||
font_name_cache_.emplace(face_name,found);
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
fset.add_face_name(face_name);
|
||||
return true;
|
||||
}
|
||||
else if (strict_)
|
||||
{
|
||||
throw config_error("Failed to find font face '" +
|
||||
*face_name + "'");
|
||||
throw config_error("Failed to find font face '" + face_name + "'");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1525,7 +1543,21 @@ void map_parser::parse_pair_layout(group_symbolizer_properties & prop, xml_node
|
|||
|
||||
void map_parser::ensure_font_face(std::string const& face_name)
|
||||
{
|
||||
if (! font_manager_.get_face(face_name))
|
||||
bool found = false;
|
||||
auto itr = font_name_cache_.find(face_name);
|
||||
if (itr != font_name_cache_.end())
|
||||
{
|
||||
found = itr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
found = freetype_engine::can_open(face_name,
|
||||
font_library_,
|
||||
font_file_mapping_,
|
||||
freetype_engine::get_mapping());
|
||||
font_name_cache_.emplace(face_name,found);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
throw config_error("Failed to find font face '" +
|
||||
face_name + "'");
|
||||
|
|
90
src/map.cpp
90
src/map.cpp
|
@ -38,8 +38,9 @@
|
|||
#include <mapnik/scale_denominator.hpp>
|
||||
#include <mapnik/config_error.hpp>
|
||||
#include <mapnik/config.hpp> // for PROJ_ENVELOPE_POINTS
|
||||
|
||||
// boost
|
||||
#include <mapnik/text/font_library.hpp>
|
||||
#include <mapnik/util/file_io.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
|
||||
// stl
|
||||
#include <stdexcept>
|
||||
|
@ -70,7 +71,11 @@ Map::Map()
|
|||
background_image_comp_op_(src_over),
|
||||
background_image_opacity_(1.0),
|
||||
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)
|
||||
: width_(width),
|
||||
|
@ -80,7 +85,11 @@ Map::Map(int width,int height, std::string const& srs)
|
|||
background_image_comp_op_(src_over),
|
||||
background_image_opacity_(1.0),
|
||||
aspectFixMode_(GROW_BBOX),
|
||||
base_path_("") {}
|
||||
base_path_(""),
|
||||
extra_params_(),
|
||||
font_directory_(),
|
||||
font_file_mapping_(),
|
||||
font_memory_cache_() {}
|
||||
|
||||
Map::Map(Map const& rhs)
|
||||
: width_(rhs.width_),
|
||||
|
@ -98,7 +107,11 @@ Map::Map(Map const& rhs)
|
|||
current_extent_(rhs.current_extent_),
|
||||
maximum_extent_(rhs.maximum_extent_),
|
||||
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)
|
||||
|
@ -117,11 +130,13 @@ Map::Map(Map && rhs)
|
|||
current_extent_(std::move(rhs.current_extent_)),
|
||||
maximum_extent_(std::move(rhs.maximum_extent_)),
|
||||
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::operator=(Map rhs)
|
||||
{
|
||||
swap(*this, rhs);
|
||||
|
@ -147,9 +162,12 @@ void swap (Map & lhs, Map & rhs)
|
|||
std::swap(lhs.maximum_extent_, rhs.maximum_extent_);
|
||||
std::swap(lhs.base_path_, rhs.base_path_);
|
||||
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_);
|
||||
// on assignment discard memory cache
|
||||
//std::swap(lhs.font_memory_cache_,rhs.font_memory_cache_);
|
||||
}
|
||||
|
||||
|
||||
bool Map::operator==(Map const& rhs) const
|
||||
{
|
||||
return (width_ == rhs.width_) &&
|
||||
|
@ -167,7 +185,10 @@ bool Map::operator==(Map const& rhs) const
|
|||
(current_extent_ == rhs.current_extent_) &&
|
||||
(maximum_extent_ == rhs.maximum_extent_) &&
|
||||
(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_);
|
||||
// Note: we don't care about font_memory_cache in comparison
|
||||
}
|
||||
|
||||
std::map<std::string,feature_type_style> const& Map::styles() const
|
||||
|
@ -200,7 +221,12 @@ Map::const_style_iterator Map::end_styles() const
|
|||
return styles_.end();
|
||||
}
|
||||
|
||||
bool Map::insert_style(std::string const& name,feature_type_style style)
|
||||
bool Map::insert_style(std::string const& name, feature_type_style const& style)
|
||||
{
|
||||
return styles_.emplace(name, style).second;
|
||||
}
|
||||
|
||||
bool Map::insert_style(std::string const& name, feature_type_style && style)
|
||||
{
|
||||
return styles_.emplace(name, std::move(style)).second;
|
||||
}
|
||||
|
@ -219,7 +245,16 @@ boost::optional<feature_type_style const&> Map::find_style(std::string const& na
|
|||
return boost::optional<feature_type_style const&>() ;
|
||||
}
|
||||
|
||||
bool Map::insert_fontset(std::string const& name, font_set fontset)
|
||||
bool Map::insert_fontset(std::string const& name, font_set const& fontset)
|
||||
{
|
||||
if (fontset.get_name() != name)
|
||||
{
|
||||
throw mapnik::config_error("Fontset name must match the name used to reference it on the map");
|
||||
}
|
||||
return fontsets_.emplace(name, fontset).second;
|
||||
}
|
||||
|
||||
bool Map::insert_fontset(std::string const& name, font_set && fontset)
|
||||
{
|
||||
if (fontset.get_name() != name)
|
||||
{
|
||||
|
@ -247,12 +282,43 @@ std::map<std::string,font_set> & Map::fontsets()
|
|||
return 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);
|
||||
}
|
||||
|
||||
bool Map::load_fonts()
|
||||
{
|
||||
bool result = false;
|
||||
for (auto const& kv : font_file_mapping_)
|
||||
{
|
||||
auto const& global_mapping = freetype_engine::get_mapping();
|
||||
if ((global_mapping.find(kv.first) == global_mapping.end()) &&
|
||||
(font_memory_cache_.find(kv.second.second) == font_memory_cache_.end()))
|
||||
{
|
||||
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
|
||||
{
|
||||
return layers_.size();
|
||||
}
|
||||
|
||||
void Map::add_layer(layer l)
|
||||
void Map::add_layer(layer const& l)
|
||||
{
|
||||
layers_.emplace_back(l);
|
||||
}
|
||||
|
||||
void Map::add_layer(layer && l)
|
||||
{
|
||||
layers_.push_back(std::move(l));
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@ renderer_common::renderer_common(Map const& map, unsigned width, unsigned height
|
|||
height_(height),
|
||||
scale_factor_(scale_factor),
|
||||
vars_(vars),
|
||||
shared_font_engine_(std::make_shared<freetype_engine>()),
|
||||
font_engine_(*shared_font_engine_),
|
||||
font_manager_(font_engine_),
|
||||
shared_font_library_(std::make_shared<font_library>()),
|
||||
font_library_(*shared_font_library_),
|
||||
font_manager_(font_library_,map.get_font_file_mapping(),map.get_font_memory_cache()),
|
||||
query_extent_(),
|
||||
t_(t),
|
||||
detector_(detector)
|
||||
|
|
|
@ -625,6 +625,12 @@ void serialize_map(ptree & pt, Map const& map, bool explicit_defaults)
|
|||
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();
|
||||
if ( image_filename )
|
||||
{
|
||||
|
|
|
@ -26,11 +26,13 @@
|
|||
|
||||
// boost
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
// stl
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <sstream>
|
||||
#include <functional>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
@ -54,9 +56,16 @@ void font_feature_settings::from_string(std::string const& features)
|
|||
qi::char_type char_;
|
||||
qi::as_string_type as_string;
|
||||
|
||||
#if BOOST_VERSION <= 104800
|
||||
// Call correct overload.
|
||||
using std::placeholders::_1;
|
||||
void (font_feature_settings::*append)(std::string const&) = &font_feature_settings::append;
|
||||
if (!qi::parse(features.begin(), features.end(), as_string[+(char_ - ',')][std::bind(append, this, _1)] % ','))
|
||||
#else
|
||||
auto app = [&](std::string const& s) { append(s); };
|
||||
|
||||
if (!qi::parse(features.begin(), features.end(), as_string[+(char_ - ',')][app] % ','))
|
||||
#endif
|
||||
|
||||
{
|
||||
throw config_error("failed to parse font-feature-settings: '" + features + "'");
|
||||
}
|
||||
|
@ -96,4 +105,3 @@ void font_feature_settings::append(std::string const& feature)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
81
src/text/font_library.cpp
Normal file
81
src/text/font_library.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* 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/text/font_library.hpp>
|
||||
|
||||
// stl
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
|
||||
// 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 {
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
font_library::~font_library()
|
||||
{
|
||||
FT_Done_Library(library_);
|
||||
}
|
||||
|
||||
} // end namespace mapnik
|
|
@ -50,6 +50,7 @@ void layout_node::to_xml(ptree &xml) const
|
|||
if (dy) serialize_property("dy", *dy, new_node);
|
||||
if (text_ratio) serialize_property("text-ratio", *text_ratio, new_node);
|
||||
if (wrap_width) serialize_property("wrap-width", *wrap_width, new_node);
|
||||
if (wrap_char) serialize_property("wrap-character", *wrap_char, new_node);
|
||||
if (wrap_before) serialize_property("wrap-before", *wrap_before, new_node);
|
||||
if (repeat_wrap_char) serialize_property("repeat-wrap-character", *repeat_wrap_char, new_node);
|
||||
if (rotate_displacement) serialize_property("rotate-displacement", *rotate_displacement, new_node);
|
||||
|
@ -71,6 +72,7 @@ node_ptr layout_node::from_xml(xml_node const& xml, fontset_map const& fontsets)
|
|||
if (xml.has_attribute("dy")) set_property_from_xml<double>(n->dy, "dy", xml);
|
||||
if (xml.has_attribute("text-ratio")) set_property_from_xml<double>(n->text_ratio, "text-ratio", xml);
|
||||
if (xml.has_attribute("wrap-width")) set_property_from_xml<double>(n->wrap_width, "wrap-width", xml);
|
||||
if (xml.has_attribute("wrap-character")) set_property_from_xml<std::string>(n->wrap_char, "wrap-character", xml);
|
||||
if (xml.has_attribute("wrap-before")) set_property_from_xml<mapnik::boolean_type>(n->wrap_before, "wrap-before", xml);
|
||||
if (xml.has_attribute("repeat-wrap-character")) set_property_from_xml<mapnik::boolean_type>(n->repeat_wrap_char, "repeat-wrap-character", xml);
|
||||
if (xml.has_attribute("rotate-displacement")) set_property_from_xml<mapnik::boolean_type>(n->rotate_displacement, "rotate-displacement", xml);
|
||||
|
@ -88,6 +90,7 @@ void layout_node::apply(evaluated_format_properties_ptr p, feature_impl const& f
|
|||
if (dy) new_properties.dy = *dy;
|
||||
if (text_ratio) new_properties.text_ratio = *text_ratio;
|
||||
if (wrap_width) new_properties.wrap_width = *wrap_width;
|
||||
if (wrap_char) new_properties.wrap_char = *wrap_char;
|
||||
if (wrap_before) new_properties.wrap_before = *wrap_before;
|
||||
if (repeat_wrap_char) new_properties.repeat_wrap_char = *repeat_wrap_char;
|
||||
if (rotate_displacement) new_properties.rotate_displacement = *rotate_displacement;
|
||||
|
@ -128,6 +131,7 @@ void layout_node::add_expressions(expression_set & output) const
|
|||
if (dy && is_expression(*dy)) output.insert(util::get<expression_ptr>(*dy));
|
||||
if (orientation && is_expression(*orientation)) output.insert(util::get<expression_ptr>(*orientation));
|
||||
if (wrap_width && is_expression(*wrap_width)) output.insert(util::get<expression_ptr>(*wrap_width));
|
||||
if (wrap_char && is_expression(*wrap_char)) output.insert(util::get<expression_ptr>(*wrap_char));
|
||||
if (wrap_before && is_expression(*wrap_before)) output.insert(util::get<expression_ptr>(*wrap_before));
|
||||
if (repeat_wrap_char && is_expression(*repeat_wrap_char)) output.insert(util::get<expression_ptr>(*repeat_wrap_char));
|
||||
if (rotate_displacement && is_expression(*rotate_displacement)) output.insert(util::get<expression_ptr>(*rotate_displacement));
|
||||
|
|
|
@ -344,7 +344,7 @@ template text_symbolizer_helper::text_symbolizer_helper(
|
|||
unsigned height,
|
||||
double scale_factor,
|
||||
view_transform const& t,
|
||||
face_manager<freetype_engine> &font_manager,
|
||||
face_manager_freetype & font_manager,
|
||||
label_collision_detector4 &detector,
|
||||
box2d<double> const& query_extent,
|
||||
agg::trans_affine const&);
|
||||
|
@ -358,7 +358,7 @@ template text_symbolizer_helper::text_symbolizer_helper(
|
|||
unsigned height,
|
||||
double scale_factor,
|
||||
view_transform const& t,
|
||||
face_manager<freetype_engine> &font_manager,
|
||||
face_manager_freetype & font_manager,
|
||||
label_collision_detector4 &detector,
|
||||
box2d<double> const& query_extent,
|
||||
agg::trans_affine const&);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <mapnik/global.hpp>
|
||||
#include <mapnik/text/vertex_cache.hpp>
|
||||
#include <mapnik/offset_converter.hpp>
|
||||
#include <mapnik/make_unique.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
@ -127,18 +128,15 @@ vertex_cache & vertex_cache::get_offseted(double offset, double region_width)
|
|||
return *this;
|
||||
}
|
||||
|
||||
vertex_cache_ptr offseted_line;
|
||||
offseted_lines_map::iterator pos = offseted_lines_.find(offset);
|
||||
if (pos != offseted_lines_.end())
|
||||
{
|
||||
offseted_line = pos->second;
|
||||
}
|
||||
else
|
||||
if (pos == offseted_lines_.end())
|
||||
{
|
||||
offset_converter<vertex_cache> converter(*this);
|
||||
converter.set_offset(offset);
|
||||
offseted_line = vertex_cache_ptr(new vertex_cache(converter));
|
||||
pos = offseted_lines_.emplace(offset, std::make_unique<vertex_cache>(converter)).first;
|
||||
}
|
||||
vertex_cache_ptr & offseted_line = pos->second;
|
||||
|
||||
offseted_line->reset();
|
||||
offseted_line->next_subpath(); //TODO: Multiple subpath support
|
||||
|
||||
|
@ -146,8 +144,6 @@ vertex_cache & vertex_cache::get_offseted(double offset, double region_width)
|
|||
// which we'll use to make the offset line aligned to this one.
|
||||
double seek = offseted_line->position_closest_to(current_position_);
|
||||
offseted_line->move(seek);
|
||||
|
||||
offseted_lines_[offset] = offseted_line;
|
||||
return *offseted_line;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include <mapnik/font_engine_freetype.hpp>
|
||||
#include <mapnik/util/fs.hpp>
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/load_map.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
@ -31,10 +33,34 @@ int main(int argc, char** argv)
|
|||
BOOST_TEST( mapnik::util::exists( fontdir ) );
|
||||
BOOST_TEST( mapnik::util::is_directory( fontdir ) );
|
||||
|
||||
// test map cached fonts
|
||||
mapnik::Map m(1,1);
|
||||
BOOST_TEST( m.register_fonts(fontdir , false ) );
|
||||
BOOST_TEST( m.get_font_memory_cache().size() == 0 );
|
||||
BOOST_TEST( m.get_font_file_mapping().size() == 1 );
|
||||
BOOST_TEST( m.load_fonts() );
|
||||
BOOST_TEST( m.get_font_memory_cache().size() == 1 );
|
||||
BOOST_TEST( m.register_fonts(fontdir , true ) );
|
||||
BOOST_TEST( m.get_font_file_mapping().size() == 22 );
|
||||
BOOST_TEST( m.load_fonts() );
|
||||
BOOST_TEST( m.get_font_memory_cache().size() == 22 );
|
||||
|
||||
// copy discards memory cache but not file mapping
|
||||
mapnik::Map m2(m);
|
||||
BOOST_TEST( m2.get_font_memory_cache().size() == 0 );
|
||||
BOOST_TEST( m2.get_font_file_mapping().size() == 22 );
|
||||
BOOST_TEST( m2.load_fonts() );
|
||||
BOOST_TEST( m2.get_font_memory_cache().size() == 22 );
|
||||
|
||||
// test font-directory from XML
|
||||
mapnik::Map m3(1,1);
|
||||
mapnik::load_map_string(m3,"<Map font-directory=\"fonts/\"></Map>");
|
||||
BOOST_TEST( m3.get_font_memory_cache().size() == 0 );
|
||||
BOOST_TEST( m3.load_fonts() );
|
||||
BOOST_TEST( m3.get_font_memory_cache().size() == 1 );
|
||||
|
||||
std::vector<std::string> face_names;
|
||||
|
||||
std::string foo("foo");
|
||||
|
||||
// fake directories
|
||||
BOOST_TEST( !mapnik::freetype_engine::register_fonts(foo , true ) );
|
||||
face_names = mapnik::freetype_engine::face_names();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
// boost
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
// stl
|
||||
#include <stdexcept>
|
||||
|
|
|
@ -75,7 +75,8 @@ int main(int argc, char** argv)
|
|||
|
||||
// value_null
|
||||
params["null"] = mapnik::value_null();
|
||||
BOOST_TEST( (params.get<mapnik::value_null>("null") && *params.get<mapnik::value_null>("null") == mapnik::value_null()) );
|
||||
// https://github.com/mapnik/mapnik/issues/2471
|
||||
//BOOST_TEST( (params.get<mapnik::value_null>("null") && *params.get<mapnik::value_null>("null") == mapnik::value_null()) );
|
||||
|
||||
if (!::boost::detail::test_errors()) {
|
||||
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include <boost/version.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
|
|
Loading…
Reference in a new issue