Skip to content

Commit 0f34618

Browse files

File tree

2 files changed

+116
-142
lines changed

2 files changed

+116
-142
lines changed
 

‎src/core/qgslabel.cpp

Lines changed: 115 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
* *
1515
***************************************************************************/
1616

17-
#include <math.h> //needed for win32 build (ts)
17+
#include <cmath>
18+
#include <limits>
1819

1920
#include <QString>
2021
#include <QFont>
@@ -45,10 +46,8 @@
4546
static const char * const ident_ =
4647
"$Id$";
4748

48-
4949
QgsLabel::QgsLabel( const QgsFieldMap & fields )
5050
{
51-
5251
mField = fields;
5352
mLabelFieldIdx.resize ( LabelFieldCount );
5453
for ( int i = 0; i < LabelFieldCount; i++ )
@@ -459,8 +458,8 @@ void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature
459458
{
460459
QgsGeometry* geometry = feature.geometry();
461460
unsigned char *geom = geometry->wkbBuffer();
461+
size_t geomlen = geometry->wkbSize();
462462
QGis::WKBTYPE wkbType = geometry->wkbType();
463-
464463
QgsPoint point;
465464

466465
switch (wkbType)
@@ -472,10 +471,11 @@ void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature
472471
case QGis::WKBPolygon25D:
473472
case QGis::WKBPolygon:
474473
{
475-
labelPoint(point, geom);
474+
labelPoint(point, geom, geomlen);
476475
points.push_back(point);
477476
}
478477
break;
478+
479479
case QGis::WKBMultiPoint25D:
480480
case QGis::WKBMultiPoint:
481481
case QGis::WKBMultiLineString25D:
@@ -484,11 +484,15 @@ void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature
484484
case QGis::WKBMultiPolygon:
485485
// Return a position for each individual in the multi-feature
486486
{
487-
int numFeatures = (int)(*(geom + 5));
488-
geom += 9; // now points to start of array of WKB's
489-
for (int i = 0; i < numFeatures; ++i)
487+
assert( 1+sizeof(wkbType)+sizeof(int)<=geomlen );
488+
geom += 1+sizeof(wkbType);
489+
int nFeatures = *(unsigned int *)geom;
490+
geom += sizeof(int);
491+
492+
unsigned char *feature = geom;
493+
for (int i = 0; i<nFeatures && feature; ++i)
490494
{
491-
geom = labelPoint(point, geom);
495+
feature = labelPoint(point, feature, geom+geomlen-feature);
492496
points.push_back(point);
493497
}
494498
}
@@ -498,156 +502,126 @@ void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature
498502
}
499503
}
500504

