diff --git a/CHANGELOG.md b/CHANGELOG.md index efc7ccac7..e650903f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ For a complete change history, see the git log. ## Future +- Support for encoding `literal` postgres types as strings 69fb17cd3/#1466 + - Fixed zoom_all behavior when Map maximum-extent is provided. Previously maximum-extent was used outright but now the combined layer extents will be again respected: they will be clipped to the maximum-extent if possible and only when back-projecting fails for all layers will the maximum-extent be used as a fallback (#1473) diff --git a/SConstruct b/SConstruct index fee066313..2ca680ac6 100644 --- a/SConstruct +++ b/SConstruct @@ -354,7 +354,7 @@ opts.AddVariables( # Other variables BoolVariable('SHAPE_MEMORY_MAPPED_FILE', 'Utilize memory-mapped files in Shapefile Plugin (higher memory usage, better performance)', 'True'), - ('SYSTEM_FONTS','Provide location for python bindings to register fonts (if given aborts installation of bundled DejaVu fonts)',''), + ('SYSTEM_FONTS','Provide location for python bindings to register fonts (if provided then the bundled DejaVu fonts are not installed)',''), ('LIB_DIR_NAME','Name to use for the subfolder beside libmapnik where fonts and plugins are installed','mapnik'), PathVariable('PYTHON','Full path to Python executable used to build bindings', sys.executable), BoolVariable('FRAMEWORK_PYTHON', 'Link against Framework Python on Mac OS X', 'True'), diff --git a/bindings/python/mapnik/__init__.py b/bindings/python/mapnik/__init__.py index f9e2542cb..f35bfe2ee 100644 --- a/bindings/python/mapnik/__init__.py +++ b/bindings/python/mapnik/__init__.py @@ -693,417 +693,300 @@ class PythonDatasource(object): return itertools.imap(make_it, features, itertools.count(1)) class _TextSymbolizer(TextSymbolizer,_injector): + @property + def name(self): + if isinstance(self.properties.format_tree, FormattingText): + return self.properties.format_tree.text + else: + return None # This text symbolizer is using complex formatting features. + # There is no single expression which could be returned as name + + @name.setter + def name(self, name): + self.properties.format_tree = FormattingText(name) + @property def text_size(self): - warnings.warn("'text_size' is deprecated, use format.text_size", - DeprecationWarning, 2) return self.format.text_size @text_size.setter def text_size(self, text_size): - warnings.warn("'text_size' is deprecated, use format.text_size", - DeprecationWarning, 2) self.format.text_size = text_size @property def face_name(self): - warnings.warn("'face_name' is deprecated, use format.face_name", - DeprecationWarning, 2) return self.format.face_name @face_name.setter def face_name(self, face_name): - warnings.warn("'face_name' is deprecated, use format.face_name", - DeprecationWarning, 2) self.format.face_name = face_name - @property def fontset(self): - warnings.warn("'fontset' is deprecated, use format.fontset", - DeprecationWarning, 2) return self.format.fontset @fontset.setter def fontset(self, fontset): - warnings.warn("'fontset' is deprecated, use format.fontset", - DeprecationWarning, 2) self.format.fontset = fontset - @property def character_spacing(self): - warnings.warn("'character_spacing' is deprecated, use format.character_spacing", - DeprecationWarning, 2) return self.format.character_spacing @character_spacing.setter def character_spacing(self, character_spacing): - warnings.warn("'character_spacing' is deprecated, use format.character_spacing", - DeprecationWarning, 2) self.format.character_spacing = character_spacing - @property def line_spacing(self): - warnings.warn("'line_spacing' is deprecated, use format.line_spacing", - DeprecationWarning, 2) return self.format.line_spacing @line_spacing.setter def line_spacing(self, line_spacing): - warnings.warn("'line_spacing' is deprecated, use format.line_spacing", - DeprecationWarning, 2) self.format.line_spacing = line_spacing - @property def text_opacity(self): - warnings.warn("'text_opacity' is deprecated, use format.text_opacity", - DeprecationWarning, 2) return self.format.text_opacity @text_opacity.setter def text_opacity(self, text_opacity): - warnings.warn("'text_opacity' is deprecated, use format.text_opacity", - DeprecationWarning, 2) self.format.text_opacity = text_opacity - @property def wrap_char(self): - warnings.warn("'wrap_char' is deprecated, use format.wrap_char", - DeprecationWarning, 2) return self.format.wrap_char @wrap_char.setter def wrap_char(self, wrap_char): - warnings.warn("'wrap_char' is deprecated, use format.wrap_char", - DeprecationWarning, 2) self.format.wrap_char = wrap_char @property def wrap_character(self): - warnings.warn("'wrap_character' is deprecated, use format.wrap_character", - DeprecationWarning, 2) return self.format.wrap_character @wrap_char.setter def wrap_character(self, wrap_character): - warnings.warn("'wrap_char' is deprecated, use format.wrap_character", - DeprecationWarning, 2) self.format.wrap_character = wrap_character @property def wrap_before(self): - warnings.warn("'wrap_before' is deprecated, use format.wrap_before", - DeprecationWarning, 2) return self.properties.wrap_before @wrap_before.setter def wrap_before(self, wrap_before): - warnings.warn("'wrap_before' is deprecated, use format.wrap_before", - DeprecationWarning, 2) self.properties.wrap_before = wrap_before - - @property def text_transform(self): - warnings.warn("'text_transform' is deprecated, use format.text_transform", - DeprecationWarning, 2) return self.format.text_transform @text_transform.setter def text_transform(self, text_transform): - warnings.warn("'text_transform' is deprecated, use format.text_transform", - DeprecationWarning, 2) self.format.text_transform = text_transform - @property def fill(self): - warnings.warn("'fill' is deprecated, use format.fill", - DeprecationWarning, 2) return self.format.fill @fill.setter def fill(self, fill): - warnings.warn("'fill' is deprecated, use format.fill", - DeprecationWarning, 2) self.format.fill = fill - @property def halo_fill(self): - warnings.warn("'halo_fill' is deprecated, use format.halo_fill", - DeprecationWarning, 2) return self.format.halo_fill @halo_fill.setter def halo_fill(self, halo_fill): - warnings.warn("'halo_fill' is deprecated, use format.halo_fill", - DeprecationWarning, 2) self.format.halo_fill = halo_fill @property def halo_radius(self): - warnings.warn("'halo_radius' is deprecated, use format.halo_radius", - DeprecationWarning, 2) return self.format.halo_radius @halo_radius.setter def halo_radius(self, halo_radius): - warnings.warn("'halo_radius' is deprecated, use format.halo_radius", - DeprecationWarning, 2) self.format.halo_radius = halo_radius @property def label_placement(self): - warnings.warn("'label_placement' is deprecated, use properties.label_placement", - DeprecationWarning, 2) return self.properties.label_placement @label_placement.setter def label_placement(self, label_placement): - warnings.warn("'label_placement' is deprecated, use properties.label_placement", - DeprecationWarning, 2) self.properties.label_placement = label_placement @property def horizontal_alignment(self): - warnings.warn("'horizontal_alignment' is deprecated, use properties.horizontal_alignment", - DeprecationWarning, 2) return self.properties.horizontal_alignment @horizontal_alignment.setter def horizontal_alignment(self, horizontal_alignment): - warnings.warn("'horizontal_alignment' is deprecated, use properties.horizontal_alignment", - DeprecationWarning, 2) self.properties.horizontal_alignment = horizontal_alignment @property def justify_alignment(self): - warnings.warn("'justify_alignment' is deprecated, use properties.justify_alignment", - DeprecationWarning, 2) return self.properties.justify_alignment @justify_alignment.setter def justify_alignment(self, justify_alignment): - warnings.warn("'justify_alignment' is deprecated, use properties.justify_alignment", - DeprecationWarning, 2) self.properties.justify_alignment = justify_alignment @property def vertical_alignment(self): - warnings.warn("'vertical_alignment' is deprecated, use properties.vertical_alignment", - DeprecationWarning, 2) return self.properties.vertical_alignment @vertical_alignment.setter def vertical_alignment(self, vertical_alignment): - warnings.warn("'vertical_alignment' is deprecated, use properties.vertical_alignment", - DeprecationWarning, 2) self.properties.vertical_alignment = vertical_alignment @property def orientation(self): - warnings.warn("'orientation' is deprecated, use properties.orientation", - DeprecationWarning, 2) return self.properties.orientation @orientation.setter def orientation(self, orientation): - warnings.warn("'orientation' is deprecated, use properties.orientation", - DeprecationWarning, 2) self.properties.orientation = orientation @property def displacement(self): - warnings.warn("'displacement' is deprecated, use properties.displacement", - DeprecationWarning, 2) return self.properties.displacement @displacement.setter def displacement(self, displacement): - warnings.warn("'displacement' is deprecated, use properties.displacement", - DeprecationWarning, 2) self.properties.displacement = displacement @property def label_spacing(self): - warnings.warn("'label_spacing' is deprecated, use properties.label_spacing", - DeprecationWarning, 2) return self.properties.label_spacing @label_spacing.setter def label_spacing(self, label_spacing): - warnings.warn("'label_spacing' is deprecated, use properties.label_spacing", - DeprecationWarning, 2) self.properties.label_spacing = label_spacing @property def label_position_tolerance(self): - warnings.warn("'label_position_tolerance' is deprecated, use properties.label_position_tolerance", - DeprecationWarning, 2) return self.properties.label_position_tolerance @label_position_tolerance.setter def label_position_tolerance(self, label_position_tolerance): - warnings.warn("'label_position_tolerance' is deprecated, use properties.label_position_tolerance", - DeprecationWarning, 2) self.properties.label_position_tolerance = label_position_tolerance @property def avoid_edges(self): - warnings.warn("'avoid_edges' is deprecated, use properties.avoid_edges", - DeprecationWarning, 2) return self.properties.avoid_edges @avoid_edges.setter def avoid_edges(self, avoid_edges): - warnings.warn("'avoid_edges' is deprecated, use properties.avoid_edges", - DeprecationWarning, 2) self.properties.avoid_edges = avoid_edges @property def minimum_distance(self): - warnings.warn("'minimum_distance' is deprecated, use properties.minimum_distance", - DeprecationWarning, 2) return self.properties.minimum_distance @minimum_distance.setter def minimum_distance(self, minimum_distance): - warnings.warn("'minimum_distance' is deprecated, use properties.minimum_distance", - DeprecationWarning, 2) self.properties.minimum_distance = minimum_distance @property def minimum_padding(self): - warnings.warn("'minimum_padding' is deprecated, use properties.minimum_padding", - DeprecationWarning, 2) return self.properties.minimum_padding @minimum_padding.setter def minimum_padding(self, minimum_padding): - warnings.warn("'minimum_padding' is deprecated, use properties.minimum_padding", - DeprecationWarning, 2) self.properties.minimum_padding = minimum_padding @property def minimum_path_length(self): - warnings.warn("'minimum_path_length' is deprecated, use properties.minimum_path_length", - DeprecationWarning, 2) return self.properties.minimum_path_length @minimum_path_length.setter def minimum_path_length(self, minimum_path_length): - warnings.warn("'minimum_path_length' is deprecated, use properties.minimum_path_length", - DeprecationWarning, 2) self.properties.minimum_path_length = minimum_path_length @property def maximum_angle_char_delta(self): - warnings.warn("'maximum_angle_char_delta' is deprecated, use properties.maximum_angle_char_delta", - DeprecationWarning, 2) return self.properties.maximum_angle_char_delta @maximum_angle_char_delta.setter def maximum_angle_char_delta(self, maximum_angle_char_delta): - warnings.warn("'maximum_angle_char_delta' is deprecated, use properties.maximum_angle_char_delta", - DeprecationWarning, 2) self.properties.maximum_angle_char_delta = maximum_angle_char_delta @property def force_odd_labels(self): - warnings.warn("'force_odd_labels' is deprecated, use properties.force_odd_labels", - DeprecationWarning, 2) return self.properties.force_odd_labels @force_odd_labels.setter def force_odd_labels(self, force_odd_labels): - warnings.warn("'force_odd_labels' is deprecated, use properties.force_odd_labels", - DeprecationWarning, 2) self.properties.force_odd_labels = force_odd_labels @property def allow_overlap(self): - warnings.warn("'allow_overlap' is deprecated, use properties.allow_overlap", - DeprecationWarning, 2) return self.properties.allow_overlap @allow_overlap.setter def allow_overlap(self, allow_overlap): - warnings.warn("'allow_overlap' is deprecated, use properties.allow_overlap", - DeprecationWarning, 2) self.properties.allow_overlap = allow_overlap @property def text_ratio(self): - warnings.warn("'text_ratio' is deprecated, use properties.text_ratio", - DeprecationWarning, 2) return self.properties.text_ratio @text_ratio.setter def text_ratio(self, text_ratio): - warnings.warn("'text_ratio' is deprecated, use properties.text_ratio", - DeprecationWarning, 2) self.properties.text_ratio = text_ratio @property def wrap_width(self): - warnings.warn("'wrap_width' is deprecated, use properties.wrap_width", - DeprecationWarning, 2) return self.properties.wrap_width @wrap_width.setter def wrap_width(self, wrap_width): - warnings.warn("'wrap_width' is deprecated, use properties.wrap_width", - DeprecationWarning, 2) self.properties.wrap_width = wrap_width diff --git a/bindings/python/mapnik_fontset.cpp b/bindings/python/mapnik_fontset.cpp index f467d816f..fbc94a292 100644 --- a/bindings/python/mapnik_fontset.cpp +++ b/bindings/python/mapnik_fontset.cpp @@ -33,8 +33,13 @@ using mapnik::font_set; void export_fontset () { using namespace boost::python; - class_("FontSet", init<>("default fontset constructor") + class_("FontSet", init("default fontset constructor") ) + .add_property("name", + make_function(&font_set::get_name,return_value_policy()), + &font_set::set_name, + "Get/Set the name of the FontSet.\n" + ) .def("add_face_name",&font_set::add_face_name, (arg("name")), "Add a face-name to the fontset.\n" diff --git a/bindings/python/mapnik_python.cpp b/bindings/python/mapnik_python.cpp index ebe2579b8..dffa358cd 100644 --- a/bindings/python/mapnik_python.cpp +++ b/bindings/python/mapnik_python.cpp @@ -617,6 +617,7 @@ BOOST_PYTHON_MODULE(_mapnik) def("has_pycairo", &has_pycairo, "Get pycairo module status"); python_optional(); + python_optional(); python_optional(); python_optional >(); python_optional(); diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp index e4a7c9a3c..e574aa4fa 100644 --- a/bindings/python/mapnik_text_placement.cpp +++ b/bindings/python/mapnik_text_placement.cpp @@ -404,9 +404,9 @@ void export_text_placement() boost::shared_ptr > ("CharProperties") .def_readwrite_convert("text_transform", &char_properties::text_transform) + .def_readwrite_convert("fontset", &char_properties::fontset) .def(init()) //Copy constructor .def_readwrite("face_name", &char_properties::face_name) - .def_readwrite("fontset", &char_properties::fontset) .def_readwrite("text_size", &char_properties::text_size) .def_readwrite("character_spacing", &char_properties::character_spacing) .def_readwrite("line_spacing", &char_properties::line_spacing) diff --git a/demo/simple-renderer/render.py b/demo/simple-renderer/render.py new file mode 100755 index 000000000..6ab075d25 --- /dev/null +++ b/demo/simple-renderer/render.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +import sys +import mapnik + +def render(input_file, output_file, width=800, height=800, bbox=None): + m = mapnik.Map(width, height) + mapnik.load_map(m, input_file, False) + if bbox is not None: + m.zoom_to_box(bbox) + else: + m.zoom_all() + mapnik.render_to_file(m, output_file) + +if len(sys.argv) == 2: + render(sys.argv[1], "output.png") +elif len(sys.argv) == 3: + render(sys.argv[1], sys.argv[2]) +elif len(sys.argv) == 5: + render(sys.argv[1], sys.argv[2], int(sys.argv[3]), int(sys.argv[4])) +else: + print "usage: %s style_file [output_file] [width height]" % sys.argv[0] + sys.exit(1) diff --git a/fonts/build.py b/fonts/build.py index 7105188dd..bf47d6bb6 100644 --- a/fonts/build.py +++ b/fonts/build.py @@ -22,15 +22,12 @@ import glob Import('env') -# grab all the deja vu fonts -includes = glob.glob('*/*/*.ttf') - -# grab single unifont ttf (available at http://unifoundry.com/unifont.html) -includes.extend(glob.glob('unifont*.ttf')) - -target_path = env['MAPNIK_FONTS_DEST'] - -if 'uninstall' not in COMMAND_LINE_TARGETS and not env['SYSTEM_FONTS']: - env.Alias(target='install', source=env.Install(target_path, includes)) - -env['create_uninstall_target'](env, target_path) \ No newline at end of file +if not env['SYSTEM_FONTS']: + # grab all the deja vu fonts + includes = glob.glob('*/*/*.ttf') + # grab single unifont ttf (available at http://unifoundry.com/unifont.html) + includes.extend(glob.glob('unifont*.ttf')) + target_path = env['MAPNIK_FONTS_DEST'] + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Alias(target='install', source=env.Install(target_path, includes)) + env['create_uninstall_target'](env, target_path) \ No newline at end of file diff --git a/include/mapnik/font_set.hpp b/include/mapnik/font_set.hpp index 4d0fd79b4..426d60b06 100644 --- a/include/mapnik/font_set.hpp +++ b/include/mapnik/font_set.hpp @@ -35,7 +35,6 @@ namespace mapnik class MAPNIK_DECL font_set { public: - font_set(); font_set(std::string const& name); font_set(font_set const& rhs); font_set& operator=(font_set const& rhs); diff --git a/include/mapnik/text_properties.hpp b/include/mapnik/text_properties.hpp index 4ef90e659..9e073a8c5 100644 --- a/include/mapnik/text_properties.hpp +++ b/include/mapnik/text_properties.hpp @@ -35,6 +35,7 @@ #include // boost +#include #include #include @@ -61,7 +62,7 @@ struct char_properties /** Write object to XML ptree. */ void to_xml(boost::property_tree::ptree &node, bool explicit_defaults, char_properties const& dfl=char_properties()) const; std::string face_name; - font_set fontset; + boost::optional fontset; double text_size; double character_spacing; double line_spacing; //Largest total height (fontsize+line_spacing) per line is chosen diff --git a/include/mapnik/text_symbolizer.hpp b/include/mapnik/text_symbolizer.hpp index b99f88cff..ad56b8ff5 100644 --- a/include/mapnik/text_symbolizer.hpp +++ b/include/mapnik/text_symbolizer.hpp @@ -92,7 +92,7 @@ struct MAPNIK_DECL text_symbolizer : public symbolizer_base void set_text_size(double size); std::string const& get_face_name() const func_deprecated; void set_face_name(std::string face_name); - font_set const& get_fontset() const func_deprecated; + boost::optional const& get_fontset() const func_deprecated; void set_fontset(font_set const& fset); color const& get_fill() const func_deprecated; void set_fill(color const& fill); diff --git a/src/agg/process_raster_symbolizer.cpp b/src/agg/process_raster_symbolizer.cpp index ec4fdc97a..dbdcc88b7 100644 --- a/src/agg/process_raster_symbolizer.cpp +++ b/src/agg/process_raster_symbolizer.cpp @@ -68,10 +68,10 @@ void agg_renderer::process(raster_symbolizer const& sym, raster target(target_ext, target_data); scaling_method_e scaling_method = sym.get_scaling_method(); double filter_radius = sym.calculate_filter_factor(); - double offset_x = ext.minx() - start_x; - double offset_y = ext.miny() - start_y; if (!prj_trans.equal()) { + double offset_x = ext.minx() - start_x; + double offset_y = ext.miny() - start_y; reproject_and_scale_raster(target, *source, prj_trans, offset_x, offset_y, sym.get_mesh_size(), @@ -80,16 +80,18 @@ void agg_renderer::process(raster_symbolizer const& sym, } else { - if (scaling_method == SCALING_BILINEAR8){ - scale_image_bilinear8(target.data_,source->data_, offset_x, offset_y); - } else { + if (scaling_method == SCALING_BILINEAR8) + { + scale_image_bilinear8(target.data_,source->data_, 0.0, 0.0); + } else + { double scaling_ratio = ext.width() / source->data_.width(); scale_image_agg(target.data_, source->data_, scaling_method, scaling_ratio, - offset_x, - offset_y, + 0.0, + 0.0, filter_radius); } } diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 05692819e..c4dade96c 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -1422,10 +1422,10 @@ void cairo_renderer_base::process(raster_symbolizer const& sym, raster target(target_ext, target_data); scaling_method_e scaling_method = sym.get_scaling_method(); double filter_radius = sym.calculate_filter_factor(); - double offset_x = ext.minx() - start_x; - double offset_y = ext.miny() - start_y; if (!prj_trans.equal()) { + double offset_x = ext.minx() - start_x; + double offset_y = ext.miny() - start_y; reproject_and_scale_raster(target, *source, prj_trans, offset_x, offset_y, sym.get_mesh_size(), @@ -1434,16 +1434,18 @@ void cairo_renderer_base::process(raster_symbolizer const& sym, } else { - if (scaling_method == SCALING_BILINEAR8){ - scale_image_bilinear8(target.data_,source->data_, offset_x, offset_y); - } else { + if (scaling_method == SCALING_BILINEAR8) + { + scale_image_bilinear8(target.data_,source->data_, 0.0, 0.0); + } else + { double scaling_ratio = ext.width() / source->data_.width(); scale_image_agg(target.data_, source->data_, scaling_method, scaling_ratio, - offset_x, - offset_y, + 0.0, + 0.0, filter_radius); } } diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index d5e304710..3e895f095 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -272,11 +272,11 @@ face_set_ptr face_manager::get_face_set(const font_set &fset) } template -face_set_ptr face_manager::get_face_set(const std::string &name, const font_set &fset) +face_set_ptr face_manager::get_face_set(const std::string &name, const boost::optional &fset) { - if (fset.size() > 0) + if (fset && fset->size() > 0) { - return get_face_set(fset); + return get_face_set(*fset); } else { diff --git a/src/font_set.cpp b/src/font_set.cpp index 9fce7b1ef..06daf5b42 100644 --- a/src/font_set.cpp +++ b/src/font_set.cpp @@ -29,8 +29,6 @@ namespace mapnik { -font_set::font_set() - : name_("") {} font_set::font_set(std::string const& name) : name_(name) {} diff --git a/src/image_scaling.cpp b/src/image_scaling.cpp index 32b2d6e5c..ab1c00b8b 100644 --- a/src/image_scaling.cpp +++ b/src/image_scaling.cpp @@ -264,8 +264,7 @@ void scale_image_agg(Image & target, double ratio) { typedef agg::pixfmt_rgba32 pixfmt; - typedef agg::pixfmt_rgba32_pre pixfmt_pre; - typedef agg::renderer_base renderer_base; + typedef agg::renderer_base renderer_base; // define some stuff we'll use soon agg::rasterizer_scanline_aa<> ras; @@ -279,9 +278,9 @@ void scale_image_agg(Image & target, typedef agg::image_accessor_clone img_src_type; img_src_type img_src(pixf_src); - // initialise destination AGG buffer (with transparency) + // initialize destination AGG buffer (with transparency) agg::rendering_buffer rbuf_dst((unsigned char*)target.getBytes(), target.width(), target.height(), target.width() * 4); - pixfmt_pre pixf_dst(rbuf_dst); + pixfmt pixf_dst(rbuf_dst); renderer_base rb_dst(pixf_dst); rb_dst.clear(agg::rgba(0, 0, 0, 0)); @@ -294,8 +293,8 @@ void scale_image_agg(Image & target, interpolator_type interpolator(img_mtx); // draw an anticlockwise polygon to render our image into - double scaled_width = source.width() * image_ratio; - double scaled_height = source.height() * image_ratio; + double scaled_width = target.width(); + double scaled_height = target.height(); ras.reset(); ras.move_to_d(x_off_f, y_off_f); ras.line_to_d(x_off_f + scaled_width, y_off_f); diff --git a/src/map.cpp b/src/map.cpp index 7e4a3f5f8..5c27fd5f0 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -159,6 +159,10 @@ boost::optional Map::find_style(std::string const& na 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_.insert(make_pair(name, fontset)).second; } diff --git a/src/processed_text.cpp b/src/processed_text.cpp index caaa31679..ab27f375f 100644 --- a/src/processed_text.cpp +++ b/src/processed_text.cpp @@ -65,22 +65,22 @@ string_info &processed_text::get_string_info() face_set_ptr faces = font_manager_.get_face_set(p.face_name, p.fontset); if (faces->size() == 0) { - if (!p.fontset.get_name().empty()) + if (p.fontset && !p.fontset->get_name().empty()) { - if (p.fontset.size()) + if (p.fontset->size()) { if (!p.face_name.empty()) { - throw config_error("Unable to find specified font face '" + p.face_name + "' in font set: '" + p.fontset.get_name() + "'"); + throw config_error("Unable to find specified font face '" + p.face_name + "' in font set: '" + p.fontset->get_name() + "'"); } else { - throw config_error("No valid font face could be loaded for font set: '" + p.fontset.get_name() + "'"); + throw config_error("No valid font face could be loaded for font set: '" + p.fontset->get_name() + "'"); } } else { - throw config_error("Font set '" + p.fontset.get_name() + "' does not contain any Font face-name entries"); + throw config_error("Font set '" + p.fontset->get_name() + "' does not contain any Font face-name entries"); } } else if (!p.face_name.empty()) diff --git a/src/text_properties.cpp b/src/text_properties.cpp index af057ed9b..be89847f7 100644 --- a/src/text_properties.cpp +++ b/src/text_properties.cpp @@ -367,11 +367,11 @@ void char_properties::from_xml(xml_node const& sym, fontset_map const& fontsets) throw config_error("Unable to find any fontset named '" + *fontset_name_ + "'", sym); } } - if (!face_name.empty() && !fontset.get_name().empty()) + if (!face_name.empty() && fontset) { throw config_error("Can't have both face-name and fontset-name", sym); } - if (face_name.empty() && fontset.get_name().empty()) + if (face_name.empty() && !fontset) { throw config_error("Must have face-name or fontset-name", sym); } @@ -379,11 +379,9 @@ void char_properties::from_xml(xml_node const& sym, fontset_map const& fontsets) void char_properties::to_xml(boost::property_tree::ptree &node, bool explicit_defaults, char_properties const &dfl) const { - std::string const& fontset_name = fontset.get_name(); - std::string const& dfl_fontset_name = dfl.fontset.get_name(); - if (fontset_name != dfl_fontset_name || explicit_defaults) + if (fontset) { - set_attr(node, "fontset-name", fontset_name); + set_attr(node, "fontset-name", fontset->get_name()); } if (face_name != dfl.face_name || explicit_defaults) diff --git a/src/text_symbolizer.cpp b/src/text_symbolizer.cpp index 4e21252c2..343ae1304 100644 --- a/src/text_symbolizer.cpp +++ b/src/text_symbolizer.cpp @@ -117,7 +117,7 @@ void text_symbolizer::set_fontset(font_set const& fontset) placement_options_->defaults.format->fontset = fontset; } -font_set const& text_symbolizer::get_fontset() const +boost::optional const& text_symbolizer::get_fontset() const { return placement_options_->defaults.format->fontset; } diff --git a/src/warp.cpp b/src/warp.cpp index ee0dc6a05..b1c135f26 100644 --- a/src/warp.cpp +++ b/src/warp.cpp @@ -78,8 +78,6 @@ void reproject_and_scale_raster(raster & target, raster const& source, typedef agg::pixfmt_rgba32 pixfmt; typedef pixfmt::color_type color_type; typedef agg::renderer_base renderer_base; - typedef agg::pixfmt_rgba32_pre pixfmt_pre; - typedef agg::renderer_base renderer_base_pre; agg::rasterizer_scanline_aa<> rasterizer; agg::scanline_u8 scanline; @@ -87,8 +85,8 @@ void reproject_and_scale_raster(raster & target, raster const& source, target.data_.width(), target.data_.height(), target.data_.width()*4); - pixfmt_pre pixf_pre(buf); - renderer_base_pre rb_pre(pixf_pre); + pixfmt pixf(buf); + renderer_base rb(pixf); rasterizer.clip_box(0, 0, target.data_.width(), target.data_.height()); agg::rendering_buffer buf_tile( (unsigned char*)source.data_.getData(), @@ -178,13 +176,13 @@ void reproject_and_scale_raster(raster & target, raster const& source, span_gen_type; span_gen_type sg(ia, interpolator); - agg::render_scanlines_aa(rasterizer, scanline, rb_pre, + agg::render_scanlines_aa(rasterizer, scanline, rb, sa, sg); } else { typedef mapnik::span_image_resample_rgba_affine span_gen_type; span_gen_type sg(ia, interpolator, filter); - agg::render_scanlines_aa(rasterizer, scanline, rb_pre, + agg::render_scanlines_aa(rasterizer, scanline, rb, sa, sg); } } diff --git a/tests/data/good_maps/raster-nodata-edge.xml b/tests/data/good_maps/raster-nodata-edge.xml new file mode 100644 index 000000000..ce2a93425 --- /dev/null +++ b/tests/data/good_maps/raster-nodata-edge.xml @@ -0,0 +1,20 @@ + + + + + + + style + + + ../raster/nodata-edge.tif + gdal + + + + \ No newline at end of file diff --git a/tests/data/raster/nodata-edge.tif b/tests/data/raster/nodata-edge.tif new file mode 100644 index 000000000..d3bd7e469 Binary files /dev/null and b/tests/data/raster/nodata-edge.tif differ diff --git a/tests/python_tests/fontset_test.py b/tests/python_tests/fontset_test.py new file mode 100644 index 000000000..4db8ca73c --- /dev/null +++ b/tests/python_tests/fontset_test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +from nose.tools import * +from utilities import execution_path + +import os, mapnik + +def setup(): + # All of the paths used are relative, if we run the tests + # from another directory we need to chdir() + os.chdir(execution_path('.')) + +def test_loading_fontset_from_map(): + m = mapnik.Map(256,256) + mapnik.load_map(m,'../data/good_maps/fontset.xml',True) + fs = m.find_fontset('book-fonts') + eq_(len(fs.names),2) + eq_(list(fs.names),['DejaVu Sans Book','DejaVu Sans Oblique']) + +def test_loading_fontset_from_python(): + m = mapnik.Map(256,256) + fset = mapnik.FontSet('foo') + fset.add_face_name('Comic Sans') + fset.add_face_name('Papyrus') + eq_(fset.name,'foo') + fset.name = 'my-set' + eq_(fset.name,'my-set') + m.append_fontset('my-set', fset) + sty = mapnik.Style() + rule = mapnik.Rule() + tsym = mapnik.TextSymbolizer() + eq_(tsym.fontset,None) + tsym.fontset = fset + rule.symbols.append(tsym) + sty.rules.append(rule) + m.append_style('Style',sty) + serialized_map = mapnik.save_map_to_string(m) + eq_('fontset-name="my-set"' in serialized_map,True) + +if __name__ == "__main__": + setup() + [eval(run)() for run in dir() if 'test_' in run] diff --git a/tests/python_tests/images/support/mapnik-merc2merc-reprojection-render1.png b/tests/python_tests/images/support/mapnik-merc2merc-reprojection-render1.png index d6ce5776e..59726ad0d 100644 Binary files a/tests/python_tests/images/support/mapnik-merc2merc-reprojection-render1.png and b/tests/python_tests/images/support/mapnik-merc2merc-reprojection-render1.png differ diff --git a/tests/python_tests/images/support/raster-nodata-edge.png b/tests/python_tests/images/support/raster-nodata-edge.png new file mode 100644 index 000000000..d3430199f Binary files /dev/null and b/tests/python_tests/images/support/raster-nodata-edge.png differ diff --git a/tests/python_tests/map_query_test.py b/tests/python_tests/map_query_test.py index 4d37ff358..7e616d3aa 100644 --- a/tests/python_tests/map_query_test.py +++ b/tests/python_tests/map_query_test.py @@ -73,8 +73,8 @@ if 'shape' in mapnik.DatasourceCache.plugin_names(): # caution - will go square due to evil aspect_fix_mode backhandedness m.zoom_all() #mapnik.render_to_file(m,'works2.png') - # valid that aspec_fix_mode modified the bbox - eq_(m.envelope(),mapnik.Box2d(-179.999999975,-179.999999975,179.999999975,179.999999975)) + # validate that aspect_fix_mode modified the bbox reasonably + eq_(str(m.envelope()),str(mapnik.Box2d(-179.999999975,-167.951396161,179.999999975,192.048603789))) fs = m.query_point(0,-98.9264, 38.1432) # somewhere in kansas feat = fs.next() eq_(feat.attributes['NAME'],u'United States') @@ -96,11 +96,11 @@ if 'shape' in mapnik.DatasourceCache.plugin_names(): m.maximum_extent = wgs84_bounds # caution - will go square due to evil aspect_fix_mode backhandedness m.zoom_all() - # valid that aspec_fix_mode modified the bbox - eq_(m.envelope(),mapnik.Box2d(-179.999999975,-179.999999975,179.999999975,179.999999975)) - fs = m.query_map_point(0,55,100) # somewhere in middle of us + # validate that aspect_fix_mode modified the bbox reasonably + eq_(str(m.envelope()),str(mapnik.Box2d(-179.999999975,-167.951396161,179.999999975,192.048603789))) + fs = m.query_map_point(0,55,100) # somewhere in Canada feat = fs.next() - eq_(feat.attributes['NAME'],u'United States') + eq_(feat.attributes['NAME'],u'Canada') if __name__ == "__main__": setup() diff --git a/tests/python_tests/object_test.py b/tests/python_tests/object_test.py index 7884322de..372ecde76 100644 --- a/tests/python_tests/object_test.py +++ b/tests/python_tests/object_test.py @@ -155,7 +155,7 @@ def test_shield_symbolizer_init(): # 11c34b1: default transform list is empty, not identity matrix eq_(s.transform, '') - eq_(len(s.fontset.names), 0) + eq_(s.fontset, None) # ShieldSymbolizer missing image file # images paths are now PathExpressions are evaluated at runtime diff --git a/tests/python_tests/raster_alpha_test.py b/tests/python_tests/raster_alpha_test.py index af1822e5e..4346b0d2e 100644 --- a/tests/python_tests/raster_alpha_test.py +++ b/tests/python_tests/raster_alpha_test.py @@ -36,6 +36,20 @@ if 'gdal' in mapnik.DatasourceCache.plugin_names(): expected_im = mapnik.Image.open(expected) eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected(%s)' % (actual,'tests/python_tests/'+ expected)) + # there should be no gray edges on raster + # https://github.com/mapnik/mapnik/issues/1471 + def test_edge_scaling_with_nodata(): + m = mapnik.Map(600,400) + mapnik.load_map(m,'../data/good_maps/raster-nodata-edge.xml') + m.zoom_all() + actual = '/tmp/mapnik-raster-nodata-edge.png' + expected = 'images/support/raster-nodata-edge.png' + im = mapnik.Image(m.width,m.height) + mapnik.render(m,im) + im.save(actual) + expected_im = mapnik.Image.open(expected) + eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected(%s)' % (actual,'tests/python_tests/'+ expected)) + if __name__ == "__main__": setup() diff --git a/tests/python_tests/test_fontset.py b/tests/python_tests/test_fontset.py deleted file mode 100644 index ec44a103d..000000000 --- a/tests/python_tests/test_fontset.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python - -from nose.tools import * -from utilities import execution_path - -import os, mapnik - -def setup(): - # All of the paths used are relative, if we run the tests - # from another directory we need to chdir() - os.chdir(execution_path('.')) - -def test_loading_fontset_from_map(): - m = mapnik.Map(256,256) - mapnik.load_map(m,'../data/good_maps/fontset.xml',True) - fs = m.find_fontset('book-fonts') - eq_(len(fs.names),2) - eq_(list(fs.names),['DejaVu Sans Book','DejaVu Sans Oblique']) - - -if __name__ == "__main__": - setup() - [eval(run)() for run in dir() if 'test_' in run]