Skip to content
Permalink
Browse files
Update version to 0.7.9.10
Deprecated use of Q3Picture for marker symbols as part of the qt4 porting effort.
Markers are now loaded and renderered using the new QSvgRenderer that came with qt 4.1
onto a qpixmap. QgsSvgCache now stores these pixmaps intead of q3pictures.
Changed miscellanious other classes to deal wiht the knock-on effect of this cahnge.
A benifit of this change is that svgs are now rendered properly (overlooking caveaat below) 
and that the resampling code that was used to overcome poor svg scaling in qpitcure in qt3 is 
no longer used. Also we are able to support a richer subset of the svg format including 
possibility for animated svg in the future.

NOTE: there is still a small renderning issue where the background of the svg and various other
small issues - these will be fixed in follow up commits


git-svn-id: http://svn.osgeo.org/qgis/trunk@4721 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
timlinux committed Jan 23, 2006
1 parent 826096d commit eeff2cfac8b26313eac9e8618377e0b32eff5766
@@ -1,6 +1,9 @@
/* ChangeLog,v 1.214 2004/11/12 00:42:21 gsherman Exp */
------------------------------------------------------------------------------
Version 0.8 'Joesephine' .... development version
2006-01-23 [timlinux] 0.7.9.10
** Dropped use of qpicture and resampling for point markers in favour of
qt4.1 qsvgrenderer new goodies
2006-01-09 [timlinux] 0.7.9.8
** Moved plugins into src/plugins
2006-01-08 [timlinux] 0.7.9.8
@@ -29,7 +29,7 @@ dnl ---------------------------------------------------------------------------
MAJOR_VERSION=0
MINOR_VERSION=7
MICRO_VERSION=9
EXTRA_VERSION=9
EXTRA_VERSION=10
if test $EXTRA_VERSION -eq 0; then
VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}
else
@@ -303,10 +303,10 @@ QRect QgsComposerVectorLegend::render ( QPainter *p )
if ( itemHeights[icnt] < mSymbolHeight ) { // init first
itemHeights[icnt] = mSymbolHeight;
}
Q3Picture pic = sym->getPointSymbolAsPicture(0,widthScale);
QRect br = pic.boundingRect();
QPixmap pic = sym->getPointSymbolAsPixmap(0,widthScale);

int h = (int) ( scale * br.height() );

int h = (int) ( scale * pic.height() );
if ( h > itemHeights[icnt] ) {
itemHeights[icnt] = h;
}
@@ -385,14 +385,13 @@ QRect QgsComposerVectorLegend::render ( QPainter *p )
double scale = map->symbolScale() * mComposition->scale();

// Get the picture of appropriate size directly from catalogue
Q3Picture pic = sym->getPointSymbolAsPicture(0,widthScale);
QPixmap pic = sym->getPointSymbolAsPixmap(0,widthScale);

QRect br = pic.boundingRect();

painter->save();
painter->scale(scale,scale);
painter->drawPicture ( static_cast<int>( (1.*mMargin+mSymbolWidth/2)/scale-br.x()-1.*br.width()/2),
static_cast<int>( (1.*localHeight+symbolHeight/2)/scale-br.y()-1.*br.height()/2),
painter->drawPixmap ( static_cast<int>( (1.*mMargin+mSymbolWidth/2)/scale-pic.width()-1.*pic.width()/2),
static_cast<int>( (1.*localHeight+symbolHeight/2)/scale-pic.height()-1.*pic.height()/2),
pic );
painter->restore();

@@ -25,6 +25,7 @@
#include <qrect.h>
#include <q3pointarray.h>
#include <qdir.h>
#include <QPicture>

#include "qgsapplication.h"
#include "qgssvgcache.h"
@@ -83,60 +84,39 @@ QgsMarkerCatalogue *QgsMarkerCatalogue::instance()
return QgsMarkerCatalogue::mMarkerCatalogue;
}

Q3Picture QgsMarkerCatalogue::marker ( QString fullName, int size, QPen pen, QBrush brush, int oversampling, bool qtBug )
QPixmap QgsMarkerCatalogue::marker ( QString fullName, int size, QPen pen, QBrush brush, int oversampling, bool qtBug )
{
//std::cerr << "QgsMarkerCatalogue::marker" << std::endl;
Q3Picture picture;

if ( fullName.left(5) == "hard:" ) {
return hardMarker ( fullName.mid(5), size, pen, brush, oversampling, qtBug );
QPicture myPicture = hardMarker ( fullName.mid(5), size, pen, brush, oversampling, qtBug );
QPixmap myPixmap = QPixmap (myPicture.width(),myPicture.height());
QPainter myPainter(&myPixmap);
myPainter.drawPicture(0,0,myPicture);
return myPixmap;
} else if ( fullName.left(4) == "svg:" ) {
return svgMarker ( fullName.mid(4), size, oversampling );
}

return picture; // empty
return QPixmap(); // empty
}