501-
unsigned char* QgsLabel::labelPoint ( QgsPoint& point, unsigned char* geom)
505+
unsigned char* QgsLabel::labelPoint ( QgsPoint& point, unsigned char *geom, size_t geomlen)
502506
{
503-
// Number of bytes that ints and doubles take in the WKB format.
504-
static const unsigned int sizeOfInt = 4;
505-
static const unsigned int sizeOfDouble = 8;
507+
// verify that local types match sizes as WKB spec
508+
assert( sizeof(int) == 4 );
509+
assert( sizeof(QGis::WKBTYPE) == 4 );
510+
assert( sizeof(double) == 8 );
511+
512+
if(geom==NULL) {
513+
QgsDebugMsg("empty wkb");
514+
return NULL;
515+
}
516+
517+
QGis::WKBTYPE wkbType;
518+
unsigned char *geomend = geom+geomlen;
506519

507-
QGis::WKBTYPE wkbType;
508-
bool hasZValue = false;
509-
double *x, *y;
510-
unsigned char *ptr;
511-
int *nPoints;
512-
// Upon return from this function, this variable will contain a
513-
// pointer to the first byte beyond the current feature.
514-
unsigned char *nextFeature = geom;
520+
assert( geom+1+sizeof(wkbType)<=geomend );
515521

516-
memcpy(&wkbType, (geom+1), sizeof(wkbType));
522+
geom++; // skip endianess
523+
memcpy(&wkbType, geom, sizeof(wkbType));
524+
geom += sizeof(wkbType);
517525

518-
switch (wkbType)
526+
int dims = 2;
527+
528+
switch (wkbType)
529+
{
530+
case QGis::WKBPoint25D:
531+
case QGis::WKBPoint:
519532
{
520-
case QGis::WKBPoint25D:
521-
case QGis::WKBPoint:
533+
assert( geom+2*sizeof(double)<=geomend );
534+
double *pts = (double *)geom;
535+
point.set( pts[0], pts[1] );
536+
geom += 2*sizeof(double);
537+
}
538+
break;
539+
540+
case QGis::WKBLineString25D:
541+
dims=3;
542+
case QGis::WKBLineString: // Line center
543+
{
544+
assert( geom+sizeof(int)<=geomend );
545+
int nPoints = *(unsigned int *)geom;
546+
geom += sizeof(int);
547+
548+
assert( geom+nPoints*sizeof(double)*dims<=geomend );
549+
550+
// get line center
551+
double *pts = (double *)geom;
552+
double tl = 0.0;
553+
for (int i = 1; i < nPoints; i++)
522554
{
523-
x = (double *) (geom + 5);
524-
y = (double *) (geom + 5 + sizeof(double));
525-
point.set(*x, *y);
526-
nextFeature += 1 + sizeOfInt + sizeOfDouble*2;
555+
double dx = pts[dims*i] - pts[dims*(i-1)];
556+
double dy = pts[dims*i+1] - pts[dims*(i-1)+1];
557+
tl += sqrt(dx*dx + dy*dy);
527558
}
528-
break;
529-
case QGis::WKBLineString25D:
530-
hasZValue = true;
531-
case QGis::WKBLineString: // Line center
559+
tl /= 2.0;
560+
561+
// find line center
562+
double l = 0.0;
563+
for (int i=1; i < nPoints; i++)
532564
{
533-
double dx, dy, tl, l;
534-
ptr = geom + 5;
535-
nPoints = (int *)ptr;
536-
if(hasZValue)
537-
{
538-
nextFeature += 1 + sizeOfInt*2 + (*nPoints)*sizeOfDouble*3;
539-
}
540-
else
541-
{
542-
nextFeature += 1 + sizeOfInt*2 + (*nPoints)*sizeOfDouble*2;
543-
}
544-
ptr = geom + 1 + 2 * sizeof(int);
565+
double dx = pts[dims*i] - pts[dims*(i-1)];
566+
double dy = pts[dims*i+1] - pts[dims*(i-1)+1];
567+
double dl = sqrt(dx*dx + dy*dy);
545568

546-
tl = 0;
547-
for (int i = 1; i < *nPoints; i++)
569+
if ( l+dl > tl )
548570
{
549-
if(hasZValue)
550-
{
551-
dx = ((double *)ptr)[3*i] - ((double *)ptr)[3*i-3];
552-
dy = ((double *)ptr)[3*i+1] - ((double *)ptr)[3*i-2];
553-
}
554-
else
555-
{
556-
dx = ((double *)ptr)[2*i] - ((double *)ptr)[2*i-2];
557-
dy = ((double *)ptr)[2*i+1] - ((double *)ptr)[2*i-1];
558-
}
559-
tl += sqrt(dx*dx + dy*dy);
560-
}
561-
tl /= 2;
571+
double k = (tl-l)/dl;
562572

563-
l = 0;
564-
for (int i = 1; i < *nPoints; i++)
565-
{
566-
double dl;
567-
if(hasZValue)
568-
{
569-
dx = ((double *)ptr)[3*i] - ((double *)ptr)[3*i-3];
570-
dy = ((double *)ptr)[3*i+1] - ((double *)ptr)[3*i-2];
571-
}
572-
else
573-
{
574-
dx = ((double *)ptr)[2*i] - ((double *)ptr)[2*i-2];
575-
dy = ((double *)ptr)[2*i+1] - ((double *)ptr)[2*i-1];
576-
}
577-
dl = sqrt(dx*dx + dy*dy);
578-
579-
if ( l+dl > tl )
580-
{
581-
l = tl - l;
582-
double k = l/dl;
583-
584-
if(hasZValue)
585-
{
586-
point.setX ( ((double *)ptr)[3*i-3] + k * dx );
587-
point.setY ( ((double *)ptr)[3*i-2] + k * dy );
588-
}
589-
else
590-
{
591-
point.setX ( ((double *)ptr)[2*i-2] + k * dx );
592-
point.setY ( ((double *)ptr)[2*i-1] + k * dy );
593-
}
594-
break;
595-
}
596-
l += dl;
573+
point.set( pts[dims*(i-1)] + k * dx,
574+
pts[dims*(i-1)+1] + k * dy);
575+
break;
597576
}
577+
578+
l += dl;
598579
}
599-
break;
600580

601-
case QGis::WKBPolygon25D:
602-
hasZValue = true;
603-
case QGis::WKBPolygon:
581+
geom += nPoints*sizeof(double)*dims;
582+
}
583+
break;
584+
585+
case QGis::WKBPolygon25D:
586+
dims = 3;
587+
case QGis::WKBPolygon: // centroid of outer ring
588+
{
589+
assert( geom+sizeof(int)<=geomend);
590+
int nRings = *(unsigned int *)geom;
591+
geom += sizeof(int);
592+
593+
for (int i=0; i<nRings; ++i)
604594
{
605-
double sx, sy;
606-
ptr = geom + 1 + 2 * sizeof(int); // set pointer to the first ring
607-
nPoints = (int *) ptr;
608-
ptr += 4;
609-
sx = sy = 0;
610-
for (int i = 0; i < *nPoints-1; i++)
611-
{
612-
if(hasZValue)
613-
{
614-
sx += ((double *)ptr)[3*i];
615-
sy += ((double *)ptr)[3*i+1];
616-
}
617-
else
618-
{
619-
sx += ((double *)ptr)[2*i];
620-
sy += ((double *)ptr)[2*i+1];
621-
}
622-
}
623-
point.setX ( sx/(*nPoints-1) );
624-
point.setY ( sy/(*nPoints-1) );
625-
// Work out a pointer to the next feature after this one.
626-
int numRings = (int)(*(geom+1+sizeOfInt));
627-
unsigned char* nextRing = nextFeature + 1 + 2*sizeOfInt;
628-
for (int i = 0; i < numRings; ++i)
629-
{
630-
int numPoints = (int)(*nextRing);
631-
// get the start of the next ring
632-
if(hasZValue)
633-
{
634-
nextRing += sizeOfInt + numPoints*sizeOfDouble*3;
635-
}
636-
else
637-
{
638-
nextRing += sizeOfInt + numPoints*sizeOfDouble*2;
639-
}
595+
assert( geom+sizeof(int)<=geomend );
596+
int nPoints = *(unsigned int *)geom;
597+
geom += sizeof(int);
598+
599+
assert( geom+nPoints*sizeof(double)*dims<=geomend );
600+
601+
if( i==0 ) {
602+
double sx=0.0, sy=0.0;
603+
double *pts = (double*) geom;
604+
for (int j=0; j<nPoints-1; j++) {
605+
sx += pts[dims*j];
606+
sy += pts[dims*j+1];
607+
}
608+
point.set( sx/(nPoints-1),
609+
sy/(nPoints-1) );
640610
}
641-
nextFeature = nextRing;
642-
}
643-
break;
644611

645-
default:
646-
// To get here is a bug because our caller should be filtering
647-
// on wkb type.
648-
break;
612+
geom += nPoints*sizeof(double)*dims;
613+
}
649614
}
650-
return nextFeature;
615+
break;
616+
617+
default:
618+
// To get here is a bug because our caller should be filtering
619+
// on wkb type.
620+
QgsDebugMsg("unsupported wkb type");
621+
return NULL;
622+
}
623+
624+
return geom;
651625
}
652626

653627
static int _elementFieldIndex(QDomElement& el)

‎src/core/qgslabel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class CORE_EXPORT QgsLabel
133133
void labelPoint ( std::vector<QgsPoint>&, QgsFeature & feature );
134134

135135
/** Get label point for the given feature in wkb format. */
136-
unsigned char* labelPoint( QgsPoint& point, unsigned char* wkb);
136+
unsigned char* labelPoint( QgsPoint& point, unsigned char* wkb, size_t wkblen);
137137

138138
/** Color to draw selected features */
139139
QColor mSelectionColor;

0 commit comments

Comments
 (0)
Please sign in to comment.