Subversion Repositories public

Rev

Rev 277 | Rev 280 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
273 andreas 1
//
274 andreas 2
// C++ Implementation: SRender
273 andreas 3
//
4
// Description: Renders a map from some shape files. This class assumes,
5
//              that the shape files are in open street map format!
6
//
7
//
8
// Author: Andreas Theofilu <andreas@theosys.at>, (C) 2009
9
//
10
// Copyright: See COPYING file that comes with this distribution
11
//
12
//
13
#define BOOST_SPIRIT_THREADSAFE
274 andreas 14
#include <QLabel>
15
#include <QString>
16
#include <QXmlReader>
17
#include <QDir>
18
#include <QColor>
275 andreas 19
#include <QImage>
274 andreas 20
#include <KStandardDirs>
21
#include <KConfig>
22
#include <KLocale>
23
#include <KMessageBox>
24
#include <KGlobalSettings>
25
#include <KConfigGroup>
275 andreas 26
#include <KIconLoader>
273 andreas 27
 
28
#include "config.h"
29
#include "render.h"
274 andreas 30
#include <iostream>
273 andreas 31
 
32
#define CON_MAP			100
33
#define CON_STYLE		101
34
#define CON_RULE		102
35
#define CON_LINESYMBOLIZER	103
36
#define CON_POINTSYMBOLIZER	104
37
#define CON_POLYGONSYMBOLIZER	105
38
#define CON_TEXTSYMBOLIZER	106
39
#define CON_POLYGONPATTERNSYMBOLIZER	107
40
#define CON_LAYER		108
41
#define CON_DATASOURCE		109
274 andreas 42
#define CON_SHIELDSYMBOLIZER	110
43
#define CON_LINEPATTERNSYMBOLIZER	111
276 andreas 44
#define CON_ELSEFILTER		112
273 andreas 45
 
46
#define FLD_FILTER		200
47
#define FLD_CSSPARAMETER	201
48
#define FLD_MINSCALE		202
49
#define FLD_MAXSCALE		203
50
#define FLD_STYLENAME		204
51
#define FLD_PARAMETER		205
52
 
53
#define ATT_FILL		300
54
#define ATT_FILE		301
55
#define ATT_TYPE		302
56
#define ATT_WIDTH		303
57
#define ATT_HEIGHT		304
58
#define ATT_SIZE		305
59
#define ATT_NAME		306
60
#define ATT_FACENAME		307
61
#define ATT_DY			308
62
#define ATT_HALORADIUS		309
63
#define ATT_WRAPWIDTH		310
64
#define ATT_MINDISTANCE		311
65
#define ATT_MAXDISTANCE		312
66
#define ATT_PLACEMENT		313
67
#define ATT_ALLOWOVERLAP	314
68
#define ATT_STATUS		315
69
#define ATT_SRS			316
275 andreas 70
#define ATT_DX			317
276 andreas 71
#define ATT_ALIGNMENT		318
273 andreas 72
 
73
#define FIRST_CON		100
276 andreas 74
#define LAST_CON		112
273 andreas 75
 
76
#define FIRST_FLD		200
77
#define LAST_FLD		205
78
 
79
#define FIRST_ATT		300
276 andreas 80
#define LAST_ATT		318
273 andreas 81
 
274 andreas 82
using std::cout;
83
using std::cerr;
84
using std::clog;
85
using std::endl;
86
 
87
TOKEN token[] = {
273 andreas 88
	// Containers
274 andreas 89
	{ CON_MAP,			in_map,			QString("Map") },
90
	{ CON_STYLE,			in_style,		QString("Style") },
91
	{ CON_RULE,			in_rule,		QString("Rule") },
92
	{ CON_LINESYMBOLIZER,		in_linesymbolizer,	QString("LineSymbolizer") },
93
	{ CON_POINTSYMBOLIZER,		in_pointsymbolizer,	QString("PointSymbolizer") },
94
	{ CON_POLYGONSYMBOLIZER,	in_polygonsymbolizer,	QString("PolygonSymbolizer") },
95
	{ CON_TEXTSYMBOLIZER,		in_textsymbolizer,	QString("TextSymbolizer") },
96
	{ CON_POLYGONPATTERNSYMBOLIZER,	in_polygonpatternsymbolizer,	QString("PolygonPatternSymbolizer") },
97
	{ CON_LAYER,			in_layer,		QString("Layer") },
98
	{ CON_DATASOURCE,		in_datasource,		QString("Datasource") },
99
	{ CON_SHIELDSYMBOLIZER,		in_shieldsymbolizer,	QString("ShieldSymbolizer") },
275 andreas 100
	{ CON_LINEPATTERNSYMBOLIZER,	in_linepatternsymbolizer, QString("LinePatternSymbolizer") },
276 andreas 101
	{ CON_ELSEFILTER,		in_rule,		QString("ElseFilter") },
273 andreas 102
	// Fields
274 andreas 103
	{ FLD_FILTER,			in_rule,		QString("Filter") },
104
	{ FLD_CSSPARAMETER,		in_symbolizer,		QString("CSSParameter") },
105
	{ FLD_MINSCALE,			in_rule,		QString("MinScaleDenominator") },
106
	{ FLD_MAXSCALE,			in_rule,		QString("MaxScaleDenominator") },
107
	{ FLD_STYLENAME,		in_style,		QString("StyleName") },
108
	{ FLD_PARAMETER,		in_datasource,		QString("Parameter") },
273 andreas 109
	// Attributes
274 andreas 110
	{ ATT_FILL,			in_symbolizer,		QString("fill") },
111
	{ ATT_NAME,			in_symbolizer,		QString("name") },
112
	{ ATT_FILE,			in_symbolizer,		QString("file") },
113
	{ ATT_TYPE,			in_symbolizer,		QString("type") },
114
	{ ATT_WIDTH,			in_symbolizer,		QString("width") },
115
	{ ATT_HEIGHT,			in_symbolizer,		QString("height") },
116
	{ ATT_SIZE,			in_symbolizer,		QString("size") },
117
	{ ATT_FACENAME,			in_symbolizer,		QString("face_name") },
275 andreas 118
	{ ATT_DX,			in_symbolizer,		QString("dx") },
274 andreas 119
	{ ATT_DY,			in_symbolizer,		QString("dy") },
120
	{ ATT_HALORADIUS,		in_symbolizer,		QString("halo_radius") },
121
	{ ATT_WRAPWIDTH,		in_symbolizer,		QString("wrap_width") },
122
	{ ATT_MINDISTANCE,		in_symbolizer,		QString("min_distance") },
123
	{ ATT_MAXDISTANCE,		in_symbolizer,		QString("max_distance") },
124
	{ ATT_PLACEMENT,		in_symbolizer,		QString("placement") },
125
	{ ATT_ALLOWOVERLAP,		in_symbolizer,		QString("allow_overlap") },
126
	{ ATT_STATUS,			in_layer,		QString("status") },
127
	{ ATT_SRS,			in_layer,		QString("srs") },
276 andreas 128
	{ ATT_ALIGNMENT,		in_symbolizer,		QString("alignment") },
274 andreas 129
	{ 0,				in_root,		QString::null }
273 andreas 130
};
131
 
274 andreas 132
SRender::SRender()
273 andreas 133
{
274 andreas 134
	label = 0;
135
	shapePath = QString::null;
136
	XmlPath = QString::null;
137
	Lay = firstLayer = lastLayer = 0;
138
	Style = firstStyle = lastStyle = 0;
273 andreas 139
	Rule = 0;
140
	LineSymbolizer = 0;
141
	PolygonSymbolizer = 0;
142
	TextSymbolizer = 0;
143
	PointSymbolizer = 0;
144
	PolygonPatternSymbolizer = 0;
145
	ShieldSymbolizer = 0;
146
	LinePatternSymbolizer = 0;
275 andreas 147
	_lx = _ly = 180.0;
148
	_rx = _ry = -180.0;
276 andreas 149
	__map_type = MAP_SHAPE;		// The default map type
274 andreas 150
	// This is true, when a XML file was parsed successfully
151
	ControlSet = false;
152
 
153
	// Read settings from config file
154
	KConfig cfg (QString("sportwatcher.rc"), KConfig::SimpleConfig);
155
	KConfigGroup ic (&cfg, "SportWatcher");
156
	KConfigGroup sh (&cfg, "ShapeFile");
157
	QString basePath = ic.readEntry("Data", QDir::home().absolutePath() + "/.sportwatcher");
158
	shapePath = ic.readEntry("MAP", basePath + "/shapefiles");
159
	// Read the shape specific informations
160
#ifdef MAPNIK_PLUGINS
161
	pluginPath = QString(MAPNIK_PLUGINS);
162
#else
277 andreas 163
	QDir dir;
274 andreas 164
	// Test some default path
165
	if (dir.exists(QString("/usr/lib/mapnik/input")))
166
	   pluginPath = sh.readEntry("PluginPath", QString("/usr/lib/mapnik/input"));
167
	else if (dir.exists(QString("/usr/local/lib/mapnik/input")))
168
	   pluginPath = sh.readEntry("PluginPath", QString("/usr/local/lib/mapnik/input"));
169
	else if (dir.exists(QString("/usr/lib/mapnik/0.6/input")))
170
	   pluginPath = sh.readEntry("PluginPath", QString("/usr/lib/mapnik/0.6/input"));
171
	else
172
	   pluginPath = sh.readEntry("PluginPath", QString(""));
173
#endif
174
#ifdef MAPNIK_FONTS
175
	fontPath = QString(MAPNIK_FONTS);
176
#else
177
	// Test some default path
178
	if (dir.exists(QString("/usr/lib/mapnik/fonts")))
179
	   fontPath = sh.readEntry("FontPath", QString("/usr/lib/mapnik/fonts"));
180
	else if (dir.exists(QString("/usr/local/lib/mapnik/fonts")))
181
	   fontPath = sh.readEntry("FontPath", QString("/usr/local/lib/mapnik/fonts"));
182
	else if (dir.exists(QString("/usr/share/mapnik/fonts")))
183
	   fontPath = sh.readEntry("FontPath", QString("/usr/share/mapnik/fonts"));
184
	else if (dir.exists(QString("/usr/share/fonts/truetype/ttf-dejavu")))
185
	   fontPath = sh.readEntry("FontPath", QString("/usr/share/fonts/truetype/ttf-dejavu"));
186
	else
187
	   fontPath = sh.readEntry("FontPath", QString(""));
188
#endif
189
	XmlPath = sh.readEntry("XmlFile", basePath + "/shapefiles/osm.xml");
278 andreas 190
	geographic = sh.readEntry("Geographic", false);
273 andreas 191
}
192
 
