| 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 | | |
| 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) {} |
| | 142 | |
| | 143 | font_face_set(void) |
| | 144 | : faces_() {} |
| | 145 | |
| | 146 | void add(face_ptr face) |
| | 147 | { |
| | 148 | faces_.push_back(face); |
| | 149 | } |
| | 150 | |
| | 151 | unsigned size() const |
| | 152 | { |
| | 153 | return faces_.size(); |
| | 154 | } |
| | 155 | |
| | 156 | glyph_ptr get_glyph(unsigned c) const |
| | 157 | { |
| | 158 | for (std::vector<face_ptr>::const_iterator face = faces_.begin(); face != faces_.end(); ++face) |
| | 159 | { |
| | 160 | FT_Face f = (*face)->get_face(); |
| | 161 | FT_UInt g = (*face)->get_char(c); |
| | 162 | |
| | 163 | if (g) return glyph_ptr(new font_glyph(f, g)); |
| | 164 | } |
| | 165 | |
| | 166 | return glyph_ptr(); |
| | 167 | } |
| 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 | | } |
| | 180 | |
| | 181 | glyph_ptr glyph = get_glyph(c); |
| | 182 | FT_Face face = glyph->get_face(); |
| | 285 | void set_pixel_sizes(unsigned size) |
| | 286 | { |
| | 287 | for (std::vector<face_ptr>::iterator face = faces_.begin(); face != faces_.end(); ++face) |
| | 288 | { |
| | 289 | (*face)->set_pixel_sizes(size); |
| | 290 | } |
| | 291 | } |
| | 292 | private: |
| | 293 | std::vector<face_ptr> faces_; |
| | 294 | }; |
| | 295 | |
| | 296 | typedef boost::shared_ptr<font_face_set> face_set_ptr; |
| | 297 | |
| | 298 | class MAPNIK_DECL freetype_engine // : public mapnik::singleton<freetype_engine,mapnik::CreateStatic>, |
| | 299 | // private boost::noncopyable |
| | 300 | { |
| | 301 | // friend class mapnik::CreateStatic<freetype_engine>; |
| | 302 | public: |
| | 303 | static bool register_font(std::string const& file_name); |
| | 304 | static std::vector<std::string> face_names (); |
| | 305 | face_ptr create_face(std::string const& family_name); |
| | 306 | virtual ~freetype_engine(); |
| | 307 | freetype_engine(); |
| | 308 | private: |
| | 309 | FT_Library library_; |
| | 310 | static boost::mutex mutex_; |
| | 311 | static std::map<std::string,std::string> name2file_; |
| | 312 | }; |
| | 313 | |
| | 314 | template <typename T> |
| | 315 | class MAPNIK_DECL face_manager : private boost::noncopyable |
| | 316 | { |
| | 317 | typedef T font_engine_type; |
| | 318 | typedef std::map<std::string,face_ptr> faces; |
| | 319 | |
| | 320 | public: |
| | 321 | face_manager(T & engine) |
| | 322 | : engine_(engine) {} |
| | 323 | |
| | 324 | face_ptr get_face(std::string const& name) |
| | 325 | { |
| | 326 | typename faces::iterator itr; |
| | 327 | itr = faces_.find(name); |
| | 328 | if (itr != faces_.end()) |
| | 329 | { |
| | 330 | return itr->second; |
| | 331 | } |
| | 332 | else |
| | 333 | { |
| | 334 | face_ptr face = engine_.create_face(name); |
| | 335 | if (face) |
| | 336 | { |
| | 337 | faces_.insert(make_pair(name,face)); |
| | 338 | } |
| | 339 | return face; |
| | 340 | } |
| | 341 | } |
| | 342 | |
| | 343 | face_set_ptr get_face_set(std::string const& name) |
| | 344 | { |
| | 345 | face_set_ptr face_set(new font_face_set); |
| | 346 | if (face_ptr face = get_face(name)) |
| | 347 | { |
| | 348 | face_set->add(face); |
| | 349 | } |
| | 350 | return face_set; |
| | 351 | } |
| | 352 | |
| | 353 | face_set_ptr get_face_set(FontSet const& fontset) |
| | 354 | { |
| | 355 | std::vector<std::string> const& names = fontset.get_face_names(); |
| | 356 | face_set_ptr face_set(new font_face_set); |
| | 357 | for (std::vector<std::string>::const_iterator name = names.begin(); name != names.end(); ++name) |
| | 358 | { |
| | 359 | if (face_ptr face = get_face(*name)) |
| | 360 | { |
| | 361 | face_set->add(face); |
| | 362 | } |
| | 363 | } |
| | 364 | return face_set; |
| | 365 | } |
| | 366 | private: |
| | 367 | faces faces_; |
| | 368 | font_engine_type & engine_; |
| | 369 | }; |
| | 370 | |
| | 371 | template <typename T> |
| | 372 | struct text_renderer : private boost::noncopyable |
| | 373 | { |
| | 374 | struct glyph_t : boost::noncopyable |
| | 375 | { |
| | 376 | FT_Glyph image; |
| | 377 | glyph_t(FT_Glyph image_) : image(image_) {} |
| | 378 | ~glyph_t () { FT_Done_Glyph(image);} |
| | 379 | }; |
| | 380 | |
| | 381 | typedef boost::ptr_vector<glyph_t> glyphs_t; |
| | 382 | typedef T pixmap_type; |
| | 383 | |
| | 384 | text_renderer (pixmap_type & pixmap, face_set_ptr faces) |
| | 385 | : pixmap_(pixmap), |
| | 386 | faces_(faces), |
| | 387 | fill_(0,0,0), |
| | 388 | halo_fill_(255,255,255), |
| | 389 | halo_radius_(0) {} |
| | 390 | |
| 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 | | } |
| | 442 | |
| | 443 | glyph_ptr glyph = faces_->get_glyph(unsigned(c)); |
| | 444 | FT_Face face = glyph->get_face(); |