mirror of
https://github.com/mapnik/mapnik.git
synced 2025-12-08 20:13:09 +00:00
Merge branch 'master' of github.com:mapnik/mapnik
This commit is contained in:
commit
f5da52bb22
114
AUTHORS.md
114
AUTHORS.md
@ -2,60 +2,60 @@
|
||||
|
||||
Mapnik is written by Artem Pavlenko with contributions from:
|
||||
|
||||
Andy Allen
|
||||
AJ Ashton
|
||||
Matt Amos
|
||||
Lucio Asnaghi
|
||||
Justin Bronn
|
||||
Christopher Brown
|
||||
Jon Burgess
|
||||
Toby Collet
|
||||
Robert Coup
|
||||
Berteun Damman
|
||||
Craig de Stigter
|
||||
Jean-Francois Doyon
|
||||
David Eastcott
|
||||
Krzysztof Godlewski
|
||||
Beau Gunderson
|
||||
John Hague
|
||||
Dominic Hargreaves
|
||||
Aubrey Holland
|
||||
Tom Hughes
|
||||
Konstantin Käfer
|
||||
Mak Kolybabi
|
||||
Peter Körner
|
||||
Hermann Kraus
|
||||
Stella Laurenzo
|
||||
David Leaver
|
||||
Carlos López
|
||||
Dennis Luxen
|
||||
Tom MacWright
|
||||
Michal Migurski
|
||||
Andrii Mishkovskyi
|
||||
Ben Moores
|
||||
Dražen Odobašić
|
||||
Cameron Patrick
|
||||
Igor Podolskiy
|
||||
Reid Priedhorsky
|
||||
Brian Quinion
|
||||
Marcin Rudowski
|
||||
Christopher Schmidt
|
||||
Andreas Schneider
|
||||
Vincent Schut
|
||||
Ehud Shabtai
|
||||
David Siegel
|
||||
Steve Singer
|
||||
Paul Smith
|
||||
Vince Spader
|
||||
Philipp Spitzer
|
||||
Dane Springmeyer
|
||||
Dave Stubbs
|
||||
River Tarnell
|
||||
Oliver Tonnhofer
|
||||
Alberto Valverde
|
||||
Martijn van Oosterhout
|
||||
Andreas Volz
|
||||
Lennard voor den Dag
|
||||
Shaun Walbridge
|
||||
Nick Whitelegg
|
||||
Leslie Wu
|
||||
* Andy Allen
|
||||
* AJ Ashton
|
||||
* Matt Amos
|
||||
* Lucio Asnaghi
|
||||
* Justin Bronn
|
||||
* Christopher Brown
|
||||
* Jon Burgess
|
||||
* Toby Collet
|
||||
* Robert Coup
|
||||
* Berteun Damman
|
||||
* Craig de Stigter
|
||||
* Jean-Francois Doyon
|
||||
* David Eastcott
|
||||
* Krzysztof Godlewski
|
||||
* Beau Gunderson
|
||||
* John Hague
|
||||
* Dominic Hargreaves
|
||||
* Aubrey Holland
|
||||
* Tom Hughes
|
||||
* Konstantin Käfer
|
||||
* Mak Kolybabi
|
||||
* Peter Körner
|
||||
* Hermann Kraus
|
||||
* Stella Laurenzo
|
||||
* David Leaver
|
||||
* Carlos López
|
||||
* Dennis Luxen
|
||||
* Tom MacWright
|
||||
* Michal Migurski
|
||||
* Andrii Mishkovskyi
|
||||
* Ben Moores
|
||||
* Dražen Odobašić
|
||||
* Cameron Patrick
|
||||
* Igor Podolskiy
|
||||
* Reid Priedhorsky
|
||||
* Brian Quinion
|
||||
* Marcin Rudowski
|
||||
* Christopher Schmidt
|
||||
* Andreas Schneider
|
||||
* Vincent Schut
|
||||
* Ehud Shabtai
|
||||
* David Siegel
|
||||
* Steve Singer
|
||||
* Paul Smith
|
||||
* Vince Spader
|
||||
* Philipp Spitzer
|
||||
* Dane Springmeyer
|
||||
* Dave Stubbs
|
||||
* River Tarnell
|
||||
* Oliver Tonnhofer
|
||||
* Alberto Valverde
|
||||
* Martijn van Oosterhout
|
||||
* Andreas Volz
|
||||
* Lennard voor den Dag
|
||||
* Shaun Walbridge
|
||||
* Nick Whitelegg
|
||||
* Leslie Wu
|
||||
|
||||
@ -9,6 +9,8 @@ For a complete change history, see the SVN log.
|
||||
|
||||
## Mapnik 2.1.0
|
||||
|
||||
- Improved logging/debugging system with release logs and file redirection (#937 and partially #986, #467)
|
||||
|
||||
- GDAL: allow setting nodata value on the fly (will override value if nodata is set in data) (#1161)
|
||||
|
||||
- GDAL: respect nodata for paletted/colormapped images (#1160)
|
||||
|
||||
21
SConstruct
21
SConstruct
@ -347,7 +347,7 @@ opts.AddVariables(
|
||||
# Variables for logging and statistics
|
||||
BoolVariable('ENABLE_LOG', 'Enable logging, which is enabled by default when building in *debug*', 'False'),
|
||||
BoolVariable('ENABLE_STATS', 'Enable global statistics during map processing', 'False'),
|
||||
('LOG_FORMAT_STRING', 'The format string used before log output string, piped through strftime (max length of 255 characters)', 'Mapnik LOG> %Y-%m-%d %H:%M:%S:'),
|
||||
('DEFAULT_LOG_SEVERITY', 'The default severity of the logger (eg. "info", "debug", "warn", "error", "fatal", "none")', 'error'),
|
||||
|
||||
# Other variables
|
||||
BoolVariable('SHAPE_MEMORY_MAPPED_FILE', 'Utilize memory-mapped files in Shapefile Plugin (higher memory usage, better performance)', 'True'),
|
||||
@ -1417,7 +1417,20 @@ if not preconfigured:
|
||||
ndebug_flags = '-DNDEBUG'
|
||||
|
||||
# Enable logging in debug mode (always) and release mode (when specified)
|
||||
log_enabled = ' -DMAPNIK_LOG -DMAPNIK_LOG_FORMAT="%s"' % env['LOG_FORMAT_STRING']
|
||||
if env['DEFAULT_LOG_SEVERITY']:
|
||||
severities = ['info', 'debug', 'warn', 'error', 'fatal', 'none']
|
||||
if env['DEFAULT_LOG_SEVERITY'] not in severities:
|
||||
color_print(1,"Cannot set default logger severity to '%s', available options are 'info', 'debug', 'warn', 'error', 'fatal', 'none'." % env['DEFAULT_LOG_SEVERITY'])
|
||||
Exit(1)
|
||||
else:
|
||||
log_severity = severities.index(env['DEFAULT_LOG_SEVERITY'])
|
||||
else:
|
||||
if env['DEBUG']:
|
||||
log_severity = 1 # debug
|
||||
else:
|
||||
log_severity = 3 # error
|
||||
|
||||
log_enabled = ' -DMAPNIK_LOG -DMAPNIK_DEFAULT_LOG_SEVERITY=%d' % log_severity
|
||||
|
||||
if env['DEBUG']:
|
||||
debug_flags += log_enabled
|
||||
@ -1432,7 +1445,7 @@ if not preconfigured:
|
||||
|
||||
# Add rdynamic to allow using statics between application and plugins
|
||||
# http://stackoverflow.com/questions/8623657/multiple-instances-of-singleton-across-shared-libraries-on-linux
|
||||
if env['PLATFORM'] != 'Darwin':
|
||||
if env['PLATFORM'] != 'Darwin' and env['CXX'] == 'g++':
|
||||
env.MergeFlags('-rdynamic')
|
||||
|
||||
# Customizing the C++ compiler flags depending on:
|
||||
@ -1719,7 +1732,7 @@ if not HELP_REQUESTED:
|
||||
|
||||
# devtools not ready for public
|
||||
#SConscript('utils/ogrindex/build.py')
|
||||
#SConscript('utils/svg2png/build.py')
|
||||
SConscript('utils/svg2png/build.py')
|
||||
env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND'])
|
||||
else :
|
||||
color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' won't be available")
|
||||
|
||||
@ -22,112 +22,48 @@
|
||||
|
||||
#include <boost/python.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
|
||||
using mapnik::logger::severity;
|
||||
using mapnik::logger::format;
|
||||
using mapnik::logger::output;
|
||||
|
||||
void set_severity(const severity::type& s)
|
||||
{
|
||||
severity::set(s);
|
||||
}
|
||||
|
||||
severity::type get_severity()
|
||||
{
|
||||
return severity::get();
|
||||
}
|
||||
|
||||
void set_object_severity(const std::string& object_name, const severity::type& s)
|
||||
{
|
||||
severity::set_object(object_name, s);
|
||||
}
|
||||
|
||||
severity::type get_object_severity(const std::string& object_name)
|
||||
{
|
||||
return severity::get_object(object_name);
|
||||
}
|
||||
|
||||
#include <mapnik/utils.hpp>
|
||||
|
||||
void export_logger()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
||||
enum_<mapnik::logger::severity::type>("SeverityType")
|
||||
.value("Info", severity::info)
|
||||
.value("Debug", severity::debug)
|
||||
.value("Warn", severity::warn)
|
||||
.value("Error", severity::error)
|
||||
.value("Fatal", severity::fatal)
|
||||
.value("None", severity::none)
|
||||
;
|
||||
|
||||
/*
|
||||
using mapnik::logger;
|
||||
using mapnik::singleton;
|
||||
using mapnik::CreateStatic;
|
||||
using namespace boost::python;
|
||||
|
||||
class_<singleton<severity,CreateStatic>,boost::noncopyable>("Singleton",no_init)
|
||||
.def("instance",&singleton<severity,CreateStatic>::instance,
|
||||
class_<singleton<logger,CreateStatic>,boost::noncopyable>("Singleton",no_init)
|
||||
.def("instance",&singleton<logger,CreateStatic>::instance,
|
||||
return_value_policy<reference_existing_object>())
|
||||
.staticmethod("instance")
|
||||
;
|
||||
|
||||
class_<severity,bases<singleton<severity,CreateStatic> >,
|
||||
boost::noncopyable>("Severity",no_init)
|
||||
.def("get",&severity::get)
|
||||
.def("set",&severity::set)
|
||||
.def("get_object",&severity::get_object)
|
||||
.def("set_object",&severity::set_object)
|
||||
.staticmethod("get")
|
||||
.staticmethod("set")
|
||||
.staticmethod("get_object")
|
||||
.staticmethod("set_object")
|
||||
class_<logger,bases<singleton<logger,CreateStatic> >,
|
||||
boost::noncopyable>("logger",no_init)
|
||||
.def_readonly("Info", logger::info)
|
||||
.def_readonly("Debug", logger::debug)
|
||||
.def_readonly("Warn", logger::warn)
|
||||
.def_readonly("Error", logger::error)
|
||||
.def_readonly("Fatal", logger::fatal)
|
||||
.def_readonly("None", logger::none)
|
||||
.def("get_severity", &logger::get_severity)
|
||||
.def("set_severity", &logger::set_severity)
|
||||
.def("get_object_severity", &logger::get_object_severity)
|
||||
.def("set_object_severity", &logger::set_object_severity)
|
||||
.def("clear_object_severity", &logger::clear_object_severity)
|
||||
.def("get_format", &logger::get_format)
|
||||
.def("set_format", &logger::set_format)
|
||||
.def("str", &logger::str)
|
||||
.def("use_file", &logger::use_file)
|
||||
.def("use_console", &logger::use_console)
|
||||
.staticmethod("get_severity")
|
||||
.staticmethod("set_severity")
|
||||
.staticmethod("get_object_severity")
|
||||
.staticmethod("set_object_severity")
|
||||
.staticmethod("clear_object_severity")
|
||||
.staticmethod("get_format")
|
||||
.staticmethod("set_format")
|
||||
.staticmethod("str")
|
||||
.staticmethod("use_file")
|
||||
.staticmethod("use_console")
|
||||
;
|
||||
*/
|
||||
|
||||
def("set_severity", &set_severity,
|
||||
"\n"
|
||||
"Set global logger severity.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> from mapnik import SeverityType, set_severity\n"
|
||||
">>> set_severity(SeverityType.None)\n"
|
||||
">>> set_severity(SeverityType.Info)\n"
|
||||
">>> set_severity(SeverityType.Debug)\n"
|
||||
">>> set_severity(SeverityType.Warn)\n"
|
||||
">>> set_severity(SeverityType.Error)\n"
|
||||
">>> set_severity(SeverityType.Fatal)\n"
|
||||
);
|
||||
|
||||
def("get_severity", &get_severity,
|
||||
"\n"
|
||||
"Get global logger severity.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> from mapnik import get_severity\n"
|
||||
">>> get_severity()\n"
|
||||
);
|
||||
|
||||
def("set_object_severity", &set_object_severity,
|
||||
"\n"
|
||||
"Set logger severity for a single object.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> from mapnik import SeverityType, set_object_severity\n"
|
||||
">>> set_object_severity('ogr', SeverityType.None)\n"
|
||||
">>> set_object_severity('gdal', SeverityType.Info)\n"
|
||||
">>> set_object_severity('cairo_renderer', SeverityType.Debug)\n"
|
||||
">>> set_object_severity('agg_renderer', SeverityType.Warn)\n"
|
||||
">>> set_object_severity('bindings', SeverityType.Error)\n"
|
||||
);
|
||||
|
||||
def("get_object_severity", &get_object_severity,
|
||||
"\n"
|
||||
"Get logger severity for a single object.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> from mapnik import get_object_severity"
|
||||
">>> get_object_severity('ogr')\n"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -43,122 +43,115 @@
|
||||
|
||||
|
||||
namespace mapnik {
|
||||
namespace logger {
|
||||
|
||||
class MAPNIK_DECL severity :
|
||||
public singleton<severity,CreateStatic>,
|
||||
private boost::noncopyable
|
||||
class MAPNIK_DECL logger :
|
||||
public singleton<logger,CreateStatic>,
|
||||
private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
enum severity_type
|
||||
{
|
||||
public:
|
||||
enum type
|
||||
{
|
||||
info,
|
||||
debug,
|
||||
warn,
|
||||
error,
|
||||
fatal,
|
||||
none
|
||||
};
|
||||
info,
|
||||
debug,
|
||||
warn,
|
||||
error,
|
||||
fatal,
|
||||
none
|
||||
};
|
||||
|
||||
typedef boost::unordered_map<std::string, type> severity_map;
|
||||
typedef boost::unordered_map<std::string, severity_type> severity_map;
|
||||
|
||||
// globally get security level
|
||||
static type get()
|
||||
// global security level
|
||||
static severity_type get_severity()
|
||||
{
|
||||
return severity_level_;
|
||||
}
|
||||
|
||||
static void set_severity(const severity_type& severity_level)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex::scoped_lock lock(severity_mutex_);
|
||||
#endif
|
||||
|
||||
severity_level_ = severity_level;
|
||||
}
|
||||
|
||||
// per object security levels
|
||||
static severity_type get_object_severity(const std::string& object_name)
|
||||
{
|
||||
severity_map::iterator it = object_severity_level_.find(object_name);
|
||||
if (object_name.empty() || it == object_severity_level_.end())
|
||||
{
|
||||
return severity_level_;
|
||||
}
|
||||
|
||||
// globally set security level
|
||||
static void set(const type& severity_level)
|
||||
else
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex::scoped_lock lock(mutex_);
|
||||
#endif
|
||||
|
||||
severity_level_ = severity_level;
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// per object get security level
|
||||
static type get_object(const std::string& object_name)
|
||||
{
|
||||
severity_map::iterator it = object_severity_level_.find(object_name);
|
||||
if (object_name.empty() || it == object_severity_level_.end())
|
||||
{
|
||||
return severity_level_;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// per object set security level
|
||||
static void set_object(const std::string& object_name,
|
||||
const type& security_level)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex::scoped_lock lock(mutex_);
|
||||
#endif
|
||||
if (! object_name.empty())
|
||||
{
|
||||
object_severity_level_[object_name] = security_level;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static type severity_level_;
|
||||
static severity_map object_severity_level_;
|
||||
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
static boost::mutex mutex_;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class MAPNIK_DECL format :
|
||||
public singleton<format,CreateStatic>,
|
||||
private boost::noncopyable
|
||||
static void set_object_severity(const std::string& object_name,
|
||||
const severity_type& security_level)
|
||||
{
|
||||
public:
|
||||
|
||||
static std::string get()
|
||||
{
|
||||
return format_;
|
||||
}
|
||||
|
||||
static void set(const std::string& format)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex::scoped_lock lock(mutex_);
|
||||
boost::mutex::scoped_lock lock(severity_mutex_);
|
||||
#endif
|
||||
format_ = format;
|
||||
if (! object_name.empty())
|
||||
{
|
||||
object_severity_level_[object_name] = security_level;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string str();
|
||||
|
||||
private:
|
||||
static std::string format_;
|
||||
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
static boost::mutex mutex_;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class MAPNIK_DECL output :
|
||||
public singleton<output,CreateStatic>,
|
||||
private boost::noncopyable
|
||||
static void clear_object_severity()
|
||||
{
|
||||
public:
|
||||
static void use_file(const std::string& filepath);
|
||||
static void use_console();
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex::scoped_lock lock(severity_mutex_);
|
||||
#endif
|
||||
|
||||
private:
|
||||
static std::ofstream file_output_;
|
||||
static std::string file_name_;
|
||||
static std::streambuf* saved_buf_;
|
||||
};
|
||||
object_severity_level_.clear();
|
||||
}
|
||||
|
||||
// format
|
||||
static std::string get_format()
|
||||
{
|
||||
return format_;
|
||||
}
|
||||
|
||||
static void set_format(const std::string& format)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex::scoped_lock lock(format_mutex_);
|
||||
#endif
|
||||
format_ = format;
|
||||
}
|
||||
|
||||
// interpolate the format string for output
|
||||
static std::string str();
|
||||
|
||||
// output
|
||||
static void use_file(const std::string& filepath);
|
||||
static void use_console();
|
||||
|
||||
private:
|
||||
static severity_type severity_level_;
|
||||
static severity_map object_severity_level_;
|
||||
static bool severity_env_check_;
|
||||
|
||||
static std::string format_;
|
||||
static bool format_env_check_;
|
||||
|
||||
static std::ofstream file_output_;
|
||||
static std::string file_name_;
|
||||
static std::streambuf* saved_buf_;
|
||||
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
static boost::mutex severity_mutex_;
|
||||
static boost::mutex format_mutex_;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class Ch, class Tr, class A>
|
||||
class clog_sink
|
||||
@ -166,19 +159,19 @@ namespace mapnik {
|
||||
public:
|
||||
typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
|
||||
|
||||
void operator()(const stream_buffer &s)
|
||||
void operator()(const logger::severity_type& severity, const stream_buffer &s)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
static boost::mutex mutex;
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
#endif
|
||||
std::clog << format::str() << " " << s.str() << std::endl;
|
||||
std::clog << logger::str() << " " << s.str() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<template <class Ch, class Tr, class A> class OutputPolicy,
|
||||
severity::type Severity,
|
||||
logger::severity_type Severity,
|
||||
class Ch = char,
|
||||
class Tr = std::char_traits<Ch>,
|
||||
class A = std::allocator<Ch> >
|
||||
@ -204,7 +197,7 @@ namespace mapnik {
|
||||
#ifdef MAPNIK_LOG
|
||||
if (check_severity())
|
||||
{
|
||||
output_policy()(streambuf_);
|
||||
output_policy()(Severity, streambuf_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -222,7 +215,7 @@ namespace mapnik {
|
||||
#ifdef MAPNIK_LOG
|
||||
inline bool check_severity()
|
||||
{
|
||||
return Severity >= severity::get_object(object_name_);
|
||||
return Severity >= logger::get_object_severity(object_name_);
|
||||
}
|
||||
|
||||
typename output_policy::stream_buffer streambuf_;
|
||||
@ -230,45 +223,46 @@ namespace mapnik {
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef base_log<clog_sink, severity::info> base_log_info;
|
||||
typedef base_log<clog_sink, severity::debug> base_log_debug;
|
||||
typedef base_log<clog_sink, severity::warn> base_log_warn;
|
||||
typedef base_log<clog_sink, severity::error> base_log_error;
|
||||
typedef base_log<clog_sink, severity::fatal> base_log_fatal;
|
||||
}
|
||||
typedef base_log<clog_sink, logger::info> base_log_info;
|
||||
typedef base_log<clog_sink, logger::debug> base_log_debug;
|
||||
typedef base_log<clog_sink, logger::warn> base_log_warn;
|
||||
typedef base_log<clog_sink, logger::error> base_log_error;
|
||||
typedef base_log<clog_sink, logger::fatal> base_log_fatal;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class MAPNIK_DECL info : public logger::base_log_info {
|
||||
// real interfaces
|
||||
class MAPNIK_DECL info : public detail::base_log_info {
|
||||
public:
|
||||
info() : logger::base_log_info() {}
|
||||
info(const char* object_name) : logger::base_log_info(object_name) {}
|
||||
info() : detail::base_log_info() {}
|
||||
info(const char* object_name) : detail::base_log_info(object_name) {}
|
||||
};
|
||||
|
||||
class MAPNIK_DECL debug : public logger::base_log_debug {
|
||||
class MAPNIK_DECL debug : public detail::base_log_debug {
|
||||
public:
|
||||
debug() : logger::base_log_debug() {}
|
||||
debug(const char* object_name) : logger::base_log_debug(object_name) {}
|
||||
debug() : detail::base_log_debug() {}
|
||||
debug(const char* object_name) : detail::base_log_debug(object_name) {}
|
||||
};
|
||||
|
||||
class MAPNIK_DECL warn : public logger::base_log_warn {
|
||||
class MAPNIK_DECL warn : public detail::base_log_warn {
|
||||
public:
|
||||
warn() : logger::base_log_warn() {}
|
||||
warn(const char* object_name) : logger::base_log_warn(object_name) {}
|
||||
warn() : detail::base_log_warn() {}
|
||||
warn(const char* object_name) : detail::base_log_warn(object_name) {}
|
||||
};
|
||||
|
||||
class MAPNIK_DECL error : public logger::base_log_error {
|
||||
class MAPNIK_DECL error : public detail::base_log_error {
|
||||
public:
|
||||
error() : logger::base_log_error() {}
|
||||
error(const char* object_name) : logger::base_log_error(object_name) {}
|
||||
error() : detail::base_log_error() {}
|
||||
error(const char* object_name) : detail::base_log_error(object_name) {}
|
||||
};
|
||||
|
||||
class MAPNIK_DECL fatal : public logger::base_log_fatal {
|
||||
class MAPNIK_DECL fatal : public detail::base_log_fatal {
|
||||
public:
|
||||
fatal() : logger::base_log_fatal() {}
|
||||
fatal(const char* object_name) : logger::base_log_fatal(object_name) {}
|
||||
fatal() : detail::base_log_fatal() {}
|
||||
fatal(const char* object_name) : detail::base_log_fatal(object_name) {}
|
||||
};
|
||||
|
||||
|
||||
// logging helpers
|
||||
#define MAPNIK_LOG_INFO(s) mapnik::info(#s)
|
||||
#define MAPNIK_LOG_DEBUG(s) mapnik::debug(#s)
|
||||
#define MAPNIK_LOG_WARN(s) mapnik::warn(#s)
|
||||
|
||||
@ -56,11 +56,10 @@ public:
|
||||
|
||||
void begin_path()
|
||||
{
|
||||
push_attr();
|
||||
unsigned idx = source_.start_new_path();
|
||||
attributes_.add(path_attributes(cur_attr(), idx));
|
||||
}
|
||||
|
||||
|
||||
void end_path()
|
||||
{
|
||||
if(attributes_.size() == 0)
|
||||
@ -71,7 +70,6 @@ public:
|
||||
unsigned idx = attributes_[attributes_.size() - 1].index;
|
||||
attr.index = idx;
|
||||
attributes_[attributes_.size() - 1] = attr;
|
||||
pop_attr();
|
||||
}
|
||||
|
||||
void move_to(double x, double y, bool rel=false) // M, m
|
||||
@ -235,7 +233,21 @@ public:
|
||||
cur_attr().visibility_flag = flag;
|
||||
}
|
||||
|
||||
bool visibility()
|
||||
{
|
||||
return cur_attr().visibility_flag;
|
||||
}
|
||||
|
||||
void display(bool flag)
|
||||
{
|
||||
cur_attr().display_flag = flag;
|
||||
}
|
||||
|
||||
bool display()
|
||||
{
|
||||
return cur_attr().display_flag;
|
||||
}
|
||||
|
||||
void stroke_width(double w)
|
||||
{
|
||||
cur_attr().stroke_width = w;
|
||||
|
||||
@ -45,6 +45,7 @@ struct path_attributes
|
||||
bool stroke_flag;
|
||||
bool even_odd_flag;
|
||||
bool visibility_flag;
|
||||
bool display_flag;
|
||||
agg::line_join_e line_join;
|
||||
agg::line_cap_e line_cap;
|
||||
double miter_limit;
|
||||
@ -63,6 +64,7 @@ struct path_attributes
|
||||
stroke_flag(false),
|
||||
even_odd_flag(false),
|
||||
visibility_flag(true),
|
||||
display_flag(true),
|
||||
line_join(agg::miter_join),
|
||||
line_cap(agg::butt_cap),
|
||||
miter_limit(4.0),
|
||||
@ -83,6 +85,7 @@ struct path_attributes
|
||||
stroke_flag(attr.stroke_flag),
|
||||
even_odd_flag(attr.even_odd_flag),
|
||||
visibility_flag(attr.visibility_flag),
|
||||
display_flag(attr.display_flag),
|
||||
line_join(attr.line_join),
|
||||
line_cap(attr.line_cap),
|
||||
miter_limit(attr.miter_limit),
|
||||
@ -102,6 +105,7 @@ struct path_attributes
|
||||
stroke_flag(attr.stroke_flag),
|
||||
even_odd_flag(attr.even_odd_flag),
|
||||
visibility_flag(attr.visibility_flag),
|
||||
display_flag(attr.display_flag),
|
||||
line_join(attr.line_join),
|
||||
line_cap(attr.line_cap),
|
||||
miter_limit(attr.miter_limit),
|
||||
|
||||
@ -65,24 +65,28 @@ DATASOURCE_PLUGIN(geos_datasource)
|
||||
|
||||
void geos_notice(const char* format, ...)
|
||||
{
|
||||
#ifdef MAPNIK_LOG
|
||||
char buffer[512];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsprintf(buffer, format, args);
|
||||
vsnprintf(buffer, 512, format, args);
|
||||
va_end(args);
|
||||
|
||||
MAPNIK_LOG_WARN(geos) << "geos_datasource: " << buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
void geos_error(const char* format, ...)
|
||||
{
|
||||
#ifdef MAPNIK_LOG
|
||||
char buffer[512];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsprintf(buffer, format, args);
|
||||
vsnprintf(buffer, 512, format, args);
|
||||
va_end(args);
|
||||
|
||||
MAPNIK_LOG_ERROR(geos) << "geos_datasource: " << buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -157,7 +157,7 @@ void occi_datasource::bind() const
|
||||
*params_.get<std::string>("user"),
|
||||
*params_.get<std::string>("password"),
|
||||
*params_.get<std::string>("host"),
|
||||
*params_.get<int>("max_size", 10),
|
||||
*params_.get<int>("max_size", 5),
|
||||
*params_.get<int>("initial_size", 1),
|
||||
1,
|
||||
StatelessConnectionPool::HOMOGENEOUS);
|
||||
|
||||
@ -30,54 +30,91 @@
|
||||
#define MAPNIK_LOG_FORMAT "Mapnik LOG> %Y-%m-%d %H:%M:%S:"
|
||||
#endif
|
||||
|
||||
namespace mapnik { namespace logger {
|
||||
#ifndef MAPNIK_DEFAULT_LOG_SEVERITY
|
||||
#ifdef MAPNIK_DEBUG
|
||||
#define MAPNIK_DEFAULT_LOG_SEVERITY 1
|
||||
#else
|
||||
#define MAPNIK_DEFAULT_LOG_SEVERITY 3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
// mutexes
|
||||
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex logger::severity_mutex_;
|
||||
boost::mutex logger::format_mutex_;
|
||||
#endif
|
||||
|
||||
|
||||
// first time checks
|
||||
|
||||
bool logger::severity_env_check_ = true;
|
||||
bool logger::format_env_check_ = true;
|
||||
|
||||
|
||||
// severity
|
||||
|
||||
severity::type severity::severity_level_ =
|
||||
#ifdef MAPNIK_DEBUG
|
||||
severity::debug
|
||||
#else
|
||||
severity::error
|
||||
#endif
|
||||
logger::severity_type logger::severity_level_ =
|
||||
#if MAPNIK_DEFAULT_LOG_SEVERITY == 0
|
||||
logger::info
|
||||
#elif MAPNIK_DEFAULT_LOG_SEVERITY == 1
|
||||
logger::debug
|
||||
#elif MAPNIK_DEFAULT_LOG_SEVERITY == 2
|
||||
logger::warn
|
||||
#elif MAPNIK_DEFAULT_LOG_SEVERITY == 3
|
||||
logger::error
|
||||
#elif MAPNIK_DEFAULT_LOG_SEVERITY == 4
|
||||
logger::fatal
|
||||
#elif MAPNIK_DEFAULT_LOG_SEVERITY == 5
|
||||
logger::none
|
||||
#else
|
||||
#error "Wrong default log severity level specified!"
|
||||
#endif
|
||||
;
|
||||
|
||||
severity::severity_map severity::object_severity_level_ = severity::severity_map();
|
||||
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex severity::mutex_;
|
||||
#endif
|
||||
logger::severity_map logger::object_severity_level_ = logger::severity_map();
|
||||
|
||||
|
||||
// format
|
||||
|
||||
#define __xstr__(s) __str__(s)
|
||||
#define __str__(s) #s
|
||||
std::string format::format_ = __xstr__(MAPNIK_LOG_FORMAT);
|
||||
std::string logger::format_ = __xstr__(MAPNIK_LOG_FORMAT);
|
||||
#undef __xstr__
|
||||
#undef __str__
|
||||
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex format::mutex_;
|
||||
std::string logger::str()
|
||||
{
|
||||
#if 0
|
||||
// update the format from getenv if this is the first time
|
||||
if (logger::format_env_check_)
|
||||
{
|
||||
logger::format_env_check_ = false;
|
||||
|
||||
const char* log_format = getenv("MAPNIK_LOG_FORMAT");
|
||||
if (log_format != NULL)
|
||||
{
|
||||
logger::format_ = log_format;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string format::str()
|
||||
{
|
||||
char buf[256];
|
||||
const time_t tm = time(0);
|
||||
strftime(buf, sizeof(buf), format::format_.c_str(), localtime(&tm));
|
||||
strftime(buf, sizeof(buf), logger::format_.c_str(), localtime(&tm));
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
// output
|
||||
|
||||
std::ofstream output::file_output_;
|
||||
std::string output::file_name_;
|
||||
std::streambuf* output::saved_buf_ = 0;
|
||||
std::ofstream logger::file_output_;
|
||||
std::string logger::file_name_;
|
||||
std::streambuf* logger::saved_buf_ = 0;
|
||||
|
||||
void output::use_file(const std::string& filepath)
|
||||
void logger::use_file(const std::string& filepath)
|
||||
{
|
||||
// save clog rdbuf
|
||||
if (saved_buf_ == 0)
|
||||
@ -109,7 +146,7 @@ void output::use_file(const std::string& filepath)
|
||||
}
|
||||
}
|
||||
|
||||
void output::use_console()
|
||||
void logger::use_console()
|
||||
{
|
||||
// save clog rdbuf
|
||||
if (saved_buf_ == 0)
|
||||
@ -117,9 +154,14 @@ void output::use_console()
|
||||
saved_buf_ = std::clog.rdbuf();
|
||||
}
|
||||
|
||||
// close the file to force a flush
|
||||
if (file_output_.is_open())
|
||||
{
|
||||
file_output_.close();
|
||||
}
|
||||
|
||||
std::clog.rdbuf(saved_buf_);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace mapnik
|
||||
|
||||
@ -190,22 +190,43 @@ void png_reader::read(unsigned x0, unsigned y0,image_data_32& image)
|
||||
if (png_get_gAMA(png_ptr, info_ptr, &gamma))
|
||||
png_set_gamma(png_ptr, 2.2, gamma);
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
//START read image rows
|
||||
unsigned w=std::min(unsigned(image.width()),width_);
|
||||
unsigned h=std::min(unsigned(image.height()),height_);
|
||||
unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr);
|
||||
boost::scoped_array<png_byte> row(new png_byte[rowbytes]);
|
||||
for (unsigned i=0;i<height_;++i)
|
||||
if (x0 == 0 && y0 == 0 && image.width() >= width_ && image.height() >= height_)
|
||||
{
|
||||
png_read_row(png_ptr,row.get(),0);
|
||||
if (i>=y0 && i<h)
|
||||
|
||||
if (png_get_interlace_type(png_ptr,info_ptr) == PNG_INTERLACE_ADAM7)
|
||||
{
|
||||
image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0]),w);
|
||||
png_set_interlace_handling(png_ptr); // FIXME: libpng bug?
|
||||
// according to docs png_read_image
|
||||
// "..automatically handles interlacing,
|
||||
// so you don't need to call png_set_interlace_handling()"
|
||||
}
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
// we can read whole image at once
|
||||
// alloc row pointers
|
||||
boost::scoped_array<png_byte*> rows(new png_bytep[height_]);
|
||||
for (unsigned i=0; i<height_; ++i)
|
||||
rows[i] = (png_bytep)image.getRow(i);
|
||||
png_read_image(png_ptr, rows.get());
|
||||
}
|
||||
//END
|
||||
else
|
||||
{
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
unsigned w=std::min(unsigned(image.width()),width_);
|
||||
unsigned h=std::min(unsigned(image.height()),height_);
|
||||
unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr);
|
||||
boost::scoped_array<png_byte> row(new png_byte[rowbytes]);
|
||||
//START read image rows
|
||||
for (unsigned i=0;i<height_;++i)
|
||||
{
|
||||
png_read_row(png_ptr,row.get(),0);
|
||||
if (i>=y0 && i<h)
|
||||
{
|
||||
image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0]),w);
|
||||
}
|
||||
}
|
||||
//END
|
||||
}
|
||||
|
||||
png_read_end(png_ptr,0);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr,0);
|
||||
fclose(fp);
|
||||
|
||||
@ -46,29 +46,29 @@
|
||||
namespace mapnik { namespace svg {
|
||||
|
||||
|
||||
typedef std::vector<std::pair<double, agg::rgba8> > color_lookup_type;
|
||||
typedef std::vector<std::pair<double, agg::rgba8> > color_lookup_type;
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
typedef std::vector<std::pair<std::string, std::string> > pairs_type;
|
||||
typedef std::vector<std::pair<std::string, std::string> > pairs_type;
|
||||
|
||||
template <typename Iterator,typename SkipType>
|
||||
struct key_value_sequence_ordered
|
||||
: qi::grammar<Iterator, pairs_type(), SkipType>
|
||||
template <typename Iterator,typename SkipType>
|
||||
struct key_value_sequence_ordered
|
||||
: qi::grammar<Iterator, pairs_type(), SkipType>
|
||||
{
|
||||
key_value_sequence_ordered()
|
||||
: key_value_sequence_ordered::base_type(query)
|
||||
{
|
||||
key_value_sequence_ordered()
|
||||
: key_value_sequence_ordered::base_type(query)
|
||||
{
|
||||
query = pair >> *( qi::lit(';') >> pair);
|
||||
pair = key >> -(':' >> value);
|
||||
key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9-");
|
||||
value = +(qi::char_ - qi::lit(';'));
|
||||
}
|
||||
query = pair >> *( qi::lit(';') >> pair);
|
||||
pair = key >> -(':' >> value);
|
||||
key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9-");
|
||||
value = +(qi::char_ - qi::lit(';'));
|
||||
}
|
||||
|
||||
qi::rule<Iterator, pairs_type(), SkipType> query;
|
||||
qi::rule<Iterator, std::pair<std::string, std::string>(), SkipType> pair;
|
||||
qi::rule<Iterator, std::string(), SkipType> key, value;
|
||||
};
|
||||
qi::rule<Iterator, pairs_type(), SkipType> query;
|
||||
qi::rule<Iterator, std::pair<std::string, std::string>(), SkipType> pair;
|
||||
qi::rule<Iterator, std::string(), SkipType> key, value;
|
||||
};
|
||||
|
||||
agg::rgba8 parse_color(const char* str)
|
||||
{
|
||||
@ -175,44 +175,11 @@ void svg_parser::start_element(xmlTextReaderPtr reader)
|
||||
const xmlChar *name;
|
||||
name = xmlTextReaderConstName(reader);
|
||||
|
||||
if (!is_defs_ && xmlStrEqual(name, BAD_CAST "g"))
|
||||
{
|
||||
path_.push_attr();
|
||||
parse_attr(reader);
|
||||
}
|
||||
else if (xmlStrEqual(name, BAD_CAST "defs"))
|
||||
if (xmlStrEqual(name, BAD_CAST "defs"))
|
||||
{
|
||||
if (xmlTextReaderIsEmptyElement(reader) == 0)
|
||||
is_defs_ = true;
|
||||
}
|
||||
else if ( !is_defs_ && xmlStrEqual(name, BAD_CAST "path"))
|
||||
{
|
||||
parse_path(reader);
|
||||
}
|
||||
else if (!is_defs_ && xmlStrEqual(name, BAD_CAST "polygon") )
|
||||
{
|
||||
parse_polygon(reader);
|
||||
}
|
||||
else if (!is_defs_ && xmlStrEqual(name, BAD_CAST "polyline"))
|
||||
{
|
||||
parse_polyline(reader);
|
||||
}
|
||||
else if (!is_defs_ && xmlStrEqual(name, BAD_CAST "line"))
|
||||
{
|
||||
parse_line(reader);
|
||||
}
|
||||
else if (!is_defs_ && xmlStrEqual(name, BAD_CAST "rect"))
|
||||
{
|
||||
parse_rect(reader);
|
||||
}
|
||||
else if (!is_defs_ && xmlStrEqual(name, BAD_CAST "circle"))
|
||||
{
|
||||
parse_circle(reader);
|
||||
}
|
||||
else if (!is_defs_ && xmlStrEqual(name, BAD_CAST "ellipse"))
|
||||
{
|
||||
parse_ellipse(reader);
|
||||
}
|
||||
// the gradient tags *should* be in defs, but illustrator seems not to put them in there so
|
||||
// accept them anywhere
|
||||
else if (xmlStrEqual(name, BAD_CAST "linearGradient"))
|
||||
@ -227,18 +194,65 @@ void svg_parser::start_element(xmlTextReaderPtr reader)
|
||||
{
|
||||
parse_gradient_stop(reader);
|
||||
}
|
||||
#ifdef MAPNIK_LOG
|
||||
else if (!xmlStrEqual(name, BAD_CAST "svg"))
|
||||
if ( !is_defs_ )
|
||||
{
|
||||
MAPNIK_LOG_WARN(svg_parser) << "svg_parser: Unhandled svg element=" << name;
|
||||
}
|
||||
if (xmlStrEqual(name, BAD_CAST "g"))
|
||||
{
|
||||
path_.push_attr();
|
||||
parse_attr(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
path_.push_attr();
|
||||
parse_attr(reader);
|
||||
if (path_.display())
|
||||
{
|
||||
if (xmlStrEqual(name, BAD_CAST "path"))
|
||||
{
|
||||
parse_path(reader);
|
||||
}
|
||||
else if (xmlStrEqual(name, BAD_CAST "polygon") )
|
||||
{
|
||||
parse_polygon(reader);
|
||||
}
|
||||
else if (xmlStrEqual(name, BAD_CAST "polyline"))
|
||||
{
|
||||
parse_polyline(reader);
|
||||
}
|
||||
else if (xmlStrEqual(name, BAD_CAST "line"))
|
||||
{
|
||||
parse_line(reader);
|
||||
}
|
||||
else if (xmlStrEqual(name, BAD_CAST "rect"))
|
||||
{
|
||||
parse_rect(reader);
|
||||
}
|
||||
else if (xmlStrEqual(name, BAD_CAST "circle"))
|
||||
{
|
||||
parse_circle(reader);
|
||||
}
|
||||
else if (xmlStrEqual(name, BAD_CAST "ellipse"))
|
||||
{
|
||||
parse_ellipse(reader);
|
||||
}
|
||||
#ifdef MAPNIK_LOG
|
||||
else if (!xmlStrEqual(name, BAD_CAST "svg"))
|
||||
{
|
||||
MAPNIK_LOG_WARN(svg_parser) << "svg_parser: Unhandled svg element=" << name;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
path_.pop_attr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void svg_parser::end_element(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *name;
|
||||
name = xmlTextReaderConstName(reader);
|
||||
|
||||
|
||||
if (!is_defs_ && xmlStrEqual(name, BAD_CAST "g"))
|
||||
{
|
||||
path_.pop_attr();
|
||||
@ -251,6 +265,7 @@ void svg_parser::end_element(xmlTextReaderPtr reader)
|
||||
{
|
||||
gradient_map_[temporary_gradient_.first] = temporary_gradient_.second;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void svg_parser::parse_attr(const xmlChar * name, const xmlChar * value )
|
||||
@ -370,7 +385,7 @@ void svg_parser::parse_attr(const xmlChar * name, const xmlChar * value )
|
||||
}
|
||||
else if (xmlStrEqual(name, BAD_CAST "display") && xmlStrEqual(value, BAD_CAST "none"))
|
||||
{
|
||||
path_.visibility(false);
|
||||
path_.display(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,100 +393,127 @@ void svg_parser::parse_attr(const xmlChar * name, const xmlChar * value )
|
||||
void svg_parser::parse_attr(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *name, *value;
|
||||
while (xmlTextReaderMoveToNextAttribute(reader))
|
||||
|
||||
if (xmlTextReaderMoveToFirstAttribute(reader) == 1)
|
||||
{
|
||||
name = xmlTextReaderConstName(reader);
|
||||
value = xmlTextReaderConstValue(reader);
|
||||
if (xmlStrEqual(name, BAD_CAST "style"))
|
||||
do
|
||||
{
|
||||
typedef std::vector<std::pair<std::string,std::string> > cont_type;
|
||||
typedef cont_type::value_type value_type;
|
||||
cont_type vec;
|
||||
parse_style((const char*)value, vec);
|
||||
BOOST_FOREACH(value_type kv , vec )
|
||||
name = xmlTextReaderConstName(reader);
|
||||
value = xmlTextReaderConstValue(reader);
|
||||
|
||||
if (xmlStrEqual(name, BAD_CAST "style"))
|
||||
{
|
||||
parse_attr(BAD_CAST kv.first.c_str(),BAD_CAST kv.second.c_str());
|
||||
typedef std::vector<std::pair<std::string,std::string> > cont_type;
|
||||
typedef cont_type::value_type value_type;
|
||||
cont_type vec;
|
||||
parse_style((const char*)value, vec);
|
||||
BOOST_FOREACH(value_type kv , vec )
|
||||
{
|
||||
parse_attr(BAD_CAST kv.first.c_str(),BAD_CAST kv.second.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_attr(name,value);
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_attr(name,value);
|
||||
}
|
||||
} while(xmlTextReaderMoveToNextAttribute(reader) == 1);
|
||||
}
|
||||
xmlTextReaderMoveToElement(reader);
|
||||
}
|
||||
void svg_parser::parse_path(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "d");
|
||||
if (value)
|
||||
{
|
||||
path_.begin_path();
|
||||
parse_attr(reader);
|
||||
|
||||
if (!mapnik::svg::parse_path((const char*) value, path_))
|
||||
{
|
||||
std::runtime_error("can't parse PATH\n");
|
||||
xmlFree(value);
|
||||
throw std::runtime_error("can't parse PATH\n");
|
||||
}
|
||||
path_.end_path();
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
|
||||
void svg_parser::parse_polygon(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "points");
|
||||
if (value)
|
||||
{
|
||||
path_.begin_path();
|
||||
parse_attr(reader);
|
||||
if (!mapnik::svg::parse_points((const char*) value, path_))
|
||||
{
|
||||
xmlFree(value);
|
||||
throw std::runtime_error("Failed to parse <polygon>\n");
|
||||
}
|
||||
path_.close_subpath();
|
||||
path_.end_path();
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
|
||||
void svg_parser::parse_polyline(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "points");
|
||||
if (value)
|
||||
{
|
||||
path_.begin_path();
|
||||
parse_attr(reader);
|
||||
if (!mapnik::svg::parse_points((const char*) value, path_))
|
||||
{
|
||||
xmlFree(value);
|
||||
throw std::runtime_error("Failed to parse <polygon>\n");
|
||||
}
|
||||
|
||||
path_.end_path();
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
|
||||
void svg_parser::parse_line(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double x2 = 0.0;
|
||||
double y2 = 0.0;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "x1");
|
||||
if (value) x1 = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
x1 = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "y1");
|
||||
if (value) y1 = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
y1 = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "x2");
|
||||
if (value) x2 = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
x2 = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "y2");
|
||||
if (value) y2 = parse_double((const char*)value);
|
||||
|
||||
if (value)
|
||||
{
|
||||
y2 = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
path_.begin_path();
|
||||
parse_attr(reader);
|
||||
path_.move_to(x1, y1);
|
||||
path_.line_to(x2, y2);
|
||||
path_.end_path();
|
||||
@ -480,19 +522,32 @@ void svg_parser::parse_line(xmlTextReaderPtr reader)
|
||||
|
||||
void svg_parser::parse_circle(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
double cx = 0.0;
|
||||
double cy = 0.0;
|
||||
double r = 0.0;
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "cx");
|
||||
if (value) cx = parse_double((const char*)value);
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "cy");
|
||||
if (value) cy = parse_double((const char*)value);
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "r");
|
||||
if (value) r = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
cx = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "cy");
|
||||
if (value)
|
||||
{
|
||||
cy = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "r");
|
||||
if (value)
|
||||
{
|
||||
r = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
path_.begin_path();
|
||||
parse_attr(reader);
|
||||
|
||||
if(r != 0.0)
|
||||
{
|
||||
@ -506,23 +561,41 @@ void svg_parser::parse_circle(xmlTextReaderPtr reader)
|
||||
|
||||
void svg_parser::parse_ellipse(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
double cx = 0.0;
|
||||
double cy = 0.0;
|
||||
double rx = 0.0;
|
||||
double ry = 0.0;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "cx");
|
||||
if (value) cx = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
cx = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "cy");
|
||||
if (value) cy = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
cy = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "rx");
|
||||
if (value) rx = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
rx = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "ry");
|
||||
if (value) ry = parse_double((const char*)value);
|
||||
|
||||
if (value)
|
||||
{
|
||||
ry = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
path_.begin_path();
|
||||
parse_attr(reader);
|
||||
|
||||
if(rx != 0.0 && ry != 0.0)
|
||||
{
|
||||
@ -533,11 +606,12 @@ void svg_parser::parse_ellipse(xmlTextReaderPtr reader)
|
||||
}
|
||||
|
||||
path_.end_path();
|
||||
|
||||
}
|
||||
|
||||
void svg_parser::parse_rect(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
double x = 0.0;
|
||||
double y = 0.0;
|
||||
double w = 0.0;
|
||||
@ -546,18 +620,39 @@ void svg_parser::parse_rect(xmlTextReaderPtr reader)
|
||||
double ry = 0.0;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "x");
|
||||
if (value) x = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
x = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "y");
|
||||
if (value) y = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
y = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "width");
|
||||
if (value) w = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
w = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "height");
|
||||
if (value) h = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
h = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
bool rounded = true;
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "rx");
|
||||
|
||||
if (value) rx = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
rx = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
else rounded = false;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "ry");
|
||||
@ -569,6 +664,7 @@ void svg_parser::parse_rect(xmlTextReaderPtr reader)
|
||||
rx = ry;
|
||||
rounded = true;
|
||||
}
|
||||
xmlFree(value);
|
||||
}
|
||||
else if (rounded)
|
||||
{
|
||||
@ -581,22 +677,10 @@ void svg_parser::parse_rect(xmlTextReaderPtr reader)
|
||||
if(h < 0.0) throw std::runtime_error("parse_rect: Invalid height");
|
||||
if(rx < 0.0) throw std::runtime_error("parse_rect: Invalid rx");
|
||||
if(ry < 0.0) throw std::runtime_error("parse_rect: Invalid ry");
|
||||
|
||||
path_.begin_path();
|
||||
parse_attr(reader);
|
||||
|
||||
|
||||
if(rounded)
|
||||
{
|
||||
//path_.move_to(x + rx,y);
|
||||
//path_.line_to(x + w - rx,y);
|
||||
//path_.arc_to (rx,ry,0,0,1,x + w, y + ry);
|
||||
//path_.line_to(x + w, y + h - ry);
|
||||
//path_.arc_to (rx,ry,0,0,1,x + w - rx, y + h);
|
||||
//path_.line_to(x + rx, y + h);
|
||||
//path_.arc_to(rx,ry,0,0,1,x,y + h - ry);
|
||||
//path_.line_to(x,y+ry);
|
||||
//path_.arc_to(rx,ry,0,0,1,x + rx,y);
|
||||
//path_.close_subpath();
|
||||
agg::rounded_rect r;
|
||||
r.rect(x,y,x+w,y+h);
|
||||
r.radius(rx,ry);
|
||||
@ -623,14 +707,18 @@ void svg_parser::parse_rect(xmlTextReaderPtr reader)
|
||||
*/
|
||||
void svg_parser::parse_gradient_stop(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
|
||||
double offset = 0.0;
|
||||
mapnik::color stop_color;
|
||||
double opacity = 1.0;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "offset");
|
||||
if (value) offset = parse_double((const char*)value);
|
||||
if (value)
|
||||
{
|
||||
offset = parse_double((const char*)value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "style");
|
||||
if (value)
|
||||
@ -658,6 +746,7 @@ void svg_parser::parse_gradient_stop(xmlTextReaderPtr reader)
|
||||
opacity = parse_double(kv.second.c_str());
|
||||
}
|
||||
}
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "stop-color");
|
||||
@ -671,12 +760,14 @@ void svg_parser::parse_gradient_stop(xmlTextReaderPtr reader)
|
||||
{
|
||||
MAPNIK_LOG_ERROR(svg_parser) << ex.what();
|
||||
}
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "stop-opacity");
|
||||
if (value)
|
||||
{
|
||||
opacity = parse_double((const char *) value);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
|
||||
@ -695,7 +786,7 @@ void svg_parser::parse_gradient_stop(xmlTextReaderPtr reader)
|
||||
|
||||
bool svg_parser::parse_common_gradient(xmlTextReaderPtr reader)
|
||||
{
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
|
||||
std::string id;
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||
@ -705,6 +796,7 @@ bool svg_parser::parse_common_gradient(xmlTextReaderPtr reader)
|
||||
gradient new_grad;
|
||||
id = std::string((const char *) value);
|
||||
temporary_gradient_ = std::make_pair(id, new_grad);
|
||||
xmlFree(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -714,36 +806,44 @@ bool svg_parser::parse_common_gradient(xmlTextReaderPtr reader)
|
||||
|
||||
// check if we should inherit from another tag
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "xlink:href");
|
||||
if (value && value[0] == '#')
|
||||
if (value)
|
||||
{
|
||||
std::string linkid = (const char *) &value[1];
|
||||
if (gradient_map_.count(linkid))
|
||||
if (value[0] == '#')
|
||||
{
|
||||
//MAPNIK_LOG_DEBUG(svg_parser) << "\tLoading linked gradient properties from " << linkid;
|
||||
temporary_gradient_.second = gradient_map_[linkid];
|
||||
std::string linkid = (const char *) &value[1];
|
||||
if (gradient_map_.count(linkid))
|
||||
{
|
||||
temporary_gradient_.second = gradient_map_[linkid];
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(svg_parser) << "Failed to find linked gradient " << linkid;
|
||||
}
|
||||
}
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "gradientUnits");
|
||||
if (value)
|
||||
{
|
||||
if (xmlStrEqual(value, BAD_CAST "userSpaceOnUse"))
|
||||
{
|
||||
temporary_gradient_.second.set_units(USER_SPACE_ON_USE);
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(svg_parser) << "Failed to find linked gradient " << linkid;
|
||||
temporary_gradient_.second.set_units(OBJECT_BOUNDING_BOX);
|
||||
}
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "gradientUnits");
|
||||
if (value && std::string((const char*) value) == "userSpaceOnUse")
|
||||
{
|
||||
temporary_gradient_.second.set_units(USER_SPACE_ON_USE);
|
||||
}
|
||||
else
|
||||
{
|
||||
temporary_gradient_.second.set_units(OBJECT_BOUNDING_BOX);
|
||||
}
|
||||
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "gradientTransform");
|
||||
if (value)
|
||||
{
|
||||
agg::trans_affine tr;
|
||||
mapnik::svg::parse_transform((const char*) value,tr);
|
||||
temporary_gradient_.second.set_transform(tr);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -766,7 +866,7 @@ void svg_parser::parse_radial_gradient(xmlTextReaderPtr reader)
|
||||
if (!parse_common_gradient(reader))
|
||||
return;
|
||||
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
double cx = 0.5;
|
||||
double cy = 0.5;
|
||||
double fx = 0.0;
|
||||
@ -775,26 +875,43 @@ void svg_parser::parse_radial_gradient(xmlTextReaderPtr reader)
|
||||
bool has_percent=true;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "cx");
|
||||
if (value) cx = parse_double_optional_percent((const char*)value, has_percent);
|
||||
if (value)
|
||||
{
|
||||
cx = parse_double_optional_percent((const char*)value, has_percent);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "cy");
|
||||
if (value) cy = parse_double_optional_percent((const char*)value, has_percent);
|
||||
if (value)
|
||||
{
|
||||
cy = parse_double_optional_percent((const char*)value, has_percent);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "fx");
|
||||
if (value)
|
||||
{
|
||||
fx = parse_double_optional_percent((const char*)value, has_percent);
|
||||
xmlFree(value);
|
||||
}
|
||||
else
|
||||
fx = cx;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "fy");
|
||||
if (value)
|
||||
{
|
||||
fy = parse_double_optional_percent((const char*)value, has_percent);
|
||||
xmlFree(value);
|
||||
}
|
||||
else
|
||||
fy = cy;
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "r");
|
||||
if (value) r = parse_double_optional_percent((const char*)value, has_percent);
|
||||
|
||||
if (value)
|
||||
{
|
||||
r = parse_double_optional_percent((const char*)value, has_percent);
|
||||
xmlFree(value);
|
||||
}
|
||||
// this logic for detecting %'s will not support mixed coordinates.
|
||||
if (has_percent && temporary_gradient_.second.get_units() == USER_SPACE_ON_USE)
|
||||
{
|
||||
@ -814,7 +931,7 @@ void svg_parser::parse_linear_gradient(xmlTextReaderPtr reader)
|
||||
if (!parse_common_gradient(reader))
|
||||
return;
|
||||
|
||||
const xmlChar *value;
|
||||
xmlChar *value;
|
||||
double x1 = 0.0;
|
||||
double x2 = 1.0;
|
||||
double y1 = 0.0;
|
||||
@ -822,17 +939,32 @@ void svg_parser::parse_linear_gradient(xmlTextReaderPtr reader)
|
||||
|
||||
bool has_percent=true;
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "x1");
|
||||
if (value) x1 = parse_double_optional_percent((const char*)value, has_percent);
|
||||
if (value)
|
||||
{
|
||||
x1 = parse_double_optional_percent((const char*)value, has_percent);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "x2");
|
||||
if (value) x2 = parse_double_optional_percent((const char*)value, has_percent);
|
||||
if (value)
|
||||
{
|
||||
x2 = parse_double_optional_percent((const char*)value, has_percent);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "y1");
|
||||
if (value) y1 = parse_double_optional_percent((const char*)value, has_percent);
|
||||
|
||||
if (value)
|
||||
{
|
||||
y1 = parse_double_optional_percent((const char*)value, has_percent);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
value = xmlTextReaderGetAttribute(reader, BAD_CAST "y2");
|
||||
if (value) y2 = parse_double_optional_percent((const char*)value, has_percent);
|
||||
|
||||
if (value)
|
||||
{
|
||||
y2 = parse_double_optional_percent((const char*)value, has_percent);
|
||||
xmlFree(value);
|
||||
}
|
||||
// this logic for detecting %'s will not support mixed coordinates.
|
||||
if (has_percent && temporary_gradient_.second.get_units() == USER_SPACE_ON_USE)
|
||||
{
|
||||
|
||||
@ -316,7 +316,8 @@ SOURCES += \
|
||||
|
||||
OTHER_FILES += \
|
||||
../SConstruct \
|
||||
../config.py
|
||||
../config.py \
|
||||
../CHANGELOG.md
|
||||
|
||||
include(agg.pri)
|
||||
include(plugins.pri)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user