Compare commits

...

45 commits

Author SHA1 Message Date
artemp
c88db8c08a + correct skia usage 2013-07-29 12:36:04 +01:00
artemp
f2dc21bf72 Merge branch 'master' into skia-renderer 2013-07-29 10:26:36 +01:00
artemp
179631560d + export as mapnik SVG 2013-07-25 14:28:32 +01:00
artemp
a2691d57ca Merge branch 'master' into skia-renderer 2013-07-25 13:36:51 +01:00
artemp
88e29148ea viewer
* add export to cairo svg
* fix gpu/gl
2013-07-25 13:35:16 +01:00
artemp
9089671ddd + default to DejaVu Sans (ArialUnicodeMT is a monster when emitting PDFs) 2013-07-25 13:24:03 +01:00
artemp
4d6cc61ec1 + restore family-name + style key 2013-07-25 13:23:03 +01:00
artemp
2b7340ca2c + fix: pass lenght in bytes 2013-07-24 14:25:22 +01:00
artemp
3d54870bea Merge remote-tracking branch 'origin/skia-renderer' into skia-renderer 2013-07-24 12:41:54 +01:00
artemp
58833e23d4 + PDF export (skia) 2013-07-24 12:41:08 +01:00
artemp
8d946f78d5 + SVG export (skia) 2013-07-24 12:39:42 +01:00
artemp
1ff1ed9b3e minor formatting 2013-07-24 12:13:38 +01:00
artemp
157039c963 + remove gpu include path (not a dependency) 2013-07-24 12:00:16 +01:00
artemp
9c2704036c cast toff_t to std::streamoff
remove 'C' style comments!!
2013-07-24 11:02:06 +01:00
Dane Springmeyer
251a393d4a fix build against skia trunk 2013-07-23 21:25:24 -04:00
Dane Springmeyer
fa67d61743 also add skia gpu and utils header paths 2013-07-23 21:25:07 -04:00
Dane Springmeyer
065c3fb624 support older Qt 2013-07-23 21:24:45 -04:00
Dane Springmeyer
734634479a remove hardcoding in viewer.pro 2013-07-23 21:24:06 -04:00
Dane Springmeyer
4604453f5d fix up skia build 2013-07-23 20:51:07 -04:00
Dane Springmeyer
2be3d4a149 restrict skia define 2013-07-23 20:11:04 -04:00
Dane Springmeyer
9522f6d6ca sync with master 2013-07-23 20:05:50 -04:00
artemp
430b1d7a84 implement Porter-Duff compositing ops 2013-07-23 15:15:27 +01:00
artemp
b1afb1d7bc Skia Gpu renderer 2013-07-23 14:03:22 +01:00
artemp
21858be3ed + update skia-renderer to work with master 2013-07-23 08:32:51 +01:00
artemp
1801a33949 Merge branch 'master' into skia-renderer 2013-07-23 08:18:44 +01:00
artemp
c2a32313d9 small fixes 2013-07-22 15:31:02 +01:00
artemp
de774ea941 * use QGLWidget
* experimental GPU backend test (todo)
2013-07-22 14:53:04 +01:00
artemp
95faf49fa2 use freetype2 for calculating glyph's metrics (hack) 2013-07-22 14:51:42 +01:00
artemp
8c25cd33b1 Merge branch 'master' into skia-renderer
Conflicts:
	src/build.py
2013-07-22 09:22:49 +01:00
artemp
99ab053558 + text rendering work-in-progress 2013-07-19 16:14:10 +01:00
artemp
acc14b9cc0 Merge branch 'master' into skia-renderer 2013-07-19 08:34:00 +01:00
artemp
55cb8188ab + initial text rendering support (FIXME: implement font metrics etc) 2013-07-18 16:55:52 +01:00
artemp
6a82e617cc skia_typeface_cache 2013-07-18 11:43:15 +01:00
artemp
5d91048534 + add missing header (dummy impl atm) 2013-07-17 18:31:21 +01:00
artemp
a464092396 c++ style 2013-07-17 18:30:58 +01:00
artemp
06701cfdf9 + style 2013-07-17 18:30:24 +01:00
artemp
b7bff7106b + c++ style - always use pre increment ++itr by default 2013-07-17 18:29:29 +01:00
artemp
ec570d8a7e + trying to fix text rendering ... sigh 2013-07-17 13:33:16 +01:00
artemp
c1a9b60b50 + implement assignment operator in terms of a copy construction and a swap. 2013-07-17 10:44:42 +01:00
artemp
1a813f8af2 Merge branch 'master' into skia-renderer 2013-07-17 10:05:05 +01:00
artemp
7c6a5f0659 + apply symbolizer opacity 2013-07-16 16:08:45 +01:00
artemp
a7e2c2ea0d + attempting to refactor out shared_ptr overuse 2013-07-16 15:57:13 +01:00
artemp
d34fdd7fca + improve c++ style
+ formatting
2013-07-16 11:15:00 +01:00
artemp
d3cd1ece47 + add line Join/Cap support 2013-07-16 09:40:03 +01:00
artemp
97039e83a1 + experimental skia backend (work-in-progress) 2013-07-15 13:32:06 +01:00
31 changed files with 1461 additions and 213 deletions

View file