274 andreas 193
SRender::~SRender()
273 andreas 194
{
274 andreas 195
	startDocument();	// Clean everything
196
	ControlSet = false;
197
}
273 andreas 198
 
274 andreas 199
bool SRender::startDocument()
200
{
201
	m.remove_all();		// delete styles and layers from map
202
 
273 andreas 203
	if (firstStyle)		// free if allocated
204
	{
205
	   Style = firstStyle;
206
 
207
	   while (Style)
208
	   {
274 andreas 209
	      STYLE *sakt = Style->next;
210
 
273 andreas 211
	      if (Style->rule)
212
	      {
213
		 RULE *rule = Style->rule;
214
 
215
		 while (rule)
216
		 {
217
		    RULE *rakt = rule->next;
218
		    LINESYMBOLIZER *LineSymbolizer = rule->LineSymbolizer;
219
		    POLYGONSYMBOLIZER *PolygonSymbolizer = rule->PolygonSymbolizer;
220
		    TEXTSYMBOLIZER *TextSymbolizer = rule->TextSymbolizer;
221
		    POINTSYMBOLIZER *PointSymbolizer = rule->PointSymbolizer;
222
		    POLYGONPATTERNSYMBOLIZER *PolygonPatternSymbolizer = rule->PolygonPatternSymbolizer;
274 andreas 223
		    SHIELDSYMBOLIZER *ShieldSymbolizer = rule->ShieldSymbolizer;
273 andreas 224
		    LINEPATTERNSYMBOLIZER *LinePatternSymbolizer = rule->LinePatternSymbolizer;
225
 
226
		    while (LineSymbolizer)
227
		    {
228
		       LINESYMBOLIZER *akt = LineSymbolizer->next;
229
		       delete LineSymbolizer;
230
		       LineSymbolizer = akt;
231
		    }
232
 
233
		    while (PolygonSymbolizer)
234
		    {
235
		       POLYGONSYMBOLIZER *akt = PolygonSymbolizer->next;
236
		       delete PolygonSymbolizer;
237
		       PolygonSymbolizer = akt;
238
		    }
239
 
240
		    while (TextSymbolizer)
241
		    {
242
		       TEXTSYMBOLIZER *akt = TextSymbolizer->next;
243
		       delete TextSymbolizer;
244
		       TextSymbolizer = akt;
245
		    }
246
 
247
		    while (PointSymbolizer)
248
		    {
249
		       POINTSYMBOLIZER *akt = PointSymbolizer->next;
250
		       delete PointSymbolizer;
251
		       PointSymbolizer = akt;
252
		    }
253
 
254
		    while (PolygonPatternSymbolizer)
255
		    {
256
		       POLYGONPATTERNSYMBOLIZER *akt = PolygonPatternSymbolizer->next;
257
		       delete PolygonPatternSymbolizer;
258
		       PolygonPatternSymbolizer = akt;
259
		    }
260
 
261
		    while (ShieldSymbolizer)
262
		    {
263
		       SHIELDSYMBOLIZER *akt = ShieldSymbolizer->next;
264
		       delete ShieldSymbolizer;
265
		       ShieldSymbolizer = akt;
266
		    }
267
 
268
		    while (LinePatternSymbolizer)
269
		    {
270
		       LINEPATTERNSYMBOLIZER *akt = LinePatternSymbolizer->next;
271
		       delete LinePatternSymbolizer;
272
		       LinePatternSymbolizer = akt;
273
		    }
274
 
275
		    delete rule;
276
		    rule = rakt;
277
		 }
278
	      }
279
 
280
	      delete Style;
281
	      Style = sakt;
282
	   }
283
	}
284
 
285
	Style = firstStyle = lastStyle = 0;
274 andreas 286
 
287
	if (firstLayer)
288
	{
289
	   Lay = firstLayer;
290
 
291
	   while (Lay)
292
	   {
293
	   LAYER *akt;
294
 
295
	      akt = Lay->next;
296
	      delete Lay;
297
	      Lay = akt;
298
	   }
299
	}
300
 
301
	Lay = firstLayer = lastLayer = 0;
275 andreas 302
	Rule = 0;
303
	LineSymbolizer = 0;
304
	PolygonSymbolizer = 0;
305
	TextSymbolizer = 0;
306
	PointSymbolizer = 0;
307
	PolygonPatternSymbolizer = 0;
308
	ShieldSymbolizer = 0;
309
	LinePatternSymbolizer = 0;
310
	_lx = _ly = 180.0;
311
	_rx = _ry = -180.0;
312
	ControlSet = false;
313
	XmlLine = 1;
274 andreas 314
	Container = in_root;
273 andreas 315
	return true;
316
}
317
 
318
/*
319
 * This is called every time a new start element was parsed.
320
 */
274 andreas 321
bool SRender::startElement( const QString&, const QString&,
273 andreas 322
                                    const QString& qName,
323
                                    const QXmlAttributes& att)
324
{
325
int i = FIRST_CON;
326
int index;
274 andreas 327
QString hv0;
273 andreas 328
 
274 andreas 329
	while (i <= LAST_CON)
273 andreas 330
	{
331
	   if (qName.toLower() == getKey(i).toLower())
332
	   {
274 andreas 333
	      Container = token[i].con;
334
 
273 andreas 335
	      switch (i)
336
	      {
337
		 case CON_MAP:
274 andreas 338
		    Container = in_map;
339
 
340
		    if (ControlSet)	// Must be false here!
341
		    {
275 andreas 342
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: There is another MAP! Only one map information is allowed!").arg(XmlPath).arg(XmlLine));
274 andreas 343
		       return false;
344
		    }
345
 
273 andreas 346
		    if ((index = att.index(QString("bgcolor"))) != -1)
275 andreas 347
		    {
274 andreas 348
		       MapPars.bgcolor = colorToUInt(att.value(index));
278 andreas 349
		       m.set_background(setColor(MapPars.bgcolor));
275 andreas 350
		    }
273 andreas 351
 
352
		    if ((index = att.index(QString("buffer_size"))) != -1)
275 andreas 353
		    {
273 andreas 354
		       MapPars.buf_size = att.value(index).toInt();
275 andreas 355
		       m.set_buffer_size(MapPars.buf_size);
356
		    }
273 andreas 357
 
358
		    if ((index = att.index(QString("srs"))) != -1)
275 andreas 359
		    {
273 andreas 360
		       MapPars.srs = att.value(index);
275 andreas 361
		       m.set_srs(MapPars.srs.toAscii().data());
362
		    }
273 andreas 363
		 break;
364
 
365
		 case CON_STYLE:
274 andreas 366
		    Container = in_style;
367
 
273 andreas 368
		    if (!lastStyle)
369
		    {
274 andreas 370
		       Style = allocStyle();
371
		       firstStyle = lastStyle = Style;
273 andreas 372
		    }
373
		    else
374
		    {
274 andreas 375
		       Style = allocStyle();
273 andreas 376
		       lastStyle->next = Style;
377
		       lastStyle = Style;
378
		    }
379
 
380
		    if ((index = att.index(QString("name"))) != -1)
381
		       Style->name = att.value(index);
382
		    else
383
		    {
275 andreas 384
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open STYLE without a name!").arg(XmlPath).arg(XmlLine));
273 andreas 385
		       return false;
386
		    }
387
		 break;
388
 
389
		 case CON_RULE:
274 andreas 390
		    Container = in_rule;
391
 
273 andreas 392
		    if (!Style)
393
		    {
275 andreas 394
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open RULE outside of a STYLE!").arg(XmlPath).arg(XmlLine));
273 andreas 395
		       return false;
396
		    }
397
 
398
		    Rule = getLastRule (Style->rule);
399
 
400
		    if (!Rule)
401
		    {
274 andreas 402
		       Rule = allocRule();
273 andreas 403
		       Style->rule = Rule;
404
		    }
405
		    else
406
		    {
274 andreas 407
		       Rule->next = allocRule();
273 andreas 408
		       Rule = Rule->next;
409
		    }
276 andreas 410
 
411
		    if ((index = att.index(QString("name"))) != -1)
412
		    {
413
		       Rule->name = att.value(index);
414
		       Rule->rl.set_name(Rule->name.toAscii().data());
415
		    }
416
 
417
		    if ((index = att.index(QString("title"))) != -1)
418
		    {
419
		       Rule->title = att.value(index);
420
		       Rule->rl.set_title(Rule->title.toAscii().data());
421
		    }
273 andreas 422
		 break;
423
 
276 andreas 424
		 case CON_ELSEFILTER:
425
		    Container = in_elsefilter;
426
 
427
		    if (!Rule)
428
		    {
429
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open ELSEFILTER outside of a RULE!").arg(XmlPath).arg(XmlLine));
430
		       return false;
431
		    }
432
		 break;
433
 
274 andreas 434
		 case CON_LAYER:
435
		    Container = in_layer;
436
 
437
		    if (!firstLayer)
438
		    {
439
		       Lay = allocLayer();
440
		       firstLayer = lastLayer = Lay;
441
		    }
442
		    else
443
		    {
444
		       Lay = allocLayer();
445
		       lastLayer->next = Lay;
446
		       lastLayer = Lay;
447
		    }
448
 
449
		    if ((index = att.index(QString("name"))) != -1)
450
		       Lay->name = att.value(index);
451
 
452
		    if ((index = att.index(QString("status"))) != -1)
453
		       Lay->status = getBool(att.value(index));
454
 
455
		    if ((index = att.index(QString("srs"))) != -1)
456
		       Lay->srs = att.value(index);
275 andreas 457
 
458
		    if ((index = att.index(QString("minzoom"))) != -1)
459
		       Lay->minzoom = att.value(index).toDouble();
460
 
461
		    if ((index = att.index(QString("maxzoom"))) != -1)
462
		       Lay->maxzoom = att.value(index).toDouble();
276 andreas 463
 
464
		    if ((index = att.index(QString("queryable"))) != -1)
465
		       Lay->queryable = getBool(att.value(index));
466
 
467
		    if ((index = att.index(QString("title"))) != -1)
468
		       Lay->title = att.value(index);
469
 
470
		    if ((index = att.index(QString("abstract"))) != -1)
471
		       Lay->abstract = att.value(index);
472
 
473
		    if ((index = att.index(QString("clear_label_cache"))) != -1)
474
		       Lay->clear_label = getBool(att.value(index));
274 andreas 475
		 break;
476
 
477
		 case CON_DATASOURCE:
478
		    Container = in_datasource;
479
		 break;
480
 
273 andreas 481
		 case CON_POINTSYMBOLIZER:
274 andreas 482
		    Container = in_pointsymbolizer;
483
 
273 andreas 484
		    if (!Rule)
485
		    {
275 andreas 486
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open POINTSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
273 andreas 487
		       return false;
488
		    }
489
 
490
		    PointSymbolizer = getLastPointSymbolizer(Rule->PointSymbolizer);
491
 
492
		    if (!PointSymbolizer)
493
		    {
274 andreas 494
		       PointSymbolizer = allocPointSymbolizer();
273 andreas 495
		       Rule->PointSymbolizer = PointSymbolizer;
496
		    }
497
		    else
498
		    {
274 andreas 499
		       PointSymbolizer->next = allocPointSymbolizer();
273 andreas 500
		       PointSymbolizer = PointSymbolizer->next;
501
		    }
502
 
503
		    if ((index = att.index(QString("file"))) != -1)
504
		       PointSymbolizer->file = att.value(index);
505
 
506
		    if ((index = att.index(QString("type"))) != -1)
274 andreas 507
		       PointSymbolizer->type = getType(att.value(index));
273 andreas 508
 
274 andreas 509
		    if ((index = att.index(QString("width"))) != -1)
273 andreas 510
		       PointSymbolizer->width = att.value(index).toDouble();
511
 
274 andreas 512
		    if ((index = att.index(QString("height"))) != -1)
273 andreas 513
		       PointSymbolizer->height = att.value(index).toDouble();
514
 
274 andreas 515
		    if ((index = att.index(QString("allow_overlap"))) != -1)
276 andreas 516
		       PointSymbolizer->allow_overlap = getBool(att.value(index));
273 andreas 517
		 break;
518
 
519
		 break;
520
 
521
		 case CON_LINESYMBOLIZER:
274 andreas 522
		    Container = in_linesymbolizer;
523
 
273 andreas 524
		    if (!Rule)
525
		    {
275 andreas 526
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open LINESYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
273 andreas 527
		       return false;
528
		    }
529
 
530
		    LineSymbolizer = getLastLineSymbolizer(Rule->LineSymbolizer);
531
 
532
		    if (!LineSymbolizer)
533
		    {
274 andreas 534
		       LineSymbolizer = allocLineSymbolizer();
273 andreas 535
		       Rule->LineSymbolizer = LineSymbolizer;
536
		    }
537
		    else
538
		    {
274 andreas 539
		       LineSymbolizer->next = allocLineSymbolizer();
273 andreas 540
		       LineSymbolizer = LineSymbolizer->next;
541
		    }
542
		 break;
543
 
544
		 case CON_POLYGONSYMBOLIZER:
274 andreas 545
		    Container = in_polygonsymbolizer;
546
 
273 andreas 547
		    if (!Rule)
548
		    {
275 andreas 549
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open POLYGONSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
273 andreas 550
		       return false;
551
		    }
552
 
553
		    PolygonSymbolizer = getLastPolygonSymbolizer(Rule->PolygonSymbolizer);
554
 
555
		    if (!PolygonSymbolizer)
556
		    {
274 andreas 557
		       PolygonSymbolizer = allocPolygonSymbolizer();
273 andreas 558
		       Rule->PolygonSymbolizer = PolygonSymbolizer;
559
		    }
560
		    else
561
		    {
274 andreas 562
		       PolygonSymbolizer->next = allocPolygonSymbolizer();
273 andreas 563
		       PolygonSymbolizer = PolygonSymbolizer->next;
564
		    }
565
		 break;
566
 
567
		 case CON_TEXTSYMBOLIZER:
274 andreas 568
		    Container = in_textsymbolizer;
569
 
273 andreas 570
		    if (!Rule)
571
		    {
275 andreas 572
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open TEXTSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
273 andreas 573
		       return false;
574
		    }
575
 
576
		    TextSymbolizer = getLastTextSymbolizer(Rule->TextSymbolizer);
577
 
578
		    if (!TextSymbolizer)
579
		    {
274 andreas 580
		       TextSymbolizer = allocTextSymbolizer();
273 andreas 581
		       Rule->TextSymbolizer = TextSymbolizer;
582
		    }
583
		    else
584
		    {
274 andreas 585
		       TextSymbolizer->next = allocTextSymbolizer();
273 andreas 586
		       TextSymbolizer = TextSymbolizer->next;
587
		    }
588
 
589
		    if ((index = att.index(QString("name"))) != -1)
590
		       TextSymbolizer->name = att.value(index);
591
 
592
		    if ((index = att.index(QString("face_name"))) != -1)
593
		       TextSymbolizer->face_name = att.value(index);
594
 
276 andreas 595
		    if ((index = att.index(QString("placement"))) != -1)
596
		       TextSymbolizer->placement = att.value(index);
597
 
273 andreas 598
		    if ((index = att.index(QString("size"))) != -1)
599
		       TextSymbolizer->size = att.value(index).toDouble();
600
 
601
		    if ((index = att.index(QString("fill"))) != -1)
274 andreas 602
		       TextSymbolizer->fill = colorToUInt(att.value(index));
603
 
604
		    if ((index = att.index(QString("halo_radius"))) != -1)
605
		       TextSymbolizer->halo_radius = att.value(index).toDouble();
606
 
607
		    if ((index = att.index(QString("wrap_width"))) != -1)
608
		       TextSymbolizer->wrap_width = att.value(index).toDouble();
609
 
276 andreas 610
		    if ((index = att.index(QString("alignment"))) != -1)
611
		       TextSymbolizer->alignment = att.value(index);
612
 
275 andreas 613
		    if ((index = att.index(QString("dx"))) != -1)
614
		       TextSymbolizer->dx = att.value(index).toDouble();
615
 
274 andreas 616
		    if ((index = att.index(QString("dy"))) != -1)
617
		       TextSymbolizer->dy = att.value(index).toDouble();
618
 
619
		    if ((index = att.index(QString("max_distance"))) != -1)
620
		       TextSymbolizer->maxdistance = att.value(index).toDouble();
621
 
622
		    if ((index = att.index(QString("min_distance"))) != -1)
623
		       TextSymbolizer->mindistance = att.value(index).toDouble();
273 andreas 624
		 break;
274 andreas 625
 
626
		 case CON_POLYGONPATTERNSYMBOLIZER:
627
		    Container = in_polygonpatternsymbolizer;
628
 
629
		    if (!Rule)
630
		    {
275 andreas 631
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open POLYGONPATTERNSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
274 andreas 632
		       return false;
633
		    }
634
 
635
		    PolygonPatternSymbolizer = getLastPolygonPatternSymbolizer(Rule->PolygonPatternSymbolizer);
636
 
637
		    if (!PolygonPatternSymbolizer)
638
		    {
639
		       PolygonPatternSymbolizer = allocPolygonPatternSymbolizer();
640
		       Rule->PolygonPatternSymbolizer = PolygonPatternSymbolizer;
641
		    }
642
		    else
643
		    {
644
		       PolygonPatternSymbolizer->next = allocPolygonPatternSymbolizer();
645
		       PolygonPatternSymbolizer = PolygonPatternSymbolizer->next;
646
		    }
647
 
648
		    if ((index = att.index(QString("file"))) != -1)
649
		       PolygonPatternSymbolizer->file = att.value(index);
650
 
651
		    if ((index = att.index(QString("type"))) != -1)
652
		       PolygonPatternSymbolizer->type = getType(att.value(index));
653
 
654
		    if ((index = att.index(QString("width"))) != -1)
655
		       PolygonPatternSymbolizer->width = att.value(index).toDouble();
656
 
657
		    if ((index = att.index(QString("height"))) != -1)
658
		       PolygonPatternSymbolizer->height = att.value(index).toDouble();
659
 
660
		    if ((index = att.index(QString("allow_overlap"))) != -1)
661
		       PolygonPatternSymbolizer->allow_overlap = getBool(att.value(index));
662
		 break;
663
 
664
		 case CON_SHIELDSYMBOLIZER:
665
		    Container = in_shieldsymbolizer;
666
 
667
		    if (!Rule)
668
		    {
275 andreas 669
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open SHIELDSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
274 andreas 670
		       return false;
671
		    }
672
 
673
		    ShieldSymbolizer = getLastShieldSymbolizer(Rule->ShieldSymbolizer);
674
 
675
		    if (!ShieldSymbolizer)
676
		    {
677
		       ShieldSymbolizer = allocShieldSymbolizer();
678
		       Rule->ShieldSymbolizer = ShieldSymbolizer;
679
		    }
680
		    else
681
		    {
682
		       ShieldSymbolizer->next = allocShieldSymbolizer();
683
		       ShieldSymbolizer = ShieldSymbolizer->next;
684
		    }
685
 
686
		    if ((index = att.index(QString("name"))) != -1)
687
		       ShieldSymbolizer->name = att.value(index);
688
 
689
		    if ((index = att.index(QString("face_name"))) != -1)
690
		       ShieldSymbolizer->face_name = att.value(index);
691
 
692
		    if ((index = att.index(QString("fill"))) != -1)
693
		       ShieldSymbolizer->fill = colorToUInt(att.value(index));
694
 
695
		    if ((index = att.index(QString("placement"))) != -1)
696
		       ShieldSymbolizer->placement = att.value(index);
697
 
698
		    if ((index = att.index(QString("file"))) != -1)
699
		       ShieldSymbolizer->file = att.value(index);
700
 
701
		    if ((index = att.index(QString("type"))) != -1)
702
		       ShieldSymbolizer->type = getType(att.value(index));
703
 
704
		    if ((index = att.index(QString("size"))) != -1)
705
		       ShieldSymbolizer->size = att.value(index).toDouble();
706
 
707
		    if ((index = att.index(QString("width"))) != -1)
708
		       ShieldSymbolizer->width = att.value(index).toDouble();
709
 
710
		    if ((index = att.index(QString("height"))) != -1)
711
		       ShieldSymbolizer->height = att.value(index).toDouble();
712
 
275 andreas 713
		    if ((index = att.index(QString("dx"))) != -1)
714
		       ShieldSymbolizer->dx = att.value(index).toDouble();
715
 
716
		    if ((index = att.index(QString("dy"))) != -1)
717
		       ShieldSymbolizer->dy = att.value(index).toDouble();
718
 
274 andreas 719
		    if ((index = att.index(QString("min_distance"))) != -1)
720
		       ShieldSymbolizer->mindistance = att.value(index).toDouble();
721
 
722
		    if ((index = att.index(QString("max_distance"))) != -1)
723
		       ShieldSymbolizer->maxdistance = att.value(index).toDouble();
724
		 break;
725
 
726
		 case CON_LINEPATTERNSYMBOLIZER:
727
		    Container = in_linepatternsymbolizer;
728
 
729
		    if (!Rule)
730
		    {
275 andreas 731
		       KMessageBox::error(0, i18n("Error parsing %1, line %2: Open LINEPATTERNSYMBOLIZER outside of a RULE!").arg(XmlPath).arg(XmlLine));
274 andreas 732
		       return false;
733
		    }
734
 
735
		    LinePatternSymbolizer = getLastLinePatternSymbolizer(Rule->LinePatternSymbolizer);
736
 
737
		    if (!LinePatternSymbolizer)
738
		    {
739
		       LinePatternSymbolizer = allocLinePatternSymbolizer();
740
		       Rule->LinePatternSymbolizer = LinePatternSymbolizer;
741
		    }
742
		    else
743
		    {
744
		       LinePatternSymbolizer->next = allocLinePatternSymbolizer();
745
		       LinePatternSymbolizer = LinePatternSymbolizer->next;
746
		    }
747
 
748
		    if ((index = att.index(QString("file"))) != -1)
749
		       LinePatternSymbolizer->file = att.value(index);
750
 
751
		    if ((index = att.index(QString("type"))) != -1)
752
		       LinePatternSymbolizer->type = getType(att.value(index));
753
 
754
		    if ((index = att.index(QString("width"))) != -1)
755
		       LinePatternSymbolizer->width = att.value(index).toDouble();
756
 
757
		    if ((index = att.index(QString("height"))) != -1)
758
		       LinePatternSymbolizer->height = att.value(index).toDouble();
759
		 break;
760
	      }
761
	   }
762
 
763
	   i++;
273 andreas 764
	}
274 andreas 765
 
766
	i = FIRST_FLD;
767
 
768
	while (i <= LAST_FLD)
769
	{
770
	   if (qName.toLower() == getKey(i).toLower())
771
	   {
772
	      Field = i;
773
 
774
	      switch(Container)
775
	      {
776
		 case in_linesymbolizer:
777
		    Names = empty;
778
 
779
		    if (i == FLD_CSSPARAMETER)
780
		    {
781
		       if ((index = att.index(QString("name"))) != -1)
782
		       {
783
			  if (att.value(index).toLower() == QString("stroke"))
784
			     Names = stroke_stroke;
785
			  else if (att.value(index).toLower() == QString("stroke-width"))
786
			     Names = stroke_width;
787
			  else if (att.value(index).toLower() == QString("stroke-opacity"))
788
			     Names = stroke_opacity;
789
			  else if (att.value(index).toLower() == QString("stroke-linejoin"))
790
			     Names = stroke_linejoin;
791
			  else if (att.value(index).toLower() == QString("stroke-linecap"))
792
			     Names = stroke_linecap;
793
			  else if (att.value(index).toLower() == QString("stroke-dasharray"))
794
			     Names = stroke_dasharray;
795
		       }
796
		       else
797
		       {
275 andreas 798
			  KMessageBox::error(0, i18n("Error parsing %1, line %2: Required attribute NAME is missing in CSSPARAMETER inside LINESYMBOLIZER!").arg(XmlPath).arg(XmlLine));
274 andreas 799
			  return false;
800
		       }
801
		    }
802
		 break;
803
 
804
		 case in_polygonsymbolizer:
805
		    Names = empty;
806
 
807
		    if (i == FLD_CSSPARAMETER)
808
		    {
809
		       if ((index = att.index(QString("name"))) != -1)
810
		       {
811
			  if (att.value(index).toLower() == QString("fill"))
812
			     Names = fill;
813
			  else if (att.value(index).toLower() == QString("fill-opacity"))
814
			     Names = fill_opacity;
815
		       }
816
		       else
817
		       {
275 andreas 818
			  KMessageBox::error(0, i18n("Error parsing %1, line %2: Required attribute NAME is missing in CSSPARAMETER inside POLYGONSYMBOLIZER!").arg(XmlPath).arg(XmlLine));
274 andreas 819
			  return false;
820
		       }
821
		    }
822
		 break;
823
 
824
		 case in_datasource:
825
		    Names = empty;
826
 
827
		    if (i == FLD_PARAMETER)
828
		    {
829
		       if ((index = att.index(QString("name"))) != -1)
830
		       {
831
			  if (att.value(index).toLower() == QString("type"))
832
			     Names = type;
833
			  else if (att.value(index).toLower() == QString("file"))
834
			     Names = file;
835
			  else if (att.value(index).toLower() == QString("host"))
836
			     Names = host;
837
			  else if (att.value(index).toLower() == QString("user"))
838
			     Names = user;
839
			  else if (att.value(index).toLower() == QString("dbname"))
840
			     Names = dbname;
841
			  else if (att.value(index).toLower() == QString("table"))
842
			     Names = table;
843
			  else if (att.value(index).toLower() == QString("estimate_extent"))
844
			     Names = estimate_extent;
845
			  else if (att.value(index).toLower() == QString("extent"))
846
			     Names = extent;
276 andreas 847
			  else if (att.value(index).toLower() == QString("parser"))
848
			     Names = parser__;
849
			  else if (att.value(index).toLower() == QString("url"))
850
			     Names = url;
851
			  else if (att.value(index).toLower() == QString("bbox"))
852
			     Names = bbox;
274 andreas 853
		       }
854
		       else
855
		       {
275 andreas 856
			  KMessageBox::error(0, i18n("Error parsing %1, line %2: Required attribute NAME is missing in PARAMETER inside DATASOURCE!").arg(XmlPath).arg(XmlLine));
274 andreas 857
			  return false;
858
		       }
859
		    }
860
		 break;
861
 
862
		 case in_root:
863
		    Names = empty;
864
		 break;
865
		 case in_map:
866
		    Names = empty;
867
		 break;
868
		 case in_style:
869
		    Names = empty;
870
		 break;
871
		 case in_rule:
872
		    Names = empty;
873
		 break;
874
		 case in_pointsymbolizer:
875
		    Names = empty;
876
		 break;
877
		 case in_textsymbolizer:
878
		    Names = empty;
879
		 break;
880
		 case in_polygonpatternsymbolizer:
881
		    Names = empty;
882
		 break;
883
		 case in_layer:
884
		    Names = empty;
885
		 break;
886
		 case in_symbolizer:
887
		    Names = empty;
888
		 break;
889
		 case in_shieldsymbolizer:
890
		    Names = empty;
891
		 break;
892
		 case in_linepatternsymbolizer:
893
		    Names = empty;
894
		 break;
276 andreas 895
		 case in_elsefilter:
896
		    Names = empty;
897
		 break;
274 andreas 898
	      }
899
	   }
900
 
901
	   i++;
902
	}
903
 
904
	return true;
273 andreas 905
}
906
 
