+ text rendering work-in-progress

This commit is contained in:
artemp 2013-07-19 16:14:10 +01:00
parent acc14b9cc0
commit 99ab053558
10 changed files with 154 additions and 67 deletions

View file

@ -68,7 +68,6 @@ public:
for (; itr != end; ++itr) for (; itr != end; ++itr)
{ {
char_properties const& p = itr->p; 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); face_set_ptr faces = font_manager.get_face_set(p.face_name, p.fontset);
if (faces->size() > 0) if (faces->size() > 0)
{ {
@ -90,19 +89,25 @@ public:
char_properties const& p = itr->p; char_properties const& p = itr->p;
if (p.fontset) 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; std::cerr << face_name << std::endl;
manager.test(face_name, itr->str);
} }
} }
StringCharacterIterator iter(itr->str); StringCharacterIterator iter(itr->str);
for (iter.setToStart(); iter.hasNext();) for (iter.setToStart(); iter.hasNext();)
{ {
UChar ch = iter.nextPostInc(); 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.format = &(itr->p);
char_dim.avg_height = 12;//avg_height; char_dim.avg_height = p.text_size * scale_factor_;
info_.add_info(char_dim); info_.add_info(char_dim);
} }
// char sizes ---> p.text_size * scale_factor_ // char sizes ---> p.text_size * scale_factor_
@ -112,7 +117,7 @@ public:
return info_; return info_;
} }
#endif #endif
//string_info const& get_string_info();
private: private:
expression_list expr_list_; expression_list expr_list_;

View file

@ -27,16 +27,23 @@
#define MAPNIK_SKIA_FONT_MANAGER_HPP #define MAPNIK_SKIA_FONT_MANAGER_HPP
#include <iostream> #include <iostream>
#include <mapnik/unicode.hpp>
namespace mapnik namespace mapnik
{ {
class skia_typeface_cache;
class skia_font_manager class skia_font_manager
{ {
public: public:
void test() const
{ skia_font_manager(skia_typeface_cache & cache)
std::cerr << "skia_font_manager" << std::endl; : cache_(cache) {}
}
void test(std::string const&, UnicodeString & ustr);
private:
skia_typeface_cache & cache_;
}; };
} }

View file

@ -34,7 +34,9 @@
#include <mapnik/rule.hpp> #include <mapnik/rule.hpp>
#include <mapnik/feature_style_processor.hpp> #include <mapnik/feature_style_processor.hpp>
#include <mapnik/skia/skia_font_manager.hpp> #include <mapnik/skia/skia_font_manager.hpp>
#include <mapnik/skia/skia_typeface_cache.hpp>
#include <mapnik/label_collision_detector.hpp> #include <mapnik/label_collision_detector.hpp>
// skia fwd decl // skia fwd decl
class SkCanvas; class SkCanvas;
@ -91,6 +93,7 @@ private:
double scale_factor_; double scale_factor_;
box2d<double> query_extent_; box2d<double> query_extent_;
skia_font_manager font_manager_; skia_font_manager font_manager_;
skia_typeface_cache typeface_cache_;
boost::shared_ptr<label_collision_detector4> detector_; boost::shared_ptr<label_collision_detector4> detector_;
}; };

View file

@ -26,7 +26,11 @@
#ifndef MAPNIK_SKIA_TYPEFACE_CACHE_HPP #ifndef MAPNIK_SKIA_TYPEFACE_CACHE_HPP
#define MAPNIK_SKIA_TYPEFACE_CACHE_HPP #define MAPNIK_SKIA_TYPEFACE_CACHE_HPP
#include <iostream> #ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif
#include <map>
class SkTypeface; class SkTypeface;
@ -36,16 +40,17 @@ namespace mapnik
class skia_typeface_cache class skia_typeface_cache
{ {
public: public:
typedef std::map<std::string, SkTypeface*> cache_type;
skia_typeface_cache(); skia_typeface_cache();
~skia_typeface_cache(); ~skia_typeface_cache();
static bool register_font(std::string const& file_name); static bool register_font(std::string const& file_name);
static bool register_fonts(std::string const& dir, bool recurse = false); static bool register_fonts(std::string const& dir, bool recurse = false);
SkTypeface * create(std::string const& family_name);
private: private:
#ifdef MAPNIK_THREADSAFE #ifdef MAPNIK_THREADSAFE
static boost::mutex mutex_; static boost::mutex mutex_;
#endif #endif
static std::map<std::string, SkTypeface*> typefaces_; static cache_type typefaces_;
}; };
} }

