nss: upgrade to release 3.73
[LibreOffice.git] / filter / source / graphicfilter / idxf / dxf2mtf.cxx
blob9ff520167e7900faee06942d3927bb6b152db2e8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <unotools/configmgr.hxx>
22 #include <vcl/gdimtf.hxx>
23 #include <vcl/metaact.hxx>
24 #include <vcl/virdev.hxx>
25 #include <tools/poly.hxx>
26 #include "dxf2mtf.hxx"
28 #include <math.h>
31 sal_uInt64 DXF2GDIMetaFile::CountEntities(const DXFEntities & rEntities)
33 const DXFBasicEntity * pBE;
34 sal_uInt64 nRes;
36 nRes=0;
37 for (pBE=rEntities.pFirst; pBE!=nullptr; pBE=pBE->pSucc) nRes++;
38 return nRes;
41 Color DXF2GDIMetaFile::ConvertColor(sal_uInt8 nColor)
43 return Color(
44 pDXF->aPalette.GetRed( nColor ),
45 pDXF->aPalette.GetGreen( nColor ),
46 pDXF->aPalette.GetBlue( nColor ) );
49 tools::Long DXF2GDIMetaFile::GetEntityColor(const DXFBasicEntity & rE)
51 tools::Long nColor;
53 nColor=rE.nColor;
54 if (nColor==256) {
55 if (rE.m_sLayer.getLength() < 2) {
56 nColor=nParentLayerColor;
57 } else {
58 const DXFLayer * pLayer=pDXF->aTables.SearchLayer(rE.m_sLayer);
59 if (pLayer!=nullptr) nColor=pLayer->nColor;
60 else nColor=nParentLayerColor;
63 else if (nColor==0) nColor=nBlockColor;
64 return nColor;
67 DXFLineInfo DXF2GDIMetaFile::LTypeToDXFLineInfo(OString const& rLineType)
69 const DXFLType * pLT;
70 DXFLineInfo aDXFLineInfo;
72 pLT = pDXF->aTables.SearchLType(rLineType);
73 if (pLT==nullptr || pLT->nDashCount == 0) {
74 aDXFLineInfo.eStyle = LineStyle::Solid;
76 else {
77 aDXFLineInfo.eStyle = LineStyle::Dash;
78 for (tools::Long i=0; i < (pLT->nDashCount); i++) {
79 const double x = pLT->fDash[i] * pDXF->getGlobalLineTypeScale();
80 if ( x >= 0.0 ) {
81 if ( aDXFLineInfo.nDotCount == 0 ) {
82 aDXFLineInfo.nDotCount ++;
83 aDXFLineInfo.fDotLen = x;
85 else if ( aDXFLineInfo.fDotLen == x ) {
86 aDXFLineInfo.nDotCount ++;
88 else if ( aDXFLineInfo.nDashCount == 0 ) {
89 aDXFLineInfo.nDashCount ++;
90 aDXFLineInfo.fDashLen = x;
92 else if ( aDXFLineInfo.fDashLen == x ) {
93 aDXFLineInfo.nDashCount ++;
95 else {
96 // It is impossible to be converted.
99 else {
100 if ( aDXFLineInfo.fDistance == 0 ) {
101 aDXFLineInfo.fDistance = -1 * x;
103 else {
104 // It is impossible to be converted.
111 return aDXFLineInfo;
114 DXFLineInfo DXF2GDIMetaFile::GetEntityDXFLineInfo(const DXFBasicEntity & rE)
116 DXFLineInfo aDXFLineInfo;
118 aDXFLineInfo.eStyle = LineStyle::Solid;
119 aDXFLineInfo.nDashCount = 0;
120 aDXFLineInfo.fDashLen = 0;
121 aDXFLineInfo.nDotCount = 0;
122 aDXFLineInfo.fDotLen = 0;
123 aDXFLineInfo.fDistance = 0;
125 if (rE.m_sLineType == "BYLAYER") {
126 if (rE.m_sLayer.getLength() < 2) {
127 aDXFLineInfo=aParentLayerDXFLineInfo;
128 } else {
129 const DXFLayer * pLayer=pDXF->aTables.SearchLayer(rE.m_sLayer);
130 if (pLayer!=nullptr) {
131 aDXFLineInfo = LTypeToDXFLineInfo(pLayer->m_sLineType);
133 else aDXFLineInfo=aParentLayerDXFLineInfo;
136 else if (rE.m_sLineType == "BYBLOCK") {
137 aDXFLineInfo=aBlockDXFLineInfo;
139 else {
140 aDXFLineInfo = LTypeToDXFLineInfo(rE.m_sLineType);
142 return aDXFLineInfo;
146 bool DXF2GDIMetaFile::SetLineAttribute(const DXFBasicEntity & rE)
148 tools::Long nColor;
149 Color aColor;
151 nColor=GetEntityColor(rE);
152 if (nColor<0) return false;
153 aColor=ConvertColor(static_cast<sal_uInt8>(nColor));
155 if (aActLineColor!=aColor) {
156 aActLineColor = aColor;
157 pVirDev->SetLineColor( aActLineColor );
160 if (aActFillColor!=COL_TRANSPARENT) {
161 aActFillColor = COL_TRANSPARENT;
162 pVirDev->SetFillColor(aActFillColor);
164 return true;
168 bool DXF2GDIMetaFile::SetAreaAttribute(const DXFBasicEntity & rE)
170 tools::Long nColor;
171 Color aColor;
173 nColor=GetEntityColor(rE);
174 if (nColor<0) return false;
175 aColor=ConvertColor(static_cast<sal_uInt8>(nColor));
177 if (aActLineColor!=aColor) {
178 aActLineColor = aColor;
179 pVirDev->SetLineColor( aActLineColor );
182 if ( aActFillColor == COL_TRANSPARENT || aActFillColor != aColor) {
183 aActFillColor = aColor;
184 pVirDev->SetFillColor( aActFillColor );
186 return true;
190 bool DXF2GDIMetaFile::SetFontAttribute(const DXFBasicEntity & rE, short nAngle, sal_uInt16 nHeight)
192 tools::Long nColor;
193 Color aColor;
194 vcl::Font aFont;
196 nAngle=-nAngle;
197 while (nAngle>=3600) nAngle-=3600;
198 while (nAngle<0) nAngle+=3600;
200 nColor=GetEntityColor(rE);
201 if (nColor<0) return false;
202 aColor=ConvertColor(static_cast<sal_uInt8>(nColor));
204 aFont.SetColor(aColor);
205 aFont.SetTransparent(true);
206 aFont.SetFamily(FAMILY_SWISS);
207 aFont.SetFontSize(Size(0,nHeight));
208 aFont.SetAlignment(ALIGN_BASELINE);
209 aFont.SetOrientation(Degree10(nAngle));
210 if (aActFont!=aFont) {
211 aActFont=aFont;
212 pVirDev->SetFont(aActFont);
215 return true;
219 void DXF2GDIMetaFile::DrawLineEntity(const DXFLineEntity & rE, const DXFTransform & rTransform)
221 if (!SetLineAttribute(rE))
222 return;
224 Point aP0,aP1;
225 rTransform.Transform(rE.aP0,aP0);
226 rTransform.Transform(rE.aP1,aP1);
228 DXFLineInfo aDXFLineInfo=GetEntityDXFLineInfo(rE);
229 LineInfo aLineInfo;
230 aLineInfo = rTransform.Transform(aDXFLineInfo);
232 pVirDev->DrawLine(aP0,aP1,aLineInfo);
233 if (rE.fThickness!=0) {
234 Point aP2,aP3;
235 rTransform.Transform(rE.aP0+DXFVector(0,0,rE.fThickness),aP2);
236 rTransform.Transform(rE.aP1+DXFVector(0,0,rE.fThickness),aP3);
237 DrawLine(aP2,aP3);
238 DrawLine(aP0,aP2);
239 DrawLine(aP1,aP3);
244 void DXF2GDIMetaFile::DrawPointEntity(const DXFPointEntity & rE, const DXFTransform & rTransform)
247 if (SetLineAttribute(rE)) {
248 Point aP0;
249 rTransform.Transform(rE.aP0,aP0);
250 if (rE.fThickness==0) pVirDev->DrawPixel(aP0);
251 else {
252 Point aP1;
253 rTransform.Transform(rE.aP0+DXFVector(0,0,rE.fThickness),aP1);
254 DrawLine(aP0,aP1);
260 void DXF2GDIMetaFile::DrawCircleEntity(const DXFCircleEntity & rE, const DXFTransform & rTransform)
262 double frx,fry;
263 sal_uInt16 nPoints,i;
264 DXFVector aC;
266 if (!SetLineAttribute(rE)) return;
267 rTransform.Transform(rE.aP0,aC);
268 if (rE.fThickness==0 && rTransform.TransCircleToEllipse(rE.fRadius,frx,fry)) {
269 pVirDev->DrawEllipse(
270 tools::Rectangle(static_cast<tools::Long>(aC.fx-frx+0.5),static_cast<tools::Long>(aC.fy-fry+0.5),
271 static_cast<tools::Long>(aC.fx+frx+0.5),static_cast<tools::Long>(aC.fy+fry+0.5)));
273 else {
274 double fAng;
275 nPoints=OptPointsPerCircle;
276 tools::Polygon aPoly(nPoints);
277 for (i=0; i<nPoints; i++) {
278 fAng=2*3.14159265359/static_cast<double>(nPoints-1)*static_cast<double>(i);
279 rTransform.Transform(
280 rE.aP0+DXFVector(rE.fRadius*cos(fAng),rE.fRadius*sin(fAng),0),
281 aPoly[i]
284 pVirDev->DrawPolyLine(aPoly);
285 if (rE.fThickness!=0) {
286 tools::Polygon aPoly2(nPoints);
287 for (i=0; i<nPoints; i++) {
288 fAng=2*3.14159265359/static_cast<double>(nPoints-1)*static_cast<double>(i);
289 rTransform.Transform(
290 rE.aP0+DXFVector(rE.fRadius*cos(fAng),rE.fRadius*sin(fAng),rE.fThickness),
291 aPoly2[i]
295 pVirDev->DrawPolyLine(aPoly2);
296 for (i=0; i<nPoints-1; i++) DrawLine(aPoly[i],aPoly2[i]);
301 void DXF2GDIMetaFile::DrawLine(const Point& rA, const Point& rB)
303 if (utl::ConfigManager::IsFuzzing())
304 return;
305 GDIMetaFile* pMetaFile = pVirDev->GetConnectMetaFile();
306 assert(pMetaFile);
307 //use AddAction instead of OutputDevice::DrawLine so that we can explicitly share
308 //the aDefaultLineInfo between the MetaLineActions to reduce memory use
309 pMetaFile->AddAction(new MetaLineAction(rA, rB, aDefaultLineInfo));
312 void DXF2GDIMetaFile::DrawArcEntity(const DXFArcEntity & rE, const DXFTransform & rTransform)
314 double frx,fry;
315 sal_uInt16 nPoints,i;
316 DXFVector aC;
318 if (!SetLineAttribute(rE)) return;
319 double fA1=rE.fStart;
320 double fdA=rE.fEnd-fA1;
321 fdA = fmod(fdA, 360.0);
322 if (fdA<=0) fdA+=360.0;
323 rTransform.Transform(rE.aP0,aC);
324 if (rE.fThickness==0 && fdA>5.0 && rTransform.TransCircleToEllipse(rE.fRadius,frx,fry)) {
325 DXFVector aVS(cos(fA1/180.0*3.14159265359),sin(fA1/180.0*3.14159265359),0.0);
326 aVS*=rE.fRadius;
327 aVS+=rE.aP0;
328 DXFVector aVE(cos((fA1+fdA)/180.0*3.14159265359),sin((fA1+fdA)/180.0*3.14159265359),0.0);
329 aVE*=rE.fRadius;
330 aVE+=rE.aP0;
331 Point aPS,aPE;
332 if (rTransform.Mirror()) {
333 rTransform.Transform(aVS,aPS);
334 rTransform.Transform(aVE,aPE);
336 else {
337 rTransform.Transform(aVS,aPE);
338 rTransform.Transform(aVE,aPS);
340 pVirDev->DrawArc(
341 tools::Rectangle(static_cast<tools::Long>(aC.fx-frx+0.5),static_cast<tools::Long>(aC.fy-fry+0.5),
342 static_cast<tools::Long>(aC.fx+frx+0.5),static_cast<tools::Long>(aC.fy+fry+0.5)),
343 aPS,aPE
346 else {
347 double fAng;
348 nPoints=static_cast<sal_uInt16>(fdA/360.0*static_cast<double>(OptPointsPerCircle)+0.5);
349 if (nPoints<2) nPoints=2;
350 tools::Polygon aPoly(nPoints);
351 for (i=0; i<nPoints; i++) {
352 fAng=3.14159265359/180.0 * ( fA1 + fdA/static_cast<double>(nPoints-1)*static_cast<double>(i) );
353 rTransform.Transform(
354 rE.aP0+DXFVector(rE.fRadius*cos(fAng),rE.fRadius*sin(fAng),0),
355 aPoly[i]
358 pVirDev->DrawPolyLine(aPoly);
359 if (rE.fThickness!=0) {
360 tools::Polygon aPoly2(nPoints);
361 for (i=0; i<nPoints; i++) {
362 fAng=3.14159265359/180.0 * ( fA1 + fdA/static_cast<double>(nPoints-1)*static_cast<double>(i) );
363 rTransform.Transform(
364 rE.aP0+DXFVector(rE.fRadius*cos(fAng),rE.fRadius*sin(fAng),rE.fThickness),
365 aPoly2[i]
368 pVirDev->DrawPolyLine(aPoly2);
369 for (i=0; i<nPoints; i++)
370 DrawLine(aPoly[i], aPoly2[i]);
375 void DXF2GDIMetaFile::DrawTraceEntity(const DXFTraceEntity & rE, const DXFTransform & rTransform)
377 if (!SetLineAttribute(rE))
378 return;
380 tools::Polygon aPoly(4);
381 rTransform.Transform(rE.aP0,aPoly[0]);
382 rTransform.Transform(rE.aP1,aPoly[1]);
383 rTransform.Transform(rE.aP3,aPoly[2]);
384 rTransform.Transform(rE.aP2,aPoly[3]);
385 pVirDev->DrawPolygon(aPoly);
386 if (rE.fThickness!=0) {
387 sal_uInt16 i;
388 tools::Polygon aPoly2(4);
389 DXFVector aVAdd(0,0,rE.fThickness);
390 rTransform.Transform(rE.aP0+aVAdd,aPoly2[0]);
391 rTransform.Transform(rE.aP1+aVAdd,aPoly2[1]);
392 rTransform.Transform(rE.aP3+aVAdd,aPoly2[2]);
393 rTransform.Transform(rE.aP2+aVAdd,aPoly2[3]);
394 pVirDev->DrawPolygon(aPoly2);
395 for (i=0; i<4; i++) DrawLine(aPoly[i],aPoly2[i]);
400 void DXF2GDIMetaFile::DrawSolidEntity(const DXFSolidEntity & rE, const DXFTransform & rTransform)
402 if (!SetAreaAttribute(rE))
403 return;
405 sal_uInt16 nN;
406 if (rE.aP2==rE.aP3) nN=3; else nN=4;
407 tools::Polygon aPoly(nN);
408 rTransform.Transform(rE.aP0,aPoly[0]);
409 rTransform.Transform(rE.aP1,aPoly[1]);
410 rTransform.Transform(rE.aP3,aPoly[2]);
411 if (nN>3) rTransform.Transform(rE.aP2,aPoly[3]);
412 pVirDev->DrawPolygon(aPoly);
413 if (rE.fThickness==0) return;
415 tools::Polygon aPoly2(nN);
416 DXFVector aVAdd(0,0,rE.fThickness);
417 rTransform.Transform(rE.aP0+aVAdd,aPoly2[0]);
418 rTransform.Transform(rE.aP1+aVAdd,aPoly2[1]);
419 rTransform.Transform(rE.aP3+aVAdd,aPoly2[2]);
420 if (nN>3) rTransform.Transform(rE.aP2+aVAdd,aPoly2[3]);
421 pVirDev->DrawPolygon(aPoly2);
422 if (SetLineAttribute(rE)) {
423 sal_uInt16 i;
424 for (i=0; i<nN; i++) DrawLine(aPoly[i],aPoly2[i]);
429 void DXF2GDIMetaFile::DrawTextEntity(const DXFTextEntity & rE, const DXFTransform & rTransform)
431 DXFVector aV;
432 double fA;
433 sal_uInt16 nHeight;
434 short nAng;
435 DXFTransform aT( DXFTransform(rE.fXScale,rE.fHeight,1.0,rE.fRotAngle,rE.aP0), rTransform );
436 aT.TransDir(DXFVector(0,1,0),aV);
437 nHeight=static_cast<sal_uInt16>(aV.Abs()+0.5);
438 fA=aT.CalcRotAngle();
439 nAng=static_cast<short>(fA*10.0+0.5);
440 aT.TransDir(DXFVector(1,0,0),aV);
441 if ( SetFontAttribute( rE,nAng, nHeight ) )
443 OUString const aUString(pDXF->ToOUString(rE.m_sText));
444 Point aPt;
445 aT.Transform( DXFVector( 0, 0, 0 ), aPt );
446 pVirDev->DrawText( aPt, aUString );
451 void DXF2GDIMetaFile::DrawInsertEntity(const DXFInsertEntity & rE, const DXFTransform & rTransform)
453 const DXFBlock * pB;
454 pB=pDXF->aBlocks.Search(rE.m_sName);
455 if (pB==nullptr)
456 return;
458 DXFTransform aDXFTransform1(1.0,1.0,1.0,DXFVector(0.0,0.0,0.0)-pB->aBasePoint);
459 DXFTransform aDXFTransform2(rE.fXScale,rE.fYScale,rE.fZScale,rE.fRotAngle,rE.aP0);
460 DXFTransform aT(
461 DXFTransform( aDXFTransform1, aDXFTransform2 ),
462 rTransform
464 tools::Long nSavedBlockColor, nSavedParentLayerColor;
465 DXFLineInfo aSavedBlockDXFLineInfo, aSavedParentLayerDXFLineInfo;
466 nSavedBlockColor=nBlockColor;
467 nSavedParentLayerColor=nParentLayerColor;
468 aSavedBlockDXFLineInfo=aBlockDXFLineInfo;
469 aSavedParentLayerDXFLineInfo=aParentLayerDXFLineInfo;
470 nBlockColor=GetEntityColor(rE);
471 aBlockDXFLineInfo=GetEntityDXFLineInfo(rE);
472 if (rE.m_sLayer.getLength() > 1) {
473 DXFLayer * pLayer=pDXF->aTables.SearchLayer(rE.m_sLayer);
474 if (pLayer!=nullptr) {
475 nParentLayerColor=pLayer->nColor;
476 aParentLayerDXFLineInfo = LTypeToDXFLineInfo(pLayer->m_sLineType);
479 DrawEntities(*pB,aT);
480 aBlockDXFLineInfo=aSavedBlockDXFLineInfo;
481 aParentLayerDXFLineInfo=aSavedParentLayerDXFLineInfo;
482 nBlockColor=nSavedBlockColor;
483 nParentLayerColor=nSavedParentLayerColor;
487 void DXF2GDIMetaFile::DrawAttribEntity(const DXFAttribEntity & rE, const DXFTransform & rTransform)
489 if ((rE.nAttrFlags&1)!=0)
490 return;
492 DXFVector aV;
493 double fA;
494 sal_uInt16 nHeight;
495 short nAng;
496 DXFTransform aT( DXFTransform( rE.fXScale, rE.fHeight, 1.0, rE.fRotAngle, rE.aP0 ), rTransform );
497 aT.TransDir(DXFVector(0,1,0),aV);
498 nHeight=static_cast<sal_uInt16>(aV.Abs()+0.5);
499 fA=aT.CalcRotAngle();
500 nAng=static_cast<short>(fA*10.0+0.5);
501 aT.TransDir(DXFVector(1,0,0),aV);
502 if (SetFontAttribute(rE,nAng,nHeight))
504 OUString const aUString(pDXF->ToOUString(rE.m_sText));
505 Point aPt;
506 aT.Transform( DXFVector( 0, 0, 0 ), aPt );
507 pVirDev->DrawText( aPt, aUString );
512 void DXF2GDIMetaFile::DrawPolyLineEntity(const DXFPolyLineEntity & rE, const DXFTransform & rTransform)
514 sal_uInt16 i,nPolySize;
515 const DXFBasicEntity * pBE;
517 nPolySize=0;
518 pBE=rE.pSucc;
519 while (pBE!=nullptr && pBE->eType==DXF_VERTEX) {
520 nPolySize++;
521 pBE=pBE->pSucc;
523 if (nPolySize<2)
524 return;
525 tools::Polygon aPoly(nPolySize);
526 pBE=rE.pSucc;
527 for (i=0; i<nPolySize; i++) {
528 rTransform.Transform(static_cast<const DXFVertexEntity*>(pBE)->aP0,aPoly[i]);
529 pBE=pBE->pSucc;
532 if (!SetLineAttribute(rE))
533 return;
535 if ((rE.nFlags&1)!=0) pVirDev->DrawPolygon(aPoly);
536 else pVirDev->DrawPolyLine(aPoly);
537 if (rE.fThickness==0)
538 return;
540 tools::Polygon aPoly2(nPolySize);
541 pBE=rE.pSucc;
542 for (i=0; i<nPolySize; i++) {
543 rTransform.Transform(
544 (static_cast<const DXFVertexEntity*>(pBE)->aP0)+DXFVector(0,0,rE.fThickness),
545 aPoly2[i]
547 pBE=pBE->pSucc;
549 if ((rE.nFlags&1)!=0) pVirDev->DrawPolygon(aPoly2);
550 else pVirDev->DrawPolyLine(aPoly2);
551 for (i=0; i<nPolySize; i++) DrawLine(aPoly[i],aPoly2[i]);
554 void DXF2GDIMetaFile::DrawLWPolyLineEntity(const DXFLWPolyLineEntity & rE, const DXFTransform & rTransform )
556 sal_Int32 nPolySize = rE.aP.size();
557 if (!nPolySize)
558 return;
560 tools::Polygon aPoly( static_cast<sal_uInt16>(nPolySize));
561 for (sal_Int32 i = 0; i < nPolySize; ++i)
563 rTransform.Transform( rE.aP[ static_cast<sal_uInt16>(i) ], aPoly[ static_cast<sal_uInt16>(i) ] );
565 if ( SetLineAttribute( rE ) )
567 if ( ( rE.nFlags & 1 ) != 0 )
568 pVirDev->DrawPolygon( aPoly );
569 else
570 pVirDev->DrawPolyLine( aPoly );
574 void DXF2GDIMetaFile::DrawHatchEntity(const DXFHatchEntity & rE, const DXFTransform & rTransform )
576 if ( !rE.nBoundaryPathCount )
577 return;
579 SetAreaAttribute( rE );
580 sal_Int32 j = 0;
581 tools::PolyPolygon aPolyPoly;
582 for ( j = 0; j < rE.nBoundaryPathCount; j++ )
584 std::vector< Point > aPtAry;
585 const DXFBoundaryPathData& rPathData = rE.pBoundaryPathData[ j ];
586 if ( rPathData.bIsPolyLine )
588 for (const auto& a : rPathData.aP)
590 Point aPt;
591 rTransform.Transform(a, aPt);
592 aPtAry.push_back( aPt );
595 else
597 for ( auto& rEdge : rPathData.aEdges )
599 const DXFEdgeType* pEdge = rEdge.get();
600 switch( pEdge->nEdgeType )
602 case 1 :
604 Point aPt;
605 rTransform.Transform( static_cast<const DXFEdgeTypeLine*>(pEdge)->aStartPoint, aPt );
606 aPtAry.push_back( aPt );
607 rTransform.Transform( static_cast<const DXFEdgeTypeLine*>(pEdge)->aEndPoint, aPt );
608 aPtAry.push_back( aPt );
610 break;
611 case 2 :
612 case 3 :
613 case 4 :
614 break;
618 sal_uInt16 i, nSize = static_cast<sal_uInt16>(aPtAry.size());
619 if ( nSize )
621 tools::Polygon aPoly( nSize );
622 for ( i = 0; i < nSize; i++ )
623 aPoly[ i ] = aPtAry[ i ];
624 aPolyPoly.Insert( aPoly );
627 if ( aPolyPoly.Count() )
628 pVirDev->DrawPolyPolygon( aPolyPoly );
631 void DXF2GDIMetaFile::Draw3DFaceEntity(const DXF3DFaceEntity & rE, const DXFTransform & rTransform)
633 sal_uInt16 nN,i;
634 if (!SetLineAttribute(rE))
635 return;
637 if (rE.aP2==rE.aP3) nN=3; else nN=4;
638 tools::Polygon aPoly(nN);
639 rTransform.Transform(rE.aP0,aPoly[0]);
640 rTransform.Transform(rE.aP1,aPoly[1]);
641 rTransform.Transform(rE.aP2,aPoly[2]);
642 if (nN>3) rTransform.Transform(rE.aP3,aPoly[3]);
643 if ((rE.nIEFlags&0x0f)==0) pVirDev->DrawPolygon(aPoly);
644 else {
645 for (i=0; i<nN; i++) {
646 if ( (rE.nIEFlags & (static_cast<tools::Long>(1)<<i)) == 0 ) {
647 DrawLine(aPoly[i],aPoly[(i+1)%nN]);
653 void DXF2GDIMetaFile::DrawDimensionEntity(const DXFDimensionEntity & rE, const DXFTransform & rTransform)
655 const DXFBlock * pB;
656 pB=pDXF->aBlocks.Search(rE.m_sPseudoBlock);
657 if (pB==nullptr)
658 return;
660 DXFTransform aT(
661 DXFTransform(1.0,1.0,1.0,DXFVector(0.0,0.0,0.0)-pB->aBasePoint),
662 rTransform
664 tools::Long nSavedBlockColor, nSavedParentLayerColor;
665 DXFLineInfo aSavedBlockDXFLineInfo, aSavedParentLayerDXFLineInfo;
666 nSavedBlockColor=nBlockColor;
667 nSavedParentLayerColor=nParentLayerColor;
668 aSavedBlockDXFLineInfo=aBlockDXFLineInfo;
669 aSavedParentLayerDXFLineInfo=aParentLayerDXFLineInfo;
670 nBlockColor=GetEntityColor(rE);
671 aBlockDXFLineInfo=GetEntityDXFLineInfo(rE);
672 if (rE.m_sLayer.getLength() > 1) {
673 DXFLayer * pLayer=pDXF->aTables.SearchLayer(rE.m_sLayer);
674 if (pLayer!=nullptr) {
675 nParentLayerColor=pLayer->nColor;
676 aParentLayerDXFLineInfo = LTypeToDXFLineInfo(pLayer->m_sLineType);
679 DrawEntities(*pB,aT);
680 aBlockDXFLineInfo=aSavedBlockDXFLineInfo;
681 aParentLayerDXFLineInfo=aSavedParentLayerDXFLineInfo;
682 nBlockColor=nSavedBlockColor;
683 nParentLayerColor=nSavedParentLayerColor;
687 void DXF2GDIMetaFile::DrawEntities(const DXFEntities & rEntities,
688 const DXFTransform & rTransform)
690 if (rEntities.mbBeingDrawn)
691 return;
692 rEntities.mbBeingDrawn = true;
694 DXFTransform aET;
695 const DXFTransform * pT;
697 const DXFBasicEntity * pE=rEntities.pFirst;
699 while (pE!=nullptr && bStatus) {
700 if (pE->nSpace==0) {
701 if (pE->aExtrusion.fz==1.0) {
702 pT=&rTransform;
704 else {
705 aET=DXFTransform(DXFTransform(pE->aExtrusion),rTransform);
706 pT=&aET;
708 switch (pE->eType) {
709 case DXF_LINE:
710 DrawLineEntity(static_cast<const DXFLineEntity&>(*pE),*pT);
711 break;
712 case DXF_POINT:
713 DrawPointEntity(static_cast<const DXFPointEntity&>(*pE),*pT);
714 break;
715 case DXF_CIRCLE:
716 DrawCircleEntity(static_cast<const DXFCircleEntity&>(*pE),*pT);
717 break;
718 case DXF_ARC:
719 DrawArcEntity(static_cast<const DXFArcEntity&>(*pE),*pT);
720 break;
721 case DXF_TRACE:
722 DrawTraceEntity(static_cast<const DXFTraceEntity&>(*pE),*pT);
723 break;
724 case DXF_SOLID:
725 DrawSolidEntity(static_cast<const DXFSolidEntity&>(*pE),*pT);
726 break;
727 case DXF_TEXT:
728 DrawTextEntity(static_cast<const DXFTextEntity&>(*pE),*pT);
729 break;
730 case DXF_INSERT:
731 DrawInsertEntity(static_cast<const DXFInsertEntity&>(*pE),*pT);
732 break;
733 case DXF_ATTRIB:
734 DrawAttribEntity(static_cast<const DXFAttribEntity&>(*pE),*pT);
735 break;
736 case DXF_POLYLINE:
737 DrawPolyLineEntity(static_cast<const DXFPolyLineEntity&>(*pE),*pT);
738 break;
739 case DXF_LWPOLYLINE :
740 DrawLWPolyLineEntity(static_cast<const DXFLWPolyLineEntity&>(*pE), *pT);
741 break;
742 case DXF_HATCH :
743 DrawHatchEntity(static_cast<const DXFHatchEntity&>(*pE), *pT);
744 break;
745 case DXF_3DFACE:
746 Draw3DFaceEntity(static_cast<const DXF3DFaceEntity&>(*pE),*pT);
747 break;
748 case DXF_DIMENSION:
749 DrawDimensionEntity(static_cast<const DXFDimensionEntity&>(*pE),*pT);
750 break;
751 default:
752 break; // four other values not handled -Wall
755 pE=pE->pSucc;
758 rEntities.mbBeingDrawn = false;
762 DXF2GDIMetaFile::DXF2GDIMetaFile()
763 : pVirDev(nullptr)
764 , pDXF(nullptr)
765 , bStatus(false)
766 , OptPointsPerCircle(0)
767 , nMinPercent(0)
768 , nMaxPercent(0)
769 , nLastPercent(0)
770 , nMainEntitiesCount(0)
771 , nBlockColor(0)
772 , nParentLayerColor(0)
777 DXF2GDIMetaFile::~DXF2GDIMetaFile()
782 bool DXF2GDIMetaFile::Convert(const DXFRepresentation & rDXF, GDIMetaFile & rMTF, sal_uInt16 nminpercent, sal_uInt16 nmaxpercent)
784 double fWidth,fHeight,fScale(0.0);
785 DXFTransform aTransform;
786 Size aPrefSize;
787 const DXFLayer * pLayer;
788 const DXFVPort * pVPort;
790 pVirDev = VclPtr<VirtualDevice>::Create();
791 pDXF = &rDXF;
792 bStatus = true;
794 OptPointsPerCircle=50;
796 nMinPercent=nminpercent;
797 nMaxPercent=nmaxpercent;
798 nLastPercent=nMinPercent;
799 nMainEntitiesCount=CountEntities(pDXF->aEntities);
801 nBlockColor=7;
802 aBlockDXFLineInfo.eStyle = LineStyle::Solid;
803 aBlockDXFLineInfo.nDashCount = 0;
804 aBlockDXFLineInfo.fDashLen = 0;
805 aBlockDXFLineInfo.nDotCount = 0;
806 aBlockDXFLineInfo.fDotLen = 0;
807 aBlockDXFLineInfo.fDistance = 0;
809 pLayer=pDXF->aTables.SearchLayer("0");
810 if (pLayer!=nullptr) {
811 nParentLayerColor=pLayer->nColor & 0xff;
812 aParentLayerDXFLineInfo = LTypeToDXFLineInfo(pLayer->m_sLineType);
814 else {
815 nParentLayerColor=7;
816 aParentLayerDXFLineInfo.eStyle = LineStyle::Solid;
817 aParentLayerDXFLineInfo.nDashCount = 0;
818 aParentLayerDXFLineInfo.fDashLen = 0;
819 aParentLayerDXFLineInfo.nDotCount = 0;
820 aParentLayerDXFLineInfo.fDotLen = 0;
821 aParentLayerDXFLineInfo.fDistance = 0;
824 pVirDev->EnableOutput(false);
825 if (!utl::ConfigManager::IsFuzzing()) // for fuzzing don't bother recording the drawing
826 rMTF.Record(pVirDev);
828 aActLineColor = pVirDev->GetLineColor();
829 aActFillColor = pVirDev->GetFillColor();
830 aActFont = pVirDev->GetFont();
832 pVPort=pDXF->aTables.SearchVPort("*ACTIVE");
833 if (pVPort!=nullptr) {
834 if (pVPort->aDirection.fx==0 && pVPort->aDirection.fy==0)
835 pVPort=nullptr;
838 if (pVPort==nullptr) {
839 if (pDXF->aBoundingBox.bEmpty)
840 bStatus=false;
841 else {
842 fWidth=pDXF->aBoundingBox.fMaxX-pDXF->aBoundingBox.fMinX;
843 fHeight=pDXF->aBoundingBox.fMaxY-pDXF->aBoundingBox.fMinY;
844 if (fWidth<=0 || fHeight<=0) {
845 bStatus=false;
847 else {
848 if (fWidth>fHeight)
849 fScale=10000.0/fWidth;
850 else
851 fScale=10000.0/fHeight;
852 aTransform=DXFTransform(fScale,-fScale,fScale,
853 DXFVector(-pDXF->aBoundingBox.fMinX*fScale,
854 pDXF->aBoundingBox.fMaxY*fScale,
855 -pDXF->aBoundingBox.fMinZ*fScale));
857 aPrefSize.setWidth(static_cast<tools::Long>(fWidth*fScale+1.5) );
858 aPrefSize.setHeight(static_cast<tools::Long>(fHeight*fScale+1.5) );
861 else {
862 fHeight=pVPort->fHeight;
863 fWidth=fHeight*pVPort->fAspectRatio;
864 if (fWidth<=0 || fHeight<=0) {
865 bStatus=false;
866 } else {
867 if (fWidth>fHeight)
868 fScale=10000.0/fWidth;
869 else
870 fScale=10000.0/fHeight;
871 aTransform=DXFTransform(
872 DXFTransform(pVPort->aDirection,pVPort->aTarget),
873 DXFTransform(
874 DXFTransform(1.0,-1.0,1.0,DXFVector(fWidth/2-pVPort->fCenterX,fHeight/2+pVPort->fCenterY,0)),
875 DXFTransform(fScale,fScale,fScale,DXFVector(0,0,0))
879 aPrefSize.setWidth(static_cast<tools::Long>(fWidth*fScale+1.5) );
880 aPrefSize.setHeight(static_cast<tools::Long>(fHeight*fScale+1.5) );
883 if (bStatus)
884 DrawEntities(pDXF->aEntities,aTransform);
886 rMTF.Stop();
888 if ( bStatus )
890 rMTF.SetPrefSize( aPrefSize );
891 // simply set map mode to 1/100-mm (1/10-mm) if the graphic
892 // does not get not too small (<0.5cm)
893 if( ( aPrefSize.Width() < 500 ) && ( aPrefSize.Height() < 500 ) )
894 rMTF.SetPrefMapMode( MapMode( MapUnit::Map10thMM ) );
895 else
896 rMTF.SetPrefMapMode( MapMode( MapUnit::Map100thMM ) );
899 pVirDev.disposeAndClear();
900 return bStatus;
904 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */