datasource_ptr datasource_cache::create(const parameters& params) { boost::optional<std::string> type = params.get<std::string>("type"); if ( ! type) { throw config_error(std::string("Could not create datasource. Required ") + "parameter 'type' is missing"); } #ifdef MAPNIK_THREADSAFE mutex::scoped_lock lock(mutex_); #endif datasource_ptr ds; std::map<std::string,boost::shared_ptr<PluginInfo> >::iterator itr=plugins_.find(*type); if ( itr == plugins_.end() ) { std::string s("Could not create datasource for type: '"); s += *type + "'"; if (plugin_directories_.empty()) { s + " (no datasource plugin directories have been successfully registered)"; } else { s + " (searched for datasource plugins in '" + plugin_directories() + "')"; } throw config_error(s); } if ( ! itr->second->handle()) { throw std::runtime_error(std::string("Cannot load library: ") + lt_dlerror()); } // http://www.mr-edd.co.uk/blog/supressing_gcc_warnings #ifdef __GNUC__ __extension__ #endif create_ds* create_datasource = reinterpret_cast<create_ds*>(lt_dlsym(itr->second->handle(), "create")); if (! create_datasource) { throw std::runtime_error(std::string("Cannot load symbols: ") + lt_dlerror()); } #ifdef MAPNIK_LOG MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: Size=" << params.size(); parameters::const_iterator i = params.begin(); for (; i != params.end(); ++i) { MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: -- " << i->first << "=" << i->second; } #endif ds = datasource_ptr(create_datasource(params), datasource_deleter()); MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: Datasource=" << ds << " type=" << type; return ds; }
void user_warning_fn(png_structp /*png_ptr*/, png_const_charp warning_msg) { MAPNIK_LOG_DEBUG(png_reader) << "libpng warning: '" << warning_msg << "'"; }
bool freetype_engine::register_font_impl(std::string const& file_name, font_library & library, freetype_engine::font_file_mapping_type & font_file_mapping) { MAPNIK_LOG_DEBUG(font_engine_freetype) << "registering: " << file_name; mapnik::util::file file(file_name); if (!file) return false; FT_Face face = 0; FT_Open_Args args; FT_StreamRec streamRec; memset(&args, 0, sizeof(args)); memset(&streamRec, 0, sizeof(streamRec)); streamRec.base = 0; streamRec.pos = 0; streamRec.size = file.size(); streamRec.descriptor.pointer = file.get(); streamRec.read = ft_read_cb; streamRec.close = nullptr; args.flags = FT_OPEN_STREAM; args.stream = &streamRec; int num_faces = 0; bool success = false; // some font files have multiple fonts in a file // the count is in the 'root' face library[0] // see the FT_FaceRec in freetype.h for ( int i = 0; face == 0 || i < num_faces; ++i ) { // if face is null then this is the first face FT_Error error = FT_Open_Face(library.get(), &args, i, &face); if (error) break; // store num_faces locally, after FT_Done_Face it can not be accessed any more if (num_faces == 0) num_faces = face->num_faces; // some fonts can lack names, skip them // http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec if (face->family_name && face->style_name) { std::string name = std::string(face->family_name) + " " + std::string(face->style_name); // skip fonts with leading . in the name if (!boost::algorithm::starts_with(name,".")) { // http://stackoverflow.com/a/24795559/2333354 auto range = font_file_mapping.equal_range(name); if (range.first == range.second) // the key was previously absent; insert a pair { font_file_mapping.emplace_hint(range.first, name, std::make_pair(i,file_name)); } else // the key was present, replace the associated value { /* some action with value range.first->second about to be overwritten here */ MAPNIK_LOG_WARN(font_engine_freetype) << "registering new " << name << " at '" << file_name << "'"; range.first->second = std::make_pair(i,file_name); // replace value } success = true; } } else { std::ostringstream s; s << "Warning: unable to load font file '" << file_name << "' "; if (!face->family_name && !face->style_name) s << "which lacks both a family name and style name"; else if (face->family_name) s << "which reports a family name of '" << std::string(face->family_name) << "' and lacks a style name"; else if (face->style_name) s << "which reports a style name of '" << std::string(face->style_name) << "' and lacks a family name"; MAPNIK_LOG_ERROR(font_engine_freetype) << "register_font: " << s.str(); } if (face) FT_Done_Face(face); } return success; }
void grid_renderer<T>::process(line_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = get<std::string>(sym, keys::file, feature); boost::optional<marker_ptr> mark = marker_cache::instance().find(filename,true); if (!mark) return; if (!(*mark)->is_bitmap()) { MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer"; return; } boost::optional<image_ptr> pat = (*mark)->get_bitmap_data(); if (!pat) return; bool clip = get<value_bool>(sym, keys::clip, feature); double offset = get<value_double>(sym, keys::offset, feature, 0.0); double simplify_tolerance = get<value_double>(sym, keys::simplify_tolerance, feature, 0.0); double smooth = get<value_double>(sym, keys::smooth, feature, false); typedef typename grid_renderer_base_type::pixfmt_type pixfmt_type; typedef typename grid_renderer_base_type::pixfmt_type::color_type color_type; typedef agg::renderer_scanline_bin_solid<grid_renderer_base_type> renderer_type; typedef boost::mpl::vector<clip_line_tag, transform_tag, offset_transform_tag, affine_transform_tag, simplify_tag, smooth_tag, stroke_tag> conv_types; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_); pixfmt_type pixf(buf); grid_renderer_base_type renb(pixf); renderer_type ren(renb); ras_ptr->reset(); int stroke_width = (*pat)->width(); agg::trans_affine tr; auto transform = get_optional<transform_type>(sym, keys::geometry_transform); if (transform) { evaluate_transform(tr, feature, *transform, common_.scale_factor_); } box2d<double> clipping_extent = common_.query_extent_; if (clip) { double padding = (double)(common_.query_extent_.width()/pixmap_.width()); double half_stroke = stroke_width/2.0; if (half_stroke > 1) padding *= half_stroke; if (std::fabs(offset) > 0) padding *= std::fabs(offset) * 1.2; padding *= common_.scale_factor_; clipping_extent.pad(padding); } // to avoid the complexity of using an agg pattern filter instead // we create a line_symbolizer in order to fake the pattern line_symbolizer line; put<value_double>(line, keys::stroke_width, value_double(stroke_width)); // TODO: really should pass the offset to the fake line too, but // this wasn't present in the previous version and makes the test // fail - in this case, probably the test should be updated. //put<value_double>(line, keys::offset, value_double(offset)); put<value_double>(line, keys::simplify_tolerance, value_double(simplify_tolerance)); put<value_double>(line, keys::smooth, value_double(smooth)); vertex_converter<box2d<double>, grid_rasterizer, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> converter(clipping_extent,*ras_ptr,line,common_.t_,prj_trans,tr,feature,common_.scale_factor_); if (clip) converter.set<clip_line_tag>(); // optional clip (default: true) converter.set<transform_tag>(); // always transform if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset converter.set<affine_transform_tag>(); // optional affine transform if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter converter.set<stroke_tag>(); //always stroke for (geometry_type & geom : feature.paths()) { if (geom.size() > 1) { converter.apply(geom); } } // render id ren.color(color_type(feature.id())); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache pixmap_.add_feature(feature); }
void grid_renderer<T>::process(polygon_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = get<std::string>(sym, keys::file, feature, common_.vars_); if (filename.empty()) return; boost::optional<mapnik::marker_ptr> mark = marker_cache::instance().find(filename, true); if (!mark) return; if (!(*mark)->is_bitmap()) { MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer"; return; } boost::optional<image_ptr> pat = (*mark)->get_bitmap_data(); if (!pat) return; ras_ptr->reset(); bool clip = get<value_bool>(sym, keys::clip, feature, common_.vars_, true); double simplify_tolerance = get<value_double>(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); double smooth = get<value_double>(sym, keys::smooth, feature, common_.vars_, false); agg::trans_affine tr; auto transform = get_optional<transform_type>(sym, keys::geometry_transform); if (transform) { evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); } using conv_types = boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag>; vertex_converter<box2d<double>, grid_rasterizer, polygon_pattern_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> converter(common_.query_extent_,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true) converter.set<transform_tag>(); //always transform converter.set<affine_transform_tag>(); if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter for ( geometry_type & geom : feature.paths()) { if (geom.size() > 2) { converter.apply(geom); } } using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; using color_type = typename grid_renderer_base_type::pixfmt_type::color_type; using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>; grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_); pixfmt_type pixf(buf); grid_renderer_base_type renb(pixf); renderer_type ren(renb); // render id ren.color(color_type(feature.id())); agg::scanline_bin sl; ras_ptr->filling_rule(agg::fill_even_odd); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache pixmap_.add_feature(feature); }
void Map::zoom_all() { try { if (layers_.empty()) { return; } projection proj0(srs_); box2d<double> ext; bool success = false; bool first = true; std::vector<layer>::const_iterator itr = layers_.begin(); std::vector<layer>::const_iterator end = layers_.end(); while (itr != end) { if (itr->active()) { std::string const& layer_srs = itr->srs(); projection proj1(layer_srs); proj_transform prj_trans(proj0,proj1); box2d<double> layer_ext = itr->envelope(); if (prj_trans.backward(layer_ext, PROJ_ENVELOPE_POINTS)) { success = true; MAPNIK_LOG_DEBUG(map) << "map: Layer " << itr->name() << " original ext=" << itr->envelope(); MAPNIK_LOG_DEBUG(map) << "map: Layer " << itr->name() << " transformed to map srs=" << layer_ext; if (first) { ext = layer_ext; first = false; } else { ext.expand_to_include(layer_ext); } } } ++itr; } if (success) { if (maximum_extent_) { ext.clip(*maximum_extent_); } zoom_to_box(ext); } else { if (maximum_extent_) { MAPNIK_LOG_ERROR(map) << "could not zoom to combined layer extents" << " so falling back to maximum-extent for zoom_all result"; zoom_to_box(*maximum_extent_); } else { std::ostringstream s; s << "could not zoom to combined layer extents " << "using zoom_all because proj4 could not " << "back project any layer extents into the map srs " << "(set map 'maximum-extent' to override layer extents)"; throw std::runtime_error(s.str()); } } } catch (proj_init_error const& ex) { throw mapnik::config_error(std::string("Projection error during map.zoom_all: ") + ex.what()); } }
void agg_renderer<T>::end_layer_processing(layer const&) { MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: End layer processing"; }
mapnik::raster_ptr pgraster_wkb_reader::get_raster() { /* Read endianness */ endian_ = *ptr_; ptr_ += 1; /* Read version of protocol */ uint16_t version = read_uint16(&ptr_, endian_); if (version != 0) { MAPNIK_LOG_WARN(pgraster) << "pgraster_wkb_reader: WKB version " << version << " unsupported"; return mapnik::raster_ptr(); } numBands_ = read_uint16(&ptr_, endian_); double scaleX = read_float64(&ptr_, endian_); double scaleY = read_float64(&ptr_, endian_); double ipX = read_float64(&ptr_, endian_); double ipY = read_float64(&ptr_, endian_); double skewX = read_float64(&ptr_, endian_); double skewY = read_float64(&ptr_, endian_); int32_t srid = read_int32(&ptr_, endian_); width_ = read_uint16(&ptr_, endian_); height_ = read_uint16(&ptr_, endian_); MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: numBands=" << numBands_; MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: scaleX=" << scaleX; MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: scaleY=" << scaleY; MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: ipX=" << ipX; MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: ipY=" << ipY; MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: skewX=" << skewX; MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: skewY=" << skewY; MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: srid=" << srid; MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: size=" << width_ << "x" << height_; // this is for color interpretation MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: bandno=" << bandno_; if ( skewX || skewY ) { MAPNIK_LOG_WARN(pgraster) << "pgraster_wkb_reader: raster rotation is not supported"; return mapnik::raster_ptr(); } mapnik::box2d<double> ext(ipX,ipY,ipX+(width_*scaleX),ipY+(height_*scaleY)); MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: Raster extent=" << ext; if ( bandno_ ) { if ( bandno_ != 1 ) { MAPNIK_LOG_WARN(pgraster) << "pgraster_wkb_reader: " "reading bands other than 1st as indexed is unsupported"; return mapnik::raster_ptr(); } MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: requested band " << bandno_; return read_indexed(ext, width_, height_); } else { switch (numBands_) { case 1: return read_grayscale(ext, width_, height_); break; case 3: case 4: return read_rgba(ext, width_, height_); break; default: std::ostringstream err; err << "pgraster_wkb_reader: raster with " << numBands_ << " bands is not supported, specify a band number"; //MAPNIK_LOG_WARN(pgraster) << err.str(); throw mapnik::datasource_exception(err.str()); return mapnik::raster_ptr(); } } return mapnik::raster_ptr(); }
void png_reader::init() { FILE *fp=fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("cannot open image file "+fileName_); png_byte header[8]; memset(header,0,8); if ( fread(header,1,8,fp) != 8) { fclose(fp); throw image_reader_exception("Could not read " + fileName_); } int is_png=!png_sig_cmp(header,0,8); if (!is_png) { fclose(fp); throw image_reader_exception(fileName_ + " is not a png file"); } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { fclose(fp); throw image_reader_exception("failed to allocate png_ptr"); } // catch errors in a custom way to avoid the need for setjmp png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn); png_infop info_ptr; try { info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw image_reader_exception("failed to create info_ptr"); } } catch (std::exception const& ex) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw; } png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data); png_set_sig_bytes(png_ptr,8); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth_, &color_type_,0,0,0); width_=width; height_=height; MAPNIK_LOG_DEBUG(png_reader) << "png_reader: bit_depth=" << bit_depth_ << ",color_type=" << color_type_; png_destroy_read_struct(&png_ptr,&info_ptr,0); fclose(fp); }
void grid_renderer<T>::process(line_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature); boost::optional<marker_ptr> mark = marker_cache::instance().find(filename,true); if (!mark) return; if (!(*mark)->is_bitmap()) { MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer"; return; } boost::optional<image_ptr> pat = (*mark)->get_bitmap_data(); if (!pat) return; typedef typename grid_renderer_base_type::pixfmt_type pixfmt_type; typedef typename grid_renderer_base_type::pixfmt_type::color_type color_type; typedef agg::renderer_scanline_bin_solid<grid_renderer_base_type> renderer_type; typedef boost::mpl::vector<clip_line_tag, transform_tag, offset_transform_tag, affine_transform_tag, simplify_tag, smooth_tag, stroke_tag> conv_types; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); pixfmt_type pixf(buf); grid_renderer_base_type renb(pixf); renderer_type ren(renb); ras_ptr->reset(); int stroke_width = (*pat)->width(); agg::trans_affine tr; evaluate_transform(tr, feature, sym.get_transform(), scale_factor_); box2d<double> clipping_extent = query_extent_; if (sym.clip()) { double padding = (double)(query_extent_.width()/pixmap_.width()); double half_stroke = stroke_width/2.0; if (half_stroke > 1) padding *= half_stroke; if (std::fabs(sym.offset()) > 0) padding *= std::fabs(sym.offset()) * 1.2; padding *= scale_factor_; clipping_extent.pad(padding); } // to avoid the complexity of using an agg pattern filter instead // we create a line_symbolizer in order to fake the pattern stroke str; str.set_width(stroke_width); line_symbolizer line(str); vertex_converter<box2d<double>, grid_rasterizer, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> converter(clipping_extent,*ras_ptr,line,t_,prj_trans,tr,scale_factor_); if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true) converter.set<transform_tag>(); // always transform if (std::fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset converter.set<affine_transform_tag>(); // optional affine transform if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter converter.set<stroke_tag>(); //always stroke for (geometry_type & geom : feature.paths()) { if (geom.size() > 1) { converter.apply(geom); } } // render id ren.color(color_type(feature.id())); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache pixmap_.add_feature(feature); }
void feature_style_processor<Processor>::prepare_layer(layer_rendering_material & mat, feature_style_context_map & ctx_map, Processor & p, double scale, double scale_denom, unsigned width, unsigned height, box2d<double> const& extent, int buffer_size, std::set<std::string>& names) { layer const& lay = mat.lay_; std::vector<std::string> const& style_names = lay.styles(); std::size_t num_styles = style_names.size(); if (num_styles == 0) { MAPNIK_LOG_DEBUG(feature_style_processor) << "feature_style_processor: No style for layer=" << lay.name(); return; } mapnik::datasource_ptr ds = lay.datasource(); if (!ds) { MAPNIK_LOG_DEBUG(feature_style_processor) << "feature_style_processor: No datasource for layer=" << lay.name(); return; } processor_context_ptr current_ctx = ds->get_context(ctx_map); proj_transform prj_trans(mat.proj0_,mat.proj1_); box2d<double> query_ext = extent; // unbuffered box2d<double> buffered_query_ext(query_ext); // buffered double buffer_padding = 2.0 * scale; boost::optional<int> layer_buffer_size = lay.buffer_size(); if (layer_buffer_size) // if layer overrides buffer size, use this value to compute buffered extent { buffer_padding *= *layer_buffer_size; } else { buffer_padding *= buffer_size; } buffered_query_ext.width(query_ext.width() + buffer_padding); buffered_query_ext.height(query_ext.height() + buffer_padding); // clip buffered extent by maximum extent, if supplied boost::optional<box2d<double> > const& maximum_extent = m_.maximum_extent(); if (maximum_extent) { buffered_query_ext.clip(*maximum_extent); } box2d<double> layer_ext = lay.envelope(); const box2d<double> buffered_query_ext_map_srs = buffered_query_ext; bool fw_success = false; bool early_return = false; // first, try intersection of map extent forward projected into layer srs if (prj_trans.forward(buffered_query_ext, PROJ_ENVELOPE_POINTS) && buffered_query_ext.intersects(layer_ext)) { fw_success = true; layer_ext.clip(buffered_query_ext); } // if no intersection and projections are also equal, early return else if (prj_trans.equal()) { early_return = true; } // next try intersection of layer extent back projected into map srs else if (prj_trans.backward(layer_ext, PROJ_ENVELOPE_POINTS) && buffered_query_ext_map_srs.intersects(layer_ext)) { layer_ext.clip(buffered_query_ext_map_srs); // forward project layer extent back into native projection if (! prj_trans.forward(layer_ext, PROJ_ENVELOPE_POINTS)) { MAPNIK_LOG_ERROR(feature_style_processor) << "feature_style_processor: Layer=" << lay.name() << " extent=" << layer_ext << " in map projection " << " did not reproject properly back to layer projection"; } } else { // if no intersection then nothing to do for layer early_return = true; } std::vector<feature_type_style const*> & active_styles = mat.active_styles_; if (early_return) { // check for styles needing compositing operations applied // https://github.com/mapnik/mapnik/issues/1477 for (std::string const& style_name : style_names) { boost::optional<feature_type_style const&> style=m_.find_style(style_name); if (!style) { continue; } if (style->comp_op() || style->image_filters().size() > 0) { if (style->active(scale_denom)) { // we'll have to handle compositing ops active_styles.push_back(&(*style)); } } } return; } // if we've got this far, now prepare the unbuffered extent // which is used as a bbox for clipping geometries if (maximum_extent) { query_ext.clip(*maximum_extent); } box2d<double> & layer_ext2 = mat.layer_ext2_; layer_ext2 = lay.envelope(); if (fw_success) { if (prj_trans.forward(query_ext, PROJ_ENVELOPE_POINTS)) { layer_ext2.clip(query_ext); } } else { if (prj_trans.backward(layer_ext2, PROJ_ENVELOPE_POINTS)) { layer_ext2.clip(query_ext); prj_trans.forward(layer_ext2, PROJ_ENVELOPE_POINTS); } } std::vector<rule_cache> & rule_caches = mat.rule_caches_; attribute_collector collector(names); // iterate through all named styles collecting active styles and attribute names for (std::string const& style_name : style_names) { boost::optional<feature_type_style const&> style=m_.find_style(style_name); if (!style) { MAPNIK_LOG_ERROR(feature_style_processor) << "feature_style_processor: Style=" << style_name << " required for layer=" << lay.name() << " does not exist."; continue; } std::vector<rule> const& style_rules = style->get_rules(); bool active_rules = false; rule_cache rc; for(rule const& r : style_rules) { if (r.active(scale_denom)) { rc.add_rule(r); active_rules = true; collector(r); } } if (active_rules) { rule_caches.push_back(std::move(rc)); active_styles.push_back(&(*style)); } } // Don't even try to do more work if there are no active styles. if (active_styles.empty()) { return; } double qw = query_ext.width()>0 ? query_ext.width() : 1; double qh = query_ext.height()>0 ? query_ext.height() : 1; query::resolution_type res(width/qw, height/qh); query q(layer_ext,res,scale_denom,extent); q.set_variables(p.variables()); if (p.attribute_collection_policy() == COLLECT_ALL) { layer_descriptor lay_desc = ds->get_descriptor(); for (attribute_descriptor const& desc : lay_desc.get_descriptors()) { q.add_property_name(desc.get_name()); } } else { for (std::string const& name : names) { q.add_property_name(name); } } q.set_filter_factor(collector.get_filter_factor()); // Also query the group by attribute std::string const& group_by = lay.group_by(); if (!group_by.empty()) { q.add_property_name(group_by); } bool cache_features = lay.cache_features() && active_styles.size() > 1; std::vector<featureset_ptr> & featureset_ptr_list = mat.featureset_ptr_list_; if (!group_by.empty() || cache_features) { featureset_ptr_list.push_back(ds->features_with_context(q,current_ctx)); } else { for(std::size_t i = 0; i < active_styles.size(); ++i) { featureset_ptr_list.push_back(ds->features_with_context(q,current_ctx)); } } }
void agg_renderer<T>::start_map_processing(Map const& map) { MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Start map processing bbox=" << map.get_current_extent(); ras_ptr->clip_box(0,0,width_,height_); }
static void write_features(T const& grid_type, boost::python::dict& feature_data, std::vector<typename T::lookup_type> const& key_order) { std::string const& key = grid_type.get_key(); std::set<std::string> const& attributes = grid_type.property_names(); typename T::feature_type const& g_features = grid_type.get_grid_features(); typename T::feature_type::const_iterator feat_itr = g_features.begin(); typename T::feature_type::const_iterator feat_end = g_features.end(); bool include_key = (attributes.find(key) != attributes.end()); for (; feat_itr != feat_end; ++feat_itr) { mapnik::feature_ptr feature = feat_itr->second; boost::optional<std::string> join_value; if (key == grid_type.key_name()) { std::stringstream s; s << feature->id(); join_value = s.str(); } else if (feature->has_key(key)) { join_value = feature->get(key).to_string(); } if (join_value) { // only serialize features visible in the grid if(std::find(key_order.begin(), key_order.end(), *join_value) != key_order.end()) { boost::python::dict feat; bool found = false; if (key == grid_type.key_name()) { // drop key unless requested if (include_key) { found = true; //TODO - add __id__ as data key? //feat[key] = *join_value; } } feature_kv_iterator itr = feature->begin(); feature_kv_iterator end = feature->end(); for ( ;itr!=end; ++itr) { std::string const& key_name = boost::get<0>(*itr); if (key_name == key) { // drop key unless requested if (include_key) { found = true; feat[key_name] = boost::get<1>(*itr); } } else if ( (attributes.find(key_name) != attributes.end()) ) { found = true; feat[key_name] = boost::get<1>(*itr); } } if (found) { feature_data[feat_itr->first] = feat; } } } else { MAPNIK_LOG_DEBUG(bindings) << "write_features: Should not get here: key " << key << " not found in grid feature properties"; } } }
stroker::~stroker() { MAPNIK_LOG_DEBUG(font_engine_freetype) << "stroker: Destroy stroker=" << s_; FT_Stroker_Done(s_); }
void grid_renderer<T>::process(polygon_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_); if (filename.empty()) return; mapnik::marker const& mark = marker_cache::instance().find(filename, true); if (mark.is<mapnik::marker_null>()) return; if (!mark.is<mapnik::marker_rgba8>()) { MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer"; return; } ras_ptr->reset(); value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_); value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_); value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_); agg::trans_affine tr; auto transform = get_optional<transform_type>(sym, keys::geometry_transform); if (transform) { evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); } using vertex_converter_type = vertex_converter<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag>; vertex_converter_type converter(common_.query_extent_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true) converter.set<transform_tag>(); //always transform converter.set<affine_transform_tag>(); if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, grid_rasterizer>; using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>; apply_vertex_converter_type apply(converter, *ras_ptr); mapnik::util::apply_visitor(vertex_processor_type(apply),feature.get_geometry()); using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; using color_type = typename grid_renderer_base_type::pixfmt_type::color_type; using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>; grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_); pixfmt_type pixf(buf); grid_renderer_base_type renb(pixf); renderer_type ren(renb); // render id ren.color(color_type(feature.id())); agg::scanline_bin sl; ras_ptr->filling_rule(agg::fill_even_odd); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache pixmap_.add_feature(feature); }
void grid_renderer<T>::process(line_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_); if (filename.empty()) return; std::shared_ptr<mapnik::marker const> mark = marker_cache::instance().find(filename, true); if (mark->is<mapnik::marker_null>()) return; if (!mark->is<mapnik::marker_rgba8>()) { MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer"; return; } value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_); value_double offset = get<value_double, keys::offset>(sym, feature, common_.vars_); value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_); value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_); using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; using color_type = typename grid_renderer_base_type::pixfmt_type::color_type; using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_); pixfmt_type pixf(buf); grid_renderer_base_type renb(pixf); renderer_type ren(renb); ras_ptr->reset(); line_pattern_enum pattern = get<line_pattern_enum, keys::line_pattern>(sym, feature, common_.vars_); std::size_t stroke_width = (pattern == LINE_PATTERN_WARP) ? mark->width() : get<value_double, keys::stroke_width>(sym, feature, common_.vars_); agg::trans_affine tr; auto transform = get_optional<transform_type>(sym, keys::geometry_transform); if (transform) { evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); } box2d<double> clipping_extent = common_.query_extent_; if (clip) { double pad_per_pixel = static_cast<double>(common_.query_extent_.width()/common_.width_); double pixels = std::ceil(std::max(stroke_width / 2.0 + std::fabs(offset), (std::fabs(offset) * offset_converter_default_threshold))); double padding = pad_per_pixel * pixels * common_.scale_factor_; clipping_extent.pad(padding); } // to avoid the complexity of using an agg pattern filter instead // we create a line_symbolizer in order to fake the pattern line_symbolizer line; put<value_double>(line, keys::stroke_width, value_double(stroke_width)); // TODO: really should pass the offset to the fake line too, but // this wasn't present in the previous version and makes the test // fail - in this case, probably the test should be updated. //put<value_double>(line, keys::offset, value_double(offset)); put<value_double>(line, keys::simplify_tolerance, value_double(simplify_tolerance)); put<value_double>(line, keys::smooth, value_double(smooth)); using vertex_converter_type = vertex_converter<clip_line_tag, transform_tag, affine_transform_tag, simplify_tag,smooth_tag, offset_transform_tag,stroke_tag>; vertex_converter_type converter(clipping_extent,line,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (clip) converter.set<clip_line_tag>(); converter.set<transform_tag>(); // always transform if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset converter.set<affine_transform_tag>(); // optional affine transform if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter converter.set<stroke_tag>(); //always stroke using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type,grid_rasterizer>; using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>; apply_vertex_converter_type apply(converter, *ras_ptr); mapnik::util::apply_visitor(vertex_processor_type(apply),feature.get_geometry()); // render id ren.color(color_type(feature.id())); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache pixmap_.add_feature(feature); }
mapnik::raster_ptr pgraster_wkb_reader::read_indexed(mapnik::box2d<double> const& bbox, uint16_t width, uint16_t height) { uint8_t type = read_uint8(&ptr_); int pixtype = BANDTYPE_PIXTYPE(type); int offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0; int hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0; MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: band type:" << pixtype << " offline:" << offline << " hasnodata:" << hasnodata; if ( offline ) { MAPNIK_LOG_WARN(pgraster) << "pgraster_wkb_reader: offline band " " unsupported"; return mapnik::raster_ptr(); } MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: reading " << height_ << "x" << width_ << " pixels"; switch (pixtype) { case PT_1BB: case PT_2BUI: case PT_4BUI: // all <8BPP values are wrote in full bytes anyway case PT_8BSI: // mapnik does not support signed anyway case PT_8BUI: return read_data_band(bbox, width_, height_, hasnodata, std::bind(read_uint8, &ptr_)); break; case PT_16BSI: // mapnik does not support signed anyway case PT_16BUI: return read_data_band(bbox, width_, height_, hasnodata, std::bind(read_uint16, &ptr_, endian_)); break; case PT_32BSI: // mapnik does not support signed anyway case PT_32BUI: return read_data_band(bbox, width_, height_, hasnodata, std::bind(read_uint32, &ptr_, endian_)); break; case PT_32BF: return read_data_band(bbox, width_, height_, hasnodata, std::bind(read_float32, &ptr_, endian_)); break; case PT_64BF: return read_data_band(bbox, width_, height_, hasnodata, std::bind(read_float64, &ptr_, endian_)); break; default: std::ostringstream err; err << "pgraster_wkb_reader: data band type " << pixtype << " unsupported"; // TODO: accept policy to decide on throw-or-skip ? //MAPNIK_LOG_WARN(pgraster) << err.str(); throw mapnik::datasource_exception(err.str()); } return mapnik::raster_ptr(); }