Rev 280 | Blame | Compare with Previous | Last modification | View Log | RSS feed
//
// C++ Implementation: SRender
//
// Description: Renders a map from some shape files. This class assumes,
// that the shape files are in open street map format!
//
//
// Author: Andreas Theofilu <andreas@theosys.at>, (C) 2009
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "config.h"
// This module will only exist, if Mapnik is available!
#if defined HAVE_MAPNIK
#define BOOST_SPIRIT_THREADSAFE
#include <QPixmap>
#include <QBitmap>
#include <QString>
#include <QXmlReader>
#include <QDir>
#include <QColor>
#include <QImage>
#include <KStandardDirs>
#include <KConfig>
#include <KLocale>
#include <KMessageBox>
#include <KGlobalSettings>
#include <KConfigGroup>
#include <KIconLoader>
#include "render.h"
#include <iostream>
#define CON_MAP 100
#define CON_STYLE 101
#define CON_RULE 102
#define CON_LINESYMBOLIZER 103
#define CON_POINTSYMBOLIZER 104
#define CON_POLYGONSYMBOLIZER 105
#define CON_TEXTSYMBOLIZER 106
#define CON_POLYGONPATTERNSYMBOLIZER 107
#define CON_LAYER 108
#define CON_DATASOURCE 109
#define CON_SHIELDSYMBOLIZER 110
#define CON_LINEPATTERNSYMBOLIZER 111
#define CON_ELSEFILTER 112
#define FLD_FILTER 200
#define FLD_CSSPARAMETER 201
#define FLD_MINSCALE 202
#define FLD_MAXSCALE 203
#define FLD_STYLENAME 204
#define FLD_PARAMETER 205
#define ATT_FILL 300
#define ATT_FILE 301
#define ATT_TYPE 302
#define ATT_WIDTH 303
#define ATT_HEIGHT 304
#define ATT_SIZE 305
#define ATT_NAME 306
#define ATT_FACENAME 307
#define ATT_DY 308
#define ATT_HALORADIUS 309
#define ATT_WRAPWIDTH 310
#define ATT_MINDISTANCE 311
#define ATT_MAXDISTANCE 312
#define ATT_PLACEMENT 313
#define ATT_ALLOWOVERLAP 314
#define ATT_STATUS 315
#define ATT_SRS 316
#define ATT_DX 317
#define ATT_ALIGNMENT 318
#define FIRST_CON 100
#define LAST_CON 112
#define FIRST_FLD 200
#define LAST_FLD 205
#define FIRST_ATT 300
#define LAST_ATT 318
using std::cout;
using std::cerr;
using std::clog;
using std::endl;
TOKEN token[] = {
// Containers
{ CON_MAP, in_map, QString("Map") },
{ CON_STYLE, in_style, QString("Style") },
{ CON_RULE, in_rule, QString("Rule") },
{ CON_LINESYMBOLIZER, in_linesymbolizer, QString("LineSymbolizer") },
{ CON_POINTSYMBOLIZER, in_pointsymbolizer, QString("PointSymbolizer") },
{ CON_POLYGONSYMBOLIZER, in_polygonsymbolizer, QString("PolygonSymbolizer") },
{ CON_TEXTSYMBOLIZER, in_textsymbolizer, QString("TextSymbolizer") },
{ CON_POLYGONPATTERNSYMBOLIZER, in_polygonpatternsymbolizer, QString("PolygonPatternSymbolizer") },
{ CON_LAYER, in_layer, QString("Layer") },
{ CON_DATASOURCE, in_datasource, QString("Datasource") },
{ CON_SHIELDSYMBOLIZER, in_shieldsymbolizer, QString("ShieldSymbolizer") },
{ CON_LINEPATTERNSYMBOLIZER, in_linepatternsymbolizer, QString("LinePatternSymbolizer") },
{ CON_ELSEFILTER, in_rule, QString("ElseFilter") },
// Fields
{ FLD_FILTER, in_rule, QString("Filter") },
{ FLD_CSSPARAMETER, in_symbolizer, QString("CSSParameter") },
{ FLD_MINSCALE, in_rule, QString("MinScaleDenominator") },
{ FLD_MAXSCALE, in_rule, QString("MaxScaleDenominator") },
{ FLD_STYLENAME, in_style, QString("StyleName") },
{ FLD_PARAMETER, in_datasource, QString("Parameter") },
// Attributes
{ ATT_FILL, in_symbolizer, QString("fill") },
{ ATT_NAME, in_symbolizer, QString("name") },
{ ATT_FILE, in_symbolizer, QString("file") },
{ ATT_TYPE, in_symbolizer, QString("type") },
{ ATT_WIDTH, in_symbolizer, QString("width") },
{ ATT_HEIGHT, in_symbolizer, QString("height") },
{ ATT_SIZE, in_symbolizer, QString("size") },
{ ATT_FACENAME, in_symbolizer, QString("face_name") },
{ ATT_DX, in_symbolizer, QString("dx") },
{ ATT_DY, in_symbolizer, QString("dy") },
{ ATT_HALORADIUS, in_symbolizer, QString("halo_radius") },
{ ATT_WRAPWIDTH, in_symbolizer, QString("wrap_width") },
{ ATT_MINDISTANCE, in_symbolizer, QString("min_distance") },
{ ATT_MAXDISTANCE, in_symbolizer, QString("max_distance") },
{ ATT_PLACEMENT, in_symbolizer, QString("placement") },
{ ATT_ALLOWOVERLAP, in_symbolizer, QString("allow_overlap") },
{ ATT_STATUS, in_layer, QString("status") },
{ ATT_SRS, in_layer, QString("srs") },
{ ATT_ALIGNMENT, in_symbolizer, QString("alignment") },
{ 0, in_root, QString::null }
};
SRender::SRender()
{
_width = _height = 0;
shapePath = QString::null;
XmlPath = QString::null;
Lay = firstLayer = lastLayer = 0;
Style = firstStyle = lastStyle = 0;
Rule = 0;
LineSymbolizer = 0;
PolygonSymbolizer = 0;
TextSymbolizer = 0;
PointSymbolizer = 0;
PolygonPatternSymbolizer = 0;
ShieldSymbolizer = 0;
LinePatternSymbolizer = 0;
_lx = _ly = 180.0;
_rx = _ry = -180.0;
__map_type = MAP_SHAPE; // The default map type
// This is true, when a XML file was parsed successfully
ControlSet = false;
// Read settings from config file
KConfig cfg (QString("sportwatcher.rc"), KConfig::SimpleConfig);
KConfigGroup ic (&cfg, "SportWatcher");
KConfigGroup sh (&cfg, "ShapeFile");
QString basePath = ic.readEntry("Data", QDir::home().absolutePath() + "/.sportwatcher");
shapePath = ic.readEntry("MAP", basePath + "/shapefiles");
// Read the shape specific informations
#ifdef MAPNIK_PLUGINS
pluginPath = QString(MAPNIK_PLUGINS);
#else
QDir dir;
// Test some default path
if (dir.exists(QString("/usr/lib/mapnik/input")))
pluginPath = sh.readEntry("PluginPath", QString("/usr/lib/mapnik/input"));
else if (dir.exists(QString("/usr/local/lib/mapnik/input")))
pluginPath = sh.readEntry("PluginPath", QString("/usr/local/lib/mapnik/input"));
else if (dir.exists(QString("/usr/lib/mapnik/0.6/input")))
pluginPath = sh.readEntry("PluginPath", QString("/usr/lib/mapnik/0.6/input"));
else
pluginPath = sh.readEntry("PluginPath", QString(""));
#endif
#ifdef MAPNIK_FONTS
fontPath = QString(MAPNIK_FONTS);
#else
// Test some default path
if (dir.exists(QString("/usr/lib/mapnik/fonts")))
fontPath = sh.readEntry("FontPath", QString("/usr/lib/mapnik/fonts"));
else if (dir.exists(QString("/usr/local/lib/mapnik/fonts")))
fontPath = sh.readEntry("FontPath", QString("/usr/local/lib/mapnik/fonts"));
else if (dir.exists(QString("/usr/share/mapnik/fonts")))
fontPath = sh.readEntry("FontPath", QString("/usr/share/mapnik/fonts"));
else if (dir.exists(QString("/usr/share/fonts/truetype/ttf-dejavu")))
fontPath = sh.readEntry("FontPath", QString("/usr/share/fonts/truetype/ttf-dejavu"));
else
fontPath = sh.readEntry("FontPath", QString(""));
#endif
XmlPath = sh.readEntry("XmlFile", basePath + "/shapefiles/osm.xml");
geographic = sh.readEntry("Geographic", false);
}
SRender::~SRender()
{
_width = _height = 0;
startDocument(); // Clean everything
ControlSet = false;
}
void SRender::setDrawArea(int w, int h)
{
_width = w;
_height = h;
}
bool SRender::startDocument()
{
m.remove_all(); // delete styles and layers from map
if (firstStyle) // free if allocated
{
Style = firstStyle;
while (Style)
{
STYLE *sakt = Style->next;
if (Style->rule)
{
RULE *rule = Style->rule;
while (rule)
{
RULE *rakt = rule->next;
LINESYMBOLIZER *LineSymbolizer = rule->LineSymbolizer;
POLYGONSYMBOLIZER *PolygonSymbolizer = rule->PolygonSymbolizer;
TEXTSYMBOLIZER *TextSymbolizer = rule->TextSymbolizer;
POINTSYMBOLIZER *PointSymbolizer = rule->PointSymbolizer;
POLYGONPATTERNSYMBOLIZER *PolygonPatternSymbolizer = rule->PolygonPatternSymbolizer;
SHIELDSYMBOLIZER *ShieldSymbolizer = rule->ShieldSymbolizer;
LINEPATTERNSYMBOLIZER *LinePatternSymbolizer = rule->LinePatternSymbolizer;
while (LineSymbolizer)
{
LINESYMBOLIZER *akt = LineSymbolizer->next;
delete LineSymbolizer;
LineSymbolizer = akt;
}
while (PolygonSymbolizer)
{
POLYGONSYMBOLIZER *akt = PolygonSymbolizer->next;
delete PolygonSymbolizer;
PolygonSymbolizer = akt;
}
while (TextSymbolizer)
{
TEXTSYMBOLIZER *akt = TextSymbolizer->next;
delete TextSymbolizer;
TextSymbolizer = akt;
}
while (PointSymbolizer)
{
POINTSYMBOLIZER *akt = PointSymbolizer->next;
delete PointSymbolizer;
PointSymbolizer = akt;
}
while (PolygonPatternSymbolizer)
{
POLYGONPATTERNSYMBOLIZER *akt = PolygonPatternSymbolizer->next;
delete PolygonPatternSymbolizer;
PolygonPatternSymbolizer = akt;
}
while (ShieldSymbolizer)
{
SHIELDSYMBOLIZER *akt = ShieldSymbolizer->next;
delete ShieldSymbolizer;
ShieldSymbolizer = akt;
}
while (LinePatternSymbolizer)
{
LINEPATTERNSYMBOLIZER *akt = LinePatternSymbolizer->next;
delete LinePatternSymbolizer;
LinePatternSymbolizer = akt;
}
delete rule;
rule = rakt;
}
}
delete Style;
Style = sakt;
}
}
Style = firstStyle = lastStyle = 0;
if (firstLayer)
{
Lay = firstLayer;
while (Lay)
{
LAYER *akt;
akt = Lay->next;
delete Lay;
Lay = akt;
}
}
Lay = firstLayer = lastLayer = 0;
Rule = 0;
LineSymbolizer = 0;
PolygonSymbolizer = 0;
TextSymbolizer = 0;
PointSymbolizer = 0;
PolygonPatternSymbolizer = 0;
ShieldSymbolizer = 0;
LinePatternSymbolizer = 0;
_lx = _ly = 180.0;
_rx = _ry = -180.0;
ControlSet = false;
XmlLine = 1;
Container = in_root;
return true;
}
/*
* This is called every time a new start element was parsed.
*/
bool SRender::startElement( const QString&, const QString&,
const QString& qName,
const QXmlAttributes& att)
{
int i = FIRST_CON;
int index;
QString hv0;
while (i <= LAST_CON)
{
if (qName.toLower() == getKey(i).toLower())
{
Container = token[i].con;
switch (i)
{
case CON_MAP:
Container = in_map;
if (ControlSet) // Must be false here!
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: There is another MAP! Only one map information is allowed!").arg(XmlPath).arg(XmlLine));
return false;
}
if ((index = att.index(QString("bgcolor"))) != -1)
{
MapPars.bgcolor = colorToUInt(att.value(index));
m.set_background(setColor(MapPars.bgcolor));
}
if ((index = att.index(QString("buffer_size"))) != -1)
{
MapPars.buf_size = att.value(index).toInt();
m.set_buffer_size(MapPars.buf_size);
}
if ((index = att.index(QString("srs"))) != -1)
{
MapPars.srs = att.value(index);
m.set_srs(MapPars.srs.toAscii().data());
}
break;
case CON_STYLE:
Container = in_style;
if (!lastStyle)
{
Style = allocStyle();
firstStyle = lastStyle = Style;
}
else
{
Style = allocStyle();
lastStyle->next = Style;
lastStyle = Style;
}
if ((index = att.index(QString("name"))) != -1)
Style->name = att.value(index);
else
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open STYLE without a name!").arg(XmlPath).arg(XmlLine));
return false;
}
break;
case CON_RULE:
Container = in_rule;
if (!Style)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open RULE outside of a STYLE!").arg(XmlPath).arg(XmlLine));
return false;
}
Rule = getLastRule (Style->rule);
if (!Rule)
{
Rule = allocRule();
Style->rule = Rule;
}
else
{
Rule->next = allocRule();
Rule = Rule->next;
}
if ((index = att.index(QString("name"))) != -1)
{
Rule->name = att.value(index);
Rule->rl.set_name(Rule->name.toAscii().data());
}
if ((index = att.index(QString("title"))) != -1)
{
Rule->title = att.value(index);
Rule->rl.set_title(Rule->title.toAscii().data());
}
break;
case CON_ELSEFILTER:
Container = in_elsefilter;
if (!Rule)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open ELSEFILTER outside of a RULE!").arg(XmlPath).arg(XmlLine));
return false;
}
break;
case CON_LAYER:
Container = in_layer;
if (!firstLayer)
{
Lay = allocLayer();
firstLayer = lastLayer = Lay;
}
else
{
Lay = allocLayer();
lastLayer->next = Lay;
lastLayer = Lay;
}
if ((index = att.index(QString("name"))) != -1)
Lay->name = att.value(index);
if ((index = att.index(QString("status"))) != -1)
Lay->status = getBool(att.value(index));
if ((index = att.index(QString("srs"))) != -1)
Lay->srs = att.value(index);
if ((index = att.index(QString("minzoom"))) != -1)
Lay->minzoom = att.value(index).toDouble();
if ((index = att.index(QString("maxzoom"))) != -1)
Lay->maxzoom = att.value(index).toDouble();
if ((index = att.index(QString("queryable"))) != -1)
Lay->queryable = getBool(att.value(index));
if ((index = att.index(QString("title"))) != -1)
Lay->title = att.value(index);
if ((index = att.index(QString("abstract"))) != -1)
Lay->abstract = att.value(index);
if ((index = att.index(QString("clear_label_cache"))) != -1)
Lay->clear_label = getBool(att.value(index));
break;
case CON_DATASOURCE:
Container = in_datasource;
break;
case CON_POINTSYMBOLIZER:
Container = in_pointsymbolizer;
if (!Rule)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open POINTSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
return false;
}
PointSymbolizer = getLastPointSymbolizer(Rule->PointSymbolizer);
if (!PointSymbolizer)
{
PointSymbolizer = allocPointSymbolizer();
Rule->PointSymbolizer = PointSymbolizer;
}
else
{
PointSymbolizer->next = allocPointSymbolizer();
PointSymbolizer = PointSymbolizer->next;
}
if ((index = att.index(QString("file"))) != -1)
PointSymbolizer->file = att.value(index);
if ((index = att.index(QString("type"))) != -1)
PointSymbolizer->type = getType(att.value(index));
if ((index = att.index(QString("width"))) != -1)
PointSymbolizer->width = att.value(index).toDouble();
if ((index = att.index(QString("height"))) != -1)
PointSymbolizer->height = att.value(index).toDouble();
if ((index = att.index(QString("allow_overlap"))) != -1)
PointSymbolizer->allow_overlap = getBool(att.value(index));
break;
break;
case CON_LINESYMBOLIZER:
Container = in_linesymbolizer;
if (!Rule)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open LINESYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
return false;
}
LineSymbolizer = getLastLineSymbolizer(Rule->LineSymbolizer);
if (!LineSymbolizer)
{
LineSymbolizer = allocLineSymbolizer();
Rule->LineSymbolizer = LineSymbolizer;
}
else
{
LineSymbolizer->next = allocLineSymbolizer();
LineSymbolizer = LineSymbolizer->next;
}
break;
case CON_POLYGONSYMBOLIZER:
Container = in_polygonsymbolizer;
if (!Rule)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open POLYGONSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
return false;
}
PolygonSymbolizer = getLastPolygonSymbolizer(Rule->PolygonSymbolizer);
if (!PolygonSymbolizer)
{
PolygonSymbolizer = allocPolygonSymbolizer();
Rule->PolygonSymbolizer = PolygonSymbolizer;
}
else
{
PolygonSymbolizer->next = allocPolygonSymbolizer();
PolygonSymbolizer = PolygonSymbolizer->next;
}
break;
case CON_TEXTSYMBOLIZER:
Container = in_textsymbolizer;
if (!Rule)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open TEXTSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
return false;
}
TextSymbolizer = getLastTextSymbolizer(Rule->TextSymbolizer);
if (!TextSymbolizer)
{
TextSymbolizer = allocTextSymbolizer();
Rule->TextSymbolizer = TextSymbolizer;
}
else
{
TextSymbolizer->next = allocTextSymbolizer();
TextSymbolizer = TextSymbolizer->next;
}
if ((index = att.index(QString("name"))) != -1)
TextSymbolizer->name = att.value(index);
if ((index = att.index(QString("face_name"))) != -1)
TextSymbolizer->face_name = att.value(index);
if ((index = att.index(QString("placement"))) != -1)
TextSymbolizer->placement = att.value(index);
if ((index = att.index(QString("size"))) != -1)
TextSymbolizer->size = att.value(index).toDouble();
if ((index = att.index(QString("fill"))) != -1)
TextSymbolizer->fill = colorToUInt(att.value(index));
if ((index = att.index(QString("halo_radius"))) != -1)
TextSymbolizer->halo_radius = att.value(index).toDouble();
if ((index = att.index(QString("wrap_width"))) != -1)
TextSymbolizer->wrap_width = att.value(index).toDouble();
if ((index = att.index(QString("alignment"))) != -1)
TextSymbolizer->alignment = att.value(index);
if ((index = att.index(QString("dx"))) != -1)
TextSymbolizer->dx = att.value(index).toDouble();
if ((index = att.index(QString("dy"))) != -1)
TextSymbolizer->dy = att.value(index).toDouble();
if ((index = att.index(QString("max_distance"))) != -1)
TextSymbolizer->maxdistance = att.value(index).toDouble();
if ((index = att.index(QString("min_distance"))) != -1)
TextSymbolizer->mindistance = att.value(index).toDouble();
break;
case CON_POLYGONPATTERNSYMBOLIZER:
Container = in_polygonpatternsymbolizer;
if (!Rule)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open POLYGONPATTERNSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
return false;
}
PolygonPatternSymbolizer = getLastPolygonPatternSymbolizer(Rule->PolygonPatternSymbolizer);
if (!PolygonPatternSymbolizer)
{
PolygonPatternSymbolizer = allocPolygonPatternSymbolizer();
Rule->PolygonPatternSymbolizer = PolygonPatternSymbolizer;
}
else
{
PolygonPatternSymbolizer->next = allocPolygonPatternSymbolizer();
PolygonPatternSymbolizer = PolygonPatternSymbolizer->next;
}
if ((index = att.index(QString("file"))) != -1)
PolygonPatternSymbolizer->file = att.value(index);
if ((index = att.index(QString("type"))) != -1)
PolygonPatternSymbolizer->type = getType(att.value(index));
if ((index = att.index(QString("width"))) != -1)
PolygonPatternSymbolizer->width = att.value(index).toDouble();
if ((index = att.index(QString("height"))) != -1)
PolygonPatternSymbolizer->height = att.value(index).toDouble();
if ((index = att.index(QString("allow_overlap"))) != -1)
PolygonPatternSymbolizer->allow_overlap = getBool(att.value(index));
break;
case CON_SHIELDSYMBOLIZER:
Container = in_shieldsymbolizer;
if (!Rule)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open SHIELDSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
return false;
}
ShieldSymbolizer = getLastShieldSymbolizer(Rule->ShieldSymbolizer);
if (!ShieldSymbolizer)
{
ShieldSymbolizer = allocShieldSymbolizer();
Rule->ShieldSymbolizer = ShieldSymbolizer;
}
else
{
ShieldSymbolizer->next = allocShieldSymbolizer();
ShieldSymbolizer = ShieldSymbolizer->next;
}
if ((index = att.index(QString("name"))) != -1)
ShieldSymbolizer->name = att.value(index);
if ((index = att.index(QString("face_name"))) != -1)
ShieldSymbolizer->face_name = att.value(index);
if ((index = att.index(QString("fill"))) != -1)
ShieldSymbolizer->fill = colorToUInt(att.value(index));
if ((index = att.index(QString("placement"))) != -1)
ShieldSymbolizer->placement = att.value(index);
if ((index = att.index(QString("file"))) != -1)
ShieldSymbolizer->file = att.value(index);
if ((index = att.index(QString("type"))) != -1)
ShieldSymbolizer->type = getType(att.value(index));
if ((index = att.index(QString("size"))) != -1)
ShieldSymbolizer->size = att.value(index).toDouble();
if ((index = att.index(QString("width"))) != -1)
ShieldSymbolizer->width = att.value(index).toDouble();
if ((index = att.index(QString("height"))) != -1)
ShieldSymbolizer->height = att.value(index).toDouble();
if ((index = att.index(QString("dx"))) != -1)
ShieldSymbolizer->dx = att.value(index).toDouble();
if ((index = att.index(QString("dy"))) != -1)
ShieldSymbolizer->dy = att.value(index).toDouble();
if ((index = att.index(QString("min_distance"))) != -1)
ShieldSymbolizer->mindistance = att.value(index).toDouble();
if ((index = att.index(QString("max_distance"))) != -1)
ShieldSymbolizer->maxdistance = att.value(index).toDouble();
break;
case CON_LINEPATTERNSYMBOLIZER:
Container = in_linepatternsymbolizer;
if (!Rule)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Open LINEPATTERNSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
return false;
}
LinePatternSymbolizer = getLastLinePatternSymbolizer(Rule->LinePatternSymbolizer);
if (!LinePatternSymbolizer)
{
LinePatternSymbolizer = allocLinePatternSymbolizer();
Rule->LinePatternSymbolizer = LinePatternSymbolizer;
}
else
{
LinePatternSymbolizer->next = allocLinePatternSymbolizer();
LinePatternSymbolizer = LinePatternSymbolizer->next;
}
if ((index = att.index(QString("file"))) != -1)
LinePatternSymbolizer->file = att.value(index);
if ((index = att.index(QString("type"))) != -1)
LinePatternSymbolizer->type = getType(att.value(index));
if ((index = att.index(QString("width"))) != -1)
LinePatternSymbolizer->width = att.value(index).toDouble();
if ((index = att.index(QString("height"))) != -1)
LinePatternSymbolizer->height = att.value(index).toDouble();
break;
}
}
i++;
}
i = FIRST_FLD;
while (i <= LAST_FLD)
{
if (qName.toLower() == getKey(i).toLower())
{
Field = i;
switch(Container)
{
case in_linesymbolizer:
Names = empty;
if (i == FLD_CSSPARAMETER)
{
if ((index = att.index(QString("name"))) != -1)
{
if (att.value(index).toLower() == QString("stroke"))
Names = stroke_stroke;
else if (att.value(index).toLower() == QString("stroke-width"))
Names = stroke_width;
else if (att.value(index).toLower() == QString("stroke-opacity"))
Names = stroke_opacity;
else if (att.value(index).toLower() == QString("stroke-linejoin"))
Names = stroke_linejoin;
else if (att.value(index).toLower() == QString("stroke-linecap"))
Names = stroke_linecap;
else if (att.value(index).toLower() == QString("stroke-dasharray"))
Names = stroke_dasharray;
}
else
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Required attribute NAME is missing in CSSPARAMETER inside LINESYMBOLIZER!").arg(XmlPath).arg(XmlLine));
return false;
}
}
break;
case in_polygonsymbolizer:
Names = empty;
if (i == FLD_CSSPARAMETER)
{
if ((index = att.index(QString("name"))) != -1)
{
if (att.value(index).toLower() == QString("fill"))
Names = fill;
else if (att.value(index).toLower() == QString("fill-opacity"))
Names = fill_opacity;
}
else
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Required attribute NAME is missing in CSSPARAMETER inside POLYGONSYMBOLIZER!").arg(XmlPath).arg(XmlLine));
return false;
}
}
break;
case in_datasource:
Names = empty;
if (i == FLD_PARAMETER)
{
if ((index = att.index(QString("name"))) != -1)
{
if (att.value(index).toLower() == QString("type"))
Names = type;
else if (att.value(index).toLower() == QString("file"))
Names = file;
else if (att.value(index).toLower() == QString("host"))
Names = host;
else if (att.value(index).toLower() == QString("user"))
Names = user;
else if (att.value(index).toLower() == QString("dbname"))
Names = dbname;
else if (att.value(index).toLower() == QString("table"))
Names = table;
else if (att.value(index).toLower() == QString("estimate_extent"))
Names = estimate_extent;
else if (att.value(index).toLower() == QString("extent"))
Names = extent;
else if (att.value(index).toLower() == QString("parser"))
Names = parser__;
else if (att.value(index).toLower() == QString("url"))
Names = url;
else if (att.value(index).toLower() == QString("bbox"))
Names = bbox;
}
else
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Required attribute NAME is missing in PARAMETER inside DATASOURCE!").arg(XmlPath).arg(XmlLine));
return false;
}
}
break;
case in_root:
Names = empty;
break;
case in_map:
Names = empty;
break;
case in_style:
Names = empty;
break;
case in_rule:
Names = empty;
break;
case in_pointsymbolizer:
Names = empty;
break;
case in_textsymbolizer:
Names = empty;
break;
case in_polygonpatternsymbolizer:
Names = empty;
break;
case in_layer:
Names = empty;
break;
case in_symbolizer:
Names = empty;
break;
case in_shieldsymbolizer:
Names = empty;
break;
case in_linepatternsymbolizer:
Names = empty;
break;
case in_elsefilter:
Names = empty;
break;
}
}
i++;
}
return true;
}
/*
* This is called every time an element is closed.
*/
bool SRender::endElement( const QString&, const QString&, const QString& qName)
{
if (qName.toLower() == QString("datasource"))
Container = in_layer;
else if (qName.toLower() == QString("layer"))
{
parameters p;
Container = in_map;
if (Lay->Datasource.type.toLower() == QString("shape") && __map_type == MAP_SHAPE)
{
QFileInfo qdi(Lay->Datasource.file);
QString hv0;
hv0 = qdi.fileName();
if (shapePath.right(1) == QChar('/'))
hv0 = shapePath + hv0;
else
hv0 = shapePath + "/" + hv0;
p["type"] = "shape";
p["file"] = hv0.toAscii().data();
}
else if (Lay->Datasource.type.toLower() == QString("postgis") && __map_type == MAP_GIS)
{
p["type"] = "postgis";
p["host"] = Lay->Datasource.host.toAscii().data();
p["user"] = Lay->Datasource.user.toAscii().data();
p["dbname"] = Lay->Datasource.dbname.toAscii().data();
p["table"] = Lay->Datasource.table.toAscii().data();
p["estimate_extent"] = (Lay->Datasource.estimate_extent) ? "true" : "false";
p["extent"] = QString("%1,%2,%3,%4").arg(Lay->Datasource.ext_lx).arg(Lay->Datasource.ext_ly).arg(Lay->Datasource.ext_rx).arg(Lay->Datasource.ext_ry).toAscii().data();
}
else if (Lay->Datasource.type.toAscii() == QString("osm") && __map_type == MAP_OSM)
{
p["type"] = "osm";
if (Lay->Datasource.parser.length() <= 0)
p["parser"] = "libxml2";
else
p["parser"] = Lay->Datasource.parser.toAscii().data();
if (!Lay->Datasource.url.isEmpty() && !Lay->Datasource.bbox.isEmpty())
{
p["url"] = Lay->Datasource.url.toAscii().data();
p["bbox"] = Lay->Datasource.bbox.toAscii().data();
}
else
p["file"] = shapePath.toAscii().data();
}
else
{
cerr << "Warning file " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Layer with no source! Ingnoring!" << endl;
return true;
}
layer lyr(Lay->name.toAscii().data());
if (!Lay->title.isEmpty())
lyr.set_title(Lay->title.toAscii().data());
if (!Lay->abstract.isEmpty())
lyr.set_abstract(Lay->abstract.toAscii().data());
lyr.set_datasource(datasource_cache::instance()->create(p));
if (!Lay->srs.isEmpty())
lyr.set_srs(Lay->srs.toAscii().data());
if (Lay->minzoom > 0.0)
lyr.setMinZoom(Lay->minzoom);
if (Lay->maxzoom > 0.0)
lyr.setMaxZoom(Lay->maxzoom);
lyr.set_clear_label_cache(Lay->clear_label);
// Add the styles
for (int i = 0; i < Lay->Styles.size(); i++)
{
if (findStyle (Lay->Styles.at(i)) != 0)
lyr.add_style(Lay->Styles.at(i).toAscii().data());
else
cerr << "Warning file " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Style \"" << Lay->Styles.at(i).toAscii().data() << "\" does not exist!" << endl;
}
lyr.setActive(Lay->status);
lyr.setQueryable(true);
m.addLayer(lyr);
box2d <double>le(lyr.envelope());
setMaxExtent(le.minx(), le.miny(), le.maxx(), le.maxy());
}
else if (qName.toLower() == QString("map"))
{
Container = in_root;
ControlSet = true;
}
else if (qName.toLower() == QString("pointsymbolizer"))
{
Container = in_rule;
if (!Rule || !PointSymbolizer)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of POINTSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
return false;
}
if (PointSymbolizer->file.length() == 0 || PointSymbolizer->width == 0 || PointSymbolizer->height == 0)
{
cerr << "Warning file " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Empty POINTSYMBOLIZER!" << endl;
point_symbolizer psym;
Rule->rl.append(psym);
}
else
{
// point_symbolizer ps(findIcon(PointSymbolizer->file).toAscii().data(), getTypeText(PointSymbolizer->type), PointSymbolizer->width, PointSymbolizer->height);
point_symbolizer ps(parse_path(findIcon(PointSymbolizer->file).toAscii().data()));
ps.set_allow_overlap (PointSymbolizer->allow_overlap);
Rule->rl.append(ps);
}
}
else if (qName.toLower() == QString("linesymbolizer"))
{
Container = in_rule;
if (!Rule || !LineSymbolizer)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of LINESYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
return false;
}
stroke st;
st.set_color (setColor(LineSymbolizer->stroke));
if (LineSymbolizer->stroke_width != 0.0)
st.set_width (LineSymbolizer->stroke_width);
if (!LineSymbolizer->stroke_linejoin.isEmpty())
{
if (LineSymbolizer->stroke_linejoin.toLower() == QString("miter"))
st.set_line_join (mapnik::MITER_JOIN);
else if (LineSymbolizer->stroke_linejoin.toLower() == QString("miter_revert") ||
LineSymbolizer->stroke_linejoin.toLower() == QString("miter-revert"))
st.set_line_join (mapnik::MITER_REVERT_JOIN);
else if (LineSymbolizer->stroke_linejoin.toLower() == QString("round"))
st.set_line_join (mapnik::ROUND_JOIN);
else if (LineSymbolizer->stroke_linejoin.toLower() == QString("bevel"))
st.set_line_join (mapnik::BEVEL_JOIN);
else
cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Unknown >>line_join<< \"" << LineSymbolizer->stroke_linejoin.toAscii().data() << "\" --> ignoring!" << endl;
}
if (!LineSymbolizer->stroke_linecap.isEmpty())
{
if (LineSymbolizer->stroke_linecap.toLower() == QString("butt"))
st.set_line_cap (mapnik::BUTT_CAP);
else if (LineSymbolizer->stroke_linecap.toLower() == QString("square"))
st.set_line_cap (mapnik::SQUARE_CAP);
else if (LineSymbolizer->stroke_linecap.toLower() == QString("round"))
st.set_line_cap (mapnik::ROUND_CAP);
else
cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Unknown >>line_cap<< \"" << LineSymbolizer->stroke_linecap.toAscii().data() << "\" --> ignoring!" << endl;
}
if (LineSymbolizer->stroke_dasharray[0] > 0 || LineSymbolizer->stroke_dasharray[1] > 0)
st.add_dash(LineSymbolizer->stroke_dasharray[0], LineSymbolizer->stroke_dasharray[1]);
if (LineSymbolizer->stroke_opacity != 0)
st.set_opacity(LineSymbolizer->stroke_opacity);
Rule->rl.append(line_symbolizer(st));
}
else if (qName.toLower() == QString("polygonsymbolizer"))
{
Container = in_rule;
if (!Rule || !PolygonSymbolizer)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of POLYGONSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
return false;
}
polygon_symbolizer ps(setColor(PolygonSymbolizer->fill));
if (PolygonSymbolizer->fill_opacity > 0.0)
ps.set_opacity(PolygonSymbolizer->fill_opacity);
Rule->rl.append(ps);
}
else if (qName.toLower() == QString("textsymbolizer"))
{
Container = in_rule;
if (!Rule || !TextSymbolizer)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of TEXTSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
return false;
}
if (TextSymbolizer->name.length() <= 0 || TextSymbolizer->face_name.length() <= 0 || TextSymbolizer->size <= 0)
cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Empty TEXTSYMBOLIZER found --> ignoring!" << endl;
else
{
// text_symbolizer ts(TextSymbolizer->name.toAscii().data(), TextSymbolizer->face_name.toAscii().data(), TextSymbolizer->size, setColor(TextSymbolizer->fill));
std::stringstream s;
s << "[" << TextSymbolizer->name.toAscii().data() << "]";
text_symbolizer ts(parse_expression(s.str()), TextSymbolizer->face_name.toAscii().data(), TextSymbolizer->size, setColor(TextSymbolizer->fill));
if (TextSymbolizer->halo_radius != 0.0)
ts.set_halo_radius((unsigned int)TextSymbolizer->halo_radius);
if (TextSymbolizer->wrap_width != 0.0)
ts.set_wrap_width((unsigned int)TextSymbolizer->wrap_width);
if (TextSymbolizer->mindistance != 0)
ts.set_label_spacing(TextSymbolizer->mindistance);
if (!TextSymbolizer->placement.isEmpty())
{
if (TextSymbolizer->placement.toLower() == QString("point"))
ts.set_label_placement(mapnik::POINT_PLACEMENT);
else if (TextSymbolizer->placement.toLower() == QString("line"))
ts.set_label_placement(mapnik::LINE_PLACEMENT);
else
cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Unknown >>label placement<< \"" << TextSymbolizer->placement.toAscii().data() << "\" --> ignoring!" << endl;
}
if (!TextSymbolizer->alignment.isEmpty())
{
if (TextSymbolizer->alignment.toLower() == QString("top"))
ts.set_vertical_alignment(mapnik::V_TOP);
else if (TextSymbolizer->alignment.toLower() == QString("middle"))
ts.set_vertical_alignment(mapnik::V_MIDDLE);
else if (TextSymbolizer->alignment.toLower() == QString("bottom"))
ts.set_vertical_alignment(mapnik::V_BOTTOM);
else
cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Unknown >>vertical placement<< \"" << TextSymbolizer->alignment.toAscii().data() << "\" --> ignoring!" << endl;
}
if (TextSymbolizer->dx != 0 || TextSymbolizer->dy != 0)
ts.set_displacement(TextSymbolizer->dx, TextSymbolizer->dy);
Rule->rl.append(ts);
}
}
else if (qName.toLower() == QString("polygonpatternsymbolizer"))
{
Container = in_rule;
if (!Rule || !PolygonPatternSymbolizer)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Endin of POLYGONPATTERNSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
return false;
}
if (PolygonPatternSymbolizer->file.length() <= 0)
cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Incomplete POLYGONPATTERNSYMBOLIZER --> ignoring!" << endl;
else
{
// Rule->rl.append(polygon_pattern_symbolizer(findIcon(PolygonPatternSymbolizer->file).toAscii().data(),
// getTypeText(PolygonPatternSymbolizer->type),
// PolygonPatternSymbolizer->width,
// PolygonPatternSymbolizer->height));
Rule->rl.append(polygon_pattern_symbolizer(parse_path(findIcon(PolygonPatternSymbolizer->file).toAscii().data())));
}
}
else if (qName.toLower() == QString("shieldsymbolizer"))
{
Container = in_rule;
if (!Rule || !ShieldSymbolizer)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of SHIELDSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
return false;
}
// shield_symbolizer ss(ShieldSymbolizer->name.toAscii().data(),
// ShieldSymbolizer->face_name.toAscii().data(),
// ShieldSymbolizer->size, setColor(ShieldSymbolizer->fill),
// findIcon(ShieldSymbolizer->file).toAscii().data(),
// getTypeText(ShieldSymbolizer->type),
// ShieldSymbolizer->width, ShieldSymbolizer->height);
std::stringstream s;
s << "[" << ShieldSymbolizer->name.toAscii().data() << "]";
shield_symbolizer ss(parse_expression(s.str()),
ShieldSymbolizer->face_name.toAscii().data(),
ShieldSymbolizer->size, setColor(ShieldSymbolizer->fill),
parse_path(findIcon(ShieldSymbolizer->file).toAscii().data()));
if (!ShieldSymbolizer->placement.isEmpty())
ss.set_label_placement((ShieldSymbolizer->placement.toLower() == QString("point")) ? mapnik::POINT_PLACEMENT : mapnik::LINE_PLACEMENT);
if (ShieldSymbolizer->dx != 0 || ShieldSymbolizer->dy != 0)
ss.set_displacement(ShieldSymbolizer->dx, ShieldSymbolizer->dy);
if (ShieldSymbolizer->mindistance != 0)
ss.set_label_spacing(ShieldSymbolizer->mindistance);
Rule->rl.append(ss);
}
else if (qName.toLower() == QString("linepatternsymbolizer"))
{
Container = in_rule;
if (!Rule || !LinePatternSymbolizer)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of LINEPATTERNSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
return false;
}
// Rule->rl.append(line_pattern_symbolizer(findIcon(LinePatternSymbolizer->file).toAscii().data(),
// getTypeText(LinePatternSymbolizer->type),
// LinePatternSymbolizer->width,
// LinePatternSymbolizer->height));
Rule->rl.append(line_pattern_symbolizer(parse_path(findIcon(LinePatternSymbolizer->file).toAscii().data())));
}
else if (qName.toLower() == QString("filter") ||
qName.toLower() == QString("maxscaledenominator") ||
qName.toLower() == QString("minscaledenominator"))
Container = in_rule;
else if (qName.toLower() == QString("rule"))
Container = in_style;
else if (qName.toLower() == QString("elsefilter"))
{
Container = in_rule;
if (!Rule)
{
KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of ELSEFILTER outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
return false;
}
Rule->rl.set_else(true);
}
else if (qName.toLower() == QString("style"))
{
Container = in_map;
feature_type_style style;
if (Style->rule)
{
Rule = Style->rule;
while (Rule)
{
style.add_rule(Rule->rl);
Rule = Rule->next;
}
}
// Add style to map
m.insert_style(Style->name.toAscii().data(), style);
}
return true;
}
/*
* The reader calls this function when it has parsed a chunk of character data
* - either normal character data or character data inside a CDATA section.
*/
bool SRender::characters (const QString& chraw)
{
if (chraw.at(0) == QChar('\n'))
{
XmlLine++;
return true;
}
QString ch = chraw.trimmed();
if (ch.length() == 0)
return true;
if (Container == in_rule && Rule)
{
if (Field == FLD_FILTER)
{
Rule->filter = ch;
if (!Rule->filter.isEmpty())
{
std::stringstream s;
s << "[" << Rule->filter.toLatin1().data() << "] = 'latin1'";
Rule->rl.set_filter(parse_expression(s.str()));
// Rule->rl.set_filter(create_filter(Rule->filter.toLatin1().data(), "latin1"));
}
else
cerr << "Warning in file " << XmlPath.toAscii().data() << " at line " << XmlLine << ": Ignoring empty filter!" << endl;
}
else if (Field == FLD_MAXSCALE)
{
Rule->maxscale = ch.toDouble();
Rule->rl.set_max_scale(Rule->maxscale);
}
else if (Field == FLD_MINSCALE)
{
Rule->minscale = ch.toDouble();
Rule->rl.set_min_scale(Rule->minscale);
}
}
else if (Container == in_linesymbolizer && LineSymbolizer)
{
if (Field == FLD_CSSPARAMETER)
{
if (Names == stroke_stroke)
LineSymbolizer->stroke = colorToUInt(ch);
else if (Names == stroke_width)
LineSymbolizer->stroke_width = ch.toDouble();
else if (Names == stroke_linejoin)
LineSymbolizer->stroke_linejoin = ch;
else if (Names == stroke_linecap)
LineSymbolizer->stroke_linecap = ch;
else if (Names == stroke_opacity)
LineSymbolizer->stroke_opacity = ch.toDouble();
else if (Names == stroke_dasharray)
{
int pos;
QString arr = ch;
QStringList list;
list = arr.split(",", QString::SkipEmptyParts);
for (pos = 0; pos < list.size() && pos < 10; pos++)
LineSymbolizer->stroke_dasharray[pos] = list.at(pos).toDouble();
LineSymbolizer->stroke_anz = pos;
}
}
}
else if (Container == in_polygonsymbolizer && PolygonSymbolizer)
{
if (Field == FLD_CSSPARAMETER)
{
if (Names == fill)
PolygonSymbolizer->fill = colorToUInt(ch);
else if (Names == fill_opacity)
PolygonSymbolizer->fill_opacity = ch.toDouble();
}
}
else if (Container == in_layer && Lay)
{
if (Field == FLD_STYLENAME)
Lay->Styles << ch;
}
else if (Container == in_datasource && Lay)
{
if (Field == FLD_PARAMETER)
{
if (Names == type)
Lay->Datasource.type = ch;
else if (Names == file)
{
QFileInfo qf(ch);
QString hv0;
hv0 = shapePath;
if (hv0.right(1) != QString("/"))
hv0 += "/";
hv0 += qf.fileName();
if (__map_type == MAP_SHAPE)
qf.setFile (hv0 + ".shp");
else if (__map_type == MAP_OSM)
qf.setFile (hv0 + ".osm");
if (!qf.exists())
{
if (__map_type == MAP_SHAPE)
KMessageBox::error(0, i18n("The shape file \"%1\" at line %2 does not exist!").arg(hv0+".shp").arg(XmlLine));
else if (__map_type == MAP_OSM)
KMessageBox::error(0, i18n("The OSM file \"%1\" at line %2 does not exist!").arg(hv0+".osm").arg(XmlLine));
return false;
}
Lay->Datasource.file = hv0;
}
else if (Names == parser__)
Lay->Datasource.parser = ch;
else if (Names == url)
Lay->Datasource.url = ch;
else if (Names == bbox)
Lay->Datasource.bbox = ch;
else if (Names == host)
Lay->Datasource.host = ch;
else if (Names == user)
Lay->Datasource.user = ch;
else if (Names == dbname)
Lay->Datasource.dbname = ch;
else if (Names == table)
Lay->Datasource.table = ch;
else if (Names == estimate_extent)
Lay->Datasource.estimate_extent = getBool(ch);
else if (Names == extent)
{
QString arr = ch;
QStringList list;
list = arr.split(",");
if (list.size() >= 1)
Lay->Datasource.ext_lx = list.at(0).toDouble();
if (list.size() >= 2)
Lay->Datasource.ext_ly = list.at(1).toDouble();
if (list.size() >= 3)
Lay->Datasource.ext_rx = list.at(2).toDouble();
if (list.size() >= 4)
Lay->Datasource.ext_ry = list.at(3).toDouble();
}
}
}
return true;
}
QString SRender::getKey (int pos)
{
int i = 0;
while (token[i].id > 0)
{
if (token[i].id == pos)
return token[i].name;
i++;
}
return QString::null;
}
TYPES SRender::getType(QString ty)
{
if (ty.toLower() == QString("png"))
return type_png;
else if (ty.toLower() == QString("gif"))
return type_gif;
else if (ty.toLower() == QString("jpg"))
return type_jpg;
else if (ty.toLower() == QString("xpm"))
return type_xpm;
else if (ty.toLower() == QString("bmp"))
return type_bmp;
else if (ty.toLower() == QString("tif") || ty.toLower() == QString("tiff"))
return type_tif;
return type_png;
}
char *grTypes[] = { (char *)"png", (char *)"gif", (char *)"jpg", (char*)"xpm",
(char *)"bmp", (char *)"tif" };
char *SRender::getTypeText(TYPES type)
{
switch (type)
{
case type_png: return grTypes[0]; break;
case type_gif: return grTypes[1]; break;
case type_jpg: return grTypes[2]; break;
case type_xpm: return grTypes[3]; break;
case type_bmp: return grTypes[4]; break;
case type_tif: return grTypes[5]; break;
}
return 0;
}
bool SRender::getBool(QString b)
{
if (b.toLower() == QString("true") ||
b.toLower() == QString("on") ||
b.toLower() == QString("1") ||
b.toLower() == QString("yes") ||
b.toLower() == QString("t") ||
b.toLower() == QString("y"))
return true;
return false;
}
bool SRender::getMap (double lx, double ly, double rx, double ry)
{
QXmlSimpleReader reader;
QString hv0;
QFile file(XmlPath);
QDir dir(fontPath);
double plx, ply, prx, pry;
if (_width <= 0 || _height <= 0)
return false;
hv0 = pluginPath;
if (hv0.right(1) != QString("/"))
hv0 += "/";
datasource_cache::instance()->register_datasources(hv0.toAscii().data());
hv0 = fontPath;
if (hv0.right(1) != QString("/"))
hv0 += "/";
// Load all fonts in directory
if (!dir.exists())
{
KMessageBox::error(0, i18n("The font directory does not exist! Please select a valid directory with at least one true type font in it!"));
return false;
}
QStringList filters;
filters << "*.ttf";
dir.setNameFilters(filters);
dir.setFilter(QDir::Readable | QDir::Files);
QFileInfoList list = dir.entryInfoList();
for (int i = 0; i < list.size(); ++i)
{
QString f;
QFileInfo fileInfo = list.at(i);
f = hv0 + fileInfo.fileName();
freetype_engine::register_font(f.toAscii().data());
}
m.set_width(_width);
m.set_height(_height);
try
{
if (!ControlSet) // Initialize the map?
{
QXmlInputSource source (&file);
reader.setContentHandler (this);
reader.parse (source);
}
plx = lx;
ply = ly;
prx = rx;
pry = ry;
projection pj(m.srs());
if (!geographic && pj.is_geographic())
{
pj.inverse(plx, ply);
pj.inverse(prx, pry);
}
if (geographic && pj.is_geographic())
{
pj.forward(plx, ply);
pj.forward(prx, pry);
}
// First we use Mapnik to create the map
m.zoom_to_box(box2d<double>(plx, ply, prx, pry));
// Here we render the map to an image buffer
image_32 buf(m.width(), m.height());
agg_renderer<image_32> ren(m, buf);
ren.apply();
// Put the image into a Qt object
QImage image((uchar*)buf.raw_data(), m.width(), m.height(), QImage::Format_ARGB32);
pxmap = QPixmap::fromImage(image.rgbSwapped());
}
catch (const mapnik::config_error &ex)
{
KMessageBox::error(0, i18n("Configuration error: %1").arg(ex.what()));
return false;
}
catch (const std::exception &ex)
{
KMessageBox::error(0, i18n("Exception at file %1: %2").arg(XmlPath).arg(ex.what()));
return false;
}
catch (...)
{
KMessageBox::error(0, i18n("Unknown exception occured!"));
return false;
}
return true;
}
void SRender::setMaxExtent(double lx, double ly, double rx, double ry)
{
if (lx > 0 && _lx > lx)
_lx = lx;
if (lx < 0 && _lx < lx)
_lx = lx;
if (ly > 0 && _ly > ly)
_ly = ly;
if (ly < 0 && _ly < ly)
_ly = ly;
if (rx > 0 && _rx < rx)
_rx = rx;
if (rx < 0 && _rx > rx)
_rx = rx;
if (ry > 0 && _ry < ry)
_ry = ry;
if (ry < 0 && _ry > ry)
_ry = ry;
}
QString SRender::findIcon(QString ic)
{
QString ptf, icon;
QFileInfo fi(ic);
icon = fi.fileName();
ptf = KStandardDirs::locate("data", QString("sportwatcher/icons/%1").arg(icon));
if (ptf.length() < icon.length())
{
KMessageBox::error(0, i18n("The icon %1 was not found!").arg(icon));
ptf.clear();
}
return ptf;
}
color SRender::setColor(unsigned col)
{
color c;
#if MAPNIK_VERSION == 600
c.set_bgr(col);
#else
int r, g, b;
b = col / 65536;
g = (col - (b * 65536)) / 256;
r = col - ((b* 65536) + (g * 256));
c.set_red(r);
c.set_green(g);
c.set_blue(b);
#endif
return c;
}
RULE *SRender::getLastRule(RULE *first)
{
RULE *akt = first;
while (akt)
{
if (!akt->next)
return akt;
akt = akt->next;
}
return 0;
}
POINTSYMBOLIZER *SRender::getLastPointSymbolizer(POINTSYMBOLIZER *first)
{
POINTSYMBOLIZER *akt = first;
while (akt)
{
if (!akt->next)
return akt;
akt = akt->next;
}
return 0;
}
LINESYMBOLIZER *SRender::getLastLineSymbolizer(LINESYMBOLIZER *first)
{
LINESYMBOLIZER *akt = first;
while (akt)
{
if (!akt->next)
return akt;
akt = akt->next;
}
return 0;
}
POLYGONSYMBOLIZER *SRender::getLastPolygonSymbolizer(POLYGONSYMBOLIZER *first)
{
POLYGONSYMBOLIZER *akt = first;
while (akt)
{
if (!akt->next)
return akt;
akt = akt->next;
}
return 0;
}
TEXTSYMBOLIZER *SRender::getLastTextSymbolizer(TEXTSYMBOLIZER *first)
{
TEXTSYMBOLIZER *akt = first;
while (akt)
{
if (!akt->next)
return akt;
akt = akt->next;
}
return 0;
}
POLYGONPATTERNSYMBOLIZER *SRender::getLastPolygonPatternSymbolizer(POLYGONPATTERNSYMBOLIZER *first)
{
POLYGONPATTERNSYMBOLIZER *akt = first;
while (akt)
{
if (!akt->next)
return akt;
akt = akt->next;
}
return 0;
}
SHIELDSYMBOLIZER *SRender::getLastShieldSymbolizer(SHIELDSYMBOLIZER *first)
{
SHIELDSYMBOLIZER *akt = first;
while (akt)
{
if (!akt->next)
return akt;
akt = akt->next;
}
return 0;
}
LINEPATTERNSYMBOLIZER *SRender::getLastLinePatternSymbolizer(LINEPATTERNSYMBOLIZER *first)
{
LINEPATTERNSYMBOLIZER *akt = first;
while (akt)
{
if (!akt->next)
return akt;
akt = akt->next;
}
return 0;
}
STYLE *SRender::findStyle(QString name)
{
STYLE *akt = firstStyle;
while (akt)
{
if (akt->name.toLower() == name.toLower())
return akt;
akt = akt->next;
}
return 0;
}
unsigned SRender::colorToUInt(QString col)
{
QColor qc(col);
return (qc.blue() * 65536) + (qc.green() * 256) + qc.red();
}
STYLE *SRender::allocStyle()
{
STYLE *St = new STYLE;
St->name.clear();
St->rule = 0;
St->next = 0;
return St;
}
RULE *SRender::allocRule()
{
RULE *Ru = new RULE;
Ru->name.clear();
Ru->title.clear();
Ru->maxscale = 0;
Ru->minscale = 0;
Ru->elsefilter = false;
Ru->filter.clear();
Ru->LineSymbolizer = 0;
Ru->PolygonSymbolizer = 0;
Ru->TextSymbolizer = 0;
Ru->PointSymbolizer = 0;
Ru->PolygonPatternSymbolizer = 0;
Ru->ShieldSymbolizer = 0;
Ru->LinePatternSymbolizer = 0;
Ru->next = 0;
return Ru;
}
LAYER *SRender::allocLayer()
{
LAYER *La = new LAYER;
La->name.clear(); // The unique name
La->title.clear();
La->abstract.clear();
La->status = false; // Is it active?
La->clear_label = false;
La->srs.clear(); // Projection
La->minzoom = 0.0;
La->maxzoom = 0.0;
La->queryable = false;
La->Datasource.type.clear();
La->Datasource.file.clear();
La->Datasource.parser.clear();
La->Datasource.url.clear();
La->Datasource.bbox.clear();
La->Datasource.host.clear();
La->Datasource.user.clear();
La->Datasource.dbname.clear();
La->Datasource.table.clear();
La->Datasource.estimate_extent = false;
La->Datasource.ext_lx = 0.0;
La->Datasource.ext_ly = 0.0;
La->Datasource.ext_rx = 0.0;
La->Datasource.ext_ry = 0.0;
La->next = 0;
return La;
}
LINEPATTERNSYMBOLIZER *SRender::allocLinePatternSymbolizer()
{
LINEPATTERNSYMBOLIZER *lps = new LINEPATTERNSYMBOLIZER;
lps->file.clear();
lps->type = type_png; // enum TYPES
lps->width = 0.0;
lps->height = 0.0;
lps->next = 0;
return lps;
}
SHIELDSYMBOLIZER *SRender::allocShieldSymbolizer()
{
SHIELDSYMBOLIZER *ss = new SHIELDSYMBOLIZER;
ss->name.clear();
ss->face_name.clear();
ss->size = 0.0;
ss->fill = 0; // Color
ss->placement.clear();
ss->file.clear();
ss->type = type_png; // enum TYPES
ss->width = 0.0;
ss->height = 0.0;
ss->dx = 0.0;
ss->dy = 0.0;
ss->mindistance = 0.0;
ss->maxdistance = 0.0;
ss->next = 0;
return ss;
}
POLYGONPATTERNSYMBOLIZER *SRender::allocPolygonPatternSymbolizer()
{
POLYGONPATTERNSYMBOLIZER *pps = new POLYGONPATTERNSYMBOLIZER;
pps->file.clear();
pps->type = type_png; // enum TYPES
pps->width = 0.0;
pps->height = 0.0;
pps->allow_overlap = false;
pps->next = 0;
return pps;
}
POINTSYMBOLIZER *SRender::allocPointSymbolizer()
{
POINTSYMBOLIZER *ps = new POINTSYMBOLIZER;
ps->file.clear();
ps->type = type_png; // enum TYPES
ps->width = 0.0;
ps->height = 0.0;
ps->allow_overlap = false;
ps->next = 0;
return ps;
}
TEXTSYMBOLIZER *SRender::allocTextSymbolizer()
{
TEXTSYMBOLIZER *ts = new TEXTSYMBOLIZER;
ts->name.clear();
ts->face_name.clear();
ts->placement.clear();
ts->alignment.clear();
ts->size = 0;
ts->fill = 0; // Color
ts->halo_radius = 0;
ts->wrap_width = 0;
ts->dx = 0.0;
ts->dy = 0.0;
ts->mindistance = 0.0;
ts->maxdistance = 0.0;
ts->next = 0;
return ts;
}
POLYGONSYMBOLIZER *SRender::allocPolygonSymbolizer()
{
POLYGONSYMBOLIZER *ps = new POLYGONSYMBOLIZER;
memset (ps, 0, sizeof(POLYGONSYMBOLIZER));
return ps;
}
LINESYMBOLIZER *SRender::allocLineSymbolizer()
{
LINESYMBOLIZER *ls = new LINESYMBOLIZER;
ls->stroke = 0; // Color
ls->stroke_width = 0.0;
ls->stroke_linejoin.clear();
ls->stroke_linecap.clear();
for (int i = 0; i < 10; i++)
ls->stroke_dasharray[i] = 0.0;
ls->stroke_anz = 0; // number of entries in dasharray
ls->stroke_opacity = 0.0;
ls->next = 0;
return ls;
}
#endif // HAVE_MAPNIK