32 #include <QApplication>
35 #include <QFontMetrics>
60 #include <QMessageBox>
82 : upsidedownLabels( Upright )
87 , mFeaturesToLabel( 0 )
88 , mFeatsSendingToPal( 0 )
102 blendMode = QPainter::CompositionMode_SourceOver;
329 , mFeaturesToLabel( 0 )
330 , mFeatsSendingToPal( 0 )
332 , showingShadowRects( false )
478 mDataDefinedNames = s.mDataDefinedNames;
510 if ( expression == NULL )
523 return QColor( r, g, b, a );
537 if ( str.
compare(
"Point", Qt::CaseInsensitive ) == 0
539 if ( str.
compare(
"MapUnit", Qt::CaseInsensitive ) == 0
547 if ( str.
compare(
"Miter", Qt::CaseInsensitive ) == 0 )
return Qt::MiterJoin;
548 if ( str.
compare(
"Round", Qt::CaseInsensitive ) == 0 )
return Qt::RoundJoin;
549 return Qt::BevelJoin;
555 if ( !layer && !parentElem )
561 while ( i.hasNext() )
567 readDataDefinedProperty( layer, i.key(), propertyMap );
569 else if ( parentElem )
577 propertyMap.
insert( i.key(), dd );
588 if ( !layer && !parentElem )
594 while ( i.hasNext() )
597 QString newPropertyName =
"labeling/dataDefined/" + i.value().first;
611 bool defaultVals = ( !active && !useExpr && expr.
isEmpty() && field.
isEmpty() );
617 values << ( active ?
"1" :
"0" );
618 values << ( useExpr ?
"1" :
"0" );
660 void QgsPalLayerSettings::readDataDefinedProperty(
QgsVectorLayer* layer,
664 QString newPropertyName =
"labeling/dataDefined/" + mDataDefinedNames.
value( p ).first;
668 if ( newPropertyField.
isValid() )
670 ddString = newPropertyField.
toString();
674 int oldIndx = mDataDefinedNames.
value( p ).second;
684 if ( !oldPropertyField.
isValid() )
691 int indx = oldPropertyField.
toInt( &conversionOk );
701 if ( !oldIndicesToNames.
isEmpty() )
703 ddString = oldIndicesToNames.
value( indx );
708 if ( indx < fields.
size() )
710 ddString = fields.
at( indx ).
name();
728 if ( oldIndx == 16 || oldIndx == 17 )
746 propertyMap.
insert( p, dd );
787 fontFamily = appFont.
family();
796 textFont =
QFont( fontFamily, fontSize, fontWeight, fontItalic );
835 else if ( bufSize != 0.0 )
947 else if ( scalemn > 0 || scalemx > 0 )
1154 fontFamily = appFont.
family();
1161 int fontWeight = textStyleElem.
attribute(
"fontWeight" ).
toInt();
1162 bool fontItalic = textStyleElem.
attribute(
"fontItalic" ).
toInt();
1163 textFont =
QFont( fontFamily, fontSize, fontWeight, fontItalic );
1181 wrapChar = textFormatElem.attribute(
"wrapChar" );
1182 multilineHeight = textFormatElem.attribute(
"multilineHeight",
"1" ).toDouble();
1189 formatNumbers = textFormatElem.attribute(
"formatNumbers" ).toInt();
1190 decimals = textFormatElem.attribute(
"decimals" ).toInt();
1191 plusSign = textFormatElem.attribute(
"plussign" ).toInt();
1204 else if ( bufSize != 0.0 )
1261 shadowDraw = shadowElem.attribute(
"shadowDraw",
"0" ).toInt();
1264 shadowOffsetDist = shadowElem.attribute(
"shadowOffsetDist",
"1" ).toDouble();
1269 shadowRadius = shadowElem.attribute(
"shadowRadius",
"1.5" ).toDouble();
1275 shadowScale = shadowElem.attribute(
"shadowScale",
"100" ).toInt();
1283 placementFlags = placementElem.attribute(
"placementFlags" ).toUInt();
1284 centroidWhole = placementElem.attribute(
"centroidWhole",
"0" ).toInt();
1285 centroidInside = placementElem.attribute(
"centroidInside",
"0" ).toInt();
1286 fitInPolygonOnly = placementElem.attribute(
"fitInPolygonOnly",
"0" ).toInt();
1287 dist = placementElem.attribute(
"dist" ).toDouble();
1288 distInMapUnits = placementElem.attribute(
"distInMapUnits" ).toInt();
1292 xOffset = placementElem.attribute(
"xOffset",
"0" ).toDouble();
1293 yOffset = placementElem.attribute(
"yOffset",
"0" ).toDouble();
1297 angleOffset = placementElem.attribute(
"angleOffset",
"0" ).toDouble();
1298 preserveRotation = placementElem.attribute(
"preserveRotation",
"1" ).toInt();
1301 priority = placementElem.attribute(
"priority" ).toInt();
1302 repeatDistance = placementElem.attribute(
"repeatDistance",
"0" ).toDouble();
1503 bool active,
bool useExpr,
const QString& expr,
const QString& field )
1505 bool defaultVals = ( !active && !useExpr && expr.
isEmpty() && field.
isEmpty() );
1519 else if ( !defaultVals )
1531 delete( it.
value() );
1541 delete( it.
value() );
1558 newValue = values.
join(
"~~" );
1583 return it.
value()->toMap();
1600 scopedEc->setFeature( f );
1601 scopedEc->setFields( fields );
1643 else if ( !useExpression && !field.
isEmpty() )
1691 bool isActive =
false;
1696 isActive = it.
value()->isActive();
1707 bool useExpression =
false;
1711 useExpression = it.
value()->useExpression();
1714 return useExpression;
1735 scopedRc->expressionContext().setFeature( *f );
1798 double size = exprVal.
toDouble( &ok );
1810 addDirSymb = exprVal.
toBool();
1835 int enmint = exprVal.
toInt( &ok );
1856 if ( fm->
width( rightDirSymb ) > fm->
width( dirSym ) )
1857 dirSym = rightDirSymb;
1869 double w = 0.0, h = 0.0;
1871 int lines = multiLineSplit.
size();
1875 h += fm->
height() + ( double )(( lines - 1 ) * labelHeight * multilineH );
1878 for (
int i = 0; i < lines; ++i )
1880 double width = fm->
width( multiLineSplit.
at( i ) );
1890 labelX = qAbs( ptSize.
x() -
ptZero.
x() );
1891 labelY = qAbs( ptSize.
y() -
ptZero.
y() );
1903 Q_ASSERT( labelFeature );
1905 Q_UNUSED( dxfLayer );
1911 registerObstacleFeature( f, context,
QString(), labelFeature );
1921 dataDefinedValues.
clear();
1927 showLabel &= exprVal.
toBool();
1940 useScaleVisibility = exprVal.
toBool();
1943 if ( useScaleVisibility )
1951 double mins = exprVal.
toDouble( &conversionOk );
1961 minScale = 1 / qAbs( minScale );
1975 double maxs = exprVal.
toDouble( &conversionOk );
1985 maxScale = 1 / qAbs( maxScale );
2015 double size = exprVal.
toDouble( &ok );
2021 if ( fontSize <= 0.0 )
2028 if ( fontPixelSize < 1 )
2043 useFontLimitPixelSize = exprVal.
toBool();
2046 if ( useFontLimitPixelSize )
2052 int sizeInt = exprVal.
toInt( &ok );
2056 fontMinPixel = sizeInt;
2064 int sizeInt = exprVal.
toInt( &ok );
2068 fontMaxPixel = sizeInt;
2084 parseTextStyle( labelFont, fontunits, context );
2085 parseTextFormatting( context );
2086 parseTextBuffer( context );
2087 parseShapeBackground( context );
2088 parseDropShadow( context );
2121 formatnum = exprVal.
toBool();
2133 int dInt = exprVal.
toInt( &ok );
2135 if ( ok && dInt > 0 )
2137 decimalPlaces = dInt;
2145 signPlus = exprVal.
toBool();
2155 if ( d > 0 && signPlus )
2157 numberFormat.
append(
"+" );
2159 numberFormat.
append(
"%1" );
2160 labelText = numberFormat.
arg( d, 0,
'f', decimalPlaces );
2167 double labelX, labelY;
2173 double maxcharanglein = 20.0;
2174 double maxcharangleout = -20.0;
2190 maxcharanglein = qBound( 20.0, (
double )maxcharanglePt.
x(), 60.0 );
2191 maxcharangleout = qBound( 20.0, (
double )maxcharanglePt.
y(), 95.0 );
2195 maxcharangleout = -( qAbs( maxcharangleout ) );
2207 if ( str.
compare(
"Visible", Qt::CaseInsensitive ) == 0 )
2209 wholeCentroid =
false;
2211 else if ( str.
compare(
"Whole", Qt::CaseInsensitive ) == 0 )
2213 wholeCentroid =
true;
2231 bool doClip =
false;
2232 if ( !centroidPoly || !wholeCentroid )
2237 const GEOSGeometry* geos_geom = 0;
2244 if ( !scopedPreparedGeom.
data() )
2246 preparedGeom = scopedPreparedGeom.
data();
2247 geos_geom = scopedPreparedGeom.
data()->asGeos();
2251 geos_geom = geom->
asGeos();
2257 if ( geos_geom == NULL )
2285 GEOSGeometry* geos_geom_clone;
2296 bool dataDefinedPosition =
false;
2297 bool layerDefinedRotation =
false;
2298 bool dataDefinedRotation =
false;
2299 double xPos = 0.0, yPos = 0.0,
angle = 0.0;
2300 bool ddXPos =
false, ddYPos =
false;
2301 double quadOffsetX = 0.0, quadOffsetY = 0.0;
2302 double offsetX = 0.0, offsetY = 0.0;
2305 bool ddFixedQuad =
false;
2310 int quadInt = exprVal.
toInt( &ok );
2312 if ( ok && 0 <= quadInt && quadInt <= 8 )
2393 if ( !offinmapunits )
2395 offsetX *= mapUntsPerMM;
2401 if ( !offinmapunits )
2403 offsetY *= mapUntsPerMM;
2411 layerDefinedRotation =
true;
2420 double rotD = exprVal.
toDouble( &ok );
2424 dataDefinedRotation =
true;
2435 xPos = exprVal.
toDouble( &ddXPos );
2442 yPos = exprVal.
toDouble( &ddYPos );
2445 if ( ddXPos && ddYPos )
2447 dataDefinedPosition =
true;
2449 if ( layerDefinedRotation && !dataDefinedRotation )
2463 if ( haliString.
compare(
"Center", Qt::CaseInsensitive ) == 0 )
2465 xdiff -= labelX / 2.0;
2467 else if ( haliString.
compare(
"Right", Qt::CaseInsensitive ) == 0 )
2479 if ( valiString.
compare(
"Bottom", Qt::CaseInsensitive ) != 0 )
2481 if ( valiString.
compare(
"Top", Qt::CaseInsensitive ) == 0 )
2487 double descentRatio = labelFontMetrics->descent() / labelFontMetrics->height();
2488 if ( valiString.
compare(
"Base", Qt::CaseInsensitive ) == 0 )
2490 ydiff -= labelY * descentRatio;
2494 double capHeightRatio = ( labelFontMetrics->boundingRect(
'H' ).height() + 1 + labelFontMetrics->descent() ) / labelFontMetrics->height();
2495 ydiff -= labelY * capHeightRatio;
2496 if ( valiString.
compare(
"Half", Qt::CaseInsensitive ) == 0 )
2498 ydiff += labelY * ( capHeightRatio - descentRatio ) / 2.0;
2505 if ( dataDefinedRotation )
2508 double xd = xdiff * cos(
angle ) - ydiff * sin(
angle );
2509 double yd = xdiff * sin(
angle ) + ydiff * cos(
angle );
2525 QgsDebugMsgLevel(
QString(
"Ignoring feature %1 due transformation exception on data-defined position" ).arg( f.
id() ), 4 );
2538 qreal xPos_qreal = xPos, yPos_qreal = yPos;
2539 t.
map( xPos_qreal, yPos_qreal, &xPosR, &yPosR );
2540 xPos = xPosR; yPos = yPosR;
2559 bool alwaysShow =
false;
2562 alwaysShow = exprVal.
toBool();
2571 double distD = exprVal.
toDouble( &ok );
2592 if ( !repeatdistinmapunit )
2594 repeatDist *= mapUntsPerMM;
2604 ( *labelFeature )->setFixedPosition(
QgsPoint( xPos, yPos ) );
2606 ( *labelFeature )->setHasFixedAngle( dataDefinedRotation || ( !dataDefinedPosition &&
angle != 0 ) );
2607 ( *labelFeature )->setFixedAngle(
angle );
2608 ( *labelFeature )->setQuadOffset(
QPointF( quadOffsetX, quadOffsetY ) );
2609 ( *labelFeature )->setPositionOffset(
QgsPoint( offsetX, offsetY ) );
2610 ( *labelFeature )->setAlwaysShow( alwaysShow );
2611 ( *labelFeature )->setRepeatDistance( repeatDist );
2612 ( *labelFeature )->setLabelText( labelText );
2626 double distance =
dist;
2630 double distD = exprVal.
toDouble( &ok );
2649 if ( distance != 0 )
2651 if ( distinmapunit )
2660 ( *labelFeature )->setDistLabel( d );
2665 ( *labelFeature )->setHasFixedQuadrant(
true );
2672 double priorityD = exprVal.
toDouble( &ok );
2675 priorityD = qBound( 0.0, priorityD, 10.0 );
2676 priorityD = 1 - priorityD / 10.0;
2677 ( *labelFeature )->setPriority( priorityD );
2685 isObstacle = exprVal.
toBool();
2688 ( *labelFeature )->setIsObstacle( isObstacle );
2694 double factorD = exprVal.
toDouble( &ok );
2697 factorD = qBound( 0.0, factorD, 10.0 );
2698 factorD = factorD / 5.0 + 0.0001;
2699 featObstacleFactor = factorD;
2702 ( *labelFeature )->setObstacleFactor( featObstacleFactor );
2711 Q_UNUSED( dxfLayer );
2721 const GEOSGeometry* geos_geom = 0;
2727 if ( !scopedPreparedGeom.
data() )
2729 geos_geom = scopedPreparedGeom.
data()->asGeos();
2733 geos_geom = geom->
asGeos();
2736 if ( geos_geom == NULL )
2739 GEOSGeometry* geos_geom_clone;
2748 bool QgsPalLayerSettings::dataDefinedValEval( DataDefinedValueType valType,
2760 bool bol = exprVal.
toBool();
2768 int size = exprVal.
toInt( &ok );
2781 int size = exprVal.
toInt( &ok );
2784 if ( ok && size > 0 )
2794 double size = exprVal.
toDouble( &ok );
2807 double size = exprVal.
toDouble( &ok );
2810 if ( ok && size > 0.0 )
2820 double rot = exprVal.
toDouble( &ok );
2824 if ( rot < -180.0 && rot >= -360 )
2828 if ( rot > 180.0 && rot <= 360 )
2832 if ( rot >= -180 && rot <= 180 )
2840 case DDTransparency:
2843 int size = exprVal.
toInt( &ok );
2845 if ( ok && size >= 0 && size <= 100 )
2878 if ( color.isValid() )
2926 void QgsPalLayerSettings::parseTextStyle(
QFont& labelFont,
2945 if ( labelFont.
family() != family )
2951 ddFontFamily = family;
2962 ddFontStyle = fontstyle;
2966 bool ddBold =
false;
2969 bool bold = exprVal.
toBool();
2975 bool ddItalic =
false;
2978 bool italic = exprVal.
toBool();
2987 bool newFontBuilt =
false;
2988 if ( ddBold || ddItalic )
2991 newFont =
QFont( !ddFontFamily.isEmpty() ? ddFontFamily : labelFont.
family() );
2992 newFontBuilt =
true;
2996 else if ( !ddFontStyle.isEmpty()
2997 && ddFontStyle.compare(
"Ignore", Qt::CaseInsensitive ) != 0 )
2999 if ( !ddFontFamily.isEmpty() )
3003 if ( appFont != styledfont )
3005 newFont = styledfont;
3006 newFontBuilt =
true;
3013 else if ( !ddFontFamily.isEmpty() )
3015 if ( ddFontStyle.compare(
"Ignore", Qt::CaseInsensitive ) != 0 )
3019 if ( appFont != styledfont )
3021 newFont = styledfont;
3022 newFontBuilt =
true;
3027 newFont =
QFont( ddFontFamily );
3028 newFontBuilt =
true;
3043 labelFont = newFont;
3051 double wspacing = exprVal.
toDouble( &ok );
3055 wordspace = wspacing;
3065 double lspacing = exprVal.
toDouble( &ok );
3069 letterspace = lspacing;
3083 if ( fcase.
compare(
"NoChange", Qt::CaseInsensitive ) == 0 )
3085 fontcaps = QFont::MixedCase;
3087 else if ( fcase.
compare(
"Upper", Qt::CaseInsensitive ) == 0 )
3089 fontcaps = QFont::AllUppercase;
3091 else if ( fcase.
compare(
"Lower", Qt::CaseInsensitive ) == 0 )
3093 fontcaps = QFont::AllLowercase;
3095 else if ( fcase.
compare(
"Capitalize", Qt::CaseInsensitive ) == 0 )
3097 fontcaps = QFont::Capitalize;
3110 bool strikeout = exprVal.
toBool();
3118 bool underline = exprVal.
toBool();
3144 drawBuffer = exprVal.
toBool();
3163 bufTransp = exprVal.
toInt();
3166 drawBuffer = ( drawBuffer && bufrSize > 0.0 && bufTransp < 100 );
3214 if ( str.
compare(
"Center", Qt::CaseInsensitive ) == 0 )
3218 else if ( str.
compare(
"Right", Qt::CaseInsensitive ) == 0 )
3222 else if ( str.
compare(
"Follow", Qt::CaseInsensitive ) == 0 )
3234 drawDirSymb = exprVal.
toBool();
3256 if ( str.
compare(
"Above", Qt::CaseInsensitive ) == 0 )
3260 else if ( str.
compare(
"Below", Qt::CaseInsensitive ) == 0 )
3275 void QgsPalLayerSettings::parseShapeBackground(
QgsRenderContext &context )
3283 drawShape = exprVal.
toBool();
3295 shapeTransp = exprVal.
toInt();
3298 drawShape = ( drawShape && shapeTransp < 100 );
3319 if ( skind.
compare(
"Square", Qt::CaseInsensitive ) == 0 )
3323 else if ( skind.
compare(
"Ellipse", Qt::CaseInsensitive ) == 0 )
3327 else if ( skind.
compare(
"Circle", Qt::CaseInsensitive ) == 0 )
3331 else if ( skind.
compare(
"SVG", Qt::CaseInsensitive ) == 0 )
3335 shapeKind = shpkind;
3364 if ( stype.
compare(
"Fixed", Qt::CaseInsensitive ) == 0 )
3368 shpSizeType = sizType;
3393 && ddShpSizeX == 0.0 ) ) )
3399 && ( ddShpSizeX == 0.0 || ddShpSizeY == 0.0 ) )
3429 if ( rotstr.
compare(
"Offset", Qt::CaseInsensitive ) == 0 )
3433 else if ( rotstr.
compare(
"Fixed", Qt::CaseInsensitive ) == 0 )
3484 drawShadow = exprVal.
toBool();
3496 shadowTransp = exprVal.
toInt();
3503 shadowOffDist = exprVal.
toDouble();
3513 drawShadow = ( drawShadow && shadowTransp < 100 && !( shadowOffDist == 0.0 && shadowRad == 0.0 ) );
3535 if ( str.
compare(
"Text", Qt::CaseInsensitive ) == 0 )
3539 else if ( str.
compare(
"Buffer", Qt::CaseInsensitive ) == 0 )
3543 else if ( str.
compare(
"Background", Qt::CaseInsensitive ) == 0 )
3583 if ( unit ==
MapUnits && mapUnitsPerPixel > 0.0 )
3589 double ptsTomm = ( unit ==
Points ? 0.352778 : 1 );
3625 bool enabled =
false;
3641 Q_UNUSED( layerID );
3664 if ( !lp->
prepare( ctx, attrNames ) )
3680 if ( !dp->
prepare( ctx, attrNames ) )
3691 QgsDebugMsg(
"Called addDiagramLayer()... need to use prepareDiagramLayer() instead!" );
3699 Q_UNUSED( dxfLayer );
3701 provider->registerFeature( f, context );
3725 if ( clipGeometry && !clipGeometry->
contains( geometry ) )
3737 Q_FOREACH (
const QString& line, text.
split( wrapCharacter ) )
3744 multiLineSplit = text.
split(
"\n" );
3747 return multiLineSplit;
3754 int currentBoundary = -1;
3755 int previousBoundary = 0;
3756 while (( currentBoundary = boundaryFinder.
toNextBoundary() ) > 0 )
3758 graphemes << text.
mid( previousBoundary, currentBoundary - previousBoundary );
3759 previousBoundary = currentBoundary;
3829 clonedGeometry.
reset( geom );
3832 if ( clipGeometry && !clipGeometry->
contains( geom ) )
3840 clonedGeometry.
reset( geom );
3843 return clonedGeometry.
take();
3867 double length = geom->
length();
3868 if ( length >= 0.0 )
3870 return ( length >= ( minSize * mapUnitsPerMM ) );
3875 double area = geom->
area();
3878 return ( sqrt( area ) >= ( minSize * mapUnitsPerMM ) );
3887 provider->registerFeature( feat, context );
3910 Q_UNUSED( layerName );