Compare commits
45 commits
master
...
skia-rende
Author | SHA1 | Date | |
---|---|---|---|
|
c88db8c08a | ||
|
f2dc21bf72 | ||
|
179631560d | ||
|
a2691d57ca | ||
|
88e29148ea | ||
|
9089671ddd | ||
|
4d6cc61ec1 | ||
|
2b7340ca2c | ||
|
3d54870bea | ||
|
58833e23d4 | ||
|
8d946f78d5 | ||
|
1ff1ed9b3e | ||
|
157039c963 | ||
|
9c2704036c | ||
|
251a393d4a | ||
|
fa67d61743 | ||
|
065c3fb624 | ||
|
734634479a | ||
|
4604453f5d | ||
|
2be3d4a149 | ||
|
9522f6d6ca | ||
|
430b1d7a84 | ||
|
b1afb1d7bc | ||
|
21858be3ed | ||
|
1801a33949 | ||
|
c2a32313d9 | ||
|
de774ea941 | ||
|
95faf49fa2 | ||
|
8c25cd33b1 | ||
|
99ab053558 | ||
|
acc14b9cc0 | ||
|
55cb8188ab | ||
|
6a82e617cc | ||
|
5d91048534 | ||
|
a464092396 | ||
|
06701cfdf9 | ||
|
b7bff7106b | ||
|
ec570d8a7e | ||
|
c1a9b60b50 | ||
|
1a813f8af2 | ||
|
7c6a5f0659 | ||
|
a7e2c2ea0d | ||
|
d34fdd7fca | ||
|
d3cd1ece47 | ||
|
97039e83a1 |
31 changed files with 1461 additions and 213 deletions
20
SConstruct
20
SConstruct
|
@ -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']
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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_);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
52
include/mapnik/skia/skia_font_manager.hpp
Normal file
52
include/mapnik/skia/skia_font_manager.hpp
Normal 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)
|
114
include/mapnik/skia/skia_renderer.hpp
Normal file
114
include/mapnik/skia/skia_renderer.hpp
Normal 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
|
59
include/mapnik/skia/skia_typeface_cache.hpp
Normal file
59
include/mapnik/skia/skia_typeface_cache.hpp
Normal 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)
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
12
src/build.py
12
src/build.py
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
78
src/skia/skia_font_manager.cpp
Normal file
78
src/skia/skia_font_manager.cpp
Normal 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
410
src/skia/skia_renderer.cpp
Normal 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
|
133
src/skia/skia_typeface_cache.cpp
Normal file
133
src/skia/skia_typeface_cache.cpp
Normal 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_;
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue