root/trunk/src/agg_renderer.cpp @ 741

Revision 741, 28.9 kB (checked in by artem, 2 years ago)

make shield_symbolizer to work with point geometries (TODO!!)

Line 
1/*****************************************************************************
2 *
3 * This file is part of Mapnik (c++ mapping toolkit)
4 *
5 * Copyright (C) 2006 Artem Pavlenko
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 *
21 *****************************************************************************/
22//$Id$
23
24// mapnik
25#include <mapnik/agg_renderer.hpp>
26#include <mapnik/image_util.hpp>
27#include <mapnik/unicode.hpp>
28#include <mapnik/placement_finder.hpp>
29#include <mapnik/markers_converter.hpp>
30#include <mapnik/arrow.hpp>
31#include <mapnik/config_error.hpp>
32#include <mapnik/font_set.hpp>
33
34// agg
35#define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
36#include "agg_rendering_buffer.h"
37#include "agg_pixfmt_rgba.h"
38#include "agg_rasterizer_scanline_aa.h"
39#include "agg_basics.h"
40#include "agg_scanline_p.h"
41#include "agg_scanline_u.h"
42#include "agg_renderer_scanline.h"
43#include "agg_path_storage.h"
44#include "agg_span_allocator.h"
45#include "agg_span_pattern_rgba.h"
46#include "agg_image_accessors.h"
47#include "agg_conv_stroke.h"
48#include "agg_conv_dash.h"
49#include "agg_conv_contour.h"
50#include "agg_conv_clip_polyline.h"
51#include "agg_vcgen_stroke.h"
52#include "agg_conv_adaptor_vcgen.h"
53#include "agg_conv_smooth_poly1.h"
54#include "agg_conv_marker.h"
55#include "agg_vcgen_markers_term.h"
56#include "agg_renderer_outline_aa.h"
57#include "agg_rasterizer_outline_aa.h"
58#include "agg_rasterizer_outline.h"
59#include "agg_renderer_outline_image.h"
60#include "agg_span_allocator.h"
61#include "agg_span_pattern_rgba.h"
62#include "agg_renderer_scanline.h"
63#include "agg_pattern_filters_rgba.h"
64#include "agg_renderer_outline_image.h"
65#include "agg_vpgen_clip_polyline.h"
66#include "agg_arrowhead.h"
67
68// boost
69#include <boost/utility.hpp>
70#include <boost/tuple/tuple.hpp>
71
72// stl
73#ifdef MAPNIK_DEBUG
74#include <iostream>
75#endif
76
77namespace mapnik
78{
79   class pattern_source : private boost::noncopyable
80   {
81      public:
82         pattern_source(ImageData32 const& pattern)
83            : pattern_(pattern) {}
84       
85         unsigned int width() const
86         {
87            return pattern_.width();
88         }
89         unsigned int height() const
90         {
91            return pattern_.height();
92         }
93         agg::rgba8 pixel(int x, int y) const
94         {
95            unsigned c = pattern_(x,y);
96            return agg::rgba8(c & 0xff, 
97                              (c >> 8) & 0xff, 
98                              (c >> 16) & 0xff,
99                              (c >> 24) & 0xff);
100         }
101      private:
102         ImageData32 const& pattern_;
103   };
104   
105   struct rasterizer :  agg::rasterizer_scanline_aa<>, boost::noncopyable {};
106   
107   template <typename T>
108   agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, unsigned offset_x, unsigned offset_y)
109      : feature_style_processor<agg_renderer>(m),
110        pixmap_(pixmap),
111        width_(pixmap_.width()),
112        height_(pixmap_.height()),
113        t_(m.getWidth(),m.getHeight(),m.getCurrentExtent(),offset_x,offset_y),
114        font_engine_(),
115        font_manager_(font_engine_),
116        detector_(Envelope<double>(-64, -64, m.getWidth() + 64 ,m.getHeight() + 64)),
117        ras_ptr(new rasterizer)
118   {
119      boost::optional<Color> bg = m.background();
120      if (bg) pixmap_.setBackground(*bg);
121#ifdef MAPNIK_DEBUG
122      std::clog << "scale=" << m.scale() << "\n";
123#endif
124   }
125   
126   template <typename T>
127   agg_renderer<T>::~agg_renderer() {}
128
129   template <typename T>
130   void agg_renderer<T>::start_map_processing(Map const& map)
131   {
132#ifdef MAPNIK_DEBUG
133      std::clog << "start map processing bbox=" 
134                << map.getCurrentExtent() << "\n";
135#endif
136      ras_ptr->clip_box(0,0,width_,height_);
137   }
138
139   template <typename T>
140   void agg_renderer<T>::end_map_processing(Map const& )
141   {
142#ifdef MAPNIK_DEBUG
143      std::clog << "end map processing\n";
144#endif
145   }
146   
147   template <typename T>
148   void agg_renderer<T>::start_layer_processing(Layer const& lay)
149   {
150#ifdef MAPNIK_DEBUG
151      std::clog << "start layer processing : " << lay.name()  << "\n";
152      std::clog << "datasource = " << lay.datasource().get() << "\n";
153#endif
154      if (lay.clear_label_cache())
155      {
156         detector_.clear();
157      }
158   }
159   
160   template <typename T>
161   void agg_renderer<T>::end_layer_processing(Layer const&)
162   {
163#ifdef MAPNIK_DEBUG
164      std::clog << "end layer processing\n";
165#endif
166   }
167   
168   template <typename T>       
169   void agg_renderer<T>::process(polygon_symbolizer const& sym,
170                                 Feature const& feature,
171                                 proj_transform const& prj_trans)
172   {
173      typedef  coord_transform2<CoordTransform,geometry2d> path_type;
174      typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;   
175      typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
176           
177      Color const& fill_ = sym.get_fill();
178      agg::scanline_u8 sl;
179     
180      agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
181      agg::pixfmt_rgba32_plain pixf(buf);
182     
183      ren_base renb(pixf); 
184      unsigned r=fill_.red();
185      unsigned g=fill_.green();
186      unsigned b=fill_.blue();
187      renderer ren(renb);
188     
189      ras_ptr->reset();
190     
191      for (unsigned i=0;i<feature.num_geometries();++i)
192      {
193         geometry2d const& geom=feature.get_geometry(i);
194         if (geom.num_points() > 2) 
195         {
196            path_type path(t_,geom,prj_trans);
197            ras_ptr->add_path(path);
198         }
199      }
200      ren.color(agg::rgba8(r, g, b, int(255 * sym.get_opacity())));
201      agg::render_scanlines(*ras_ptr, sl, ren);
202   }
203   
204   typedef boost::tuple<double,double,double,double> segment_t;
205   bool y_order(segment_t const& first,segment_t const& second)
206   {
207      double miny0 = std::min(first.get<1>(),first.get<3>());
208      double miny1 = std::min(second.get<1>(),second.get<3>()); 
209      return  miny0 > miny1;
210   }
211     
212   template <typename T>       
213   void agg_renderer<T>::process(building_symbolizer const& sym,
214                                 Feature const& feature,
215                                 proj_transform const& prj_trans)
216   {
217      typedef  coord_transform2<CoordTransform,geometry2d> path_type;
218      typedef  coord_transform3<CoordTransform,geometry2d> path_type_roof;
219      typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;   
220      typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
221     
222      agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
223      agg::pixfmt_rgba32_plain pixf(buf);
224      ren_base renb(pixf);
225     
226      Color const& fill_  = sym.get_fill();
227      unsigned r=fill_.red();
228      unsigned g=fill_.green();
229      unsigned b=fill_.blue();
230      renderer ren(renb);         
231      agg::scanline_u8 sl;
232     
233      ras_ptr->reset();
234      double height = 0.7071 * sym.height(); // height in meters
235     
236      for (unsigned i=0;i<feature.num_geometries();++i)
237      {
238         geometry2d const& geom = feature.get_geometry(i);
239         if (geom.num_points() > 2) 
240         { 
241            boost::scoped_ptr<geometry2d> frame(new line_string_impl);
242            boost::scoped_ptr<geometry2d> roof(new polygon_impl);
243            std::deque<segment_t> face_segments;
244            double x0(0);
245            double y0(0);
246            unsigned cm = geom.vertex(&x0,&y0);
247            for (unsigned j=1;j<geom.num_points();++j)
248            {
249               double x,y;
250               cm = geom.vertex(&x,&y);
251               if (cm == SEG_MOVETO)
252               {
253                  frame->move_to(x,y);
254               }
255               else if (cm == SEG_LINETO)
256               {
257                  frame->line_to(x,y);
258               }
259               if (j!=0)
260               {
261                  face_segments.push_back(segment_t(x0,y0,x,y));
262               }
263               x0 = x; 
264               y0 = y;
265            }
266            std::sort(face_segments.begin(),face_segments.end(), y_order);
267            std::deque<segment_t>::const_iterator itr=face_segments.begin();
268            for (;itr!=face_segments.end();++itr)
269            {
270               boost::scoped_ptr<geometry2d> faces(new polygon_impl);
271               faces->move_to(itr->get<0>(),itr->get<1>());
272               faces->line_to(itr->get<2>(),itr->get<3>());
273               faces->line_to(itr->get<2>(),itr->get<3>() + height);
274               faces->line_to(itr->get<0>(),itr->get<1>() + height);
275               
276               path_type faces_path (t_,*faces,prj_trans);
277               ras_ptr->add_path(faces_path);
278               ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(255 * sym.get_opacity())));
279               agg::render_scanlines(*ras_ptr, sl, ren);
280               ras_ptr->reset();
281               
282               frame->move_to(itr->get<0>(),itr->get<1>());
283               frame->line_to(itr->get<0>(),itr->get<1>()+height);   
284            }
285           
286            geom.rewind(0);
287            for (unsigned j=0;j<geom.num_points();++j)
288            {
289               double x,y;
290               unsigned cm = geom.vertex(&x,&y);
291               if (cm == SEG_MOVETO)
292               {
293                  frame->move_to(x,y+height);
294                  roof->move_to(x,y+height);
295               }
296               else if (cm == SEG_LINETO)
297               {
298                  frame->line_to(x,y+height);
299                  roof->line_to(x,y+height);
300               }
301            }           
302            path_type path(t_,*frame,prj_trans); 
303            agg::conv_stroke<path_type>  stroke(path);
304            ras_ptr->add_path(stroke);
305            ren.color(agg::rgba8(128, 128, 128, int(255 * sym.get_opacity())));
306            agg::render_scanlines(*ras_ptr, sl, ren);
307            ras_ptr->reset();
308           
309            path_type roof_path (t_,*roof,prj_trans);
310            ras_ptr->add_path(roof_path);
311            ren.color(agg::rgba8(r, g, b, int(255 * sym.get_opacity())));
312            agg::render_scanlines(*ras_ptr, sl, ren);
313         }
314      }
315   }
316
317   template <typename T>
318   void agg_renderer<T>::process(line_symbolizer const& sym,
319                              Feature const& feature,
320                              proj_transform const& prj_trans)
321   {   
322      typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base; 
323      typedef coord_transform2<CoordTransform,geometry2d> path_type;
324      typedef agg::renderer_outline_aa<ren_base> renderer_oaa;
325      typedef agg::rasterizer_outline_aa<renderer_oaa> rasterizer_outline_aa;
326      typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
327     
328      agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
329      agg::pixfmt_rgba32_plain pixf(buf); 
330
331      ren_base renb(pixf);               
332      mapnik::stroke const&  stroke_ = sym.get_stroke();
333      Color const& col = stroke_.get_color();
334      unsigned r=col.red();
335      unsigned g=col.green();
336      unsigned b=col.blue();
337      renderer ren(renb);
338      ras_ptr->reset();
339      agg::scanline_p8 sl;
340 
341      for (unsigned i=0;i<feature.num_geometries();++i)
342      {
343         geometry2d const& geom = feature.get_geometry(i);
344         if (geom.num_points() > 1)
345         {
346            path_type path(t_,geom,prj_trans);
347           
348            if (stroke_.has_dash())
349            {             
350               agg::conv_dash<path_type> dash(path);
351               dash_array const& d = stroke_.get_dash_array();
352               dash_array::const_iterator itr = d.begin();
353               dash_array::const_iterator end = d.end();
354               for (;itr != end;++itr)
355               {
356                  dash.add_dash(itr->first, itr->second); 
357               }
358               
359               agg::conv_stroke<agg::conv_dash<path_type > > stroke(dash);
360               
361               line_join_e join=stroke_.get_line_join();
362               if ( join == MITER_JOIN)
363                  stroke.generator().line_join(agg::miter_join);
364               else if( join == MITER_REVERT_JOIN) 
365                  stroke.generator().line_join(agg::miter_join);
366               else if( join == ROUND_JOIN) 
367                  stroke.generator().line_join(agg::round_join);
368               else
369                  stroke.generator().line_join(agg::bevel_join);
370               
371               line_cap_e cap=stroke_.get_line_cap();
372               if (cap == BUTT_CAP)   
373                  stroke.generator().line_cap(agg::butt_cap);
374               else if (cap == SQUARE_CAP)
375                  stroke.generator().line_cap(agg::square_cap);
376               else 
377                  stroke.generator().line_cap(agg::round_cap);
378               
379               stroke.generator().miter_limit(4.0);
380               stroke.generator().width(stroke_.get_width());
381               
382               ras_ptr->add_path(stroke);
383               
384            }
385            else 
386            {
387               agg::conv_stroke<path_type>  stroke(path);
388               line_join_e join=stroke_.get_line_join();
389               if ( join == MITER_JOIN)
390                  stroke.generator().line_join(agg::miter_join);
391               else if( join == MITER_REVERT_JOIN) 
392                  stroke.generator().line_join(agg::miter_join);
393               else if( join == ROUND_JOIN) 
394                  stroke.generator().line_join(agg::round_join);
395               else
396                  stroke.generator().line_join(agg::bevel_join);
397               
398               line_cap_e cap=stroke_.get_line_cap();
399               if (cap == BUTT_CAP)   
400                  stroke.generator().line_cap(agg::butt_cap);
401               else if (cap == SQUARE_CAP)
402                  stroke.generator().line_cap(agg::square_cap);
403               else 
404                  stroke.generator().line_cap(agg::round_cap);
405               
406               stroke.generator().miter_limit(4.0);
407               stroke.generator().width(stroke_.get_width());
408               ras_ptr->add_path(stroke);
409            }
410         }
411      }
412      ren.color(agg::rgba8(r, g, b, int(255*stroke_.get_opacity())));
413      agg::render_scanlines(*ras_ptr, sl, ren);
414   }
415   
416   template <typename T>
417   void agg_renderer<T>::process(point_symbolizer const& sym,
418                              Feature const& feature,
419                              proj_transform const& prj_trans)
420   {
421      double x;
422      double y;
423      double z=0;
424      boost::shared_ptr<ImageData32> const& data = sym.get_image();
425      if ( data )
426      {
427         for (unsigned i=0;i<feature.num_geometries();++i)
428         {
429            geometry2d const& geom = feature.get_geometry(i);
430           
431            geom.label_position(&x,&y);
432            prj_trans.backward(x,y,z);
433            t_.forward(&x,&y);
434            int w = data->width();
435            int h = data->height();
436            int px=int(floor(x - 0.5 * w));
437            int py=int(floor(y - 0.5 * h));
438            Envelope<double> label_ext (floor(x - 0.5 * w),
439                                        floor(y - 0.5 * h),
440                                        ceil (x + 0.5 * w),
441                                        ceil (y + 0.5 * h));
442            if (sym.get_allow_overlap() || 
443                detector_.has_placement(label_ext))
444            {   
445               pixmap_.set_rectangle_alpha(px,py,*data);
446               detector_.insert(label_ext);
447            }
448         }
449      }
450   }
451   
452   template <typename T>
453   void  agg_renderer<T>::process(shield_symbolizer const& sym,
454                                  Feature const& feature,
455                                  proj_transform const& prj_trans)
456   {
457      typedef  coord_transform2<CoordTransform,geometry2d> path_type;
458      UnicodeString text = feature[sym.get_name()].to_unicode();
459      boost::shared_ptr<ImageData32> const& data = sym.get_image();
460      if (text.length() > 0 && data)
461      {
462         face_set_ptr faces;
463
464         if (sym.get_fontset().size() > 0)
465         {
466            faces = font_manager_.get_face_set(sym.get_fontset());
467         }
468         else 
469         {
470            faces = font_manager_.get_face_set(sym.get_face_name());
471         }
472
473         if (faces->size() > 0)
474         {
475            text_renderer<mapnik::Image32> ren(pixmap_, faces);
476           
477            ren.set_pixel_size(sym.get_text_size());
478            ren.set_fill(sym.get_fill());
479            ren.set_halo_fill(sym.get_halo_fill());
480            ren.set_halo_radius(sym.get_halo_radius());
481
482            placement_finder<label_collision_detector4> finder(detector_);
483           
484            string_info info(text);
485           
486            faces->get_string_info(info);
487           
488
489            int w = data->width();
490            int h = data->height();
491           
492            unsigned num_geom = feature.num_geometries();
493            for (unsigned i=0;i<num_geom;++i)
494            {
495               geometry2d const& geom = feature.get_geometry(i); 
496               if (geom.num_points() > 0 ) 
497               {   
498                  path_type path(t_,geom,prj_trans);
499                  placement text_placement(info, sym);
500                  text_placement.avoid_edges = sym.get_avoid_edges();
501                  if (sym.get_label_placement() == POINT_PLACEMENT) 
502                  {
503                     double label_x;
504                     double label_y;
505                     double z=0.0;
506                     geom.label_position(&label_x, &label_y);
507                     prj_trans.backward(label_x,label_y, z);
508                     t_.forward(&label_x,&label_y);
509                     finder.find_point_placement(text_placement,label_x,label_y);
510
511                     for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
512                     { 
513                        double x = text_placement.placements[ii].starting_x;
514                        double y = text_placement.placements[ii].starting_y;
515                        // remove displacement from image label
516                        position pos = sym.get_displacement();
517                        double lx = x - boost::get<0>(pos);
518                        double ly = y - boost::get<1>(pos);
519                        int px=int(lx - (0.5 * w)) ;
520                        int py=int(ly - (0.5 * h)) ;
521                        Envelope<double> label_ext (floor(lx - 0.5 * w), floor(ly - 0.5 * h), ceil (lx + 0.5 * w), ceil (ly + 0.5 * h));
522                       
523                        if ( detector_.has_placement(label_ext))
524                        {   
525                           pixmap_.set_rectangle_alpha(px,py,*data);
526                           Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
527                           ren.render(x,y);
528                           detector_.insert(label_ext);
529                        }
530                     }
531                     finder.update_detector(text_placement);
532                  }
533                 
534                  else if (geom.num_points() > 1 && sym.get_label_placement() == LINE_PLACEMENT) 
535                  {
536                     finder.find_point_placements<path_type>(text_placement,path);
537                     
538                     for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
539                     {
540                        int w = data->width();
541                        int h = data->height();                     
542                        double x = text_placement.placements[ii].starting_x;
543                        double y = text_placement.placements[ii].starting_y;
544                       
545                        int px=int(x - (w/2));
546                        int py=int(y - (h/2));
547                       
548                        pixmap_.set_rectangle_alpha(px,py,*data);
549                       
550                        Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
551                        ren.render(x,y);
552                     }
553                     finder.update_detector(text_placement);
554                  }
555               }
556            }
557         }
558      }
559   }
560   
561   template <typename T>
562   void  agg_renderer<T>::process(line_pattern_symbolizer const& sym,
563                               Feature const& feature,
564                               proj_transform const& prj_trans)
565   {
566      typedef  coord_transform2<CoordTransform,geometry2d> path_type;
567      typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type;
568      typedef agg::renderer_base<agg::pixfmt_rgba32_plain> renderer_base;
569      typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type;
570      typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
571     
572      agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
573      agg::pixfmt_rgba32_plain pixf(buf);
574     
575      ImageData32 pat =  * sym.get_image();
576      renderer_base ren_base(pixf); 
577      agg::pattern_filter_bilinear_rgba8 filter; 
578      pattern_source source(pat);
579      pattern_type pattern (filter,source);
580      renderer_type ren(ren_base, pattern);
581      ren.clip_box(0,0,width_,height_);
582      rasterizer_type ras(ren);
583     
584      for (unsigned i=0;i<feature.num_geometries();++i)
585      {
586         geometry2d const& geom = feature.get_geometry(i);
587         if (geom.num_points() > 1)
588         {
589            path_type path(t_,geom,prj_trans);
590            ras.add_path(path);   
591         } 
592      }
593   }
594   
595   template <typename T>
596   void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
597                                 Feature const& feature,
598                                 proj_transform const& prj_trans)
599   {
600      typedef coord_transform2<CoordTransform,geometry2d> path_type;
601      typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base; 
602      typedef agg::wrap_mode_repeat wrap_x_type;
603      typedef agg::wrap_mode_repeat wrap_y_type;
604      typedef agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32,
605         agg::row_accessor<agg::int8u>, agg::pixel32_type> rendering_buffer;
606      typedef agg::image_accessor_wrap<rendering_buffer, 
607         wrap_x_type,
608         wrap_y_type> img_source_type;
609       
610      typedef agg::span_pattern_rgba<img_source_type> span_gen_type;
611       
612      typedef agg::renderer_scanline_aa<ren_base, 
613         agg::span_allocator<agg::rgba8>,
614         span_gen_type> renderer_type; 
615     
616     
617      agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
618      agg::pixfmt_rgba32_plain pixf(buf);
619      ren_base renb(pixf);
620     
621      agg::scanline_u8 sl;
622      ras_ptr->reset();
623     
624      ImageData32 const& pattern =  * sym.get_image();
625      unsigned w=pattern.width();
626      unsigned h=pattern.height();
627      agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4); 
628      agg::span_allocator<agg::rgba8> sa;
629      agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32,
630         agg::row_accessor<agg::int8u>, agg::pixel32_type> pixf_pattern(pattern_rbuf);
631      img_source_type img_src(pixf_pattern);
632     
633      double x0=0,y0=0;
634      unsigned num_geometries = feature.num_geometries();
635      if (num_geometries>0)
636      {
637         path_type path(t_,feature.get_geometry(0),prj_trans);
638         path.vertex(&x0,&y0);
639      }
640      unsigned offset_x = unsigned(width_-x0);
641      unsigned offset_y = unsigned(height_-y0);
642      span_gen_type sg(img_src, offset_x, offset_y);     
643      renderer_type rp(renb,sa, sg);
644      for (unsigned i=0;i<num_geometries;++i)
645      {
646         geometry2d const& geom = feature.get_geometry(i);
647         if (geom.num_points() > 2)
648         {     
649            path_type path(t_,geom,prj_trans);           
650            ras_ptr->add_path(path); 
651         }
652      }
653      agg::render_scanlines(*ras_ptr, sl, rp);   
654   }
655
656   template <typename T>
657   void agg_renderer<T>::process(raster_symbolizer const&,
658                                 Feature const& feature,
659                                 proj_transform const& prj_trans)
660   {
661      // TODO -- at the moment raster_symbolizer is an empty class
662      // used for type dispatching, but we can have some fancy raster
663      // processing in a future (filters??). Just copy raster into pixmap for now.
664      raster_ptr const& raster=feature.get_raster();
665      if (raster)
666      {
667         Envelope<double> ext=t_.forward(raster->ext_);
668         ImageData32 target(int(ext.width() + 0.5),int(ext.height() + 0.5));
669         scale_image<ImageData32>(target,raster->data_);
670         pixmap_.set_rectangle(int(ext.minx()),int(ext.miny()),target);
671      }
672   }
673   
674   template <typename T>
675   void agg_renderer<T>::process(markers_symbolizer const& sym,
676                                 Feature const& feature,
677                                 proj_transform const& prj_trans)
678   {
679      typedef  coord_transform2<CoordTransform,geometry2d> path_type;
680      typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;   
681      typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
682      arrow arrow_;
683      ras_ptr->reset();
684   
685      agg::scanline_u8 sl;
686      agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
687      agg::pixfmt_rgba32_plain pixf(buf);
688      ren_base renb(pixf); 
689     
690      unsigned r = 0;// fill_.red();
691      unsigned g = 0; //fill_.green();
692      unsigned b = 255; //fill_.blue();
693      renderer ren(renb); 
694      for (unsigned i=0;i<feature.num_geometries();++i)
695      {
696         geometry2d const& geom=feature.get_geometry(i);
697         if (geom.num_points() > 1) 
698         {
699            path_type path(t_,geom,prj_trans);
700           
701            agg::conv_dash <path_type> dash(path);
702            dash.add_dash(20.0,200.0);
703            markers_converter<agg::conv_dash<path_type>, 
704               arrow, 
705               label_collision_detector4>
706               marker(dash, arrow_, detector_);
707            ras_ptr->add_path(marker);
708         }
709      }
710      ren.color(agg::rgba8(r, g, b, 255));
711      agg::render_scanlines(*ras_ptr, sl, ren);
712   }
713   
714   template <typename T>
715   void agg_renderer<T>::process(text_symbolizer const& sym,
716                                 Feature const& feature,
717                                 proj_transform const& prj_trans)
718   {
719      typedef  coord_transform2<CoordTransform,geometry2d> path_type;
720     
721      UnicodeString text = feature[sym.get_name()].to_unicode();
722      if ( text.length() > 0 )
723      {
724         Color const& fill = sym.get_fill();
725
726         face_set_ptr faces;
727
728         if (sym.get_fontset().size() > 0)
729         {
730            faces = font_manager_.get_face_set(sym.get_fontset());
731         }
732         else 
733         {
734            faces = font_manager_.get_face_set(sym.get_face_name());
735         }
736
737         if (faces->size() > 0)
738         {
739            text_renderer<mapnik::Image32> ren(pixmap_, faces);
740            ren.set_pixel_size(sym.get_text_size());
741            ren.set_fill(fill);
742            ren.set_halo_fill(sym.get_halo_fill());
743            ren.set_halo_radius(sym.get_halo_radius());
744           
745            placement_finder<label_collision_detector4> finder(detector_);
746           
747            string_info info(text);
748           
749            faces->get_string_info(info);
750            unsigned num_geom = feature.num_geometries();
751            for (unsigned i=0;i<num_geom;++i)
752            {
753               geometry2d const& geom = feature.get_geometry(i);
754               if (geom.num_points() > 0) // don't bother with empty geometries
755               {
756                  path_type path(t_,geom,prj_trans);
757                  placement text_placement(info,sym); 
758                  text_placement.avoid_edges = sym.get_avoid_edges();
759                  if (sym.get_label_placement() == POINT_PLACEMENT) 
760                  {
761                     double label_x, label_y, z=0.0;
762                     geom.label_position(&label_x, &label_y);
763                     prj_trans.backward(label_x,label_y, z);
764                     t_.forward(&label_x,&label_y);
765                     finder.find_point_placement(text_placement,label_x,label_y);
766                     finder.update_detector(text_placement);
767                  }
768                  else //LINE_PLACEMENT
769                  {
770                     finder.find_line_placements<path_type>(text_placement,path);
771                  }
772                 
773                  for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii)
774                  {
775                     double x = text_placement.placements[ii].starting_x;
776                     double y = text_placement.placements[ii].starting_y;
777                     Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
778                     ren.render(x,y);
779                  }
780               }
781            } 
782         }
783         else
784         {
785            throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'");
786         }
787      }
788   }
789   template class agg_renderer<Image32>;
790}
Note: See TracBrowser for help on using the browser.