Changeset 704
- Timestamp:
- 06/29/08 06:58:48 (8 weeks ago)
- Location:
- trunk
- Files:
-
- 8 modified
-
include/mapnik/font_engine_freetype.hpp (modified) (12 diffs)
-
include/mapnik/map.hpp (modified) (2 diffs)
-
include/mapnik/text_symbolizer.hpp (modified) (4 diffs)
-
src/SConscript (modified) (1 diff)
-
src/agg_renderer.cpp (modified) (6 diffs)
-
src/load_map.cpp (modified) (9 diffs)
-
src/map.cpp (modified) (1 diff)
-
src/text_symbolizer.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/mapnik/font_engine_freetype.hpp
r702 r704 31 31 #include <mapnik/geometry.hpp> 32 32 #include <mapnik/text_path.hpp> 33 #include <mapnik/font_set.hpp> 33 34 34 35 // freetype2 … … 62 63 { 63 64 public: 64 typedef std::pair<unsigned,unsigned> dimension_t; 65 66 font_face(FT_Face face) 65 font_face(FT_Face face) 67 66 : face_(face) {} 68 67 … … 105 104 } 106 105 106 ~font_face() 107 { 108 #ifdef MAPNIK_DEBUG 109 std::clog << "~font_face: Clean up face \"" << family_name() 110 << " " << style_name() << "\"" << std::endl; 111 #endif 112 FT_Done_Face(face_); 113 } 114 115 private: 116 FT_Face face_; 117 }; 118 119 typedef boost::shared_ptr<font_face> face_ptr; 120 121 class MAPNIK_DECL freetype_engine // : public mapnik::singleton<freetype_engine,mapnik::CreateStatic>, 122 // private boost::noncopyable 123 { 124 // friend class mapnik::CreateStatic<freetype_engine>; 125 public: 126 static bool register_font(std::string const& file_name); 127 static std::vector<std::string> face_names (); 128 face_ptr create_face(std::string const& family_name); 129 virtual ~freetype_engine(); 130 freetype_engine(); 131 private: 132 FT_Library library_; 133 static boost::mutex mutex_; 134 static std::map<std::string,std::string> name2file_; 135 }; 136 137 template <typename T> 138 class MAPNIK_DECL face_manager : private boost::noncopyable 139 { 140 typedef T font_engine_type; 141 typedef std::map<std::string,face_ptr> faces; 142 143 public: 144 face_manager(T & engine) 145 : engine_(engine) {} 146 147 face_ptr get_face(std::string const& name) 148 { 149 typename faces::iterator itr; 150 itr = faces_.find(name); 151 if (itr != faces_.end()) 152 { 153 return itr->second; 154 } 155 else 156 { 157 face_ptr face = engine_.create_face(name); 158 if (face) 159 { 160 faces_.insert(make_pair(name,face)); 161 } 162 return face; 163 } 164 } 165 private: 166 faces faces_; 167 font_engine_type & engine_; 168 }; 169 170 template <typename T> 171 struct text_renderer : private boost::noncopyable 172 { 173 typedef std::pair<unsigned,unsigned> dimension_t; 174 175 struct glyph_t : boost::noncopyable 176 { 177 FT_Glyph image; 178 glyph_t(FT_Glyph image_) : image(image_) {} 179 ~glyph_t () { FT_Done_Glyph(image);} 180 }; 181 182 typedef boost::ptr_vector<glyph_t> glyphs_t; 183 typedef T pixmap_type; 184 185 text_renderer (pixmap_type & pixmap, std::vector<face_ptr> faces) 186 : pixmap_(pixmap), 187 faces_(faces), 188 fill_(0,0,0), 189 halo_fill_(255,255,255), 190 halo_radius_(0) {} 191 107 192 dimension_t character_dimensions(const unsigned c) 108 193 { … … 111 196 FT_Error error; 112 197 113 FT_GlyphSlot slot = face_->glyph;114 115 198 pen.x = 0; 116 199 pen.y = 0; … … 118 201 FT_BBox glyph_bbox; 119 202 FT_Glyph image; 120 203 204 FT_Face face = (*faces_.begin())->get_face(); 205 206 FT_UInt glyph_index = FT_Get_Char_Index(face, c); 207 208 // If there's no glyph_index we loop through the remaining fonts 209 // in the fontset looking for one. 210 if (!glyph_index) { 211 std::vector<face_ptr>::iterator itr = faces_.begin(); 212 std::vector<face_ptr>::iterator end = faces_.end(); 213 214 ++itr; // Skip the first one, we already tried it. 215 216 for (; itr != end; ++itr) 217 { 218 FT_Face f = (*itr)->get_face(); 219 220 glyph_index = FT_Get_Char_Index(f, c); 221 222 if (glyph_index) { 223 face = f; 224 break; 225 } 226 } 227 } 228 121 229 matrix.xx = (FT_Fixed)( 1 * 0x10000L ); 122 230 matrix.xy = (FT_Fixed)( 0 * 0x10000L ); 123 231 matrix.yx = (FT_Fixed)( 0 * 0x10000L ); 124 232 matrix.yy = (FT_Fixed)( 1 * 0x10000L ); 125 126 FT_Set_Transform (face_,&matrix,&pen); 127 128 FT_UInt glyph_index = FT_Get_Char_Index( face_, c); 129 130 error = FT_Load_Glyph (face_,glyph_index,FT_LOAD_NO_HINTING); 233 234 FT_Set_Transform(face, &matrix, &pen); 235 236 error = FT_Load_Glyph (face, glyph_index, FT_LOAD_NO_HINTING); 131 237 if ( error ) 132 238 return dimension_t(0, 0); 133 239 134 error = FT_Get_Glyph( face_->glyph, &image);240 error = FT_Get_Glyph(face->glyph, &image); 135 241 if ( error ) 136 242 return dimension_t(0, 0); 137 138 FT_Glyph_Get_CBox(image,ft_glyph_bbox_pixels, &glyph_bbox); 139 FT_Done_Glyph(image); 140 return dimension_t(slot->advance.x >> 6, glyph_bbox.yMax - glyph_bbox.yMin); 243 244 FT_Glyph_Get_CBox(image, ft_glyph_bbox_pixels, &glyph_bbox); 245 FT_Done_Glyph(image); 246 247 unsigned tempx = face->glyph->advance.x >> 6; 248 unsigned tempy = glyph_bbox.yMax - glyph_bbox.yMin; 249 250 //std::clog << "glyph: " << glyph_index << " x: " << tempx << " y: " << tempy << std::endl; 251 252 return dimension_t(tempx, tempy); 141 253 } 142 254 … … 188 300 if ( *arabic.getBuffer() >= 0x0600 && *arabic.getBuffer() <= 0x06ff) 189 301 { 190 191 302 UnicodeString shaped; 192 303 u_shapeArabic(arabic.getBuffer(),arabic.length(),shaped.getBuffer(arabic.length()),arabic.length(), … … 216 327 info.set_dimensions(width, height); 217 328 } 218 219 ~font_face() 220 { 221 #ifdef MAPNIK_DEBUG 222 std::clog << "clean up face:" << family_name()<<":" << style_name() << std::endl; 223 #endif 224 FT_Done_Face(face_); 225 } 226 227 private: 228 FT_Face face_; 229 }; 230 231 typedef boost::shared_ptr<font_face> face_ptr; 232 class MAPNIK_DECL freetype_engine // : public mapnik::singleton<freetype_engine,mapnik::CreateStatic>, 233 // private boost::noncopyable 234 { 235 // friend class mapnik::CreateStatic<freetype_engine>; 236 public: 237 static bool register_font(std::string const& file_name); 238 static std::vector<std::string> face_names (); 239 face_ptr create_face(std::string const& family_name); 240 virtual ~freetype_engine(); 241 freetype_engine(); 242 private: 243 FT_Library library_; 244 static boost::mutex mutex_; 245 static std::map<std::string,std::string> name2file_; 246 }; 247 248 template <typename T> 249 class MAPNIK_DECL face_manager : private boost::noncopyable 250 { 251 typedef T font_engine_type; 252 typedef std::map<std::string,face_ptr> faces; 253 254 public: 255 face_manager(T & engine) 256 : engine_(engine) {} 257 258 face_ptr get_face(std::string const& name) 259 { 260 typename faces::iterator itr; 261 itr = faces_.find(name); 262 if (itr != faces_.end()) 263 { 264 return itr->second; 265 } 266 else 267 { 268 face_ptr face = engine_.create_face(name); 269 if (face) 270 { 271 faces_.insert(make_pair(name,face)); 272 } 273 return face; 274 } 275 } 276 private: 277 faces faces_; 278 font_engine_type & engine_; 279 }; 280 281 template <typename T> 282 struct text_renderer : private boost::noncopyable 283 { 284 struct glyph_t : boost::noncopyable 285 { 286 FT_Glyph image; 287 glyph_t(FT_Glyph image_) : image(image_) {} 288 ~glyph_t () { FT_Done_Glyph(image);} 289 }; 290 291 typedef boost::ptr_vector<glyph_t> glyphs_t; 292 typedef T pixmap_type; 293 294 text_renderer (pixmap_type & pixmap, face_ptr face) 295 : pixmap_(pixmap), 296 face_(face), 297 fill_(0,0,0), 298 halo_fill_(255,255,255), 299 halo_radius_(0) {} 300 329 301 330 void set_pixel_size(unsigned size) 302 331 { 303 face_->set_pixel_sizes(size); 332 std::vector<face_ptr>::iterator itr = faces_.begin(); 333 std::vector<face_ptr>::iterator end = faces_.end(); 334 for (; itr != end; ++itr) 335 { 336 (*itr)->set_pixel_sizes(size); 337 } 304 338 } 305 339 … … 327 361 FT_Vector pen; 328 362 FT_Error error; 329 330 FT_Face face = face_->get_face(); 331 // FT_GlyphSlot slot = face->glyph; 332 363 333 364 FT_BBox bbox; 334 bbox.xMin = bbox.yMin = 32000; 335 bbox.xMax = bbox.yMax = -32000; //hmm?? 336 365 bbox.xMin = bbox.yMin = 32000; // Initialize these so we can tell if we 366 bbox.xMax = bbox.yMax = -32000; // properly grew the bbox later 367 368 std::vector<face_ptr>::iterator end = faces_.end(); 369 337 370 for (int i = 0; i < path->num_nodes(); i++) 338 371 { 339 372 int c; 340 373 double x, y, angle; 341 374 342 375 path->vertex(&c, &x, &y, &angle); 343 // std::clog << " prepare_glyph: " << (unsigned char)c << "," << x << "," << y << "," << angle << std::endl; 344 376 377 #ifdef MAPNIK_DEBUG 378 // TODO Enable when we have support for setting verbosity 379 //std::clog << "prepare_glyphs: " << c << "," << x << 380 // "," << y << "," << angle << std::endl; 381 #endif 345 382 346 383 FT_BBox glyph_bbox; … … 350 387 pen.y = int(y * 64); 351 388 389 FT_Face face = (*faces_.begin())->get_face(); 390 391 FT_UInt glyph_index = FT_Get_Char_Index(face, unsigned(c)); 392 393 // If there's no glyph_index we loop through the remaining fonts 394 // in the fontset looking for one. 395 if (!glyph_index) { 396 std::vector<face_ptr>::iterator itr = faces_.begin(); 397 ++itr; // Skip the first one, we already tried it. 398 399 for (; itr != end; ++itr) 400 { 401 #ifdef MAPNIK_DEBUG 402 // TODO Enable when we have support for setting verbosity 403 //std::clog << "prepare_glyphs: Falling back to font named \"" 404 // << (*itr)->family_name() << " " << (*itr)->style_name() 405 // << "\"" << std::endl; 406 #endif 407 408 FT_Face f = (*itr)->get_face(); 409 410 glyph_index = FT_Get_Char_Index(f, unsigned(c)); 411 412 if (glyph_index) { 413 face = f; 414 break; 415 } 416 } 417 418 #ifdef MAPNIK_DEBUG 419 // TODO Enable when we have support for setting verbosity 420 //if (!glyph_index) { 421 // std::clog << "prepare_glyphs: Failed to fall back, glyph " 422 // << c << " not found in any font." << std::endl; 423 //} 424 #endif 425 } 426 352 427 matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L ); 353 428 matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L ); 354 429 matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L ); 355 430 matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L ); 356 357 FT_Set_Transform (face,&matrix,&pen); 358 359 FT_UInt glyph_index = FT_Get_Char_Index( face, unsigned(c)); 360 361 error = FT_Load_Glyph (face,glyph_index, FT_LOAD_NO_HINTING); 431 432 FT_Set_Transform(face, &matrix, &pen); 433 434 error = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_HINTING); 362 435 if ( error ) 363 436 continue; 364 365 error = FT_Get_Glyph( face->glyph, &image);437 438 error = FT_Get_Glyph(face->glyph, &image); 366 439 if ( error ) 367 440 continue; 368 441 369 442 FT_Glyph_Get_CBox(image,ft_glyph_bbox_pixels, &glyph_bbox); 370 443 if (glyph_bbox.xMin < bbox.xMin) … … 376 449 if (glyph_bbox.yMax > bbox.yMax) 377 450 bbox.yMax = glyph_bbox.yMax; 378 451 452 // Check if we properly grew the bbox 379 453 if ( bbox.xMin > bbox.xMax ) 380 454 { … … 485 559 486 560 pixmap_type & pixmap_; 487 face_ptr face_;561 std::vector<face_ptr> faces_; 488 562 mapnik::Color fill_; 489 563 mapnik::Color halo_fill_; … … 495 569 } 496 570 497 498 571 #endif // FONT_ENGINE_FREETYPE_HPP -
trunk/include/mapnik/map.hpp
r702 r704 45 45 boost::optional<Color> background_; 46 46 std::map<std::string,feature_type_style> styles_; 47 std::map<std::string,FontSet> fontsets_; 47 48 std::vector<Layer> layers_; 48 49 Envelope<double> currentExtent_; … … 129 130 */ 130 131 feature_type_style const& find_style(std::string const& name) const; 132 133 /*! \brief Insert a fontset into the map. 134 * @param name The name of the fontset. 135 * @param style The fontset to insert. 136 * @return true If success. 137 * @return false If failure. 138 */ 139 bool insert_fontset(std::string const& name, FontSet const& fontset); 140 141 /*! \brief Find a fontset. 142 * @param name The name of the fontset. 143 * @return The fontset if found. If not found return the default map fontset. 144 */ 145 FontSet const& find_fontset(std::string const& name) const; 131 146 132 147 /*! \brief Get number of all layers. -
trunk/include/mapnik/text_symbolizer.hpp
r702 r704 28 28 #include <mapnik/enumeration.hpp> 29 29 #include <mapnik/color.hpp> 30 #include <mapnik/graphics.hpp> 30 #include <mapnik/font_set.hpp> 31 #include <mapnik/graphics.hpp> 31 32 // boost 32 33 #include <boost/tuple/tuple.hpp> … … 50 51 text_symbolizer(std::string const& name,std::string const& face_name, 51 52 unsigned size, Color const& fill); 53 text_symbolizer(std::string const& name, unsigned size, Color const& fill); 52 54 text_symbolizer(text_symbolizer const& rhs); 53 55 text_symbolizer& operator=(text_symbolizer const& rhs); … … 67 69 unsigned get_text_size() const; 68 70 std::string const& get_face_name() const; 71 void set_face_name(std::string face_name); 72 FontSet const& get_fontset() const; 73 void set_fontset(FontSet fontset); 69 74 Color const& get_fill() const; 70 75 void set_halo_fill(Color const& fill); … … 87 92 std::string name_; 88 93 std::string face_name_; 94 FontSet fontset_; 89 95 unsigned size_; 90 96 unsigned text_ratio_; -
trunk/src/SConscript
r702 r704 48 48 filter_factory.cpp 49 49 font_engine_freetype.cpp 50 font_set.cpp 50 51 graphics.cpp 51 52 image_reader.cpp -
trunk/src/agg_renderer.cpp
r703 r704 30 30 #include <mapnik/arrow.hpp> 31 31 #include <mapnik/config_error.hpp> 32 #include <mapnik/font_set.hpp> 32 33 33 34 // agg … … 281 282 frame->move_to(itr->get<0>(),itr->get<1>()); 282 283 frame->line_to(itr->get<0>(),itr->get<1>()+height); 283 284 284 } 285 285 … … 311 311 ren.color(agg::rgba8(r, g, b, int(255 * sym.get_opacity()))); 312 312 agg::render_scanlines(*ras_ptr, sl, ren); 313 314 313 } 315 314 } … … 461 460 if (text.length() > 0 && data) 462 461 { 463 face_ptr face = font_manager_.get_face(sym.get_face_name()); 464 if (face) 465 { 466 text_renderer<mapnik::Image32> ren(pixmap_,face); 462 std::vector<face_ptr> faces; 463 464 faces.push_back(font_manager_.get_face(sym.get_face_name())); 465 466 if (faces.size() > 0) 467 { 468 text_renderer<mapnik::Image32> ren(pixmap_, faces); 469 467 470 ren.set_pixel_size(sym.get_text_size()); 468 471 ren.set_fill(sym.get_fill()); 469 472 470 473 string_info info(text); 471 face->get_string_info(info); 474 475 ren.get_string_info(info); 472 476 473 477 placement_finder<label_collision_detector4> finder(detector_); … … 670 674 if ( text.length() > 0 ) 671 675 { 672 Color const& fill = sym.get_fill(); 673 face_ptr face = font_manager_.get_face(sym.get_face_name()); 674 if (face) 675 { 676 text_renderer<mapnik::Image32> ren(pixmap_,face); 676 Color const& fill = sym.get_fill(); 677 678 std::vector<face_ptr> faces; 679 680 FontSet fontset = sym.get_fontset(); 681 std::vector<std::string> face_names = fontset.get_face_names(); 682 683 if (face_names.size() > 0) 684 { 685 std::vector<std::string>::iterator itr = face_names.begin(); 686 std::vector<std::string>::iterator end = face_names.end(); 687 688 for (; itr != end; ++itr) 689 { 690 faces.push_back(font_manager_.get_face(*itr)); 691 } 692 } 693 else 694 { 695 faces.push_back(font_manager_.get_face(sym.get_face_name())); 696 } 697 698 if (faces.size() > 0) 699 { 700 text_renderer<mapnik::Image32> ren(pixmap_, faces); 677 701 ren.set_pixel_size(sym.get_text_size()); 678 702 ren.set_fill(fill); … … 683 707 684 708 string_info info(text); 685 face->get_string_info(info); 709 710 ren.get_string_info(info); 686 711 unsigned num_geom = feature.num_geometries(); 687 712 for (unsigned i=0;i<num_geom;++i) -
trunk/src/load_map.cpp
r703 r704 30 30 #include <mapnik/datasource_cache.hpp> 31 31 #include <mapnik/font_engine_freetype.hpp> 32 #include <mapnik/font_set.hpp> 32 33 33 34 #include <mapnik/ptree_helpers.hpp> … … 67 68 void parse_style( Map & map, ptree const & sty); 68 69 void parse_layer( Map & map, ptree const & lay); 69 70 71 void parse_fontset(Map & map, ptree const & fset); 72 void parse_font(FontSet & fset, ptree const & f); 73 70 74 void parse_rule( feature_type_style & style, ptree const & r); 71 75 … … 80 84 void parse_markers_symbolizer( rule_type & rule, ptree const & sym ); 81 85 82 void ensure_font_face( const text_symbolizer & text_symbol);86 void ensure_font_face( const std::string & face_name ); 83 87 84 88 bool strict_; … … 87 91 face_manager<freetype_engine> font_manager_; 88 92 std::map<std::string,std::string> file_sources_; 93 std::map<std::string,FontSet> fontsets_; 89 94 }; 90 95 … … 143 148 else if (v.first == "Layer") 144 149 { 145 146 150 parse_layer(map, v.second ); 151 } 152 else if (v.first == "FontSet") 153 { 154 parse_fontset(map, v.second); 147 155 } 148 156 else if (v.first == "FileSource") … … 227 235 } 228 236 } 237 238 void map_parser::parse_fontset( Map & map, ptree const & fset ) 239 { 240 string name("<missing name>"); 241 try 242
