From 99ab053558e5a3318fa5e61284b2bed502bfaf63 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 19 Jul 2013 16:14:10 +0100 Subject: [PATCH] + text rendering work-in-progress --- include/mapnik/processed_text.hpp | 17 +++-- include/mapnik/skia/skia_font_manager.hpp | 15 ++-- include/mapnik/skia/skia_renderer.hpp | 3 + include/mapnik/skia/skia_typeface_cache.hpp | 11 ++- src/build.py | 2 +- src/font_engine_freetype.cpp | 5 +- src/processed_text.cpp | 47 ------------- src/skia/skia_font_manager.cpp | 78 +++++++++++++++++++++ src/skia/skia_renderer.cpp | 30 +++++++- src/skia/skia_typeface_cache.cpp | 13 +++- 10 files changed, 154 insertions(+), 67 deletions(-) create mode 100644 src/skia/skia_font_manager.cpp diff --git a/include/mapnik/processed_text.hpp b/include/mapnik/processed_text.hpp index 647673a07..6589da0a8 100644 --- a/include/mapnik/processed_text.hpp +++ b/include/mapnik/processed_text.hpp @@ -68,7 +68,6 @@ public: for (; itr != end; ++itr) { char_properties const& p = itr->p; - std::cerr << p.face_name << " : " << p.fontset << std::endl; face_set_ptr faces = font_manager.get_face_set(p.face_name, p.fontset); if (faces->size() > 0) { @@ -90,19 +89,25 @@ public: char_properties const& p = itr->p; if (p.fontset) { - for (auto const& face_name : p.fontset->get_face_names()) + for (auto face_name : p.fontset->get_face_names()) { + face_name.erase(remove_if(face_name.begin(), face_name.end(), ::isspace), face_name.end()); + size_t pos = face_name.rfind("-"); + if (pos != std::string::npos) + { + face_name = face_name.substr(0,pos); + } std::cerr << face_name << std::endl; + manager.test(face_name, itr->str); } } - StringCharacterIterator iter(itr->str); for (iter.setToStart(); iter.hasNext();) { UChar ch = iter.nextPostInc(); - char_info char_dim(ch, 10, 12, 0, 12); + char_info char_dim(ch, p.text_size * scale_factor_, p.text_size * scale_factor_, 0, p.text_size * scale_factor_); char_dim.format = &(itr->p); - char_dim.avg_height = 12;//avg_height; + char_dim.avg_height = p.text_size * scale_factor_; info_.add_info(char_dim); } // char sizes ---> p.text_size * scale_factor_ @@ -112,7 +117,7 @@ public: return info_; } #endif - //string_info const& get_string_info(); + private: expression_list expr_list_; diff --git a/include/mapnik/skia/skia_font_manager.hpp b/include/mapnik/skia/skia_font_manager.hpp index 56b0f8226..7192933c5 100644 --- a/include/mapnik/skia/skia_font_manager.hpp +++ b/include/mapnik/skia/skia_font_manager.hpp @@ -27,16 +27,23 @@ #define MAPNIK_SKIA_FONT_MANAGER_HPP #include +#include + namespace mapnik { +class skia_typeface_cache; + class skia_font_manager { public: - void test() const - { - std::cerr << "skia_font_manager" << std::endl; - } + + skia_font_manager(skia_typeface_cache & cache) + : cache_(cache) {} + + void test(std::string const&, UnicodeString & ustr); +private: + skia_typeface_cache & cache_; }; } diff --git a/include/mapnik/skia/skia_renderer.hpp b/include/mapnik/skia/skia_renderer.hpp index 5ff3b9907..ef921210f 100644 --- a/include/mapnik/skia/skia_renderer.hpp +++ b/include/mapnik/skia/skia_renderer.hpp @@ -34,7 +34,9 @@ #include #include #include +#include #include + // skia fwd decl class SkCanvas; @@ -91,6 +93,7 @@ private: double scale_factor_; box2d query_extent_; skia_font_manager font_manager_; + skia_typeface_cache typeface_cache_; boost::shared_ptr detector_; }; diff --git a/include/mapnik/skia/skia_typeface_cache.hpp b/include/mapnik/skia/skia_typeface_cache.hpp index 0c2caa8b1..c6046dccc 100644 --- a/include/mapnik/skia/skia_typeface_cache.hpp +++ b/include/mapnik/skia/skia_typeface_cache.hpp @@ -26,7 +26,11 @@ #ifndef MAPNIK_SKIA_TYPEFACE_CACHE_HPP #define MAPNIK_SKIA_TYPEFACE_CACHE_HPP -#include +#ifdef MAPNIK_THREADSAFE +#include +#endif + +#include class SkTypeface; @@ -36,16 +40,17 @@ namespace mapnik class skia_typeface_cache { public: + typedef std::map cache_type; skia_typeface_cache(); ~skia_typeface_cache(); static bool register_font(std::string const& file_name); static bool register_fonts(std::string const& dir, bool recurse = false); - + SkTypeface * create(std::string const& family_name); private: #ifdef MAPNIK_THREADSAFE static boost::mutex mutex_; #endif - static std::map typefaces_; + static cache_type typefaces_; }; } diff --git a/src/build.py b/src/build.py index e5464076c..f702ecfae 100644 --- a/src/build.py +++ b/src/build.py @@ -263,7 +263,7 @@ if env['HAS_SKIA']: libmapnik_defines.append('-DHAVE_SKIA') source.insert(0,'skia/skia_renderer.cpp') source.insert(0,'skia/skia_typeface_cache.cpp') - + source.insert(0,'skia/skia_font_manager.cpp') if env['JPEG']: source += Split( diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index 7f66c62fd..6b2e75f70 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -114,7 +114,7 @@ bool freetype_engine::register_font(std::string const& file_name) // http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec if (face->family_name && face->style_name) { - std::string name = std::string(face->family_name) + " " + std::string(face->style_name); + std::string name = std::string(face->family_name) + "-" + std::string(face->style_name); // skip fonts with leading . in the name if (!boost::algorithm::starts_with(name,".")) { @@ -217,8 +217,7 @@ std::map > const& freetype_engine::get_ma face_ptr freetype_engine::create_face(std::string const& family_name) { - std::map >::const_iterator itr; - itr = name2file_.find(family_name); + std::map >::const_iterator itr = name2file_.find(family_name); if (itr != name2file_.end()) { FT_Face face; diff --git a/src/processed_text.cpp b/src/processed_text.cpp index 4ed4fba59..8a4644e43 100644 --- a/src/processed_text.cpp +++ b/src/processed_text.cpp @@ -51,51 +51,4 @@ void processed_text::clear() expr_list_.clear(); } -/* -string_info const& processed_text::get_string_info() -{ - info_.clear(); //if this function is called twice invalid results are returned, so clear string_info first - expression_list::iterator itr = expr_list_.begin(); - expression_list::iterator end = expr_list_.end(); - for (; itr != end; ++itr) - { - char_properties const &p = itr->p; - face_set_ptr faces = font_manager_.get_face_set(p.face_name, p.fontset); - if (faces->size() == 0) - { - if (p.fontset && !p.fontset->get_name().empty()) - { - if (p.fontset->size()) - { - if (!p.face_name.empty()) - { - throw config_error("Unable to find specified font face '" + p.face_name - + "' in font set: '" + p.fontset->get_name() + "'"); - } - else - { - throw config_error("No valid font face could be loaded for font set: '" + p.fontset->get_name() + "'"); - } - } - else - { - throw config_error("Font set '" + p.fontset->get_name() + "' does not contain any Font face-name entries"); - } - } - else if (!p.face_name.empty()) - { - throw config_error("Unable to find specified font face '" + p.face_name + "'"); - } - else - { - throw config_error("Both font set and face name are empty!"); - } - } - faces->set_character_sizes(p.text_size * scale_factor_); - faces->get_string_info(info_, itr->str, &(itr->p)); - info_.add_text(itr->str); - } - return info_; -} -*/ } //ns mapnik diff --git a/src/skia/skia_font_manager.cpp b/src/skia/skia_font_manager.cpp new file mode 100644 index 000000000..108bb99b7 --- /dev/null +++ b/src/skia/skia_font_manager.cpp @@ -0,0 +1,78 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include +#include +#include + +#include + +#include +#include + +namespace mapnik { + +void skia_font_manager::test(std::string const& family_name, UnicodeString & ustr) +{ + SkTypeface * typeface = cache_.create(family_name); +//SkTypeface * typeface = SkTypeface::CreateFromName(family_name.c_str(),SkTypeface::kNormal); + if (typeface) + { + std::cerr << "ustr.length()=" << ustr.length() << std::endl; + std::vector glyph_ids; + glyph_ids.resize(ustr.length()); + std::cerr << (char*)ustr.getTerminatedBuffer() << std::endl; + int num_ids = typeface->charsToGlyphs((void*)ustr.getTerminatedBuffer(), SkTypeface::kUTF16_Encoding, + &glyph_ids[0], glyph_ids.size()); + + std::cerr << "num_ids = " << num_ids << std::endl; + std::vector glyph_32_ids; + for (std::size_t i = 0; i < glyph_ids.size() ;++i) + { + glyph_32_ids.push_back(glyph_ids[i]); + } + //const uint32_t glyph_id = 0; +// SkAdvancedTypefaceMetrics * metrics = + // typeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo, &glyph_32_ids[0], glyph_32_ids.size()); + + + //auto const& advances = metrics->fGlyphWidths->fAdvance; + //std::cerr << "count = " << advances.count(); + //for ( unsigned j=0; j< num_ids; ++j) + //{ + // std::cerr << advances[j] << ","; + //} + //std::cerr << std::endl; + //for (size_t i = 0; i( box2d(-map.buffer_size(), -map.buffer_size(), map.width() + map.buffer_size(), map.height() + map.buffer_size()))) {} @@ -261,6 +262,31 @@ void skia_renderer::process(text_symbolizer const& sym, { double sx = placements[i].center.x; double sy = placements[i].center.y; + + placements[i].rewind(); +// halo + for (int j = 0; j < placements[i].num_nodes(); ++j) + { + char_info_ptr c; + double x, y, angle; + placements[i].vertex(c, x, y, angle); + SkPaint paint; + paint.setStyle(SkPaint::kStroke_Style); + paint.setAntiAlias(true); + double text_size = c->format->text_size * scale_factor_; + paint.setTextSize((SkScalar)text_size); + paint.setStrokeWidth(2.0 * c->format->halo_radius * scale_factor_); + paint.setStrokeJoin(SkPaint::kRound_Join); + color const& halo_fill = c->format->halo_fill; // !! + paint.setARGB(int(halo_fill.alpha() * c->format->text_opacity), halo_fill.red(), halo_fill.green(), halo_fill.blue()); + SkPoint pt = SkPoint::Make(0,0); + canvas_.save(); + canvas_.translate((SkScalar)(sx + x), (SkScalar)(sy - y)); + canvas_.rotate(-(SkScalar)180 * (angle/M_PI)); + canvas_.drawPosText(&(c->c),1, &pt, paint); + canvas_.restore(); + } +// text placements[i].rewind(); for (int j = 0; j < placements[i].num_nodes(); ++j) @@ -274,7 +300,7 @@ void skia_renderer::process(text_symbolizer const& sym, double text_size = c->format->text_size * scale_factor_; paint.setTextSize((SkScalar)text_size); color const& fill = c->format->fill; // !! - paint.setARGB(int(fill.alpha() * sym.get_text_opacity()), fill.red(), fill.green(), fill.blue()); + paint.setARGB(int(fill.alpha() * c->format->text_opacity), fill.red(), fill.green(), fill.blue()); SkPoint pt = SkPoint::Make(0,0); canvas_.save(); canvas_.translate((SkScalar)(sx + x), (SkScalar)(sy - y)); diff --git a/src/skia/skia_typeface_cache.cpp b/src/skia/skia_typeface_cache.cpp index 320f81d93..abea00a07 100644 --- a/src/skia/skia_typeface_cache.cpp +++ b/src/skia/skia_typeface_cache.cpp @@ -45,6 +45,17 @@ skia_typeface_cache::~skia_typeface_cache() { } + +SkTypeface * skia_typeface_cache::create(std::string const& family_name) +{ + cache_type::const_iterator itr = typefaces_.find(family_name); + if (itr != typefaces_.end()) + { + return itr->second; + } + return 0; +} + bool skia_typeface_cache::register_font(std::string const& file_name) { #ifdef MAPNIK_THREADSAFE @@ -117,6 +128,6 @@ bool skia_typeface_cache::register_fonts(std::string const& dir, bool recurse) #ifdef MAPNIK_THREADSAFE boost::mutex skia_typeface_cache::mutex_; #endif -std::map skia_typeface_cache::typefaces_; +skia_typeface_cache::cache_type skia_typeface_cache::typefaces_; }