@ -70,6 +70,7 @@ pretty_dep_names = {
'proj':'Proj.4 C Projections library | configure with PROJ_LIBS & PROJ_INCLUDES | more info: http://trac.osgeo.org/proj/',
'pg':'Postgres C Library required for PostGIS plugin | configure with pg_config program | more info: https://github.com/mapnik/mapnik/wiki/PostGIS',
'sqlite3':'SQLite3 C Library | configure with SQLITE_LIBS & SQLITE_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki/SQLite',
'skia_core':'Skia rendering toolkit | configure with SKIA_LIBS & SKIA_INCLUDES',
'jpeg':'JPEG C library | configure with JPEG_LIBS & JPEG_INCLUDES',
'tiff':'TIFF C library | configure with TIFF_LIBS & TIFF_INCLUDES',
'png':'PNG C library | configure with PNG_LIBS & PNG_INCLUDES',
@ -347,6 +348,12 @@ opts.AddVariables(
BoolVariable('CAIRO', 'Attempt to build with Cairo rendering support', 'True'),
PathVariable('CAIRO_INCLUDES', 'Search path for cairo include files', '',PathVariable.PathAccept),
PathVariable('CAIRO_LIBS', 'Search path for cairo library files','',PathVariable.PathAccept),
# Skia backend
BoolVariable('SKIA', 'Attempt to build with Skia rendering support', 'False'),
PathVariable('SKIA_INCLUDES', 'Search path for skia include files', '',PathVariable.PathAccept),
PathVariable('SKIA_LIBS', 'Search path for skia library files','',PathVariable.PathAccept),
('GDAL_CONFIG', 'The path to the gdal-config executable for finding gdal and ogr details.', 'gdal-config'),
('PG_CONFIG', 'The path to the pg_config executable.', 'pg_config'),
PathVariable('OCCI_INCLUDES', 'Search path for OCCI include files', '/usr/lib/oracle/10.2.0.3/client/include', PathVariable.PathAccept),
@ -426,6 +433,7 @@ pickle_store = [# Scons internal variables
'HAS_CAIRO',
'HAS_PYCAIRO',
'HAS_LIBXML2',
'SKIA_RENDERER',
'PYTHON_IS_64BIT',
'SAMPLE_INPUT_PLUGINS',
'PKG_CONFIG_PATH',
@ -1050,6 +1058,7 @@ if not preconfigured:
env['CAIRO_LIBPATHS'] = []
env['CAIRO_ALL_LIBS'] = []
env['CAIRO_CPPPATHS'] = []
env['SKIA_RENDERER'] = False
env['HAS_PYCAIRO'] = False
env['HAS_LIBXML2'] = False
env['LIBMAPNIK_LIBS'] = []
@ -1189,6 +1198,17 @@ if not preconfigured:
OPTIONAL_LIBSHEADERS = []
if env['SKIA']:
OPTIONAL_LIBSHEADERS.append(['skia_core', ['SkCanvas.h'], False,'C++','-DSKIA_RENDERER'])
if env['SKIA_LIBS'] or env['SKIA_INCLUDES']:
env.AppendUnique(CPPPATH = os.path.realpath(env['SKIA_INCLUDES'] + '/config'))
env.AppendUnique(CPPPATH = os.path.realpath(env['SKIA_INCLUDES'] + '/utils'))
env.AppendUnique(CPPPATH = os.path.realpath(env['SKIA_INCLUDES'] + '/core'))
env.AppendUnique(CPPPATH = os.path.realpath(env['SKIA_INCLUDES'] + '/effects'))
env.AppendUnique(LIBPATH = os.path.realpath(env['SKIA_LIBS']))
else:
env['SKIPPED_DEPS'].extend(['skia'])
if env['JPEG']:
OPTIONAL_LIBSHEADERS.append(['jpeg', ['stdio.h', 'jpeglib.h'], False,'C','-DHAVE_JPEG'])
inc_path = env['%s_INCLUDES' % 'JPEG']

View file

@ -397,6 +397,15 @@ bool has_grid_renderer()
#endif
}
bool has_skia_renderer()
{
#if defined(SKIA_RENDERER)
return true;
#else
return false;
#endif
}
bool has_jpeg()
{
#if defined(HAVE_JPEG)

View file

@ -19,11 +19,14 @@
// qt
#include <QtWidgets/QApplication>
#include <QApplication>
#include <QStringList>
#include <QSettings>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#if defined(SKIA_RENDERER)
#include <mapnik/skia/skia_typeface_cache.hpp>
#endif
#include "mainwindow.hpp"
// boost
@ -54,6 +57,15 @@ int main( int argc, char **argv )
QString font_dir = settings.value("dir").toString();
freetype_engine::register_fonts(font_dir.toStdString());
}
#if defined(SKIA_RENDERER)
for (int index=0; index < count; ++index)
{
settings.setArrayIndex(index);
QString font_dir = settings.value("dir").toString();
mapnik::skia_typeface_cache::register_fonts(font_dir.toStdString());
}
#endif
settings.endArray();
QApplication app( argc, argv );

View file

@ -263,6 +263,71 @@ void MainWindow::export_as()
}
}
#ifdef SKIA_RENDERER
void MainWindow::export_as_skia_pdf()
{
QAction *action = qobject_cast<QAction *>(sender());
QByteArray fileFormat = action->data().toByteArray();
QString initialPath = QDir::currentPath() + "/map-skia." + fileFormat;
QString fileName = QFileDialog::getSaveFileName(this, tr("Export As Skia PDF"),
initialPath,
tr("%1 Files (*.%2);;All Files (*)")
.arg(QString(fileFormat.toUpper()))
.arg(QString(fileFormat)));
if (!fileName.isEmpty())
{
std::cerr << "Skia PDF" << std::endl;
mapWidget_->export_skia_pdf(fileName);
}
}
#endif
#ifdef HAVE_CAIRO
void MainWindow::export_as_cairo_pdf()
{
QAction *action = qobject_cast<QAction *>(sender());
QByteArray fileFormat = action->data().toByteArray();
QString initialPath = QDir::currentPath() + "/map-cairo." + fileFormat;
QString fileName = QFileDialog::getSaveFileName(this, tr("Export As Cairo PDF"),
initialPath,
tr("%1 Files (*.%2);;All Files (*)")
.arg(QString(fileFormat.toUpper()))
.arg(QString(fileFormat)));
if (!fileName.isEmpty())
{
std::cerr << "Cairo PDF" << std::endl;
mapWidget_->export_cairo_pdf(fileName);
}
}
#endif
#ifdef SVG_RENDERER
void MainWindow::export_as_mapnik_svg()
{
QAction *action = qobject_cast<QAction *>(sender());
QByteArray fileFormat = action->data().toByteArray();
QString initialPath = QDir::currentPath() + "/map-mapnik." + fileFormat;
QString fileName = QFileDialog::getSaveFileName(this, tr("Export As Mapnik SVG"),
initialPath,
tr("%1 Files (*.%2);;All Files (*)")
.arg(QString(fileFormat.toUpper()))
.arg(QString(fileFormat)));
if (!fileName.isEmpty())
{
std::cerr << "Mapnik SVG" << std::endl;
mapWidget_->export_mapnik_svg(fileName);
}
}
#endif
void MainWindow::print()
{
@ -334,6 +399,23 @@ void MainWindow::createActions()
connect(action, SIGNAL(triggered()), this, SLOT(export_as()));
exportAsActs.append(action);
}
#ifdef SKIA_RENDERER
exportSkiaPDF = new QAction("Skia",this);
exportSkiaPDF->setData(QByteArray("pdf"));
connect(exportSkiaPDF, SIGNAL(triggered()), this, SLOT(export_as_skia_pdf()));
#endif
#ifdef HAVE_CAIRO
exportCairoPDF = new QAction("Cairo",this);
exportCairoPDF->setData(QByteArray("pdf"));
connect(exportCairoPDF, SIGNAL(triggered()), this, SLOT(export_as_cairo_pdf()));
#endif
#ifdef SVG_RENDERER
exportMapnikSVG = new QAction("Mapnik",this);
exportMapnikSVG->setData(QByteArray("svg"));
connect(exportMapnikSVG, SIGNAL(triggered()), this, SLOT(export_as_mapnik_svg()));
#endif
printAct = new QAction(QIcon(":/images/print.png"),tr("&Print ..."),this);
printAct->setShortcut(tr("Ctrl+E"));
@ -353,10 +435,19 @@ void MainWindow::createMenus()
foreach (QAction *action, exportAsActs)
exportMenu->addAction(action);
exportPDFMenu = new QMenu(tr("&Export As PDF"), this);
exportPDFMenu->addAction(exportSkiaPDF);
exportPDFMenu->addAction(exportCairoPDF);
exportSVGMenu = new QMenu(tr("&Export As SVG"), this);
exportSVGMenu->addAction(exportMapnikSVG);
fileMenu = new QMenu(tr("&File"),this);
fileMenu->addAction(openAct);
fileMenu->addAction(saveAct);
fileMenu->addMenu(exportMenu);
fileMenu->addMenu(exportPDFMenu);
fileMenu->addMenu(exportSVGMenu);
fileMenu->addAction(printAct);
fileMenu->addSeparator();
fileMenu->addAction(exitAct);
@ -386,6 +477,10 @@ void MainWindow::createToolBars()
renderer_selector_->addItem("AGG");
#ifdef HAVE_CAIRO
renderer_selector_->addItem("Cairo");
#endif
#ifdef SKIA_RENDERER
renderer_selector_->addItem("Skia");
renderer_selector_->addItem("Skia-Gpu");
#endif
renderer_selector_->addItem("Grid");
fileToolBar->addWidget(renderer_selector_);

View file

@ -41,7 +41,7 @@ class QDoubleSpinBox;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
public:
MainWindow();
virtual ~MainWindow();
void set_default_extent(double x0,double y0,double x1, double y1);
@ -54,6 +54,9 @@ public slots:
void pan();
void info();
void export_as();
void export_as_skia_pdf();
void export_as_cairo_pdf();
void export_as_mapnik_svg();
void open(QString const& path = QString());
void reload();
void save();
@ -96,11 +99,16 @@ private:
QAction *panDownAct;
QAction *reloadAct;
QAction *layerInfo;
QAction *exportSkiaPDF;
QAction *exportCairoPDF;
QAction *exportMapnikSVG;
//toolbars
QToolBar *fileToolBar;
QToolBar *editToolBar;
//menus
QMenu *exportMenu;
QMenu *exportPDFMenu;
QMenu *exportSVGMenu;
QMenu *fileMenu;
QMenu *helpMenu;
//status bar

View file

@ -35,14 +35,50 @@
#include <mapnik/config_error.hpp>
#include <mapnik/image_util.hpp>
#ifdef SVG_RENDERER
#include <mapnik/svg/output/svg_renderer.hpp>
#endif
#ifdef HAVE_CAIRO
// cairo
#include <mapnik/cairo_renderer.hpp>
#endif
#ifdef SKIA_RENDERER
// skia
#include <mapnik/skia/skia_renderer.hpp>
#include <SkCanvas.h>
#include <SkBitmap.h>
#include <SkStream.h>
#include <SkPDFDevice.h>
#include <SkPDFDocument.h>
#include <SkGpuDevice.h>
#include <gl/GrGLInterface.h>
#if SK_SUPPORT_GPU
#include <gl/GrGLFunctions.h>
#include <GrContextFactory.h>
#include <gl/GrGLDefines.h>
#include <gl/GrGLUtil.h>
#include <gl/GrGLExtensions.h>
GrContextFactory gGrContextFactory;
#endif
GrContextFactory* GetGrContextFactory() {
#if SK_SUPPORT_GPU
return &gGrContextFactory;
#else
return NULL;
#endif
}
#endif
#include "mapwidget.hpp"
#include "info_dialog.hpp"
using mapnik::image_32;
using mapnik::Map;
using mapnik::layer;
@ -77,7 +113,7 @@ double scales [] = {279541132.014,
533.182395962};
MapWidget::MapWidget(QWidget *parent)
: QWidget(parent),
: QGLWidget(parent),
map_(),
selected_(1),
extent_(),
@ -98,6 +134,7 @@ MapWidget::MapWidget(QWidget *parent)
pen_.setJoinStyle(Qt::RoundJoin);
}
void MapWidget::setTool(eTool tool)
{
cur_tool_=tool;
@ -495,18 +532,15 @@ void MapWidget::set_scaling_factor(double scaling_factor)
void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{
boost::timer::auto_cpu_timer t;
unsigned width=map.width();
unsigned height=map.height();
image_32 buf(width,height);
mapnik::agg_renderer<image_32> ren(map,buf,scaling_factor);
try
{
{
boost::timer::auto_cpu_timer t;
ren.apply();
}
QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped());
}
@ -524,17 +558,130 @@ void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
}
}
#ifdef SKIA_RENDERER
void render_skia(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{
boost::timer::auto_cpu_timer t;
unsigned width=map.width();
unsigned height=map.height();
mapnik::image_32 buf(width,height);
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
bitmap.setPixels(buf.raw_data());
SkCanvas canvas(bitmap);
mapnik::skia_renderer ren(map,canvas,scaling_factor);
try
{
ren.apply();
QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped());
}
catch (mapnik::config_error & ex)
{
std::cerr << "Skia:" << ex.what() << std::endl;
}
catch (const std::exception & ex)
{
std::cerr << "Skia:exception: " << ex.what() << std::endl;
}
catch (...)
{
std::cerr << "Skia:Unknown exception caught!\n";
}
}
void render_skia_gpu(GrGLInterface const * cur_interface, mapnik::Map const& map, double scaling_factor)
{
std::cerr << "SKIA GPU start " << cur_interface << std::endl ;
boost::timer::auto_cpu_timer t;
unsigned width=map.width();
unsigned height=map.height();
GrContext* context = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext) cur_interface);
GrBackendRenderTargetDesc desc;
desc.fConfig = kSkia8888_GrPixelConfig;
desc.fWidth = width;
desc.fHeight = height;
//GrGLExtensions extensions;
//GrGLBinding binding;
//GrGLInterface interface;
//interface.validate(binding);
//extensions.init(binding, cur_interface);
GR_GL_GetIntegerv(cur_interface, GR_GL_SAMPLES, &desc.fSampleCnt);
GR_GL_GetIntegerv(cur_interface, GR_GL_STENCIL_BITS, &desc.fStencilBits);
GrGLint buffer;
GR_GL_GetIntegerv(cur_interface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
desc.fRenderTargetHandle = buffer;
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
GrRenderTarget* curRenderTarget = context->wrapBackendRenderTarget(desc);
SkGpuDevice device(context, curRenderTarget);
SkCanvas canvas(&device);
mapnik::skia_renderer ren(map,canvas,scaling_factor);
ren.apply();
context->resetContext();
context->flush();
std::cerr << "SKIA GPU Done" << std::endl;
}
void MapWidget::export_skia_pdf(QString const& filename)
{
unsigned width = map_->width();
unsigned height = map_->height();
SkISize pageSize = SkISize::Make(width,height);
SkPDFDevice dev(pageSize, pageSize, SkMatrix::I());
SkCanvas canvas(&dev);
mapnik::skia_renderer ren(*map_,canvas,scaling_factor_);
try
{
ren.apply();
}
catch (mapnik::config_error & ex)
{
std::cerr << "Skia:" << ex.what() << std::endl;
}
catch (const std::exception & ex)
{
std::cerr << "Skia:exception: " << ex.what() << std::endl;
}
catch (...)
{
std::cerr << "Skia:Unknown exception caught!\n";
}
SkPDFDocument doc;
doc.appendPage(&dev);
std::cerr << filename.toStdString() << std::endl;
SkFILEWStream stream(filename.toStdString().c_str());
if (stream.isValid())
{
doc.emitPDF(&stream);
}
std::cerr << "Done" << std::endl;
}
#endif
void render_grid(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{
std::cerr << "Not supported" << std::endl;
}
#ifdef HAVE_CAIRO
void MapWidget::export_cairo_pdf(QString const& filename)
{
save_to_cairo_file(*map_,filename.toStdString(),scaling_factor_);
std::cerr << "Done" << std::endl;
}
void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{
#ifdef HAVE_CAIRO
boost::timer::auto_cpu_timer t;
mapnik::cairo_surface_ptr image_surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,map.width(),map.height()),
mapnik::cairo_surface_closer());
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> renderer(map, image_surface, scaling_factor);
@ -542,15 +689,49 @@ void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
image_32 buf(image_surface);
QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped());
#endif
}
#endif
#ifdef SVG_RENDERER
void MapWidget::export_mapnik_svg(QString const& filename)
{
boost::timer::auto_cpu_timer t;
std::ofstream output_stream(filename.toStdString().c_str());
if (output_stream)
{
std::ostream_iterator<char> output_itr(output_stream);
mapnik::svg_renderer<std::ostream_iterator<char> > ren(*map_, output_itr, scaling_factor_);
try
{
ren.apply();
}
catch (...)
{
std::cerr << "Exception caught." << std::endl;
}
output_stream.close();
}
std::cerr << "Done" << std::endl;
}
#endif
void MapWidget::updateRenderer(QString const& txt)
{
bool auto_swap = true;
if (txt == "AGG") cur_renderer_ = AGG;
else if (txt == "Cairo") cur_renderer_ = Cairo;
else if (txt == "Grid") cur_renderer_ = Grid;
else if (txt == "Skia") cur_renderer_ = Skia;
else if (txt == "Skia-Gpu")
{
cur_renderer_ = Skia_Gpu;
auto_swap = false;
}
std::cerr << "Update renderer called" << std::endl;
setAutoBufferSwap(auto_swap);
updateMap();
}
@ -568,14 +749,28 @@ void MapWidget::updateMap()
{
render_agg(*map_, scaling_factor_, pix_);
}
#ifdef HAVE_CAIRO
else if (cur_renderer_ == Cairo)
{
render_cairo(*map_, scaling_factor_, pix_);
}
#endif
else if (cur_renderer_ == Grid)
{
render_grid(*map_, scaling_factor_, pix_);
}
#ifdef SKIA_RENDERER
else if (cur_renderer_ == Skia)
{
render_skia(*map_, scaling_factor_, pix_);
}
else if (cur_renderer_ == Skia_Gpu)
{
GrGLInterface const* cur_interface = GrGLCreateNativeInterface();
render_skia_gpu(cur_interface, *map_, scaling_factor_);
swapBuffers();
}
#endif
else
{
std::cerr << "Unknown renderer..." << std::endl;

View file

@ -22,6 +22,7 @@
#define MAP_WIDGET_HPP
#include <QWidget>
#include <QGLWidget>
#include <QImage>
#include <QPixmap>
#include <QPen>
@ -35,7 +36,9 @@
#include <mapnik/map.hpp>
#endif
class MapWidget : public QWidget
struct GrGLInterface;
class MapWidget : public QGLWidget
{
Q_OBJECT
@ -49,8 +52,10 @@ public:
enum eRenderer
{
AGG,
AGG = 1,
Cairo,
Skia,
Skia_Gpu,
Grid
};
@ -85,6 +90,18 @@ public:
void panUp();
void panDown();
void set_scaling_factor(double);
#ifdef SKIA_RENDERER
void export_skia_pdf(QString const& filename);
#endif
#ifdef HAVE_CAIRO
void export_cairo_pdf(QString const& filename);
#endif
#ifdef SVG_RENDERER
void export_mapnik_svg(QString const& filename);
#endif
public slots:
void zoomToLevel(int level);
void updateMap();
@ -105,6 +122,7 @@ protected:
unsigned height,
std::string const& filename,
std::string const& type);
};
#endif // MAP_WIDGET_HPP

