Skip to content

Commit 521426c

Browse files
committed
Improve dxf export for svg symbols
1 parent 99c6875 commit 521426c

File tree

2 files changed

+182
-27
lines changed

2 files changed

+182
-27
lines changed

src/core/dxf/qgsdxfpaintengine.cpp

+166-21
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ void QgsDxfPaintEngine::updateState( const QPaintEngineState& state )
6262
{
6363
mPen = state.pen();
6464
}
65+
if ( state.state() & QPaintEngine::DirtyBrush )
66+
{
67+
mBrush = state.brush();
68+
}
6569
}
6670

6771
void QgsDxfPaintEngine::drawPolygon( const QPointF* points, int pointCount, PolygonDrawMode mode )
@@ -79,7 +83,7 @@ void QgsDxfPaintEngine::drawPolygon( const QPointF* points, int pointCount, Poly
7983
}
8084

8185
bool closed = ( pointCount > 3 && points[0] == points[pointCount - 1] );
82-
mDxf->writePolyline( polyline, mLayer, "CONTINUOUS", currentPenColor(), currentWidth(), closed );
86+
mDxf->writePolyline( polyline, mLayer, "CONTINUOUS", currentColor(), currentWidth(), closed );
8387
}
8488

8589
void QgsDxfPaintEngine::drawRects( const QRectF* rects, int rectCount )
@@ -99,7 +103,7 @@ void QgsDxfPaintEngine::drawRects( const QRectF* rects, int rectCount )
99103
QgsPoint pt2 = toDxfCoordinates( QPointF( right, bottom ) );
100104
QgsPoint pt3 = toDxfCoordinates( QPointF( left, top ) );
101105
QgsPoint pt4 = toDxfCoordinates( QPointF( right, top ) );
102-
mDxf->writeSolid( mLayer, currentPenColor(), pt1, pt2, pt3, pt4 );
106+
mDxf->writeSolid( mLayer, currentColor(), pt1, pt2, pt3, pt4 );
103107
}
104108
}
105109

@@ -110,58 +114,60 @@ void QgsDxfPaintEngine::drawEllipse( const QRectF& rect )
110114
//a circle
111115
if ( qgsDoubleNear( rect.width(), rect.height() ) )
112116
{
113-
mDxf->writeCircle( mLayer, currentPenColor(), toDxfCoordinates( midPoint ), rect.width() / 2.0 );
117+
mDxf->writeCircle( mLayer, currentColor(), toDxfCoordinates( midPoint ), rect.width() / 2.0 );
114118
}
115119

116120
//todo: create polyline for real ellises
117121
}
118122

119123
void QgsDxfPaintEngine::drawPath( const QPainterPath& path )
120124
{
121-
/*QList<QPolygonF> polygonList = path.toFillPolygons();
122-
QList<QPolygonF>::const_iterator pIt = polygonList.constBegin();
123-
for ( ; pIt != polygonList.constEnd(); ++pIt )
124-
{
125-
drawPolygon( pIt->constData(), pIt->size(), pIt->isClosed() ? QPaintEngine::OddEvenMode : QPaintEngine::PolylineMode );
126-
}*/
127-
128125
int pathLength = path.elementCount();
129126
for ( int i = 0; i < pathLength; ++i )
130127
{
131128
const QPainterPath::Element& pathElem = path.elementAt( i );
132-
if ( pathElem.isMoveTo() )
129+
if ( pathElem.type == QPainterPath::MoveToElement )
133130
{
134131
moveTo( pathElem.x, pathElem.y );
135132
}
136-
else if ( pathElem.isLineTo() )
133+
else if ( pathElem.type == QPainterPath::LineToElement )
137134
{
138135
lineTo( pathElem.x, pathElem.y );
139136
}
140-
else if ( pathElem.isCurveTo() )
137+
else if ( pathElem.type == QPainterPath::CurveToElement )
141138
{
142139
curveTo( pathElem.x, pathElem.y );
143140
}
141+
else if ( pathElem.type == QPainterPath::CurveToDataElement )
142+
{
143+
mCurrentCurve.append( QPointF( pathElem.x, pathElem.y ) );
144+
}
144145
}
146+
endCurve();
145147
endPolygon();
146148
}
147149

