1
/***************************************************************************
5
copyright : (C) 2005 by Radim Blazek
7
***************************************************************************/
8
/***************************************************************************
10
* This program is free software; you can redistribute it and/or modify *
11
* it under the terms of the GNU General Public License as published by *
12
* the Free Software Foundation; either version 2 of the License, or *
13
* (at your option) any later version. *
15
***************************************************************************/
24
#include <QStringList>
29
#include <QSvgRenderer>
32
#include "qgsapplication.h"
33
#include "qgsmarkercatalogue.h"
35
QgsMarkerCatalogue *QgsMarkerCatalogue::mMarkerCatalogue = 0;
37
QgsMarkerCatalogue::QgsMarkerCatalogue()
42
mList.append ( "hard:circle" );
43
mList.append ( "hard:rectangle" );
44
mList.append ( "hard:diamond" );
45
mList.append ( "hard:cross" );
46
mList.append ( "hard:cross2" );
47
mList.append ( "hard:triangle");
48
mList.append ( "hard:star");
51
QString svgPath = QgsApplication::svgPath();
56
QStringList dl = dir.entryList(QDir::Dirs);
58
for ( QStringList::iterator it = dl.begin(); it != dl.end(); ++it ) {
59
if ( *it == "." || *it == ".." ) continue;
61
QDir dir2 ( svgPath + *it );
63
QStringList dl2 = dir2.entryList("*.svg",QDir::Files);
65
for ( QStringList::iterator it2 = dl2.begin(); it2 != dl2.end(); ++it2 ) {
66
// TODO test if it is correct SVG
67
mList.append ( "svg:" + svgPath + *it + "/" + *it2 );
72
QStringList QgsMarkerCatalogue::list()
77
QgsMarkerCatalogue::~QgsMarkerCatalogue()
81
QgsMarkerCatalogue *QgsMarkerCatalogue::instance()
83
if ( !QgsMarkerCatalogue::mMarkerCatalogue ) {
84
QgsMarkerCatalogue::mMarkerCatalogue = new QgsMarkerCatalogue();
87
return QgsMarkerCatalogue::mMarkerCatalogue;
89
QPixmap QgsMarkerCatalogue::pixmapMarker ( QString fullName, int size, QPen pen, QBrush brush, bool qtBug )
91
//std::cerr << "QgsMarkerCatalogue::marker " << fullName.toLocal8Bit().data() << " sice:" << size << std::endl;
94
// First prepare the paintdevice that the marker will be drawn onto
97
if ( fullName.left(5) == "hard:" )
99
//Note teh +1 offset below is required because the
100
//otherwise the icons are getting clipped
101
myPixmap = QPixmap (size+1,size+1);
105
// TODO Change this logic so width is size and height is same
106
// proportion of scale factor as in oritignal SVG TS XXX
107
if (size < 1) size=1;
108
//QPixmap myPixmap = QPixmap(width,height);
109
myPixmap = QPixmap(size,size);
111
// The following is window-system-conditional since (at least)
112
// the combination of Qt 4.1.0 and RealVNC's Xvnc 4.1
113
// will result in the pixmap becoming invisible if it is filled
114
// with a non-opaque colour.
115
// This is probably because Xvnc 4.1 doesn't have the RENDER
116
// extension compiled into it.
117
#if defined(Q_WS_X11)
118
// Do a runtime test to see if the X RENDER extension is available
119
if ( myPixmap.x11PictureHandle() )
122
myPixmap.fill(QColor(255,255,255,0)); // transparent
123
#if defined(Q_WS_X11)
127
myPixmap.fill(QColor(255,255,255)); // opaque
130
QPainter myPainter(&myPixmap);
131
myPainter.setRenderHint(QPainter::Antialiasing);
134
// Now pass the paintdevice along to have the marker rndered on it
137
if ( fullName.left(5) == "hard:" )
139
hardMarker ( &myPainter, fullName.mid(5), size, pen, brush, qtBug );
142
else if ( fullName.left(4) == "svg:" )
144
svgMarker ( &myPainter, fullName.mid(4), size );
147
return QPixmap(); // empty
150
QPicture QgsMarkerCatalogue::pictureMarker ( QString fullName, int size, QPen pen, QBrush brush, bool qtBug )
154
// First prepare the paintdevice that the marker will be drawn onto
157
if ( fullName.left(5) == "hard:" )
159
//Note teh +1 offset below is required because the
160
//otherwise the icons are getting clipped
161
myPicture = QPicture (size+1);
165
// TODO Change this logic so width is size and height is same
166
// proportion of scale factor as in oritignal SVG TS XXX
167
if (size < 1) size=1;
168
//QPicture myPicture = QPicture(width,height);
169
myPicture = QPicture(size);
171
QPainter myPainter(&myPicture);
172
myPainter.setRenderHint(QPainter::Antialiasing);
175
// Now pass the paintdevice along to have the marker rndered on it
178
if ( fullName.left(5) == "hard:" )
180
hardMarker ( &myPainter, fullName.mid(5), size, pen, brush, qtBug );
183
else if ( fullName.left(4) == "svg:" )
185
svgMarker ( &myPainter, fullName.mid(4), size );
188
return QPicture(); // empty
191
void QgsMarkerCatalogue::svgMarker ( QPainter * thepPainter, QString filename, int scaleFactor)
194
mySVG.load(filename);
195
mySVG.render(thepPainter);
199
void QgsMarkerCatalogue::hardMarker (QPainter * thepPainter, QString name, int s, QPen pen, QBrush brush, bool qtBug )
201
// Size of polygon symbols is calculated so that the area is equal to circle with
202
// diameter mPointSize
205
int half = (int)floor(s/2.0); // number of points from center
206
int size = 2*half + 1; // must be odd
207
double area = 3.14 * (size/2.) * (size/2.);
211
thepPainter->begin(&picture);
212
thepPainter->setRenderHint(QPainter::Antialiasing);
214
// Also width must be odd otherwise there are discrepancies visible in canvas!
215
int lw = (int)(2*floor((double)pen.width()/2)+1); // -> lw > 0
217
thepPainter->setPen ( pen );
218
thepPainter->setBrush( brush);
221
if ( name == "circle" )
223
thepPainter->drawEllipse(0, 0, size, size);
225
else if ( name == "rectangle" )
227
size = (int) (2*floor(sqrt(area)/2.) + 1);
228
thepPainter->drawRect(0, 0, size, size);
230
else if ( name == "diamond" )
232
half = (int) ( sqrt(area/2.) );
234
pa.setPoint ( 0, 0, half);
235
pa.setPoint ( 1, half, 2*half);
236
pa.setPoint ( 2, 2*half, half);
237
pa.setPoint ( 3, half, 0);
238
thepPainter->drawPolygon ( pa );
240
// Warning! if pen width > 0 thepPainter->drawLine(x1,y1,x2,y2) will draw only (x1,y1,x2-1,y2-1) !
241
// It is impossible to draw lines as rectangles because line width scaling would not work
242
// (QPicture is scaled later in QgsVectorLayer)
243
// -> reset boundingRect for cross, cross2
244
else if ( name == "cross" )
249
add = 1; // lw always > 0
256
thepPainter->drawLine(0, half, size-1+add, half); // horizontal
257
thepPainter->drawLine(half, 0, half, size-1+add); // vertical
258
box.setRect ( 0, 0, size, size );
260
else if ( name == "cross2" )
262
half = (int) floor( s/2/sqrt(2.0));
267
add = 1; // lw always > 0
272
int addwidth = (int) ( 0.5 * lw ); // width correction, cca lw/2 * cos(45)
274
thepPainter->drawLine( 0, 0, size-1+add, size-1+add);
275
thepPainter->drawLine( 0, size-1, size-1+add, 0-add);
277
box.setRect ( -addwidth, -addwidth, size + 2*addwidth, size + 2*addwidth );
279
else if ( name == "triangle")
282
pa.setPoint ( 0, 0, size);
283
pa.setPoint ( 1, size, size);
284
pa.setPoint ( 2, half, 0);
285
thepPainter->drawPolygon ( pa );
287
else if (name == "star")
289
int oneThird = (int)(floor(size/3+0.5));
290
int twoThird = (int)(floor(size/3*2+0.5));
292
pa.setPoint(0, half, 0);
293
pa.setPoint(1, oneThird, oneThird);
294
pa.setPoint(2, 0, oneThird);
295
pa.setPoint(3, oneThird, half);
296
pa.setPoint(4, 0, size);
297
pa.setPoint(5, half, twoThird);
298
pa.setPoint(6, size, size);
299
pa.setPoint(7, twoThird, half);
300
pa.setPoint(8, size, oneThird);
301
pa.setPoint(9, twoThird, oneThird);
302
thepPainter->drawPolygon ( pa );
304
if ( name == "cross" || name == "cross2" )
306
picture.setBoundingRect ( box );