View file

@ -3,12 +3,24 @@
######################################################################
TEMPLATE = app
QT += core gui widgets
QMAKE_CXX = clang++
QMAKE_CXXFLAGS += $$system(mapnik-config --cxxflags)
QT += opengl
QMAKE_CXX = $$system(mapnik-config --cxx)
QMAKE_LINK = $$system(mapnik-config --cxx)
QMAKE_CXXFLAGS += $$system(mapnik-config --cxxflags --defines)
QMAKE_CXXFLAGS += $$system(mapnik-config --includes --dep-includes)
QMAKE_CXXFLAGS += "-I/Users/artem/Projects/skia/trunk/include/gpu"
QMAKE_CXXFLAGS += "-I/Users/artem/Projects/skia/trunk/include/pdf"
QMAKE_CXXFLAGS += "-I/Users/artem/Projects/skia/trunk/src/gpu"
QMAKE_LFLAGS += $$system(mapnik-config --libs)
QMAKE_LFLAGS += $$system(mapnik-config --ldflags --dep-libs)
QMAKE_LFLAGS += -lboost_timer
QMAKE_LFLAGS += -lskia_pdf
QMAKE_LFLAGS += -lskia_skgpu
QMAKE_LFLAGS += -lzlib
QMAKE_LFLAGS += "-framework Cocoa"
# Input
CONFIG += qt debug_and_release

View file

@ -4,7 +4,7 @@ from glob import glob
Import('env')
base = './mapnik/'
subdirs = ['','svg','wkt','grid','json','util','text_placements','formatting']
subdirs = ['','svg','wkt','grid','json','util','text_placements','formatting','skia']
if env['SVG_RENDERER']:
subdirs.append('svg/output')

View file

@ -78,19 +78,17 @@ void check_object_status_and_throw_exception(T const& object)
class cairo_face : private mapnik::noncopyable
{
public:
cairo_face(boost::shared_ptr<freetype_engine> const& engine, face_ptr const& face);
cairo_face(boost::shared_ptr<freetype_engine> const& engine, FT_Face face);
~cairo_face();
cairo_font_face_t * face() const;
private:
class handle
{
public:
handle(boost::shared_ptr<freetype_engine> const& engine, face_ptr const& face)
: engine_(engine), face_(face) {}
handle(boost::shared_ptr<freetype_engine> const& engine)
: engine_(engine) {}
private:
boost::shared_ptr<freetype_engine> engine_;
face_ptr face_;
};
static void destroy(void *data)
@ -100,20 +98,21 @@ private:
}
private:
face_ptr face_;
cairo_font_face_t *c_face_;
};
typedef boost::shared_ptr<cairo_face> cairo_face_ptr;
struct FT_FaceRec_;
class cairo_face_manager : private mapnik::noncopyable
{
public:
cairo_face_manager(boost::shared_ptr<freetype_engine> engine);
cairo_face_ptr get_face(face_ptr face);
cairo_face_ptr get_face(font_face const& face);
private:
typedef std::map<face_ptr,cairo_face_ptr> cairo_face_cache;
typedef std::map<FT_FaceRec_*,cairo_face_ptr> cairo_face_cache;
boost::shared_ptr<freetype_engine> font_engine_;
cairo_face_cache cache_;
};
@ -310,7 +309,7 @@ public:
void set_gradient(cairo_gradient const& pattern, box2d<double> const& bbox);
void add_image(double x, double y, image_data_32 & data, double opacity = 1.0);
void add_image(agg::trans_affine const& tr, image_data_32 & data, double opacity = 1.0);
void set_font_face(cairo_face_manager & manager, face_ptr face);
void set_font_face(cairo_face_manager & manager, font_face const& face);
void set_font_matrix(cairo_matrix_t const& matrix);
void set_matrix(cairo_matrix_t const& matrix);
void transform(cairo_matrix_t const& matrix);

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
* 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
@ -37,7 +37,7 @@
#include <mapnik/noncopyable.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/font_util.hpp>
// boost
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
@ -68,13 +68,13 @@ struct glyph_t;
typedef boost::shared_ptr<font_face> face_ptr;
class MAPNIK_DECL font_glyph : private mapnik::noncopyable
class MAPNIK_DECL font_glyph //: private mapnik::noncopyable FIXME
{
public:
font_glyph(face_ptr face, unsigned index)
font_glyph(font_face const& face, unsigned index)
: face_(face), index_(index) {}
face_ptr get_face() const
font_face const& get_face() const
{
return face_;
}
@ -84,13 +84,10 @@ public:
return index_;
}
private:
face_ptr face_;
font_face const& face_;
unsigned index_;
};
typedef boost::shared_ptr<font_glyph> glyph_ptr;
class MAPNIK_DECL font_face_set : private mapnik::noncopyable
{
@ -98,13 +95,13 @@ public:
typedef std::vector<face_ptr> container_type;
typedef container_type::size_type size_type;
font_face_set(void)
font_face_set()
: faces_(),
dimension_cache_() {}
void add(face_ptr face);
size_type size() const;
glyph_ptr get_glyph(unsigned c) const;
font_glyph get_glyph(unsigned c) const;
char_info character_dimensions(unsigned c);
void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format);
void set_pixel_sizes(unsigned size);
@ -163,8 +160,7 @@ public:
face_ptr get_face(std::string const& name)
{
face_ptr_cache_type::iterator itr;
itr = face_ptr_cache_.find(name);
face_ptr_cache_type::iterator itr = face_ptr_cache_.find(name);
if (itr != face_ptr_cache_.end())
{
return itr->second;
@ -213,7 +209,7 @@ public:
return face_set;
}
face_set_ptr get_face_set(std::string const& name, boost::optional<font_set> fset)
face_set_ptr get_face_set(std::string const& name, boost::optional<font_set> fset) // FIXME : bad style !!
{
if (fset && fset->size() > 0)
{

View file

@ -37,7 +37,7 @@ class MAPNIK_DECL font_set
public:
font_set(std::string const& name);
font_set(font_set const& rhs);
font_set& operator=(font_set const& rhs);
font_set& operator=(font_set rhs);
unsigned size() const;
void set_name(std::string const& name);
std::string const& get_name() const;

View file

@ -30,10 +30,13 @@
namespace mapnik {
namespace formatting {
class MAPNIK_DECL text_node: public node {
class MAPNIK_DECL text_node: public node
{
public:
text_node(expression_ptr text): node(), text_(text) {}
text_node(std::string text): node(), text_(parse_expression(text)) {}
text_node(expression_ptr text)
: node(), text_(text) {}
text_node(std::string const& text)
: node(), text_(parse_expression(text)) {}
void to_xml(boost::property_tree::ptree &xml) const;
static node_ptr from_xml(xml_node const& xml);
virtual void apply(char_properties const& p, feature_impl const& feature, processed_text &output) const;

View file

@ -122,7 +122,10 @@
namespace mapnik { namespace filter { namespace detail {
static const float blur_matrix[] = {0.1111f,0.1111f,0.1111f,0.1111f,0.1111f,0.1111f,0.1111f,0.1111f,0.1111f};
static const float blur_matrix[] = {1/16.0f,2/16.0f,1/16.0f,
2/16.0f,4/16.0f,2/16.0f,
1/16.0f,2/16.0f,1/16.0f};
static const float emboss_matrix[] = {-2,-1,0,-1,1,1,0,1,2};
static const float sharpen_matrix[] = {0,-1,0,-1,5,-1,0,-1,0 };
static const float edge_detect_matrix[] = {0,1,0,1,-4,1,0,1,0 };

View file

@ -26,16 +26,18 @@
#include <mapnik/text_properties.hpp>
#include <mapnik/text_path.hpp>
#include <mapnik/noncopyable.hpp>
#include <mapnik/font_engine_freetype.hpp> //!!
#include <mapnik/skia/skia_font_manager.hpp>
// stl
#include <list>
// icu (temp)
#include <unicode/schriter.h>
namespace mapnik
{
namespace mapnik {
// fwd declares
class freetype_engine;
template <typename T> class face_manager;
//class freetype_engine;
//template <typename T> class face_manager;
class MAPNIK_DECL processed_text : mapnik::noncopyable
{
@ -48,7 +50,7 @@ public:
UnicodeString str;
};
public:
processed_text(face_manager<freetype_engine> & font_manager, double scale_factor);
processed_text(double scale_factor);
void push_back(char_properties const& properties, UnicodeString const& text);
unsigned size() const { return expr_list_.size(); }
unsigned empty() const { return expr_list_.empty(); }
@ -56,10 +58,69 @@ public:
typedef std::list<processed_expression> expression_list;
expression_list::const_iterator begin() const;
expression_list::const_iterator end() const;
string_info const& get_string_info();
template <typename T>
string_info const& get_string_info(T & font_manager)
{
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)
{
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_;
}
#if defined(SKIA_RENDERER)
string_info const& get_string_info(skia_font_manager & manager)
{
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;
if (p.fontset)
{
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, 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 = p.text_size * scale_factor_;
info_.add_info(char_dim);
}
// char sizes ---> p.text_size * scale_factor_
info_.add_text(itr->str);
}
return info_;
}
#endif
private:
expression_list expr_list_;
face_manager<freetype_engine> &font_manager_;
double scale_factor_;
string_info info_;
};

View file

@ -0,0 +1,52 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#if defined(SKIA_RENDERER)
#ifndef MAPNIK_SKIA_FONT_MANAGER_HPP
#define MAPNIK_SKIA_FONT_MANAGER_HPP
#include <iostream>
#include <mapnik/unicode.hpp>
namespace mapnik
{
class skia_typeface_cache;
class skia_font_manager
{
public:
skia_font_manager(skia_typeface_cache & cache)
: cache_(cache) {}
void test(std::string const&, UnicodeString & ustr);
private:
skia_typeface_cache & cache_;
};
}
#endif // MAPNIK_SKIA_FONT_MANAGER_HPP
#endif // #if defined(SKIA_RENDERER)

View file

@ -0,0 +1,114 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#if defined(SKIA_RENDERER)
#ifndef MAPNIK_SKIA_RENDERER_HPP
#define MAPNIK_SKIA_RENDERER_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/feature_style_processor.hpp>
#include <mapnik/skia/skia_font_manager.hpp>
#include <mapnik/skia/skia_typeface_cache.hpp>
#include <mapnik/label_collision_detector.hpp>
//
#include <mapnik/font_engine_freetype.hpp>
// skia fwd decl
class SkCanvas;
namespace mapnik
{
class MAPNIK_DECL skia_renderer : public feature_style_processor<skia_renderer>,
private mapnik::noncopyable
{
public:
typedef skia_renderer processor_impl_type;
skia_renderer(Map const& map, SkCanvas & canvas, double scale_factor = 1.0);
~skia_renderer();
void start_map_processing(Map const& map);
void end_map_processing(Map const& map);
void start_layer_processing(layer const& lay, box2d<double> const& query_extent);
void end_layer_processing(layer const& lay);
void start_style_processing(feature_type_style const& st);
void end_style_processing(feature_type_style const& st);
void process(line_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
void process(polygon_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
void process(text_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
void painted(bool painted) {};
inline double scale_factor() const
{
return scale_factor_;
}
inline bool process(rule::symbolizers const& ,
mapnik::feature_impl & ,
proj_transform const& )
{
return false;
}
inline eAttributeCollectionPolicy attribute_collection_policy() const
{
return DEFAULT;
}
private:
SkCanvas & canvas_;
unsigned width_;
unsigned height_;
CoordTransform t_;
double scale_factor_;
box2d<double> query_extent_;
//skia_font_manager font_manager_;
skia_typeface_cache typeface_cache_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
boost::shared_ptr<label_collision_detector4> detector_;
};
}
#endif //MAPNIK_SKIA_RENDERER_HPP
#endif // SKIA_RENDERER

View file

@ -0,0 +1,59 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#if defined(SKIA_RENDERER)
#ifndef MAPNIK_SKIA_TYPEFACE_CACHE_HPP
#define MAPNIK_SKIA_TYPEFACE_CACHE_HPP
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif
#include <map>
class SkTypeface;
namespace mapnik
{
class skia_typeface_cache
{
public:
typedef std::map<std::string, SkTypeface*> 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 cache_type typefaces_;
};
}
#endif // MAPNIK_SKIA_TYPEFACE_CACHE_HPP
#endif // #if defined(SKIA_RENDERER)

View file

@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef TEXT_PROPERTIES_HPP
#define TEXT_PROPERTIES_HPP
@ -57,9 +58,9 @@ typedef std::map<std::string, font_set> fontset_map;
struct MAPNIK_DECL char_properties
{
char_properties();
/** Construct object from XML. */
// Construct object from XML.
void from_xml(xml_node const &sym, fontset_map const & fontsets);
/** Write object to XML ptree. */
// Write object to XML ptree.
void to_xml(boost::property_tree::ptree &node, bool explicit_defaults, char_properties const& dfl=char_properties()) const;
std::string face_name;
boost::optional<font_set> fontset;
@ -124,27 +125,27 @@ typedef std::pair<double, double> position;
class processed_text;
/** Contains all text symbolizer properties which are not directly related to text formatting. */
// Contains all text symbolizer properties which are not directly related to text formatting.
struct MAPNIK_DECL text_symbolizer_properties
{
text_symbolizer_properties();
/** Load all values from XML ptree. */
// Load all values from XML ptree.
void from_xml(xml_node const &sym, fontset_map const & fontsets);
/** Save all values to XML ptree (but does not create a new parent node!). */
void to_xml(boost::property_tree::ptree &node, bool explicit_defaults, text_symbolizer_properties const &dfl=text_symbolizer_properties()) const;
// Save all values to XML ptree (but does not create a new parent node!).
void to_xml(boost::property_tree::ptree &node, bool explicit_defaults,
text_symbolizer_properties const &dfl=text_symbolizer_properties()) const;
/** Takes a feature and produces formated text as output.
* The output object has to be created by the caller and passed in for thread safety.
*/
// Takes a feature and produces formated text as output.
// The output object has to be created by the caller and passed in for thread safety.
void process(processed_text &output, feature_impl const& feature) const;
/** Automatically create processing instructions for a single expression. */
// Automatically create processing instructions for a single expression.
void set_old_style_expression(expression_ptr expr);
/** Sets new format tree. */
// Sets new format tree.
void set_format_tree(formatting::node_ptr tree);
/** Get format tree. */
// Get format tree.
formatting::node_ptr format_tree() const;
/** Get a list of all expressions used in any placement.
* This function is used to collect attributes. */
// Get a list of all expressions used in any placement.
// This function is used to collect attributes.
void add_expressions(expression_set &output) const;
//Per symbolizer options
@ -154,26 +155,26 @@ struct MAPNIK_DECL text_symbolizer_properties
horizontal_alignment_e halign;
justify_alignment_e jalign;
vertical_alignment_e valign;
/** distance between repeated labels on a single geometry */
// distance between repeated labels on a single geometry
double label_spacing;
/** distance the label can be moved on the line to fit, if 0 the default is used */
// distance the label can be moved on the line to fit, if 0 the default is used
unsigned label_position_tolerance;
bool avoid_edges;
double minimum_distance;
double minimum_padding;
double minimum_path_length;
double max_char_angle_delta;
/** Always try render an odd amount of labels */
// Always try render an odd amount of labels
bool force_odd_labels;
bool allow_overlap;
/** Only consider geometry with largest bbox (polygons) */
// Only consider geometry with largest bbox (polygons)
bool largest_bbox_only;
double text_ratio;
double wrap_width;
/** Default values for char_properties. */
// Default values for char_properties.
char_properties format;
private:
/** A tree of formatting::nodes which contain text and formatting information. */
// A tree of formatting::nodes which contain text and formatting information.
formatting::node_ptr tree_;
};

View file

@ -261,6 +261,18 @@ if env['HAS_CAIRO']:
source.insert(0,'cairo_renderer.cpp')
source.insert(0,'cairo_context.cpp')
if '-DSKIA_RENDERER' in env['CPPDEFINES']:
lib_env.AppendUnique(LIBPATH=env['SKIA_LIBS'])
lib_env.Append(LIBS=['skia_core','skia_ports','skia_utils','skia_images',
'skia_effects','skia_sfnt','skia_opts','skia_opts_ssse3','skia_skgpu'])
lib_env.Append(FRAMEWORKS = ['Cocoa'])
lib_env.Append(CPPDEFINES = '-DSKIA_RENDERER')
libmapnik_defines.append('-DSKIA_RENDERER')
source.insert(0,'skia/skia_renderer.cpp')
source.insert(0,'skia/skia_typeface_cache.cpp')
source.insert(0,'skia/skia_font_manager.cpp')
for cpp in enabled_imaging_libraries:
source.append(cpp)

View file

@ -29,14 +29,34 @@
#include <cairo-ft.h>
#include <valarray>
namespace mapnik {
cairo_face::cairo_face(boost::shared_ptr<freetype_engine> const& engine, face_ptr const& face)
: face_(face)
cairo_face_manager::cairo_face_manager(boost::shared_ptr<freetype_engine> engine)
: font_engine_(engine) {}
cairo_face_ptr cairo_face_manager::get_face(font_face const& face)
{
cairo_face_cache::iterator itr = cache_.find((FT_FaceRec_ *const)face.get_face());
cairo_face_ptr entry;
if (itr != cache_.end())
{
entry = itr->second;
}
else
{
entry = boost::make_shared<cairo_face>(font_engine_, face.get_face());
cache_.insert(std::make_pair((FT_FaceRec_ *const)face.get_face(), entry));
}
return entry;
}
cairo_face::cairo_face(boost::shared_ptr<freetype_engine> const& engine, FT_Face face)
{
static cairo_user_data_key_t key;
c_face_ = cairo_ft_font_face_create_for_ft_face(face->get_face(), FT_LOAD_NO_HINTING);
cairo_font_face_set_user_data(c_face_, &key, new handle(engine, face), destroy);
c_face_ = cairo_ft_font_face_create_for_ft_face(face, FT_LOAD_NO_HINTING);
cairo_font_face_set_user_data(c_face_, &key, new handle(engine), destroy);
}
cairo_face::~cairo_face()
@ -363,7 +383,7 @@ void cairo_context::add_image(agg::trans_affine const& tr, image_data_32 & data,
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_font_face(cairo_face_manager & manager, face_ptr face)
void cairo_context::set_font_face(cairo_face_manager & manager, font_face const& face)
{
cairo_set_font_face(cairo_.get(), manager.get_face(face)->face());
}
@ -447,10 +467,7 @@ void cairo_context::add_text(text_path const& path,
double text_size = c->format->text_size * scale_factor;
faces->set_character_sizes(text_size);
glyph_ptr glyph = faces->get_glyph(c->c);
if (glyph)
{
font_glyph glyph = faces->get_glyph(c->c);
cairo_matrix_t matrix;
matrix.xx = text_size * std::cos(angle);
matrix.xy = text_size * std::sin(angle);
@ -459,14 +476,13 @@ void cairo_context::add_text(text_path const& path,
matrix.x0 = 0;
matrix.y0 = 0;
set_font_matrix(matrix);
set_font_face(manager, glyph->get_face());
glyph_path(glyph->get_index(), sx + x, sy - y);
set_font_face(manager, glyph.get_face());
glyph_path(glyph.get_index(), sx + x, sy - y);
set_line_width(2.0 * c->format->halo_radius * scale_factor);
set_line_join(ROUND_JOIN);
set_color(c->format->halo_fill);
stroke();
}
}
path.rewind();
@ -481,10 +497,8 @@ void cairo_context::add_text(text_path const& path,
double text_size = c->format->text_size * scale_factor;
faces->set_character_sizes(text_size);
glyph_ptr glyph = faces->get_glyph(c->c);
font_glyph glyph = faces->get_glyph(c->c);
if (glyph)
{
cairo_matrix_t matrix;
matrix.xx = text_size * std::cos(angle);
matrix.xy = text_size * std::sin(angle);
@ -493,10 +507,9 @@ void cairo_context::add_text(text_path const& path,
matrix.x0 = 0;
matrix.y0 = 0;
set_font_matrix(matrix);
set_font_face(manager, glyph->get_face());
set_font_face(manager, glyph.get_face());
set_color(c->format->fill);
show_glyph(glyph->get_index(), sx + x, sy - y);
}
show_glyph(glyph.get_index(), sx + x, sy - y);
}
}

View file

@ -95,31 +95,6 @@ struct cairo_save_restore
cairo_context & context_;
};
cairo_face_manager::cairo_face_manager(boost::shared_ptr<freetype_engine> engine)
: font_engine_(engine)
{
}
cairo_face_ptr cairo_face_manager::get_face(face_ptr face)
{
cairo_face_cache::iterator itr = cache_.find(face);
cairo_face_ptr entry;
if (itr != cache_.end())
{
entry = itr->second;
}
else
{
entry = boost::make_shared<cairo_face>(font_engine_, face);
cache_.insert(std::make_pair(face, entry));
}
return entry;
}
cairo_renderer_base::cairo_renderer_base(Map const& m,
cairo_ptr const& cairo,
double scale_factor,

View file

@ -39,6 +39,10 @@
#include <mapnik/svg/output/svg_renderer.hpp>
#endif
#if defined(SKIA_RENDERER)
#include <mapnik/skia/skia_renderer.hpp>
#endif
namespace mapnik
{
@ -47,6 +51,10 @@ template class feature_style_processor<cairo_renderer<cairo_ptr> >;
template class feature_style_processor<cairo_renderer<cairo_surface_ptr> >;
#endif
#if defined(SKIA_RENDERER)
template class feature_style_processor<skia_renderer>;
#endif
#if defined(SVG_RENDERER)
template class feature_style_processor<svg_renderer<std::ostream_iterator<char> > >;
#endif

View file

@ -104,7 +104,8 @@ bool freetype_engine::register_font(std::string const& file_name)
// some font files have multiple fonts in a file
// the count is in the 'root' face library[0]
// see the FT_FaceRec in freetype.h
for ( int i = 0; face == 0 || i < num_faces; i++ ) {
for ( int i = 0; face == 0 || i < num_faces; i++ )
{
// if face is null then this is the first face
error = FT_New_Face (library,file_name.c_str(),i,&face);
if (error)
@ -221,8 +222,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)
{
std::map<std::string, std::pair<int,std::string> >::const_iterator itr;
itr = name2file_.find(family_name);
std::map<std::string, std::pair<int,std::string> >::const_iterator itr = name2file_.find(family_name);
if (itr != name2file_.end())
{
FT_Face face;
@ -289,16 +289,21 @@ font_face_set::size_type font_face_set::size() const
return faces_.size();
}
glyph_ptr font_face_set::get_glyph(unsigned c) const
font_glyph font_face_set::get_glyph(unsigned c) const
{
FT_UInt g = 0;
font_face * cur_face = 0;
BOOST_FOREACH ( face_ptr const& face, faces_)
{
FT_UInt g = face->get_char(c);
if (g) return boost::make_shared<font_glyph>(face, g);
if (g = face->get_char(c))
{
cur_face = face.get();
break;
}
}
// Final fallback to empty square if nothing better in any font
return boost::make_shared<font_glyph>(*faces_.begin(), 0);
return font_glyph(g > 0 ? *cur_face: *(*faces_.begin()), g);
}
char_info font_face_set::character_dimensions(unsigned int c)
@ -321,8 +326,8 @@ char_info font_face_set::character_dimensions(unsigned int c)
FT_BBox glyph_bbox;
FT_Glyph image;
glyph_ptr glyph = get_glyph(c);
FT_Face face = glyph->get_face()->get_face();
font_glyph glyph = get_glyph(c);
FT_Face face = glyph.get_face().get_face();
matrix.xx = (FT_Fixed)( 1 * 0x10000L );
matrix.xy = (FT_Fixed)( 0 * 0x10000L );
@ -331,7 +336,7 @@ char_info font_face_set::character_dimensions(unsigned int c)
FT_Set_Transform(face, &matrix, &pen);
error = FT_Load_Glyph (face, glyph->get_index(), FT_LOAD_NO_HINTING);
error = FT_Load_Glyph (face, glyph.get_index(), FT_LOAD_NO_HINTING);
if ( error )
return char_info();
@ -374,9 +379,11 @@ void font_face_set::get_string_info(string_info & info, UnicodeString const& ust
shaped.releaseBuffer(length);
if (U_SUCCESS(err)) {
if (U_SUCCESS(err))
{
StringCharacterIterator iter(shaped);
for (iter.setToStart(); iter.hasNext();) {
for (iter.setToStart(); iter.hasNext();)
{
UChar ch = iter.nextPostInc();
char_info char_dim = character_dimensions(ch);
char_dim.format = format;
@ -564,8 +571,8 @@ box2d<double> text_renderer<T>::prepare_glyphs(text_path const& path)
face_set_ptr faces = font_manager_.get_face_set(c->format->face_name, c->format->fontset);
faces->set_character_sizes(c->format->text_size*scale_factor_);
glyph_ptr glyph = faces->get_glyph(unsigned(c->c));
FT_Face face = glyph->get_face()->get_face();
font_glyph glyph = faces->get_glyph(unsigned(c->c));
FT_Face face = glyph.get_face().get_face();
matrix.xx = (FT_Fixed)( std::cos( angle ) * 0x10000L );
matrix.xy = (FT_Fixed)(-std::sin( angle ) * 0x10000L );
@ -574,7 +581,7 @@ box2d<double> text_renderer<T>::prepare_glyphs(text_path const& path)
FT_Set_Transform(face, &matrix, &pen);
error = FT_Load_Glyph(face, glyph->get_index(), FT_LOAD_NO_HINTING);
error = FT_Load_Glyph(face, glyph.get_index(), FT_LOAD_NO_HINTING);
if ( error )
continue;

View file

@ -36,13 +36,10 @@ font_set::font_set(font_set const& rhs)
: name_(rhs.name_),
face_names_(rhs.face_names_) {}
font_set& font_set::operator=(font_set const& other)
font_set& font_set::operator=(font_set other)
{
if (this == &other)
return *this;
name_ = other.name_;
face_names_ = other.face_names_;
std::swap(name_,other.name_);
std::swap(face_names_,other.face_names_);
return *this;
}

View file

@ -1714,7 +1714,7 @@ void map_parser::find_unused_nodes_recursive(xml_node const& node, std::string &
xml_node::attribute_map const& attr = node.get_attributes();
xml_node::attribute_map::const_iterator aitr = attr.begin();
xml_node::attribute_map::const_iterator aend = attr.end();
for (;aitr!=aend; aitr++)
for (;aitr!=aend; ++aitr)
{
if (!aitr->second.processed)
{
@ -1725,7 +1725,7 @@ void map_parser::find_unused_nodes_recursive(xml_node const& node, std::string &
}
xml_node::const_iterator itr = node.begin();
xml_node::const_iterator end = node.end();
for (; itr!=end; itr++)
for (; itr!=end; ++itr)
{
find_unused_nodes_recursive(*itr, error_message);
}

View file

@ -42,11 +42,8 @@ processed_text::expression_list::const_iterator processed_text::end() const
return expr_list_.end();
}
processed_text::processed_text(face_manager<freetype_engine> & font_manager, double scale_factor)
: font_manager_(font_manager), scale_factor_(scale_factor)
{
}
processed_text::processed_text( double scale_factor)
: scale_factor_(scale_factor) {}
void processed_text::clear()
{
@ -54,50 +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

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;
}
}
}

410
src/skia/skia_renderer.cpp Normal file
View file

@ -0,0 +1,410 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#if defined(SKIA_RENDERER)
#include <mapnik/skia/skia_renderer.hpp>
#include <mapnik/vertex_converters.hpp>
#include <mapnik/symbolizer_helpers.hpp>
// skia
#include <SkCanvas.h>
#include <SkPath.h>
#include <SkPaint.h>
#include <SkDashPathEffect.h>
#include "agg_trans_affine.h"
namespace mapnik {
void set_comp_op(SkPaint & paint, composite_mode_e comp_op)
{
SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
switch (comp_op)
{
case clear:
mode = SkXfermode::kClear_Mode;
break;
case src:
mode = SkXfermode::kSrc_Mode;
break;
case dst:
mode = SkXfermode::kDst_Mode;
break;
case src_over:
mode = SkXfermode::kSrcOver_Mode;
break;
case dst_over:
mode = SkXfermode::kDstOver_Mode;
break;
case src_in:
mode = SkXfermode::kSrcIn_Mode;
break;
case dst_in:
mode = SkXfermode::kDstIn_Mode;
break;
case src_out:
mode = SkXfermode::kSrcOut_Mode;
break;
case dst_out:
mode = SkXfermode::kDstOut_Mode;
break;
case src_atop:
mode = SkXfermode::kSrcATop_Mode;
break;
case dst_atop:
mode = SkXfermode::kDstATop_Mode;
break;
case _xor:
mode = SkXfermode::kXor_Mode;
break;
case plus:
mode = SkXfermode::kPlus_Mode;
break;
case multiply:
mode = SkXfermode::kMultiply_Mode;
break;
case screen:
mode = SkXfermode::kScreen_Mode;
break;
case overlay:
mode = SkXfermode::kOverlay_Mode;
break;
case darken:
mode = SkXfermode::kDarken_Mode;
break;
case lighten:
mode = SkXfermode::kLighten_Mode;
break;
case color_dodge:
mode = SkXfermode::kColorDodge_Mode;
break;
case color_burn:
mode = SkXfermode::kColorBurn_Mode;
break;
case hard_light:
mode = SkXfermode::kHardLight_Mode;
break;
case soft_light:
mode = SkXfermode::kSoftLight_Mode;
break;
case difference:
mode = SkXfermode::kDifference_Mode;
break;
case exclusion:
mode = SkXfermode::kExclusion_Mode;
break;
case hue:
mode = SkXfermode::kHue_Mode;
break;
case saturation:
mode = SkXfermode::kSaturation_Mode;
break;
case _color:
mode = SkXfermode::kColor_Mode;
break;
default:
break;
}
paint.setXfermodeMode(mode);
}
struct skia_path_adapter : private mapnik::noncopyable
{
skia_path_adapter(SkPath & path)
: sk_path_(path) {}
template <typename T>
void add_path(T & path)
{
vertex2d vtx(vertex2d::no_init);
path.rewind(0);
while ((vtx.cmd = path.vertex(&vtx.x, &vtx.y)) != SEG_END)
{
switch (vtx.cmd)
{
case SEG_MOVETO:
sk_path_.moveTo(vtx.x, vtx.y);
case SEG_LINETO:
sk_path_.lineTo(vtx.x, vtx.y);
}
}
}
SkPath & sk_path_;
};
skia_renderer::skia_renderer(Map const& map, SkCanvas & canvas, double scale_factor)
: feature_style_processor<skia_renderer>(map,scale_factor),
canvas_(canvas),
width_(map.width()),
height_(map.height()),
t_(map.width(), map.height(), map.get_current_extent()),
scale_factor_(scale_factor),
typeface_cache_(),
//font_manager_(typeface_cache_),
font_engine_(),
font_manager_(font_engine_),
detector_(boost::make_shared<label_collision_detector4>(
box2d<double>(-map.buffer_size(), -map.buffer_size(),
map.width() + map.buffer_size(), map.height() + map.buffer_size()))) {}
skia_renderer::~skia_renderer() {}
void skia_renderer::start_map_processing(Map const& map)
{
MAPNIK_LOG_DEBUG(skia_renderer) << "skia_renderer_base: Start map processing bbox=" << map.get_current_extent();
boost::optional<color> bg = map.background();
if (bg)
{
canvas_.drawARGB((*bg).alpha(), (*bg).red(), (*bg).green(), (*bg).blue());
}
}
void skia_renderer::end_map_processing(Map const& map)
{
MAPNIK_LOG_DEBUG(skia_renderer) << "skia_renderer_base: End map processing";
}
void skia_renderer::start_layer_processing(layer const& lay, box2d<double> const& query_extent)
{
MAPNIK_LOG_DEBUG(skia_renderer) << "skia_renderer_base: Start processing layer=" << lay.name() ;
MAPNIK_LOG_DEBUG(skia_renderer) << "skia_renderer_base: -- datasource=" << lay.datasource().get();
MAPNIK_LOG_DEBUG(skia_renderer) << "skia_renderer_base: -- query_extent=" << query_extent;
query_extent_ = query_extent;
}
void skia_renderer::end_layer_processing(layer const& lay)
{
MAPNIK_LOG_DEBUG(skia_renderer) << "skia_renderer_base: End layer processing";
}
void skia_renderer::start_style_processing(feature_type_style const& st)
{
MAPNIK_LOG_DEBUG(skia_renderer) << "skia_renderer:start style processing";
}
void skia_renderer::end_style_processing(feature_type_style const& st)
{
MAPNIK_LOG_DEBUG(skia_renderer) << "skia_renderer:end style processing";
}
void skia_renderer::process(line_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
agg::trans_affine tr;
evaluate_transform(tr, feature, sym.get_transform());
box2d<double> clipping_extent = query_extent_;
SkPath path;
skia_path_adapter adapter(path);
typedef boost::mpl::vector<clip_line_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> conv_types;
vertex_converter<box2d<double>, skia_path_adapter, line_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(clipping_extent,adapter,sym,t_,prj_trans,tr,scale_factor_);
if (prj_trans.equal() && sym.clip()) converter.template set<clip_line_tag>(); //optional clip (default: true)
converter.template set<transform_tag>(); //always transform
converter.template set<affine_transform_tag>();
if (sym.simplify_tolerance() > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (sym.smooth() > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
BOOST_FOREACH( geometry_type & geom, feature.paths())
{
if (geom.size() > 1)
{
converter.apply(geom);
}
}
stroke const& strk = sym.get_stroke();
color const& col = strk.get_color();
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setAntiAlias(true);
set_comp_op(paint, sym.comp_op());
paint.setARGB(int(col.alpha() * strk.get_opacity()), col.red(), col.green(), col.blue());
paint.setStrokeWidth(strk.get_width() * scale_factor_);
switch (strk.get_line_join())
{
case MITER_JOIN:
paint.setStrokeJoin(SkPaint::kMiter_Join);
break;
case MITER_REVERT_JOIN:
break;
case ROUND_JOIN:
paint.setStrokeJoin(SkPaint::kRound_Join);
break;
case BEVEL_JOIN:
paint.setStrokeJoin(SkPaint::kBevel_Join);
break;
default:
break;
}
switch (strk.get_line_cap())
{
case BUTT_CAP:
paint.setStrokeCap(SkPaint::kButt_Cap);
break;
case SQUARE_CAP:
paint.setStrokeCap(SkPaint::kSquare_Cap);
break;
case ROUND_CAP:
paint.setStrokeCap(SkPaint::kRound_Cap);
break;
default:
break;
}
if (strk.has_dash())
{
std::vector<SkScalar> dash;
for (auto p : strk.get_dash_array())
{
dash.push_back(p.first * scale_factor_);
dash.push_back(p.second * scale_factor_);
}
paint.setPathEffect(new SkDashPathEffect(&dash[0], dash.size(), strk.dash_offset(), false));
}
canvas_.drawPath(path, paint);
}
void skia_renderer::process(polygon_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
agg::trans_affine tr;
evaluate_transform(tr, feature, sym.get_transform());
SkPath path;
skia_path_adapter adapter(path);
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> conv_types;
vertex_converter<box2d<double>, skia_path_adapter, polygon_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(query_extent_, adapter ,sym,t_,prj_trans,tr,scale_factor_);
if (prj_trans.equal() && sym.clip()) converter.template set<clip_poly_tag>(); //optional clip (default: true)
converter.template set<transform_tag>(); //always transform
converter.template set<affine_transform_tag>();
if (sym.simplify_tolerance() > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (sym.smooth() > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
BOOST_FOREACH( geometry_type & geom, feature.paths())
{
if (geom.size() > 2)
{
converter.apply(geom);
}
}
color const& fill = sym.get_fill();
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setAntiAlias(true);
set_comp_op(paint, sym.comp_op());
paint.setARGB(int(fill.alpha() * sym.get_opacity()), fill.red(), fill.green(), fill.blue());
canvas_.drawPath(path, paint);
}
void skia_renderer::process(text_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
text_symbolizer_helper<face_manager<freetype_engine>,label_collision_detector4>
//text_symbolizer_helper<skia_font_manager,label_collision_detector4>
helper(sym, feature, prj_trans,
width_, height_,
scale_factor_,
t_, font_manager_, *detector_, query_extent_);
while (helper.next())
{
placements_type const& placements = helper.placements();
for (unsigned i = 0; i < placements.size(); ++i)
{
double sx = placements[i].center.x;
double sy = placements[i].center.y;
placements[i].rewind();
SkPaint paint;
paint.setAntiAlias(true);
set_comp_op(paint, sym.comp_op());
SkTypeface * typeface = typeface_cache_.create("DejaVuSans"); // FIXME
if (typeface) paint.setTypeface(typeface);
paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
// 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);
if (c->format->halo_radius > 0)
{
paint.setStyle(SkPaint::kStroke_Style);
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),4, &pt, paint);
canvas_.restore();
}
}
// text
placements[i].rewind();
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);
paint.setStyle(SkPaint::kFill_Style);
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() * 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));
canvas_.rotate(-(SkScalar)180 * (angle/M_PI));
canvas_.drawPosText(&(c->c),4, &pt, paint);
canvas_.restore();
}
}
}
}
}
#endif // SKIA_RENDERER

View file

@ -0,0 +1,133 @@
/*****************************************************************************
*
* 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/debug.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif
#include <SkTypeface.h>
//#include <SkFontHost.h>
#include <SkAdvancedTypefaceMetrics.h>
#include <mapnik/skia/skia_typeface_cache.hpp>
#include <mapnik/util/fs.hpp>
namespace mapnik
{
skia_typeface_cache::skia_typeface_cache()
{
}
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
boost::mutex::scoped_lock lock(mutex_);
#endif
SkTypeface * typeface = SkTypeface::CreateFromFile(file_name.c_str());
if (typeface)
{
SkAdvancedTypefaceMetrics * metrics = typeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo);
std::cerr << metrics->fFontName.c_str() << std::endl;
typefaces_.insert(std::make_pair(std::string(metrics->fFontName.c_str()),typeface));
return true;
}
return false;
}
bool skia_typeface_cache::register_fonts(std::string const& dir, bool recurse)
{
if (!mapnik::util::exists(dir))
{
return false;
}
if (!mapnik::util::is_directory(dir))
{
return register_font(dir);
}
bool success = false;
try
{
boost::filesystem::directory_iterator end_itr;
for (boost::filesystem::directory_iterator itr(dir); itr != end_itr; ++itr)
{
#if (BOOST_FILESYSTEM_VERSION == 3)
std::string file_name = itr->path().string();
#else // v2
std::string file_name = itr->string();
#endif
if (boost::filesystem::is_directory(*itr) && recurse)
{
if (register_fonts(file_name, true))
{
success = true;
}
}
else
{
#if (BOOST_FILESYSTEM_VERSION == 3)
std::string base_name = itr->path().filename().string();
#else // v2
std::string base_name = itr->filename();
#endif
if (!boost::algorithm::starts_with(base_name,".") &&
boost::filesystem::is_regular_file(file_name))
{
if (register_font(file_name))
{
success = true;
}
}
}
}
}
catch (std::exception const& ex)
{
MAPNIK_LOG_ERROR(skia_typeface_cache) << "register_fonts: " << ex.what();
}
return success;
}
#ifdef MAPNIK_THREADSAFE
boost::mutex skia_typeface_cache::mutex_;
#endif
skia_typeface_cache::cache_type skia_typeface_cache::typefaces_;
}

View file

@ -34,6 +34,10 @@
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/pixel_position.hpp>
#if defined(SKIA_RENDERER)
#include <mapnik/skia/skia_font_manager.hpp>
#endif
// agg
#include "agg_conv_clip_polyline.h"
@ -58,7 +62,7 @@ text_symbolizer_helper<FaceManagerT, DetectorT>::text_symbolizer_helper(text_sym
detector_(detector),
dims_(0, 0, width, height),
query_extent_(query_extent),
text_(font_manager, scale_factor),
text_(scale_factor),
angle_(0.0),
placement_valid_(false),
points_on_line_(false),
@ -331,7 +335,7 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_placement()
}
finder_.reset(new placement_finder<DetectorT>(*placement_,
text_.get_string_info(),
text_.get_string_info(font_manager_),
detector_, dims_));
placement_valid_ = true;
return true;
@ -503,6 +507,9 @@ agg::trans_affine const& shield_symbolizer_helper<FaceManagerT, DetectorT>::get_
}
template class text_symbolizer_helper<face_manager<freetype_engine>, label_collision_detector4>;
#if defined(SKIA_RENDERER)
template class text_symbolizer_helper<skia_font_manager, label_collision_detector4>;
#endif
template class shield_symbolizer_helper<face_manager<freetype_engine>, label_collision_detector4>;
template class mapnik::placement_finder<mapnik::label_collision_detector4>;
} //namespace