148150
void QgsDxfPaintEngine::moveTo( double dx, double dy )
149151
{
150-
if ( mCurrentPolygon.size() < 0 )
151-
{
152-
endPolygon();
153-
}
152+
endCurve();
153+
endPolygon();
154154
mCurrentPolygon.append( QPointF( dx, dy ) );
155155
}
156156

157157
void QgsDxfPaintEngine::lineTo( double dx, double dy )
158158
{
159+
endCurve();
159160
mCurrentPolygon.append( QPointF( dx, dy ) );
160161
}
161162

162163
void QgsDxfPaintEngine::curveTo( double dx, double dy )
163164
{
164-
mCurrentPolygon.append( QPointF( dx, dy ) ); //todo...
165+
endCurve();
166+
if ( mCurrentPolygon.size() > 0 )
167+
{
168+
mCurrentCurve.append( mCurrentPolygon.last() );
169+
}
170+
mCurrentCurve.append( QPointF( dx, dy ) );
165171
}
166172

167173
void QgsDxfPaintEngine::endPolygon()
@@ -173,6 +179,35 @@ void QgsDxfPaintEngine::endPolygon()
173179
mCurrentPolygon.clear();
174180
}
175181

182+
void QgsDxfPaintEngine::endCurve()
183+
{
184+
if ( mCurrentCurve.size() < 1 )
185+
{
186+
return;
187+
}
188+
if ( mCurrentPolygon.size() < 1 )
189+
{
190+
mCurrentCurve.clear();
191+
return;
192+
}
193+
//mCurrentCurve.prepend( mCurrentPolygon.last() );
194+
195+
if ( mCurrentCurve.size() >= 3 )
196+
{
197+
double t = 0.05;
198+
for ( int i = 1; i < 20; ++i ) //approximate curve with 20 segments
199+
{
200+
mCurrentPolygon.append( bezierPoint( mCurrentCurve, t ) );
201+
t += 0.05;
202+
}
203+
}
204+
else if ( mCurrentCurve.size() == 2 )
205+
{
206+
mCurrentPolygon.append( mCurrentCurve.at( 1 ) );
207+
}
208+
mCurrentCurve.clear();
209+
}
210+
176211
void QgsDxfPaintEngine::drawLines( const QLineF* lines, int lineCount )
177212
{
178213
if ( !mDxf || !mPaintDevice || !lines )
@@ -184,7 +219,7 @@ void QgsDxfPaintEngine::drawLines( const QLineF* lines, int lineCount )
184219
{
185220
QgsPoint pt1 = toDxfCoordinates( lines[i].p1() );
186221
QgsPoint pt2 = toDxfCoordinates( lines[i].p2() );
187-
mDxf->writeLine( pt1, pt2, mLayer, "CONTINUOUS", currentPenColor(), currentWidth() );
222+
mDxf->writeLine( pt1, pt2, mLayer, "CONTINUOUS", currentColor(), currentWidth() );
188223
}
189224
}
190225

@@ -199,14 +234,19 @@ QgsPoint QgsDxfPaintEngine::toDxfCoordinates( const QPointF& pt ) const
199234
return QgsPoint( dxfPt.x(), dxfPt.y() );
200235
}
201236

202-
int QgsDxfPaintEngine::currentPenColor() const
237+
int QgsDxfPaintEngine::currentColor() const
203238
{
204239
if ( !mDxf )
205240
{
206241
return 0;
207242
}
208243

209-
return mDxf->closestColorMatch( mPen.color().rgb() );
244+
QColor c = mPen.color();
245+
if ( mPen.style() == Qt::NoPen )
246+
{
247+
c = mBrush.color();
248+
}
249+
return mDxf->closestColorMatch( c.rgb() );
210250
}
211251

212252
double QgsDxfPaintEngine::currentWidth() const
@@ -218,3 +258,108 @@ double QgsDxfPaintEngine::currentWidth() const
218258

