static boost::python::tuple
    getinitargs(const shield_symbolizer& s)
    {
        std::string filename = path_processor_type::to_string(*s.get_filename());
        //(name, font name, font size, font color, image file, image type, width, height)
        return boost::python::make_tuple( "TODO",//s.get_name(),
                                          s.get_face_name(),s.get_text_size(),s.get_fill(),filename,guess_type(filename));

    }
void  grid_renderer<T>::process(shield_symbolizer const& sym,
                                mapnik::feature_impl & feature,
                                proj_transform const& prj_trans)
{
    shield_symbolizer_helper<face_manager<freetype_engine>,
        label_collision_detector4> helper(
            sym, feature, prj_trans,
            width_, height_,
            scale_factor_,
            t_, font_manager_, *detector_,
            query_extent_);
    bool placement_found = false;

    text_renderer<T> ren(pixmap_,
                         font_manager_,
                         sym.get_halo_rasterizer(),
                         sym.comp_op(),
                         scale_factor_);

    text_placement_info_ptr placement;
    while (helper.next())
    {
        placement_found = true;
        placements_type const& placements = helper.placements();
        for (unsigned int ii = 0; ii < placements.size(); ++ii)
        {
            // get_marker_position returns (minx,miny) corner position,
            // while (currently only) agg_renderer::render_marker newly
            // expects center position;
            // until all renderers and shield_symbolizer_helper are
            // modified accordingly, we must adjust the position here
            pixel_position pos = helper.get_marker_position(placements[ii]);
            pos.x += 0.5 * helper.get_marker_width();
            pos.y += 0.5 * helper.get_marker_height();
            render_marker(feature,
                          pixmap_.get_resolution(),
                          pos,
                          helper.get_marker(),
                          helper.get_image_transform(),
                          sym.get_opacity(),
                          sym.comp_op());

            ren.prepare_glyphs(placements[ii]);
            ren.render_id(feature.id(), placements[ii].center);
        }
    }
    if (placement_found)
        pixmap_.add_feature(feature);
}
void  grid_renderer<T>::process(shield_symbolizer const& sym,
                                mapnik::feature_ptr const& feature,
                                proj_transform const& prj_trans)
{
    box2d<double> query_extent;
    shield_symbolizer_helper<face_manager<freetype_engine>,
        label_collision_detector4> helper(
            sym, *feature, prj_trans,
            width_, height_,
            scale_factor_,
            t_, font_manager_, detector_, query_extent);

    bool placement_found = false;

    text_renderer<T> ren(pixmap_, font_manager_, *(font_manager_.get_stroker()));

    text_placement_info_ptr placement;
    while (helper.next()) {
        placement_found = true;
        placements_type &placements = helper.placements();
        for (unsigned int ii = 0; ii < placements.size(); ++ii)
        {
            render_marker(feature, pixmap_.get_resolution(),
                          helper.get_marker_position(placements[ii]),
                          helper.get_marker(), helper.get_transform(),
                          sym.get_opacity());

            ren.prepare_glyphs(&(placements[ii]));
            ren.render_id(feature->id(), placements[ii].center, 2);
        }
    }
    if (placement_found)
        pixmap_.add_feature(feature);
}
    // TODO add lots more...
    static void
    setstate (shield_symbolizer& s, boost::python::tuple state)
    {
        using namespace boost::python;
        /*if (len(state) != 1)
          {
          PyErr_SetObject(PyExc_ValueError,
          ("expected 1-item tuple in call to __setstate__; got %s"
          % state).ptr()
          );
          throw_error_already_set();
          }*/

        s.set_halo_fill(extract<color>(state[0]));
        s.set_halo_radius(extract<float>(state[1]));

    }
Example #5
0
    void operator () (shield_symbolizer const& sym)
    {
        expression_set::const_iterator it;
        expression_set expressions;
        sym.get_placement_options()->add_expressions(expressions);
        for (it=expressions.begin(); it != expressions.end(); it++)
        {
            if (*it) boost::apply_visitor(f_attr, **it);
        }

        path_expression_ptr const& filename_expr = sym.get_filename();
        if (filename_expr)
        {
            path_processor_type::collect_attributes(*filename_expr,names_);
        }
        collect_transform(sym.get_image_transform());
        collect_transform(sym.get_transform());
    }
