1 /****************************************************************************
2 **
3 ** This file is part of the LibreCAD project, a 2D CAD program
4 **
5 ** Copyright (C) 2015 A. Stebich (librecad@mail.lordofbikes.de)
6 ** Copyright (C) 2011 Rallaz, rallazz@gmail.com
7 ** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
8 **
9 **
10 ** This file may be distributed and/or modified under the terms of the
11 ** GNU General Public License as published by the Free Software
12 ** Foundation either version 2 of the License, or (at your option)
13 ** any later version.
14 **
15 ** This program is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ** GNU General Public License for more details.
19 **
20 ** You should have received a copy of the GNU General Public License
21 ** along with this program; if not, write to the Free Software
22 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 **
24 **********************************************************************/
25
26 #include<cstdlib>
27 #include <QStringList>
28 #include <QTextCodec>
29
30 #include "rs_filterdxfrw.h"
31
32 #include "rs_arc.h"
33 #include "rs_circle.h"
34 #include "rs_dimaligned.h"
35 #include "rs_dimangular.h"
36 #include "rs_dimdiametric.h"
37 #include "rs_dimlinear.h"
38 #include "rs_dimradial.h"
39 #include "rs_ellipse.h"
40 #include "rs_hatch.h"
41 #include "rs_image.h"
42 #include "rs_insert.h"
43 #include "rs_layer.h"
44 #include "rs_leader.h"
45 #include "rs_line.h"
46 #include "rs_mtext.h"
47 #include "rs_point.h"
48 #include "rs_polyline.h"
49 #include "rs_solid.h"
50 #include "rs_spline.h"
51 #include "lc_splinepoints.h"
52 #include "rs_system.h"
53 #include "rs_text.h"
54 #include "rs_graphicview.h"
55 #include "rs_dialogfactory.h"
56 #include "rs_math.h"
57
58 #ifdef DWGSUPPORT
59 #include "libdwgr.h"
60 #include "rs_debug.h"
61 #endif
62
63 /**
64 * Default constructor.
65 *
66 */
RS_FilterDXFRW()67 RS_FilterDXFRW::RS_FilterDXFRW()
68 :RS_FilterInterface(),DRW_Interface() {
69
70 RS_DEBUG->print("RS_FilterDXFRW::RS_FilterDXFRW()");
71
72 currentContainer = nullptr;
73 graphic = nullptr;
74 // Init hash to change the QCAD "normal" style to the more correct ISO-3059
75 // or draftsight symbol (AR*.shx) to sy*.lff
76 fontList["normal"] = "iso";
77 fontList["normallatin1"] = "iso";
78 fontList["normallatin2"] = "iso";
79 fontList["arastro"] = "syastro";
80 fontList["armap"] = "symap";
81 fontList["math"] = "symath";
82 fontList["armeteo"] = "symeteo";
83 fontList["armusic"] = "symusic";
84
85
86 RS_DEBUG->print("RS_FilterDXFRW::RS_FilterDXFRW(): OK");
87 }
88
89 /**
90 * Destructor.
91 */
~RS_FilterDXFRW()92 RS_FilterDXFRW::~RS_FilterDXFRW() {
93 RS_DEBUG->print("RS_FilterDXFRW::~RS_FilterDXFRW(): OK");
94 }
95
96
97
98 /**
99 * Implementation of the method used for RS_Import to communicate
100 * with this filter.
101 *
102 * @param g The graphic in which the entities from the file
103 * will be created or the graphics from which the entities are
104 * taken to be stored in a file.
105 */
fileImport(RS_Graphic & g,const QString & file,RS2::FormatType type)106 bool RS_FilterDXFRW::fileImport(RS_Graphic& g, const QString& file, RS2::FormatType type) {
107 RS_DEBUG->print("RS_FilterDXFRW::fileImport");
108
109 RS_DEBUG->print("DXFRW Filter: importing file '%s'...", (const char*)QFile::encodeName(file));
110 #ifndef DWGSUPPORT
111 Q_UNUSED(type)
112 #endif
113
114 graphic = &g;
115 currentContainer = graphic;
116 dummyContainer = new RS_EntityContainer(nullptr, true);
117
118 this->file = file;
119 // add some variables that need to be there for DXF drawings:
120 graphic->addVariable("$DIMSTYLE", "Standard", 2);
121 dimStyle = "Standard";
122 codePage = "ANSI_1252";
123 textStyle = "Standard";
124 //reset library version
125 isLibDxfRw = false;
126 libDxfRwVersion = 0;
127
128 #ifdef DWGSUPPORT
129 if (type == RS2::FormatDWG) {
130 dwgR dwgr(QFile::encodeName(file));
131 RS_DEBUG->print("RS_FilterDXFRW::fileImport: reading DWG file");
132 if (RS_DEBUG->getLevel()== RS_Debug::D_DEBUGGING)
133 dwgr.setDebug(DRW::DEBUG);
134 bool success = dwgr.read(this, true);
135 RS_DEBUG->print("RS_FilterDXFRW::fileImport: reading DWG file: OK");
136 RS_DIALOGFACTORY->commandMessage(QObject::tr("Opened dwg file version %1.").arg(printDwgVersion(dwgr.getVersion())));
137 int lastError = dwgr.getError();
138 if (success==false) {
139 printDwgError(lastError);
140 RS_DEBUG->print(RS_Debug::D_WARNING,
141 "Cannot open DWG file '%s'.", (const char*)QFile::encodeName(file));
142 return false;
143 }
144 } else {
145 #endif
146 dxfRW dxfR(QFile::encodeName(file));
147
148 RS_DEBUG->print("RS_FilterDXFRW::fileImport: reading file");
149 bool success = dxfR.read(this, true);
150 RS_DEBUG->print("RS_FilterDXFRW::fileImport: reading file: OK");
151 //graphic->setAutoUpdateBorders(true);
152
153 if (success==false) {
154 RS_DEBUG->print(RS_Debug::D_WARNING,
155 "Cannot open DXF file '%s'.", (const char*)QFile::encodeName(file));
156 return false;
157 }
158 #ifdef DWGSUPPORT
159 }
160 #endif
161
162 delete dummyContainer;
163 /*set current layer */
164 RS_Layer* cl = graphic->findLayer(graphic->getVariableString("$CLAYER", "0"));
165 if (cl ){
166 //require to notify
167 graphic->getLayerList()->activate(cl, true);
168 }
169 RS_DEBUG->print("RS_FilterDXFRW::fileImport: updating inserts");
170 graphic->updateInserts();
171
172 RS_DEBUG->print("RS_FilterDXFRW::fileImport OK");
173
174 return true;
175 }
176
177 /**
178 * Implementation of the method which handles layers.
179 */
addLayer(const DRW_Layer & data)180 void RS_FilterDXFRW::addLayer(const DRW_Layer &data) {
181 RS_DEBUG->print("RS_FilterDXF::addLayer");
182 RS_DEBUG->print(" adding layer: %s", data.name.c_str());
183
184 RS_DEBUG->print("RS_FilterDXF::addLayer: creating layer");
185
186 QString name = QString::fromUtf8(data.name.c_str());
187 if (name != "0" && graphic->findLayer(name)) {
188 return;
189 }
190 RS_Layer* layer = new RS_Layer(name);
191 RS_DEBUG->print("RS_FilterDXF::addLayer: set pen");
192 layer->setPen(attributesToPen(&data));
193
194 RS_DEBUG->print("RS_FilterDXF::addLayer: flags");
195 if (data.flags&0x01) {
196 layer->freeze(true);
197 }
198 if (data.flags&0x04) {
199 layer->lock(true);
200 }
201 layer->setPrint(data.plotF);
202
203 //parse extended data to read construction flag
204 if (!data.extData.empty()){
205 RS_DEBUG->print(RS_Debug::D_WARNING, "RS_FilterDXF::addLayer: layer %s have extended data", layer->getName().toStdString().c_str());
206 bool isLCdata = false;
207 for (std::vector<DRW_Variant*>::const_iterator it=data.extData.begin(); it!=data.extData.end(); ++it){
208 if ((*it)->code() == 1001){
209 if (*(*it)->content.s == std::string("LibreCad"))
210 isLCdata = true;
211 else
212 isLCdata = false;
213 } else if (isLCdata && (*it)->code() == 1070){
214 if ((*it)->content.i == 1){
215 layer->setConstruction(true);
216 }
217 }
218 }
219 }
220 //pre dxfrw 0.5.13 plot flag are used to store construction layer
221 if( isLibDxfRw && libDxfRwVersion < LIBDXFRW_VERSION( 0, 5, 13)) {
222 layer->setConstruction(! data.plotF);
223 }
224
225 if (layer->isConstruction())
226 RS_DEBUG->print(RS_Debug::D_WARNING, "RS_FilterDXF::addLayer: layer %s is construction layer", layer->getName().toStdString().c_str());
227
228 RS_DEBUG->print("RS_FilterDXF::addLayer: add layer to graphic");
229 graphic->addLayer(layer);
230 RS_DEBUG->print("RS_FilterDXF::addLayer: OK");
231 }
232
233 /**
234 * Implementation of the method which handles dimension styles.
235 */
addDimStyle(const DRW_Dimstyle & data)236 void RS_FilterDXFRW::addDimStyle(const DRW_Dimstyle& data){
237 RS_DEBUG->print("RS_FilterDXFRW::addLayer");
238 QString dimstyle = graphic->getVariableString("$DIMSTYLE", "standard");
239
240 if (QString::compare(data.name.c_str(), dimstyle, Qt::CaseInsensitive) == 0) {
241 if( isLibDxfRw && libDxfRwVersion < LIBDXFRW_VERSION( 0, 6, 2)) {
242 graphic->addVariable("$DIMDEC", graphic->getVariableInt("$DIMDEC",
243 graphic->getVariableInt("$LUPREC", 4)), 70);
244 graphic->addVariable("$DIMADEC", graphic->getVariableInt("$DIMADEC",
245 graphic->getVariableInt("$AUPREC", 2)), 70);
246 //do nothing;
247 } else {
248 graphic->addVariable("$DIMDEC", data.dimdec, 70);
249 graphic->addVariable("$DIMADEC", data.dimadec, 70);
250 }
251 }
252 }
253
254 /**
255 * Implementation of the method which handles vports.
256 */
addVport(const DRW_Vport & data)257 void RS_FilterDXFRW::addVport(const DRW_Vport &data) {
258 QString name = QString::fromStdString(data.name);
259 if (name.toLower() == "*active") {
260 data.grid == 1? graphic->setGridOn(true):graphic->setGridOn(false);
261 graphic->setIsometricGrid(data.snapStyle);
262 graphic->setCrosshairType( (RS2::CrosshairType)data.snapIsopair);
263 RS_GraphicView *gv = graphic->getGraphicView();
264 if (gv ) {
265 double width = data.height * data.ratio;
266 double factorX= gv->getWidth() / width;
267 double factorY= gv->getHeight() / data.height;
268 if (factorX > factorY)
269 factorX = factorY;
270 int ox = gv->getWidth() -data.center.x*2*factorX;
271 int oy = gv->getHeight() -data.center.y*2*factorX;
272 gv->setOffset(ox, oy);
273 gv->setFactor(factorX);
274 }
275 }
276 }
277
278 /**
279 * Implementation of the method which handles blocks.
280 *
281 * @todo Adding blocks to blocks (stack for currentContainer)
282 */
addBlock(const DRW_Block & data)283 void RS_FilterDXFRW::addBlock(const DRW_Block& data) {
284
285 RS_DEBUG->print("RS_FilterDXF::addBlock");
286
287 RS_DEBUG->print(" adding block: %s", data.name.c_str());
288 /*TODO correct handle of model-space*/
289
290 QString name = QString::fromUtf8(data.name.c_str());
291 QString mid = name.mid(1,11);
292 // Prevent special blocks (paper_space, model_space) from being added:
293 if (mid.toLower() != "paper_space" && mid.toLower() != "model_space") {
294
295 RS_Vector bp(data.basePoint.x, data.basePoint.y);
296 RS_Block* block =
297 new RS_Block(graphic, RS_BlockData(name, bp, false ));
298 //block->setFlags(flags);
299
300 if (graphic->addBlock(block)) {
301 currentContainer = block;
302 blockHash.insert(data.parentHandle, currentContainer);
303 } else
304 blockHash.insert(data.parentHandle, dummyContainer);
305 } else {
306 if (mid.toLower() == "model_space") {
307 blockHash.insert(data.parentHandle, graphic);
308 } else {
309 blockHash.insert(data.parentHandle, dummyContainer);
310 }
311 }
312 }
313
314
setBlock(const int handle)315 void RS_FilterDXFRW::setBlock(const int handle){
316 if (blockHash.contains(handle)) {
317 currentContainer = blockHash.value(handle);
318 } else
319 currentContainer = graphic;
320 }
321
322 /**
323 * Implementation of the method which closes blocks.
324 */
endBlock()325 void RS_FilterDXFRW::endBlock() {
326 if (currentContainer->rtti() == RS2::EntityBlock) {
327 RS_Block *bk = (RS_Block *)currentContainer;
328 //remove unnamed blocks *D only if version != R12
329 if (version!=1009) {
330 if (bk->getName().startsWith("*D") )
331 graphic->removeBlock(bk);
332 }
333 }
334 currentContainer = graphic;
335 }
336
337
338
339 /**
340 * Implementation of the method which handles point entities.
341 */
addPoint(const DRW_Point & data)342 void RS_FilterDXFRW::addPoint(const DRW_Point& data) {
343 RS_Vector v(data.basePoint.x, data.basePoint.y);
344
345 RS_Point* entity = new RS_Point(currentContainer,
346 RS_PointData(v));
347 setEntityAttributes(entity, &data);
348
349 currentContainer->addEntity(entity);
350 }
351
352
353
354 /**
355 * Implementation of the method which handles line entities.
356 */
addLine(const DRW_Line & data)357 void RS_FilterDXFRW::addLine(const DRW_Line& data) {
358 RS_DEBUG->print("RS_FilterDXF::addLine");
359
360 RS_Vector v1(data.basePoint.x, data.basePoint.y);
361 RS_Vector v2(data.secPoint.x, data.secPoint.y);
362
363 RS_DEBUG->print("RS_FilterDXF::addLine: create line");
364
365 if (!currentContainer) {
366 RS_DEBUG->print("RS_FilterDXF::addLine: currentContainer is nullptr");
367 }
368
369 RS_Line* entity = new RS_Line{currentContainer, {v1, v2}};
370 RS_DEBUG->print("RS_FilterDXF::addLine: set attributes");
371 setEntityAttributes(entity, &data);
372
373 RS_DEBUG->print("RS_FilterDXF::addLine: add entity");
374
375 if (currentContainer) currentContainer->addEntity(entity);
376
377 RS_DEBUG->print("RS_FilterDXF::addLine: OK");
378 }
379
380
381 /**
382 * Implementation of the method which handles ray entities.
383 */
addRay(const DRW_Ray & data)384 void RS_FilterDXFRW::addRay(const DRW_Ray& data) {
385 RS_DEBUG->print("RS_FilterDXF::addRay");
386
387 RS_Vector v1{data.basePoint.x, data.basePoint.y};
388 RS_Vector v2{data.basePoint.x+data.secPoint.x,
389 data.basePoint.y+data.secPoint.y};
390
391 RS_DEBUG->print("RS_FilterDXF::addRay: create line");
392
393 if (!currentContainer) {
394 RS_DEBUG->print("RS_FilterDXF::addRay: currentContainer is nullptr");
395 }
396
397 RS_Line* entity = new RS_Line{currentContainer, {v1, v2}};
398 RS_DEBUG->print("RS_FilterDXF::addRay: set attributes");
399 setEntityAttributes(entity, &data);
400
401 RS_DEBUG->print("RS_FilterDXF::addRay: add entity");
402
403 if (currentContainer) currentContainer->addEntity(entity);
404
405 RS_DEBUG->print("RS_FilterDXF::addRay: OK");
406 }
407
408
409 /**
410 * Implementation of the method which handles line entities.
411 */
addXline(const DRW_Xline & data)412 void RS_FilterDXFRW::addXline(const DRW_Xline& data) {
413 RS_DEBUG->print("RS_FilterDXF::addXline");
414
415 RS_Vector v1(data.basePoint.x, data.basePoint.y);
416 RS_Vector v2(data.basePoint.x+data.secPoint.x, data.basePoint.y+data.secPoint.y);
417
418 RS_DEBUG->print("RS_FilterDXF::addXline: create line");
419
420 if (!currentContainer) {
421 RS_DEBUG->print("RS_FilterDXF::addXline: currentContainer is nullptr");
422 }
423
424 RS_Line* entity = new RS_Line{currentContainer, {v1, v2}};
425 RS_DEBUG->print("RS_FilterDXF::addXline: set attributes");
426 setEntityAttributes(entity, &data);
427
428 RS_DEBUG->print("RS_FilterDXF::addXline: add entity");
429
430 if (currentContainer) currentContainer->addEntity(entity);
431
432 RS_DEBUG->print("RS_FilterDXF::addXline: OK");
433 }
434
435
436
437 /**
438 * Implementation of the method which handles circle entities.
439 */
addCircle(const DRW_Circle & data)440 void RS_FilterDXFRW::addCircle(const DRW_Circle& data) {
441 RS_DEBUG->print("RS_FilterDXF::addCircle");
442
443 RS_Vector v{data.basePoint.x, data.basePoint.y};
444 RS_Circle* entity = new RS_Circle(currentContainer, {v, data.radious});
445 setEntityAttributes(entity, &data);
446
447 currentContainer->addEntity(entity);
448 }
449
450
451
452 /**
453 * Implementation of the method which handles arc entities.
454 *
455 * @param angle1 Start angle in deg (!)
456 * @param angle2 End angle in deg (!)
457 */
addArc(const DRW_Arc & data)458 void RS_FilterDXFRW::addArc(const DRW_Arc& data) {
459 RS_DEBUG->print("RS_FilterDXF::addArc");
460 RS_Vector v(data.basePoint.x, data.basePoint.y);
461 RS_ArcData d(v, data.radious,
462 data.staangle,
463 data.endangle,
464 false);
465 RS_Arc* entity = new RS_Arc(currentContainer, d);
466 setEntityAttributes(entity, &data);
467
468 currentContainer->addEntity(entity);
469 }
470
471
472
473 /**
474 * Implementation of the method which handles ellipse entities.
475 *
476 * @param angle1 Start angle in rad (!)
477 * @param angle2 End angle in rad (!)
478 */
addEllipse(const DRW_Ellipse & data)479 void RS_FilterDXFRW::addEllipse(const DRW_Ellipse& data) {
480 RS_DEBUG->print("RS_FilterDXFRW::addEllipse");
481
482 RS_Vector v1(data.basePoint.x, data.basePoint.y);
483 RS_Vector v2(data.secPoint.x, data.secPoint.y);
484 double ang2 = data.endparam;
485 if (fabs(ang2 - 2.*M_PI) < RS_TOLERANCE &&
486 fabs(data.staparam) < RS_TOLERANCE)
487 ang2 = 0.;
488 RS_Ellipse* entity = new RS_Ellipse{currentContainer,
489 {v1, v2,
490 data.ratio,
491 data.staparam, ang2, false}};
492 setEntityAttributes(entity, &data);
493
494 currentContainer->addEntity(entity);
495 }
496
497
498 /**
499 * Implementation of the method which handles trace entities.
500 */
addTrace(const DRW_Trace & data)501 void RS_FilterDXFRW::addTrace(const DRW_Trace& data) {
502 RS_Solid* entity;
503 RS_Vector v1{data.basePoint.x, data.basePoint.y};
504 RS_Vector v2{data.secPoint.x, data.secPoint.y};
505 RS_Vector v3{data.thirdPoint.x, data.thirdPoint.y};
506 RS_Vector v4{data.fourPoint.x, data.fourPoint.y};
507 if (v3 == v4)
508 entity = new RS_Solid(currentContainer, RS_SolidData(v1, v2, v3));
509 else
510 entity = new RS_Solid(currentContainer, RS_SolidData(v1, v2, v3,v4));
511
512 setEntityAttributes(entity, &data);
513 currentContainer->addEntity(entity);
514 }
515
516 /**
517 * Implementation of the method which handles solid entities.
518 */
addSolid(const DRW_Solid & data)519 void RS_FilterDXFRW::addSolid(const DRW_Solid& data) {
520 addTrace(data);
521 }
522
523 /**
524 * Implementation of the method which handles lightweight polyline entities.
525 */
addLWPolyline(const DRW_LWPolyline & data)526 void RS_FilterDXFRW::addLWPolyline(const DRW_LWPolyline& data) {
527 RS_DEBUG->print("RS_FilterDXFRW::addLWPolyline");
528 if (data.vertlist.empty())
529 return;
530 RS_PolylineData d(RS_Vector{},
531 RS_Vector{},
532 data.flags&0x1);
533 RS_Polyline *polyline = new RS_Polyline(currentContainer, d);
534 setEntityAttributes(polyline, &data);
535
536 std::vector< std::pair<RS_Vector, double> > verList;
537 for (auto const& v: data.vertlist)
538 verList.emplace_back(std::make_pair(RS_Vector{v->x, v->y}, v->bulge));
539
540 polyline->appendVertexs(verList);
541
542 currentContainer->addEntity(polyline);
543 }
544
545
546 /**
547 * Implementation of the method which handles polyline entities.
548 */
addPolyline(const DRW_Polyline & data)549 void RS_FilterDXFRW::addPolyline(const DRW_Polyline& data) {
550 RS_DEBUG->print("RS_FilterDXFRW::addPolyline");
551 if ( data.flags&0x10)
552 return; //the polyline is a polygon mesh, not handled
553
554 if ( data.flags&0x40)
555 return; //the polyline is a poliface mesh, TODO convert
556
557 RS_PolylineData d(RS_Vector{},
558 RS_Vector{},
559 data.flags&0x1);
560 RS_Polyline *polyline = new RS_Polyline(currentContainer, d);
561 setEntityAttributes(polyline, &data);
562
563 std::vector< std::pair<RS_Vector, double> > verList;
564
565 for (auto const& v: data.vertlist)
566 verList.emplace_back(
567 std::make_pair(RS_Vector{v->basePoint.x, v->basePoint.y},
568 v->bulge));
569
570 polyline->appendVertexs(verList);
571
572 currentContainer->addEntity(polyline);
573 }
574
575
576 /**
577 * Implementation of the method which handles splines.
578 */
addSpline(const DRW_Spline * data)579 void RS_FilterDXFRW::addSpline(const DRW_Spline* data) {
580 RS_DEBUG->print("RS_FilterDXFRW::addSpline: degree: %d", data->degree);
581
582 if(data->degree == 2)
583 {
584 LC_SplinePoints* splinePoints;
585 LC_SplinePointsData d(((data->flags&0x1)==0x1), true);
586 splinePoints = new LC_SplinePoints(currentContainer, d);
587 setEntityAttributes(splinePoints, data);
588 currentContainer->addEntity(splinePoints);
589
590 for(auto const& vert: data->controllist) {
591 RS_Vector v(vert->x, vert->y);
592 splinePoints->addControlPoint(v);
593 }
594 splinePoints->update();
595 return;
596 }
597
598 RS_Spline* spline;
599 if (data->degree>=1 && data->degree<=3) {
600 RS_SplineData d(data->degree, ((data->flags&0x1)==0x1));
601 if (data->knotslist.size())
602 d.knotslist = data->knotslist;
603 spline = new RS_Spline(currentContainer, d);
604 setEntityAttributes(spline, data);
605
606 currentContainer->addEntity(spline);
607 } else {
608 RS_DEBUG->print(RS_Debug::D_WARNING,
609 "RS_FilterDXF::addSpline: Invalid degree for spline: %d. "
610 "Accepted values are 1..3.", data->degree);
611 return;
612 }
613 for (auto const& vert: data->controllist)
614 spline->addControlPoint({vert->x, vert->y});
615
616 if (data->ncontrol== 0 && data->degree != 2){
617 for (auto const& vert: data->fitlist)
618 spline->addControlPoint({vert->x, vert->y});
619
620 }
621 spline->update();
622 }
623
624
625 /**
626 * Implementation of the method which handles inserts.
627 */
addInsert(const DRW_Insert & data)628 void RS_FilterDXFRW::addInsert(const DRW_Insert& data) {
629
630 RS_DEBUG->print("RS_FilterDXF::addInsert");
631
632 RS_Vector ip(data.basePoint.x, data.basePoint.y);
633 RS_Vector sc(data.xscale, data.yscale);
634 RS_Vector sp(data.colspace, data.rowspace);
635
636 //cout << "Insert: " << name << " " << ip << " " << cols << "/" << rows << endl;
637
638 RS_InsertData d( QString::fromUtf8(data.name.c_str()),
639 ip, sc, data.angle,
640 data.colcount, data.rowcount,
641 sp, nullptr, RS2::NoUpdate);
642 RS_Insert* entity = new RS_Insert(currentContainer, d);
643 setEntityAttributes(entity, &data);
644 RS_DEBUG->print(" id: %d", entity->getId());
645 // entity->update();
646 currentContainer->addEntity(entity);
647 }
648
649
650
651 /**
652 * Implementation of the method which handles
653 * multi texts (MTEXT).
654 */
addMText(const DRW_MText & data)655 void RS_FilterDXFRW::addMText(const DRW_MText& data) {
656 RS_DEBUG->print("RS_FilterDXF::addMText: %s", data.text.c_str());
657
658 RS_MTextData::VAlign valign;
659 RS_MTextData::HAlign halign;
660 RS_MTextData::MTextDrawingDirection dir;
661 RS_MTextData::MTextLineSpacingStyle lss;
662 QString sty = QString::fromUtf8(data.style.c_str());
663 sty=sty.toLower();
664
665 if (data.textgen<=3) {
666 valign=RS_MTextData::VATop;
667 } else if (data.textgen<=6) {
668 valign=RS_MTextData::VAMiddle;
669 } else {
670 valign=RS_MTextData::VABottom;
671 }
672
673 if (data.textgen%3==1) {
674 halign=RS_MTextData::HALeft;
675 } else if (data.textgen%3==2) {
676 halign=RS_MTextData::HACenter;
677 } else {
678 halign=RS_MTextData::HARight;
679 }
680
681 if (data.alignH==1) {
682 dir = RS_MTextData::LeftToRight;
683 } else if (data.alignH==3) {
684 dir = RS_MTextData::TopToBottom;
685 } else {
686 dir = RS_MTextData::ByStyle;
687 }
688
689 if (data.alignV==1) {
690 lss = RS_MTextData::AtLeast;
691 } else {
692 lss = RS_MTextData::Exact;
693 }
694
695 QString mtext = toNativeString(QString::fromUtf8(data.text.c_str()));
696 // use default style for the drawing:
697 if (sty.isEmpty()) {
698 // japanese, cyrillic:
699 if (codePage=="ANSI_932" || codePage=="ANSI_1251") {
700 sty = "Unicode";
701 } else {
702 sty = textStyle;
703 }
704 } else {
705 sty = fontList.value(sty, sty);
706 }
707
708 RS_DEBUG->print("Text as unicode:");
709 RS_DEBUG->printUnicode(mtext);
710 double interlin = data.interlin;
711 double angle = data.angle*M_PI/180.;
712 RS_Vector ip = RS_Vector(data.basePoint.x, data.basePoint.y);
713
714 //Correct bad alignment of older dxflib or libdxfrw < 0.5.4
715 if (oldMText) {
716 interlin = data.interlin*0.96;
717 if (valign == RS_MTextData::VABottom) {
718 QStringList tl = mtext.split('\n', QString::SkipEmptyParts);
719 if (!tl.isEmpty()) {
720 QString txt = tl.at(tl.size()-1);
721 RS_TextData d(RS_Vector(0.,0.,0.), RS_Vector(0.,0.,0.),
722
723 data.height, 1, RS_TextData::VABaseline, RS_TextData::HALeft,
724 RS_TextData::None, txt, sty, 0,
725 RS2::Update);
726 RS_Text* entity = new RS_Text(nullptr, d);
727 double textTail = entity->getMin().y;
728 delete entity;
729 RS_Vector ot = RS_Vector(0.0,textTail).rotate(angle);
730 ip.move(ot);
731 }
732 }
733 }
734
735 RS_MTextData d(ip, data.height, data.widthscale,
736 valign, halign,
737 dir, lss,
738 interlin,
739 mtext, sty, angle,
740 RS2::NoUpdate);
741 RS_MText* entity = new RS_MText(currentContainer, d);
742
743 setEntityAttributes(entity, &data);
744 entity->update();
745 currentContainer->addEntity(entity);
746 }
747
748
749
750 /**
751 * Implementation of the method which handles
752 * texts (TEXT).
753 */
addText(const DRW_Text & data)754 void RS_FilterDXFRW::addText(const DRW_Text& data) {
755 RS_DEBUG->print("RS_FilterDXFRW::addText");
756 RS_Vector refPoint = RS_Vector(data.basePoint.x, data.basePoint.y);;
757 RS_Vector secPoint = RS_Vector(data.secPoint.x, data.secPoint.y);;
758 double angle = data.angle;
759
760 if (data.alignV !=0 || data.alignH !=0 ||data.alignH ==DRW_Text::HMiddle){
761 if (data.alignH !=DRW_Text::HAligned && data.alignH !=DRW_Text::HFit){
762 secPoint = RS_Vector(data.basePoint.x, data.basePoint.y);
763 refPoint = RS_Vector(data.secPoint.x, data.secPoint.y);
764 }
765 }
766
767 RS_TextData::VAlign valign = (RS_TextData::VAlign)data.alignV;
768 RS_TextData::HAlign halign = (RS_TextData::HAlign)data.alignH;
769 RS_TextData::TextGeneration dir;
770 QString sty = QString::fromUtf8(data.style.c_str());
771 sty=sty.toLower();
772
773 if (data.textgen==2) {
774 dir = RS_TextData::Backward;
775 } else if (data.textgen==4) {
776 dir = RS_TextData::UpsideDown;
777 } else {
778 dir = RS_TextData::None;
779 }
780
781 QString mtext = toNativeString(QString::fromUtf8(data.text.c_str()));
782 // use default style for the drawing:
783 if (sty.isEmpty()) {
784 // japanese, cyrillic:
785 if (codePage=="ANSI_932" || codePage=="ANSI_1251") {
786 sty = "Unicode";
787 } else {
788 sty = textStyle;
789 }
790 } else {
791 sty = fontList.value(sty, sty);
792 }
793
794 RS_DEBUG->print("Text as unicode:");
795 RS_DEBUG->printUnicode(mtext);
796
797 RS_TextData d(refPoint, secPoint, data.height, data.widthscale,
798 valign, halign, dir,
799 mtext, sty, angle*M_PI/180,
800 RS2::NoUpdate);
801 RS_Text* entity = new RS_Text(currentContainer, d);
802
803 setEntityAttributes(entity, &data);
804 entity->update();
805 currentContainer->addEntity(entity);
806 }
807
808
809
810 /**
811 * Implementation of the method which handles
812 * dimensions (DIMENSION).
813 */
convDimensionData(const DRW_Dimension * data)814 RS_DimensionData RS_FilterDXFRW::convDimensionData(const DRW_Dimension* data) {
815
816 DRW_Coord crd = data->getDefPoint();
817 RS_Vector defP(crd.x, crd.y);
818 crd = data->getTextPoint();
819 RS_Vector midP(crd.x, crd.y);
820 RS_MTextData::VAlign valign;
821 RS_MTextData::HAlign halign;
822 RS_MTextData::MTextLineSpacingStyle lss;
823 QString sty = QString::fromUtf8(data->getStyle().c_str());
824
825 QString t; //= data.text;
826
827 // middlepoint of text can be 0/0 which is considered to be invalid (!):
828 // 0/0 because older QCad versions save the middle of the text as 0/0
829 // although they didn't support saving of the middle of the text.
830 if (fabs(crd.x)<1.0e-6 && fabs(crd.y)<1.0e-6) {
831 midP = RS_Vector(false);
832 }
833
834 if (data->getAlign()<=3) {
835 valign=RS_MTextData::VATop;
836 } else if (data->getAlign()<=6) {
837 valign=RS_MTextData::VAMiddle;
838 } else {
839 valign=RS_MTextData::VABottom;
840 }
841
842 if (data->getAlign()%3==1) {
843 halign=RS_MTextData::HALeft;
844 } else if (data->getAlign()%3==2) {
845 halign=RS_MTextData::HACenter;
846 } else {
847 halign=RS_MTextData::HARight;
848 }
849
850 if (data->getTextLineStyle()==1) {
851 lss = RS_MTextData::AtLeast;
852 } else {
853 lss = RS_MTextData::Exact;
854 }
855
856 t = toNativeString(QString::fromUtf8( data->getText().c_str() ));
857
858 if (sty.isEmpty()) {
859 sty = dimStyle;
860 }
861
862 RS_DEBUG->print("Text as unicode:");
863 RS_DEBUG->printUnicode(t);
864
865 // data needed to add the actual dimension entity
866 return RS_DimensionData(defP, midP,
867 valign, halign,
868 lss,
869 data->getTextLineFactor(),
870 t, sty, data->getDir());
871 }
872
873
874
875 /**
876 * Implementation of the method which handles
877 * aligned dimensions (DIMENSION).
878 */
addDimAlign(const DRW_DimAligned * data)879 void RS_FilterDXFRW::addDimAlign(const DRW_DimAligned *data) {
880 RS_DEBUG->print("RS_FilterDXFRW::addDimAligned");
881
882 RS_DimensionData dimensionData = convDimensionData((DRW_Dimension*)data);
883
884 RS_Vector ext1(data->getDef1Point().x, data->getDef1Point().y);
885 RS_Vector ext2(data->getDef2Point().x, data->getDef2Point().y);
886
887 RS_DimAlignedData d(ext1, ext2);
888
889 RS_DimAligned* entity = new RS_DimAligned(currentContainer,
890 dimensionData, d);
891 setEntityAttributes(entity, data);
892 entity->updateDimPoint();
893 entity->update();
894 currentContainer->addEntity(entity);
895 }
896
897
898
899 /**
900 * Implementation of the method which handles
901 * linear dimensions (DIMENSION).
902 */
addDimLinear(const DRW_DimLinear * data)903 void RS_FilterDXFRW::addDimLinear(const DRW_DimLinear *data) {
904 RS_DEBUG->print("RS_FilterDXFRW::addDimLinear");
905
906 RS_DimensionData dimensionData = convDimensionData((DRW_Dimension*)data);
907
908 RS_Vector dxt1(data->getDef1Point().x, data->getDef1Point().y);
909 RS_Vector dxt2(data->getDef2Point().x, data->getDef2Point().y);
910
911 RS_DimLinearData d(dxt1, dxt2, RS_Math::deg2rad(data->getAngle()),
912 RS_Math::deg2rad(data->getOblique()));
913
914 RS_DimLinear* entity = new RS_DimLinear(currentContainer,
915 dimensionData, d);
916 setEntityAttributes(entity, data);
917 entity->update();
918 currentContainer->addEntity(entity);
919 }
920
921
922
923 /**
924 * Implementation of the method which handles
925 * radial dimensions (DIMENSION).
926 */
addDimRadial(const DRW_DimRadial * data)927 void RS_FilterDXFRW::addDimRadial(const DRW_DimRadial* data) {
928 RS_DEBUG->print("RS_FilterDXFRW::addDimRadial");
929
930 RS_DimensionData dimensionData = convDimensionData((DRW_Dimension*)data);
931 RS_Vector dp(data->getDiameterPoint().x, data->getDiameterPoint().y);
932
933 RS_DimRadialData d(dp, data->getLeaderLength());
934
935 RS_DimRadial* entity = new RS_DimRadial(currentContainer,
936 dimensionData, d);
937
938 setEntityAttributes(entity, data);
939 entity->update();
940 currentContainer->addEntity(entity);
941 }
942
943
944
945 /**
946 * Implementation of the method which handles
947 * diametric dimensions (DIMENSION).
948 */
addDimDiametric(const DRW_DimDiametric * data)949 void RS_FilterDXFRW::addDimDiametric(const DRW_DimDiametric* data) {
950 RS_DEBUG->print("RS_FilterDXFRW::addDimDiametric");
951
952 RS_DimensionData dimensionData = convDimensionData((DRW_Dimension*)data);
953 RS_Vector dp(data->getDiameter1Point().x, data->getDiameter1Point().y);
954
955 RS_DimDiametricData d(dp, data->getLeaderLength());
956
957 RS_DimDiametric* entity = new RS_DimDiametric(currentContainer,
958 dimensionData, d);
959
960 setEntityAttributes(entity, data);
961 entity->update();
962 currentContainer->addEntity(entity);
963 }
964
965
966
967 /**
968 * Implementation of the method which handles
969 * angular dimensions (DIMENSION).
970 */
addDimAngular(const DRW_DimAngular * data)971 void RS_FilterDXFRW::addDimAngular(const DRW_DimAngular* data) {
972 RS_DEBUG->print("RS_FilterDXFRW::addDimAngular");
973
974 RS_DimensionData dimensionData = convDimensionData(data);
975 RS_Vector dp1(data->getFirstLine1().x, data->getFirstLine1().y);
976 RS_Vector dp2(data->getFirstLine2().x, data->getFirstLine2().y);
977 RS_Vector dp3(data->getSecondLine1().x, data->getSecondLine1().y);
978 RS_Vector dp4(data->getDimPoint().x, data->getDimPoint().y);
979
980 RS_DimAngularData d(dp1, dp2, dp3, dp4);
981
982 RS_DimAngular* entity = new RS_DimAngular(currentContainer,
983 dimensionData, d);
984
985 setEntityAttributes(entity, data);
986 entity->update();
987 currentContainer->addEntity(entity);
988 }
989
990
991
992 /**
993 * Implementation of the method which handles
994 * angular dimensions (DIMENSION).
995 */
addDimAngular3P(const DRW_DimAngular3p * data)996 void RS_FilterDXFRW::addDimAngular3P(const DRW_DimAngular3p* data) {
997 RS_DEBUG->print("RS_FilterDXFRW::addDimAngular3P");
998
999 RS_DimensionData dimensionData = convDimensionData(data);
1000 RS_Vector dp1(data->getFirstLine().x, data->getFirstLine().y);
1001 RS_Vector dp2(data->getSecondLine().x, data->getSecondLine().y);
1002 RS_Vector dp3(data->getVertexPoint().x, data->getVertexPoint().y);
1003 RS_Vector dp4 = dimensionData.definitionPoint;
1004 dimensionData.definitionPoint = RS_Vector(data->getVertexPoint().x, data->getVertexPoint().y);
1005
1006 RS_DimAngularData d(dp1, dp2, dp3, dp4);
1007
1008 RS_DimAngular* entity = new RS_DimAngular(currentContainer,
1009 dimensionData, d);
1010
1011 setEntityAttributes(entity, data);
1012 entity->update();
1013 currentContainer->addEntity(entity);
1014 }
1015
1016
1017
addDimOrdinate(const DRW_DimOrdinate *)1018 void RS_FilterDXFRW::addDimOrdinate(const DRW_DimOrdinate* /*data*/) {
1019 RS_DEBUG->print("RS_FilterDXFRW::addDimOrdinate(const DL_DimensionData&, const DL_DimOrdinateData&) not yet implemented");
1020 }
1021
1022
1023 /**
1024 * Implementation of the method which handles leader entities.
1025 */
addLeader(const DRW_Leader * data)1026 void RS_FilterDXFRW::addLeader(const DRW_Leader *data) {
1027 RS_DEBUG->print("RS_FilterDXFRW::addDimLeader");
1028 RS_LeaderData d(data->arrow!=0);
1029 RS_Leader* leader = new RS_Leader(currentContainer, d);
1030 setEntityAttributes(leader, data);
1031
1032 for (auto const& vert: data->vertexlist)
1033 leader->addVertex({vert->x, vert->y});
1034
1035 leader->update();
1036 currentContainer->addEntity(leader);
1037
1038 }
1039
1040
1041
1042 /**
1043 * Implementation of the method which handles hatch entities.
1044 */
addHatch(const DRW_Hatch * data)1045 void RS_FilterDXFRW::addHatch(const DRW_Hatch *data) {
1046 RS_DEBUG->print("RS_FilterDXF::addHatch()");
1047 RS_Hatch* hatch;
1048 RS_EntityContainer* hatchLoop;
1049
1050 hatch = new RS_Hatch(currentContainer,
1051 RS_HatchData(data->solid, data->scale, data->angle,
1052 QString::fromUtf8(data->name.c_str())));
1053 setEntityAttributes(hatch, data);
1054 currentContainer->appendEntity(hatch);
1055
1056 for (unsigned int i=0; i < data->looplist.size(); i++) {
1057 auto& loop = data->looplist.at(i);
1058 if ((loop->type & 32) == 32) continue;
1059 hatchLoop = new RS_EntityContainer(hatch);
1060 hatchLoop->setLayer(nullptr);
1061 hatch->addEntity(hatchLoop);
1062
1063 RS_Entity* e = nullptr;
1064 if ((loop->type & 2) == 2){ //polyline, convert to lines & arcs
1065 DRW_LWPolyline* pline = (DRW_LWPolyline *)loop->objlist.at(0).get();
1066 RS_Polyline polyline{nullptr,
1067 RS_PolylineData(RS_Vector(false), RS_Vector(false), pline->flags)};
1068 for (auto const& vert: pline->vertlist)
1069 polyline.addVertex(RS_Vector{vert->x, vert->y}, vert->bulge);
1070
1071 for (RS_Entity* e=polyline.firstEntity(); e;
1072 e=polyline.nextEntity()) {
1073 RS_Entity* tmp = e->clone();
1074 tmp->reparent(hatchLoop);
1075 tmp->setLayer(nullptr);
1076 hatchLoop->addEntity(tmp);
1077 }
1078
1079 } else {
1080 for (unsigned int j=0; j<loop->objlist.size(); j++) {
1081 e = nullptr;
1082 auto& ent = loop->objlist.at(j);
1083 switch (ent->eType) {
1084 case DRW::LINE: {
1085 DRW_Line *e2 = (DRW_Line *)ent.get();
1086 e = new RS_Line{hatchLoop,
1087 {{e2->basePoint.x, e2->basePoint.y},
1088 {e2->secPoint.x, e2->secPoint.y}}};
1089 break;
1090 }
1091 case DRW::ARC: {
1092 DRW_Arc *e2 = (DRW_Arc *)ent.get();
1093 if (e2->isccw && e2->staangle<1.0e-6 && e2->endangle>RS_Math::deg2rad(360)-1.0e-6) {
1094 e = new RS_Circle(hatchLoop,
1095 {{e2->basePoint.x, e2->basePoint.y},
1096 e2->radious});
1097 } else {
1098
1099 if (e2->isccw) {
1100 e = new RS_Arc(hatchLoop,
1101 RS_ArcData(RS_Vector(e2->basePoint.x, e2->basePoint.y), e2->radious,
1102 RS_Math::correctAngle(e2->staangle),
1103 RS_Math::correctAngle(e2->endangle),
1104 false));
1105 } else {
1106 e = new RS_Arc(hatchLoop,
1107 RS_ArcData(RS_Vector(e2->basePoint.x, e2->basePoint.y), e2->radious,
1108 RS_Math::correctAngle(2*M_PI-e2->staangle),
1109 RS_Math::correctAngle(2*M_PI-e2->endangle),
1110 true));
1111 }
1112 }
1113 break;
1114 }
1115 case DRW::ELLIPSE: {
1116 DRW_Ellipse *e2 = (DRW_Ellipse *)ent.get();
1117 double ang1 = e2->staparam;
1118 double ang2 = e2->endparam;
1119 if ( fabs(ang2 - 2.*M_PI) < 1.0e-10 && fabs(ang1) < 1.0e-10 )
1120 ang2 = 0.0;
1121 else { //convert angle to parameter
1122 ang1 = atan(tan(ang1)/e2->ratio);
1123 ang2 = atan(tan(ang2)/e2->ratio);
1124 if (ang1 < 0){//quadrant 2 & 4
1125 ang1 +=M_PI;
1126 if (e2->staparam > M_PI) //quadrant 4
1127 ang1 +=M_PI;
1128 } else if (e2->staparam > M_PI){//3 quadrant
1129 ang1 +=M_PI;
1130 }
1131 if (ang2 < 0){//quadrant 2 & 4
1132 ang2 +=M_PI;
1133 if (e2->endparam > M_PI) //quadrant 4
1134 ang2 +=M_PI;
1135 } else if (e2->endparam > M_PI){//3 quadrant
1136 ang2 +=M_PI;
1137 }
1138 }
1139 e = new RS_Ellipse{hatchLoop,
1140 {{e2->basePoint.x, e2->basePoint.y},
1141 {e2->secPoint.x, e2->secPoint.y},
1142 e2->ratio, ang1, ang2, !e2->isccw}};
1143 break;
1144 }
1145 default:
1146 break;
1147 }
1148 if (e) {
1149 e->setLayer(nullptr);
1150 hatchLoop->addEntity(e);
1151 }
1152 }
1153 }
1154
1155 }
1156
1157 RS_DEBUG->print("hatch->update()");
1158 if (hatch->validate()) {
1159 hatch->update();
1160 } else {
1161 graphic->removeEntity(hatch);
1162 RS_DEBUG->print(RS_Debug::D_ERROR,
1163 "RS_FilterDXFRW::endEntity(): updating hatch failed: invalid hatch area");
1164 }
1165 }
1166
1167
1168 /**
1169 * Implementation of the method which handles image entities.
1170 */
addImage(const DRW_Image * data)1171 void RS_FilterDXFRW::addImage(const DRW_Image *data) {
1172 RS_DEBUG->print("RS_FilterDXF::addImage");
1173
1174 RS_Vector ip(data->basePoint.x, data->basePoint.y);
1175 RS_Vector uv(data->secPoint.x, data->secPoint.y);
1176 RS_Vector vv(data->vVector.x, data->vVector.y);
1177 RS_Vector size(data->sizeu, data->sizev);
1178
1179 RS_Image* image = new RS_Image( currentContainer,
1180 RS_ImageData(data->ref, ip, uv, vv, size,
1181 QString(""), data->brightness,
1182 data->contrast, data->fade));
1183
1184 setEntityAttributes(image, data);
1185 currentContainer->appendEntity(image);
1186 }
1187
1188
1189
1190 /**
1191 * Implementation of the method which links image entities to image files.
1192 */
linkImage(const DRW_ImageDef * data)1193 void RS_FilterDXFRW::linkImage(const DRW_ImageDef *data) {
1194 RS_DEBUG->print("RS_FilterDXFRW::linkImage");
1195
1196 int handle = data->handle;
1197 QString sfile(QString::fromUtf8(data->name.c_str()));
1198 QFileInfo fiDxf(file);
1199 QFileInfo fiBitmap(sfile);
1200
1201 // try to find the image file:
1202
1203 // first: absolute path:
1204 if (!fiBitmap.exists()) {
1205 RS_DEBUG->print("File %s doesn't exist.",
1206 (const char*)QFile::encodeName(sfile));
1207 // try relative path:
1208 QString f1 = fiDxf.absolutePath() + "/" + sfile;
1209 if (QFileInfo(f1).exists()) {
1210 sfile = f1;
1211 } else {
1212 RS_DEBUG->print("File %s doesn't exist.", (const char*)QFile::encodeName(f1));
1213 // try drawing path:
1214 QString f2 = fiDxf.absolutePath() + "/" + fiBitmap.fileName();
1215 if (QFileInfo(f2).exists()) {
1216 sfile = f2;
1217 } else {
1218 RS_DEBUG->print("File %s doesn't exist.", (const char*)QFile::encodeName(f2));
1219 }
1220 }
1221 }
1222
1223 // Also link images in subcontainers (e.g. inserts):
1224 for (RS_Entity* e=graphic->firstEntity(RS2::ResolveNone);
1225 e; e=graphic->nextEntity(RS2::ResolveNone)) {
1226 if (e->rtti()==RS2::EntityImage) {
1227 RS_Image* img = (RS_Image*)e;
1228 if (img->getHandle()==handle) {
1229 img->setFile(sfile);
1230 RS_DEBUG->print("image found: %s", (const char*)QFile::encodeName(img->getFile()));
1231 img->update();
1232 }
1233 }
1234 }
1235
1236 // update images in blocks:
1237 for (unsigned i=0; i<graphic->countBlocks(); ++i) {
1238 RS_Block* b = graphic->blockAt(i);
1239 for (RS_Entity* e=b->firstEntity(RS2::ResolveNone);
1240 e; e=b->nextEntity(RS2::ResolveNone)) {
1241 if (e->rtti()==RS2::EntityImage) {
1242 RS_Image* img = (RS_Image*)e;
1243 if (img->getHandle()==handle) {
1244 img->setFile(sfile);
1245 RS_DEBUG->print("image in block found: %s",
1246 (const char*)QFile::encodeName(img->getFile()));
1247 img->update();
1248 }
1249 }
1250 }
1251 }
1252 RS_DEBUG->print("linking image: OK");
1253 }
1254
1255 using std::map;
1256 /**
1257 * Sets the header variables from the DXF file.
1258 */
addHeader(const DRW_Header * data)1259 void RS_FilterDXFRW::addHeader(const DRW_Header* data){
1260 RS_Graphic* container = nullptr;
1261 if (currentContainer->rtti()==RS2::EntityGraphic) {
1262 container = (RS_Graphic*)currentContainer;
1263 } else return;
1264
1265 map<std::string,DRW_Variant *>::const_iterator it;
1266 for ( it=data->vars.begin() ; it != data->vars.end(); ++it ){
1267 QString key = QString::fromStdString((*it).first);
1268 DRW_Variant *var = (*it).second;
1269 switch (var->type()) {
1270 case DRW_Variant::COORD:
1271 container->addVariable(key,
1272 RS_Vector(var->content.v->x, var->content.v->y, var->content.v->z), var->code());
1273 break;
1274 case DRW_Variant::STRING:
1275 container->addVariable(key, QString::fromUtf8(var->content.s->c_str()), var->code());
1276 break;
1277 case DRW_Variant::INTEGER:
1278 container->addVariable(key, var->content.i, var->code());
1279 break;
1280 case DRW_Variant::DOUBLE:
1281 container->addVariable(key, var->content.d, var->code());
1282 break;
1283 default:
1284 break;
1285 }
1286
1287 }
1288 codePage = graphic->getVariableString("$DWGCODEPAGE", "ANSI_1252");
1289 textStyle = graphic->getVariableString("$TEXTSTYLE", "Standard");
1290 dimStyle = graphic->getVariableString("$DIMSTYLE", "Standard");
1291 //initialize units vars if not are present in dxf file
1292 graphic->getVariableInt("$LUNITS", 2);
1293 graphic->getVariableInt("$LUPREC", 4);
1294 graphic->getVariableInt("$AUNITS", 0);
1295 graphic->getVariableInt("$AUPREC", 4);
1296
1297
1298 QString acadver = versionStr = graphic->getVariableString("$ACADVER", "");
1299 acadver.replace(QRegExp("[a-zA-Z]"), "");
1300 bool ok;
1301 version=acadver.toInt(&ok);
1302 if (!ok) { version = 1021;}
1303
1304 //detect if dxf lib are a old dxflib or libdxfrw < 0.5.4 (used to correct mtext alignment)
1305 oldMText = false;
1306 isLibDxfRw = false;
1307 libDxfRwVersion = 0;
1308 QStringList commentList = QString::fromStdString( data->getComments()).split('\n',QString::SkipEmptyParts);
1309 for( auto commentLine: commentList) {
1310 QStringList commentWords = commentLine.split(' ',QString::SkipEmptyParts);
1311 if( 0 < commentWords.size()) {
1312 if( "dxflib" == commentWords.at(0)) {
1313 oldMText = true;
1314 break;
1315 } else if( "dxfrw" == commentWords.at(0)) {
1316 QStringList libVersionList = commentWords.at(1).split('.',QString::SkipEmptyParts);
1317 if( 2 < libVersionList.size()) {
1318 isLibDxfRw = true;
1319 libDxfRwVersion = LIBDXFRW_VERSION( libVersionList.at(0).toInt(),
1320 libVersionList.at(1).toInt(),
1321 libVersionList.at(2).toInt() );
1322 if( libDxfRwVersion < LIBDXFRW_VERSION( 0, 5, 4)) {
1323 oldMText = true;
1324 }
1325 }
1326 break;
1327 }
1328 }
1329 }
1330 }
1331
1332
1333 /**
1334 * Implementation of the method used for RS_Export to communicate
1335 * with this filter.
1336 *
1337 * @param file Full path to the DXF file that will be written.
1338 */
fileExport(RS_Graphic & g,const QString & file,RS2::FormatType type)1339 bool RS_FilterDXFRW::fileExport(RS_Graphic& g, const QString& file, RS2::FormatType type) {
1340
1341 RS_DEBUG->print("RS_FilterDXFDW::fileExport: exporting file '%s'...",
1342 (const char*)QFile::encodeName(file));
1343 RS_DEBUG->print("RS_FilterDXFDW::fileExport: file type '%d'", (int)type);
1344
1345 this->graphic = &g;
1346
1347 // check if we can write to that directory:
1348 #ifndef Q_OS_WIN
1349
1350 QString path = QFileInfo(file).absolutePath();
1351 if (QFileInfo(path).isWritable()==false) {
1352 RS_DEBUG->print("RS_FilterDXFRW::fileExport: can't write file: "
1353 "no permission");
1354 return false;
1355 }
1356 //
1357 #endif
1358
1359 // set version for DXF filter:
1360 exactColor = false;
1361 DRW::Version exportVersion;
1362 if (type==RS2::FormatDXFRW12) {
1363 exportVersion = DRW::AC1009;
1364 version = 1009;
1365 } else if (type==RS2::FormatDXFRW14) {
1366 exportVersion = DRW::AC1014;
1367 version = 1014;
1368 } else if (type==RS2::FormatDXFRW2000) {
1369 exportVersion = DRW::AC1015;
1370 version = 1015;
1371 } else if (type==RS2::FormatDXFRW2004) {
1372 exportVersion = DRW::AC1018;
1373 version = 1018;
1374 exactColor = true;
1375 } else {
1376 exportVersion = DRW::AC1021;
1377 version = 1021;
1378 exactColor = true;
1379 }
1380
1381 dxfW = new dxfRW(QFile::encodeName(file));
1382 bool success = dxfW->write(this, exportVersion, false); //ascii
1383 // bool success = dxf->write(this, exportVersion, true); //binary
1384 delete dxfW;
1385
1386 if (!success) {
1387 RS_DEBUG->print("RS_FilterDXFDW::fileExport: can't write file");
1388 return false;
1389 }
1390 /*RLZ pte*/
1391 /* RS_DEBUG->print("writing tables...");
1392 dw->sectionTables();
1393 // VPORT:
1394 dxf.writeVPort(*dw);
1395 dw->tableEnd();
1396
1397 // VIEW:
1398 RS_DEBUG->print("writing views...");
1399 dxf.writeView(*dw);
1400
1401 // UCS:
1402 RS_DEBUG->print("writing ucs...");
1403 dxf.writeUcs(*dw);
1404
1405 // Appid:
1406 RS_DEBUG->print("writing appid...");
1407 dw->tableAppid(1);
1408 writeAppid(*dw, "ACAD");
1409 dw->tableEnd();
1410 */
1411 return success;
1412 }
1413
1414 /**
1415 * Prepare unnamed blocks.
1416 */
prepareBlocks()1417 void RS_FilterDXFRW::prepareBlocks() {
1418 RS_Block *blk;
1419 int dimNum = 0, hatchNum= 0;
1420 QString prefix, sufix;
1421
1422 //check for existing *D?? or *U??
1423 for (unsigned i = 0; i < graphic->countBlocks(); i++) {
1424 blk = graphic->blockAt(i);
1425 prefix = blk->getName().left(2).toUpper();
1426 sufix = blk->getName().mid(2);
1427 if (prefix == "*D") {
1428 if (sufix.toInt() > dimNum) dimNum = sufix.toInt();
1429 } else if (prefix == "*U") {
1430 if (sufix.toInt() > hatchNum) hatchNum = sufix.toInt();
1431 }
1432 }
1433 //Add a name to each dimension, in dxfR12 also for hatches
1434 for (RS_Entity *e = graphic->firstEntity(RS2::ResolveNone);
1435 e ; e = graphic->nextEntity(RS2::ResolveNone)) {
1436 if ( !(e->getFlag(RS2::FlagUndone)) ) {
1437 switch (e->rtti()) {
1438 case RS2::EntityDimLinear:
1439 case RS2::EntityDimAligned:
1440 case RS2::EntityDimAngular:
1441 case RS2::EntityDimRadial:
1442 case RS2::EntityDimDiametric:
1443 case RS2::EntityDimLeader:
1444 prefix = "*D" + QString::number(++dimNum);
1445 noNameBlock[e] = prefix;
1446 break;
1447 case RS2::EntityHatch:
1448 if (version==1009) {
1449 if ( !((RS_Hatch*)e)->isSolid() ) {
1450 prefix = "*U" + QString::number(++hatchNum);
1451 noNameBlock[e] = prefix;
1452 }
1453 }
1454 break;
1455 default:
1456 break;
1457 }//end switch
1458 }//end if !RS2::FlagUndone
1459 }
1460 }
1461
1462 /**
1463 * Writes block records (just the name, not the entities in it).
1464 */
writeBlockRecords()1465 void RS_FilterDXFRW::writeBlockRecords(){
1466 //first prepare and send unnamed blocks, the while loop can be omitted for R12
1467 prepareBlocks();
1468 QHash<RS_Entity*, QString>::const_iterator it = noNameBlock.constBegin();
1469 while (it != noNameBlock.constEnd()) {
1470 dxfW->writeBlockRecord(it.value().toStdString());
1471 ++it;
1472 }
1473
1474 //next send "normal" blocks
1475 RS_Block *blk;
1476 for (unsigned i = 0; i < graphic->countBlocks(); i++) {
1477 blk = graphic->blockAt(i);
1478 if (!blk->isUndone()){
1479 RS_DEBUG->print("writing block record: %s", (const char*)blk->getName().toLocal8Bit());
1480 dxfW->writeBlockRecord(blk->getName().toUtf8().data());
1481 }
1482 }
1483 }
1484
1485 /**
1486 * Writes blocks.
1487 */
writeBlocks()1488 void RS_FilterDXFRW::writeBlocks() {
1489 RS_Block *blk;
1490
1491 //write unnamed blocks
1492 QHash<RS_Entity*, QString>::const_iterator it = noNameBlock.constBegin();
1493 while (it != noNameBlock.constEnd()) {
1494 DRW_Block block;
1495 block.name = it.value().toStdString();
1496 block.basePoint.x = 0.0;
1497 block.basePoint.y = 0.0;
1498 block.basePoint.z = 0.0;
1499 block.flags = 1;//flag for unnamed block
1500 dxfW->writeBlock(&block);
1501 RS_EntityContainer *ct = (RS_EntityContainer *)it.key();
1502 for (RS_Entity* e=ct->firstEntity(RS2::ResolveNone);
1503 e; e=ct->nextEntity(RS2::ResolveNone)) {
1504 if ( !(e->getFlag(RS2::FlagUndone)) ) {
1505 writeEntity(e);
1506 }
1507 }
1508 ++it;
1509 }
1510
1511 //next write "normal" blocks
1512 for (unsigned i = 0; i < graphic->countBlocks(); i++) {
1513 blk = graphic->blockAt(i);
1514 if (!blk->isUndone()) {
1515 RS_DEBUG->print("writing block: %s", (const char*)blk->getName().toLocal8Bit());
1516
1517 DRW_Block block;
1518 block.name = blk->getName().toUtf8().data();
1519 block.basePoint.x = blk->getBasePoint().x;
1520 block.basePoint.y = blk->getBasePoint().y;
1521 block.basePoint.z = blk->getBasePoint().z;
1522 dxfW->writeBlock(&block);
1523 for (RS_Entity* e=blk->firstEntity(RS2::ResolveNone);
1524 e; e=blk->nextEntity(RS2::ResolveNone)) {
1525 if ( !(e->getFlag(RS2::FlagUndone)) ) {
1526 writeEntity(e);
1527 }
1528 }
1529 }
1530 }
1531 }
1532
1533
writeHeader(DRW_Header & data)1534 void RS_FilterDXFRW::writeHeader(DRW_Header& data){
1535 RS_Vector v;
1536 /*TODO $ISOMETRICGRID == $SNAPSTYLE and "GRID on/off" not handled because is part of
1537 active vport to save is required read/write VPORT table */
1538 QHash<QString, RS_Variable>vars = graphic->getVariableDict();
1539 QHash<QString, RS_Variable>::iterator it = vars.begin();
1540 if (!vars.contains ( "$DWGCODEPAGE" )) {
1541 //RLZ: TODO verify this
1542 codePage = RS_SYSTEM->localeToISO(QLocale::system().name().toLocal8Bit());
1543 // RS_Variable v( QString(RS_SYSTEM->localeToISO(QLocale::system().name().toLocal8Bit())),0 );
1544 vars.insert(QString("$DWGCODEPAGE"), RS_Variable(codePage, 0) );
1545 }
1546
1547 while (it != vars.end()) {
1548 switch (it.value().getType()) {
1549 case RS2::VariableInt:
1550 data.addInt(it.key().toStdString(), it.value().getInt(), it.value().getCode());
1551 break;
1552 case RS2::VariableDouble:
1553 data.addDouble(it.key().toStdString(), it.value().getDouble(), it.value().getCode());
1554 break;
1555 case RS2::VariableString:
1556 data.addStr(it.key().toStdString(), it.value().getString().toUtf8().data(), it.value().getCode());
1557 break;
1558 case RS2::VariableVector:
1559 v = it.value().getVector();
1560 data.addCoord(it.key().toStdString(), DRW_Coord(v.x, v.y, v.z), it.value().getCode());
1561 break;
1562 default:
1563 break;
1564 }
1565 ++it;
1566 }
1567 v = graphic->getMin();
1568 data.addCoord("$EXTMIN", DRW_Coord(v.x, v.y, 0.0), 0);
1569 v = graphic->getMax();
1570 data.addCoord("$EXTMAX", DRW_Coord(v.x, v.y, 0.0), 0);
1571
1572 //when saving a block, there is no active layer. ignore it to avoid crash
1573 if(graphic->getActiveLayer()==0) return;
1574 data.addStr("$CLAYER", (graphic->getActiveLayer()->getName()).toUtf8().data(), 8);
1575 }
1576
writeLTypes()1577 void RS_FilterDXFRW::writeLTypes(){
1578 DRW_LType ltype;
1579 // Standard linetypes for LibreCAD / AutoCAD
1580 ltype.name = "CONTINUOUS";
1581 ltype.desc = "Solid line";
1582 dxfW->writeLineType(<ype);
1583 ltype.name = "ByLayer";
1584 dxfW->writeLineType(<ype);
1585 ltype.name = "ByBlock";
1586 dxfW->writeLineType(<ype);
1587
1588 ltype.name = "DOT";
1589 ltype.desc = "Dot . . . . . . . . . . . . . . . . . . . . . .";
1590 ltype.size = 2;
1591 ltype.length = 6.35;
1592 ltype.path.push_back(0.0);
1593 ltype.path.push_back(-6.35);
1594 dxfW->writeLineType(<ype);
1595
1596 ltype.path.clear();
1597 ltype.name = "DOTTINY";
1598 ltype.desc = "Dot (.15x) .....................................";
1599 ltype.size = 2;
1600 ltype.length = 0.9525;
1601 ltype.path.push_back(0.0);
1602 ltype.path.push_back(-0.9525);
1603 dxfW->writeLineType(<ype);
1604
1605 ltype.path.clear();
1606 ltype.name = "DOT2";
1607 ltype.desc = "Dot (.5x) .....................................";
1608 ltype.size = 2;
1609 ltype.length = 3.175;
1610 ltype.path.push_back(0.0);
1611 ltype.path.push_back(-3.175);
1612 dxfW->writeLineType(<ype);
1613
1614 ltype.path.clear();
1615 ltype.name = "DOTX2";
1616 ltype.desc = "Dot (2x) . . . . . . . . . . . . .";
1617 ltype.size = 2;
1618 ltype.length = 12.7;
1619 ltype.path.push_back(0.0);
1620 ltype.path.push_back(-12.7);
1621 dxfW->writeLineType(<ype);
1622
1623 ltype.path.clear();
1624 ltype.name = "DASHED";
1625 ltype.desc = "Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _";
1626 ltype.size = 2;
1627 ltype.length = 19.05;
1628 ltype.path.push_back(12.7);
1629 ltype.path.push_back(-6.35);
1630 dxfW->writeLineType(<ype);
1631
1632 ltype.path.clear();
1633 ltype.name = "DASHEDTINY";
1634 ltype.desc = "Dashed (.15x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _";
1635 ltype.size = 2;
1636 ltype.length = 2.8575;
1637 ltype.path.push_back(1.905);
1638 ltype.path.push_back(-0.9525);
1639 dxfW->writeLineType(<ype);
1640
1641 ltype.path.clear();
1642 ltype.name = "DASHED2";
1643 ltype.desc = "Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _";
1644 ltype.size = 2;
1645 ltype.length = 9.525;
1646 ltype.path.push_back(6.35);
1647 ltype.path.push_back(-3.175);
1648 dxfW->writeLineType(<ype);
1649
1650 ltype.path.clear();
1651 ltype.name = "DASHEDX2";
1652 ltype.desc = "Dashed (2x) ____ ____ ____ ____ ____ ___";
1653 ltype.size = 2;
1654 ltype.length = 38.1;
1655 ltype.path.push_back(25.4);
1656 ltype.path.push_back(-12.7);
1657 dxfW->writeLineType(<ype);
1658
1659 ltype.path.clear();
1660 ltype.name = "DASHDOT";
1661 ltype.desc = "Dash dot __ . __ . __ . __ . __ . __ . __ . __";
1662 ltype.size = 4;
1663 ltype.length = 25.4;
1664 ltype.path.push_back(12.7);
1665 ltype.path.push_back(-6.35);
1666 ltype.path.push_back(0.0);
1667 ltype.path.push_back(-6.35);
1668 dxfW->writeLineType(<ype);
1669
1670 ltype.path.clear();
1671 ltype.name = "DASHDOTTINY";
1672 ltype.desc = "Dash dot (.15x) _._._._._._._._._._._._._._._.";
1673 ltype.size = 4;
1674 ltype.length = 3.81;
1675 ltype.path.push_back(1.905);
1676 ltype.path.push_back(-0.9525);
1677 ltype.path.push_back(0.0);
1678 ltype.path.push_back(-0.9525);
1679 dxfW->writeLineType(<ype);
1680
1681 ltype.path.clear();
1682 ltype.name = "DASHDOT2";
1683 ltype.desc = "Dash dot (.5x) _._._._._._._._._._._._._._._.";
1684 ltype.size = 4;
1685 ltype.length = 12.7;
1686 ltype.path.push_back(6.35);
1687 ltype.path.push_back(-3.175);
1688 ltype.path.push_back(0.0);
1689 ltype.path.push_back(-3.175);
1690 dxfW->writeLineType(<ype);
1691
1692 ltype.path.clear();
1693 ltype.name = "DASHDOTX2";
1694 ltype.desc = "Dash dot (2x) ____ . ____ . ____ . ___";
1695 ltype.size = 4;
1696 ltype.length = 50.8;
1697 ltype.path.push_back(25.4);
1698 ltype.path.push_back(-12.7);
1699 ltype.path.push_back(0.0);
1700 ltype.path.push_back(-12.7);
1701 dxfW->writeLineType(<ype);
1702
1703 ltype.path.clear();
1704 ltype.name = "DIVIDE";
1705 ltype.desc = "Divide ____ . . ____ . . ____ . . ____ . . ____";
1706 ltype.size = 6;
1707 ltype.length = 31.75;
1708 ltype.path.push_back(12.7);
1709 ltype.path.push_back(-6.35);
1710 ltype.path.push_back(0.0);
1711 ltype.path.push_back(-6.35);
1712 ltype.path.push_back(0.0);
1713 ltype.path.push_back(-6.35);
1714 dxfW->writeLineType(<ype);
1715
1716 ltype.path.clear();
1717 ltype.name = "DIVIDETINY";
1718 ltype.desc = "Divide (.15x) __..__..__..__..__..__..__..__.._";
1719 ltype.size = 6;
1720 ltype.length = 4.7625;
1721 ltype.path.push_back(1.905);
1722 ltype.path.push_back(-0.9525);
1723 ltype.path.push_back(0.0);
1724 ltype.path.push_back(-0.9525);
1725 ltype.path.push_back(0.0);
1726 ltype.path.push_back(-0.9525);
1727 dxfW->writeLineType(<ype);
1728
1729 ltype.path.clear();
1730 ltype.name = "DIVIDE2";
1731 ltype.desc = "Divide (.5x) __..__..__..__..__..__..__..__.._";
1732 ltype.size = 6;
1733 ltype.length = 15.875;
1734 ltype.path.push_back(6.35);
1735 ltype.path.push_back(-3.175);
1736 ltype.path.push_back(0.0);
1737 ltype.path.push_back(-3.175);
1738 ltype.path.push_back(0.0);
1739 ltype.path.push_back(-3.175);
1740 dxfW->writeLineType(<ype);
1741
1742 ltype.path.clear();
1743 ltype.name = "DIVIDEX2";
1744 ltype.desc = "Divide (2x) ________ . . ________ . . _";
1745 ltype.size = 6;
1746 ltype.length = 63.5;
1747 ltype.path.push_back(25.4);
1748 ltype.path.push_back(-12.7);
1749 ltype.path.push_back(0.0);
1750 ltype.path.push_back(-12.7);
1751 ltype.path.push_back(0.0);
1752 ltype.path.push_back(-12.7);
1753 dxfW->writeLineType(<ype);
1754
1755 ltype.path.clear();
1756 ltype.name = "BORDER";
1757 ltype.desc = "Border __ __ . __ __ . __ __ . __ __ . __ __ .";
1758 ltype.size = 6;
1759 ltype.length = 44.45;
1760 ltype.path.push_back(12.7);
1761 ltype.path.push_back(-6.35);
1762 ltype.path.push_back(12.7);
1763 ltype.path.push_back(-6.35);
1764 ltype.path.push_back(0.0);
1765 ltype.path.push_back(-6.35);
1766 dxfW->writeLineType(<ype);
1767
1768 ltype.path.clear();
1769 ltype.name = "BORDERTINY";
1770 ltype.desc = "Border (.15x) __.__.__.__.__.__.__.__.__.__.__.";
1771 ltype.size = 6;
1772 ltype.length = 6.6675;
1773 ltype.path.push_back(1.905);
1774 ltype.path.push_back(-0.9525);
1775 ltype.path.push_back(1.905);
1776 ltype.path.push_back(-0.9525);
1777 ltype.path.push_back(0.0);
1778 ltype.path.push_back(-0.9525);
1779 dxfW->writeLineType(<ype);
1780
1781 ltype.path.clear();
1782 ltype.name = "BORDER2";
1783 ltype.desc = "Border (.5x) __.__.__.__.__.__.__.__.__.__.__.";
1784 ltype.size = 6;
1785 ltype.length = 22.225;
1786 ltype.path.push_back(6.35);
1787 ltype.path.push_back(-3.175);
1788 ltype.path.push_back(6.35);
1789 ltype.path.push_back(-3.175);
1790 ltype.path.push_back(0.0);
1791 ltype.path.push_back(-3.175);
1792 dxfW->writeLineType(<ype);
1793
1794 ltype.path.clear();
1795 ltype.name = "BORDERX2";
1796 ltype.desc = "Border (2x) ____ ____ . ____ ____ . ___";
1797 ltype.size = 6;
1798 ltype.length = 88.9;
1799 ltype.path.push_back(25.4);
1800 ltype.path.push_back(-12.7);
1801 ltype.path.push_back(25.4);
1802 ltype.path.push_back(-12.7);
1803 ltype.path.push_back(0.0);
1804 ltype.path.push_back(-12.7);
1805 dxfW->writeLineType(<ype);
1806
1807 ltype.path.clear();
1808 ltype.name = "CENTER";
1809 ltype.desc = "Center ____ _ ____ _ ____ _ ____ _ ____ _ ____";
1810 ltype.size = 4;
1811 ltype.length = 50.8;
1812 ltype.path.push_back(31.75);
1813 ltype.path.push_back(-6.35);
1814 ltype.path.push_back(6.35);
1815 ltype.path.push_back(-6.35);
1816 dxfW->writeLineType(<ype);
1817
1818 ltype.path.clear();
1819 ltype.name = "CENTERTINY";
1820 ltype.desc = "Center (.15x) ___ _ ___ _ ___ _ ___ _ ___ _ ___";
1821 ltype.size = 4;
1822 ltype.length = 7.62;
1823 ltype.path.push_back(4.7625);
1824 ltype.path.push_back(-0.9525);
1825 ltype.path.push_back(0.9525);
1826 ltype.path.push_back(-0.9525);
1827 dxfW->writeLineType(<ype);
1828
1829 ltype.path.clear();
1830 ltype.name = "CENTER2";
1831 ltype.desc = "Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___";
1832 ltype.size = 4;
1833 ltype.length = 28.575;
1834 ltype.path.push_back(19.05);
1835 ltype.path.push_back(-3.175);
1836 ltype.path.push_back(3.175);
1837 ltype.path.push_back(-3.175);
1838 dxfW->writeLineType(<ype);
1839
1840 ltype.path.clear();
1841 ltype.name = "CENTERX2";
1842 ltype.desc = "Center (2x) ________ __ ________ __ _____";
1843 ltype.size = 4;
1844 ltype.length = 101.6;
1845 ltype.path.push_back(63.5);
1846 ltype.path.push_back(-12.7);
1847 ltype.path.push_back(12.7);
1848 ltype.path.push_back(-12.7);
1849 dxfW->writeLineType(<ype);
1850 }
1851
writeLayers()1852 void RS_FilterDXFRW::writeLayers(){
1853 DRW_Layer lay;
1854 RS_LayerList* ll = graphic->getLayerList();
1855 int exact_rgb;
1856 for (unsigned int i = 0; i < ll->count(); i++) {
1857 lay.reset();
1858 RS_Layer* l = ll->at(i);
1859 RS_Pen pen = l->getPen();
1860 lay.name = l->getName().toUtf8().data();
1861 lay.color = colorToNumber(pen.getColor(), &exact_rgb);
1862 lay.color24 = exact_rgb;
1863 lay.lWeight = widthToNumber(pen.getWidth());
1864 lay.lineType = lineTypeToName(pen.getLineType()).toStdString();
1865 lay.flags = l->isFrozen() ? 0x01 : 0x00;
1866 if (l->isLocked()) lay.flags |=0x04;
1867 lay.plotF = l->isPrint();
1868 if( l->isConstruction()) {
1869 lay.extData.push_back(new DRW_Variant(1001, "LibreCad"));
1870 lay.extData.push_back(new DRW_Variant(1070, 1));
1871 RS_DEBUG->print(RS_Debug::D_WARNING, "RS_FilterDXF::writeLayers: layer %s saved as construction layer", lay.name.c_str());
1872 }
1873 dxfW->writeLayer(&lay);
1874 }
1875 }
1876
writeTextstyles()1877 void RS_FilterDXFRW::writeTextstyles(){
1878 QHash<QString, QString> styles;
1879 QString sty;
1880 //Find fonts used by text entities in drawing
1881 for (RS_Entity *e = graphic->firstEntity(RS2::ResolveNone);
1882 e ; e = graphic->nextEntity(RS2::ResolveNone)) {
1883 if ( !(e->getFlag(RS2::FlagUndone)) ) {
1884 switch (e->rtti()) {
1885 case RS2::EntityMText:
1886 sty = ((RS_MText*)e)->getStyle();
1887 break;
1888 case RS2::EntityText:
1889 sty = ((RS_Text*)e)->getStyle();
1890 break;
1891 default:
1892 sty.clear();
1893 break;
1894 }
1895 if (!sty.isEmpty() && !styles.contains(sty))
1896 styles.insert(sty, sty);
1897 }
1898 }
1899 //Find fonts used by text entities in blocks
1900 RS_Block *blk;
1901 for (unsigned i = 0; i < graphic->countBlocks(); i++) {
1902 blk = graphic->blockAt(i);
1903 for (RS_Entity *e = blk->firstEntity(RS2::ResolveNone);
1904 e ; e = blk->nextEntity(RS2::ResolveNone)) {
1905 if ( !(e->getFlag(RS2::FlagUndone)) ) {
1906 switch (e->rtti()) {
1907 case RS2::EntityMText:
1908 sty = ((RS_MText*)e)->getStyle();
1909 break;
1910 case RS2::EntityText:
1911 sty = ((RS_Text*)e)->getStyle();
1912 break;
1913 default:
1914 sty.clear();
1915 break;
1916 }
1917 if (!sty.isEmpty() && !styles.contains(sty))
1918 styles.insert(sty, sty);
1919 }
1920 }
1921 }
1922 DRW_Textstyle ts;
1923 QHash<QString, QString>::const_iterator it = styles.constBegin();
1924 while (it != styles.constEnd()) {
1925 ts.name = (it.key()).toStdString();
1926 ts.font = it.value().toStdString();
1927 // ts.flags;
1928 dxfW->writeTextstyle( &ts );
1929 ++it;
1930 }
1931 }
1932
writeVports()1933 void RS_FilterDXFRW::writeVports(){
1934 DRW_Vport vp;
1935 vp.name = "*Active";
1936 graphic->isGridOn()? vp.grid = 1 : vp.grid = 0;
1937 RS_Vector spacing = graphic->getVariableVector("$GRIDUNIT",
1938 RS_Vector(0.0,0.0));
1939 vp.gridBehavior = 3;
1940 vp.gridSpacing.x = spacing.x;
1941 vp.gridSpacing.y = spacing.y;
1942 vp.snapStyle = graphic->isIsometricGrid();
1943 vp.snapIsopair = graphic->getCrosshairType();
1944 if (vp.snapIsopair > 2)
1945 vp.snapIsopair = 0;
1946 if (fabs(spacing.x) < 1.0e-6) {
1947 vp.gridBehavior = 7; //auto
1948 vp.gridSpacing.x = 10;
1949 }
1950 if (fabs(spacing.y) < 1.0e-6) {
1951 vp.gridBehavior = 7; //auto
1952 vp.gridSpacing.y = 10;
1953 }
1954 RS_GraphicView *gv = graphic->getGraphicView();
1955 if (gv ) {
1956 RS_Vector fac =gv->getFactor();
1957 vp.height = gv->getHeight()/fac.y;
1958 vp.ratio = (double)gv->getWidth() / (double)gv->getHeight();
1959 vp.center.x = ( gv->getWidth() - gv->getOffsetX() )/ (fac.x * 2.0);
1960 vp.center.y = ( gv->getHeight() - gv->getOffsetY() )/ (fac.y * 2.0);
1961 }
1962 dxfW->writeVport(&vp);
1963 }
1964
1965
writeDimstyles()1966 void RS_FilterDXFRW::writeDimstyles(){
1967 DRW_Dimstyle dsty;
1968 dsty.name = "Standard";
1969 dsty.dimscale = graphic->getVariableDouble("$DIMSCALE", 1.0);
1970 dsty.dimasz = graphic->getVariableDouble("$DIMASZ", 2.5);
1971 dsty.dimexo = graphic->getVariableDouble("$DIMEXO", 0.625);
1972 dsty.dimexe = graphic->getVariableDouble("$DIMEXE", 1.25);
1973 dsty.dimfxl = graphic->getVariableDouble("$DIMFXL", 1.0);
1974 dsty.dimtxt = graphic->getVariableDouble("$DIMTXT", 2.5);
1975 dsty.dimtsz = graphic->getVariableDouble("$DIMTSZ", 2.5);
1976 dsty.dimlfac = graphic->getVariableDouble("$DIMLFAC", 1.0);
1977 dsty.dimgap = graphic->getVariableDouble("$DIMGAP", 0.625);
1978 dsty.dimtih = graphic->getVariableInt("$DIMTIH", 2);
1979 dsty.dimzin = graphic->getVariableInt("$DIMZIN", 1);
1980 dsty.dimazin = graphic->getVariableInt("$DIMAZIN", 0);
1981 dsty.dimclrd = graphic->getVariableInt("$DIMCLRD", 0);
1982 dsty.dimclre = graphic->getVariableInt("$DIMCLRE", 0);
1983 dsty.dimclrt = graphic->getVariableInt("$DIMCLRT", 0);
1984 dsty.dimadec = graphic->getVariableInt("$DIMADEC", 0);
1985 dsty.dimdec = graphic->getVariableInt("$DIMDEC", 2);
1986 dsty.dimaunit = graphic->getVariableInt("$DIMAUNIT", 0);
1987 dsty.dimlunit = graphic->getVariableInt("$DIMLUNIT", 2);
1988 dsty.dimdsep = graphic->getVariableInt("$DIMDSEP", 0);
1989 dsty.dimfxlon = graphic->getVariableInt("$DIMFXLON", 0);
1990 dsty.dimtxsty = graphic->getVariableString("$DIMTXSTY", "standard").toStdString();
1991 dsty.dimlwd = graphic->getVariableInt("$DIMLWD", -2);
1992 dsty.dimlwe = graphic->getVariableInt("$DIMLWE", -2);
1993 dxfW->writeDimstyle(&dsty);
1994 }
1995
writeObjects()1996 void RS_FilterDXFRW::writeObjects() {
1997 /* PLOTSETTINGS */
1998 DRW_PlotSettings ps;
1999 QString horizXvert = QString("%1x%2").arg(graphic->getPagesNumHoriz())
2000 .arg(graphic->getPagesNumVert());
2001 ps.plotViewName = horizXvert.toStdString();
2002 ps.marginLeft = graphic->getMarginLeft();
2003 ps.marginTop = graphic->getMarginTop();
2004 ps.marginRight = graphic->getMarginRight();
2005 ps.marginBottom = graphic->getMarginBottom();
2006 dxfW->writePlotSettings(&ps);
2007 }
2008
writeAppId()2009 void RS_FilterDXFRW::writeAppId(){
2010 DRW_AppId ai;
2011 ai.name ="LibreCad";
2012 dxfW->writeAppId(&ai);
2013 }
2014
writeEntities()2015 void RS_FilterDXFRW::writeEntities(){
2016 for (RS_Entity *e = graphic->firstEntity(RS2::ResolveNone);
2017 e ; e = graphic->nextEntity(RS2::ResolveNone)) {
2018 if ( !(e->getFlag(RS2::FlagUndone)) ) {
2019 writeEntity(e);
2020 }
2021 }
2022 }
2023
writeEntity(RS_Entity * e)2024 void RS_FilterDXFRW::writeEntity(RS_Entity* e){
2025 switch (e->rtti()) {
2026 case RS2::EntityPoint:
2027 writePoint((RS_Point*)e);
2028 break;
2029 case RS2::EntityLine:
2030 writeLine((RS_Line*)e);
2031 break;
2032 case RS2::EntityCircle:
2033 writeCircle((RS_Circle*)e);
2034 break;
2035 case RS2::EntityArc:
2036 writeArc((RS_Arc*)e);
2037 break;
2038 case RS2::EntitySolid:
2039 writeSolid((RS_Solid*)e);
2040 break;
2041 case RS2::EntityEllipse:
2042 writeEllipse((RS_Ellipse*)e);
2043 break;
2044 case RS2::EntityPolyline:
2045 writeLWPolyline((RS_Polyline*)e);
2046 break;
2047 case RS2::EntitySpline:
2048 writeSpline((RS_Spline*)e);
2049 break;
2050 case RS2::EntitySplinePoints:
2051 writeSplinePoints((LC_SplinePoints*)e);
2052 break;
2053 // case RS2::EntityVertex:
2054 // break;
2055 case RS2::EntityInsert:
2056 writeInsert((RS_Insert*)e);
2057 break;
2058 case RS2::EntityMText:
2059 writeMText((RS_MText*)e);
2060 break;
2061 case RS2::EntityText:
2062 writeText((RS_Text*)e);
2063 break;
2064 case RS2::EntityDimLinear:
2065 case RS2::EntityDimAligned:
2066 case RS2::EntityDimAngular:
2067 case RS2::EntityDimRadial:
2068 case RS2::EntityDimDiametric:
2069 writeDimension((RS_Dimension*)e);
2070 break;
2071 case RS2::EntityDimLeader:
2072 writeLeader((RS_Leader*)e);
2073 break;
2074 case RS2::EntityHatch:
2075 writeHatch((RS_Hatch*)e);
2076 break;
2077 case RS2::EntityImage:
2078 writeImage((RS_Image*)e);
2079 break;
2080 default:
2081 break;
2082 }
2083 }
2084
2085
2086 /**
2087 * Writes the given Point entity to the file.
2088 */
writePoint(RS_Point * p)2089 void RS_FilterDXFRW::writePoint(RS_Point* p) {
2090 DRW_Point point;
2091 getEntityAttributes(&point, p);
2092 point.basePoint.x = p->getStartpoint().x;
2093 point.basePoint.y = p->getStartpoint().y;
2094 dxfW->writePoint(&point);
2095 }
2096
2097
2098 /**
2099 * Writes the given Line( entity to the file.
2100 */
writeLine(RS_Line * l)2101 void RS_FilterDXFRW::writeLine(RS_Line* l) {
2102 DRW_Line line;
2103 getEntityAttributes(&line, l);
2104 line.basePoint.x = l->getStartpoint().x;
2105 line.basePoint.y = l->getStartpoint().y;
2106 line.secPoint.x = l->getEndpoint().x;
2107 line.secPoint.y = l->getEndpoint().y;
2108 dxfW->writeLine(&line);
2109 }
2110
2111
2112 /**
2113 * Writes the given circle entity to the file.
2114 */
writeCircle(RS_Circle * c)2115 void RS_FilterDXFRW::writeCircle(RS_Circle* c) {
2116 DRW_Circle circle;
2117 getEntityAttributes(&circle, c);
2118 circle.basePoint.x = c->getCenter().x;
2119 circle.basePoint.y = c->getCenter().y;
2120 circle.radious = c->getRadius();
2121 dxfW->writeCircle(&circle);
2122 }
2123
2124
2125 /**
2126 * Writes the given arc entity to the file.
2127 */
writeArc(RS_Arc * a)2128 void RS_FilterDXFRW::writeArc(RS_Arc* a) {
2129 DRW_Arc arc;
2130 getEntityAttributes(&arc, a);
2131 arc.basePoint.x = a->getCenter().x;
2132 arc.basePoint.y = a->getCenter().y;
2133 arc.radious = a->getRadius();
2134 if (a->isReversed()) {
2135 arc.staangle = a->getAngle2();
2136 arc.endangle = a->getAngle1();
2137 } else {
2138 arc.staangle = a->getAngle1();
2139 arc.endangle = a->getAngle2();
2140 }
2141 dxfW->writeArc(&arc);
2142 }
2143
2144
2145 /**
2146 * Writes the given polyline entity to the file as lwpolyline.
2147 */
writeLWPolyline(RS_Polyline * l)2148 void RS_FilterDXFRW::writeLWPolyline(RS_Polyline* l) {
2149 //skip if are empty polyline
2150 if (l->isEmpty())
2151 return;
2152 // version 12 are old style polyline
2153 if (version==1009) {
2154 writePolyline(l);
2155 return;
2156 }
2157 DRW_LWPolyline pol;
2158 RS_Entity* currEntity = 0;
2159 RS_Entity* nextEntity = 0;
2160 RS_AtomicEntity* ae = nullptr;
2161 double bulge=0.0;
2162
2163 for (RS_Entity* e=l->firstEntity(RS2::ResolveNone);
2164 e; e=nextEntity) {
2165
2166 currEntity = e;
2167 nextEntity = l->nextEntity(RS2::ResolveNone);
2168
2169 if (!e->isAtomic()) {
2170 continue;
2171 }
2172 ae = (RS_AtomicEntity*)e;
2173
2174 // Write vertex:
2175 if (e->rtti()==RS2::EntityArc) {
2176 bulge = ((RS_Arc*)e)->getBulge();
2177 } else
2178 bulge = 0.0;
2179 pol.addVertex( DRW_Vertex2D(ae->getStartpoint().x,
2180 ae->getStartpoint().y, bulge));
2181 }
2182 if (l->isClosed()) {
2183 pol.flags = 1;
2184 } else {
2185 ae = (RS_AtomicEntity*)currEntity;
2186 if (ae->rtti()==RS2::EntityArc) {
2187 bulge = ((RS_Arc*)ae)->getBulge();
2188 }
2189 pol.addVertex( DRW_Vertex2D(ae->getEndpoint().x,
2190 ae->getEndpoint().y, bulge));
2191 }
2192 pol.vertexnum = pol.vertlist.size();
2193 getEntityAttributes(&pol, l);
2194 dxfW->writeLWPolyline(&pol);
2195 }
2196
2197 /**
2198 * Writes the given polyline entity to the file (old style).
2199 */
writePolyline(RS_Polyline * p)2200 void RS_FilterDXFRW::writePolyline(RS_Polyline* p) {
2201 DRW_Polyline pol;
2202 RS_Entity* currEntity = 0;
2203 RS_Entity* nextEntity = 0;
2204 RS_AtomicEntity* ae = nullptr;
2205 double bulge=0.0;
2206
2207 for (RS_Entity* e=p->firstEntity(RS2::ResolveNone);
2208 e; e=nextEntity) {
2209
2210 currEntity = e;
2211 nextEntity = p->nextEntity(RS2::ResolveNone);
2212
2213 if (!e->isAtomic()) {
2214 continue;
2215 }
2216 ae = (RS_AtomicEntity*)e;
2217
2218 // Write vertex:
2219 if (e->rtti()==RS2::EntityArc) {
2220 bulge = ((RS_Arc*)e)->getBulge();
2221 } else
2222 bulge = 0.0;
2223 pol.addVertex( DRW_Vertex(ae->getStartpoint().x,
2224 ae->getStartpoint().y, 0.0, bulge));
2225 }
2226 if (p->isClosed()) {
2227 pol.flags = 1;
2228 } else {
2229 ae = (RS_AtomicEntity*)currEntity;
2230 if (ae->rtti()==RS2::EntityArc) {
2231 bulge = ((RS_Arc*)ae)->getBulge();
2232 }
2233 pol.addVertex( DRW_Vertex(ae->getEndpoint().x,
2234 ae->getEndpoint().y, 0.0, bulge));
2235 }
2236 getEntityAttributes(&pol, p);
2237 dxfW->writePolyline(&pol);
2238 }
2239
2240
2241
2242 /**
2243 * Writes the given spline entity to the file.
2244 */
writeSpline(RS_Spline * s)2245 void RS_FilterDXFRW::writeSpline(RS_Spline *s) {
2246
2247 if (s->getNumberOfControlPoints() < s->getDegree()+1) {
2248 RS_DEBUG->print(RS_Debug::D_ERROR, "RS_FilterDXF::writeSpline: "
2249 "Discarding spline: not enough control points given.");
2250 return;
2251 }
2252
2253 // version 12 do not support Spline write as polyline
2254 if (version==1009) {
2255 DRW_Polyline pol;
2256 RS_Entity* e;
2257 for (e=s->firstEntity(RS2::ResolveNone);
2258 e; e=s->nextEntity(RS2::ResolveNone)) {
2259 pol.addVertex( DRW_Vertex(e->getStartpoint().x,
2260 e->getStartpoint().y, 0.0, 0.0));
2261 }
2262 if (s->isClosed()) {
2263 pol.flags = 1;
2264 } else {
2265 pol.addVertex( DRW_Vertex(s->getEndpoint().x,
2266 s->getEndpoint().y, 0.0, 0.0));
2267 }
2268 getEntityAttributes(&pol, s);
2269 dxfW->writePolyline(&pol);
2270 return;
2271 }
2272
2273 DRW_Spline sp;
2274
2275 if (s->isClosed())
2276 sp.flags = 11;
2277 else
2278 sp.flags = 8;
2279 sp.ncontrol = s->getNumberOfControlPoints();
2280 sp.degree = s->getDegree();
2281 sp.nknots = sp.ncontrol + sp.degree + 1;
2282
2283 // write spline knots:
2284 if (s->getData().knotslist.size()) {
2285 sp.knotslist = s->getData().knotslist;
2286 } else {
2287 int k = sp.degree+1;
2288 for (int i=1; i<=sp.nknots; i++) {
2289 if (i<=k) {
2290 sp.knotslist.push_back(0.0);
2291 } else if (i<=sp.nknots-k) {
2292 sp.knotslist.push_back(1.0/(sp.nknots-2*k+1) * (i-k));
2293 } else {
2294 sp.knotslist.push_back(1.0);
2295 }
2296 }
2297 }
2298
2299 // write spline control points:
2300 auto cp = s->getControlPoints();
2301 for (const RS_Vector& v: cp)
2302 sp.controllist.push_back(std::make_shared<DRW_Coord>(v.x, v.y, 0.));
2303
2304 getEntityAttributes(&sp, s);
2305 dxfW->writeSpline(&sp);
2306
2307 }
2308
2309
2310 /**
2311 * Writes the given spline entity to the file.
2312 */
writeSplinePoints(LC_SplinePoints * s)2313 void RS_FilterDXFRW::writeSplinePoints(LC_SplinePoints *s)
2314 {
2315 int nCtrls = s->getNumberOfControlPoints();
2316 auto const& cp = s->getControlPoints();
2317
2318 if(nCtrls < 3)
2319 {
2320 if(nCtrls > 1)
2321 {
2322 DRW_Line line;
2323 line.basePoint.x = cp.at(0).x;
2324 line.basePoint.y = cp.at(0).y;
2325 line.secPoint.x = cp.at(1).x;
2326 line.secPoint.y = cp.at(1).y;
2327 getEntityAttributes(&line, s);
2328 dxfW->writeLine(&line);
2329 }
2330 return;
2331 }
2332
2333 // version 12 do not support Spline write as polyline
2334 if(version == 1009)
2335 {
2336 DRW_Polyline pol;
2337 auto const& sp = s->getStrokePoints();
2338
2339 for(size_t i = 0; i < sp.size(); i++)
2340 {
2341 pol.addVertex(DRW_Vertex(sp.at(i).x, sp.at(i).y, 0.0, 0.0));
2342 }
2343
2344 if(s->isClosed()) pol.flags = 1;
2345
2346 getEntityAttributes(&pol, s);
2347 dxfW->writePolyline(&pol);
2348 return;
2349 }
2350
2351 DRW_Spline sp;
2352
2353 if(s->isClosed()) sp.flags = 11;
2354 else sp.flags = 8;
2355
2356 sp.ncontrol = nCtrls;
2357 sp.degree = 2;
2358 sp.nknots = nCtrls + 3;
2359
2360 // write spline knots:
2361 for(int i = 1; i <= sp.nknots; i++)
2362 {
2363 if(i <= 3)
2364 {
2365 sp.knotslist.push_back(0.0);
2366 }
2367 else if(i <= nCtrls)
2368 {
2369 sp.knotslist.push_back((i - 3.0)/(nCtrls - 2.0));
2370 }
2371 else
2372 {
2373 sp.knotslist.push_back(1.0);
2374 }
2375 }
2376
2377 // write spline control points:
2378 for (auto const& v: cp)
2379 sp.controllist.push_back(std::make_shared<DRW_Coord>(v.x, v.y, 0.));
2380
2381 getEntityAttributes(&sp, s);
2382 dxfW->writeSpline(&sp);
2383 }
2384
2385
2386 /**
2387 * Writes the given Ellipse entity to the file.
2388 */
writeEllipse(RS_Ellipse * s)2389 void RS_FilterDXFRW::writeEllipse(RS_Ellipse* s) {
2390 // version 12 do not support Ellipse but are
2391 // converted in polyline by library
2392 DRW_Ellipse el;
2393 getEntityAttributes(&el, s);
2394 el.basePoint.x = s->getCenter().x;
2395 el.basePoint.y = s->getCenter().y;
2396 el.secPoint.x = s->getMajorP().x;
2397 el.secPoint.y = s->getMajorP().y;
2398 el.ratio = s->getRatio();
2399 if (s->isReversed()) {
2400 el.staparam = s->getAngle2();
2401 el.endparam = s->getAngle1();
2402 } else {
2403 el.staparam = s->getAngle1();
2404 el.endparam = s->getAngle2();
2405 }
2406 dxfW->writeEllipse(&el);
2407 }
2408
2409 /**
2410 * Writes the given block insert entity to the file.
2411 */
writeInsert(RS_Insert * i)2412 void RS_FilterDXFRW::writeInsert(RS_Insert* i) {
2413 DRW_Insert in;
2414 getEntityAttributes(&in, i);
2415 in.basePoint.x = i->getInsertionPoint().x;
2416 in.basePoint.y = i->getInsertionPoint().y;
2417 in.basePoint.z = i->getInsertionPoint().z;
2418 in.name = i->getName().toUtf8().data();
2419 in.xscale = i->getScale().x;
2420 in.yscale = i->getScale().y;
2421 in.zscale = i->getScale().z;
2422 in.angle = i->getAngle();
2423 in.colcount = i->getCols();
2424 in.rowcount = i->getRows();
2425 in.colspace = i->getSpacing().x;
2426 in.rowspace =i->getSpacing().y;
2427 dxfW->writeInsert(&in);
2428 }
2429
2430
2431 /**
2432 * Writes the given mText entity to the file.
2433 */
writeMText(RS_MText * t)2434 void RS_FilterDXFRW::writeMText(RS_MText* t) {
2435 DRW_Text *text;
2436 DRW_Text txt1;
2437 DRW_MText txt2;
2438
2439 if (version==1009)
2440 text = &txt1;
2441 else
2442 text = &txt2;
2443
2444 getEntityAttributes(text, t);
2445 text->basePoint.x = t->getInsertionPoint().x;
2446 text->basePoint.y = t->getInsertionPoint().y;
2447 text->height = t->getHeight();
2448 text->angle = t->getAngle()*180/M_PI;
2449 text->style = t->getStyle().toStdString();
2450
2451 if (version==1009) {
2452 if (t->getHAlign()==RS_MTextData::HALeft) {
2453 text->alignH =DRW_Text::HLeft;
2454 } else if (t->getHAlign()==RS_MTextData::HACenter) {
2455 text->alignH =DRW_Text::HCenter;
2456 } else if (t->getHAlign()==RS_MTextData::HARight) {
2457 text->alignH = DRW_Text::HRight;
2458 }
2459 if (t->getVAlign()==RS_MTextData::VATop) {
2460 text->alignV = DRW_Text::VTop;
2461 } else if (t->getVAlign()==RS_MTextData::VAMiddle) {
2462 text->alignV = DRW_Text::VMiddle;
2463 } else if (t->getVAlign()==RS_MTextData::VABottom) {
2464 text->alignV = DRW_Text::VBaseLine;
2465 }
2466 QStringList txtList = t->getText().split('\n',QString::KeepEmptyParts);
2467 double dist = t->getLineSpacingFactor()*5*t->getHeight()/3;
2468 bool setSec = false;
2469 if (text->alignH != DRW_Text::HLeft || text->alignV != DRW_Text::VBaseLine) {
2470 text->secPoint.x = t->getInsertionPoint().x;
2471 text->secPoint.y = t->getInsertionPoint().y;
2472 setSec = true;
2473 }
2474 if (text->alignV == DRW_Text::VTop)
2475 dist = dist * -1;
2476 for (int i=0; i<txtList.size();++i){
2477 if (!txtList.at(i).isEmpty()) {
2478 text->text = toDxfString(txtList.at(i)).toUtf8().data();
2479 RS_Vector inc = RS_Vector::polar(dist*i, t->getAngle()+M_PI_2);
2480 if (setSec) {
2481 text->secPoint.x += inc.x;
2482 text->secPoint.y += inc.y;
2483 } else {
2484 text->basePoint.x += inc.x;
2485 text->basePoint.y += inc.y;
2486 }
2487 dxfW->writeText(text);
2488 }
2489 }
2490 } else {
2491 if (t->getHAlign()==RS_MTextData::HALeft) {
2492 text->textgen =1;
2493 } else if (t->getHAlign()==RS_MTextData::HACenter) {
2494 text->textgen =2;
2495 } else if (t->getHAlign()==RS_MTextData::HARight) {
2496 text->textgen = 3;
2497 }
2498 if (t->getVAlign()==RS_MTextData::VAMiddle) {
2499 text->textgen += 3;
2500 } else if (t->getVAlign()==RS_MTextData::VABottom) {
2501 text->textgen += 6;
2502 }
2503 if (t->getDrawingDirection() == RS_MTextData::LeftToRight)
2504 text->alignH = (DRW_Text::HAlign)1;
2505 else if (t->getDrawingDirection() == RS_MTextData::TopToBottom)
2506 text->alignH = (DRW_Text::HAlign)3;
2507 else text->alignH = (DRW_Text::HAlign)5;
2508 if (t->getLineSpacingStyle() == RS_MTextData::AtLeast)
2509 text->alignV = (DRW_Text::VAlign)1;
2510 else text->alignV = (DRW_Text::VAlign)2;
2511
2512 text->text = toDxfString(t->getText()).toUtf8().data();
2513 // text->widthscale =t->getWidth();
2514 text->widthscale =t->getUsedTextWidth(); //getSize().x;
2515 txt2.interlin = t->getLineSpacingFactor();
2516
2517 dxfW->writeMText((DRW_MText*)text);
2518 }
2519 }
2520
2521 /**
2522 * Writes the given Text entity to the file.
2523 */
writeText(RS_Text * t)2524 void RS_FilterDXFRW::writeText(RS_Text* t){
2525 DRW_Text text;
2526
2527 getEntityAttributes(&text, t);
2528 text.basePoint.x = t->getInsertionPoint().x;
2529 text.basePoint.y = t->getInsertionPoint().y;
2530 text.height = t->getHeight();
2531 text.angle = t->getAngle()*180/M_PI;
2532 text.style = t->getStyle().toStdString();
2533 text.alignH =(DRW_Text::HAlign)t->getHAlign();
2534 text.alignV =(DRW_Text::VAlign)t->getVAlign();
2535 text.widthscale = t->getWidthRel();
2536
2537 if (text.alignV != DRW_Text::VBaseLine || text.alignH != DRW_Text::HLeft) {
2538 // if (text.alignV != DRW_Text::VBaseLine || text.alignH == DRW_Text::HMiddle) {
2539 // if (text.alignH != DRW_Text::HLeft) {
2540 if (text.alignH == DRW_Text::HAligned || text.alignH == DRW_Text::HFit) {
2541 text.secPoint.x = t->getSecondPoint().x;
2542 text.secPoint.y = t->getSecondPoint().y;
2543 } else {
2544 text.secPoint.x = t->getInsertionPoint().x;
2545 text.secPoint.y = t->getInsertionPoint().y;
2546 }
2547 }
2548
2549 /* if (text.alignH == DRW_Text::HAligned || text.alignH == DRW_Text::HFit) {
2550 text.secPoint.x = t->getSecondPoint().x;
2551 text.secPoint.y = t->getSecondPoint().y;
2552 }*/
2553
2554 if (!t->getText().isEmpty()) {
2555 text.text = toDxfString(t->getText()).toUtf8().data();
2556 dxfW->writeText(&text);
2557 }
2558 }
2559
2560 /**
2561 * Writes the given dimension entity to the file.
2562 */
writeDimension(RS_Dimension * d)2563 void RS_FilterDXFRW::writeDimension(RS_Dimension* d) {
2564 QString blkName;
2565 if (noNameBlock.contains(d)) {
2566 blkName = noNameBlock.take(d);
2567 }
2568
2569 // version 12 are inserts of *D blocks
2570 if (version==1009) {
2571 if (!blkName.isEmpty()) {
2572 DRW_Insert in;
2573 getEntityAttributes(&in, d);
2574 in.basePoint.x = in.basePoint.y = 0.0;
2575 in.basePoint.z = 0.0;
2576 in.name = blkName.toStdString();
2577 in.xscale = in.yscale = 1.0;
2578 in.zscale = 1.0;
2579 in.angle = 0.0;
2580 in.colcount = in.rowcount = 1;
2581 in.colspace = in.rowspace = 0.0;
2582 dxfW->writeInsert(&in);
2583 }
2584 return;
2585 }
2586
2587 DRW_Dimension* dim;
2588 int attachmentPoint=1;
2589 if (d->getHAlign()==RS_MTextData::HALeft) {
2590 attachmentPoint=1;
2591 } else if (d->getHAlign()==RS_MTextData::HACenter) {
2592 attachmentPoint=2;
2593 } else if (d->getHAlign()==RS_MTextData::HARight) {
2594 attachmentPoint=3;
2595 }
2596 if (d->getVAlign()==RS_MTextData::VATop) {
2597 attachmentPoint+=0;
2598 } else if (d->getVAlign()==RS_MTextData::VAMiddle) {
2599 attachmentPoint+=3;
2600 } else if (d->getVAlign()==RS_MTextData::VABottom) {
2601 attachmentPoint+=6;
2602 }
2603
2604 switch (d->rtti()) {
2605 case RS2::EntityDimAligned: {
2606 RS_DimAligned* da = (RS_DimAligned*)d;
2607 DRW_DimAligned * dd = new DRW_DimAligned();
2608 dim = dd ;
2609 dim->type = 1 +32;
2610 dd->setDef1Point(DRW_Coord (da->getExtensionPoint1().x, da->getExtensionPoint1().y, 0.0));
2611 dd->setDef2Point(DRW_Coord (da->getExtensionPoint2().x, da->getExtensionPoint2().y, 0.0));
2612 break; }
2613 case RS2::EntityDimDiametric: {
2614 RS_DimDiametric* dr = (RS_DimDiametric*)d;
2615 DRW_DimDiametric * dd = new DRW_DimDiametric();
2616 dim = dd ;
2617 dim->type = 3+32;
2618 dd->setDiameter1Point(DRW_Coord (dr->getDefinitionPoint().x, dr->getDefinitionPoint().y, 0.0));
2619 dd->setLeaderLength(dr->getLeader());
2620 break; }
2621 case RS2::EntityDimRadial: {
2622 RS_DimRadial* dr = (RS_DimRadial*)d;
2623 DRW_DimRadial * dd = new DRW_DimRadial();
2624 dim = dd ;
2625 dim->type = 4+32;
2626 dd->setDiameterPoint(DRW_Coord (dr->getDefinitionPoint().x, dr->getDefinitionPoint().y, 0.0));
2627 dd->setLeaderLength(dr->getLeader());
2628 break; }
2629 case RS2::EntityDimAngular: {
2630 RS_DimAngular* da = static_cast<RS_DimAngular*>(d);
2631 if (da->getDefinitionPoint3() == da->getData().definitionPoint) {
2632 DRW_DimAngular3p * dd = new DRW_DimAngular3p();
2633 dim = dd ;
2634 dim->type = 5+32;
2635 dd->setFirstLine(DRW_Coord (da->getDefinitionPoint().x, da->getDefinitionPoint().y, 0.0)); //13
2636 dd->setSecondLine(DRW_Coord (da->getDefinitionPoint().x, da->getDefinitionPoint().y, 0.0)); //14
2637 dd->SetVertexPoint(DRW_Coord (da->getDefinitionPoint().x, da->getDefinitionPoint().y, 0.0)); //15
2638 dd->setDimPoint(DRW_Coord (da->getDefinitionPoint().x, da->getDefinitionPoint().y, 0.0)); //10
2639 } else {
2640 DRW_DimAngular * dd = new DRW_DimAngular();
2641 dim = dd ;
2642 dim->type = 2+32;
2643 dd->setFirstLine1(DRW_Coord (da->getDefinitionPoint1().x, da->getDefinitionPoint1().y, 0.0)); //13
2644 dd->setFirstLine2(DRW_Coord (da->getDefinitionPoint2().x, da->getDefinitionPoint2().y, 0.0)); //14
2645 dd->setSecondLine1(DRW_Coord (da->getDefinitionPoint3().x, da->getDefinitionPoint3().y, 0.0)); //15
2646 dd->setDimPoint(DRW_Coord (da->getDefinitionPoint4().x, da->getDefinitionPoint4().y, 0.0)); //16
2647 }
2648 break; }
2649 default: { //default to DimLinear
2650 RS_DimLinear* dl = (RS_DimLinear*)d;
2651 DRW_DimLinear * dd = new DRW_DimLinear();
2652 dim = dd ;
2653 dim->type = 0+32;
2654 dd->setDef1Point(DRW_Coord (dl->getExtensionPoint1().x, dl->getExtensionPoint1().y, 0.0));
2655 dd->setDef2Point(DRW_Coord (dl->getExtensionPoint2().x, dl->getExtensionPoint2().y, 0.0));
2656 dd->setAngle( RS_Math::rad2deg(dl->getAngle()) );
2657 dd->setOblique(dl->getOblique());
2658 break; }
2659 }
2660 getEntityAttributes(dim, d);
2661 dim->setDefPoint(DRW_Coord(d->getDefinitionPoint().x, d->getDefinitionPoint().y, 0));
2662 dim->setTextPoint(DRW_Coord(d->getMiddleOfText().x, d->getMiddleOfText().y, 0));
2663 dim->setStyle (d->getStyle().toUtf8().data());
2664 dim->setAlign (attachmentPoint);
2665 dim->setTextLineStyle(d->getLineSpacingStyle());
2666 dim->setText (toDxfString(d->getText()).toUtf8().data());
2667 dim->setTextLineFactor(d->getLineSpacingFactor());
2668 if (!blkName.isEmpty()) {
2669 dim->setName(blkName.toStdString());
2670 }
2671
2672 dxfW->writeDimension(dim);
2673 delete dim;
2674 }
2675
2676
2677 /**
2678 * Writes the given leader entity to the file.
2679 */
writeLeader(RS_Leader * l)2680 void RS_FilterDXFRW::writeLeader(RS_Leader* l) {
2681 if (l->count()<=0)
2682 RS_DEBUG->print(RS_Debug::D_WARNING, "dropping leader with no vertices");
2683
2684 DRW_Leader leader;
2685 getEntityAttributes(&leader, l);
2686 leader.style = "Standard";
2687 leader.arrow = l->hasArrowHead();
2688 leader.leadertype = 0;
2689 leader.flag = 3;
2690 leader.hookline = 0;
2691 leader.hookflag = 0;
2692 leader.textheight = 1;
2693 leader.textwidth = 10;
2694 leader.vertnum = l->count();
2695 RS_Line* li =nullptr;
2696 for (RS_Entity* v=l->firstEntity(RS2::ResolveNone);
2697 v; v=l->nextEntity(RS2::ResolveNone)) {
2698 if (v->rtti()==RS2::EntityLine) {
2699 li = (RS_Line*)v;
2700 leader.vertexlist.push_back(std::make_shared<DRW_Coord>(li->getStartpoint().x, li->getStartpoint().y, 0.0));
2701 }
2702 }
2703 if (li )
2704 leader.vertexlist.push_back(std::make_shared<DRW_Coord>(li->getEndpoint().x, li->getEndpoint().y, 0.0));
2705
2706 dxfW->writeLeader(&leader);
2707 }
2708
2709
2710 /**
2711 * Writes the given hatch entity to the file.
2712 */
writeHatch(RS_Hatch * h)2713 void RS_FilterDXFRW::writeHatch(RS_Hatch * h) {
2714 // version 12 are inserts of *U blocks
2715 if (version==1009) {
2716 if (noNameBlock.contains(h)) {
2717 DRW_Insert in;
2718 getEntityAttributes(&in, h);
2719 in.basePoint.x = in.basePoint.y = 0.0;
2720 in.basePoint.z = 0.0;
2721 in.name = noNameBlock.value(h).toUtf8().data();
2722 in.xscale = in.yscale = 1.0;
2723 in.zscale = 1.0;
2724 in.angle = 0.0;
2725 in.colcount = in.rowcount = 1;
2726 in.colspace = in.rowspace = 0.0;
2727 dxfW->writeInsert(&in);
2728 }
2729 return;
2730 }
2731
2732 bool writeIt = true;
2733 if (h->countLoops()>0) {
2734 // check if all of the loops contain entities:
2735 for (RS_Entity* l=h->firstEntity(RS2::ResolveNone);
2736 l;
2737 l=h->nextEntity(RS2::ResolveNone)) {
2738
2739 if (l->isContainer() && !l->getFlag(RS2::FlagTemp)) {
2740 if (l->count()==0) {
2741 writeIt = false;
2742 }
2743 }
2744 }
2745 } else {
2746 writeIt = false;
2747 }
2748
2749 if (!writeIt) {
2750 RS_DEBUG->print(RS_Debug::D_WARNING,
2751 "RS_FilterDXF::writeHatch: Dropping Hatch");
2752 return;
2753 }
2754
2755 DRW_Hatch ha;
2756 getEntityAttributes(&ha, h);
2757 ha.solid = h->isSolid();
2758 ha.scale = h->getScale();
2759 ha.angle = h->getAngle();
2760 if (ha.solid)
2761 ha.name = "SOLID";
2762 else
2763 ha.name = h->getPattern().toUtf8().data();
2764 ha.loopsnum = h->countLoops();
2765
2766 for (RS_Entity* l=h->firstEntity(RS2::ResolveNone);
2767 l;
2768 l=h->nextEntity(RS2::ResolveNone)) {
2769
2770 // Write hatch loops:
2771 if (l->isContainer() && !l->getFlag(RS2::FlagTemp)) {
2772 RS_EntityContainer* loop = (RS_EntityContainer*)l;
2773 std::shared_ptr<DRW_HatchLoop> lData = std::make_shared<DRW_HatchLoop>(0);
2774
2775 for (RS_Entity* ed=loop->firstEntity(RS2::ResolveNone);
2776 ed;
2777 ed=loop->nextEntity(RS2::ResolveNone)) {
2778
2779 // Write hatch loop edges:
2780 if (ed->rtti()==RS2::EntityLine) {
2781 RS_Line* ln = (RS_Line*)ed;
2782 std::shared_ptr<DRW_Line> line = std::make_shared<DRW_Line>();
2783 line->basePoint.x = ln->getStartpoint().x;
2784 line->basePoint.y = ln->getStartpoint().y;
2785 line->secPoint.x = ln->getEndpoint().x;
2786 line->secPoint.y = ln->getEndpoint().y;
2787 lData->objlist.push_back(line);
2788 } else if (ed->rtti()==RS2::EntityArc) {
2789 RS_Arc* ar = (RS_Arc*)ed;
2790 std::shared_ptr<DRW_Arc> arc = std::make_shared<DRW_Arc>();
2791 arc->basePoint.x = ar->getCenter().x;
2792 arc->basePoint.y = ar->getCenter().y;
2793 arc->radious = ar->getRadius();
2794 if (!ar->isReversed()) {
2795 arc->staangle = ar->getAngle1();
2796 arc->endangle = ar->getAngle2();
2797 arc->isccw = true;
2798 } else {
2799 arc->staangle = 2*M_PI-ar->getAngle1();
2800 arc->endangle = 2*M_PI-ar->getAngle2();
2801 arc->isccw = false;
2802 }
2803 lData->objlist.push_back(arc);
2804 } else if (ed->rtti()==RS2::EntityCircle) {
2805 RS_Circle* ci = (RS_Circle*)ed;
2806 std::shared_ptr<DRW_Arc> arc = std::make_shared<DRW_Arc>();
2807 arc->basePoint.x = ci->getCenter().x;
2808 arc->basePoint.y = ci->getCenter().y;
2809 arc->radious = ci->getRadius();
2810 arc->staangle = 0.0;
2811 arc->endangle = 2*M_PI; //2*M_PI;
2812 arc->isccw = true;
2813 lData->objlist.push_back(arc);
2814 } else if (ed->rtti()==RS2::EntityEllipse) {
2815 RS_Ellipse* el = (RS_Ellipse*)ed;
2816 std::shared_ptr<DRW_Ellipse> ell = std::make_shared<DRW_Ellipse>();
2817 ell->basePoint.x = el->getCenter().x;
2818 ell->basePoint.y = el->getCenter().y;
2819 ell->secPoint.x = el->getMajorP().x;
2820 ell->secPoint.y = el->getMajorP().y;
2821 ell->ratio = el->getRatio();
2822 double rot = el->getMajorP().angle();
2823 double startAng = el->getCenter().angleTo(el->getStartpoint()) - rot;
2824 double endAng = el->getCenter().angleTo(el->getEndpoint()) - rot;
2825 if (startAng < 0) startAng = M_PI*2 + startAng;
2826 if (endAng < 0) endAng = M_PI*2 + endAng;
2827 ell->staparam = startAng;
2828 ell->endparam = endAng;
2829 ell->isccw = !el->isReversed();
2830 lData->objlist.push_back(ell);
2831 }
2832 }
2833 lData->update(); //change to DRW_HatchLoop
2834 ha.appendLoop(lData);
2835 }
2836 }
2837 dxfW->writeHatch(&ha);
2838 }
2839
2840
2841 /**
2842 * Writes the given Solid entity to the file.
2843 */
writeSolid(RS_Solid * s)2844 void RS_FilterDXFRW::writeSolid(RS_Solid* s) {
2845 RS_SolidData data;
2846 DRW_Solid solid;
2847 RS_Vector corner;
2848 getEntityAttributes(&solid, s);
2849 corner = s->getCorner(0);
2850 solid.basePoint.x = corner.x;
2851 solid.basePoint.y = corner.y;
2852 corner = s->getCorner(1);
2853 solid.secPoint.x = corner.x;
2854 solid.secPoint.y = corner.y;
2855 corner = s->getCorner(2);
2856 solid.thirdPoint.x = corner.x;
2857 solid.thirdPoint.y = corner.y;
2858 if (s->isTriangle()) {
2859 solid.fourPoint.x = solid.thirdPoint.x;
2860 solid.fourPoint.y = solid.thirdPoint.y;
2861 } else {
2862 corner = s->getCorner(3);
2863 solid.fourPoint.x = corner.x;
2864 solid.fourPoint.y = corner.y;
2865 }
2866 dxfW->writeSolid(&solid);
2867 }
2868
2869
writeImage(RS_Image * i)2870 void RS_FilterDXFRW::writeImage(RS_Image * i) {
2871 DRW_Image image;
2872 getEntityAttributes(&image, i);
2873
2874 image.basePoint.x = i->getInsertionPoint().x;
2875 image.basePoint.y = i->getInsertionPoint().y;
2876 image.secPoint.x = i->getUVector().x;
2877 image.secPoint.y = i->getUVector().y;
2878 image.vVector.x = i->getVVector().x;
2879 image.vVector.y = i->getVVector().y;
2880 image.sizeu = i->getWidth();
2881 image.sizev = i->getHeight();
2882 image.brightness = i->getBrightness();
2883 image.contrast = i->getContrast();
2884 image.fade = i->getFade();
2885
2886 DRW_ImageDef *imgDef = dxfW->writeImage(&image, i->getFile().toUtf8().data());
2887 if (imgDef ) {
2888 imgDef->loaded = 1;
2889 imgDef->u = i->getData().size.x;
2890 imgDef->v = i->getData().size.y;
2891 imgDef->up = 1;
2892 imgDef->vp = 1;
2893 imgDef->resolution = 0;
2894 }
2895 }
2896
2897
2898
2899 /*void RS_FilterDXFRW::writeEntityContainer(DL_WriterA& dw, RS_EntityContainer* con,
2900 const DRW_Entity& attrib) {
2901 QString blkName;
2902 blkName = "__CE";
2903
2904 // Creating an unique ID from the element ID
2905 int tmp, c=1; // tmp = temporary var c = counter var
2906 tmp = con->getId();
2907
2908 while (true) {
2909 tmp = tmp/c;
2910 blkName.append((char) tmp %10 + 48);
2911 c *= 10;
2912 if (tmp < 10) {
2913 break;
2914 }
2915 }
2916
2917 //Block definition
2918 dw.sectionTables();
2919 dxf.writeBlockRecord(dw);
2920 dw.dxfString( 0, "BLOCK_RECORD");
2921
2922 dw.handle();
2923 dw.dxfHex(330, 1);
2924 dw.dxfString(100, "AcDbSymbolTableRecord");
2925 dw.dxfString(100, "AcDbBlockTableRecord");
2926 dw.dxfString( 2, blkName.toLatin1().data());
2927 dw.dxfHex(340, 0);
2928 dw.dxfString(0, "ENDTAB");
2929
2930 //Block creation
2931 RS_BlockData blkdata(blkName, RS_Vector(0,0), false);
2932
2933 RS_Block* blk = new RS_Block(graphic, blkdata);
2934
2935 for (RS_Entity* e1 = con->firstEntity(); e1 ;
2936 e1 = con->nextEntity() ) {
2937 blk->addEntity(e1);
2938 }
2939 writeBlock(dw, blk);
2940 //delete e1;
2941 }*/
2942
2943
2944
2945 /**
2946 * Writes the atomic entities of the given container to the file.
2947 */
2948 /*void RS_FilterDXFRW::writeAtomicEntities(DL_WriterA& dw, RS_EntityContainer* c,
2949 const DRW_Entity& attrib,
2950 RS2::ResolveLevel level) {
2951
2952 for (RS_Entity* e=c->firstEntity(level);
2953 e;
2954 e=c->nextEntity(level)) {
2955
2956 writeEntity(dw, e, attrib);
2957 }
2958 }*/
2959
2960
2961 /**
2962 * Sets the entities attributes according to the attributes
2963 * that come from a DXF file.
2964 */
setEntityAttributes(RS_Entity * entity,const DRW_Entity * attrib)2965 void RS_FilterDXFRW::setEntityAttributes(RS_Entity* entity,
2966 const DRW_Entity* attrib) {
2967 RS_DEBUG->print("RS_FilterDXF::setEntityAttributes");
2968
2969 RS_Pen pen;
2970 pen.setColor(Qt::black);
2971 pen.setLineType(RS2::SolidLine);
2972 QString layName = toNativeString(QString::fromUtf8(attrib->layer.c_str()));
2973
2974 // Layer: add layer in case it doesn't exist:
2975 if (!graphic->findLayer(layName)) {
2976 DRW_Layer lay;
2977 lay.name = attrib->layer;
2978 addLayer(lay);
2979 }
2980 entity->setLayer(layName);
2981
2982 // Color:
2983 if (attrib->color24 >= 0)
2984 pen.setColor(RS_Color(attrib->color24 >> 16,
2985 attrib->color24 >> 8 & 0xFF,
2986 attrib->color24 & 0xFF));
2987 else
2988 pen.setColor(numberToColor(attrib->color));
2989
2990 // Linetype:
2991 pen.setLineType(nameToLineType( QString::fromUtf8(attrib->lineType.c_str()) ));
2992
2993 // Width:
2994 pen.setWidth(numberToWidth(attrib->lWeight));
2995
2996 entity->setPen(pen);
2997 RS_DEBUG->print("RS_FilterDXF::setEntityAttributes: OK");
2998 }
2999
3000
3001
3002 /**
3003 * Gets the entities attributes as a DL_Attributes object.
3004 */
getEntityAttributes(DRW_Entity * ent,const RS_Entity * entity)3005 void RS_FilterDXFRW::getEntityAttributes(DRW_Entity* ent, const RS_Entity* entity) {
3006 //DRW_Entity RS_FilterDXFRW::getEntityAttributes(RS_Entity* /*entity*/) {
3007
3008 // Layer:
3009 RS_Layer* layer = entity->getLayer();
3010 QString layerName;
3011 if (layer) {
3012 layerName = layer->getName();
3013 } else {
3014 layerName = "0";
3015 }
3016
3017 RS_Pen pen = entity->getPen(false);
3018
3019 // Color:
3020 int exact_rgb;
3021 int color = colorToNumber(pen.getColor(), &exact_rgb);
3022 //printf("Color is: %s -> %d\n", pen.getColor().name().toLatin1().data(), color);
3023
3024 // Linetype:
3025 QString lineType = lineTypeToName(pen.getLineType());
3026
3027 // Width:
3028 DRW_LW_Conv::lineWidth width = widthToNumber(pen.getWidth());
3029
3030 ent->layer = toDxfString(layerName).toUtf8().data();
3031 ent->color = color;
3032 ent->color24 = exact_rgb;
3033 ent->lWeight = width;
3034 ent->lineType = lineType.toUtf8().data();
3035 }
3036
3037
3038
3039 /**
3040 * @return Pen with the same attributes as 'attrib'.
3041 */
attributesToPen(const DRW_Layer * att) const3042 RS_Pen RS_FilterDXFRW::attributesToPen(const DRW_Layer* att) const {
3043
3044 RS_Color col;
3045 if (att->color24 >= 0)
3046 col = RS_Color(att->color24 >> 16,
3047 att->color24 >> 8 & 0xFF,
3048 att->color24 & 0xFF);
3049 else
3050 col = numberToColor(att->color);
3051
3052 RS_Pen pen(col, numberToWidth(att->lWeight),
3053 nameToLineType(QString::fromUtf8(att->lineType.c_str())) );
3054 return pen;
3055 }
3056
3057
3058
3059 /**
3060 * Converts a color index (num) into a RS_Color object.
3061 * Please refer to the dxflib documentation for details.
3062 *
3063 * @param num Color number.
3064 */
numberToColor(int num)3065 RS_Color RS_FilterDXFRW::numberToColor(int num) {
3066 if (num==0) {
3067 return RS_Color(RS2::FlagByBlock);
3068 } else if (num==256) {
3069 return RS_Color(RS2::FlagByLayer);
3070 } else if (num<=255 && num>=0) {
3071 return RS_Color(DRW::dxfColors[num][0],
3072 DRW::dxfColors[num][1],
3073 DRW::dxfColors[num][2]);
3074 } else {
3075 RS_DEBUG->print(RS_Debug::D_WARNING,
3076 "RS_FilterDXF::numberToColor: Invalid color number given.");
3077 return RS_Color(RS2::FlagByLayer);
3078 }
3079
3080 return RS_Color();
3081 }
3082
3083
3084
3085 /**
3086 * Converts a color into a color number in the DXF palette.
3087 * The color that fits best is chosen.
3088 */
colorToNumber(const RS_Color & col,int * rgb)3089 int RS_FilterDXFRW::colorToNumber(const RS_Color& col, int *rgb) {
3090
3091 //printf("Searching color for %s\n", col.name().toLatin1().data());
3092
3093 *rgb = -1;
3094 // Special color BYBLOCK:
3095 if (col.getFlag(RS2::FlagByBlock)) {
3096 return 0;
3097 }
3098
3099 // Special color BYLAYER
3100 else if (col.getFlag(RS2::FlagByLayer)) {
3101 return 256;
3102 }
3103
3104 // Special color black is not in the table but white represents both
3105 // black and white
3106 else if (col.red()==0 && col.green()==0 && col.blue()==0) {
3107 return 7;
3108 }
3109
3110 // All other colors
3111 else {
3112 int num=0;
3113 int diff=255*3; // smallest difference to a color in the table found so far
3114
3115 // Run through the whole table and compare
3116 for (int i=1; i<=255; i++) {
3117 int d = abs(col.red()-DRW::dxfColors[i][0])
3118 + abs(col.green()-DRW::dxfColors[i][1])
3119 + abs(col.blue()-DRW::dxfColors[i][2]);
3120
3121 if (d<diff) {
3122 /*
3123 printf("color %f,%f,%f is closer\n",
3124 dxfColors[i][0],
3125 dxfColors[i][1],
3126 dxfColors[i][2]);
3127 */
3128 diff = d;
3129 num = i;
3130 if (d==0) {
3131 break;
3132 }
3133 }
3134 }
3135 //printf(" Found: %d, diff: %d\n", num, diff);
3136 if(diff != 0) {
3137 *rgb = 0;
3138 *rgb = col.red()<<16 | col.green()<<8 | col.blue();
3139 }
3140 return num;
3141 }
3142 }
3143
add3dFace(const DRW_3Dface & data)3144 void RS_FilterDXFRW::add3dFace(const DRW_3Dface& data) {
3145 RS_DEBUG->print("RS_FilterDXFRW::add3dFace");
3146 RS_PolylineData d(RS_Vector(false),
3147 RS_Vector(false),
3148 !data.invisibleflag);
3149 RS_Polyline *polyline = new RS_Polyline(currentContainer, d);
3150 setEntityAttributes(polyline, &data);
3151 RS_Vector v1(data.basePoint.x, data.basePoint.y);
3152 RS_Vector v2(data.secPoint.x, data.secPoint.y);
3153 RS_Vector v3(data.thirdPoint.x, data.thirdPoint.y);
3154 RS_Vector v4(data.fourPoint.x, data.fourPoint.y);
3155
3156 polyline->addVertex(v1, 0.0);
3157 polyline->addVertex(v2, 0.0);
3158 polyline->addVertex(v3, 0.0);
3159 polyline->addVertex(v4, 0.0);
3160
3161 currentContainer->addEntity(polyline);
3162 }
3163
addComment(const char *)3164 void RS_FilterDXFRW::addComment(const char*) {
3165 RS_DEBUG->print("RS_FilterDXF::addComment(const char*) not yet implemented.");
3166 }
3167
addPlotSettings(const DRW_PlotSettings * data)3168 void RS_FilterDXFRW::addPlotSettings(const DRW_PlotSettings *data) {
3169 graphic->setPagesNum(QString::fromStdString(data->plotViewName));
3170 graphic->setMargins(data->marginLeft, data->marginTop,
3171 data->marginRight, data->marginBottom);
3172 }
3173
3174 /**
3175 * Converts a line type name (e.g. "CONTINUOUS") into a RS2::LineType
3176 * object.
3177 */
nameToLineType(const QString & name)3178 RS2::LineType RS_FilterDXFRW::nameToLineType(const QString& name) {
3179
3180 QString uName = name.toUpper();
3181
3182 // Standard linetypes for QCad II / AutoCAD
3183 if (uName.isEmpty() || uName=="BYLAYER") {
3184 return RS2::LineByLayer;
3185
3186 } else if (uName=="BYBLOCK") {
3187 return RS2::LineByBlock;
3188
3189 } else if (uName=="CONTINUOUS" || uName=="ACAD_ISO01W100") {
3190 return RS2::SolidLine;
3191
3192 } else if (uName=="ACAD_ISO07W100" || uName=="DOT") {
3193 return RS2::DotLine;
3194
3195 } else if (uName=="DOTTINY") {
3196 return RS2::DotLineTiny;
3197
3198 } else if (uName=="DOT2") {
3199 return RS2::DotLine2;
3200
3201 } else if (uName=="DOTX2") {
3202 return RS2::DotLineX2;
3203
3204
3205 } else if (uName=="ACAD_ISO02W100" || uName=="ACAD_ISO03W100" ||
3206 uName=="DASHED" || uName=="HIDDEN") {
3207 return RS2::DashLine;
3208
3209 } else if (uName=="DASHEDTINY" || uName=="HIDDEN2") {
3210 return RS2::DashLineTiny;
3211
3212 } else if (uName=="DASHED2" || uName=="HIDDEN2") {
3213 return RS2::DashLine2;
3214
3215 } else if (uName=="DASHEDX2" || uName=="HIDDENX2") {
3216 return RS2::DashLineX2;
3217
3218
3219 } else if (uName=="ACAD_ISO10W100" ||
3220 uName=="DASHDOT") {
3221 return RS2::DashDotLine;
3222
3223 } else if (uName=="DASHDOTTINY") {
3224 return RS2::DashDotLineTiny;
3225
3226 } else if (uName=="DASHDOT2") {
3227 return RS2::DashDotLine2;
3228
3229 } else if (uName=="ACAD_ISO04W100" ||
3230 uName=="DASHDOTX2") {
3231 return RS2::DashDotLineX2;
3232
3233
3234 } else if (uName=="ACAD_ISO12W100" || uName=="DIVIDE") {
3235 return RS2::DivideLine;
3236
3237 } else if (uName=="DIVIDETINY") {
3238 return RS2::DivideLineTiny;
3239
3240 } else if (uName=="DIVIDE2") {
3241 return RS2::DivideLine2;
3242
3243 } else if (uName=="ACAD_ISO05W100" || uName=="DIVIDEX2") {
3244 return RS2::DivideLineX2;
3245
3246
3247 } else if (uName=="CENTER") {
3248 return RS2::CenterLine;
3249
3250 } else if (uName=="CENTERTINY") {
3251 return RS2::CenterLineTiny;
3252
3253 } else if (uName=="CENTER2") {
3254 return RS2::CenterLine2;
3255
3256 } else if (uName=="CENTERX2") {
3257 return RS2::CenterLineX2;
3258
3259
3260 } else if (uName=="BORDER") {
3261 return RS2::BorderLine;
3262
3263 } else if (uName=="BORDERTINY") {
3264 return RS2::BorderLineTiny;
3265
3266 } else if (uName=="BORDER2") {
3267 return RS2::BorderLine2;
3268
3269 } else if (uName=="BORDERX2") {
3270 return RS2::BorderLineX2;
3271 }
3272
3273 return RS2::SolidLine;
3274 }
3275
3276
3277
3278 /**
3279 * Converts a RS_LineType into a name for a line type.
3280 */
lineTypeToName(RS2::LineType lineType)3281 QString RS_FilterDXFRW::lineTypeToName(RS2::LineType lineType) {
3282
3283 // Standard linetypes for QCad II / AutoCAD
3284 switch (lineType) {
3285
3286 case RS2::SolidLine:
3287 return "CONTINUOUS";
3288 break;
3289
3290 case RS2::DotLine:
3291 return "DOT";
3292 break;
3293 case RS2::DotLineTiny:
3294 return "DOTTINY";
3295 break;
3296 case RS2::DotLine2:
3297 return "DOT2";
3298 break;
3299 case RS2::DotLineX2:
3300 return "DOTX2";
3301 break;
3302
3303 case RS2::DashLine:
3304 return "DASHED";
3305 break;
3306 case RS2::DashLineTiny:
3307 return "DASHEDTINY";
3308 break;
3309 case RS2::DashLine2:
3310 return "DASHED2";
3311 break;
3312 case RS2::DashLineX2:
3313 return "DASHEDX2";
3314 break;
3315
3316 case RS2::DashDotLine:
3317 return "DASHDOT";
3318 break;
3319 case RS2::DashDotLineTiny:
3320 return "DASHDOTTINY";
3321 break;
3322 case RS2::DashDotLine2:
3323 return "DASHDOT2";
3324 break;
3325 case RS2::DashDotLineX2:
3326 return "DASHDOTX2";
3327 break;
3328
3329 case RS2::DivideLine:
3330 return "DIVIDE";
3331 break;
3332 case RS2::DivideLineTiny:
3333 return "DIVIDETINY";
3334 break;
3335 case RS2::DivideLine2:
3336 return "DIVIDE2";
3337 break;
3338 case RS2::DivideLineX2:
3339 return "DIVIDEX2";
3340 break;
3341
3342 case RS2::CenterLine:
3343 return "CENTER";
3344 break;
3345 case RS2::CenterLineTiny:
3346 return "CENTERTINY";
3347 break;
3348 case RS2::CenterLine2:
3349 return "CENTER2";
3350 break;
3351 case RS2::CenterLineX2:
3352 return "CENTERX2";
3353 break;
3354
3355 case RS2::BorderLine:
3356 return "BORDER";
3357 break;
3358 case RS2::BorderLineTiny:
3359 return "BORDERTINY";
3360 break;
3361 case RS2::BorderLine2:
3362 return "BORDER2";
3363 break;
3364 case RS2::BorderLineX2:
3365 return "BORDERX2";
3366 break;
3367
3368 case RS2::LineByLayer:
3369 return "ByLayer";
3370 break;
3371 case RS2::LineByBlock:
3372 return "ByBlock";
3373 break;
3374 default:
3375 break;
3376 }
3377
3378 return "CONTINUOUS";
3379 }
3380
3381
3382
3383 /**
3384 * Converts a RS_LineType into a name for a line type.
3385 */
3386 /*QString RS_FilterDXFRW::lineTypeToDescription(RS2::LineType lineType) {
3387
3388 // Standard linetypes for QCad II / AutoCAD
3389 switch (lineType) {
3390 case RS2::SolidLine:
3391 return "Solid line";
3392 case RS2::DotLine:
3393 return "ISO Dashed __ __ __ __ __ __ __ __ __ __ _";
3394 case RS2::DashLine:
3395 return "ISO Dashed with Distance __ __ __ _";
3396 case RS2::DashDotLine:
3397 return "ISO Long Dashed Dotted ____ . ____ . __";
3398 case RS2::DashDotDotLine:
3399 return "ISO Long Dashed Double Dotted ____ .. __";
3400 case RS2::LineByLayer:
3401 return "";
3402 case RS2::LineByBlock:
3403 return "";
3404 default:
3405 break;
3406 }
3407
3408 return "CONTINUOUS";
3409 }*/
3410
3411
3412
3413 /**
3414 * Converts a DRW_LW_Conv::lineWidth into a RS2::LineWidth.
3415 */
numberToWidth(DRW_LW_Conv::lineWidth lw)3416 RS2::LineWidth RS_FilterDXFRW::numberToWidth(DRW_LW_Conv::lineWidth lw) {
3417 switch (lw) {
3418 case DRW_LW_Conv::widthByLayer:
3419 return RS2::WidthByLayer;
3420 break;
3421 case DRW_LW_Conv::widthByBlock:
3422 return RS2::WidthByBlock;
3423 break;
3424 case DRW_LW_Conv::widthDefault:
3425 return RS2::WidthDefault;
3426 break;
3427 case DRW_LW_Conv::width00:
3428 return RS2::Width00;
3429 break;
3430 case DRW_LW_Conv::width01:
3431 return RS2::Width01;
3432 break;
3433 case DRW_LW_Conv::width02:
3434 return RS2::Width02;
3435 break;
3436 case DRW_LW_Conv::width03:
3437 return RS2::Width03;
3438 break;
3439 case DRW_LW_Conv::width04:
3440 return RS2::Width04;
3441 break;
3442 case DRW_LW_Conv::width05:
3443 return RS2::Width05;
3444 break;
3445 case DRW_LW_Conv::width06:
3446 return RS2::Width06;
3447 break;
3448 case DRW_LW_Conv::width07:
3449 return RS2::Width07;
3450 break;
3451 case DRW_LW_Conv::width08:
3452 return RS2::Width08;
3453 break;
3454 case DRW_LW_Conv::width09:
3455 return RS2::Width09;
3456 break;
3457 case DRW_LW_Conv::width10:
3458 return RS2::Width10;
3459 break;
3460 case DRW_LW_Conv::width11:
3461 return RS2::Width11;
3462 break;
3463 case DRW_LW_Conv::width12:
3464 return RS2::Width12;
3465 break;
3466 case DRW_LW_Conv::width13:
3467 return RS2::Width13;
3468 break;
3469 case DRW_LW_Conv::width14:
3470 return RS2::Width14;
3471 break;
3472 case DRW_LW_Conv::width15:
3473 return RS2::Width15;
3474 break;
3475 case DRW_LW_Conv::width16:
3476 return RS2::Width16;
3477 break;
3478 case DRW_LW_Conv::width17:
3479 return RS2::Width17;
3480 break;
3481 case DRW_LW_Conv::width18:
3482 return RS2::Width18;
3483 break;
3484 case DRW_LW_Conv::width19:
3485 return RS2::Width19;
3486 break;
3487 case DRW_LW_Conv::width20:
3488 return RS2::Width20;
3489 break;
3490 case DRW_LW_Conv::width21:
3491 return RS2::Width21;
3492 break;
3493 case DRW_LW_Conv::width22:
3494 return RS2::Width22;
3495 break;
3496 case DRW_LW_Conv::width23:
3497 return RS2::Width23;
3498 break;
3499 default:
3500 break;
3501 }
3502 return RS2::WidthDefault;
3503 }
3504
3505
3506
3507 /**
3508 * Converts a RS2::LineWidth into an DRW_LW_Conv::lineWidth.
3509 */
widthToNumber(RS2::LineWidth width)3510 DRW_LW_Conv::lineWidth RS_FilterDXFRW::widthToNumber(RS2::LineWidth width) {
3511 switch (width) {
3512 case RS2::WidthByLayer:
3513 return DRW_LW_Conv::widthByLayer;
3514 break;
3515 case RS2::WidthByBlock:
3516 return DRW_LW_Conv::widthByBlock;
3517 break;
3518 case RS2::WidthDefault:
3519 return DRW_LW_Conv::widthDefault;
3520 break;
3521 case RS2::Width00:
3522 return DRW_LW_Conv::width00;
3523 break;
3524 case RS2::Width01:
3525 return DRW_LW_Conv::width01;
3526 break;
3527 case RS2::Width02:
3528 return DRW_LW_Conv::width02;
3529 break;
3530 case RS2::Width03:
3531 return DRW_LW_Conv::width03;
3532 break;
3533 case RS2::Width04:
3534 return DRW_LW_Conv::width04;
3535 break;
3536 case RS2::Width05:
3537 return DRW_LW_Conv::width05;
3538 break;
3539 case RS2::Width06:
3540 return DRW_LW_Conv::width06;
3541 break;
3542 case RS2::Width07:
3543 return DRW_LW_Conv::width07;
3544 break;
3545 case RS2::Width08:
3546 return DRW_LW_Conv::width08;
3547 break;
3548 case RS2::Width09:
3549 return DRW_LW_Conv::width09;
3550 break;
3551 case RS2::Width10:
3552 return DRW_LW_Conv::width10;
3553 break;
3554 case RS2::Width11:
3555 return DRW_LW_Conv::width11;
3556 break;
3557 case RS2::Width12:
3558 return DRW_LW_Conv::width12;
3559 break;
3560 case RS2::Width13:
3561 return DRW_LW_Conv::width13;
3562 break;
3563 case RS2::Width14:
3564 return DRW_LW_Conv::width14;
3565 break;
3566 case RS2::Width15:
3567 return DRW_LW_Conv::width15;
3568 break;
3569 case RS2::Width16:
3570 return DRW_LW_Conv::width16;
3571 break;
3572 case RS2::Width17:
3573 return DRW_LW_Conv::width17;
3574 break;
3575 case RS2::Width18:
3576 return DRW_LW_Conv::width18;
3577 break;
3578 case RS2::Width19:
3579 return DRW_LW_Conv::width19;
3580 break;
3581 case RS2::Width20:
3582 return DRW_LW_Conv::width20;
3583 break;
3584 case RS2::Width21:
3585 return DRW_LW_Conv::width21;
3586 break;
3587 case RS2::Width22:
3588 return DRW_LW_Conv::width22;
3589 break;
3590 case RS2::Width23:
3591 return DRW_LW_Conv::width23;
3592 break;
3593 default:
3594 break;
3595 }
3596 return DRW_LW_Conv::widthDefault;
3597 }
3598
3599
3600 /**
3601 * Converts a native unicode string into a DXF encoded string.
3602 *
3603 * DXF endoding includes the following special sequences:
3604 * - %%%c for a diameter sign
3605 * - %%%d for a degree sign
3606 * - %%%p for a plus/minus sign
3607 */
toDxfString(const QString & str)3608 QString RS_FilterDXFRW::toDxfString(const QString& str) {
3609 QString res = "";
3610 int j=0;
3611 for (int i=0; i<str.length(); ++i) {
3612 int c = str.at(i).unicode();
3613 if (c>175 || c<11){
3614 res.append(str.mid(j,i-j));
3615 j=i;
3616
3617 switch (c) {
3618 case 0x0A:
3619 res+="\\P";
3620 break;
3621 // diameter:
3622 case 0x2205://RLZ: Empty_set, diameter is 0x2300 need to add in all fonts
3623 case 0x2300:
3624 res+="%%C";
3625 break;
3626 // degree:
3627 case 0x00B0:
3628 res+="%%D";
3629 break;
3630 // plus/minus
3631 case 0x00B1:
3632 res+="%%P";
3633 break;
3634 default:
3635 j--;
3636 break;
3637 }
3638 j++;
3639 }
3640
3641 }
3642 res.append(str.mid(j));
3643 return res;
3644 }
3645
3646
3647
3648 /**
3649 * Converts a DXF encoded string into a native Unicode string.
3650 */
toNativeString(const QString & data)3651 QString RS_FilterDXFRW::toNativeString(const QString& data) {
3652 QString res;
3653
3654 // Ignore font tags:
3655 int j = 0;
3656 for (int i=0; i<data.length(); ++i) {
3657 if (data.at(i).unicode() == 0x7B){ //is '{' ?
3658 if (data.at(i+1).unicode() == 0x5c){ //and is "{\" ?
3659 //check known codes
3660 if ( (data.at(i+2).unicode() == 0x66) || //is "\f" ?
3661 (data.at(i+2).unicode() == 0x48) || //is "\H" ?
3662 (data.at(i+2).unicode() == 0x43) //is "\C" ?
3663 ) {
3664 //found tag, append parsed part
3665 res.append(data.mid(j,i-j));
3666 int pos = data.indexOf(0x7D, i+3);//find '}'
3667 if (pos <0) break; //'}' not found
3668 QString tmp = data.mid(i+1, pos-i-1);
3669 do {
3670 tmp = tmp.remove(0,tmp.indexOf(0x3B, 0)+1 );//remove to ';'
3671 } while(tmp.startsWith("\\f") || tmp.startsWith("\\H") || tmp.startsWith("\\C"));
3672 res.append(tmp);
3673 i = j = pos;
3674 ++j;
3675 }
3676 }
3677 }
3678 }
3679 res.append(data.mid(j));
3680
3681 // Line feed:
3682 res = res.replace(QRegExp("\\\\P"), "\n");
3683 // Space:
3684 res = res.replace(QRegExp("\\\\~"), " ");
3685 // Tab:
3686 res = res.replace(QRegExp("\\^I"), " ");//RLZ: change 4 spaces for \t when mtext have support for tab
3687 // diameter:
3688 res = res.replace(QRegExp("%%[cC]"), QChar(0x2300));//RLZ: Empty_set is 0x2205, diameter is 0x2300 need to add in all fonts
3689 // degree:
3690 res = res.replace(QRegExp("%%[dD]"), QChar(0x00B0));
3691 // plus/minus
3692 res = res.replace(QRegExp("%%[pP]"), QChar(0x00B1));
3693
3694 return res;
3695 }
3696
3697
3698
3699 /**
3700 * Converts the given number from a DXF file into an AngleFormat enum.
3701 *
3702 * @param num $DIMAUNIT from DXF (0: decimal deg, 1: deg/min/sec, 2: gradians,
3703 * 3: radians, 4: surveyor's units)
3704 *
3705 * @ret Matching AngleFormat enum value.
3706 */
numberToAngleFormat(int num)3707 RS2::AngleFormat RS_FilterDXFRW::numberToAngleFormat(int num) {
3708
3709 RS2::AngleFormat af;
3710
3711 switch (num) {
3712 default:
3713 case 0:
3714 af = RS2::DegreesDecimal;
3715 break;
3716 case 1:
3717 af = RS2::DegreesMinutesSeconds;
3718 break;
3719 case 2:
3720 af = RS2::Gradians;
3721 break;
3722 case 3:
3723 af = RS2::Radians;
3724 break;
3725 case 4:
3726 af = RS2::Surveyors;
3727 break;
3728 }
3729
3730 return af;
3731 }
3732
3733
3734 /**
3735 * Converts AngleFormat enum to DXF number.
3736 */
angleFormatToNumber(RS2::AngleFormat af)3737 int RS_FilterDXFRW::angleFormatToNumber(RS2::AngleFormat af) {
3738
3739 int num;
3740
3741 switch (af) {
3742 default:
3743 case RS2::DegreesDecimal:
3744 num = 0;
3745 break;
3746 case RS2::DegreesMinutesSeconds:
3747 num = 1;
3748 break;
3749 case RS2::Gradians:
3750 num = 2;
3751 break;
3752 case RS2::Radians:
3753 num = 3;
3754 break;
3755 case RS2::Surveyors:
3756 num = 4;
3757 break;
3758 }
3759
3760 return num;
3761 }
3762
3763
3764
3765 /**
3766 * converts a DXF unit setting (e.g. INSUNITS) to a unit enum.
3767 */
numberToUnit(int num)3768 RS2::Unit RS_FilterDXFRW::numberToUnit(int num) {
3769 switch (num) {
3770 default:
3771 case 0:
3772 return RS2::None;
3773 break;
3774 case 1:
3775 return RS2::Inch;
3776 break;
3777 case 2:
3778 return RS2::Foot;
3779 break;
3780 case 3:
3781 return RS2::Mile;
3782 break;
3783 case 4:
3784 return RS2::Millimeter;
3785 break;
3786 case 5:
3787 return RS2::Centimeter;
3788 break;
3789 case 6:
3790 return RS2::Meter;
3791 break;
3792 case 7:
3793 return RS2::Kilometer;
3794 break;
3795 case 8:
3796 return RS2::Microinch;
3797 break;
3798 case 9:
3799 return RS2::Mil;
3800 break;
3801 case 10:
3802 return RS2::Yard;
3803 break;
3804 case 11:
3805 return RS2::Angstrom;
3806 break;
3807 case 12:
3808 return RS2::Nanometer;
3809 break;
3810 case 13:
3811 return RS2::Micron;
3812 break;
3813 case 14:
3814 return RS2::Decimeter;
3815 break;
3816 case 15:
3817 return RS2::Decameter;
3818 break;
3819 case 16:
3820 return RS2::Hectometer;
3821 break;
3822 case 17:
3823 return RS2::Gigameter;
3824 break;
3825 case 18:
3826 return RS2::Astro;
3827 break;
3828 case 19:
3829 return RS2::Lightyear;
3830 break;
3831 case 20:
3832 return RS2::Parsec;
3833 break;
3834 }
3835
3836 return RS2::None;
3837 }
3838
3839
3840
3841 /**
3842 * Converts a unit enum into a DXF unit number e.g. for INSUNITS.
3843 */
unitToNumber(RS2::Unit unit)3844 int RS_FilterDXFRW::unitToNumber(RS2::Unit unit) {
3845 switch (unit) {
3846 default:
3847 case RS2::None:
3848 return 0;
3849 break;
3850 case RS2::Inch:
3851 return 1;
3852 break;
3853 case RS2::Foot:
3854 return 2;
3855 break;
3856 case RS2::Mile:
3857 return 3;
3858 break;
3859 case RS2::Millimeter:
3860 return 4;
3861 break;
3862 case RS2::Centimeter:
3863 return 5;
3864 break;
3865 case RS2::Meter:
3866 return 6;
3867 break;
3868 case RS2::Kilometer:
3869 return 7;
3870 break;
3871 case RS2::Microinch:
3872 return 8;
3873 break;
3874 case RS2::Mil:
3875 return 9;
3876 break;
3877 case RS2::Yard:
3878 return 10;
3879 break;
3880 case RS2::Angstrom:
3881 return 11;
3882 break;
3883 case RS2::Nanometer:
3884 return 12;
3885 break;
3886 case RS2::Micron:
3887 return 13;
3888 break;
3889 case RS2::Decimeter:
3890 return 14;
3891 break;
3892 case RS2::Decameter:
3893 return 15;
3894 break;
3895 case RS2::Hectometer:
3896 return 16;
3897 break;
3898 case RS2::Gigameter:
3899 return 17;
3900 break;
3901 case RS2::Astro:
3902 return 18;
3903 break;
3904 case RS2::Lightyear:
3905 return 19;
3906 break;
3907 case RS2::Parsec:
3908 return 20;
3909 break;
3910 }
3911
3912 return 0;
3913 }
3914
3915
3916
3917 /**
3918 * Checks if the given variable is two-dimensional (e.g. $LIMMIN).
3919 */
isVariableTwoDimensional(const QString & var)3920 bool RS_FilterDXFRW::isVariableTwoDimensional(const QString& var) {
3921 if (var=="$LIMMIN" ||
3922 var=="$LIMMAX" ||
3923 var=="$PLIMMIN" ||
3924 var=="$PLIMMAX" ||
3925 var=="$GRIDUNIT" ||
3926 var=="$VIEWCTR") {
3927
3928 return true;
3929 } else {
3930 return false;
3931 }
3932 }
3933
3934 #ifdef DWGSUPPORT
printDwgVersion(int v)3935 QString RS_FilterDXFRW::printDwgVersion(int v){
3936 switch (v) {
3937 case DRW::AC1006:
3938 return "10";
3939 break;
3940 case DRW::AC1009:
3941 return "dwg version 11 or 12";
3942 case DRW::AC1012:
3943 return "dwg version 13";
3944 case DRW::AC1014:
3945 return "dwg version 14";
3946 case DRW::AC1015:
3947 return "dwg version 2000";
3948 case DRW::AC1018:
3949 return "dwg version 2004";
3950 case DRW::AC1021:
3951 return "dwg version 2007";
3952 case DRW::AC1024:
3953 return "dwg version 2010";
3954 case DRW::AC1027:
3955 return "dwg version 2013";
3956 default:
3957 return "unknown";
3958 }
3959 }
3960
printDwgError(int le)3961 void RS_FilterDXFRW::printDwgError(int le){
3962 switch (le) {
3963 case DRW::BAD_UNKNOWN:
3964 RS_DIALOGFACTORY->commandMessage(QObject::tr("unknown error opening dwg file"));
3965 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_UNKNOWN");
3966 break;
3967 case DRW::BAD_OPEN:
3968 RS_DIALOGFACTORY->commandMessage(QObject::tr("can't open this dwg file"));
3969 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_OPEN");
3970 break;
3971 case DRW::BAD_VERSION:
3972 RS_DIALOGFACTORY->commandMessage(QObject::tr("unsupported dwg version"));
3973 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_VERSION");
3974 break;
3975 case DRW::BAD_READ_METADATA:
3976 RS_DIALOGFACTORY->commandMessage(QObject::tr("error reading file metadata in dwg file"));
3977 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_READ_FILE_HEADER");
3978 break;
3979 case DRW::BAD_READ_FILE_HEADER:
3980 RS_DIALOGFACTORY->commandMessage(QObject::tr("error reading file header in dwg file"));
3981 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_READ_FILE_HEADER");
3982 break;
3983 case DRW::BAD_READ_HEADER:
3984 RS_DIALOGFACTORY->commandMessage(QObject::tr("error reading header vars in dwg file"));
3985 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_READ_HEADER");
3986 break;
3987 case DRW::BAD_READ_CLASSES:
3988 RS_DIALOGFACTORY->commandMessage(QObject::tr("error reading classes in dwg file"));
3989 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_READ_CLASSES");
3990 break;
3991 case DRW::BAD_READ_HANDLES:
3992 RS_DIALOGFACTORY->commandMessage(QObject::tr("error reading offsets in dwg file"));
3993 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_READ_OFFSETS");
3994 break;
3995 case DRW::BAD_READ_TABLES:
3996 RS_DIALOGFACTORY->commandMessage(QObject::tr("error reading tables in dwg file"));
3997 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_READ_TABLES");
3998 break;
3999 case DRW::BAD_READ_BLOCKS:
4000 RS_DIALOGFACTORY->commandMessage(QObject::tr("error reading blocks in dwg file"));
4001 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_READ_OFFSETS");
4002 break;
4003 case DRW::BAD_READ_ENTITIES:
4004 RS_DIALOGFACTORY->commandMessage(QObject::tr("error reading entities in dwg file"));
4005 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_READ_ENTITIES");
4006 break;
4007 case DRW::BAD_READ_OBJECTS:
4008 RS_DIALOGFACTORY->commandMessage(QObject::tr("error reading objects in dwg file"));
4009 RS_DEBUG->print("RS_FilterDXFRW::printDwgError: DRW::BAD_READ_OBJECTS");
4010 break;
4011 default:
4012 break;
4013 }
4014 }
4015 #endif
4016
4017 // EOF
4018
4019