Q3Picture QgsMarkerCatalogue::svgMarker ( QString name, int s, int oversampling )
QPixmap QgsMarkerCatalogue::svgMarker ( QString name, int s, int oversampling )
{
Q3Picture picture;
QPainter painter;
painter.begin(&picture);

if ( oversampling <= 1 )
{
Q3Picture pic = QgsSVGCache::instance().getPicture(name);

QRect br = pic.boundingRect();

double scale = 1. * s / ( ( br.width() + br.height() ) / 2 ) ;

painter.scale ( scale, scale );
painter.drawPicture ( 0, 0, pic );

}
else
{
QPixmap pixmap = QgsSVGCache::instance().getPixmap(name,1.);

double scale = 1. * s / ( ( pixmap.width() + pixmap.height() ) / 2 ) ;

pixmap = QgsSVGCache::instance().getPixmap(name,scale);

painter.drawPixmap ( 0, 0, pixmap );

}
painter.end();

return picture;
return pixmap;
}

Q3Picture QgsMarkerCatalogue::hardMarker ( QString name, int s, QPen pen, QBrush brush, int oversampling, bool qtBug )
QPicture QgsMarkerCatalogue::hardMarker ( QString name, int s, QPen pen, QBrush brush, int oversampling, bool qtBug )
{
// Size of polygon symbols is calculated so that the area is equal to circle with
// diameter mPointSize

Q3Picture picture;
QPicture picture;

// Size for circle
int half = (int)floor(s/2.0); // number of points from center
@@ -21,7 +21,7 @@
#include <qbrush.h>
#include <qpen.h>
#include <qpixmap.h>
#include <q3picture.h>
#include <qpicture.h>
#include <qdom.h>
#include <qstringlist.h>

@@ -43,7 +43,7 @@ class QgsMarkerCatalogue{
/** Returns picture of the marker
* \param fullName full name, e.g. hard:circle, svg:/home/usr1/marker1.svg
*/
Q3Picture marker ( QString fullName, int size, QPen pen, QBrush brush, int oversampling = 1, bool qtBug = true );
QPixmap marker ( QString fullName, int size, QPen pen, QBrush brush, int oversampling = 1, bool qtBug = true );

private:

@@ -56,10 +56,10 @@ class QgsMarkerCatalogue{
QStringList mList;

/** Hard coded */
Q3Picture hardMarker ( QString name, int size, QPen pen, QBrush brush, int oversampling = 1, bool qtBug = true );
QPicture hardMarker ( QString name, int size, QPen pen, QBrush brush, int oversampling = 1, bool qtBug = true );

/** Hard coded */
Q3Picture svgMarker ( QString name, int size, int oversampling = 1 );
QPixmap svgMarker ( QString name, int size, int oversampling = 1 );
};

#endif // QGSMARKERCATALOGUE_H
@@ -23,7 +23,7 @@ class QgsMapToPixel;
class QgsVectorLayer;
class QPainter;
class QgsDlgVectorLayerProperties;
class Q3Picture;
class QPixmap;
class QDomNode;
class QColor;

@@ -53,7 +53,7 @@ class QgsRenderer
@param f a pointer to the feature to be rendered
@param pic pointer to a marker from SVG (is only used by marker renderers)
@param scalefactor pointer to the scale factor for the marker image*/
virtual void renderFeature(QPainter* p, QgsFeature* f,Q3Picture* pic, double* scalefactor, bool selected, int oversampling = 1, double widthScale = 1.)=0;
virtual void renderFeature(QPainter* p, QgsFeature* f,QPixmap* pic, double* scalefactor, bool selected, int oversampling = 1, double widthScale = 1.)=0;
/**Reads the renderer configuration from an XML file
@param rnode the DOM node to read
@param vl the vector layer which will be associated with the renderer*/
@@ -27,6 +27,7 @@
#include "qgssvgcache.h"
//Added by qt3to4:
#include <QPixmap>
#include <QSvgRenderer>


QgsSVGCache::QgsSVGCache() {
@@ -35,60 +36,55 @@ QgsSVGCache::QgsSVGCache() {
pixelLimit = settings.readNumEntry("/qgis/svgcachesize", 200000);
totalPixels = 0;
}
QgsSVGCache::~QgsSVGCache()
{
//QMapIterator<QString, QSvgRenderer *> i(pictureMap);
//while (i.hasNext()) {
// i.next();
// delete i.value() ;
//}
//pictureMap.clear();
}

Q3Picture QgsSVGCache::getPicture(QString filename)
QSvgRenderer * QgsSVGCache::getPicture(QString filename)
{
PictureMap::const_iterator iter;
PictureMap::key_type key(filename);

iter = pictureMap.find(key);
PictureMap::const_iterator i = pictureMap.find(filename);
while (i != pictureMap.end())
{
return (*i).second ;
}

if (iter != pictureMap.end()) {
#if QGISDEBUG > 2
std::cerr<<"SVGCACHE: " << filename << " is already loaded"<<std::endl;
#endif
return iter->second;
}
QSvgRenderer * mySVG;
mySVG->load(filename);

#if QGISDEBUG > 2
std::cerr<<"SVGCACHE: loading " << filename << std::endl;
#endif

Q3Picture pic;
pic.load(filename,"svg");

pictureMap[key] = pic;
pictureMap[filename] = mySVG;

return pic;
return mySVG;
}

QPixmap QgsSVGCache::getPixmap(QString filename, double scaleFactor) {
QPixmap QgsSVGCache::getPixmap(QString filename, double scaleFactor)
{

// make the symbols smaller
scaleFactor *= 0.30;

PixmapMap::const_iterator iter;
PixmapMap::key_type key(filename, scaleFactor);
iter = pixmapMap.find(key);

// if we already have the pixmap, return it
if (iter != pixmapMap.end()) {
#if QGISDEBUG > 2
std::cerr<<"SVGCACHE: "<<filename<<"["<<scaleFactor
<<"] is already loaded"<<std::endl;
#endif
return iter->second;
std::pair<QString, double> myPair(filename, scaleFactor) ;
PixmapMap::iterator i = pixmapMap.find(myPair);
while (i != pixmapMap.end())
{
QPixmap myPixmap = i->second ;
return myPixmap;
}

// if not, try to load it
#if QGISDEBUG > 2
std::cerr<<"SVGCACHE: loading "<<filename<<"["<<scaleFactor<<"]"<<std::endl;
#endif
Q3Picture pic;
pic.load(filename,"svg");
int width=pic.boundingRect().width();
QSvgRenderer mySVG;
mySVG.load(filename);
int width=mySVG.defaultSize().width();
width=static_cast<int>(static_cast<double>(width)*scaleFactor);
int height=pic.boundingRect().height();
int height=mySVG.defaultSize().height();
height=static_cast<int>(static_cast<double>(height)*scaleFactor);

//prevent 0 width or height, which would cause a crash
@@ -99,63 +95,18 @@ QPixmap QgsSVGCache::getPixmap(QString filename, double scaleFactor) {
height = 1;
}

// render and rescale it (with smoothing)
QPixmap osPixmap(oversampling*width,oversampling*height);
osPixmap.fill(QColor(qRgb(255, 255, 0)));
QPainter p(&osPixmap);
p.scale(scaleFactor*oversampling,scaleFactor*oversampling);
p.drawPicture(0,0,pic);
QImage osImage = osPixmap.convertToImage();
// set a mask - this is probably terribly inefficient
osImage.setAlphaBuffer(true);
for (int i = 0; i < osImage.width(); ++i) {
for (int j = 0; j < osImage.height(); ++j) {
#ifdef Q_OS_MACX
// set opaque since pixels are transparent by default
QRgb pixel = osImage.pixel(i, j);
if (pixel != qRgba(255, 255, 0, 0)) {
osImage.setPixel(i, j, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), 255));
}
#else
// set transparent since pixels are opaque by default
if (osImage.pixel(i, j) == qRgb(255, 255, 0)) {
osImage.setPixel(i, j, qRgba(255, 255, 0, 0));
}
#endif
}
}
if (oversampling != 1)
osImage = osImage.smoothScale(width, height);
QPixmap pixmap = QPixmap(osImage);

// cache it if possible, and remove other pixmaps from the cache
// if it grows too large
if (width * height < pixelLimit) {
#if QGISDEBUG > 2
std::cerr<<"SVGCACHE: Caching "<<filename<<"["<<scaleFactor<<"]"
<<std::endl;
#endif
pixmapMap[key] = pixmap;
fifo.push(key);
totalPixels += width * height;
while (totalPixels > pixelLimit) {
#if QGISDEBUG > 2
std::cerr<<"SVGCACHE: Deleting "<<fifo.front().first<<"["
<<fifo.front().second<<"] from cache"<<std::endl;
#endif
QPixmap& oldPM(pixmapMap[fifo.front()]);
fifo.pop();
totalPixels -= oldPM.width() * oldPM.height();
}
}

return pixmap;
QPixmap myPixmap = QPixmap(width,height);
myPixmap.fill(QColor(255,255,255.0)); //transparent
QPainter myPainter(&myPixmap);
mySVG.render(&myPainter);
pixmapMap[std::pair<QString, double>(filename, scaleFactor)] = myPixmap;
return myPixmap;
}


void QgsSVGCache::clear() {
pixmapMap.clear();
fifo = std::queue<PixmapMap::key_type>();
fifo = std::queue<std::pair<QString, double> >();
totalPixels = 0;
}

0 comments on commit eeff2cf

Please sign in to comment.