/****************************************************************************** ** ** ** Copyright (C) 2015 José F. Soriano, rallazz@gmail.com ** ** ** ** This library is free software, licensed under the terms of the GNU ** ** General Public License as published by the Free Software Foundation, ** ** either version 2 of the License, or (at your option) any later version. ** ** You should have received a copy of the GNU General Public License ** ** along with this program. If not, see . ** ******************************************************************************/ #include "dxiface.h" #include "../vmisc/vabstractapplication.h" #include "libdxfrw/drw_entities.h" #include "libdxfrw/libdxfrw.h" #include #include #include #include #include dx_iface::dx_iface(const std::string &file, DRW::Version v, VarMeasurement varMeasurement, VarInsunits varInsunits) : dxfW(new dxfRW(file.c_str())), cData(), version(v) { InitHeader(varMeasurement, varInsunits); InitTextstyles(); InitVPorts(); InitAppId(); } dx_iface::~dx_iface() { delete dxfW; } auto dx_iface::fileExport(bool binary) -> bool { bool success = dxfW->write(this, version, binary); return success; } void dx_iface::writeEntity(DRW_Entity *e) { switch (e->eType) { case DRW::POINT: dxfW->writePoint(static_cast(e)); break; case DRW::ASTMNOTCH: dxfW->writeASTMNotch(static_cast(e)); break; case DRW::ATTDEF: dxfW->writeATTDEF(static_cast(e)); break; case DRW::LINE: dxfW->writeLine(static_cast(e)); break; case DRW::CIRCLE: dxfW->writeCircle(static_cast(e)); break; case DRW::ARC: dxfW->writeArc(static_cast(e)); break; case DRW::SOLID: dxfW->writeSolid(static_cast(e)); break; case DRW::ELLIPSE: dxfW->writeEllipse(static_cast(e)); break; case DRW::LWPOLYLINE: dxfW->writeLWPolyline(static_cast(e)); break; case DRW::POLYLINE: dxfW->writePolyline(static_cast(e)); break; case DRW::SPLINE: dxfW->writeSpline(static_cast(e)); break; // case RS2::EntitySplinePoints: // writeSplinePoints(static_cast(e)); // break; // case RS2::EntityVertex: // break; case DRW::INSERT: dxfW->writeInsert(static_cast(e)); break; case DRW::MTEXT: dxfW->writeMText(static_cast(e)); break; case DRW::TEXT: dxfW->writeText(static_cast(e)); break; case DRW::DIMLINEAR: case DRW::DIMALIGNED: case DRW::DIMANGULAR: case DRW::DIMANGULAR3P: case DRW::DIMRADIAL: case DRW::DIMDIAMETRIC: case DRW::DIMORDINATE: dxfW->writeDimension(static_cast(e)); break; case DRW::LEADER: dxfW->writeLeader(static_cast(e)); break; case DRW::HATCH: dxfW->writeHatch(static_cast(e)); break; case DRW::IMAGE: dxfW->writeImage(static_cast(e), static_cast(e)->path); break; default: break; } } auto dx_iface::ErrorString() const -> std::string { return dxfW->ErrorString(); } void dx_iface::writeHeader(DRW_Header &data) { // complete copy of header vars: data = cData.headerC; // or copy one by one: // for (auto it=cData->headerC.vars.begin(); it != cData->headerC.vars.end(); ++it) // data.vars[it->first] = new DRW_Variant( *(it->second) ); } void dx_iface::writeBlocks() { // write each block for (auto *bk : cData.blocks) { dxfW->writeBlock(bk); // and write each entity in block for (std::list::const_iterator it = bk->ent.begin(); it != bk->ent.end(); ++it) writeEntity(*it); } } void dx_iface::writeBlockRecords() { for (std::list::iterator it = cData.blocks.begin(); it != cData.blocks.end(); ++it) dxfW->writeBlockRecord((*it)->name); } void dx_iface::writeEntities() { for (std::list::const_iterator it = cData.mBlock->ent.begin(); it != cData.mBlock->ent.end(); ++it) writeEntity(*it); } void dx_iface::writeLTypes() { for (std::list::iterator it = cData.lineTypes.begin(); it != cData.lineTypes.end(); ++it) dxfW->writeLineType(&(*it)); } void dx_iface::writeLayers() { for (std::list::iterator it = cData.layers.begin(); it != cData.layers.end(); ++it) dxfW->writeLayer(&(*it)); } void dx_iface::writeTextstyles() { for (std::list::iterator it = cData.textStyles.begin(); it != cData.textStyles.end(); ++it) dxfW->writeTextstyle(&(*it)); } void dx_iface::writeVports() { for (std::list::iterator it = cData.VPorts.begin(); it != cData.VPorts.end(); ++it) dxfW->writeVport(&(*it)); } void dx_iface::writeDimstyles() { for (std::list::iterator it = cData.dimStyles.begin(); it != cData.dimStyles.end(); ++it) dxfW->writeDimstyle(&(*it)); } void dx_iface::writeObjects() { // default implementation for new DRW_Interface method } void dx_iface::writeAppId() { for (auto it = cData.appIds.begin(); it != cData.appIds.end(); ++it) dxfW->writeAppId(&(*it)); } void dx_iface::InitHeader(VarMeasurement varMeasurement, VarInsunits varInsunits) { cData.headerC.addComment("Valentina DXF File"); // 1 = Clockwise angles, 0 = Counterclockwise cData.headerC.addInt("$ANGDIR", 0, 70); // Qt use counterclockwise // Sets drawing units: 0 = English; 1 = Metric cData.headerC.addInt("$MEASUREMENT", static_cast(varMeasurement), 70); cData.headerC.addInt("$INSUNITS", static_cast(varInsunits), 70); QString dateTime = QDateTime::currentDateTime().toString("yyyyMMdd.HHmmsszzz"); dateTime.chop(1); // we need hundredths of a second cData.headerC.addStr("$TDCREATE", dateTime.toStdString(), 40); if (version >= DRW::AC1021) { // Full support Unicode cData.headerC.addStr("$DWGCODEPAGE", "UTF-8", 3); } else { cData.headerC.addStr("$DWGCODEPAGE", LocaleToISO(), 3); } } auto dx_iface::QtPenStyleToString(Qt::PenStyle style) -> UTF8STRING { switch (style) { case Qt::DashLine: return "DASHED"; case Qt::DotLine: return "DOT"; case Qt::DashDotLine: return "DASHDOT2"; case Qt::DashDotDotLine: return "DIVIDE2"; case Qt::NoPen: case Qt::SolidLine: default: return "CONTINUOUS"; } } void dx_iface::AddQtLTypes() { DRW_LType ltype; ltype.name = "DOT"; ltype.desc = "Dot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ."; ltype.size = 2; ltype.length = 0.125; ltype.path.push_back(0.0); ltype.path.push_back(-0.125); cData.lineTypes.push_back(ltype); ltype.path.clear(); ltype.name = "DASHED"; ltype.desc = "Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _"; ltype.size = 2; ltype.length = 0.375; ltype.path.push_back(0.25); ltype.path.push_back(-0.125); cData.lineTypes.push_back(ltype); ltype.path.clear(); ltype.name = "DASHDOT2"; ltype.desc = "Dash dot2 _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._."; ltype.size = 4; ltype.length = 0.5; ltype.path.push_back(0.25); ltype.path.push_back(-0.125); ltype.path.push_back(0.0); ltype.path.push_back(-0.125); cData.lineTypes.push_back(ltype); ltype.path.clear(); ltype.name = "DIVIDE2"; ltype.desc = "Divide2 __..__..__..__..__..__..__..__..__..__..__..__..__..__..__..__.."; ltype.size = 6; ltype.length = 0.625; ltype.path.push_back(0.25); ltype.path.push_back(-0.125); ltype.path.push_back(0.0); ltype.path.push_back(-0.125); ltype.path.push_back(0.0); ltype.path.push_back(-0.125); cData.lineTypes.push_back(ltype); } void dx_iface::AddAAMALayers() { DRW_Layer layer; layer.name = '1'; // CUT, OUTLINE layer.color = DRW::black; cData.layers.push_back(layer); layer.name = '8'; // DRAW, INK layer.color = DRW::black; cData.layers.push_back(layer); layer.name = '7'; // GRAINLINE layer.color = DRW::black; cData.layers.push_back(layer); // layer.name = '6';// MIRROR LINES // layer.color = DRW::black; // cData.layers.push_back(layer); layer.name = "11"; // INTCUT layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "13"; // DRILL layer.color = DRW::black; cData.layers.push_back(layer); layer.name = '4'; // NOTCH layer.color = DRW::black; cData.layers.push_back(layer); // Optitex doesn't like this layer // layer.name = "19";// TEXT // layer.color = DRW::black; // cData.layers.push_back(layer); // layer.name = "26";// REF // layer.color = DRW::black; // cData.layers.push_back(layer); } void dx_iface::AddDefHeaderData() { cData.headerC.addInt("$HANDLING", 1, 70); // Enabled by default for flat version. } void dx_iface::AddAAMAHeaderData() { cData.headerC.addStr("$CLAYER", "1", 8); // Current layer name // Looks like doesn't work with handling enabled. // Missing or 0 for $HANDLING value disables handling. } void dx_iface::AddASTMLayers() { DRW_Layer layer; layer.name = '1'; // piece boundary layer.color = DRW::black; cData.layers.push_back(layer); // Do not support // layer.name = '2';// turn points // layer.color = DRW::black; // cData.layers.push_back(layer); // Do not support // layer.name = '3';// curve points // layer.color = DRW::black; // cData.layers.push_back(layer); layer.name = '4'; // V-notch and slit notch layer.color = DRW::black; cData.layers.push_back(layer); // Do not support // layer.name = '5';// grade reference and alternate grade reference line(s) // layer.color = DRW::black; // cData.layers.push_back(layer); // Do not support // layer.name = '6';// mirror line // layer.color = DRW::black; // cData.layers.push_back(layer); layer.name = '7'; // grainline layer.color = DRW::black; cData.layers.push_back(layer); layer.name = '8'; // internal line(s) layer.color = DRW::black; cData.layers.push_back(layer); // Do not support // layer.name = '9';// stripe reference line(s) // layer.color = DRW::black; // cData.layers.push_back(layer); // Do not support // layer.name = '10';// plaid reference line(s) // layer.color = DRW::black; // cData.layers.push_back(layer); layer.name = "11"; // internal cutout(s) layer.color = DRW::black; cData.layers.push_back(layer); // Layer 12 intentionally left blank by the standard layer.name = "13"; // drill holes layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "14"; // sew line(s) layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "15"; // annotation text layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "80"; // T-notch layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "81"; // castle notch layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "82"; // check notch layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "83"; // U-notch layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "84"; // piece boundary quality validation curves layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "85"; // internal lines quality validation curves layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "86"; // internal cutouts quality validation curves layer.color = DRW::black; cData.layers.push_back(layer); layer.name = "87"; // sew lines quality validation curves layer.color = DRW::black; cData.layers.push_back(layer); } void dx_iface::AddDefLayers() { DRW_Layer defLayer; defLayer.name = '0'; defLayer.color = DRW::black; // default color defLayer.lWeight = DRW_LW_Conv::width03; // default width cData.layers.push_back(defLayer); } void dx_iface::InitTextstyles() { DRW_Textstyle style; style.name = "Standard"; style.lastHeight = 2.5; style.font = "txt"; cData.textStyles.push_back(style); } void dx_iface::InitVPorts() { DRW_Vport vport; vport.name = "*ACTIVE"; vport.height = 297.0; cData.VPorts.push_back(vport); } void dx_iface::InitAppId() { DRW_AppId ai; ai.name = "Valentina"; cData.appIds.push_back(ai); } void dx_iface::AddEntity(DRW_Entity *e) { cData.mBlock->ent.push_back(e); } auto dx_iface::AddFont(const QFont &f) -> UTF8STRING { DRW_Textstyle ts; ts.name = f.family().toUpper().toStdString(); // Idea source https://stackoverflow.com/questions/20111522/writing-text-styles-into-dxf-from-a-delphi-application if (f.bold()) { ts.name += "_BOLD"; ts.fontFamily += 0x2000000; } if (f.italic()) { ts.name += "_ITALIC"; ts.fontFamily += 0x1000000; } for (auto it = cData.textStyles.begin(); it != cData.textStyles.end(); ++it) { if ((*it).name == ts.name) { return ts.name; } } ts.font = f.family().toStdString(); cData.textStyles.push_back(ts); return ts.name; } void dx_iface::AddBlock(dx_ifaceBlock *block) { cData.blocks.push_back(block); } auto dx_iface::LocaleToISO() -> std::string { QMap locMap = LocaleMap(); return locMap.value(QLocale(VAbstractApplication::VApp()->Settings()->GetLocale()).name(), "ISO8859-1") .toStdString(); }