LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/dxf - ogr_dxf.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 158 174 90.8 %
Date: 2025-01-18 02:53:07 Functions: 47 55 85.5 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  DXF Translator
       4             :  * Purpose:  Definition of classes for OGR .dxf driver.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2009,  Frank Warmerdam
       9             :  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  * Copyright (c) 2017, Alan Thomas <alant@outlook.com.au>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #ifndef OGR_DXF_H_INCLUDED
      16             : #define OGR_DXF_H_INCLUDED
      17             : 
      18             : #include "ogrsf_frmts.h"
      19             : #include "ogr_autocad_services.h"
      20             : #include "cpl_conv.h"
      21             : #include <vector>
      22             : #include <map>
      23             : #include <set>
      24             : #include <queue>
      25             : #include <memory>
      26             : 
      27             : class OGRDXFDataSource;
      28             : class OGRDXFFeature;
      29             : 
      30             : /************************************************************************/
      31             : /*                          DXFBlockDefinition                          */
      32             : /*                                                                      */
      33             : /*      Container for info about a block.                               */
      34             : /************************************************************************/
      35             : 
      36             : class DXFBlockDefinition
      37             : {
      38             :   public:
      39          75 :     DXFBlockDefinition()
      40          75 :     {
      41          75 :     }
      42             : 
      43             :     ~DXFBlockDefinition();
      44             : 
      45             :     std::vector<OGRDXFFeature *> apoFeatures;
      46             : };
      47             : 
      48             : /************************************************************************/
      49             : /*                         OGRDXFFeatureQueue                           */
      50             : /************************************************************************/
      51             : 
      52             : class OGRDXFFeatureQueue
      53             : {
      54             :     std::queue<OGRDXFFeature *> apoFeatures;
      55             : 
      56             :   public:
      57         571 :     OGRDXFFeatureQueue()
      58         571 :     {
      59         571 :     }
      60             : 
      61             :     void push(OGRDXFFeature *poFeature);
      62             : 
      63        1736 :     OGRDXFFeature *front() const
      64             :     {
      65        1736 :         return apoFeatures.front();
      66             :     }
      67             : 
      68             :     void pop();
      69             : 
      70        5977 :     bool empty() const
      71             :     {
      72        5977 :         return apoFeatures.empty();
      73             :     }
      74             : 
      75             :     size_t size() const
      76             :     {
      77             :         return apoFeatures.size();
      78             :     }
      79             : };
      80             : 
      81             : /************************************************************************/
      82             : /*                          OGRDXFBlocksLayer                           */
      83             : /************************************************************************/
      84             : 
      85             : class OGRDXFBlocksLayer final : public OGRLayer
      86             : {
      87             :     OGRDXFDataSource *poDS;
      88             : 
      89             :     OGRFeatureDefn *poFeatureDefn;
      90             : 
      91             :     GIntBig iNextFID;
      92             : 
      93             :     std::map<CPLString, DXFBlockDefinition>::iterator oIt;
      94             :     CPLString osBlockName;
      95             : 
      96             :     OGRDXFFeatureQueue apoPendingFeatures;
      97             : 
      98             :   public:
      99             :     explicit OGRDXFBlocksLayer(OGRDXFDataSource *poDS);
     100             :     ~OGRDXFBlocksLayer();
     101             : 
     102             :     void ResetReading() override;
     103             :     OGRFeature *GetNextFeature() override;
     104             : 
     105          14 :     OGRFeatureDefn *GetLayerDefn() override
     106             :     {
     107          14 :         return poFeatureDefn;
     108             :     }
     109             : 
     110             :     int TestCapability(const char *) override;
     111             : 
     112             :     OGRDXFFeature *GetNextUnfilteredFeature();
     113             : };
     114             : 
     115             : /************************************************************************/
     116             : /*                       OGRDXFInsertTransformer                        */
     117             : /*                                                                      */
     118             : /*      Stores the transformation needed to insert a block reference.   */
     119             : /************************************************************************/
     120             : 
     121             : class OGRDXFInsertTransformer final : public OGRCoordinateTransformation
     122             : {
     123             :   public:
     124         370 :     OGRDXFInsertTransformer() = default;
     125             : 
     126             :     double dfXOffset = 0.0;
     127             :     double dfYOffset = 0.0;
     128             :     double dfZOffset = 0.0;
     129             :     double dfXScale = 1.0;
     130             :     double dfYScale = 1.0;
     131             :     double dfZScale = 1.0;
     132             :     double dfAngle = 0.0;
     133             : 
     134         696 :     OGRDXFInsertTransformer GetOffsetTransformer()
     135             :     {
     136         696 :         OGRDXFInsertTransformer oResult;
     137         696 :         oResult.dfXOffset = this->dfXOffset;
     138         696 :         oResult.dfYOffset = this->dfYOffset;
     139         696 :         oResult.dfZOffset = this->dfZOffset;
     140         696 :         return oResult;
     141             :     }
     142             : 
     143         696 :     OGRDXFInsertTransformer GetRotateScaleTransformer()
     144             :     {
     145         696 :         OGRDXFInsertTransformer oResult;
     146         696 :         oResult.dfXScale = this->dfXScale;
     147         696 :         oResult.dfYScale = this->dfYScale;
     148         696 :         oResult.dfZScale = this->dfZScale;
     149         696 :         oResult.dfAngle = this->dfAngle;
     150         696 :         return oResult;
     151             :     }
     152             : 
     153           0 :     OGRCoordinateTransformation *Clone() const override
     154             :     {
     155           0 :         return new OGRDXFInsertTransformer(*this);
     156             :     }
     157             : 
     158           0 :     const OGRSpatialReference *GetSourceCS() const override
     159             :     {
     160           0 :         return nullptr;
     161             :     }
     162             : 
     163        3410 :     const OGRSpatialReference *GetTargetCS() const override
     164             :     {
     165        3410 :         return nullptr;
     166             :     }
     167             : 
     168        3275 :     int Transform(size_t nCount, double *x, double *y, double *z,
     169             :                   double * /* t */, int *pabSuccess) override
     170             :     {
     171       16649 :         for (size_t i = 0; i < nCount; i++)
     172             :         {
     173       13374 :             x[i] *= dfXScale;
     174       13374 :             y[i] *= dfYScale;
     175       13374 :             if (z)
     176       13374 :                 z[i] *= dfZScale;
     177             : 
     178       13374 :             const double dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
     179       13374 :             const double dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
     180             : 
     181       13374 :             x[i] = dfXNew;
     182       13374 :             y[i] = dfYNew;
     183             : 
     184       13374 :             x[i] += dfXOffset;
     185       13374 :             y[i] += dfYOffset;
     186       13374 :             if (z)
     187       13374 :                 z[i] += dfZOffset;
     188             : 
     189       13374 :             if (pabSuccess)
     190       13374 :                 pabSuccess[i] = TRUE;
     191             :         }
     192        3275 :         return TRUE;
     193             :     }
     194             : 
     195           0 :     OGRCoordinateTransformation *GetInverse() const override
     196             :     {
     197           0 :         return nullptr;
     198             :     }
     199             : };
     200             : 
     201             : /************************************************************************/
     202             : /*                         OGRDXFAffineTransform                        */
     203             : /*                                                                      */
     204             : /*    A simple 3D affine transform used to keep track of the            */
     205             : /*    transformation to be applied to an ASM entity.                    */
     206             : /************************************************************************/
     207             : 
     208             : class OGRDXFAffineTransform
     209             : {
     210             :   public:
     211           2 :     OGRDXFAffineTransform()
     212           2 :         : adfData{1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}
     213             :     {
     214           2 :     }
     215             : 
     216             :     double adfData[12];  // Column-major: adfMatrix[5] is column 2, row 3
     217             :                          // Last 3 elements are translation
     218             : 
     219             :     // Left composition (composes oOther o this), modifying this
     220           6 :     void ComposeWith(const OGRDXFInsertTransformer &oCT)
     221             :     {
     222             :         double adfNew[12];
     223             : 
     224           6 :         adfNew[0] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[0] -
     225           6 :                     oCT.dfYScale * sin(oCT.dfAngle) * adfData[1];
     226           6 :         adfNew[1] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[0] +
     227           6 :                     oCT.dfYScale * cos(oCT.dfAngle) * adfData[1];
     228           6 :         adfNew[2] = oCT.dfZScale * adfData[2];
     229             : 
     230           6 :         adfNew[3] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[3] -
     231           6 :                     oCT.dfYScale * sin(oCT.dfAngle) * adfData[4];
     232           6 :         adfNew[4] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[3] +
     233           6 :                     oCT.dfYScale * cos(oCT.dfAngle) * adfData[4];
     234           6 :         adfNew[5] = oCT.dfZScale * adfData[5];
     235             : 
     236           6 :         adfNew[6] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[6] -
     237           6 :                     oCT.dfYScale * sin(oCT.dfAngle) * adfData[7];
     238           6 :         adfNew[7] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[6] +
     239           6 :                     oCT.dfYScale * cos(oCT.dfAngle) * adfData[7];
     240           6 :         adfNew[8] = oCT.dfZScale * adfData[8];
     241             : 
     242           6 :         adfNew[9] = oCT.dfXScale * cos(oCT.dfAngle) * adfData[9] -
     243           6 :                     oCT.dfYScale * sin(oCT.dfAngle) * adfData[10] +
     244           6 :                     oCT.dfXOffset;
     245           6 :         adfNew[10] = oCT.dfXScale * sin(oCT.dfAngle) * adfData[9] +
     246           6 :                      oCT.dfYScale * cos(oCT.dfAngle) * adfData[10] +
     247           6 :                      oCT.dfYOffset;
     248           6 :         adfNew[11] = oCT.dfZScale * adfData[11] + oCT.dfZOffset;
     249             : 
     250           6 :         memcpy(adfData, adfNew, sizeof(adfNew));
     251           6 :     }
     252             : 
     253           5 :     void SetField(OGRFeature *poFeature, const char *pszFieldName) const
     254             :     {
     255           5 :         poFeature->SetField(pszFieldName, 12, adfData);
     256           5 :     }
     257             : };
     258             : 
     259             : /************************************************************************/
     260             : /*                         OGRDXFOCSTransformer                         */
     261             : /************************************************************************/
     262             : 
     263             : class OGRDXFOCSTransformer final : public OGRCoordinateTransformation
     264             : {
     265             :   private:
     266             :     double adfN[3];
     267             :     double adfAX[3];
     268             :     double adfAY[3];
     269             : 
     270             :     double dfDeterminant;
     271             :     double aadfInverse[4][4];
     272             : 
     273             :   public:
     274             :     explicit OGRDXFOCSTransformer(double adfNIn[3], bool bInverse = false);
     275             : 
     276           0 :     const OGRSpatialReference *GetSourceCS() const override
     277             :     {
     278           0 :         return nullptr;
     279             :     }
     280             : 
     281        2078 :     const OGRSpatialReference *GetTargetCS() const override
     282             :     {
     283        2078 :         return nullptr;
     284             :     }
     285             : 
     286             :     int Transform(size_t nCount, double *adfX, double *adfY, double *adfZ,
     287             :                   double *adfT, int *pabSuccess) override;
     288             : 
     289             :     int InverseTransform(size_t nCount, double *adfX, double *adfY,
     290             :                          double *adfZ);
     291             : 
     292             :     void ComposeOnto(OGRDXFAffineTransform &poCT) const;
     293             : 
     294           0 :     OGRCoordinateTransformation *Clone() const override
     295             :     {
     296           0 :         return new OGRDXFOCSTransformer(*this);
     297             :     }
     298             : 
     299           0 :     OGRCoordinateTransformation *GetInverse() const override
     300             :     {
     301           0 :         return nullptr;
     302             :     }
     303             : };
     304             : 
     305             : /************************************************************************/
     306             : /*                              DXFTriple                               */
     307             : /*                                                                      */
     308             : /*     Represents a triple (X, Y, Z) used for various purposes in       */
     309             : /*     DXF files.  We do not use OGRPoint for this purpose, as the      */
     310             : /*     triple does not always represent a point as such (for            */
     311             : /*     example, it could contain a scale factor for each dimension).    */
     312             : /************************************************************************/
     313             : struct DXFTriple
     314             : {
     315             :     double dfX, dfY, dfZ;
     316             : 
     317          27 :     DXFTriple() : dfX(0.0), dfY(0.0), dfZ(0.0)
     318             :     {
     319          27 :     }
     320             : 
     321       12587 :     DXFTriple(double x, double y, double z) : dfX(x), dfY(y), dfZ(z)
     322             :     {
     323       12587 :     }
     324             : 
     325        1956 :     void ToArray(double adfOut[3]) const
     326             :     {
     327        1956 :         adfOut[0] = dfX;
     328        1956 :         adfOut[1] = dfY;
     329        1956 :         adfOut[2] = dfZ;
     330        1956 :     }
     331             : 
     332          18 :     DXFTriple &operator*=(const double dfValue)
     333             :     {
     334          18 :         dfX *= dfValue;
     335          18 :         dfY *= dfValue;
     336          18 :         dfZ *= dfValue;
     337          18 :         return *this;
     338             :     }
     339             : 
     340           2 :     DXFTriple &operator/=(const double dfValue)
     341             :     {
     342           2 :         dfX /= dfValue;
     343           2 :         dfY /= dfValue;
     344           2 :         dfZ /= dfValue;
     345           2 :         return *this;
     346             :     }
     347             : 
     348             :     bool operator==(const DXFTriple &oOther) const
     349             :     {
     350             :         return dfX == oOther.dfX && dfY == oOther.dfY && dfZ == oOther.dfZ;
     351             :     }
     352             : };
     353             : 
     354             : /************************************************************************/
     355             : /*                            OGRDXFFeature                             */
     356             : /*                                                                      */
     357             : /*     Extends OGRFeature with some DXF-specific members.               */
     358             : /************************************************************************/
     359             : class OGRDXFFeature final : public OGRFeature
     360             : {
     361             :     friend class OGRDXFLayer;
     362             : 
     363             :   protected:
     364             :     // The feature's Object Coordinate System (OCS) unit normal vector
     365             :     DXFTriple oOCS;
     366             : 
     367             :     // A list of properties that are used to construct the style string
     368             :     std::map<CPLString, CPLString> oStyleProperties;
     369             : 
     370             :     // Additional data for INSERT entities
     371             :     bool bIsBlockReference;
     372             :     CPLString osBlockName;
     373             :     double dfBlockAngle;
     374             :     DXFTriple oBlockScale;
     375             : 
     376             :     // Used for INSERT entities when DXF_INLINE_BLOCKS is false, to store
     377             :     // the OCS insertion point
     378             :     DXFTriple oOriginalCoords;
     379             : 
     380             :     // Used in 3D mode to store transformation parameters for ASM entities
     381             :     std::unique_ptr<OGRDXFAffineTransform> poASMTransform;
     382             : 
     383             :     // Additional data for ATTRIB and ATTDEF entities
     384             :     CPLString osAttributeTag;
     385             : 
     386             :     // Store ATTRIB entities associated with an INSERT, for use when
     387             :     // DXF_INLINE_BLOCKS is true and a block with attributes is INSERTed
     388             :     // in another block
     389             :     std::vector<std::unique_ptr<OGRDXFFeature>> apoAttribFeatures;
     390             : 
     391             :   public:
     392             :     explicit OGRDXFFeature(OGRFeatureDefn *poFeatureDefn);
     393             : 
     394             :     OGRDXFFeature *CloneDXFFeature();
     395             : 
     396             :     DXFTriple GetOCS() const
     397             :     {
     398             :         return oOCS;
     399             :     }
     400             : 
     401        2695 :     bool IsBlockReference() const
     402             :     {
     403        2695 :         return bIsBlockReference;
     404             :     }
     405             : 
     406             :     CPLString GetBlockName() const
     407             :     {
     408             :         return osBlockName;
     409             :     }
     410             : 
     411             :     double GetBlockAngle() const
     412             :     {
     413             :         return dfBlockAngle;
     414             :     }
     415             : 
     416             :     DXFTriple GetBlockScale() const
     417             :     {
     418             :         return oBlockScale;
     419             :     }
     420             : 
     421         793 :     DXFTriple GetInsertOCSCoords() const
     422             :     {
     423         793 :         return oOriginalCoords;
     424             :     }
     425             : 
     426          44 :     CPLString GetAttributeTag() const
     427             :     {
     428          44 :         return osAttributeTag;
     429             :     }
     430             : 
     431             :     const std::vector<std::unique_ptr<OGRDXFFeature>> &GetAttribFeatures() const
     432             :     {
     433             :         return apoAttribFeatures;
     434             :     }
     435             : 
     436         793 :     void SetInsertOCSCoords(const DXFTriple &oTriple)
     437             :     {
     438         793 :         oOriginalCoords = oTriple;
     439         793 :     }
     440             : 
     441             :     void ApplyOCSTransformer(OGRGeometry *const poGeometry) const;
     442             :     void ApplyOCSTransformer(OGRDXFAffineTransform *const poCT) const;
     443             :     const CPLString GetColor(OGRDXFDataSource *const poDS,
     444             :                              OGRDXFFeature *const poBlockFeature = nullptr);
     445             : };
     446             : 
     447             : /************************************************************************/
     448             : /*                             OGRDXFLayer                              */
     449             : /************************************************************************/
     450             : class OGRDXFLayer final : public OGRLayer
     451             : {
     452             :     friend class OGRDXFBlocksLayer;
     453             : 
     454             :     OGRDXFDataSource *poDS;
     455             : 
     456             :     OGRFeatureDefn *poFeatureDefn;
     457             :     GIntBig iNextFID;
     458             : 
     459             :     std::set<CPLString> oIgnoredEntities;
     460             : 
     461             :     OGRDXFFeatureQueue apoPendingFeatures;
     462             : 
     463             :     struct InsertState
     464             :     {
     465             :         OGRDXFInsertTransformer m_oTransformer{};
     466             :         CPLString m_osBlockName{};
     467             :         CPLStringList m_aosAttribs{};
     468             :         int m_nColumnCount = 0;
     469             :         int m_nRowCount = 0;
     470             :         int m_iCurCol = 0;
     471             :         int m_iCurRow = 0;
     472             :         double m_dfColumnSpacing = 0.0;
     473             :         double m_dfRowSpacing = 0.0;
     474             :         std::vector<std::unique_ptr<OGRDXFFeature>> m_apoAttribs{};
     475             :         std::unique_ptr<OGRDXFFeature> m_poTemplateFeature{};
     476             :     };
     477             : 
     478             :     InsertState m_oInsertState{};
     479             : 
     480             :     void ClearPendingFeatures();
     481             : 
     482             :     void TranslateGenericProperty(OGRDXFFeature *poFeature, int nCode,
     483             :                                   char *pszValue);
     484             : 
     485             :     void PrepareFeatureStyle(OGRDXFFeature *const poFeature,
     486             :                              OGRDXFFeature *const poBlockFeature = nullptr);
     487             :     void PrepareBrushStyle(OGRDXFFeature *const poFeature,
     488             :                            OGRDXFFeature *const poBlockFeature = nullptr);
     489             :     void PrepareLineStyle(OGRDXFFeature *const poFeature,
     490             :                           OGRDXFFeature *const poBlockFeature = nullptr);
     491             : 
     492             :     OGRDXFFeature *TranslatePOINT();
     493             :     OGRDXFFeature *TranslateLINE();
     494             :     OGRDXFFeature *TranslatePOLYLINE();
     495             :     OGRDXFFeature *TranslateLWPOLYLINE();
     496             :     OGRDXFFeature *TranslateMLINE();
     497             :     OGRDXFFeature *TranslateCIRCLE();
     498             :     OGRDXFFeature *TranslateELLIPSE();
     499             :     OGRDXFFeature *TranslateARC();
     500             :     OGRDXFFeature *TranslateSPLINE();
     501             :     OGRDXFFeature *Translate3DFACE();
     502             :     bool TranslateINSERT();
     503             :     OGRDXFFeature *TranslateMTEXT();
     504             :     OGRDXFFeature *TranslateTEXT(const bool bIsAttribOrAttdef);
     505             :     OGRDXFFeature *TranslateDIMENSION();
     506             :     OGRDXFFeature *TranslateHATCH();
     507             :     OGRDXFFeature *TranslateSOLID();
     508             :     OGRDXFFeature *TranslateLEADER();
     509             :     OGRDXFFeature *TranslateMLEADER();
     510             :     OGRDXFFeature *TranslateASMEntity();
     511             : 
     512             :     static constexpr int FORTRAN_INDEXING = 1;
     513             : 
     514             :     bool GenerateINSERTFeatures();
     515             :     std::unique_ptr<OGRLineString>
     516             :     InsertSplineWithChecks(const int nDegree,
     517             :                            std::vector<double> &adfControlPoints, bool bHasZ,
     518             :                            int nControlPoints, std::vector<double> &adfKnots,
     519             :                            int nKnots, std::vector<double> &adfWeights);
     520             :     static OGRGeometry *SimplifyBlockGeometry(OGRGeometryCollection *);
     521             :     OGRDXFFeature *InsertBlockInline(GUInt32 nInitialErrorCounter,
     522             :                                      const CPLString &osBlockName,
     523             :                                      OGRDXFInsertTransformer oTransformer,
     524             :                                      OGRDXFFeature *const poFeature,
     525             :                                      OGRDXFFeatureQueue &apoExtraFeatures,
     526             :                                      const bool bInlineNestedBlocks,
     527             :                                      const bool bMergeGeometry);
     528             :     static OGRDXFFeature *
     529             :     InsertBlockReference(const CPLString &osBlockName,
     530             :                          const OGRDXFInsertTransformer &oTransformer,
     531             :                          OGRDXFFeature *const poFeature);
     532             :     static void FormatDimension(CPLString &osText, const double dfValue,
     533             :                                 int nPrecision);
     534             :     void InsertArrowhead(OGRDXFFeature *const poFeature,
     535             :                          const CPLString &osBlockName,
     536             :                          OGRLineString *const poLine,
     537             :                          const double dfArrowheadSize,
     538             :                          const bool bReverse = false);
     539             :     OGRErr CollectBoundaryPath(OGRGeometryCollection *poGC,
     540             :                                const double dfElevation);
     541             :     OGRErr CollectPolylinePath(OGRGeometryCollection *poGC,
     542             :                                const double dfElevation);
     543             : 
     544             :     CPLString TextRecode(const char *);
     545             :     CPLString TextUnescape(const char *, bool);
     546             : 
     547             :   public:
     548             :     explicit OGRDXFLayer(OGRDXFDataSource *poDS);
     549             :     ~OGRDXFLayer();
     550             : 
     551             :     void ResetReading() override;
     552             :     OGRFeature *GetNextFeature() override;
     553             : 
     554         323 :     OGRFeatureDefn *GetLayerDefn() override
     555             :     {
     556         323 :         return poFeatureDefn;
     557             :     }
     558             : 
     559             :     int TestCapability(const char *) override;
     560             : 
     561             :     GDALDataset *GetDataset() override;
     562             : 
     563             :     OGRDXFFeature *GetNextUnfilteredFeature();
     564             : };
     565             : 
     566             : /************************************************************************/
     567             : /*                             OGRDXFReader                             */
     568             : /*                                                                      */
     569             : /*      A class for very low level DXF reading without interpretation.  */
     570             : /************************************************************************/
     571             : 
     572             : #define DXF_READER_ERROR()                                                     \
     573             :     do                                                                         \
     574             :     {                                                                          \
     575             :         CPLError(CE_Failure, CPLE_AppDefined,                                  \
     576             :                  "%s, %d: error at line %d of %s", __FILE__, __LINE__,         \
     577             :                  GetLineNumber(), GetDescription());                           \
     578             :     } while (0)
     579             : #define DXF_LAYER_READER_ERROR()                                               \
     580             :     do                                                                         \
     581             :     {                                                                          \
     582             :         CPLError(CE_Failure, CPLE_AppDefined,                                  \
     583             :                  "%s, %d: error at line %d of %s", __FILE__, __LINE__,         \
     584             :                  poDS->GetLineNumber(), poDS->GetDescription());               \
     585             :     } while (0)
     586             : 
     587             : class OGRDXFReader
     588             : {
     589             :     int ReadValueRaw(char *pszValueBuffer, int nValueBufferSize);
     590             : 
     591             :   public:
     592             :     OGRDXFReader();
     593             :     ~OGRDXFReader();
     594             : 
     595             :     void Initialize(VSILFILE *fp);
     596             : 
     597             :     VSILFILE *fp;
     598             : 
     599             :     unsigned int iSrcBufferOffset;
     600             :     unsigned int nSrcBufferBytes;
     601             :     unsigned int iSrcBufferFileOffset;
     602             :     char achSrcBuffer[1025];
     603             : 
     604             :     unsigned int nLastValueSize;
     605             :     int nLineNumber;
     606             : 
     607             :     int ReadValue(char *pszValueBuffer, int nValueBufferSize = 81);
     608             :     void UnreadValue();
     609             :     void LoadDiskChunk();
     610             :     void ResetReadPointer(unsigned int iNewOffset, int nNewLineNumber = 0);
     611             : };
     612             : 
     613             : /************************************************************************/
     614             : /*                           OGRDXFFieldModes                           */
     615             : /*                                                                      */
     616             : /*    Represents which fields should be included in the data source.    */
     617             : /************************************************************************/
     618             : 
     619             : enum OGRDXFFieldModes
     620             : {
     621             :     ODFM_None = 0,
     622             :     ODFM_IncludeRawCodeValues = 0x1,
     623             :     ODFM_IncludeBlockFields = 0x2,
     624             :     ODFM_Include3DModeFields = 0x4
     625             : };
     626             : 
     627             : /************************************************************************/
     628             : /*                           OGRDXFDataSource                           */
     629             : /************************************************************************/
     630             : 
     631             : class OGRDXFDataSource final : public GDALDataset
     632             : {
     633             :     VSILFILE *fp;
     634             : 
     635             :     std::vector<OGRLayer *> apoLayers;
     636             : 
     637             :     unsigned int iEntitiesOffset;
     638             :     int iEntitiesLineNumber;
     639             : 
     640             :     std::map<CPLString, DXFBlockDefinition> oBlockMap;
     641             :     std::map<CPLString, CPLString> oBlockRecordHandles;
     642             :     std::map<CPLString, CPLString> oHeaderVariables;
     643             : 
     644             :     CPLString osEncoding;
     645             : 
     646             :     // indexed by layer name, then by property name.
     647             :     std::map<CPLString, std::map<CPLString, CPLString>> oLayerTable;
     648             : 
     649             :     // indexed by style name, then by property name.
     650             :     std::map<CPLString, std::map<CPLString, CPLString>> oTextStyleTable;
     651             :     std::map<CPLString, CPLString> oTextStyleHandles;
     652             : 
     653             :     // indexed by dimstyle name, then by DIM... variable name
     654             :     std::map<CPLString, std::map<CPLString, CPLString>> oDimStyleTable;
     655             : 
     656             :     std::map<CPLString, std::vector<double>> oLineTypeTable;
     657             : 
     658             :     bool bInlineBlocks;
     659             :     bool bMergeBlockGeometries;
     660             :     bool bTranslateEscapeSequences;
     661             :     bool bIncludeRawCodeValues;
     662             :     bool m_bClosedLineAsPolygon = false;
     663             :     double m_dfHatchTolerance = -1.0;
     664             : 
     665             :     bool b3DExtensibleMode;
     666             :     bool bHaveReadSolidData;
     667             :     std::map<CPLString, std::vector<GByte>> oSolidBinaryData;
     668             : 
     669             :     OGRDXFReader oReader;
     670             : 
     671             :     std::vector<CPLString> aosBlockInsertionStack;
     672             : 
     673             :   public:
     674             :     OGRDXFDataSource();
     675             :     ~OGRDXFDataSource();
     676             : 
     677             :     int Open(const char *pszFilename, bool bHeaderOnly,
     678             :              CSLConstList papszOptionsIn);
     679             : 
     680         494 :     int GetLayerCount() override
     681             :     {
     682         494 :         return static_cast<int>(apoLayers.size());
     683             :     }
     684             : 
     685             :     OGRLayer *GetLayer(int) override;
     686             : 
     687             :     int TestCapability(const char *) override;
     688             : 
     689             :     // The following is only used by OGRDXFLayer
     690             : 
     691        1400 :     bool InlineBlocks() const
     692             :     {
     693        1400 :         return bInlineBlocks;
     694             :     }
     695             : 
     696         122 :     bool ShouldMergeBlockGeometries() const
     697             :     {
     698         122 :         return bMergeBlockGeometries;
     699             :     }
     700             : 
     701         148 :     bool ShouldTranslateEscapes() const
     702             :     {
     703         148 :         return bTranslateEscapeSequences;
     704             :     }
     705             : 
     706        2800 :     bool ShouldIncludeRawCodeValues() const
     707             :     {
     708        2800 :         return bIncludeRawCodeValues;
     709             :     }
     710             : 
     711         207 :     bool In3DExtensibleMode() const
     712             :     {
     713         207 :         return b3DExtensibleMode;
     714             :     }
     715             : 
     716          25 :     bool ClosedLineAsPolygon() const
     717             :     {
     718          25 :         return m_bClosedLineAsPolygon;
     719             :     }
     720             : 
     721          28 :     double HatchTolerance() const
     722             :     {
     723          28 :         return m_dfHatchTolerance;
     724             :     }
     725             : 
     726             :     static void AddStandardFields(OGRFeatureDefn *poDef, const int nFieldModes);
     727             : 
     728             :     // Implemented in ogrdxf_blockmap.cpp
     729             :     bool ReadBlocksSection();
     730             :     DXFBlockDefinition *LookupBlock(const char *pszName);
     731             :     CPLString GetBlockNameByRecordHandle(const char *pszID);
     732             : 
     733          42 :     std::map<CPLString, DXFBlockDefinition> &GetBlockMap()
     734             :     {
     735          42 :         return oBlockMap;
     736             :     }
     737             : 
     738             :     bool PushBlockInsertion(const CPLString &osBlockName);
     739             : 
     740         296 :     void PopBlockInsertion()
     741             :     {
     742         296 :         aosBlockInsertionStack.pop_back();
     743         296 :     }
     744             : 
     745             :     // Layer and other Table Handling (ogrdatasource.cpp)
     746             :     bool ReadTablesSection();
     747             :     bool ReadLayerDefinition();
     748             :     bool ReadLineTypeDefinition();
     749             :     bool ReadTextStyleDefinition();
     750             :     bool ReadDimStyleDefinition();
     751             :     const char *LookupLayerProperty(const char *pszLayer,
     752             :                                     const char *pszProperty);
     753             :     const char *LookupTextStyleProperty(const char *pszTextStyle,
     754             :                                         const char *pszProperty,
     755             :                                         const char *pszDefault);
     756             :     bool LookupDimStyle(const char *pszDimstyle,
     757             :                         std::map<CPLString, CPLString> &oDimStyleProperties);
     758             : 
     759           4 :     const std::map<CPLString, std::vector<double>> &GetLineTypeTable() const
     760             :     {
     761           4 :         return oLineTypeTable;
     762             :     }
     763             : 
     764             :     std::vector<double> LookupLineType(const char *pszName);
     765             :     bool TextStyleExists(const char *pszTextStyle);
     766             :     CPLString GetTextStyleNameByHandle(const char *pszID);
     767             :     static void PopulateDefaultDimStyleProperties(
     768             :         std::map<CPLString, CPLString> &oDimStyleProperties);
     769             :     size_t GetEntryFromAcDsDataSection(const char *pszEntityHandle,
     770             :                                        const GByte **pabyBuffer);
     771             : 
     772             :     // Header variables.
     773             :     bool ReadHeaderSection();
     774             :     const char *GetVariable(const char *pszName,
     775             :                             const char *pszDefault = nullptr);
     776             : 
     777        2918 :     const char *GetEncoding()
     778             :     {
     779        2918 :         return osEncoding;
     780             :     }
     781             : 
     782             :     // reader related.
     783           6 :     int GetLineNumber()
     784             :     {
     785           6 :         return oReader.nLineNumber;
     786             :     }
     787             : 
     788      134296 :     int ReadValue(char *pszValueBuffer, int nValueBufferSize = 81)
     789             :     {
     790      134296 :         return oReader.ReadValue(pszValueBuffer, nValueBufferSize);
     791             :     }
     792             : 
     793         179 :     void RestartEntities()
     794             :     {
     795         179 :         oReader.ResetReadPointer(iEntitiesOffset, iEntitiesLineNumber);
     796         179 :     }
     797             : 
     798        2208 :     void UnreadValue()
     799             :     {
     800        2208 :         oReader.UnreadValue();
     801        2208 :     }
     802             : 
     803          56 :     void ResetReadPointer(int iNewOffset)
     804             :     {
     805          56 :         oReader.ResetReadPointer(iNewOffset);
     806          56 :     }
     807             : };
     808             : 
     809             : /************************************************************************/
     810             : /*                          OGRDXFWriterLayer                           */
     811             : /************************************************************************/
     812             : 
     813             : class OGRDXFWriterDS;
     814             : 
     815             : class OGRDXFWriterLayer final : public OGRLayer
     816             : {
     817             :     VSILFILE *fp;
     818             :     OGRFeatureDefn *poFeatureDefn;
     819             : 
     820             :     OGRDXFWriterDS *poDS;
     821             : 
     822             :     int WriteValue(int nCode, const char *pszValue);
     823             :     int WriteValue(int nCode, int nValue);
     824             :     int WriteValue(int nCode, double dfValue);
     825             : 
     826             :     OGRErr WriteCore(OGRFeature *);
     827             :     OGRErr WritePOINT(OGRFeature *);
     828             :     OGRErr WriteTEXT(OGRFeature *);
     829             :     OGRErr WritePOLYLINE(OGRFeature *, const OGRGeometry * = nullptr);
     830             :     OGRErr WriteHATCH(OGRFeature *, OGRGeometry * = nullptr);
     831             :     OGRErr WriteINSERT(OGRFeature *);
     832             : 
     833             :     static CPLString TextEscape(const char *);
     834             :     static int ColorStringToDXFColor(const char *);
     835             :     static std::vector<double> PrepareLineTypeDefinition(OGRStylePen *);
     836             :     static std::map<CPLString, CPLString>
     837             :     PrepareTextStyleDefinition(OGRStyleLabel *);
     838             : 
     839             :     std::map<CPLString, std::vector<double>> oNewLineTypes;
     840             :     std::map<CPLString, std::map<CPLString, CPLString>> oNewTextStyles;
     841             :     int nNextAutoID;
     842             :     int bWriteHatch;
     843             : 
     844             :   public:
     845             :     OGRDXFWriterLayer(OGRDXFWriterDS *poDS, VSILFILE *fp);
     846             :     ~OGRDXFWriterLayer();
     847             : 
     848          16 :     void ResetReading() override
     849             :     {
     850          16 :     }
     851             : 
     852          16 :     OGRFeature *GetNextFeature() override
     853             :     {
     854          16 :         return nullptr;
     855             :     }
     856             : 
     857         494 :     OGRFeatureDefn *GetLayerDefn() override
     858             :     {
     859         494 :         return poFeatureDefn;
     860             :     }
     861             : 
     862             :     int TestCapability(const char *) override;
     863             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     864             :     OGRErr CreateField(const OGRFieldDefn *poField,
     865             :                        int bApproxOK = TRUE) override;
     866             : 
     867             :     GDALDataset *GetDataset() override;
     868             : 
     869             :     void ResetFP(VSILFILE *);
     870             : 
     871          48 :     std::map<CPLString, std::vector<double>> &GetNewLineTypeMap()
     872             :     {
     873          48 :         return oNewLineTypes;
     874             :     }
     875             : 
     876          48 :     std::map<CPLString, std::map<CPLString, CPLString>> &GetNewTextStyleMap()
     877             :     {
     878          48 :         return oNewTextStyles;
     879             :     }
     880             : };
     881             : 
     882             : /************************************************************************/
     883             : /*                       OGRDXFBlocksWriterLayer                        */
     884             : /************************************************************************/
     885             : 
     886             : class OGRDXFBlocksWriterLayer final : public OGRLayer
     887             : {
     888             :     OGRFeatureDefn *poFeatureDefn;
     889             : 
     890             :   public:
     891             :     explicit OGRDXFBlocksWriterLayer(OGRDXFWriterDS *poDS);
     892             :     ~OGRDXFBlocksWriterLayer();
     893             : 
     894           0 :     void ResetReading() override
     895             :     {
     896           0 :     }
     897             : 
     898           0 :     OGRFeature *GetNextFeature() override
     899             :     {
     900           0 :         return nullptr;
     901             :     }
     902             : 
     903          10 :     OGRFeatureDefn *GetLayerDefn() override
     904             :     {
     905          10 :         return poFeatureDefn;
     906             :     }
     907             : 
     908             :     int TestCapability(const char *) override;
     909             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     910             :     OGRErr CreateField(const OGRFieldDefn *poField,
     911             :                        int bApproxOK = TRUE) override;
     912             : 
     913             :     std::vector<OGRFeature *> apoBlocks;
     914             :     OGRFeature *FindBlock(const char *);
     915             : };
     916             : 
     917             : /************************************************************************/
     918             : /*                           OGRDXFWriterDS                             */
     919             : /************************************************************************/
     920             : 
     921             : class OGRDXFWriterDS final : public GDALDataset
     922             : {
     923             :     friend class OGRDXFWriterLayer;
     924             : 
     925             :     int nNextFID;
     926             : 
     927             :     OGRDXFWriterLayer *poLayer;
     928             :     OGRDXFBlocksWriterLayer *poBlocksLayer;
     929             :     VSILFILE *fp;
     930             :     CPLString osTrailerFile;
     931             : 
     932             :     CPLString osTempFilename;
     933             :     VSILFILE *fpTemp;
     934             : 
     935             :     CPLString osHeaderFile;
     936             :     OGRDXFDataSource oHeaderDS;
     937             :     char **papszLayersToCreate;
     938             : 
     939             :     vsi_l_offset nHANDSEEDOffset;
     940             : 
     941             :     std::vector<int> anDefaultLayerCode;
     942             :     std::vector<CPLString> aosDefaultLayerText;
     943             : 
     944             :     std::set<CPLString> aosUsedEntities;
     945             :     void ScanForEntities(const char *pszFilename, const char *pszTarget);
     946             : 
     947             :     bool WriteNewLineTypeRecords(VSILFILE *fp);
     948             :     bool WriteNewTextStyleRecords(VSILFILE *fp);
     949             :     bool WriteNewBlockRecords(VSILFILE *);
     950             :     bool WriteNewBlockDefinitions(VSILFILE *);
     951             :     bool WriteNewLayerDefinitions(VSILFILE *);
     952             :     bool TransferUpdateHeader(VSILFILE *);
     953             :     bool TransferUpdateTrailer(VSILFILE *);
     954             :     bool FixupHANDSEED(VSILFILE *);
     955             : 
     956             :     OGREnvelope oGlobalEnvelope;
     957             : 
     958             :     bool m_bHeaderFileIsTemp = false;
     959             :     bool m_bTrailerFileIsTemp = false;
     960             :     OGRSpatialReference m_oSRS{};
     961             :     std::string m_osINSUNITS = "AUTO";
     962             :     std::string m_osMEASUREMENT = "HEADER_VALUE";
     963             : 
     964             :   public:
     965             :     OGRDXFWriterDS();
     966             :     ~OGRDXFWriterDS();
     967             : 
     968             :     int Open(const char *pszFilename, char **papszOptions);
     969             : 
     970             :     int GetLayerCount() override;
     971             :     OGRLayer *GetLayer(int) override;
     972             : 
     973             :     int TestCapability(const char *) override;
     974             : 
     975             :     OGRLayer *ICreateLayer(const char *pszName,
     976             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     977             :                            CSLConstList papszOptions) override;
     978             : 
     979             :     bool CheckEntityID(const char *pszEntityID);
     980             :     bool WriteEntityID(VSILFILE *fp, unsigned int &nAssignedFID,
     981             :                        GIntBig nPreferredFID = OGRNullFID);
     982             : 
     983             :     void UpdateExtent(OGREnvelope *psEnvelope);
     984             : };
     985             : 
     986             : #endif /* ndef OGR_DXF_H_INCLUDED */

Generated by: LCOV version 1.14