Merge commit '1454105b124daccc4d64654e11c442a2a1aa5008' into harfbuzz

Conflicts:
	src/build.py
This commit is contained in:
Hermann Kraus 2013-03-16 17:44:03 +01:00
commit 20ff37eb2d
22 changed files with 468 additions and 313 deletions

View file

@ -8,6 +8,10 @@ For a complete change history, see the git log.
## Future ## Future
- Added ability to access style list from map by (name,obj) in python (#1725)
- Added `is_solid` method to python mapnik.Image and mapnik.ImageView classes (#1728)
- Changed scale_denominator C++ interface to take scale as first argument rather than map. - Changed scale_denominator C++ interface to take scale as first argument rather than map.
- Added support for `background-image` in cairo_renderer (#1724) - Added support for `background-image` in cairo_renderer (#1724)

View file

@ -370,6 +370,8 @@ PathVariable.PathAccept),
('JOBS', 'Set the number of parallel compilations', "1", lambda key, value, env: int(value), int), ('JOBS', 'Set the number of parallel compilations', "1", lambda key, value, env: int(value), int),
BoolVariable('DEMO', 'Compile demo c++ application', 'True'), BoolVariable('DEMO', 'Compile demo c++ application', 'True'),
BoolVariable('PGSQL2SQLITE', 'Compile and install a utility to convert postgres tables to sqlite', 'False'), BoolVariable('PGSQL2SQLITE', 'Compile and install a utility to convert postgres tables to sqlite', 'False'),
BoolVariable('SHAPEINDEX', 'Compile and install a utility to generate shapefile indexes in the custom format (.index) Mapnik supports', 'True'),
BoolVariable('SVG2PNG', 'Compile and install a utility to generate render an svg file to a png on the command line', 'False'),
BoolVariable('COLOR_PRINT', 'Print build status information in color', 'True'), BoolVariable('COLOR_PRINT', 'Print build status information in color', 'True'),
BoolVariable('SAMPLE_INPUT_PLUGINS', 'Compile and install sample plugins', 'False'), BoolVariable('SAMPLE_INPUT_PLUGINS', 'Compile and install sample plugins', 'False'),
BoolVariable('BIGINT', 'Compile support for 64-bit integers in mapnik::value', 'True'), BoolVariable('BIGINT', 'Compile support for 64-bit integers in mapnik::value', 'True'),
@ -1805,12 +1807,14 @@ if not HELP_REQUESTED:
# Build shapeindex and remove its dependency from the LIBS # Build shapeindex and remove its dependency from the LIBS
if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']: if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']:
if env['SHAPEINDEX']:
SConscript('utils/shapeindex/build.py') SConscript('utils/shapeindex/build.py')
# Build the pgsql2psqlite app if requested # Build the pgsql2psqlite app if requested
if env['PGSQL2SQLITE']: if env['PGSQL2SQLITE']:
SConscript('utils/pgsql2sqlite/build.py') SConscript('utils/pgsql2sqlite/build.py')
if env['SVG2PNG']:
SConscript('utils/svg2png/build.py') SConscript('utils/svg2png/build.py')
# devtools not ready for public # devtools not ready for public

View file

@ -138,6 +138,9 @@ boost::python::list field_types(boost::shared_ptr<mapnik::datasource> const& ds)
return fld_types; return fld_types;
}} }}
mapnik::parameters const& (mapnik::datasource::*params_const)() const = &mapnik::datasource::params;
void export_datasource() void export_datasource()
{ {
using namespace boost::python; using namespace boost::python;
@ -164,7 +167,7 @@ void export_datasource()
.def("fields",&fields) .def("fields",&fields)
.def("field_types",&field_types) .def("field_types",&field_types)
.def("features_at_point",&datasource::features_at_point, (arg("coord"),arg("tolerance")=0)) .def("features_at_point",&datasource::features_at_point, (arg("coord"),arg("tolerance")=0))
.def("params",&datasource::params,return_value_policy<copy_const_reference>(), .def("params",make_function(params_const,return_value_policy<copy_const_reference>()),
"The configuration parameters of the data source. " "The configuration parameters of the data source. "
"These vary depending on the type of data source.") "These vary depending on the type of data source.")
; ;

View file

@ -107,6 +107,28 @@ bool painted(mapnik::image_32 const& im)
return im.painted(); return im.painted();
} }
bool is_solid(mapnik::image_32 const& im)
{
if (im.width() > 0 && im.height() > 0)
{
mapnik::image_data_32 const & data = im.data();
mapnik::image_data_32::pixel_type const* first_row = data.getRow(0);
mapnik::image_data_32::pixel_type const first_pixel = first_row[0];
for (unsigned y = 0; y < im.height(); ++y)
{
mapnik::image_data_32::pixel_type const * row = data.getRow(y);
for (unsigned x = 0; x < im.width(); ++x)
{
if (first_pixel != row[x])
{
return false;
}
}
}
}
return true;
}
unsigned get_pixel(mapnik::image_32 const& im, int x, int y) unsigned get_pixel(mapnik::image_32 const& im, int x, int y)
{ {
if (x < static_cast<int>(im.width()) && y < static_cast<int>(im.height())) if (x < static_cast<int>(im.width()) && y < static_cast<int>(im.height()))
@ -206,6 +228,7 @@ void export_image()
.def("height",&image_32::height) .def("height",&image_32::height)
.def("view",&image_32::get_view) .def("view",&image_32::get_view)
.def("painted",&painted) .def("painted",&painted)
.def("is_solid",&is_solid)
.add_property("background",make_function .add_property("background",make_function
(&image_32::get_background,return_value_policy<copy_const_reference>()), (&image_32::get_background,return_value_policy<copy_const_reference>()),
&image_32::set_background, "The background color of the image.") &image_32::set_background, "The background color of the image.")

View file

@ -76,6 +76,27 @@ PyObject* view_tostring3(image_view<image_data_32> const & view, std::string con
(s.data(),s.size()); (s.data(),s.size());
} }
bool is_solid(image_view<image_data_32> const& view)
{
if (view.width() > 0 && view.height() > 0)
{
mapnik::image_view<image_data_32>::pixel_type const* first_row = view.getRow(0);
mapnik::image_view<image_data_32>::pixel_type const first_pixel = first_row[0];
for (unsigned y = 0; y < view.height(); ++y)
{
mapnik::image_view<image_data_32>::pixel_type const * row = view.getRow(y);
for (unsigned x = 0; x < view.width(); ++x)
{
if (first_pixel != row[x])
{
return false;
}
}
}
}
return true;
}
void save_view1(image_view<image_data_32> const& view, void save_view1(image_view<image_data_32> const& view,
std::string const& filename) std::string const& filename)
{ {
@ -104,6 +125,7 @@ void export_image_view()
class_<image_view<image_data_32> >("ImageView","A view into an image.",no_init) class_<image_view<image_data_32> >("ImageView","A view into an image.",no_init)
.def("width",&image_view<image_data_32>::width) .def("width",&image_view<image_data_32>::width)
.def("height",&image_view<image_data_32>::height) .def("height",&image_view<image_data_32>::height)
.def("is_solid",&is_solid)
.def("tostring",&view_tostring1) .def("tostring",&view_tostring1)
.def("tostring",&view_tostring2) .def("tostring",&view_tostring2)
.def("tostring",&view_tostring3) .def("tostring",&view_tostring3)

View file

@ -116,10 +116,10 @@ void set_maximum_extent(mapnik::Map & m, boost::optional<mapnik::box2d<double> >
struct extract_style struct extract_style
{ {
typedef mapnik::feature_type_style result_type; typedef boost::python::tuple result_type;
result_type operator() (std::map<std::string, mapnik::feature_type_style>::value_type const& val) const result_type operator() (std::map<std::string, mapnik::feature_type_style>::value_type const& val) const
{ {
return val.second; return boost::python::make_tuple(val.first,val.second);
} }
}; };

View file

@ -28,7 +28,6 @@
#include <mapnik/value_error.hpp> #include <mapnik/value_error.hpp>
#include "mapnik_enumeration.hpp" #include "mapnik_enumeration.hpp"
#include <mapnik/feature_type_style.hpp> #include <mapnik/feature_type_style.hpp>
#include <mapnik/image_filter_grammar.hpp> // image_filter_grammar
#include <mapnik/image_filter_types.hpp> // generate_image_filters #include <mapnik/image_filter_types.hpp> // generate_image_filters
using mapnik::feature_type_style; using mapnik::feature_type_style;
@ -45,18 +44,12 @@ std::string get_image_filters(feature_type_style & style)
void set_image_filters(feature_type_style & style, std::string const& filters) void set_image_filters(feature_type_style & style, std::string const& filters)
{ {
std::string::const_iterator itr = filters.begin();
std::string::const_iterator end = filters.end();
mapnik::image_filter_grammar<std::string::const_iterator,
std::vector<mapnik::filter::filter_type> > filter_grammar;
std::vector<mapnik::filter::filter_type> new_filters; std::vector<mapnik::filter::filter_type> new_filters;
bool result = boost::spirit::qi::phrase_parse(itr,end,
filter_grammar, bool result = parse_image_filters(filters, new_filters);
boost::spirit::qi::ascii::space, if (!result)
new_filters);
if (!result || itr!=end)
{ {
throw mapnik::value_error("failed to parse image-filters: '" + std::string(itr,end) + "'"); throw mapnik::value_error("failed to parse image-filters: '" + filters + "'");
} }
style.image_filters().swap(new_filters); style.image_filters().swap(new_filters);
} }

View file

@ -45,7 +45,7 @@ namespace mapnik {
template <typename T> template <typename T>
void grid2utf(T const& grid_type, void grid2utf(T const& grid_type,
boost::python::list& l, boost::python::list& l,
std::vector<grid::lookup_type>& key_order) std::vector<typename T::lookup_type>& key_order)
{ {
typedef std::map< typename T::lookup_type, typename T::value_type> keys_type; typedef std::map< typename T::lookup_type, typename T::value_type> keys_type;
typedef typename keys_type::const_iterator keys_iterator; typedef typename keys_type::const_iterator keys_iterator;

View file

@ -48,6 +48,8 @@ namespace agg
ClipperLib::Clipper m_clipper; ClipperLib::Clipper m_clipper;
clipper_PolyFillType m_subjFillType; clipper_PolyFillType m_subjFillType;
clipper_PolyFillType m_clipFillType; clipper_PolyFillType m_clipFillType;
double start_x_;
double start_y_;
int Round(double val) int Round(double val)
{ {
@ -67,7 +69,9 @@ namespace agg
m_contour(-1), m_contour(-1),
m_operation(op), m_operation(op),
m_subjFillType(subjFillType), m_subjFillType(subjFillType),
m_clipFillType(clipFillType) m_clipFillType(clipFillType),
start_x_(0),
start_y_(0)
{ {
m_scaling_factor = std::max(std::min(scaling_factor, 6),0); m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor)); m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
@ -84,7 +88,9 @@ namespace agg
m_contour(-1), m_contour(-1),
m_operation(op), m_operation(op),
m_subjFillType(subjFillType), m_subjFillType(subjFillType),
m_clipFillType(clipFillType) m_clipFillType(clipFillType),
start_x_(0),
start_y_(0)
{ {
m_scaling_factor = std::max(std::min(scaling_factor, 6),0); m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor)); m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
@ -271,6 +277,8 @@ namespace agg
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------
template<class VSA, class VSB> template<class VSA, class VSB>
unsigned conv_clipper<VSA, VSB>::vertex(double *x, double *y) unsigned conv_clipper<VSA, VSB>::vertex(double *x, double *y)
{ {
@ -281,10 +289,14 @@ namespace agg
if( next_vertex( x, y ) ) if( next_vertex( x, y ) )
{ {
m_status =status_line_to; m_status =status_line_to;
start_x_ = *x;
start_y_ = *y;
return path_cmd_move_to; return path_cmd_move_to;
} }
else else
{ {
*x = start_x_;
*y = start_y_;
m_status = status_stop; m_status = status_stop;
return path_cmd_end_poly | path_flags_close; return path_cmd_end_poly | path_flags_close;
} }
@ -301,6 +313,8 @@ namespace agg
else else
{ {
m_status = status_move_to; m_status = status_move_to;
*x = start_x_;
*y = start_y_;
return path_cmd_end_poly | path_flags_close; return path_cmd_end_poly | path_flags_close;
} }
} }

View file

@ -99,6 +99,11 @@ public:
return params_; return params_;
} }
parameters & params()
{
return params_;
}
/*! /*!
* @brief Get the type of the datasource * @brief Get the type of the datasource
* @return The type of the datasource (Vector or Raster) * @return The type of the datasource (Vector or Raster)

View file

@ -320,8 +320,14 @@ operator>>(std::istream & is, mapnik::enumeration<ENUM, THE_MAX> & e)
/** Helper macro. Creates a typedef. /** Helper macro. Creates a typedef.
* @relates mapnik::enumeration * @relates mapnik::enumeration
*/ */
#ifdef _MSC_VER
#define DEFINE_ENUM( name, e) \
template enumeration<e, e ## _MAX>; \
typedef enumeration<e, e ## _MAX> name
#else
#define DEFINE_ENUM( name, e) \ #define DEFINE_ENUM( name, e) \
typedef enumeration<e, e ## _MAX> name typedef enumeration<e, e ## _MAX> name
#endif
/** Helper macro. Runs the verify_mapnik_enum() method during static initialization. /** Helper macro. Runs the verify_mapnik_enum() method during static initialization.
* @relates mapnik::enumeration * @relates mapnik::enumeration

View file

@ -23,6 +23,9 @@
#ifndef MAPNIK_IMAGE_FILTER_TYPES_HPP #ifndef MAPNIK_IMAGE_FILTER_TYPES_HPP
#define MAPNIK_IMAGE_FILTER_TYPES_HPP #define MAPNIK_IMAGE_FILTER_TYPES_HPP
// mapnik
#include <mapnik/config.hpp>
// boost // boost
#include <boost/variant/variant_fwd.hpp> #include <boost/variant/variant_fwd.hpp>
@ -125,7 +128,9 @@ inline std::ostream& operator<< (std::ostream& os, invert)
inline std::ostream& operator<< (std::ostream& os, filter_type const& filter); inline std::ostream& operator<< (std::ostream& os, filter_type const& filter);
bool generate_image_filters(std::back_insert_iterator<std::string> & sink, std::vector<filter_type> const& v); MAPNIK_DECL bool generate_image_filters(std::back_insert_iterator<std::string> & sink, std::vector<filter_type> const& v);
MAPNIK_DECL bool parse_image_filters(std::string const& filters, std::vector<filter_type>& image_filters);
}} }}

View file

@ -24,34 +24,14 @@
#define MAPNIK_GEOMETRY_TO_WKT_HPP #define MAPNIK_GEOMETRY_TO_WKT_HPP
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/config.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/util/geometry_wkt_generator.hpp>
// boost
#include <boost/spirit/include/karma.hpp>
namespace mapnik { namespace util { namespace mapnik { namespace util {
namespace karma = boost::spirit::karma; MAPNIK_DECL bool to_wkt(std::string & wkt, mapnik::geometry_type const& geom);
bool to_wkt(std::string & wkt, mapnik::geometry_type const& geom) MAPNIK_DECL bool to_wkt(std::string & wkt, mapnik::geometry_container const& geom);
{
typedef std::back_insert_iterator<std::string> sink_type;
sink_type sink(wkt);
wkt_generator<sink_type, mapnik::geometry_type> generator(true);
bool result = karma::generate(sink, generator, geom);
return result;
}
bool to_wkt(std::string & wkt, mapnik::geometry_container const& geom)
{
typedef std::back_insert_iterator<std::string> sink_type;
sink_type sink(wkt);
wkt_multi_generator<sink_type, mapnik::geometry_container> generator;
bool result = karma::generate(sink, generator, geom);
return result;
}
}} }}

View file

@ -56,11 +56,20 @@ regex = 'boost_regex%s' % env['BOOST_APPEND']
system = 'boost_system%s' % env['BOOST_APPEND'] system = 'boost_system%s' % env['BOOST_APPEND']
# clear out and re-set libs for this env # clear out and re-set libs for this env
lib_env['LIBS'] = ['freetype','ltdl','png','tiff','z','proj',env['ICU_LIB_NAME'],filesystem,system,regex,'harfbuzz'] lib_env['LIBS'] = ['freetype','ltdl','z',env['ICU_LIB_NAME'],filesystem,system,regex,'harfbuzz']
if env['PROJ']:
lib_env['LIBS'].append('proj')
if env['PNG']:
lib_env['LIBS'].append('png')
if env['JPEG']: if env['JPEG']:
lib_env['LIBS'].append('jpeg') lib_env['LIBS'].append('jpeg')
if env['TIFF']:
lib_env['LIBS'].append('tiff')
if len(env['EXTRA_FREETYPE_LIBS']): if len(env['EXTRA_FREETYPE_LIBS']):
lib_env['LIBS'].extend(copy(env['EXTRA_FREETYPE_LIBS'])) lib_env['LIBS'].extend(copy(env['EXTRA_FREETYPE_LIBS']))
@ -141,7 +150,6 @@ source = Split(
palette.cpp palette.cpp
path_expression_grammar.cpp path_expression_grammar.cpp
plugin.cpp plugin.cpp
png_reader.cpp
point_symbolizer.cpp point_symbolizer.cpp
polygon_pattern_symbolizer.cpp polygon_pattern_symbolizer.cpp
polygon_symbolizer.cpp polygon_symbolizer.cpp
@ -149,7 +157,6 @@ source = Split(
save_map.cpp save_map.cpp
shield_symbolizer.cpp shield_symbolizer.cpp
text_symbolizer.cpp text_symbolizer.cpp
tiff_reader.cpp
wkb.cpp wkb.cpp
projection.cpp projection.cpp
proj_transform.cpp proj_transform.cpp
@ -219,6 +226,18 @@ if env['JPEG']:
jpeg_reader.cpp jpeg_reader.cpp
""") """)
if env['TIFF']:
source += Split(
"""
tiff_reader.cpp
""")
if env['PNG']:
source += Split(
"""
png_reader.cpp
""")
# agg backend # agg backend
source += Split( source += Split(
""" """

View file

@ -34,6 +34,14 @@ static const char * gradient_strings[] = {
IMPLEMENT_ENUM( gradient_e, gradient_strings ) IMPLEMENT_ENUM( gradient_e, gradient_strings )
static const char * gradient_unit_strings[] = {
"user-space-on-use",
"user-space-on-use-bounding-box",
"object-bounding-box",
""
};
IMPLEMENT_ENUM( gradient_unit_e, gradient_unit_strings )
gradient::gradient() gradient::gradient()
: gradient_type_(NO_GRADIENT), : gradient_type_(NO_GRADIENT),

View file

@ -21,6 +21,7 @@
*****************************************************************************/ *****************************************************************************/
// mapnik // mapnik
#include <mapnik/image_filter_types.hpp> #include <mapnik/image_filter_types.hpp>
#include <mapnik/image_filter_grammar.hpp> // image_filter_grammar
// boost // boost
#include <boost/spirit/include/karma.hpp> #include <boost/spirit/include/karma.hpp>
@ -63,4 +64,17 @@ bool generate_image_filters(std::back_insert_iterator<std::string>& sink, std::v
return r; return r;
} }
bool parse_image_filters(std::string const& filters, std::vector<filter_type>& image_filters)
{
std::string::const_iterator itr = filters.begin();
std::string::const_iterator end = filters.end();
mapnik::image_filter_grammar<std::string::const_iterator,
std::vector<mapnik::filter::filter_type> > filter_grammar;
bool r = boost::spirit::qi::phrase_parse(itr,end,
filter_grammar,
boost::spirit::qi::ascii::space,
image_filters);
return r && itr==end;
}
}} }}

View file

@ -425,15 +425,10 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
if (filters) if (filters)
{ {
std::string filter_str = *filters; std::string filter_str = *filters;
std::string::const_iterator itr = filter_str.begin(); bool result = filter::parse_image_filters(filter_str, style.image_filters());
std::string::const_iterator end = filter_str.end(); if (!result)
bool result = boost::spirit::qi::phrase_parse(itr,end,
sty.get_tree().image_filters_grammar,
boost::spirit::qi::ascii::space,
style.image_filters());
if (!result || itr!=end)
{ {
throw config_error("failed to parse image-filters: '" + std::string(itr,end) + "'"); throw config_error("failed to parse image-filters: '" + filter_str + "'");
} }
} }

View file

@ -26,6 +26,7 @@
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/util/geometry_wkt_generator.hpp> #include <mapnik/util/geometry_wkt_generator.hpp>
#include <mapnik/util/geometry_to_wkt.hpp>
#include <mapnik/util/path_iterator.hpp> #include <mapnik/util/path_iterator.hpp>
#include <mapnik/util/container_adapter.hpp> #include <mapnik/util/container_adapter.hpp>
@ -156,6 +157,23 @@ wkt_multi_generator<OutputIterator, GeometryContainer>::wkt_multi_generator()
template struct mapnik::util::wkt_generator<std::back_insert_iterator<std::string>, mapnik::geometry_type>; template struct mapnik::util::wkt_generator<std::back_insert_iterator<std::string>, mapnik::geometry_type>;
template struct mapnik::util::wkt_multi_generator<std::back_insert_iterator<std::string>, mapnik::geometry_container >; template struct mapnik::util::wkt_multi_generator<std::back_insert_iterator<std::string>, mapnik::geometry_container >;
bool to_wkt(std::string & wkt, mapnik::geometry_type const& geom)
{
typedef std::back_insert_iterator<std::string> sink_type;
sink_type sink(wkt);
wkt_generator<sink_type, mapnik::geometry_type> generator(true);
bool result = karma::generate(sink, generator, geom);
return result;
}
bool to_wkt(std::string & wkt, mapnik::geometry_container const& geom)
{
typedef std::back_insert_iterator<std::string> sink_type;
sink_type sink(wkt);
wkt_multi_generator<sink_type, mapnik::geometry_container> generator;
bool result = karma::generate(sink, generator, geom);
return result;
}
}} }}