void  agg_renderer<T>::process(shield_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    shield_symbolizer_helper<face_manager<freetype_engine>,
        label_collision_detector4> helper(
            sym, feature, prj_trans,
            width_, height_,
            scale_factor_,
            t_, font_manager_, *detector_, query_extent_);

    text_renderer<T> ren(*current_buffer_, font_manager_, *(font_manager_.get_stroker()));

    while (helper.next()) {
        placements_type &placements = helper.placements();
        for (unsigned int ii = 0; ii < placements.size(); ++ii)
        {
            // get_marker_position returns (minx,miny) corner position,
            // while (currently only) agg_renderer::render_marker newly
            // expects center position;
            // until all renderers and shield_symbolizer_helper are
            // modified accordingly, we must adjust the position here
            pixel_position pos = helper.get_marker_position(placements[ii]);
            pos.x += 0.5 * helper.get_marker_width();
            pos.y += 0.5 * helper.get_marker_height();
            render_marker(pos,
                          helper.get_marker(),
                          helper.get_image_transform(),
                          sym.get_opacity(),
                          sym.comp_op());

            ren.prepare_glyphs(&(placements[ii]));
            ren.render(placements[ii].center);
        }
    }
}
void  agg_renderer<T>::process(shield_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{


    for (std::list<feature_ptr>::iterator f = featureList_->begin(); f != featureList_->end(); f++) {
        feature_ptr featurePtr = *f;

    shield_symbolizer_helper<face_manager<freetype_engine>,
        label_collision_detector4> helper(
            sym, *featurePtr, prj_trans,
            width_, height_,
            scale_factor_,
            t_, font_manager_, *detector_,
            query_extent_);

    text_renderer<T> ren(*current_buffer_,
                         font_manager_,
                         *(font_manager_.get_stroker()),
                         sym.comp_op(),
                         scale_factor_);

    while (helper.next())
    {
        placements_type const& placements = helper.placements();
        for (unsigned int ii = 0; ii < placements.size(); ++ii)
        {
            // get_marker_position returns (minx,miny) corner position,
            // while (currently only) agg_renderer::render_marker newly
            // expects center position;
            // until all renderers and shield_symbolizer_helper are
            // modified accordingly, we must adjust the position here
             pixel_position pos = helper.get_marker_position(placements[ii]);
            // pos.x += 0.5 * helper.get_marker_width();
            // pos.y += 0.5 * helper.get_marker_height();
            // render_marker(pos,
            //               helper.get_marker(),
            //               helper.get_image_transform(),
            //               sym.get_opacity(),
            //               sym.comp_op());


          marker const& marker_ = helper.get_marker();

          image_data_32 const& src = **marker_.get_bitmap_data();
          double width =  src.width();
          double height =  src.height();

          const double shifted = 0;
          double markerX = pos.x + shifted, markerY = height_ - pos.y - shifted - height;



  glMatrixLoadIdentityEXT(GL_PROJECTION);
  glMatrixOrthoEXT(GL_PROJECTION, 0, width_, height_, 0, -1, 1);
  glMatrixLoadIdentityEXT(GL_MODELVIEW);


  GLubyte cmd[5];  
  GLfloat coord[8];
  int m = 0, n = 0;


  cmd[m++] = GL_MOVE_TO_NV;
  coord[n++] = markerX;
  coord[n++] = markerY;
  cmd[m++] = GL_LINE_TO_NV;
  coord[n++] = markerX + width;
  coord[n++] = markerY;
  cmd[m++] = GL_LINE_TO_NV;
  coord[n++] = markerX + width;
  coord[n++] = markerY + height;
  cmd[m++] = GL_LINE_TO_NV;
  coord[n++] = markerX;
  coord[n++] = markerY + height;
  cmd[m++] = GL_CLOSE_PATH_NV;

  glPathCommandsNV(pathObject_, m, cmd, n, GL_FLOAT, coord);



  // glStencilFunc(GL_NOTEQUAL, 0, 0x1F);
  // glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);


  //makeFaceTexture(TEXTURE_FACE);
  static GLuint texName;
  glGenTextures(1, &texName);
  glBindTexture(GL_TEXTURE_2D, texName);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
    GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)src.getBytes());


  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);




  GLfloat data[2][3] = { { 1,0,0 },    /* s = 1*x + 0*y + 0 */
                         { 0,1,0 } };  /* t = 0*x + 1*y + 0 */

  //glEnable(GL_STENCIL_TEST);
  
    //glColor3f(1,1,1);
    glEnable(GL_TEXTURE_2D);
    glPathTexGenNV(GL_TEXTURE0, GL_PATH_OBJECT_BOUNDING_BOX_NV, 2, &data[0][0]);
    glStencilFillPathNV(pathObject_, GL_COUNT_UP_NV, 0x1F);
    glCoverFillPathNV(pathObject_, GL_BOUNDING_BOX_NV);
    glDisable(GL_TEXTURE_2D);

    pathObject_++;


            //Text rendering
            //ren.prepare_glyphs(placements[ii]);
            //ren.render(placements[ii].center);

             const int size = placements[ii].num_nodes();
            int strokeEnable = 0;
            char word[size]; 
            unsigned red,green,blue,alpha;
            double textWidth = 0;
            double textHeight = 0;
            color textColor,strokeColor;
            double opacity = 0.0;


             for (int i = 0; i < placements[ii].num_nodes(); i++)
            {
              char_info_ptr c;
              double x, y, angle;

             placements[ii].vertex(&c, &x, &y, &angle);
             word[i] = (char)c->c;
              textWidth += c->width;
            textHeight = c->height();

              double halo_radius = c->format->halo_radius;

                if (halo_radius > 0.0 && halo_radius < 1024.0){
                  strokeEnable = 1;
                  // red = c->format->halo_fill.red();
                  // green = c->format->halo_fill.green();
                  // blue = c->format->halo_fill.blue();
                  // alpha = c->format->halo_fill.alpha();
                  strokeColor = c->format->halo_fill;

                } 

               textColor = c->format->fill;
               opacity = c->format->text_opacity;
            }

           double posX = placements[ii].center.x, posY = placements[ii].center.y;

           int centerText = textWidth / 2;
           double posTextY = height_ - markerY - (height)/2;
           double posTextX = posX - centerText;

           if(posTextY <= height_ / 2) posTextY -= 5;
           if(posTextX >= width_ / 2) posTextX += 5;


           if(!strokeEnable){
            render_text(size, word, posTextX, posTextY,textColor, opacity);  
           }

           if(strokeEnable){
            render_text(size, word, posTextX, posTextY,textColor,strokeColor,opacity);  
           }




        }
    }

  }
}
 static  boost::python::tuple
 getstate(const shield_symbolizer& s)
 {
     return boost::python::make_tuple(s.get_halo_fill(),s.get_halo_radius());
 }
