22 #include <QFontMetrics>
26 #include <QDomElement>
44 #define M_PI 4*atan(1.0)
49 mMaxScale( 100000000 ),
50 mScaleBasedVisibility( false )
56 mLabelFieldIdx[i] = -1;
63 delete mLabelAttributes;
68 int idx = mLabelFieldIdx[attr];
69 return idx < 0 ? QString() : feature.
attribute( idx ).toString();
76 Q_UNUSED( classAttributes );
89 double x1 = point.
x();
91 double x2 = point.
x();
92 double scale = ( x2 - x1 ) * 0.001;
96 if ( value.isEmpty() )
98 text = mLabelAttributes->
text();
107 if ( value.isEmpty() )
109 font.setFamily( mLabelAttributes->
family() );
113 font.setFamily( value );
118 if ( value.isEmpty() )
120 size = mLabelAttributes->
size();
124 size = value.toDouble();
128 if ( value.isEmpty() )
129 sizeType = mLabelAttributes->
sizeType();
132 value = value.toLower();
133 if ( value.compare(
"mapunits" ) == 0 )
144 double sizeMM = size * 0.3527;
152 if ((
int )size <= 0 )
156 font.setPixelSize( size );
159 if ( value.isEmpty() )
161 pen.setColor( mLabelAttributes->
color() );
165 pen.setColor( QColor( value ) );
169 if ( value.isEmpty() )
171 font.setBold( mLabelAttributes->
bold() );
175 font.setBold((
bool ) value.toInt() );
179 if ( value.isEmpty() )
181 font.setItalic( mLabelAttributes->
italic() );
185 font.setItalic((
bool ) value.toInt() );
189 if ( value.isEmpty() )
191 font.setUnderline( mLabelAttributes->
underline() );
195 font.setUnderline((
bool ) value.toInt() );
199 if ( value.isEmpty() )
201 font.setStrikeOut( mLabelAttributes->
strikeOut() );
205 font.setStrikeOut((
bool ) value.toInt() );
210 bool useOverridePoint =
false;
212 if ( !value.isEmpty() )
214 overridePoint.
setX( value.toDouble() );
215 useOverridePoint =
true;
218 if ( !value.isEmpty() )
220 overridePoint.
setY( value.toDouble() );
221 useOverridePoint =
true;
226 QFontMetrics fm( font );
231 QStringList texts = text.split(
"\n" );
234 for (
int i = 0; i < texts.size(); i++ )
236 int w = fm.width( texts[i] );
241 height = fm.height() * texts.size();
245 width = fm.width( text );
246 height = fm.height();
253 if ( value.isEmpty() )
255 alignment = mLabelAttributes->
alignment();
259 value = value.toLower();
263 if ( value.contains(
"left" ) )
264 alignment |= Qt::AlignLeft;
265 else if ( value.contains(
"right" ) )
266 alignment |= Qt::AlignRight;
268 alignment |= Qt::AlignHCenter;
270 if ( value.contains(
"bottom" ) )
271 alignment |= Qt::AlignBottom;
272 else if ( value.contains(
"top" ) )
273 alignment |= Qt::AlignTop;
275 alignment |= Qt::AlignVCenter;
278 if ( alignment & Qt::AlignLeft )
282 else if ( alignment & Qt::AlignHCenter )
286 else if ( alignment & Qt::AlignRight )
291 if ( alignment & Qt::AlignBottom )
295 else if ( alignment & Qt::AlignVCenter )
299 else if ( alignment & Qt::AlignTop )
305 double xoffset, yoffset;
307 if ( value.isEmpty() )
309 xoffset = mLabelAttributes->
xOffset();
313 xoffset = value.toDouble();
316 if ( value.isEmpty() )
318 yoffset = mLabelAttributes->
yOffset();
322 yoffset = value.toDouble();
333 xoffset = xoffset * 0.3527 * renderContext.
scaleFactor();
334 yoffset = yoffset * 0.3527 * renderContext.
scaleFactor();
340 if ( value.isEmpty() )
342 ang = mLabelAttributes->
angle();
346 ang = value.toDouble();
353 if ( useOverridePoint )
355 renderLabel( renderContext, overridePoint, text, font, pen, dx, dy,
356 xoffset, yoffset, ang, width, height, alignment );
360 std::vector<labelpoint> points;
361 labelPoint( points, feature );
362 for ( uint i = 0; i < points.size(); ++i )
364 renderLabel( renderContext, points[i].p, text, font, pen, dx, dy,
365 xoffset, yoffset, mLabelAttributes->
angleIsAuto() ? points[i].angle : ang, width, height, alignment );
372 QString text, QFont font, QPen pen,
374 double xoffset,
double yoffset,
376 int width,
int height,
int alignment )
378 QPainter *painter = renderContext.
painter();
390 QgsDebugMsg(
"Caught transform error. Skipping rendering this label" );
397 double x = point.
x();
398 double y = point.
y();
400 double rad = ang *
M_PI / 180;
402 x = x + xoffset * cos( rad ) - yoffset * sin( rad );
403 y = y - xoffset * sin( rad ) - yoffset * cos( rad );
406 painter->setFont( font );
407 painter->translate( x, y );
410 painter->rotate( -ang );
421 bufferPen.setColor( mLabelAttributes->
bufferColor() );
425 bufferPen.setColor( Qt::white );
427 painter->setPen( bufferPen );
429 double bufferStepSize;
439 for (
double i = dx - myBufferSize; i <= dx + myBufferSize; i += bufferStepSize )
441 for (
double j = dy - myBufferSize; j <= dy + myBufferSize; j += bufferStepSize )
444 painter->drawText( QRectF( i, j - height, width, height ), alignment, text );
446 painter->drawText( QPointF( i, j ), text );
451 painter->setPen( pen );
453 painter->drawText( dx, dy - height, width, height, alignment, text );
455 painter->drawText( dx, dy, text );
463 if ( mLabelFieldIdx[i] == -1 )
466 for ( QgsAttributeList::iterator it = fields.begin(); it != fields.end(); ++it )
468 if ( *it == mLabelFieldIdx[i] )
476 fields.append( mLabelFieldIdx[i] );
496 mLabelFieldIdx[attr] = fieldIndex;
504 int fieldIndex = mLabelFieldIdx[attr];
505 if ( fieldIndex < 0 || fieldIndex >= mFields.
count() )
507 return mFields[fieldIndex].name();
512 return mLabelAttributes;
515 void QgsLabel::labelPoint( std::vector<labelpoint>& points,
QgsFeature & feature )
518 const unsigned char *geom = geometry->
asWkb();
519 size_t geomlen = geometry->
wkbSize();
532 labelPoint( point, geom, geomlen );
533 points.push_back( point );
545 Q_ASSERT( 1 +
sizeof( wkbType ) +
sizeof(
int ) <= geomlen );
546 geom += 1 +
sizeof( wkbType );
547 int nFeatures = *(
unsigned int * )geom;
548 geom +=
sizeof( int );
550 const unsigned char *feature = geom;
551 for (
int i = 0; i < nFeatures && feature; ++i )
553 feature = labelPoint( point, feature, geom + geomlen - feature );
554 points.push_back( point );
559 QgsDebugMsg(
"Unknown geometry type of " + QString::number( wkbType ) );
563 const unsigned char* QgsLabel::labelPoint( labelpoint& point,
const unsigned char *geom,
size_t geomlen )
566 Q_ASSERT(
sizeof(
int ) == 4 );
568 Q_ASSERT(
sizeof(
double ) == 8 );
578 const unsigned char *geomend = geom + geomlen;
582 Q_ASSERT( geom + 1 +
sizeof( wkbType ) <= geomend );
585 memcpy( &wkbType, geom,
sizeof( wkbType ) );
586 geom +=
sizeof( wkbType );
595 Q_ASSERT( geom + 2*
sizeof(
double ) <= geomend );
596 double *pts = (
double * )geom;
597 point.p.set( pts[0], pts[1] );
599 geom += 2 *
sizeof( double );
608 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
609 int nPoints = *(
unsigned int * )geom;
610 geom +=
sizeof( int );
612 Q_ASSERT( geom + nPoints*
sizeof(
double )*dims <= geomend );
615 double *pts = (
double * )geom;
617 for (
int i = 1; i < nPoints; i++ )
619 double dx = pts[dims*i] - pts[dims*( i-1 )];
620 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
621 tl += sqrt( dx * dx + dy * dy );
627 for (
int i = 1; i < nPoints; i++ )
629 double dx = pts[dims*i] - pts[dims*( i-1 )];
630 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
631 double dl = sqrt( dx * dx + dy * dy );
635 double k = ( tl - l ) / dl;
637 point.p.set( pts[dims*( i-1 )] + k * dx,
638 pts[dims*( i-1 )+1] + k * dy );
639 point.angle = atan2( dy, dx ) * 180.0 * M_1_PI;
646 geom += nPoints *
sizeof( double ) * dims;
655 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
656 int nRings = *(
unsigned int * )geom;
657 geom +=
sizeof( int );
659 for (
int i = 0; i < nRings; ++i )
661 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
662 int nPoints = *(
unsigned int * )geom;
663 geom +=
sizeof( int );
665 Q_ASSERT( geom + nPoints*
sizeof(
double )*dims <= geomend );
669 double sx = 0.0, sy = 0.0;
670 double *pts = (
double* ) geom;
671 for (
int j = 0; j < nPoints - 1; j++ )
676 point.p.set( sx / ( nPoints - 1 ),
677 sy / ( nPoints - 1 ) );
681 geom += nPoints *
sizeof( double ) * dims;
696 bool QgsLabel::readLabelField( QDomElement &el,
int attr, QString prefix =
"field" )
698 QString name = prefix +
"name";
700 if ( el.hasAttribute( name ) )
702 name = el.attribute( name );
705 for ( ; idx < mFields.
count(); ++idx )
707 if ( mFields[idx].name() == name )
713 if ( idx != mFields.
count() )
715 mLabelFieldIdx[attr] = idx;
719 else if ( el.hasAttribute( prefix ) )
721 QString value = el.attribute( prefix );
722 mLabelFieldIdx[attr] = value.isEmpty() ? -1 : value.toInt();
726 mLabelFieldIdx[attr] = -1;
733 QgsDebugMsg(
" called for layer label properties, got node " + node.nodeName() );
735 QDomNode scratchNode;
738 int red, green, blue;
742 scratchNode = node.namedItem(
"label" );
744 if ( scratchNode.isNull() )
746 QgsDebugMsg(
"couldn't find QgsLabel ``label'' attribute" );
750 el = scratchNode.toElement();
751 mLabelAttributes->
setText( el.attribute(
"text",
"" ) );
752 readLabelField( el,
Text );
756 scratchNode = node.namedItem(
"family" );
758 if ( scratchNode.isNull() )
760 QgsDebugMsg(
"couldn't find QgsLabel ``family'' attribute" );
764 el = scratchNode.toElement();
765 mLabelAttributes->
setFamily( el.attribute(
"name",
"" ) );
766 readLabelField( el,
Family );
770 scratchNode = node.namedItem(
"size" );
772 if ( scratchNode.isNull() )
774 QgsDebugMsg(
"couldn't find QgsLabel ``size'' attribute" );
778 el = scratchNode.toElement();
779 if ( !el.hasAttribute(
"unitfield" ) && !el.hasAttribute(
"unitfieldname" ) )
782 mLabelAttributes->
setSize( el.attribute(
"value",
"0.0" ).toDouble(), type );
786 readLabelField( el,
SizeType,
"unitfield" );
788 readLabelField( el,
Size );
792 scratchNode = node.namedItem(
"bold" );
794 if ( scratchNode.isNull() )
796 QgsDebugMsg(
"couldn't find QgsLabel ``bold'' attribute" );
800 el = scratchNode.toElement();
801 mLabelAttributes->
setBold((
bool )el.attribute(
"on",
"0" ).toInt() );
802 readLabelField( el,
Bold );
806 scratchNode = node.namedItem(
"italic" );
808 if ( scratchNode.isNull() )
810 QgsDebugMsg(
"couldn't find QgsLabel ``italic'' attribute" );
814 el = scratchNode.toElement();
815 mLabelAttributes->
setItalic((
bool )el.attribute(
"on",
"0" ).toInt() );
816 readLabelField( el,
Italic );
820 scratchNode = node.namedItem(
"underline" );
822 if ( scratchNode.isNull() )
824 QgsDebugMsg(
"couldn't find QgsLabel ``underline'' attribute" );
828 el = scratchNode.toElement();
829 mLabelAttributes->
setUnderline((
bool )el.attribute(
"on",
"0" ).toInt() );
834 scratchNode = node.namedItem(
"strikeout" );
836 if ( scratchNode.isNull() )
838 QgsDebugMsg(
"couldn't find QgsLabel ``strikeout'' attribute" );
842 el = scratchNode.toElement();
843 mLabelAttributes->
setStrikeOut((
bool )el.attribute(
"on",
"0" ).toInt() );
848 scratchNode = node.namedItem(
"color" );
850 if ( scratchNode.isNull() )
852 QgsDebugMsg(
"couldn't find QgsLabel ``color'' attribute" );
856 el = scratchNode.toElement();
858 red = el.attribute(
"red",
"0" ).toInt();
859 green = el.attribute(
"green",
"0" ).toInt();
860 blue = el.attribute(
"blue",
"0" ).toInt();
862 mLabelAttributes->
setColor( QColor( red, green, blue ) );
864 readLabelField( el,
Color );
868 scratchNode = node.namedItem(
"x" );
870 if ( scratchNode.isNull() )
872 QgsDebugMsg(
"couldn't find QgsLabel ``x'' attribute" );
876 el = scratchNode.toElement();
881 scratchNode = node.namedItem(
"y" );
883 if ( scratchNode.isNull() )
885 QgsDebugMsg(
"couldn't find QgsLabel ``y'' attribute" );
889 el = scratchNode.toElement();
895 scratchNode = node.namedItem(
"offset" );
897 if ( scratchNode.isNull() )
899 QgsDebugMsg(
"couldn't find QgsLabel ``offset'' attribute" );
903 double xoffset, yoffset;
905 el = scratchNode.toElement();
908 xoffset = el.attribute(
"x",
"0.0" ).toDouble();
909 yoffset = el.attribute(
"y",
"0.0" ).toDouble();
911 mLabelAttributes->
setOffset( xoffset, yoffset, type );
912 readLabelField( el,
XOffset,
"xfield" );
913 readLabelField( el,
YOffset,
"yfield" );
917 scratchNode = node.namedItem(
"angle" );
919 if ( scratchNode.isNull() )
921 QgsDebugMsg(
"couldn't find QgsLabel ``angle'' attribute" );
925 el = scratchNode.toElement();
926 mLabelAttributes->
setAngle( el.attribute(
"value",
"0.0" ).toDouble() );
927 readLabelField( el,
Angle );
928 mLabelAttributes->
setAutoAngle( el.attribute(
"auto",
"0" ) ==
"1" );
932 scratchNode = node.namedItem(
"alignment" );
934 if ( scratchNode.isNull() )
936 QgsDebugMsg(
"couldn't find QgsLabel ``alignment'' attribute" );
940 el = scratchNode.toElement();
947 scratchNode = node.namedItem(
"buffercolor" );
949 if ( scratchNode.isNull() )
951 QgsDebugMsg(
"couldn't find QgsLabel ``buffercolor'' attribute" );
955 el = scratchNode.toElement();
957 red = el.attribute(
"red",
"0" ).toInt();
958 green = el.attribute(
"green",
"0" ).toInt();
959 blue = el.attribute(
"blue",
"0" ).toInt();
965 scratchNode = node.namedItem(
"buffersize" );
967 if ( scratchNode.isNull() )
969 QgsDebugMsg(
"couldn't find QgsLabel ``bffersize'' attribute" );
973 el = scratchNode.toElement();
976 mLabelAttributes->
setBufferSize( el.attribute(
"value",
"0.0" ).toDouble(), type );
980 scratchNode = node.namedItem(
"bufferenabled" );
982 if ( scratchNode.isNull() )
984 QgsDebugMsg(
"couldn't find QgsLabel ``bufferenabled'' attribute" );
988 el = scratchNode.toElement();
990 mLabelAttributes->
setBufferEnabled((
bool )el.attribute(
"on",
"0" ).toInt() );
994 scratchNode = node.namedItem(
"multilineenabled" );
996 if ( scratchNode.isNull() )
998 QgsDebugMsg(
"couldn't find QgsLabel ``multilineenabled'' attribute" );
1002 el = scratchNode.toElement();
1008 scratchNode = node.namedItem(
"selectedonly" );
1010 if ( scratchNode.isNull() )
1012 QgsDebugMsg(
"couldn't find QgsLabel ``selectedonly'' attribute" );
1016 el = scratchNode.toElement();
1017 mLabelAttributes->
setSelectedOnly((
bool )el.attribute(
"on",
"0" ).toInt() );
1026 QDomElement labelattributes = document.createElement(
"labelattributes" );
1029 QDomElement label = document.createElement(
"label" );
1030 label.setAttribute(
"text", mLabelAttributes->
text() );
1031 if ( mLabelAttributes->
textIsSet() && mLabelFieldIdx[
Text] != -1 )
1037 label.setAttribute(
"fieldname",
"" );
1039 labelattributes.appendChild( label );
1042 QDomElement family = document.createElement(
"family" );
1045 if ( mLabelFieldIdx[
Family] != -1 )
1047 family.setAttribute(
"name", mLabelAttributes->
family() );
1052 family.setAttribute(
"name", mLabelAttributes->
family() );
1053 family.setAttribute(
"fieldname",
"" );
1058 family.setAttribute(
"name",
"Arial" );
1059 family.setAttribute(
"fieldname",
"" );
1061 labelattributes.appendChild( family );
1064 QDomElement
size = document.createElement(
"size" );
1065 size.setAttribute(
"value", QString::number( mLabelAttributes->
size() ) );
1068 if ( mLabelFieldIdx[
Size] != -1 )
1070 if ( mLabelFieldIdx[
SizeType] != -1 )
1083 size.setAttribute(
"fieldname",
"" );
1088 size.setAttribute(
"value",
"12" );
1089 size.setAttribute(
"units",
"Points" );
1090 size.setAttribute(
"fieldname",
"" );
1092 labelattributes.appendChild( size );
1095 QDomElement bold = document.createElement(
"bold" );
1098 bold.setAttribute(
"on", mLabelAttributes->
bold() );
1099 if ( mLabelFieldIdx[
Bold] != -1 )
1105 bold.setAttribute(
"fieldname",
"" );
1110 bold.setAttribute(
"on", 0 );
1111 bold.setAttribute(
"fieldname", 0 );
1113 labelattributes.appendChild( bold );
1116 QDomElement italic = document.createElement(
"italic" );
1119 italic.setAttribute(
"on", mLabelAttributes->
italic() );
1120 if ( mLabelFieldIdx[
Italic] != -1 )
1126 italic.setAttribute(
"fieldname",
"" );
1131 italic.setAttribute(
"on",
"0" );
1132 italic.setAttribute(
"fieldname",
"" );
1134 labelattributes.appendChild( italic );
1137 QDomElement underline = document.createElement(
"underline" );
1140 underline.setAttribute(
"on", mLabelAttributes->
underline() );
1147 underline.setAttribute(
"fieldname",
"" );
1152 underline.setAttribute(
"on", 0 );
1153 underline.setAttribute(
"fieldname",
"" );
1155 labelattributes.appendChild( underline );
1158 QDomElement strikeOut = document.createElement(
"strikeout" );
1161 strikeOut.setAttribute(
"on", mLabelAttributes->
strikeOut() );
1168 strikeOut.setAttribute(
"fieldname",
"" );
1173 strikeOut.setAttribute(
"on", 0 );
1174 strikeOut.setAttribute(
"fieldname",
"" );
1176 labelattributes.appendChild( strikeOut );
1179 QDomElement color = document.createElement(
"color" );
1182 color.setAttribute(
"red", mLabelAttributes->
color().red() );
1183 color.setAttribute(
"green", mLabelAttributes->
color().green() );
1184 color.setAttribute(
"blue", mLabelAttributes->
color().blue() );
1185 if ( mLabelFieldIdx[
Color] != -1 )
1191 color.setAttribute(
"fieldname",
"" );
1196 color.setAttribute(
"red", 0 );
1197 color.setAttribute(
"green", 0 );
1198 color.setAttribute(
"blue", 0 );
1199 color.setAttribute(
"fieldname",
"" );
1201 labelattributes.appendChild( color );
1204 QDomElement x = document.createElement(
"x" );
1211 x.setAttribute(
"fieldname",
"" );
1213 labelattributes.appendChild( x );
1216 QDomElement y = document.createElement(
"y" );
1223 y.setAttribute(
"fieldname",
"" );
1225 labelattributes.appendChild( y );
1230 QDomElement offset = document.createElement(
"offset" );
1232 offset.setAttribute(
"x", QString::number( mLabelAttributes->
xOffset() ) );
1234 offset.setAttribute(
"y", QString::number( mLabelAttributes->
yOffset() ) );
1236 labelattributes.appendChild( offset );
1240 QDomElement
angle = document.createElement(
"angle" );
1243 angle.setAttribute(
"value", QString::number( mLabelAttributes->
angle() ) );
1244 if ( mLabelFieldIdx[
Angle] != -1 )
1250 angle.setAttribute(
"fieldname",
"" );
1255 angle.setAttribute(
"value",
"" );
1256 angle.setAttribute(
"fieldname",
"" );
1258 angle.setAttribute(
"auto", mLabelAttributes->
angleIsAuto() ?
"1" :
"0" );
1259 labelattributes.appendChild( angle );
1264 QDomElement alignment = document.createElement(
"alignment" );
1267 labelattributes.appendChild( alignment );
1271 QDomElement buffercolor = document.createElement(
"buffercolor" );
1274 buffercolor.setAttribute(
"red", mLabelAttributes->
bufferColor().red() );
1275 buffercolor.setAttribute(
"green", mLabelAttributes->
bufferColor().green() );
1276 buffercolor.setAttribute(
"blue", mLabelAttributes->
bufferColor().blue() );
1283 buffercolor.setAttribute(
"fieldname",
"" );
1288 buffercolor.setAttribute(
"red",
"" );
1289 buffercolor.setAttribute(
"green",
"" );
1290 buffercolor.setAttribute(
"blue",
"" );
1291 buffercolor.setAttribute(
"fieldname",
"" );
1293 labelattributes.appendChild( buffercolor );
1296 QDomElement buffersize = document.createElement(
"buffersize" );
1299 buffersize.setAttribute(
"value", QString::number( mLabelAttributes->
bufferSize() ) );
1307 buffersize.setAttribute(
"fieldname",
"" );
1312 buffersize.setAttribute(
"value",
"" );
1313 buffersize.setAttribute(
"units",
"" );
1314 buffersize.setAttribute(
"fieldname",
"" );
1316 labelattributes.appendChild( buffersize );
1319 QDomElement bufferenabled = document.createElement(
"bufferenabled" );
1322 bufferenabled.setAttribute(
"on", mLabelAttributes->
bufferEnabled() );
1329 bufferenabled.setAttribute(
"fieldname",
"" );
1334 bufferenabled.setAttribute(
"on",
"" );
1335 bufferenabled.setAttribute(
"fieldname",
"" );
1337 labelattributes.appendChild( bufferenabled );
1340 QDomElement multilineenabled = document.createElement(
"multilineenabled" );
1343 multilineenabled.setAttribute(
"on", mLabelAttributes->
multilineEnabled() );
1350 multilineenabled.setAttribute(
"fieldname",
"" );
1355 multilineenabled.setAttribute(
"on",
"" );
1356 multilineenabled.setAttribute(
"fieldname",
"" );
1358 labelattributes.appendChild( multilineenabled );
1360 QDomElement selectedonly = document.createElement(
"selectedonly" );
1363 selectedonly.setAttribute(
"on", mLabelAttributes->
selectedOnly() );
1367 selectedonly.setAttribute(
"on",
"" );
1369 labelattributes.appendChild( selectedonly );
1371 layer_node.appendChild( labelattributes );
1376 mScaleBasedVisibility = theVisibilityFlag;
1381 return mScaleBasedVisibility;
1386 mMinScale = theMinScale;
1396 mMaxScale = theMaxScale;