LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/dxf - ogrdxfwriterds.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 348 279 80.2 %
Date: 2012-12-26 Functions: 23 17 73.9 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrdxfwriterds.cpp 24359 2012-05-01 17:01:22Z rouault $
       3                 :  *
       4                 :  * Project:  DXF Translator
       5                 :  * Purpose:  Implements OGRDXFWriterDS - the OGRDataSource class used for
       6                 :  *           writing a DXF file.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "ogr_dxf.h"
      32                 : #include "cpl_conv.h"
      33                 : #include "cpl_string.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ogrdxfwriterds.cpp 24359 2012-05-01 17:01:22Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                          OGRDXFWriterDS()                          */
      39                 : /************************************************************************/
      40                 : 
      41               7 : OGRDXFWriterDS::OGRDXFWriterDS()
      42                 : 
      43                 : {
      44               7 :     fp = NULL;
      45               7 :     fpTemp = NULL;
      46               7 :     poLayer = NULL;
      47               7 :     poBlocksLayer = NULL;
      48               7 :     papszLayersToCreate = NULL;
      49               7 :     nNextFID = 80;
      50               7 :     nHANDSEEDOffset = 0;
      51               7 : }
      52                 : 
      53                 : /************************************************************************/
      54                 : /*                         ~OGRDXFWriterDS()                          */
      55                 : /************************************************************************/
      56                 : 
      57               7 : OGRDXFWriterDS::~OGRDXFWriterDS()
      58                 : 
      59                 : {
      60               7 :     if (fp != NULL)
      61                 :     {
      62                 : /* -------------------------------------------------------------------- */
      63                 : /*      Transfer over the header into the destination file with any     */
      64                 : /*      adjustments or insertions needed.                               */
      65                 : /* -------------------------------------------------------------------- */
      66               7 :         CPLDebug( "DXF", "Compose final DXF file from components." );
      67                 : 
      68               7 :         TransferUpdateHeader( fp );
      69                 : 
      70               7 :         if (fpTemp != NULL)
      71                 :         {
      72                 : /* -------------------------------------------------------------------- */
      73                 : /*      Copy in the temporary file contents.                            */
      74                 : /* -------------------------------------------------------------------- */
      75                 :             const char *pszLine;
      76                 : 
      77               7 :             VSIFCloseL(fpTemp);
      78               7 :             fpTemp = VSIFOpenL( osTempFilename, "r" );
      79                 : 
      80             474 :             while( (pszLine = CPLReadLineL(fpTemp)) != NULL )
      81                 :             {
      82             460 :                 VSIFWriteL( pszLine, 1, strlen(pszLine), fp );
      83             460 :                 VSIFWriteL( "\n", 1, 1, fp );
      84                 :             }
      85                 :                     
      86                 : /* -------------------------------------------------------------------- */
      87                 : /*      Cleanup temporary file.                                         */
      88                 : /* -------------------------------------------------------------------- */
      89               7 :             VSIFCloseL( fpTemp );
      90               7 :             VSIUnlink( osTempFilename );
      91                 :         }
      92                 : 
      93                 : /* -------------------------------------------------------------------- */
      94                 : /*      Write trailer.                                                  */
      95                 : /* -------------------------------------------------------------------- */
      96               7 :         if( osTrailerFile != "" )
      97               7 :             TransferUpdateTrailer( fp );
      98                 : 
      99                 : /* -------------------------------------------------------------------- */
     100                 : /*      Fixup the HANDSEED value now that we know all the entity ids    */
     101                 : /*      created.                                                        */
     102                 : /* -------------------------------------------------------------------- */
     103               7 :         FixupHANDSEED( fp );
     104                 : 
     105                 : /* -------------------------------------------------------------------- */
     106                 : /*      Close file.                                                     */
     107                 : /* -------------------------------------------------------------------- */
     108                 : 
     109               7 :         VSIFCloseL( fp );
     110               7 :         fp = NULL;
     111                 :     }
     112                 : 
     113                 : /* -------------------------------------------------------------------- */
     114                 : /*      Destroy layers.                                                 */
     115                 : /* -------------------------------------------------------------------- */
     116               7 :     delete poLayer;
     117               7 :     delete poBlocksLayer;
     118                 : 
     119               7 :     CSLDestroy(papszLayersToCreate);
     120               7 : }
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                           TestCapability()                           */
     124                 : /************************************************************************/
     125                 : 
     126               0 : int OGRDXFWriterDS::TestCapability( const char * pszCap )
     127                 : 
     128                 : {
     129               0 :     if( EQUAL(pszCap,ODsCCreateLayer) )
     130               0 :         return TRUE;
     131                 :     else
     132               0 :         return FALSE;
     133                 : }
     134                 : 
     135                 : /************************************************************************/
     136                 : /*                              GetLayer()                              */
     137                 : /************************************************************************/
     138                 : 
     139                 : 
     140               0 : OGRLayer *OGRDXFWriterDS::GetLayer( int iLayer )
     141                 : 
     142                 : {
     143               0 :     if( iLayer == 0 )
     144               0 :         return poLayer;
     145                 :     else
     146               0 :         return NULL;
     147                 : }
     148                 : 
     149                 : /************************************************************************/
     150                 : /*                           GetLayerCount()                            */
     151                 : /************************************************************************/
     152                 : 
     153               0 : int OGRDXFWriterDS::GetLayerCount()
     154                 : 
     155                 : {
     156               0 :     if( poLayer )
     157               0 :         return 1;
     158                 :     else
     159               0 :         return 0;
     160                 : }
     161                 : 
     162                 : /************************************************************************/
     163                 : /*                                Open()                                */
     164                 : /************************************************************************/
     165                 : 
     166               7 : int OGRDXFWriterDS::Open( const char * pszFilename, char **papszOptions )
     167                 : 
     168                 : {
     169                 : /* -------------------------------------------------------------------- */
     170                 : /*      Open the standard header, or a user provided header.            */
     171                 : /* -------------------------------------------------------------------- */
     172               7 :     if( CSLFetchNameValue(papszOptions,"HEADER") != NULL )
     173               3 :         osHeaderFile = CSLFetchNameValue(papszOptions,"HEADER");
     174                 :     else
     175                 :     {
     176               4 :         const char *pszValue = CPLFindFile( "gdal", "header.dxf" );
     177               4 :         if( pszValue == NULL )
     178                 :         {
     179                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     180               0 :                       "Failed to find template header file header.dxf for reading,\nis GDAL_DATA set properly?" );
     181               0 :             return FALSE;
     182                 :         }
     183               4 :         osHeaderFile = pszValue;
     184                 :     }
     185                 : 
     186                 : /* -------------------------------------------------------------------- */
     187                 : /*      Establish the name for our trailer file.                        */
     188                 : /* -------------------------------------------------------------------- */
     189               7 :     if( CSLFetchNameValue(papszOptions,"TRAILER") != NULL )
     190               0 :         osTrailerFile = CSLFetchNameValue(papszOptions,"TRAILER");
     191                 :     else
     192                 :     {
     193               7 :         const char *pszValue = CPLFindFile( "gdal", "trailer.dxf" );
     194               7 :         if( pszValue != NULL )
     195               7 :             osTrailerFile = pszValue;
     196                 :     }
     197                 : 
     198                 : /* -------------------------------------------------------------------- */
     199                 : /*      What entity id do we want to start with when writing?  Small    */
     200                 : /*      values run a risk of overlapping some undetected entity in      */
     201                 : /*      the header or trailer despite the prescanning we do.            */
     202                 : /* -------------------------------------------------------------------- */
     203                 : #ifdef DEBUG
     204               7 :     nNextFID = 80;
     205                 : #else
     206                 :     nNextFID = 131072;
     207                 : #endif
     208                 : 
     209               7 :     if( CSLFetchNameValue( papszOptions, "FIRST_ENTITY" ) != NULL )
     210               1 :         nNextFID = atoi(CSLFetchNameValue( papszOptions, "FIRST_ENTITY" ));
     211                 : 
     212                 : /* -------------------------------------------------------------------- */
     213                 : /*      Prescan the header and trailer for entity codes.                */
     214                 : /* -------------------------------------------------------------------- */
     215               7 :     ScanForEntities( osHeaderFile, "HEADER" );
     216               7 :     ScanForEntities( osTrailerFile, "TRAILER" );
     217                 : 
     218                 : /* -------------------------------------------------------------------- */
     219                 : /*      Attempt to read the template header file so we have a list      */
     220                 : /*      of layers, linestyles and blocks.                               */
     221                 : /* -------------------------------------------------------------------- */
     222               7 :     if( !oHeaderDS.Open( osHeaderFile, TRUE ) )
     223               0 :         return FALSE;
     224                 : 
     225                 : /* -------------------------------------------------------------------- */
     226                 : /*      Create the output file.                                         */
     227                 : /* -------------------------------------------------------------------- */
     228               7 :     fp = VSIFOpenL( pszFilename, "w+" );
     229                 : 
     230               7 :     if( fp == NULL )
     231                 :     {
     232                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     233                 :                   "Failed to open '%s' for writing.", 
     234               0 :                   pszFilename );
     235               0 :         return FALSE;
     236                 :     }
     237                 : 
     238                 : /* -------------------------------------------------------------------- */
     239                 : /*      Establish the temporary file.                                   */
     240                 : /* -------------------------------------------------------------------- */
     241               7 :     osTempFilename = pszFilename;
     242               7 :     osTempFilename += ".tmp";
     243                 : 
     244               7 :     fpTemp = VSIFOpenL( osTempFilename, "w" );
     245               7 :     if( fpTemp == NULL )
     246                 :     {
     247                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     248                 :                   "Failed to open '%s' for writing.", 
     249               0 :                   osTempFilename.c_str() );
     250               0 :         return FALSE;
     251                 :     }
     252                 : 
     253               7 :     return TRUE;
     254                 : }
     255                 : 
     256                 : /************************************************************************/
     257                 : /*                            CreateLayer()                             */
     258                 : /************************************************************************/
     259                 : 
     260               8 : OGRLayer *OGRDXFWriterDS::CreateLayer( const char *pszName, 
     261                 :                                        OGRSpatialReference *, 
     262                 :                                        OGRwkbGeometryType, 
     263                 :                                        char ** )
     264                 : 
     265                 : {
     266               8 :     if( EQUAL(pszName,"blocks") && poBlocksLayer == NULL )
     267                 :     {
     268               1 :         poBlocksLayer = new OGRDXFBlocksWriterLayer( this );
     269               1 :         return poBlocksLayer;
     270                 :     }
     271               7 :     else if( poLayer == NULL )
     272                 :     {
     273               7 :         poLayer = new OGRDXFWriterLayer( this, fpTemp );
     274               7 :         return poLayer;
     275                 :     }
     276                 :     else
     277                 :     {
     278                 :         CPLError( CE_Failure, CPLE_AppDefined,
     279               0 :                   "Unable to have more than one OGR entities layer in a DXF file, with one options blocks layer." );
     280               0 :         return NULL;
     281                 :     }
     282                 : }
     283                 : 
     284                 : /************************************************************************/
     285                 : /*                             WriteValue()                             */
     286                 : /************************************************************************/
     287                 : 
     288           13352 : static int WriteValue( VSILFILE *fp, int nCode, const char *pszLine )
     289                 : 
     290                 : {
     291                 :     char szLinePair[300];
     292                 : 
     293           13352 :     snprintf(szLinePair, sizeof(szLinePair), "%3d\n%s\n", nCode, pszLine );
     294           13352 :     size_t nLen = strlen(szLinePair);
     295           13352 :     if( VSIFWriteL( szLinePair, 1, nLen, fp ) != nLen )
     296                 :     {
     297                 :         CPLError( CE_Failure, CPLE_FileIO,
     298               0 :                   "Attempt to write line to DXF file failed, disk full?." );
     299               0 :         return FALSE;
     300                 :     }
     301                 :     else
     302           13352 :         return TRUE;
     303                 : }
     304                 : 
     305                 : /************************************************************************/
     306                 : /*                             WriteValue()                             */
     307                 : /************************************************************************/
     308                 : 
     309              28 : static int WriteValue( VSILFILE *fp, int nCode, double dfValue )
     310                 : 
     311                 : {
     312                 :     char szLinePair[64];
     313                 : 
     314              28 :     snprintf(szLinePair, sizeof(szLinePair), "%3d\n%.15g\n", nCode, dfValue );
     315              28 :     char* pszComma = strchr(szLinePair, ',');
     316              28 :     if (pszComma)
     317               0 :         *pszComma = '.';
     318              28 :     size_t nLen = strlen(szLinePair);
     319              28 :     if( VSIFWriteL( szLinePair, 1, nLen, fp ) != nLen )
     320                 :     {
     321                 :         CPLError( CE_Failure, CPLE_FileIO,
     322               0 :                   "Attempt to write line to DXF file failed, disk full?." );
     323               0 :         return FALSE;
     324                 :     }
     325                 :     else
     326              28 :         return TRUE;
     327                 : }
     328                 : /************************************************************************/
     329                 : /*                        TransferUpdateHeader()                        */
     330                 : /************************************************************************/
     331                 : 
     332               7 : int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
     333                 : 
     334                 : {
     335               7 :     oHeaderDS.ResetReadPointer( 0 );
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Copy header, inserting in new objects as needed.                */
     339                 : /* -------------------------------------------------------------------- */
     340                 :     char szLineBuf[257];
     341                 :     int nCode;
     342               7 :     CPLString osSection, osTable, osEntity;
     343                 : 
     344            5536 :     while( (nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 
     345                 :            && osSection != "ENTITIES" )
     346                 :     {
     347            5522 :         if( nCode == 0 && EQUAL(szLineBuf,"ENDTAB") )
     348                 :         {
     349                 :             // If we are at the end of the LAYER TABLE consider inserting 
     350                 :             // missing definitions.
     351              63 :             if( osTable == "LAYER" )
     352                 :             {
     353               7 :                 if( !WriteNewLayerDefinitions( fp ) )
     354               0 :                     return FALSE;
     355                 :             }
     356                 : 
     357                 :             // If at the end of the BLOCK_RECORD TABLE consider inserting 
     358                 :             // missing definitions.
     359              63 :             if( osTable == "BLOCK_RECORD" && poBlocksLayer )
     360                 :             {
     361               1 :                 if( !WriteNewBlockRecords( fp ) )
     362               0 :                     return FALSE;
     363                 :             }
     364                 : 
     365                 :             // If at the end of the LTYPE TABLE consider inserting 
     366                 :             // missing layer type definitions.
     367              63 :             if( osTable == "LTYPE" )
     368                 :             {
     369               7 :                 if( !WriteNewLineTypeRecords( fp ) )
     370               0 :                     return FALSE;
     371                 :             }
     372                 : 
     373              63 :             osTable = "";
     374                 :         }
     375                 : 
     376                 :         // If we are at the end of the BLOCKS section, consider inserting
     377                 :         // suplementary blocks. 
     378            5522 :         if( nCode == 0 && osSection == "BLOCKS" && EQUAL(szLineBuf,"ENDSEC") 
     379                 :             && poBlocksLayer != NULL )
     380                 :         {
     381               1 :             if( !WriteNewBlockDefinitions( fp ) )
     382               0 :                 return FALSE;
     383                 :         }
     384                 : 
     385                 :         // We need to keep track of where $HANDSEED is so that we can
     386                 :         // come back and fix it up when we have generated all entity ids. 
     387            5522 :         if( nCode == 9 && EQUAL(szLineBuf,"$HANDSEED") )
     388                 :         {
     389               7 :             if( !WriteValue( fpOut, nCode, szLineBuf ) )
     390               0 :                 return FALSE;
     391                 : 
     392               7 :             nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
     393                 : 
     394                 :             // ensure we have room to overwrite with a longer value.
     395              56 :             while( strlen(szLineBuf) < 8 )
     396                 :             {
     397              42 :                 memmove( szLineBuf+1, szLineBuf, strlen(szLineBuf)+1 );
     398              42 :                 szLineBuf[0] = '0';
     399                 :             }
     400                 : 
     401               7 :             nHANDSEEDOffset = VSIFTellL( fpOut );
     402                 :         }
     403                 : 
     404                 :         // Patch EXTMIN with minx and miny
     405            5522 :         if( nCode == 9 && EQUAL(szLineBuf,"$EXTMIN") )
     406                 :         {
     407               7 :             if( !WriteValue( fpOut, nCode, szLineBuf ) )
     408               0 :                 return FALSE;
     409                 : 
     410               7 :             nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
     411               7 :             if (nCode == 10)
     412                 :             {
     413               7 :                 if( !WriteValue( fpOut, nCode, oGlobalEnvelope.MinX ) )
     414               0 :                     return FALSE;
     415                 : 
     416               7 :                 nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
     417               7 :                 if (nCode == 20)
     418                 :                 {
     419               7 :                     if( !WriteValue( fpOut, nCode, oGlobalEnvelope.MinY ) )
     420               0 :                         return FALSE;
     421                 : 
     422               7 :                     continue;
     423                 :                 }
     424                 :             }
     425                 :         }
     426                 : 
     427                 :         // Patch EXTMAX with maxx and maxy
     428            5515 :         if( nCode == 9 && EQUAL(szLineBuf,"$EXTMAX") )
     429                 :         {
     430               7 :             if( !WriteValue( fpOut, nCode, szLineBuf ) )
     431               0 :                 return FALSE;
     432                 : 
     433               7 :             nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
     434               7 :             if (nCode == 10)
     435                 :             {
     436               7 :                 if( !WriteValue( fpOut, nCode, oGlobalEnvelope.MaxX ) )
     437               0 :                     return FALSE;
     438                 : 
     439               7 :                 nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
     440               7 :                 if (nCode == 20)
     441                 :                 {
     442               7 :                     if( !WriteValue( fpOut, nCode, oGlobalEnvelope.MaxY ) )
     443               0 :                         return FALSE;
     444                 : 
     445               7 :                     continue;
     446                 :                 }
     447                 :             }
     448                 :         }
     449                 : 
     450                 :         // Copy over the source line.
     451            5508 :         if( !WriteValue( fpOut, nCode, szLineBuf ) )
     452               0 :             return FALSE;
     453                 : 
     454                 :         // Track what entity we are in - that is the last "code 0" object.
     455            5508 :         if( nCode == 0  )
     456             349 :             osEntity = szLineBuf;
     457                 : 
     458                 :         // Track what section we are in.
     459            5508 :         if( nCode == 0 && EQUAL(szLineBuf,"SECTION") )
     460                 :         {
     461              35 :             nCode = oHeaderDS.ReadValue( szLineBuf );
     462              35 :             if( nCode == -1 )
     463               0 :                 break;
     464                 : 
     465              35 :             if( !WriteValue( fpOut, nCode, szLineBuf ) )
     466               0 :                 return FALSE;
     467                 :                 
     468              35 :             osSection = szLineBuf;
     469                 :         }
     470                 : 
     471                 :         // Track what TABLE we are in.
     472            5508 :         if( nCode == 0 && EQUAL(szLineBuf,"TABLE") )
     473                 :         {
     474              63 :             nCode = oHeaderDS.ReadValue( szLineBuf );
     475              63 :             if( !WriteValue( fpOut, nCode, szLineBuf ) )
     476               0 :                 return FALSE;
     477                 : 
     478              63 :             osTable = szLineBuf;
     479                 :         }
     480                 :         
     481                 :         // If we are starting the first layer, then capture
     482                 :         // the layer contents while copying so we can duplicate
     483                 :         // it for any new layer definitions.
     484            5508 :         if( nCode == 0 && EQUAL(szLineBuf,"LAYER")
     485                 :             && osTable == "LAYER" && aosDefaultLayerText.size() == 0 )
     486                 :         {
     487              77 :             do { 
     488              77 :                 anDefaultLayerCode.push_back( nCode );
     489              77 :                 aosDefaultLayerText.push_back( szLineBuf );
     490                 : 
     491              77 :                 if( nCode != 0 && !WriteValue( fpOut, nCode, szLineBuf ) )
     492               0 :                     return FALSE;
     493                 : 
     494              77 :                 nCode = oHeaderDS.ReadValue( szLineBuf );
     495                 : 
     496              77 :                 if( nCode == 2 && !EQUAL(szLineBuf,"0") )
     497                 :                 {
     498               0 :                     anDefaultLayerCode.resize(0);
     499               0 :                     aosDefaultLayerText.resize(0);
     500               0 :                     break;
     501                 :                 }
     502                 :             } while( nCode != 0 );
     503                 : 
     504               7 :             oHeaderDS.UnreadValue();
     505                 :         }
     506                 :     }
     507                 : 
     508               7 :     return TRUE;
     509                 : }    
     510                 : 
     511                 : /************************************************************************/
     512                 : /*                       TransferUpdateTrailer()                        */
     513                 : /************************************************************************/
     514                 : 
     515               7 : int OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
     516                 : {
     517               7 :     OGRDXFReader oReader;
     518                 :     VSILFILE *fp;
     519                 : 
     520                 : /* -------------------------------------------------------------------- */
     521                 : /*      Open the file and setup a reader.                               */
     522                 : /* -------------------------------------------------------------------- */
     523               7 :     fp = VSIFOpenL( osTrailerFile, "r" );
     524                 : 
     525               7 :     if( fp == NULL )
     526               0 :         return FALSE;
     527                 : 
     528               7 :     oReader.Initialize( fp );
     529                 : 
     530                 : /* -------------------------------------------------------------------- */
     531                 : /*      Scan ahead to find the OBJECTS section.                         */
     532                 : /* -------------------------------------------------------------------- */
     533                 :     char szLineBuf[257];
     534                 :     int  nCode;
     535                 : 
     536              21 :     while( (nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 )
     537                 :     {
     538              14 :         if( nCode == 0 && EQUAL(szLineBuf,"SECTION") )
     539                 :         {
     540               7 :             nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) );
     541               7 :             if( nCode == 2 && EQUAL(szLineBuf,"OBJECTS") )
     542               7 :                 break;
     543                 :         }
     544                 :     }
     545                 : 
     546               7 :     if( nCode == -1 )
     547                 :     {
     548                 :         CPLError( CE_Failure, CPLE_AppDefined,
     549                 :                   "Failed to find OBJECTS section in trailer file '%s'.",
     550               0 :                   osTrailerFile.c_str() );
     551               0 :         return FALSE;
     552                 :     }
     553                 : 
     554                 : /* -------------------------------------------------------------------- */
     555                 : /*      Insert the "end of section" for ENTITIES, and the start of      */
     556                 : /*      the OBJECTS section.                                            */
     557                 : /* -------------------------------------------------------------------- */
     558               7 :     WriteValue( fpOut, 0, "ENDSEC" );
     559               7 :     WriteValue( fpOut, 0, "SECTION" );
     560               7 :     WriteValue( fpOut, 2, "OBJECTS" );
     561                 : 
     562                 : /* -------------------------------------------------------------------- */
     563                 : /*      Copy the remainder of the file.                                 */
     564                 : /* -------------------------------------------------------------------- */
     565            7560 :     while( (nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 )
     566                 :     {
     567            7546 :         if( !WriteValue( fpOut, nCode, szLineBuf ) )
     568                 :         {
     569               0 :             VSIFCloseL( fp );
     570               0 :             return FALSE;
     571                 :         }
     572                 :     }
     573                 : 
     574               7 :     VSIFCloseL( fp );
     575                 : 
     576               7 :     return TRUE;
     577                 : }
     578                 : 
     579                 : /************************************************************************/
     580                 : /*                           FixupHANDSEED()                            */
     581                 : /*                                                                      */
     582                 : /*      Fixup the next entity id information in the $HANDSEED header    */
     583                 : /*      variable.                                                       */
     584                 : /************************************************************************/
     585                 : 
     586               7 : int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fp )
     587                 : 
     588                 : {
     589                 : /* -------------------------------------------------------------------- */
     590                 : /*      What is a good next handle seed?  Scan existing values.         */
     591                 : /* -------------------------------------------------------------------- */
     592               7 :     unsigned int   nHighestHandle = 0;
     593               7 :     std::set<CPLString>::iterator it;
     594                 : 
     595             451 :     for( it = aosUsedEntities.begin(); it != aosUsedEntities.end(); it++ ) 
     596                 :     {
     597                 :         unsigned int nHandle;
     598             444 :         if( sscanf( (*it).c_str(), "%x", &nHandle ) == 1 )
     599                 :         {
     600             444 :             if( nHandle > nHighestHandle )
     601             298 :                 nHighestHandle = nHandle;
     602                 :         }
     603                 :     }
     604                 : 
     605                 : /* -------------------------------------------------------------------- */
     606                 : /*      Read the existing handseed value, replace it, and write back.   */
     607                 : /* -------------------------------------------------------------------- */
     608                 :     char szWorkBuf[30];
     609               7 :     int  i = 0;
     610                 : 
     611               7 :     if( nHANDSEEDOffset == 0 )
     612               0 :         return FALSE;
     613                 : 
     614               7 :     VSIFSeekL( fp, nHANDSEEDOffset, SEEK_SET );
     615               7 :     VSIFReadL( szWorkBuf, 1, sizeof(szWorkBuf), fp );
     616                 :     
     617              35 :     while( szWorkBuf[i] != '\n' )
     618              21 :         i++;
     619                 : 
     620               7 :     i++;
     621               7 :     if( szWorkBuf[i] == '\r' )
     622               0 :         i++;
     623                 :     
     624               7 :     CPLString osNewValue;
     625                 : 
     626               7 :     osNewValue.Printf( "%08X", nHighestHandle + 1 );
     627               7 :     strncpy( szWorkBuf + i, osNewValue.c_str(), osNewValue.size() );
     628                 : 
     629               7 :     VSIFSeekL( fp, nHANDSEEDOffset, SEEK_SET );
     630               7 :     VSIFWriteL( szWorkBuf, 1, sizeof(szWorkBuf), fp );
     631                 : 
     632               7 :     return TRUE;
     633                 : }
     634                 : 
     635                 : /************************************************************************/
     636                 : /*                      WriteNewLayerDefinitions()                      */
     637                 : /************************************************************************/
     638                 : 
     639               7 : int  OGRDXFWriterDS::WriteNewLayerDefinitions( VSILFILE * fpOut )
     640                 : 
     641                 : {                                               
     642               7 :     int iLayer, nNewLayers = CSLCount(papszLayersToCreate);
     643                 : 
     644              10 :     for( iLayer = 0; iLayer < nNewLayers; iLayer++ )
     645                 :     {
     646              36 :         for( unsigned i = 0; i < aosDefaultLayerText.size(); i++ )
     647                 :         {
     648              33 :             if( anDefaultLayerCode[i] == 2 )
     649                 :             {
     650               3 :                 if( !WriteValue( fpOut, 2, papszLayersToCreate[iLayer] ) )
     651               0 :                     return FALSE;
     652                 :             }
     653              30 :             else if( anDefaultLayerCode[i] == 5 )
     654                 :             {
     655               3 :                 WriteEntityID( fpOut );
     656                 :             }
     657                 :             else
     658                 :             {
     659              27 :                 if( !WriteValue( fpOut,
     660                 :                                  anDefaultLayerCode[i],
     661                 :                                  aosDefaultLayerText[i] ) )
     662               0 :                     return FALSE;
     663                 :             }
     664                 :         }
     665                 :     }
     666                 : 
     667               7 :     return TRUE;
     668                 : }
     669                 : 
     670                 : /************************************************************************/
     671                 : /*                      WriteNewLineTypeRecords()                       */
     672                 : /************************************************************************/
     673                 : 
     674               7 : int OGRDXFWriterDS::WriteNewLineTypeRecords( VSILFILE *fp )
     675                 : 
     676                 : {
     677               7 :     if( poLayer == NULL )
     678               0 :         return TRUE;
     679                 : 
     680               7 :     std::map<CPLString,CPLString>::iterator oIt;
     681                 :     std::map<CPLString,CPLString>& oNewLineTypes = 
     682               7 :         poLayer->GetNewLineTypeMap();
     683                 : 
     684               9 :     for( oIt = oNewLineTypes.begin(); 
     685                 :          oIt != oNewLineTypes.end(); oIt++ )
     686                 :     {
     687               2 :         WriteValue( fp, 0, "LTYPE" );
     688               2 :         WriteEntityID( fp );
     689               2 :         WriteValue( fp, 100, "AcDbSymbolTableRecord" );
     690               2 :         WriteValue( fp, 100, "AcDbLinetypeTableRecord" );
     691               2 :         WriteValue( fp, 2, (*oIt).first );
     692               2 :         WriteValue( fp, 70, "0" );
     693               2 :         WriteValue( fp, 3, "" );
     694               2 :         WriteValue( fp, 72, "65" );
     695               2 :         VSIFWriteL( (*oIt).second.c_str(), 1, (*oIt).second.size(), fp );
     696                 : 
     697                 :         CPLDebug( "DXF", "Define Line type '%s'.", 
     698               2 :                   (*oIt).first.c_str() );
     699                 :     }
     700                 : 
     701               7 :     return TRUE;
     702                 : }
     703                 : 
     704                 : /************************************************************************/
     705                 : /*                        WriteNewBlockRecords()                        */
     706                 : /************************************************************************/
     707                 : 
     708               1 : int OGRDXFWriterDS::WriteNewBlockRecords( VSILFILE * fp )
     709                 : 
     710                 : {
     711               1 :     std::set<CPLString> aosAlreadyHandled;
     712                 : 
     713                 : /* ==================================================================== */
     714                 : /*      Loop over all block objects written via the blocks layer.       */
     715                 : /* ==================================================================== */
     716               1 :     for( size_t iBlock=0; iBlock < poBlocksLayer->apoBlocks.size(); iBlock++ )
     717                 :     {
     718               1 :         OGRFeature* poThisBlockFeat = poBlocksLayer->apoBlocks[iBlock];
     719                 : 
     720                 : /* -------------------------------------------------------------------- */
     721                 : /*      Is this block already defined in the template header?           */
     722                 : /* -------------------------------------------------------------------- */
     723               1 :         CPLString osBlockName = poThisBlockFeat->GetFieldAsString("BlockName");
     724                 : 
     725               1 :         if( oHeaderDS.LookupBlock( osBlockName ) != NULL )
     726               0 :             continue;
     727                 : 
     728                 : /* -------------------------------------------------------------------- */
     729                 : /*      Have we already written a BLOCK_RECORD for this block?          */
     730                 : /* -------------------------------------------------------------------- */
     731               1 :         if( aosAlreadyHandled.find(osBlockName) != aosAlreadyHandled.end() )
     732               0 :             continue;
     733                 : 
     734               1 :         aosAlreadyHandled.insert( osBlockName );
     735                 : 
     736                 : /* -------------------------------------------------------------------- */
     737                 : /*      Write the block record.                                         */
     738                 : /* -------------------------------------------------------------------- */
     739               1 :         WriteValue( fp, 0, "BLOCK_RECORD" );
     740               1 :         WriteEntityID( fp );
     741               1 :         WriteValue( fp, 100, "AcDbSymbolTableRecord" );
     742               1 :         WriteValue( fp, 100, "AcDbBlockTableRecord" );
     743               1 :         WriteValue( fp, 2, poThisBlockFeat->GetFieldAsString("BlockName") );
     744               1 :         if( !WriteValue( fp, 340, "0" ) )
     745               0 :             return FALSE;
     746                 :     }
     747                 : 
     748               1 :     return TRUE;
     749                 : }
     750                 : 
     751                 : /************************************************************************/
     752                 : /*                      WriteNewBlockDefinitions()                      */
     753                 : /************************************************************************/
     754                 : 
     755               1 : int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fp )
     756                 : 
     757                 : {
     758               1 :     poLayer->ResetFP( fp );
     759                 : 
     760                 : /* ==================================================================== */
     761                 : /*      Loop over all block objects written via the blocks layer.       */
     762                 : /* ==================================================================== */
     763               1 :     for( size_t iBlock=0; iBlock < poBlocksLayer->apoBlocks.size(); iBlock++ )
     764                 :     {
     765               1 :         OGRFeature* poThisBlockFeat = poBlocksLayer->apoBlocks[iBlock];
     766                 : 
     767                 : /* -------------------------------------------------------------------- */
     768                 : /*      Is this block already defined in the template header?           */
     769                 : /* -------------------------------------------------------------------- */
     770               1 :         CPLString osBlockName = poThisBlockFeat->GetFieldAsString("BlockName");
     771                 : 
     772               1 :         if( oHeaderDS.LookupBlock( osBlockName ) != NULL )
     773               0 :             continue;
     774                 : 
     775                 : /* -------------------------------------------------------------------- */
     776                 : /*      Write the block definition preamble.                            */
     777                 : /* -------------------------------------------------------------------- */
     778                 :         CPLDebug( "DXF", "Writing BLOCK definition for '%s'.",
     779               1 :                   poThisBlockFeat->GetFieldAsString("BlockName") );
     780                 : 
     781               1 :         WriteValue( fp, 0, "BLOCK" );
     782               1 :         WriteEntityID( fp );
     783               1 :         WriteValue( fp, 100, "AcDbEntity" );
     784               1 :         if( strlen(poThisBlockFeat->GetFieldAsString("Layer")) > 0 )
     785               0 :             WriteValue( fp, 8, poThisBlockFeat->GetFieldAsString("Layer") );
     786                 :         else
     787               1 :             WriteValue( fp, 8, "0" );
     788               1 :         WriteValue( fp, 100, "AcDbBlockBegin" );
     789               1 :         WriteValue( fp, 2, poThisBlockFeat->GetFieldAsString("BlockName") );
     790               1 :         WriteValue( fp, 70, "0" );
     791                 : 
     792                 :         // Origin
     793               1 :         WriteValue( fp, 10, "0.0" );
     794               1 :         WriteValue( fp, 20, "0.0" );
     795               1 :         WriteValue( fp, 30, "0.0" );
     796                 : 
     797               1 :         WriteValue( fp, 3, poThisBlockFeat->GetFieldAsString("BlockName") );
     798               1 :         WriteValue( fp, 1, "" );
     799                 : 
     800                 : /* -------------------------------------------------------------------- */
     801                 : /*      Write out the feature entities.                                 */
     802                 : /* -------------------------------------------------------------------- */
     803               1 :         if( poLayer->CreateFeature( poThisBlockFeat ) != OGRERR_NONE )
     804               0 :             return FALSE;
     805                 : 
     806                 : /* -------------------------------------------------------------------- */
     807                 : /*      Write out following features if they are the same block.        */
     808                 : /* -------------------------------------------------------------------- */
     809               2 :         while( iBlock < poBlocksLayer->apoBlocks.size()-1 
     810                 :             && EQUAL(poBlocksLayer->apoBlocks[iBlock+1]->GetFieldAsString("BlockName"),
     811                 :                      osBlockName) )
     812                 :         {
     813               0 :             iBlock++;
     814                 :             
     815               0 :             if( poLayer->CreateFeature( poBlocksLayer->apoBlocks[iBlock] )
     816                 :                 != OGRERR_NONE )
     817               0 :                 return FALSE;
     818                 :         }
     819                 :         
     820                 : /* -------------------------------------------------------------------- */
     821                 : /*      Write out the block definition postamble.                       */
     822                 : /* -------------------------------------------------------------------- */
     823               1 :         WriteValue( fp, 0, "ENDBLK" );
     824               1 :         WriteEntityID( fp );
     825               1 :         WriteValue( fp, 100, "AcDbEntity" );
     826               1 :         if( strlen(poThisBlockFeat->GetFieldAsString("Layer")) > 0 )
     827               0 :             WriteValue( fp, 8, poThisBlockFeat->GetFieldAsString("Layer") );
     828                 :         else
     829               1 :             WriteValue( fp, 8, "0" );
     830               1 :         WriteValue( fp, 100, "AcDbBlockEnd" );
     831                 :     }
     832                 : 
     833               1 :     return TRUE;
     834                 : }
     835                 : 
     836                 : /************************************************************************/
     837                 : /*                          ScanForEntities()                           */
     838                 : /*                                                                      */
     839                 : /*      Scan the indicated file for entity ids ("5" records) and        */
     840                 : /*      build them up as a set so we can be careful to avoid            */
     841                 : /*      creating new entities with conflicting ids.                     */
     842                 : /************************************************************************/
     843                 : 
     844              14 : void OGRDXFWriterDS::ScanForEntities( const char *pszFilename,
     845                 :                                       const char *pszTarget )
     846                 : 
     847                 : {
     848              14 :     OGRDXFReader oReader;
     849                 :     VSILFILE *fp;
     850                 : 
     851                 : /* -------------------------------------------------------------------- */
     852                 : /*      Open the file and setup a reader.                               */
     853                 : /* -------------------------------------------------------------------- */
     854              14 :     fp = VSIFOpenL( pszFilename, "r" );
     855                 : 
     856              14 :     if( fp == NULL )
     857                 :         return;
     858                 : 
     859              14 :     oReader.Initialize( fp );
     860                 : 
     861                 : /* -------------------------------------------------------------------- */
     862                 : /*      Add every code "5" line to our entities list.                   */
     863                 : /* -------------------------------------------------------------------- */
     864                 :     char szLineBuf[257];
     865                 :     int  nCode;
     866              14 :     const char *pszPortion = "HEADER";
     867                 : 
     868           13278 :     while( (nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 )
     869                 :     {
     870           13250 :         if( (nCode == 5 || nCode == 105) && EQUAL(pszTarget,pszPortion) )
     871                 :         {
     872             426 :             CPLString osEntity( szLineBuf );
     873                 : 
     874             426 :             if( CheckEntityID( osEntity ) )
     875                 :                 CPLDebug( "DXF", "Encounted entity '%s' multiple times.",
     876               6 :                           osEntity.c_str() );
     877                 :             else
     878             420 :                 aosUsedEntities.insert( osEntity );
     879                 :         }
     880                 : 
     881           13250 :         if( nCode == 0 && EQUAL(szLineBuf,"SECTION") )
     882                 :         {
     883              42 :             nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) );
     884              42 :             if( nCode == 2 && EQUAL(szLineBuf,"ENTITIES") )
     885               7 :                 pszPortion = "BODY";
     886              42 :             if( nCode == 2 && EQUAL(szLineBuf,"OBJECTS") )
     887               7 :                 pszPortion = "TRAILER";
     888                 :         }
     889                 :     }
     890                 : 
     891              14 :     VSIFCloseL( fp );
     892                 : }
     893                 : 
     894                 : /************************************************************************/
     895                 : /*                           CheckEntityID()                            */
     896                 : /*                                                                      */
     897                 : /*      Does the mentioned entity already exist?                        */
     898                 : /************************************************************************/
     899                 : 
     900             451 : int OGRDXFWriterDS::CheckEntityID( const char *pszEntityID )
     901                 : 
     902                 : {
     903             451 :     std::set<CPLString>::iterator it;
     904                 : 
     905             451 :     it = aosUsedEntities.find( pszEntityID );
     906             451 :     if( it != aosUsedEntities.end() )
     907               7 :         return TRUE;
     908                 :     else
     909             444 :         return FALSE;
     910                 : }
     911                 : 
     912                 : /************************************************************************/
     913                 : /*                           WriteEntityID()                            */
     914                 : /************************************************************************/
     915                 : 
     916              24 : long OGRDXFWriterDS::WriteEntityID( VSILFILE *fp, long nPreferredFID )
     917                 : 
     918                 : {
     919              24 :     CPLString osEntityID;
     920                 : 
     921              24 :     if( nPreferredFID != OGRNullFID )
     922                 :     {
     923                 :         
     924               1 :         osEntityID.Printf( "%X", (unsigned int) nPreferredFID );
     925               1 :         if( !CheckEntityID( osEntityID ) )
     926                 :         {
     927               0 :             aosUsedEntities.insert( osEntityID );
     928               0 :             WriteValue( fp, 5, osEntityID );
     929               0 :             return nPreferredFID;
     930                 :         }
     931                 :     }
     932                 : 
     933              24 :     do 
     934                 :     {
     935              24 :         osEntityID.Printf( "%X", nNextFID++ );
     936                 :     }
     937                 :     while( CheckEntityID( osEntityID ) );
     938                 :     
     939              24 :     aosUsedEntities.insert( osEntityID );
     940              24 :     WriteValue( fp, 5, osEntityID );
     941                 : 
     942              24 :     return nNextFID - 1;
     943                 : }
     944                 : 
     945                 : /************************************************************************/
     946                 : /*                           UpdateExtent()                             */
     947                 : /************************************************************************/
     948                 : 
     949              17 : void OGRDXFWriterDS::UpdateExtent( OGREnvelope* psEnvelope )
     950                 : {
     951              17 :     oGlobalEnvelope.Merge(*psEnvelope);
     952              17 : }

Generated by: LCOV version 1.7