View file

@ -182,10 +182,14 @@ std::string xml_node::xml_text = "<xmltext>";
std::string const& xml_node::name() const std::string const& xml_node::name() const
{ {
if (!is_text_) if (!is_text_)
{
return name_; return name_;
}
else else
{
return xml_text; return xml_text;
} }
}
std::string const& xml_node::text() const std::string const& xml_node::text() const
{ {
@ -193,7 +197,8 @@ std::string const& xml_node::text() const
{ {
processed_ = true; processed_ = true;
return name_; return name_;
} else }
else
{ {
throw config_error("text() called on non-text node", *this); throw config_error("text() called on non-text node", *this);
} }
@ -336,7 +341,8 @@ std::string xml_node::get_text() const
if (is_text_) if (is_text_)
{ {
return name_; return name_;
} else }
else
{ {
return ""; return "";
} }

View file

@ -335,6 +335,16 @@ def test_map_init():
m = mapnik.Map(256, 256, '+proj=latlong') m = mapnik.Map(256, 256, '+proj=latlong')
eq_(m.srs, '+proj=latlong') eq_(m.srs, '+proj=latlong')
def test_map_style_access():
m = mapnik.Map(256, 256)
sty = mapnik.Style()
m.append_style("style",sty)
styles = list(m.styles)
eq_(len(styles),1)
eq_(styles[0][0],'style')
# returns a copy so let's just check it is the right instance
eq_(isinstance(styles[0][1],mapnik.Style),True)
def test_map_maximum_extent_modification(): def test_map_maximum_extent_modification():
m = mapnik.Map(256, 256) m = mapnik.Map(256, 256)
eq_(m.maximum_extent, None) eq_(m.maximum_extent, None)

View file

@ -12,56 +12,76 @@ def setup():
# from another directory we need to chdir() # from another directory we need to chdir()
os.chdir(execution_path('.')) os.chdir(execution_path('.'))
def test_simplest_render(): def test_simplest_render():
m = mapnik.Map(256, 256) m = mapnik.Map(256, 256)
i = mapnik.Image(m.width, m.height) im = mapnik.Image(m.width, m.height)
eq_(im.painted(),False)
mapnik.render(m, i) eq_(im.is_solid(),True)
mapnik.render(m, im)
s = i.tostring() eq_(im.painted(),False)
eq_(im.is_solid(),True)
s = im.tostring()
eq_(s, 256 * 256 * '\x00\x00\x00\x00') eq_(s, 256 * 256 * '\x00\x00\x00\x00')
def test_render_image_to_string(): def test_render_image_to_string():
i = mapnik.Image(256, 256) im = mapnik.Image(256, 256)
im.background = mapnik.Color('black')
i.background = mapnik.Color('black') eq_(im.painted(),False)
eq_(im.is_solid(),True)
s = i.tostring() s = im.tostring()
eq_(s, 256 * 256 * '\x00\x00\x00\xff') eq_(s, 256 * 256 * '\x00\x00\x00\xff')
s = im.tostring('png')
s = i.tostring('png') def test_non_solid_image():
im = mapnik.Image(256, 256)
im.background = mapnik.Color('black')
eq_(im.painted(),False)
eq_(im.is_solid(),True)
# set one pixel to a different color
im.set_pixel(0,0,mapnik.Color('white'))
eq_(im.painted(),False)
eq_(im.is_solid(),False)
def test_non_solid_image_view():
im = mapnik.Image(256, 256)
im.background = mapnik.Color('black')
view = im.view(0,0,256,256)
eq_(view.is_solid(),True)
# set one pixel to a different color
im.set_pixel(0,0,mapnik.Color('white'))
eq_(im.is_solid(),False)
# view, since it is the exact dimensions of the image
# should also be non-solid
eq_(view.is_solid(),False)
# but not a view that excludes the single diff pixel
view2 = im.view(1,1,256,256)
eq_(view2.is_solid(),True)
def test_setting_alpha(): def test_setting_alpha():
w,h = 256,256 w,h = 256,256
im1 = mapnik.Image(w,h) im1 = mapnik.Image(w,h)
# white, half transparent # white, half transparent
im1.background = mapnik.Color('rgba(255,255,255,.5)') im1.background = mapnik.Color('rgba(255,255,255,.5)')
eq_(im1.painted(),False)
eq_(im1.is_solid(),True)
# pure white # pure white
im2 = mapnik.Image(w,h) im2 = mapnik.Image(w,h)
im2.background = mapnik.Color('rgba(255,255,255,1)') im2.background = mapnik.Color('rgba(255,255,255,1)')
im2.set_alpha(.5) im2.set_alpha(.5)
eq_(im2.painted(),False)
eq_(im2.is_solid(),True)
eq_(len(im1.tostring()), len(im2.tostring())) eq_(len(im1.tostring()), len(im2.tostring()))
def test_render_image_to_file(): def test_render_image_to_file():
i = mapnik.Image(256, 256) im = mapnik.Image(256, 256)
im.background = mapnik.Color('black')
i.background = mapnik.Color('black')
if mapnik.has_jpeg(): if mapnik.has_jpeg():
i.save('test.jpg') im.save('test.jpg')
i.save('test.png', 'png') im.save('test.png', 'png')
if os.path.exists('test.jpg'): if os.path.exists('test.jpg'):
os.remove('test.jpg') os.remove('test.jpg')
else: else:
return False return False
if os.path.exists('test.png'): if os.path.exists('test.png'):
os.remove('test.png') os.remove('test.png')
else: else:
@ -71,34 +91,32 @@ def get_paired_images(w,h,mapfile):
tmp_map = 'tmp_map.xml' tmp_map = 'tmp_map.xml'
m = mapnik.Map(w,h) m = mapnik.Map(w,h)
mapnik.load_map(m,mapfile) mapnik.load_map(m,mapfile)
i = mapnik.Image(w,h) im = mapnik.Image(w,h)
m.zoom_all() m.zoom_all()
mapnik.render(m,i) mapnik.render(m,im)
mapnik.save_map(m,tmp_map) mapnik.save_map(m,tmp_map)
m2 = mapnik.Map(w,h) m2 = mapnik.Map(w,h)
mapnik.load_map(m2,tmp_map) mapnik.load_map(m2,tmp_map)
i2 = mapnik.Image(w,h) im2 = mapnik.Image(w,h)
m2.zoom_all() m2.zoom_all()
mapnik.render(m2,i2) mapnik.render(m2,im2)
os.remove(tmp_map) os.remove(tmp_map)
return i,i2 return im,im2
def test_render_from_serialization(): def test_render_from_serialization():
try: try:
i,i2 = get_paired_images(100,100,'../data/good_maps/building_symbolizer.xml') im,im2 = get_paired_images(100,100,'../data/good_maps/building_symbolizer.xml')
eq_(i.tostring(),i2.tostring()) eq_(im.tostring(),im2.tostring())
i,i2 = get_paired_images(100,100,'../data/good_maps/polygon_symbolizer.xml') im,im2 = get_paired_images(100,100,'../data/good_maps/polygon_symbolizer.xml')
eq_(i.tostring(),i2.tostring()) eq_(im.tostring(),im2.tostring())
except RuntimeError, e: except RuntimeError, e:
# only test datasources that we have installed # only test datasources that we have installed
if not 'Could not create datasource' in str(e): if not 'Could not create datasource' in str(e):
raise RuntimeError(e) raise RuntimeError(e)
def test_render_points(): def test_render_points():
if not mapnik.has_cairo(): return if not mapnik.has_cairo(): return
# create and populate point datasource (WGS84 lat-lon coordinates) # create and populate point datasource (WGS84 lat-lon coordinates)
ds = mapnik.MemoryDatasource() ds = mapnik.MemoryDatasource()
context = mapnik.Context() context = mapnik.Context()
@ -163,6 +181,14 @@ def test_render_with_scale_factor():
for size in sizes: for size in sizes:
im = mapnik.Image(256, 256) im = mapnik.Image(256, 256)
mapnik.render(m,im,size) mapnik.render(m,im,size)
expected_file = './images/support/marker-text-line-scale-factor-%s.png' % size
actual_file = '/tmp/' + os.path.basename(expected_file)
im.save(actual_file,'png8')
#im.save(expected_file,'png8')
# we save and re-open here so both png8 images are ready as full color png
actual = mapnik.Image.open(expected_file)
expected = mapnik.Image.open(expected_file)
eq_(actual.tostring(),expected.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual_file,expected_file))
im.save('./images/support/marker-text-line-scale-factor-%s.png' % size,'png8') im.save('./images/support/marker-text-line-scale-factor-%s.png' % size,'png8')
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -73,7 +73,7 @@ def main():
argv.append('-v') argv.append('-v')
dirname = os.path.dirname(sys.argv[0]) dirname = os.path.dirname(sys.argv[0])
argv.extend(['-w', dirname+'/python_tests']) argv.extend(['-w', os.path.join(dirname,'python_tests')])
if not nose.run(argv=argv, plugins=[TodoPlugin(), Doctest()]): if not nose.run(argv=argv, plugins=[TodoPlugin(), Doctest()]):
sys.exit(1) sys.exit(1)