View file

@ -263,7 +263,7 @@ if env['HAS_SKIA']:
libmapnik_defines.append('-DHAVE_SKIA') libmapnik_defines.append('-DHAVE_SKIA')
source.insert(0,'skia/skia_renderer.cpp') source.insert(0,'skia/skia_renderer.cpp')
source.insert(0,'skia/skia_typeface_cache.cpp') source.insert(0,'skia/skia_typeface_cache.cpp')
source.insert(0,'skia/skia_font_manager.cpp')
if env['JPEG']: if env['JPEG']:
source += Split( source += Split(

View file

@ -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 // http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec
if (face->family_name && face->style_name) 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 // skip fonts with leading . in the name
if (!boost::algorithm::starts_with(name,".")) if (!boost::algorithm::starts_with(name,"."))
{ {
@ -217,8 +217,7 @@ std::map<std::string,std::pair<int,std::string> > const& freetype_engine::get_ma
face_ptr freetype_engine::create_face(std::string const& family_name) face_ptr freetype_engine::create_face(std::string const& family_name)
{ {
std::map<std::string, std::pair<int,std::string> >::const_iterator itr; std::map<std::string, std::pair<int,std::string> >::const_iterator itr = name2file_.find(family_name);
itr = name2file_.find(family_name);
if (itr != name2file_.end()) if (itr != name2file_.end())
{ {
FT_Face face; FT_Face face;

View file

@ -51,51 +51,4 @@ void processed_text::clear()
expr_list_.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 } //ns mapnik

View file

@ -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 <mapnik/skia/skia_font_manager.hpp>
#include <mapnik/skia/skia_typeface_cache.hpp>
#include <mapnik/unicode.hpp>
#include <SkTypeface.h>
#include <iostream>
#include <vector>
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<uint16_t> 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<uint32_t> 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<metrics.fGlyphWidths.
//std::cerr << "SkAdvancedTypefaceMetrics: fFontName=" << metrics->fFontName.c_str() << std::endl;
//std::cerr << "SkAdvancedTypefaceMetrics: fAscent=" << metrics->fAscent << std::endl;
//std::cerr << "SkAdvancedTypefaceMetrics: fCapHeight=" << metrics->fCapHeight << std::endl;
}
else
{
std::cerr << "FAIL" << std::endl;
}
}
}

View file

@ -75,7 +75,8 @@ skia_renderer::skia_renderer(Map const& map, SkCanvas & canvas, double scale_fac
height_(map.height()), height_(map.height()),
t_(map.width(), map.height(), map.get_current_extent()), t_(map.width(), map.height(), map.get_current_extent()),
scale_factor_(scale_factor), scale_factor_(scale_factor),
font_manager_(), typeface_cache_(),
font_manager_(typeface_cache_),
detector_(boost::make_shared<label_collision_detector4>( detector_(boost::make_shared<label_collision_detector4>(
box2d<double>(-map.buffer_size(), -map.buffer_size(), box2d<double>(-map.buffer_size(), -map.buffer_size(),
map.width() + map.buffer_size(), map.height() + 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 sx = placements[i].center.x;
double sy = placements[i].center.y; 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(); placements[i].rewind();
for (int j = 0; j < placements[i].num_nodes(); ++j) 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_; double text_size = c->format->text_size * scale_factor_;
paint.setTextSize((SkScalar)text_size); paint.setTextSize((SkScalar)text_size);
color const& fill = c->format->fill; // !! 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); SkPoint pt = SkPoint::Make(0,0);
canvas_.save(); canvas_.save();
canvas_.translate((SkScalar)(sx + x), (SkScalar)(sy - y)); canvas_.translate((SkScalar)(sx + x), (SkScalar)(sy - y));

View file

@ -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) bool skia_typeface_cache::register_font(std::string const& file_name)
{ {
#ifdef MAPNIK_THREADSAFE #ifdef MAPNIK_THREADSAFE
@ -117,6 +128,6 @@ bool skia_typeface_cache::register_fonts(std::string const& dir, bool recurse)
#ifdef MAPNIK_THREADSAFE #ifdef MAPNIK_THREADSAFE
boost::mutex skia_typeface_cache::mutex_; boost::mutex skia_typeface_cache::mutex_;
#endif #endif
std::map<std::string, SkTypeface* > skia_typeface_cache::typefaces_; skia_typeface_cache::cache_type skia_typeface_cache::typefaces_;
} }