219259
return mPen.widthF() * mPaintDevice->widthScaleFactor();
220260
}
261+
262+
QPointF QgsDxfPaintEngine::bezierPoint( const QList<QPointF>& controlPolygon, double t )
263+
{
264+
/*if ( p && mControlPoly )
265+
{
266+
p->setX( 0 );
267+
p->setY( 0 );
268+
p->setZ( 0 );
269+
270+
for ( int n = 1; n <= int( mControlPoly->count() ); n++ )
271+
{
272+
double bernst = MathUtils::calcBernsteinPoly( mControlPoly->count() - 1, n - 1, t );
273+
p->setX( p->getX() + ( *mControlPoly )[n-1]->getX()*bernst );
274+
p->setY( p->getY() + ( *mControlPoly )[n-1]->getY()*bernst );
275+
p->setZ( p->getZ() + ( *mControlPoly )[n-1]->getZ()*bernst );
276+
}
277+
}
278+
279+
else
280+
{
281+
QgsDebugMsg( "warning: null pointer" );
282+
}*/
283+
284+
double x = 0;
285+
double y = 0;
286+
int cPolySize = controlPolygon.size();
287+
double bPoly = 0;
288+
289+
QList<QPointF>::const_iterator it = controlPolygon.constBegin();
290+
int i = 0;
291+
for ( ; it != controlPolygon.constEnd(); ++it )
292+
{
293+
bPoly = bernsteinPoly( cPolySize - 1, i, t );
294+
x += ( it->x() * bPoly );
295+
y += ( it->y() * bPoly );
296+
++i;
297+
}
298+
299+
return QPointF( x, y );
300+
}
301+
302+
double QgsDxfPaintEngine::bernsteinPoly( int n, int i, double t )
303+
{
304+
if ( i < 0 )
305+
{
306+
return 0;
307+
}
308+
309+
return lower( n, i )*power( t, i )*power(( 1 - t ), ( n - i ) );
310+
}
311+
312+
int QgsDxfPaintEngine::lower( int n, int i )
313+
{
314+
if ( i >= 0 && i <= n )
315+
{
316+
return faculty( n ) / ( faculty( i )*faculty( n - i ) );
317+
}
318+
else
319+
{
320+
return 0;
321+
}
322+
}
323+
324+
double QgsDxfPaintEngine::power( double a, int b )
325+
{
326+
if ( b == 0 )
327+
{
328+
return 1;
329+
}
330+
double tmp = a;
331+
for ( int i = 2; i <= qAbs(( double )b ); i++ )
332+
{
333+
334+
a *= tmp;
335+
}
336+
if ( b > 0 )
337+
{
338+
return a;
339+
}
340+
else
341+
{
342+
return ( 1.0 / a );
343+
}
344+
}
345+
346+
int QgsDxfPaintEngine::faculty( int n )
347+
{
348+
if ( n < 0 )//Is faculty also defined for negative integers?
349+
{
350+
return 0;
351+
}
352+
int i;
353+
int result = n;
354+
355+
if ( n == 0 || n == 1 )
356+
{
357+
return 1;
358+
}//faculty of 0 is 1!
359+
360+
for ( i = n - 1; i >= 2; i-- )
361+
{
362+
result *= i;
363+
}
364+
return result;
365+
}

src/core/dxf/qgsdxfpaintengine.h

+16-6
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,35 @@ class CORE_EXPORT QgsDxfPaintEngine: public QPaintEngine
4848

4949
void setShift( const QPointF& shift ) { mShift = shift; }
5050

51-
void moveTo( double dx, double dy );
52-
void lineTo( double dx, double dy );
53-
void curveTo( double dx, double dy );
54-
void endPolygon();
55-
5651
private:
5752
const QgsDxfPaintDevice* mPaintDevice;
5853
QgsDxfExport* mDxf;
5954

6055
//painter state information
6156
QTransform mTransform;
6257
QPen mPen;
58+
QBrush mBrush;
6359
QString mLayer;
6460
QPointF mShift;
6561
QPolygonF mCurrentPolygon;
62+
QList<QPointF> mCurrentCurve;
6663

6764
QgsPoint toDxfCoordinates( const QPointF& pt ) const;
68-
int currentPenColor() const;
65+
int currentColor() const;
6966
double currentWidth() const;
67+
68+
void moveTo( double dx, double dy );
69+
void lineTo( double dx, double dy );
70+
void curveTo( double dx, double dy );
71+
void endPolygon();
72+
void endCurve();
73+
74+
//utils for bezier curve calculation
75+
static QPointF bezierPoint( const QList<QPointF>& controlPolygon, double t );
76+
static double bernsteinPoly( int n, int i, double t );
77+
static int lower( int n, int i );
78+
static double power( double a, int b );
79+
static int faculty( int n );
7080
};
7181

7282
#endif // QGSDXFPAINTENGINE_H

0 commit comments

Comments
 (0)