diff --git a/include/mapnik/text/renderer.hpp b/include/mapnik/text/renderer.hpp index 18c1e31bb..e2d5ef79b 100644 --- a/include/mapnik/text/renderer.hpp +++ b/include/mapnik/text/renderer.hpp @@ -22,21 +22,37 @@ extern "C" namespace mapnik { template -struct text_renderer : private boost::noncopyable -{ typedef T pixmap_type; +class text_renderer : private boost::noncopyable +{ +public: + typedef T pixmap_type; - text_renderer (pixmap_type & pixmap, face_manager &font_manager_, stroker & s, composite_mode_e comp_op = src_over); + text_renderer (pixmap_type & pixmap, face_manager &font_manager_, composite_mode_e comp_op = src_over); void render(glyph_positions_ptr pos); void render_id(int feature_id, pixel_position pos, double min_radius=1.0); - private: void render_bitmap(FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity); void render_bitmap_id(FT_Bitmap *bitmap,int feature_id,int x,int y); + struct glyph_t : boost::noncopyable + { + FT_Glyph image; + char_properties_ptr properties; + + glyph_t(FT_Glyph image_, char_properties_ptr properties_) + : image(image_), properties(properties_) {} + + ~glyph_t () { FT_Done_Glyph(image);} + + }; + + void prepare_glyphs(glyph_positions_ptr pos); + pixmap_type & pixmap_; face_manager &font_manager_; stroker & stroker_; composite_mode_e comp_op_; + boost::ptr_vector glyphs_; }; } #endif // RENDERER_HPP diff --git a/src/text/renderer.cpp b/src/text/renderer.cpp index a3a9e5e63..1da94b1cc 100644 --- a/src/text/renderer.cpp +++ b/src/text/renderer.cpp @@ -1,20 +1,21 @@ #include #include #include +#include namespace mapnik { template -text_renderer::text_renderer (pixmap_type & pixmap, face_manager &font_manager_, stroker & s, composite_mode_e comp_op) +text_renderer::text_renderer (pixmap_type & pixmap, face_manager &font_manager_, composite_mode_e comp_op) : pixmap_(pixmap), font_manager_(font_manager_), - stroker_(s), + stroker_(*(font_manager_.get_stroker())), comp_op_(comp_op) {} -#if 0 + template -box2d text_renderer::prepare_glyphs(text_path *path) +void text_renderer::prepare_glyphs(glyph_positions_ptr pos) { //clear glyphs glyphs_.clear(); @@ -23,74 +24,61 @@ box2d text_renderer::prepare_glyphs(text_path *path) FT_Vector pen; FT_Error error; - FT_BBox bbox; - bbox.xMin = bbox.yMin = 32000; // Initialize these so we can tell if we - bbox.xMax = bbox.yMax = -32000; // properly grew the bbox later - - for (int i = 0; i < path->num_nodes(); i++) + pos->rewind(); + bool constant_angle = pos->is_constant_angle(); + if (constant_angle) { - char_info_ptr c; - double x, y, angle; - - path->vertex(&c, &x, &y, &angle); - - // TODO Enable when we have support for setting verbosity - // MAPNIK_LOG_DEBUG(font_engine_freetype) << "text_renderer: prepare_glyphs=" - // << c << "," << x << "," << y << "," << angle; - - FT_BBox glyph_bbox; - FT_Glyph image; - - pen.x = int(x * 64); - pen.y = int(y * 64); - - face_set_ptr faces = font_manager_.get_face_set(c->format->face_name, c->format->fontset); - faces->set_character_sizes(c->format->text_size); - - glyph_ptr glyph = faces->get_glyph(unsigned(c->c)); - FT_Face face = glyph->get_face()->get_face(); - - matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L ); - matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L ); - matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L ); - matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L ); - - FT_Set_Transform(face, &matrix, &pen); - - error = FT_Load_Glyph(face, glyph->get_index(), FT_LOAD_NO_HINTING); - if ( error ) - continue; - - error = FT_Get_Glyph(face->glyph, &image); - if ( error ) - continue; - - FT_Glyph_Get_CBox(image,ft_glyph_bbox_pixels, &glyph_bbox); - if (glyph_bbox.xMin < bbox.xMin) - bbox.xMin = glyph_bbox.xMin; - if (glyph_bbox.yMin < bbox.yMin) - bbox.yMin = glyph_bbox.yMin; - if (glyph_bbox.xMax > bbox.xMax) - bbox.xMax = glyph_bbox.xMax; - if (glyph_bbox.yMax > bbox.yMax) - bbox.yMax = glyph_bbox.yMax; - - // Check if we properly grew the bbox - if ( bbox.xMin > bbox.xMax ) + double angle = pos->get_angle(); + double cosa = cos(angle); + double sina = sin(angle); + matrix.xx = (FT_Fixed)( cosa * 0x10000L); + matrix.xy = (FT_Fixed)(-sina * 0x10000L); + matrix.yx = (FT_Fixed)( sina * 0x10000L); + matrix.yy = (FT_Fixed)( cosa * 0x10000L); + } + float text_size = 0; + while (pos->next()) + { + char_properties_ptr format = pos->get_format(); + if (format) { - bbox.xMin = 0; - bbox.yMin = 0; - bbox.xMax = 0; - bbox.yMax = 0; + //Only update parameters when format has changed. + text_size = format->text_size; } - // take ownership of the glyph - glyphs_.push_back(new glyph_t(image, c->format)); - } - return box2d(bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax); + pixel_position p = pos->get_position(); + pen.x = int(p.x * 64); + pen.y = int(p.y * 64); + + glyph_info const& glyph = pos->get_glyph(); + glyph.face->set_character_sizes(text_size); //TODO: Optimize this? + + if (!constant_angle) + { + double angle = pos->get_angle(); + double cosa = cos(angle); + double sina = sin(angle); + matrix.xx = (FT_Fixed)( cosa * 0x10000L); + matrix.xy = (FT_Fixed)(-sina * 0x10000L); + matrix.yx = (FT_Fixed)( sina * 0x10000L); + matrix.yy = (FT_Fixed)( cosa * 0x10000L); + } + + FT_Face face = glyph.face->get_face(); + FT_Set_Transform(face, &matrix, &pen); + + error = FT_Load_Glyph(face, glyph.glyph_index, FT_LOAD_NO_HINTING); + if (error) continue; + + FT_Glyph image; + error = FT_Get_Glyph(face->glyph, &image); + if (error) continue; + + // take ownership of the glyph + glyphs_.push_back(new glyph_t(image, format)); + } } -#endif template void composite_bitmap(T & pixmap, FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity, composite_mode_e comp_op) @@ -242,6 +230,8 @@ void text_renderer::render_bitmap_id(FT_Bitmap *bitmap,int feature_id,int x,i #endif } + + template void text_renderer::render_bitmap(FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity) { @@ -264,10 +254,10 @@ void text_renderer::render_bitmap(FT_Bitmap *bitmap, unsigned rgba, int x, in #endif } -template void text_renderer::render(glyph_positions_ptr); -template text_renderer::text_renderer(image_32&, face_manager&, stroker&, composite_mode_e); +template class text_renderer; //::render(glyph_positions_ptr); +//template text_renderer::text_renderer(image_32&, face_manager&, stroker&, composite_mode_e); -template void text_renderer::render_id(int, pixel_position, double ); -template text_renderer::text_renderer(grid&, face_manager&, stroker&, composite_mode_e); +template class text_renderer; //::render_id(int, pixel_position, double ); +//template text_renderer::text_renderer(grid&, face_manager&, stroker&, composite_mode_e); }