void  agg_renderer<T>::process(shield_symbolizer const& sym,
                               Feature const& feature,
                               proj_transform const& prj_trans)
{
    typedef  coord_transform2<CoordTransform,geometry_type> path_type;


    text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info();
    placement_options->next();
    placement_options->next_position_only();

    UnicodeString text;
    if( sym.get_no_text() )
        text = UnicodeString( " " );  // TODO: fix->use 'space' as the text to render
    else
    {
        expression_ptr name_expr = sym.get_name();
        if (!name_expr) return;
        value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*name_expr);
        text = result.to_unicode();
    }
    
    if ( sym.get_text_transform() == UPPERCASE)
    {
        text = text.toUpper();
    }
    else if ( sym.get_text_transform() == LOWERCASE)
    {
        text = text.toLower();
    }
    else if ( sym.get_text_transform() == CAPITALIZE)
    {
        text = text.toTitle(NULL);
    }
    
    agg::trans_affine tr;
    boost::array<double,6> const& m = sym.get_transform();
    tr.load_from(&m[0]);
    
    std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature);
    boost::optional<mapnik::marker_ptr> marker;
    if ( !filename.empty() )
    {
        marker = marker_cache::instance()->find(filename, true);
    }
    else
    {
        marker.reset(boost::make_shared<mapnik::marker>());
    }
    
    
    if (text.length() > 0 && marker)
    {
        int w = (*marker)->width();
        int h = (*marker)->height();
        
        double px0 = - 0.5 * w;
        double py0 = - 0.5 * h;
        double px1 = 0.5 * w;
        double py1 = 0.5 * h;
        double px2 = px1;
        double py2 = py0;
        double px3 = px0;
        double py3 = py1;
        tr.transform(&px0,&py0);
        tr.transform(&px1,&py1);
        tr.transform(&px2,&py2);
        tr.transform(&px3,&py3);
        box2d<double> label_ext (px0, py0, px1, py1);
        label_ext.expand_to_include(px2, py2);
        label_ext.expand_to_include(px3, py3);
        
        face_set_ptr faces;

        if (sym.get_fontset().size() > 0)
        {
            faces = font_manager_.get_face_set(sym.get_fontset());
        }
        else
        {
            faces = font_manager_.get_face_set(sym.get_face_name());
        }

        stroker_ptr strk = font_manager_.get_stroker();
        if (strk && faces->size() > 0)
        {
            text_renderer<T> ren(pixmap_, faces, *strk);

            ren.set_pixel_size(sym.get_text_size() * scale_factor_);
            ren.set_fill(sym.get_fill());
            ren.set_halo_fill(sym.get_halo_fill());
            ren.set_halo_radius(sym.get_halo_radius() * scale_factor_);
            ren.set_opacity(sym.get_text_opacity());

            placement_finder<label_collision_detector4> finder(detector_);

            string_info info(text);

            faces->get_string_info(info);

            metawriter_with_properties writer = sym.get_metawriter();

            for (unsigned i = 0; i < feature.num_geometries(); ++i)
            {
                geometry_type const& geom = feature.get_geometry(i);
                if (geom.num_points() > 0 )
                {
                    path_type path(t_,geom,prj_trans);

                    label_placement_enum how_placed = sym.get_label_placement();
                    if (how_placed == POINT_PLACEMENT || how_placed == VERTEX_PLACEMENT || how_placed == INTERIOR_PLACEMENT)
                    {
                        // for every vertex, try and place a shield/text
                        geom.rewind(0);
                        placement text_placement(info, sym, scale_factor_, w, h, false);
                        text_placement.avoid_edges = sym.get_avoid_edges();
                        text_placement.allow_overlap = sym.get_allow_overlap();
                        if (writer.first)
                            text_placement.collect_extents =true; // needed for inmem metawriter
                        position const& pos = sym.get_displacement();
                        position const& shield_pos = sym.get_shield_displacement();
                        for( unsigned jj = 0; jj < geom.num_points(); jj++ )
                        {
                            double label_x;
                            double label_y;
                            double z=0.0;

                            if( how_placed == VERTEX_PLACEMENT )
                                geom.vertex(&label_x,&label_y);  // by vertex
                            else if( how_placed == INTERIOR_PLACEMENT )
                                geom.label_interior_position(&label_x,&label_y);
                            else
                                geom.label_position(&label_x, &label_y);  // by middle of line or by point
                            prj_trans.backward(label_x,label_y, z);
                            t_.forward(&label_x,&label_y);

                            label_x += boost::get<0>(shield_pos);
                            label_y += boost::get<1>(shield_pos);

                            finder.find_point_placement( text_placement, placement_options,
                                                         label_x, label_y, 0.0,
                                                         sym.get_line_spacing(),
                                                         sym.get_character_spacing());

                            // check to see if image overlaps anything too, there is only ever 1 placement found for points and verticies
                            if( text_placement.placements.size() > 0)
                            {
                                double x = floor(text_placement.placements[0].starting_x);
                                double y = floor(text_placement.placements[0].starting_y);
                                int px;
                                int py;
                                
                                if( !sym.get_unlock_image() )
                                {
                                    // center image at text center position
                                    // remove displacement from image label
                                    double lx = x - boost::get<0>(pos);
                                    double ly = y - boost::get<1>(pos);
                                    px=int(floor(lx - (0.5 * w))) + 1;
                                    py=int(floor(ly - (0.5 * h))) + 1;
                                    label_ext.re_center(lx,ly);
                                }
                                else
                                {  // center image at reference location
                                    px=int(floor(label_x - 0.5 * w));
                                    py=int(floor(label_y - 0.5 * h));
                                    label_ext.re_center(label_x,label_y);
                                }
                                
                                if ( sym.get_allow_overlap() || detector_.has_placement(label_ext) )
                                {
                                    render_marker(px,py,**marker,tr,sym.get_opacity());

                                    box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[0]);
                                    ren.render(x,y);
                                    detector_.insert(label_ext);
                                    finder.update_detector(text_placement);
                                    if (writer.first) {
                                        writer.first->add_box(label_ext, feature, t_, writer.second);
                                        writer.first->add_text(text_placement, faces, feature, t_, writer.second);
                                    }
                                }
                            }
                        }
                    }

                    else if (geom.num_points() > 1 && how_placed == LINE_PLACEMENT)
                    {
                        placement text_placement(info, sym, scale_factor_, w, h, false);
                        position const& pos = sym.get_displacement();

                        text_placement.avoid_edges = sym.get_avoid_edges();
                        text_placement.additional_boxes.push_back(
                           box2d<double>(-0.5 * label_ext.width() - boost::get<0>(pos),
                                         -0.5 * label_ext.height() - boost::get<1>(pos),
                                         0.5 * label_ext.width() - boost::get<0>(pos),
                                         0.5 * label_ext.height() - boost::get<1>(pos)));
                        finder.find_point_placements<path_type>(text_placement, placement_options, path);

                        for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
                        {
                            double x = floor(text_placement.placements[ii].starting_x);
                            double y = floor(text_placement.placements[ii].starting_y);

                            double lx = x - boost::get<0>(pos);
                            double ly = y - boost::get<1>(pos);
                            int px=int(floor(lx - (0.5*w))) + 1;
                            int py=int(floor(ly - (0.5*h))) + 1;
                            label_ext.re_center(lx, ly);

                            render_marker(px,py,**marker,tr,sym.get_opacity());

                            box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
                            ren.render(x,y);
                            if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second);
                        }
                        finder.update_detector(text_placement);
                        if (writer.first) writer.first->add_text(text_placement, faces, feature, t_, writer.second);
                    }
                }
            }
        }
    }
}