907
/*
908
 * This is called every time an element is closed.
909
 */
274 andreas 910
bool SRender::endElement( const QString&, const QString&, const QString& qName)
273 andreas 911
{
274 andreas 912
	if (qName.toLower() == QString("datasource"))
913
	   Container = in_layer;
914
	else if (qName.toLower() == QString("layer"))
915
	{
916
	   parameters p;
917
	   Container = in_map;
918
 
276 andreas 919
	   if (Lay->Datasource.type.toLower() == QString("shape") && __map_type == MAP_SHAPE)
274 andreas 920
	   {
276 andreas 921
	   QFileInfo qdi(Lay->Datasource.file);
922
	   QString hv0;
923
 
924
	      hv0 = qdi.fileName();
925
 
926
	      if (shapePath.right(1) == QChar('/'))
927
		 hv0 = shapePath + hv0;
928
	      else
929
		 hv0 = shapePath + "/" + hv0;
930
 
274 andreas 931
	      p["type"] = "shape";
276 andreas 932
	      p["file"] = hv0.toAscii().data();
274 andreas 933
	   }
276 andreas 934
	   else if (Lay->Datasource.type.toLower() == QString("postgis") && __map_type == MAP_GIS)
274 andreas 935
	   {
936
	      p["type"] = "postgis";
276 andreas 937
	      p["host"] = Lay->Datasource.host.toAscii().data();
938
	      p["user"] = Lay->Datasource.user.toAscii().data();
939
	      p["dbname"] = Lay->Datasource.dbname.toAscii().data();
940
	      p["table"] = Lay->Datasource.table.toAscii().data();
274 andreas 941
	      p["estimate_extent"] = (Lay->Datasource.estimate_extent) ? "true" : "false";
942
	      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();
943
	   }
276 andreas 944
	   else if (Lay->Datasource.type.toAscii() == QString("osm") && __map_type == MAP_OSM)
945
	   {
946
	      p["type"] = "osm";
947
 
948
	      if (Lay->Datasource.parser.length() <= 0)
949
		 p["parser"] = "libxml2";
950
	      else
951
		 p["parser"] = Lay->Datasource.parser.toAscii().data();
952
 
953
	      if (!Lay->Datasource.url.isEmpty() && !Lay->Datasource.bbox.isEmpty())
954
	      {
955
		 p["url"] = Lay->Datasource.url.toAscii().data();
956
		 p["bbox"] = Lay->Datasource.bbox.toAscii().data();
957
	      }
958
	      else
959
		 p["file"] = shapePath.toAscii().data();
960
	   }
274 andreas 961
	   else
962
	   {
275 andreas 963
	      cerr << "Warning file " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Layer with no source! Ingnoring!" << endl;
274 andreas 964
	      return true;
965
	   }
966
 
967
	   Layer lyr(Lay->name.toAscii().data());
276 andreas 968
 
969
	   if (!Lay->title.isEmpty())
970
	      lyr.set_title(Lay->title.toAscii().data());
971
 
972
	   if (!Lay->abstract.isEmpty())
973
	      lyr.set_abstract(Lay->abstract.toAscii().data());
974
 
274 andreas 975
	   lyr.set_datasource(datasource_cache::instance()->create(p));
976
 
276 andreas 977
	   if (!Lay->srs.isEmpty())
978
	      lyr.set_srs(Lay->srs.toAscii().data());
979
 
275 andreas 980
	   if (Lay->minzoom > 0.0)
981
	      lyr.setMinZoom(Lay->minzoom);
982
 
983
	   if (Lay->maxzoom > 0.0)
984
	      lyr.setMaxZoom(Lay->maxzoom);
985
 
276 andreas 986
	   lyr.set_clear_label_cache(Lay->clear_label);
274 andreas 987
 
988
	   // Add the styles
989
	   for (int i = 0; i < Lay->Styles.size(); i++)
275 andreas 990
	   {
991
	      if (findStyle (Lay->Styles.at(i)) != 0)
276 andreas 992
		 lyr.add_style(Lay->Styles.at(i).toAscii().data());
275 andreas 993
	      else
994
		 cerr << "Warning file " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Style \"" << Lay->Styles.at(i).toAscii().data() << "\" does not exist!" << endl;
995
	   }
274 andreas 996
 
275 andreas 997
	   lyr.setActive(Lay->status);
276 andreas 998
	   lyr.setQueryable(true);
274 andreas 999
	   m.addLayer(lyr);
275 andreas 1000
	   Envelope <double>le(lyr.envelope());
1001
	   setMaxExtent(le.minx(), le.miny(), le.maxx(), le.maxy());
274 andreas 1002
	}
1003
	else if (qName.toLower() == QString("map"))
1004
	{
1005
	   Container = in_root;
1006
	   ControlSet = true;
1007
	}
275 andreas 1008
	else if (qName.toLower() == QString("pointsymbolizer"))
1009
	{
274 andreas 1010
	   Container = in_rule;
275 andreas 1011
 
1012
	   if (!Rule || !PointSymbolizer)
1013
	   {
1014
	      KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of POINTSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
1015
	      return false;
1016
	   }
1017
 
1018
	   if (PointSymbolizer->file.length() == 0 || PointSymbolizer->width == 0 || PointSymbolizer->height == 0)
1019
	   {
1020
	      cerr << "Warning file " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Empty POINTSYMBOLIZER!" << endl;
1021
	      point_symbolizer psym;
1022
	      Rule->rl.append(psym);
1023
	   }
1024
	   else
1025
	   {
276 andreas 1026
	      point_symbolizer ps(findIcon(PointSymbolizer->file).toAscii().data(), getTypeText(PointSymbolizer->type), PointSymbolizer->width, PointSymbolizer->height);
275 andreas 1027
	      ps.set_allow_overlap (PointSymbolizer->allow_overlap);
1028
	      Rule->rl.append(ps);
1029
	   }
1030
	}
1031
	else if (qName.toLower() == QString("linesymbolizer"))
274 andreas 1032
	{
275 andreas 1033
	   Container = in_rule;
274 andreas 1034
 
275 andreas 1035
	   if (!Rule || !LineSymbolizer)
274 andreas 1036
	   {
275 andreas 1037
	      KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of LINESYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
1038
	      return false;
1039
	   }
274 andreas 1040
 
275 andreas 1041
	   stroke st;
278 andreas 1042
	   st.set_color (setColor(LineSymbolizer->stroke));
274 andreas 1043
 
275 andreas 1044
	   if (LineSymbolizer->stroke_width != 0.0)
1045
	      st.set_width (LineSymbolizer->stroke_width);
274 andreas 1046
 
275 andreas 1047
	   if (!LineSymbolizer->stroke_linejoin.isEmpty())
1048
	   {
1049
	      if (LineSymbolizer->stroke_linejoin.toLower() == QString("miter"))
1050
		 st.set_line_join (mapnik::MITER_JOIN);
1051
	      else if (LineSymbolizer->stroke_linejoin.toLower() == QString("miter_revert") ||
1052
			 LineSymbolizer->stroke_linejoin.toLower() == QString("miter-revert"))
1053
		 st.set_line_join (mapnik::MITER_REVERT_JOIN);
1054
	      else if (LineSymbolizer->stroke_linejoin.toLower() == QString("round"))
1055
		 st.set_line_join (mapnik::ROUND_JOIN);
1056
	      else if (LineSymbolizer->stroke_linejoin.toLower() == QString("bevel"))
1057
		 st.set_line_join (mapnik::BEVEL_JOIN);
1058
	      else
1059
		 cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Unknown >>line_join<< \"" << LineSymbolizer->stroke_linejoin.toAscii().data() << "\" --> ignoring!" << endl;
1060
	   }
274 andreas 1061
 
275 andreas 1062
	   if (!LineSymbolizer->stroke_linecap.isEmpty())
1063
	   {
1064
	      if (LineSymbolizer->stroke_linecap.toLower() == QString("butt"))
1065
		st.set_line_cap (mapnik::BUTT_CAP);
1066
	      else if (LineSymbolizer->stroke_linecap.toLower() == QString("square"))
1067
		st.set_line_cap (mapnik::SQUARE_CAP);
1068
	      else if (LineSymbolizer->stroke_linecap.toLower() == QString("round"))
1069
		st.set_line_cap (mapnik::ROUND_CAP);
1070
	      else
1071
		 cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Unknown >>line_cap<< \"" << LineSymbolizer->stroke_linecap.toAscii().data() << "\" --> ignoring!" << endl;
1072
	   }
274 andreas 1073
 
275 andreas 1074
	   if (LineSymbolizer->stroke_dasharray[0] > 0 || LineSymbolizer->stroke_dasharray[1] > 0)
1075
	      st.add_dash(LineSymbolizer->stroke_dasharray[0], LineSymbolizer->stroke_dasharray[1]);
274 andreas 1076
 
275 andreas 1077
	   if (LineSymbolizer->stroke_opacity != 0)
1078
	      st.set_opacity(LineSymbolizer->stroke_opacity);
274 andreas 1079
 
275 andreas 1080
	   Rule->rl.append(line_symbolizer(st));
1081
	}
1082
	else if (qName.toLower() == QString("polygonsymbolizer"))
1083
	{
1084
	   Container = in_rule;
274 andreas 1085
 
275 andreas 1086
	   if (!Rule || !PolygonSymbolizer)
1087
	   {
1088
	      KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of POLYGONSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
1089
	      return false;
1090
	   }
274 andreas 1091
 
278 andreas 1092
	   polygon_symbolizer ps(setColor(PolygonSymbolizer->fill));
274 andreas 1093
 
275 andreas 1094
	   if (PolygonSymbolizer->fill_opacity > 0.0)
1095
	      ps.set_opacity(PolygonSymbolizer->fill_opacity);
274 andreas 1096
 
275 andreas 1097
	   Rule->rl.append(ps);
1098
	}
1099
	else if (qName.toLower() == QString("textsymbolizer"))
1100
	{
1101
	   Container = in_rule;
274 andreas 1102
 
275 andreas 1103
	   if (!Rule || !TextSymbolizer)
1104
	   {
1105
	      KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of TEXTSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
1106
	      return false;
1107
	   }
274 andreas 1108
 
276 andreas 1109
	   if (TextSymbolizer->name.length() <= 0 || TextSymbolizer->face_name.length() <= 0 || TextSymbolizer->size <= 0)
1110
	      cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Empty TEXTSYMBOLIZER found --> ignoring!" << endl;
1111
	   else
1112
	   {
278 andreas 1113
	      text_symbolizer ts(TextSymbolizer->name.toAscii().data(), TextSymbolizer->face_name.toAscii().data(), TextSymbolizer->size, setColor(TextSymbolizer->fill));
274 andreas 1114
 
276 andreas 1115
	      if (TextSymbolizer->halo_radius != 0.0)
1116
		 ts.set_halo_radius((unsigned int)TextSymbolizer->halo_radius);
274 andreas 1117
 
276 andreas 1118
	      if (TextSymbolizer->wrap_width != 0.0)
1119
		 ts.set_wrap_width((unsigned int)TextSymbolizer->wrap_width);
274 andreas 1120
 
276 andreas 1121
	      if (TextSymbolizer->mindistance != 0)
1122
		 ts.set_label_spacing(TextSymbolizer->mindistance);
274 andreas 1123
 
276 andreas 1124
	      if (!TextSymbolizer->placement.isEmpty())
1125
	      {
1126
		 if (TextSymbolizer->placement.toLower() == QString("point"))
1127
		    ts.set_label_placement(mapnik::POINT_PLACEMENT);
1128
		 else if (TextSymbolizer->placement.toLower() == QString("line"))
1129
		    ts.set_label_placement(mapnik::LINE_PLACEMENT);
1130
		 else
1131
		    cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Unknown >>label placement<< \"" << TextSymbolizer->placement.toAscii().data() << "\" --> ignoring!" << endl;
1132
	      }
274 andreas 1133
 
276 andreas 1134
	      if (!TextSymbolizer->alignment.isEmpty())
1135
	      {
1136
		 if (TextSymbolizer->alignment.toLower() == QString("top"))
1137
		    ts.set_vertical_alignment(mapnik::TOP);
1138
		 else if (TextSymbolizer->alignment.toLower() == QString("middle"))
1139
		    ts.set_vertical_alignment(mapnik::MIDDLE);
1140
		 else if (TextSymbolizer->alignment.toLower() == QString("bottom"))
1141
		    ts.set_vertical_alignment(mapnik::BOTTOM);
1142
		 else
1143
		    cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Unknown >>vertical placement<< \"" << TextSymbolizer->alignment.toAscii().data() << "\" --> ignoring!" << endl;
1144
	      }
1145
 
1146
	      if (TextSymbolizer->dx != 0 || TextSymbolizer->dy != 0)
1147
		 ts.set_displacement(TextSymbolizer->dx, TextSymbolizer->dy);
1148
 
1149
	      Rule->rl.append(ts);
1150
	   }
275 andreas 1151
	}
1152
	else if (qName.toLower() == QString("polygonpatternsymbolizer"))
1153
	{
1154
	   Container = in_rule;
274 andreas 1155
 
275 andreas 1156
	   if (!Rule || !PolygonPatternSymbolizer)
1157
	   {
1158
	      KMessageBox::error(0, i18n("Error parsing %1, line %2: Endin of POLYGONPATTERNSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
1159
	      return false;
1160
	   }
274 andreas 1161
 
276 andreas 1162
	   if (PolygonPatternSymbolizer->file.length() <= 0)
1163
	      cerr << "Error parsing " << XmlPath.toAscii().data() << ", line " << XmlLine << ": Incomplete POLYGONPATTERNSYMBOLIZER --> ignoring!" << endl;
1164
	   else
1165
	   {
1166
	      Rule->rl.append(polygon_pattern_symbolizer(findIcon(PolygonPatternSymbolizer->file).toAscii().data(),
275 andreas 1167
						getTypeText(PolygonPatternSymbolizer->type),
1168
						PolygonPatternSymbolizer->width,
1169
						PolygonPatternSymbolizer->height));
276 andreas 1170
	   }
275 andreas 1171
	}
1172
	else if (qName.toLower() == QString("shieldsymbolizer"))
1173
	{
1174
	   Container = in_rule;
274 andreas 1175
 
275 andreas 1176
	   if (!Rule || !ShieldSymbolizer)
1177
	   {
1178
	      KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of SHIELDSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
1179
	      return false;
1180
	   }
274 andreas 1181
 
275 andreas 1182
	   shield_symbolizer ss(ShieldSymbolizer->name.toAscii().data(),
1183
				ShieldSymbolizer->face_name.toAscii().data(),
278 andreas 1184
				ShieldSymbolizer->size, setColor(ShieldSymbolizer->fill),
275 andreas 1185
				findIcon(ShieldSymbolizer->file).toAscii().data(),
1186
				getTypeText(ShieldSymbolizer->type),
1187
				ShieldSymbolizer->width, ShieldSymbolizer->height);
1188
 
1189
	   if (!ShieldSymbolizer->placement.isEmpty())
1190
	      ss.set_label_placement((ShieldSymbolizer->placement.toLower() == QString("point")) ? mapnik::POINT_PLACEMENT : mapnik::LINE_PLACEMENT);
1191
 
1192
	   if (ShieldSymbolizer->dx != 0 || ShieldSymbolizer->dy != 0)
1193
	      ss.set_displacement(ShieldSymbolizer->dx, ShieldSymbolizer->dy);
1194
 
1195
	   if (ShieldSymbolizer->mindistance != 0)
1196
	      ss.set_label_spacing(ShieldSymbolizer->mindistance);
1197
 
1198
	   Rule->rl.append(ss);
1199
	}
1200
	else if (qName.toLower() == QString("linepatternsymbolizer"))
1201
	{
1202
	   Container = in_rule;
1203
 
1204
	   if (!Rule || !LinePatternSymbolizer)
1205
	   {
1206
	      KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of LINEPATTERNSYMBOLIZER without start, or outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
1207
	      return false;
1208
	   }
1209
 
1210
	   Rule->rl.append(line_pattern_symbolizer(findIcon(LinePatternSymbolizer->file).toAscii().data(),
1211
						getTypeText(LinePatternSymbolizer->type),
1212
						LinePatternSymbolizer->width,
1213
						LinePatternSymbolizer->height));
1214
	}
1215
	else if (qName.toLower() == QString("filter") ||
1216
		 qName.toLower() == QString("maxscaledenominator") ||
1217
		 qName.toLower() == QString("minscaledenominator"))
1218
	   Container = in_rule;
1219
	else if (qName.toLower() == QString("rule"))
1220
	   Container = in_style;
276 andreas 1221
	else if (qName.toLower() == QString("elsefilter"))
1222
	{
1223
	   Container = in_rule;
1224
 
1225
	   if (!Rule)
1226
	   {
1227
	      KMessageBox::error(0, i18n("Error parsing %1, line %2: Ending of ELSEFILTER outside of a RULE detected!").arg(XmlPath).arg(XmlLine));
1228
	      return false;
1229
	   }
1230
 
1231
	   Rule->rl.set_else(true);
1232
	}
275 andreas 1233
	else if (qName.toLower() == QString("style"))
1234
	{
1235
	   Container = in_map;
1236
	   feature_type_style style;
1237
 
1238
	   if (Style->rule)
1239
	   {
1240
	      Rule = Style->rule;
1241
 
1242
	      while (Rule)
1243
	      {
1244
		 style.add_rule(Rule->rl);
274 andreas 1245
		 Rule = Rule->next;
1246
	      }
1247
	   }
1248
 
1249
	   // Add style to map
1250
	   m.insert_style(Style->name.toAscii().data(), style);
1251
	}
1252
 
1253
	return true;
273 andreas 1254
}
1255
 
1256
/*
1257
 * The reader calls this function when it has parsed a chunk of character data
1258
 * - either normal character data or character data inside a CDATA section.
1259
 */
275 andreas 1260
bool SRender::characters (const QString& chraw)
273 andreas 1261
{
276 andreas 1262
	if (chraw.at(0) == QChar('\n'))
1263
	{
1264
	   XmlLine++;
1265
	   return true;
1266
	}
1267
 
275 andreas 1268
	QString ch = chraw.trimmed();
1269
 
1270
	if (ch.length() == 0)
274 andreas 1271
	   return true;
1272
 
1273
	if (Container == in_rule && Rule)
1274
	{
1275
	   if (Field == FLD_FILTER)
275 andreas 1276
	   {
274 andreas 1277
	      Rule->filter = ch;
275 andreas 1278
 
1279
	      if (!Rule->filter.isEmpty())
276 andreas 1280
		 Rule->rl.set_filter(create_filter(Rule->filter.toLatin1().data(), "latin1"));
275 andreas 1281
	      else
1282
		 cerr << "Warning in file " << XmlPath.toAscii().data() << " at line " << XmlLine << ": Ignoring empty filter!" << endl;
1283
	   }
274 andreas 1284
	   else if (Field == FLD_MAXSCALE)
275 andreas 1285
	   {
274 andreas 1286
	      Rule->maxscale = ch.toDouble();
275 andreas 1287
	      Rule->rl.set_max_scale(Rule->maxscale);
1288
	   }
274 andreas 1289
	   else if (Field == FLD_MINSCALE)
275 andreas 1290
	   {
274 andreas 1291
	      Rule->minscale = ch.toDouble();
275 andreas 1292
	      Rule->rl.set_min_scale(Rule->minscale);
1293
	   }
274 andreas 1294
	}
1295
	else if (Container == in_linesymbolizer && LineSymbolizer)
1296
	{
1297
	   if (Field == FLD_CSSPARAMETER)
1298
	   {
1299
	      if (Names == stroke_stroke)
1300
		 LineSymbolizer->stroke = colorToUInt(ch);
1301
	      else if (Names == stroke_width)
1302
		 LineSymbolizer->stroke_width = ch.toDouble();
1303
	      else if (Names == stroke_linejoin)
1304
		 LineSymbolizer->stroke_linejoin = ch;
1305
	      else if (Names == stroke_linecap)
1306
		 LineSymbolizer->stroke_linecap = ch;
1307
	      else if (Names == stroke_opacity)
1308
		 LineSymbolizer->stroke_opacity = ch.toDouble();
1309
	      else if (Names == stroke_dasharray)
1310
	      {
1311
	      int pos;
1312
	      QString arr = ch;
1313
	      QStringList list;
1314
 
1315
		 list = arr.split(",", QString::SkipEmptyParts);
1316
 
1317
		 for (pos = 0; pos < list.size() && pos < 10; pos++)
1318
		    LineSymbolizer->stroke_dasharray[pos] = list.at(pos).toDouble();
1319
 
1320
		 LineSymbolizer->stroke_anz = pos;
1321
	      }
1322
	   }
1323
	}
1324
	else if (Container == in_polygonsymbolizer && PolygonSymbolizer)
1325
	{
1326
	   if (Field == FLD_CSSPARAMETER)
1327
	   {
1328
	      if (Names == fill)
1329
		 PolygonSymbolizer->fill = colorToUInt(ch);
1330
	      else if (Names == fill_opacity)
1331
		 PolygonSymbolizer->fill_opacity = ch.toDouble();
1332
	   }
1333
	}
1334
	else if (Container == in_layer && Lay)
1335
	{
1336
	   if (Field == FLD_STYLENAME)
1337
	      Lay->Styles << ch;
1338
	}
1339
	else if (Container == in_datasource && Lay)
1340
	{
1341
	   if (Field == FLD_PARAMETER)
1342
	   {
1343
	      if (Names == type)
1344
		 Lay->Datasource.type = ch;
1345
	      else if (Names == file)
275 andreas 1346
	      {
1347
	      QFileInfo qf(ch);
1348
	      QString hv0;
1349
 
1350
		 hv0 = shapePath;
1351
 
1352
		 if (hv0.right(1) != QString("/"))
1353
		    hv0 += "/";
1354
 
1355
		 hv0 += qf.fileName();
1356
 
276 andreas 1357
		 if (__map_type == MAP_SHAPE)
1358
		    qf.setFile (hv0 + ".shp");
1359
		 else if (__map_type == MAP_OSM)
1360
		    qf.setFile (hv0 + ".osm");
1361
 
275 andreas 1362
		 if (!qf.exists())
1363
		 {
276 andreas 1364
		    if (__map_type == MAP_SHAPE)
1365
		       KMessageBox::error(0, i18n("The shape file \"%1\" at line %2 does not exist!").arg(hv0+".shp").arg(XmlLine));
1366
		    else if (__map_type == MAP_OSM)
1367
		       KMessageBox::error(0, i18n("The OSM file \"%1\" at line %2 does not exist!").arg(hv0+".osm").arg(XmlLine));
1368
 
275 andreas 1369
		    return false;
1370
		 }
1371
 
1372
		 Lay->Datasource.file = hv0;
1373
	      }
276 andreas 1374
	      else if (Names == parser__)
1375
		 Lay->Datasource.parser = ch;
1376
	      else if (Names == url)
1377
		 Lay->Datasource.url = ch;
1378
	      else if (Names == bbox)
1379
		 Lay->Datasource.bbox = ch;
274 andreas 1380
	      else if (Names == host)
1381
		 Lay->Datasource.host = ch;
1382
	      else if (Names == user)
1383
		 Lay->Datasource.user = ch;
1384
	      else if (Names == dbname)
1385
		 Lay->Datasource.dbname = ch;
1386
	      else if (Names == table)
1387
		 Lay->Datasource.table = ch;
1388
	      else if (Names == estimate_extent)
1389
		 Lay->Datasource.estimate_extent = getBool(ch);
1390
	      else if (Names == extent)
1391
	      {
1392
		 QString arr = ch;
1393
		 QStringList list;
1394
		 list = arr.split(",");
275 andreas 1395
 
1396
		 if (list.size() >= 1)
1397
		    Lay->Datasource.ext_lx = list.at(0).toDouble();
1398
 
1399
		 if (list.size() >= 2)
1400
		    Lay->Datasource.ext_ly = list.at(1).toDouble();
1401
 
1402
		 if (list.size() >= 3)
1403
		    Lay->Datasource.ext_rx = list.at(2).toDouble();
1404
 
1405
		 if (list.size() >= 4)
1406
		    Lay->Datasource.ext_ry = list.at(3).toDouble();
274 andreas 1407
	      }
1408
	   }
1409
	}
1410
 
1411
	return true;
273 andreas 1412
}
1413
 
274 andreas 1414
QString SRender::getKey (int pos)
273 andreas 1415
{
1416
int i = 0;
1417
 
274 andreas 1418
	while (token[i].id > 0)
273 andreas 1419
	{
274 andreas 1420
	   if (token[i].id == pos)
1421
	      return token[i].name;
273 andreas 1422
 
1423
	   i++;
1424
	}
1425
 
1426
	return QString::null;
1427
}
1428
 
274 andreas 1429
TYPES SRender::getType(QString ty)
273 andreas 1430
{
274 andreas 1431
	if (ty.toLower() == QString("png"))
1432
	   return type_png;
1433
	else if (ty.toLower() == QString("gif"))
1434
	   return type_gif;
1435
	else if (ty.toLower() == QString("jpg"))
1436
	   return type_jpg;
1437
	else if (ty.toLower() == QString("xpm"))
1438
	   return type_xpm;
1439
	else if (ty.toLower() == QString("bmp"))
1440
	   return type_bmp;
1441
	else if (ty.toLower() == QString("tif") || ty.toLower() == QString("tiff"))
1442
	   return type_tif;
273 andreas 1443
 
274 andreas 1444
	return type_png;
1445
}
273 andreas 1446
 
274 andreas 1447
char *grTypes[] = { (char *)"png", (char *)"gif", (char *)"jpg", (char*)"xpm",
1448
		    (char *)"bmp", (char *)"tif" };
273 andreas 1449
 
274 andreas 1450
char *SRender::getTypeText(TYPES type)
1451
{
1452
	switch (type)
1453
	{
1454
	   case type_png: return grTypes[0]; break;
1455
	   case type_gif: return grTypes[1]; break;
1456
	   case type_jpg: return grTypes[2]; break;
1457
	   case type_xpm: return grTypes[3]; break;
1458
	   case type_bmp: return grTypes[4]; break;
1459
	   case type_tif: return grTypes[5]; break;
1460
	}
273 andreas 1461
 
274 andreas 1462
	return 0;
1463
}
273 andreas 1464
 
274 andreas 1465
bool SRender::getBool(QString b)
1466
{
1467
	if (b.toLower() == QString("true") ||
1468
	    b.toLower() == QString("on") ||
1469
	    b.toLower() == QString("1") ||
1470
	    b.toLower() == QString("yes") ||
1471
	    b.toLower() == QString("t") ||
1472
	    b.toLower() == QString("y"))
1473
	   return true;
273 andreas 1474
 
274 andreas 1475
	return false;
1476
}
273 andreas 1477
 
274 andreas 1478
bool SRender::getMap (double lx, double ly, double rx, double ry)
1479
{
275 andreas 1480
int width, height;
274 andreas 1481
QXmlSimpleReader reader;
1482
QString hv0;
1483
QFile file(XmlPath);
278 andreas 1484
QDir dir(fontPath);
275 andreas 1485
double plx, ply, prx, pry;
273 andreas 1486
 
275 andreas 1487
	hv0 = pluginPath;
1488
 
1489
	if (hv0.right(1) != QString("/"))
1490
	   hv0 += "/";
1491
 
274 andreas 1492
	datasource_cache::instance()->register_datasources(hv0.toAscii().data());
275 andreas 1493
	hv0 = fontPath;
1494
 
1495
	if (hv0.right(1) != QString("/"))
1496
	   hv0 += "/";
1497
 
278 andreas 1498
	// Load all fonts in directory
1499
	if (!dir.exists())
1500
	{
1501
	   KMessageBox::error(0, i18n("The font directory does not exist! Please select a valid directory with at least one true type font in it!"));
1502
	   return false;
1503
	}
273 andreas 1504
 
278 andreas 1505
	QStringList filters;
1506
	filters << "*.ttf";
1507
	dir.setNameFilters(filters);
1508
	dir.setFilter(QDir::Readable | QDir::Files);
1509
	QFileInfoList list = dir.entryInfoList();
1510
 
1511
	for (int i = 0; i < list.size(); ++i)
1512
	{
1513
	QString f;
1514
 
1515
	   QFileInfo fileInfo = list.at(i);
1516
	   f = hv0 + fileInfo.fileName();
1517
	   freetype_engine::register_font(f.toAscii().data());
1518
	}
1519
 
1520
//	hv0 += "DejaVuSans.ttf";	// Default font
1521
//	freetype_engine::register_font(hv0.toAscii().data());
1522
 
274 andreas 1523
	width = label->width();
1524
	height = label->height();
273 andreas 1525
 
274 andreas 1526
	m.setWidth(width);
1527
	m.setHeight(height);
273 andreas 1528
 
276 andreas 1529
	try
274 andreas 1530
	{
276 andreas 1531
	   if (!ControlSet)	// Initialize the map?
1532
	   {
1533
	      QXmlInputSource source (&file);
1534
	      reader.setContentHandler (this);
1535
	      reader.parse (source);
1536
	   }
273 andreas 1537
 
276 andreas 1538
	   plx = lx;
1539
	   ply = ly;
1540
	   prx = rx;
1541
	   pry = ry;
1542
	   projection pj(m.srs());
275 andreas 1543
 
278 andreas 1544
	   if (!geographic && pj.is_geographic())
276 andreas 1545
	   {
1546
	      pj.inverse(plx, ply);
1547
	      pj.inverse(prx, pry);
1548
	   }
278 andreas 1549
 
1550
	   if (geographic && pj.is_geographic())
276 andreas 1551
	   {
278 andreas 1552
	      pj.forward(plx, ply);
1553
	      pj.forward(prx, pry);
276 andreas 1554
	   }
275 andreas 1555
 
276 andreas 1556
	   // First we use Mapnik to create the map
1557
	   m.zoomToBox(Envelope<double>(plx, ply, prx, pry));
275 andreas 1558
 
278 andreas 1559
	   // Here we render the map to an image buffer
276 andreas 1560
	   Image32 buf(m.getWidth(), m.getHeight());
1561
	   agg_renderer<Image32> ren(m, buf);
1562
	   ren.apply();
273 andreas 1563
 
276 andreas 1564
	   // Put the image into a Qt object
1565
	   QImage image((uchar*)buf.raw_data(), m.getWidth(), m.getHeight(), QImage::Format_ARGB32);
1566
	   label->setPixmap(QPixmap::fromImage(image.rgbSwapped()));
1567
	}
1568
 
1569
	catch (const mapnik::config_error &ex)
1570
	{
1571
	   KMessageBox::error(0, i18n("Configuration error: %1").arg(ex.what()));
1572
	   return false;
1573
	}
1574
 
1575
	catch (const std::exception &ex)
1576
	{
1577
	   KMessageBox::error(0, i18n("Exception at file %1: %2").arg(XmlPath).arg(ex.what()));
1578
	   return false;
1579
	}
1580
 
1581
	catch (...)
1582
	{
1583
	   KMessageBox::error(0, i18n("Unknown exception occured!"));
1584
	   return false;
1585
	}
1586
 
274 andreas 1587
	return true;
1588
}
273 andreas 1589
 
275 andreas 1590
void SRender::setMaxExtent(double lx, double ly, double rx, double ry)
1591
{
1592
	if (lx > 0 && _lx > lx)
1593
	   _lx = lx;
1594
 
1595
	if (lx < 0 && _lx < lx)
1596
	   _lx = lx;
1597
 
1598
	if (ly > 0 && _ly > ly)
1599
	   _ly = ly;
1600
 
1601
	if (ly < 0 && _ly < ly)
1602
	   _ly = ly;
1603
 
1604
	if (rx > 0 && _rx < rx)
1605
	   _rx = rx;
1606
 
1607
	if (rx < 0 && _rx > rx)
1608
	   _rx = rx;
1609
 
1610
	if (ry > 0 && _ry < ry)
1611
	   _ry = ry;
1612
 
1613
	if (ry < 0 && _ry > ry)
1614
	   _ry = ry;
1615
}
1616
 
1617
QString SRender::findIcon(QString ic)
1618
{
1619
QString ptf, icon;
1620
QFileInfo fi(ic);
1621
 
1622
	icon = fi.fileName();
1623
	ptf = KStandardDirs::locate("data", QString("sportwatcher/icons/%1").arg(icon));
1624
 
1625
	if (ptf.length() < icon.length())
1626
	{
1627
	   KMessageBox::error(0, i18n("The icon %1 was not found!").arg(icon));
1628
	   ptf.clear();
1629
	}
1630
 
1631
	return ptf;
1632
}
1633
 
278 andreas 1634
color SRender::setColor(unsigned col)
1635
{
1636
color c;
1637
#if MAPNIK_VERSION == 600
1638
	c.set_bgr(col);
1639
#else
1640
	int r, g, b;
1641
	b = col / 65536;
1642
	g = (col - (b * 65536)) / 256;
1643
	r = col - ((b* 65536) + (g * 256));
1644
	c.set_red(r);
1645
	c.set_green(g);
1646
	c.set_blue(b);
1647
#endif
1648
	return c;
1649
}
1650
 
274 andreas 1651
RULE *SRender::getLastRule(RULE *first)
1652
{
1653
RULE *akt = first;
273 andreas 1654
 
274 andreas 1655
	while (akt)
1656
	{
1657
	   if (!akt->next)
1658
	      return akt;
1659
 
1660
	   akt = akt->next;
1661
	}
1662
 
1663
	return 0;
273 andreas 1664
}
1665
 
274 andreas 1666
POINTSYMBOLIZER *SRender::getLastPointSymbolizer(POINTSYMBOLIZER *first)
273 andreas 1667
{
274 andreas 1668
POINTSYMBOLIZER *akt = first;
273 andreas 1669
 
274 andreas 1670
	while (akt)
1671
	{
1672
	   if (!akt->next)
1673
	      return akt;
273 andreas 1674
 
274 andreas 1675
	   akt = akt->next;
1676
	}
273 andreas 1677
 
274 andreas 1678
	return 0;
1679
}
1680
 
1681
LINESYMBOLIZER *SRender::getLastLineSymbolizer(LINESYMBOLIZER *first)
1682
{
1683
LINESYMBOLIZER *akt = first;
1684
 
1685
	while (akt)
273 andreas 1686
	{
274 andreas 1687
	   if (!akt->next)
1688
	      return akt;
273 andreas 1689
 
274 andreas 1690
	   akt = akt->next;
273 andreas 1691
	}
1692
 
274 andreas 1693
	return 0;
1694
}
273 andreas 1695
 
274 andreas 1696
POLYGONSYMBOLIZER *SRender::getLastPolygonSymbolizer(POLYGONSYMBOLIZER *first)
1697
{
1698
POLYGONSYMBOLIZER *akt = first;
273 andreas 1699
 
274 andreas 1700
	while (akt)
273 andreas 1701
	{
274 andreas 1702
	   if (!akt->next)
1703
	      return akt;
273 andreas 1704
 
274 andreas 1705
	   akt = akt->next;
273 andreas 1706
	}
1707
 
274 andreas 1708
	return 0;
273 andreas 1709
}
1710
 
274 andreas 1711
TEXTSYMBOLIZER *SRender::getLastTextSymbolizer(TEXTSYMBOLIZER *first)
273 andreas 1712
{
274 andreas 1713
TEXTSYMBOLIZER *akt = first;
273 andreas 1714
 
274 andreas 1715
	while (akt)
273 andreas 1716
	{
274 andreas 1717
	   if (!akt->next)
1718
	      return akt;
273 andreas 1719
 
274 andreas 1720
	   akt = akt->next;
273 andreas 1721
	}
1722
 
274 andreas 1723
	return 0;
1724
}
273 andreas 1725
 
274 andreas 1726
POLYGONPATTERNSYMBOLIZER *SRender::getLastPolygonPatternSymbolizer(POLYGONPATTERNSYMBOLIZER *first)
1727
{
1728
POLYGONPATTERNSYMBOLIZER *akt = first;
273 andreas 1729
 
274 andreas 1730
	while (akt)
273 andreas 1731
	{
274 andreas 1732
	   if (!akt->next)
1733
	      return akt;
273 andreas 1734
 
274 andreas 1735
	   akt = akt->next;
273 andreas 1736
	}
1737
 
274 andreas 1738
	return 0;
273 andreas 1739
}
1740
 
274 andreas 1741
SHIELDSYMBOLIZER *SRender::getLastShieldSymbolizer(SHIELDSYMBOLIZER *first)
273 andreas 1742
{
274 andreas 1743
SHIELDSYMBOLIZER *akt = first;
273 andreas 1744
 
274 andreas 1745
	while (akt)
273 andreas 1746
	{
274 andreas 1747
	   if (!akt->next)
1748
	      return akt;
1749
 
1750
	   akt = akt->next;
273 andreas 1751
	}
1752
 
274 andreas 1753
	return 0;
273 andreas 1754
}
1755
 
274 andreas 1756
LINEPATTERNSYMBOLIZER *SRender::getLastLinePatternSymbolizer(LINEPATTERNSYMBOLIZER *first)
273 andreas 1757
{
274 andreas 1758
LINEPATTERNSYMBOLIZER *akt = first;
273 andreas 1759
 
1760
	while (akt)
1761
	{
1762
	   if (!akt->next)
1763
	      return akt;
1764
 
1765
	   akt = akt->next;
1766
	}
1767
 
1768
	return 0;
1769
}
1770
 
274 andreas 1771
STYLE *SRender::findStyle(QString name)
273 andreas 1772
{
274 andreas 1773
STYLE *akt = firstStyle;
273 andreas 1774
 
1775
	while (akt)
1776
	{
274 andreas 1777
	   if (akt->name.toLower() == name.toLower())
273 andreas 1778
	      return akt;
1779
 
1780
	   akt = akt->next;
1781
	}
1782
 
1783
	return 0;
1784
}
274 andreas 1785
 
1786
unsigned SRender::colorToUInt(QString col)
1787
{
1788
QColor qc(col);
1789
 
275 andreas 1790
	return (qc.blue() * 65536) + (qc.green() * 256) + qc.red();
274 andreas 1791
}
1792
 
1793
STYLE *SRender::allocStyle()
1794
{
1795
STYLE *St = new STYLE;
1796
 
1797
	St->name.clear();
1798
	St->rule = 0;
1799
	St->next = 0;
1800
	return St;
1801
}
1802
 
1803
RULE *SRender::allocRule()
1804
{
1805
RULE *Ru = new RULE;
1806
 
276 andreas 1807
	Ru->name.clear();
1808
	Ru->title.clear();
274 andreas 1809
	Ru->maxscale = 0;
1810
	Ru->minscale = 0;
276 andreas 1811
	Ru->elsefilter = false;
274 andreas 1812
	Ru->filter.clear();
1813
	Ru->LineSymbolizer = 0;
1814
	Ru->PolygonSymbolizer = 0;
1815
	Ru->TextSymbolizer = 0;
1816
	Ru->PointSymbolizer = 0;
1817
	Ru->PolygonPatternSymbolizer = 0;
1818
	Ru->ShieldSymbolizer = 0;
1819
	Ru->LinePatternSymbolizer = 0;
1820
	Ru->next = 0;
1821
	return Ru;
1822
}
1823
 
1824
LAYER *SRender::allocLayer()
1825
{
1826
LAYER *La = new LAYER;
1827
 
1828
	La->name.clear();	// The unique name
276 andreas 1829
	La->title.clear();
1830
	La->abstract.clear();
274 andreas 1831
	La->status = false;	// Is it active?
276 andreas 1832
	La->clear_label = false;
274 andreas 1833
	La->srs.clear();	// Projection
275 andreas 1834
	La->minzoom = 0.0;
1835
	La->maxzoom = 0.0;
276 andreas 1836
	La->queryable = false;
274 andreas 1837
	La->Datasource.type.clear();
1838
	La->Datasource.file.clear();
276 andreas 1839
	La->Datasource.parser.clear();
1840
	La->Datasource.url.clear();
1841
	La->Datasource.bbox.clear();
274 andreas 1842
	La->Datasource.host.clear();
1843
	La->Datasource.user.clear();
1844
	La->Datasource.dbname.clear();
1845
	La->Datasource.table.clear();
1846
	La->Datasource.estimate_extent = false;
1847
	La->Datasource.ext_lx = 0.0;
1848
	La->Datasource.ext_ly = 0.0;
1849
	La->Datasource.ext_rx = 0.0;
1850
	La->Datasource.ext_ry = 0.0;
1851
	La->next = 0;
1852
	return La;
1853
}
1854
 
1855
LINEPATTERNSYMBOLIZER *SRender::allocLinePatternSymbolizer()
1856
{
1857
LINEPATTERNSYMBOLIZER *lps = new LINEPATTERNSYMBOLIZER;
1858
 
1859
	lps->file.clear();
1860
	lps->type = type_png;		// enum TYPES
1861
	lps->width = 0.0;
1862
	lps->height = 0.0;
1863
	lps->next = 0;
1864
	return lps;
1865
}
1866
 
1867
SHIELDSYMBOLIZER *SRender::allocShieldSymbolizer()
1868
{
1869
SHIELDSYMBOLIZER *ss = new SHIELDSYMBOLIZER;
1870
 
1871
	ss->name.clear();
1872
	ss->face_name.clear();
1873
	ss->size = 0.0;
275 andreas 1874
	ss->fill = 0;			// Color
274 andreas 1875
	ss->placement.clear();
1876
	ss->file.clear();
1877
	ss->type = type_png;		// enum TYPES
1878
	ss->width = 0.0;
1879
	ss->height = 0.0;
275 andreas 1880
	ss->dx = 0.0;
1881
	ss->dy = 0.0;
274 andreas 1882
	ss->mindistance = 0.0;
1883
	ss->maxdistance = 0.0;
1884
	ss->next = 0;
1885
	return ss;
1886
}
1887
 
1888
POLYGONPATTERNSYMBOLIZER *SRender::allocPolygonPatternSymbolizer()
1889
{
1890
POLYGONPATTERNSYMBOLIZER *pps = new POLYGONPATTERNSYMBOLIZER;
1891
 
1892
	pps->file.clear();
1893
	pps->type = type_png;		// enum TYPES
1894
	pps->width = 0.0;
1895
	pps->height = 0.0;
1896
	pps->allow_overlap = false;
1897
	pps->next = 0;
1898
	return pps;
1899
}
1900
 
1901
POINTSYMBOLIZER *SRender::allocPointSymbolizer()
1902
{
1903
POINTSYMBOLIZER *ps = new POINTSYMBOLIZER;
1904
 
1905
	ps->file.clear();
1906
	ps->type = type_png;		// enum TYPES
1907
	ps->width = 0.0;
1908
	ps->height = 0.0;
1909
	ps->allow_overlap = false;
1910
	ps->next = 0;
1911
	return ps;
1912
}
1913
 
1914
TEXTSYMBOLIZER *SRender::allocTextSymbolizer()
1915
{
1916
TEXTSYMBOLIZER *ts = new TEXTSYMBOLIZER;
1917
 
1918
	ts->name.clear();
1919
	ts->face_name.clear();
276 andreas 1920
	ts->placement.clear();
1921
	ts->alignment.clear();
274 andreas 1922
	ts->size = 0;
1923
	ts->fill = 0;			// Color
1924
	ts->halo_radius = 0;
1925
	ts->wrap_width = 0;
275 andreas 1926
	ts->dx = 0.0;
274 andreas 1927
	ts->dy = 0.0;
1928
	ts->mindistance = 0.0;
1929
	ts->maxdistance = 0.0;
1930
	ts->next = 0;
1931
	return ts;
1932
}
1933
 
1934
POLYGONSYMBOLIZER *SRender::allocPolygonSymbolizer()
1935
{
1936
POLYGONSYMBOLIZER *ps = new POLYGONSYMBOLIZER;
1937
 
1938
	memset (ps, 0, sizeof(POLYGONSYMBOLIZER));
1939
	return ps;
1940
}
1941
 
1942
LINESYMBOLIZER *SRender::allocLineSymbolizer()
1943
{
1944
LINESYMBOLIZER *ls = new LINESYMBOLIZER;
1945
 
1946
	ls->stroke = 0;		// Color
1947
	ls->stroke_width = 0.0;
1948
	ls->stroke_linejoin.clear();
1949
	ls->stroke_linecap.clear();
1950
 
1951
	for (int i = 0; i < 10; i++)
1952
	   ls->stroke_dasharray[i] = 0.0;
1953
 
1954
	ls->stroke_anz = 0;		// number of entries in dasharray
1955
	ls->stroke_opacity = 0.0;
1956
	ls->next = 0;
1957
	return ls;
1958
}