19 #include "qgsdxfexport.h"
20 #include "qgsdxfpaintdevice.h"
27 #include <QSvgRenderer>
30 #include <QDomDocument>
31 #include <QDomElement>
38 : mOutlineStyle( Qt::SolidLine ), mOutlineWidth( 0 ), mOutlineWidthUnit(
QgsSymbolV2::MM )
62 if ( props.contains(
"name" ) )
64 if ( props.contains(
"color" ) )
66 if ( props.contains(
"color_border" ) )
68 if ( props.contains(
"size" ) )
69 size = props[
"size"].toDouble();
70 if ( props.contains(
"angle" ) )
71 angle = props[
"angle"].toDouble();
72 if ( props.contains(
"scale_method" ) )
76 if ( props.contains(
"offset" ) )
78 if ( props.contains(
"offset_unit" ) )
80 if ( props.contains(
"size_unit" ) )
83 if ( props.contains(
"outline_style" ) )
87 if ( props.contains(
"outline_width" ) )
91 if ( props.contains(
"outline_width_unit" ) )
96 if ( props.contains(
"horizontal_anchor_point" ) )
100 if ( props.contains(
"vertical_anchor_point" ) )
106 if ( props.contains(
"name_expression" ) )
110 if ( props.contains(
"color_expression" ) )
114 if ( props.contains(
"color_border_expression" ) )
118 if ( props.contains(
"outline_width_expression" ) )
122 if ( props.contains(
"size_expression" ) )
126 if ( props.contains(
"angle_expression" ) )
130 if ( props.contains(
"offset_expression" ) )
134 if ( props.contains(
"horizontal_anchor_point_expression" ) )
138 if ( props.contains(
"vertical_anchor_point_expression" ) )
148 return "SimpleMarker";
153 QColor brushColor =
mColor;
156 brushColor.setAlphaF(
mColor.alphaF() * context.
alpha() );
159 mBrush = QBrush( brushColor );
160 mPen = QPen( penColor );
166 if ( context.
alpha() < 1 )
168 selBrushColor.setAlphaF( context.
alpha() );
169 selPenColor.setAlphaF( context.
alpha() );
195 if (
mName !=
"circle" )
196 mSelPen.setColor( selBrushColor );
208 if ( !hasDataDefinedSize )
213 double half = scaledSize / 2.0;
214 transform.scale( half, half );
218 if ( !hasDataDefinedRotation &&
mAngle != 0 )
220 transform.rotate(
mAngle );
254 double pw = ((
mPen.widthF() == 0 ? 1 :
mPen.widthF() ) + 1 ) / 2 * 2;
255 int imageSize = (( int ) scaledSize + pw ) / 2 * 2 + 1;
256 double center = imageSize / 2.0;
263 mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
268 p.setRenderHint( QPainter::Antialiasing );
271 p.translate( QPointF( center, center ) );
279 mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
283 p.setRenderHint( QPainter::Antialiasing );
286 p.translate( QPointF( center, center ) );
297 p.setRenderHint( QPainter::Antialiasing );
298 p.fillRect( 0, 0, imageSize, imageSize, selColor );
301 p.translate( QPointF( center, center ) );
323 if ( name ==
"square" || name ==
"rectangle" )
325 mPolygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 1, 1 ) ) );
328 else if ( name ==
"diamond" )
330 mPolygon << QPointF( -1, 0 ) << QPointF( 0, 1 )
331 << QPointF( 1, 0 ) << QPointF( 0, -1 );
334 else if ( name ==
"pentagon" )
343 else if ( name ==
"triangle" )
345 mPolygon << QPointF( -1, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 );
348 else if ( name ==
"equilateral_triangle" )
355 else if ( name ==
"star" )
357 double sixth = 1.0 / 3;
360 << QPointF( -sixth, -sixth )
361 << QPointF( -1, -sixth )
362 << QPointF( -sixth, 0 )
364 << QPointF( 0, + sixth )
366 << QPointF( + sixth, 0 )
367 << QPointF( 1, -sixth )
368 << QPointF( + sixth, -sixth );
371 else if ( name ==
"regular_star" )
377 << QPointF( inner_r * sin(
DEG2RAD( 252.0 ) ), - inner_r * cos(
DEG2RAD( 252.0 ) ) )
379 << QPointF( 0, inner_r )
381 << QPointF( inner_r * sin(
DEG2RAD( 108.0 ) ), - inner_r * cos(
DEG2RAD( 108.0 ) ) )
383 << QPointF( inner_r * sin(
DEG2RAD( 36.0 ) ), - inner_r * cos(
DEG2RAD( 36.0 ) ) )
387 else if ( name ==
"arrow" )
391 << QPointF( 0.5, -0.5 )
392 << QPointF( 0.25, -0.25 )
393 << QPointF( 0.25, 1 )
394 << QPointF( -0.25, 1 )
395 << QPointF( -0.25, -0.5 )
396 << QPointF( -0.5, -0.5 );
399 else if ( name ==
"filled_arrowhead" )
401 mPolygon << QPointF( 0, 0 ) << QPointF( -1, 1 ) << QPointF( -1, -1 );
410 mPath = QPainterPath();
416 if ( name ==
"circle" )
418 mPath.addEllipse( QRectF( -1, -1, 2, 2 ) );
421 else if ( name ==
"cross" )
423 mPath.moveTo( -1, 0 );
424 mPath.lineTo( 1, 0 );
425 mPath.moveTo( 0, -1 );
426 mPath.lineTo( 0, 1 );
429 else if ( name ==
"x" || name ==
"cross2" )
431 mPath.moveTo( -1, -1 );
432 mPath.lineTo( 1, 1 );
433 mPath.moveTo( 1, -1 );
434 mPath.lineTo( -1, 1 );
437 else if ( name ==
"line" )
439 mPath.moveTo( 0, -1 );
440 mPath.lineTo( 0, 1 );
443 else if ( name ==
"arrowhead" )
445 mPath.moveTo( 0, 0 );
446 mPath.lineTo( -1, -1 );
447 mPath.moveTo( 0, 0 );
448 mPath.lineTo( -1, 1 );
467 QPointF off( offsetX, offsetY );
493 p->drawImage( QRectF( point.x() - s / 2.0 + off.x(),
494 point.y() - s / 2.0 + off.y(),
502 transform.translate( point.x() + off.x(), point.y() + off.y() );
508 if ( hasDataDefinedSize )
510 double scaledSize =
mSize;
511 if ( sizeExpression )
513 scaledSize = sizeExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
519 scaledSize = sqrt( scaledSize );
527 double half = scaledSize / 2.0;
528 transform.scale( half, half );
532 if ( angle != 0 && hasDataDefinedRotation )
533 transform.rotate( angle );
538 if ( colorExpression )
542 if ( colorBorderExpression )
547 if ( outlineWidthExpression )
558 p->drawPolygon( transform.map(
mPolygon ) );
560 p->drawPath( transform.map(
mPath ) );
571 map[
"size"] = QString::number(
mSize );
573 map[
"angle"] = QString::number(
mAngle );
606 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
607 element.appendChild( graphicElem );
614 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
617 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mAngle );
619 else if ( angle +
mAngle != 0 )
621 angleFunc = QString::number( angle +
mAngle );
631 Q_UNUSED( mmScaleFactor );
632 Q_UNUSED( mapUnitScaleFactor );
634 QString ogrType =
"3";
635 if (
mName ==
"square" )
639 else if (
mName ==
"triangle" )
643 else if (
mName ==
"star" )
647 else if (
mName ==
"circle" )
651 else if (
mName ==
"cross" )
659 else if (
mName ==
"line" )
665 ogrString.append(
"SYMBOL(" );
666 ogrString.append(
"id:" );
667 ogrString.append(
"\"" );
668 ogrString.append(
"ogr-sym-" );
669 ogrString.append( ogrType );
670 ogrString.append(
"\"" );
671 ogrString.append(
",c:" );
672 ogrString.append(
mColor.name() );
673 ogrString.append(
",o:" );
675 ogrString.append( QString(
",s:%1mm" ).arg(
mSize ) );
676 ogrString.append(
")" );
681 ogrString.append(
"PEN(" );
682 ogrString.append(
"c:" );
683 ogrString.append(
mColor.name() );
684 ogrString.append(
",w:" );
685 ogrString.append( QString::number(
mSize ) );
686 ogrString.append(
"mm" );
687 ogrString.append(
")" );
695 QDomElement graphicElem = element.firstChildElement(
"Graphic" );
696 if ( graphicElem.isNull() )
699 QString
name =
"square";
701 double borderWidth,
size;
702 Qt::PenStyle borderStyle;
712 double d = angleFunc.toDouble( &ok );
737 p->drawPath(
mPath );
747 bool hasDataDefinedSize =
false;
754 if ( hasDataDefinedSize )
756 if ( sizeExpression )
758 size = sizeExpression->
evaluate( const_cast<QgsFeature*>( context->
feature() ) ).toDouble();
774 size *= mmMapUnitScaleFactor;
776 double halfSize = size / 2.0;
781 if ( outlineWidthExpression )
783 outlineWidth = outlineWidthExpression->
evaluate( const_cast<QgsFeature*>( context->
feature() ) ).toDouble();
787 outlineWidth *= mmMapUnitScaleFactor;
791 QColor c =
mPen.color();
792 if (
mPen.style() == Qt::NoPen )
797 if ( colorExpression )
801 int colorIndex = QgsDxfExport::closestColorMatch( c.rgb() );
807 QPointF off( offsetX, offsetY );
812 if ( angleExpression )
814 angle = angleExpression->
evaluate( const_cast<QgsFeature*>( context->
feature() ) ).toDouble();
822 off *= mmMapUnitScaleFactor;
826 t.translate( shift.x() + offsetX, shift.y() + offsetY );
833 if (
mName ==
"circle" )
835 e.writeGroup( 0,
"CIRCLE" );
836 e.writeGroup( 8, layerName );
838 e.writeGroup( 62, colorIndex );
839 e.writeGroup( 10, shift.x() );
840 e.writeGroup( 20, shift.y() );
841 e.writeGroup( 30, 0.0 );
842 e.writeGroup( 40, halfSize );
844 else if (
mName ==
"square" ||
mName ==
"rectangle" )
846 QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
847 QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) );
848 QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) );
849 QPointF pt4 = t.map( QPointF( halfSize, halfSize ) );
850 e.writeSolid( layerName, colorIndex,
QgsPoint( pt1.x(), pt1.y() ),
QgsPoint( pt2.x(), pt2.y() ),
QgsPoint( pt3.x(), pt3.y() ),
QgsPoint( pt4.x(), pt4.y() ) );
852 else if (
mName ==
"diamond" )
854 QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
855 QPointF pt2 = t.map( QPointF( 0, -halfSize ) );
856 QPointF pt3 = t.map( QPointF( 0, halfSize ) );
857 QPointF pt4 = t.map( QPointF( halfSize, 0 ) );
858 e.writeSolid( layerName, colorIndex,
QgsPoint( pt1.x(), pt1.y() ),
QgsPoint( pt2.x(), pt2.y() ),
QgsPoint( pt3.x(), pt3.y() ),
QgsPoint( pt4.x(), pt4.y() ) );
860 else if (
mName ==
"triangle" )
862 QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
863 QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) );
864 QPointF pt3 = t.map( QPointF( 0, halfSize ) );
865 e.writeSolid( layerName, colorIndex,
QgsPoint( pt1.x(), pt1.y() ),
QgsPoint( pt2.x(), pt2.y() ),
QgsPoint( pt3.x(), pt3.y() ),
QgsPoint( pt3.x(), pt3.y() ) );
871 else if (
mName ==
"line" )
873 QPointF pt1 = t.map( QPointF( 0, halfSize ) );
874 QPointF pt2 = t.map( QPointF( 0, -halfSize ) );
875 e.writeLine(
QgsPoint( pt1.x(), pt1.y() ),
QgsPoint( pt2.x(), pt2.y() ), layerName,
"CONTINUOUS", colorIndex, outlineWidth );
877 else if (
mName ==
"coss" )
879 QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
880 QPointF pt2 = t.map( QPointF( halfSize, 0 ) );
881 QPointF pt3 = t.map( QPointF( 0, -halfSize ) );
882 QPointF pt4 = t.map( QPointF( 0, halfSize ) );
883 e.writeLine(
QgsPoint( pt1.x(), pt1.y() ),
QgsPoint( pt2.x(), pt2.y() ), layerName,
"CONTINUOUS", colorIndex, outlineWidth );
884 e.writeLine(
QgsPoint( pt3.x(), pt3.y() ),
QgsPoint( pt4.x(), pt4.y() ), layerName,
"CONTINUOUS", colorIndex, outlineWidth );
888 QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
889 QPointF pt2 = t.map( QPointF( halfSize, halfSize ) );
890 QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) );
891 QPointF pt4 = t.map( QPointF( halfSize, -halfSize ) );
892 e.writeLine(
QgsPoint( pt1.x(), pt1.y() ),
QgsPoint( pt2.x(), pt2.y() ), layerName,
"CONTINUOUS", colorIndex, outlineWidth );
893 e.writeLine(
QgsPoint( pt3.x(), pt3.y() ),
QgsPoint( pt4.x(), pt4.y() ), layerName,
"CONTINUOUS", colorIndex, outlineWidth );
895 else if (
mName ==
"arrowhead" )
897 QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
898 QPointF pt2 = t.map( QPointF( 0, 0 ) );
899 QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
900 e.writeLine(
QgsPoint( pt1.x(), pt1.y() ),
QgsPoint( pt2.x(), pt2.y() ), layerName,
"CONTINUOUS", colorIndex, outlineWidth );
901 e.writeLine(
QgsPoint( pt3.x(), pt3.y() ),
QgsPoint( pt2.x(), pt2.y() ), layerName,
"CONTINUOUS", colorIndex, outlineWidth );
903 else if (
mName ==
"filled_arrowhead" )
905 QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
906 QPointF pt2 = t.map( QPointF( 0, 0 ) );
907 QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
908 e.writeSolid( layerName, colorIndex,
QgsPoint( pt1.x(), pt1.y() ),
QgsPoint( pt2.x(), pt2.y() ),
QgsPoint( pt3.x(), pt3.y() ),
QgsPoint( pt3.x(), pt3.y() ) );
939 if ( props.contains(
"name" ) )
940 name = props[
"name"];
941 if ( props.contains(
"size" ) )
942 size = props[
"size"].toDouble();
943 if ( props.contains(
"angle" ) )
944 angle = props[
"angle"].toDouble();
949 if ( !props.contains(
"fill" ) && !props.contains(
"outline" ) && !props.contains(
"outline-width" ) )
953 bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
959 if ( hasOutlineParam )
963 if ( hasOutlineWidthParam )
969 if ( props.contains(
"size_unit" ) )
971 if ( props.contains(
"offset" ) )
973 if ( props.contains(
"offset_unit" ) )
975 if ( props.contains(
"fill" ) )
977 if ( props.contains(
"outline" ) )
979 if ( props.contains(
"outline-width" ) )
981 if ( props.contains(
"outline_width_unit" ) )
984 if ( props.contains(
"horizontal_anchor_point" ) )
988 if ( props.contains(
"vertical_anchor_point" ) )
994 if ( props.contains(
"size_expression" ) )
998 if ( props.contains(
"outline-width_expression" ) )
1002 if ( props.contains(
"angle_expression" ) )
1006 if ( props.contains(
"offset_expression" ) )
1010 if ( props.contains(
"name_expression" ) )
1014 if ( props.contains(
"fill_expression" ) )
1018 if ( props.contains(
"outline_expression" ) )
1022 if ( props.contains(
"horizontal_anchor_point_expression" ) )
1026 if ( props.contains(
"vertical_anchor_point_expression" ) )
1038 bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
1044 if ( hasOutlineParam )
1048 if ( hasOutlineWidthParam )
1063 Q_UNUSED( context );
1069 Q_UNUSED( context );
1082 if ( sizeExpression )
1084 size = sizeExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1087 if ( hasDataDefinedSize )
1092 size = sqrt( size );
1101 if ((
int )size < 1 || 10000.0 <
size )
1112 QPointF outputOffset( offsetX, offsetY );
1116 if ( angleExpression )
1118 angle = angleExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1122 p->translate( point + outputOffset );
1131 if ( nameExpression )
1133 path = nameExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
1138 if ( outlineWidthExpression )
1140 outlineWidth = outlineWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1145 if ( fillExpression )
1152 if ( outlineExpression )
1158 bool fitsInCache =
true;
1159 bool usePict =
true;
1160 double hwRatio = 1.0;
1161 if ( drawOnScreen && !rotated )
1166 if ( fitsInCache && img.width() > 1 )
1171 QImage transparentImage = img.copy();
1173 p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
1174 hwRatio = ( double )transparentImage.height() / ( double )transparentImage.width();
1178 p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
1179 hwRatio = ( double )img.height() / ( double )img.width();
1184 if ( usePict || !fitsInCache )
1186 p->setOpacity( context.
alpha() );
1190 if ( pct.width() > 1 )
1192 p->drawPicture( 0, 0, pct );
1193 hwRatio = ( double )pct.height() / ( double )pct.width();
1201 if ( penWidth > size / 20 )
1204 penWidth = size / 20;
1206 double penOffset = penWidth / 2;
1207 pen.setWidth( penWidth );
1209 p->setBrush( Qt::NoBrush );
1210 double wSize = size + penOffset;
1211 double hSize = size * hwRatio + penOffset;
1212 p->drawRect( QRectF( -wSize / 2.0, -hSize / 2.0, wSize, hSize ) );
1223 map[
"size"] = QString::number(
mSize );
1225 map[
"angle"] = QString::number(
mAngle );
1275 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
1276 element.appendChild( graphicElem );
1283 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
1286 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mAngle );
1288 else if ( angle +
mAngle != 0 )
1290 angleFunc = QString::number( angle +
mAngle );
1303 QDomElement graphicElem = element.firstChildElement(
"Graphic" );
1304 if ( graphicElem.isNull() )
1307 QString
path, mimeType;
1314 if ( mimeType !=
"image/svg+xml" )
1322 double d = angleFunc.toDouble( &ok );
1340 const QPointF& shift )
const
1342 Q_UNUSED( layerName );
1345 QSvgRenderer r(
mPath );
1351 QgsDxfPaintDevice pd( &e );
1352 pd.setDrawingSize( QSizeF( r.defaultSize() ) );
1359 if ( sizeExpression )
1361 size = sizeExpression->
evaluate( *f ).toDouble();
1364 if ( hasDataDefinedSize )
1369 size = sqrt( size );
1378 size *= mmMapUnitScaleFactor;
1381 double halfSize = size / 2.0;
1386 if ( offsetExpression )
1388 QString offsetString = offsetExpression->
evaluate( *f ).toString();
1391 double offsetX = offset.x();
1392 double offsetY = offset.y();
1395 offsetX *= mmMapUnitScaleFactor;
1396 offsetY *= mmMapUnitScaleFactor;
1399 QPointF outputOffset( offsetX, offsetY );
1403 if ( angleExpression )
1405 angle = angleExpression->
evaluate( *f ).toDouble();
1415 p.translate( r.defaultSize().width() / 2.0, r.defaultSize().height() / 2.0 );
1417 p.translate( -r.defaultSize().width() / 2.0, -r.defaultSize().height() / 2.0 );
1419 pd.setShift( shift );
1420 pd.setOutputSize( QRectF( -halfSize, -halfSize, size, size ) );
1421 pd.setLayer( layerName );
1449 if ( props.contains(
"font" ) )
1450 fontFamily = props[
"font"];
1451 if ( props.contains(
"chr" ) && props[
"chr"].length() > 0 )
1452 chr = props[
"chr"].at( 0 );
1453 if ( props.contains(
"size" ) )
1454 pointSize = props[
"size"].toDouble();
1455 if ( props.contains(
"color" ) )
1457 if ( props.contains(
"angle" ) )
1458 angle = props[
"angle"].toDouble();
1461 if ( props.contains(
"offset" ) )
1463 if ( props.contains(
"offset_unit" ) )
1465 if ( props.contains(
"size_unit" ) )
1467 if ( props.contains(
"horizontal_anchor_point" ) )
1471 if ( props.contains(
"vertical_anchor_point" ) )
1480 return "FontMarker";
1487 QFontMetrics fm(
mFont );
1495 Q_UNUSED( context );
1505 penColor.setAlphaF(
mColor.alphaF() * context.
alpha() );
1506 p->setPen( penColor );
1507 p->setFont(
mFont );
1514 QPointF outputOffset( offsetX, offsetY );
1517 p->translate( point + outputOffset );
1536 props[
"chr"] =
mChr;
1537 props[
"size"] = QString::number(
mSize );
1540 props[
"angle"] = QString::number(
mAngle );
1562 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
1563 element.appendChild( graphicElem );
1565 QString fontPath = QString(
"ttf://%1" ).arg(
mFontFamily );
1566 int markIndex =
mChr.unicode();
1572 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
1575 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mAngle );
1577 else if ( angle +
mAngle != 0 )
1579 angleFunc = QString::number( angle +
mAngle );
1591 QDomElement graphicElem = element.firstChildElement(
"Graphic" );
1592 if ( graphicElem.isNull() )
1595 QString name, format;
1603 if ( !name.startsWith(
"ttf://" ) || format !=
"ttf" )
1613 double d = angleFunc.toDouble( &ok );