LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/dxf - ogrdxfwriterds.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 311 251 80.7 %
Date: 2012-04-28 Functions: 21 15 71.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrdxfwriterds.cpp 21075 2010-11-06 20:45:00Z warmerdam $
       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 21075 2010-11-06 20:45:00Z warmerdam $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                          OGRDXFWriterDS()                          */
      39                 : /************************************************************************/
      40                 : 
      41              10 : OGRDXFWriterDS::OGRDXFWriterDS()
      42                 : 
      43                 : {
      44              10 :     fp = NULL;
      45              10 :     fpTemp = NULL;
      46              10 :     poLayer = NULL;
      47              10 :     poBlocksLayer = NULL;
      48              10 :     papszLayersToCreate = NULL;
      49              10 :     nNextFID = 80;
      50              10 :     nHANDSEEDOffset = 0;
      51              10 : }
      52                 : 
      53                 : /************************************************************************/
      54                 : /*                         ~OGRDXFWriterDS()                          */
      55                 : /************************************************************************/
      56                 : 
      57              10 : OGRDXFWriterDS::~OGRDXFWriterDS()
      58                 : 
      59                 : {
      60              10 :     if (fp != NULL)
      61                 :     {
      62                 : /* -------------------------------------------------------------------- */
      63                 : /*      Transfer over the header into the destination file with any     */
      64                 : /*      adjustments or insertions needed.                               */
      65                 : /* -------------------------------------------------------------------- */
      66              10 :         CPLDebug( "DXF", "Compose final DXF file from components." );
      67                 : 
      68              10 :         TransferUpdateHeader( fp );
      69                 : 
      70              10 :         if (fpTemp != NULL)
      71                 :         {
      72                 : /* -------------------------------------------------------------------- */
      73                 : /*      Copy in the temporary file contents.                            */
      74                 : /* -------------------------------------------------------------------- */
      75                 :             const char *pszLine;
      76                 : 
      77              10 :             VSIFCloseL(fpTemp);
      78              10 :             fpTemp = VSIFOpenL( osTempFilename, "r" );
      79                 : 
      80             616 :             while( (pszLine = CPLReadLineL(fpTemp)) != NULL )
      81                 :             {
      82             596 :                 VSIFWriteL( pszLine, 1, strlen(pszLine), fp );
      83             596 :                 VSIFWriteL( "\n", 1, 1, fp );
      84                 :             }
      85                 :                     
      86                 : /* -------------------------------------------------------------------- */
      87                 : /*      Cleanup temporary file.                                         */
      88                 : /* -------------------------------------------------------------------- */
      89              10 :             VSIFCloseL( fpTemp );
      90              10 :             VSIUnlink( osTempFilename );
      91                 :         }
      92                 : 
      93                 : /* -------------------------------------------------------------------- */
      94                 : /*      Write trailer.                                                  */
      95                 : /* -------------------------------------------------------------------- */
      96              10 :         if( osTrailerFile != "" )
      97              10 :             TransferUpdateTrailer( fp );
      98                 : 
      99                 : /* -------------------------------------------------------------------- */
     100                 : /*      Fixup the HANDSEED value now that we know all the entity ids    */
     101                 : /*      created.                                                        */
     102                 : /* -------------------------------------------------------------------- */
     103              10 :         FixupHANDSEED( fp );
     104                 : 
     105                 : /* -------------------------------------------------------------------- */
     106                 : /*      Close file.                                                     */
     107                 : /* -------------------------------------------------------------------- */
     108                 : 
     109              10 :         VSIFCloseL( fp );
     110              10 :         fp = NULL;
     111                 :     }
     112                 : 
     113                 : /* -------------------------------------------------------------------- */
     114                 : /*      Destroy layers.                                                 */
     115                 : /* -------------------------------------------------------------------- */
     116              10 :     delete poLayer;
     117              10 :     delete poBlocksLayer;
     118                 : 
     119              10 :     CSLDestroy(papszLayersToCreate);
     120              10 : }
     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              10 : int OGRDXFWriterDS::Open( const char * pszFilename, char **papszOptions )
     167                 : 
     168                 : {
     169                 : /* -------------------------------------------------------------------- */
     170                 : /*      Open the standard header, or a user provided header.            */
     171                 : /* -------------------------------------------------------------------- */
     172              10 :     if( CSLFetchNameValue(papszOptions,"HEADER") != NULL )
     173               6 :         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              10 :     if( CSLFetchNameValue(papszOptions,"TRAILER") != NULL )
     190               0 :         osTrailerFile = CSLFetchNameValue(papszOptions,"TRAILER");
     191                 :     else
     192                 :     {
     193              10 :         const char *pszValue = CPLFindFile( "gdal", "trailer.dxf" );
     194              10 :         if( pszValue != NULL )
     195              10 :             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              10 :     nNextFID = 80;
     205                 : #else
     206                 :     nNextFID = 131072;
     207                 : #endif
     208                 : 
     209              10 :     if( CSLFetchNameValue( papszOptions, "FIRST_ENTITY" ) != NULL )
     210               2 :         nNextFID = atoi(CSLFetchNameValue( papszOptions, "FIRST_ENTITY" ));
     211                 : 
     212                 : /* -------------------------------------------------------------------- */
     213                 : /*      Prescan the header and trailer for entity codes.                */
     214                 : /* -------------------------------------------------------------------- */
     215              10 :     ScanForEntities( osHeaderFile, "HEADER" );
     216              10 :     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              10 :     if( !oHeaderDS.Open( osHeaderFile, TRUE ) )
     223               0 :         return FALSE;
     224                 : 
     225                 : /* -------------------------------------------------------------------- */
     226                 : /*      Create the output file.                                         */
     227                 : /* -------------------------------------------------------------------- */
     228              10 :     fp = VSIFOpenL( pszFilename, "w+" );
     229                 : 
     230              10 :     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              10 :     osTempFilename = pszFilename;
     242              10 :     osTempFilename += ".tmp";
     243                 : 
     244              10 :     fpTemp = VSIFOpenL( osTempFilename, "w" );
     245              10 :     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              10 :     return TRUE;
     254                 : }
     255                 : 
     256                 : /************************************************************************/
     257                 : /*                            CreateLayer()                             */
     258                 : /************************************************************************/
     259                 : 
     260              12 : OGRLayer *OGRDXFWriterDS::CreateLayer( const char *pszName, 
     261                 :                                        OGRSpatialReference *, 
     262                 :                                        OGRwkbGeometryType, 
     263                 :                                        char ** )
     264                 : 
     265                 : {
     266              12 :     if( EQUAL(pszName,"blocks") && poBlocksLayer == NULL )
     267                 :     {
     268               2 :         poBlocksLayer = new OGRDXFBlocksWriterLayer( this );
     269               2 :         return poBlocksLayer;
     270                 :     }
     271              10 :     else if( poLayer == NULL )
     272                 :     {
     273              10 :         poLayer = new OGRDXFWriterLayer( this, fpTemp );
     274              10 :         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           19344 : static int WriteValue( VSILFILE *fp, int nCode, const char *pszLine )
     289                 : 
     290                 : {
     291                 :     char szLinePair[300];
     292                 : 
     293           19344 :     snprintf(szLinePair, sizeof(szLinePair), "%3d\n%s\n", nCode, pszLine );
     294           19344 :     size_t nLen = strlen(szLinePair);
     295           19344 :     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           19344 :         return TRUE;
     303                 : }
     304                 : 
     305                 : /************************************************************************/
     306                 : /*                        TransferUpdateHeader()                        */
     307                 : /************************************************************************/
     308                 : 
     309              10 : int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
     310                 : 
     311                 : {
     312              10 :     oHeaderDS.ResetReadPointer( 0 );
     313                 : 
     314                 : /* -------------------------------------------------------------------- */
     315                 : /*      Copy header, inserting in new objects as needed.                */
     316                 : /* -------------------------------------------------------------------- */
     317                 :     char szLineBuf[257];
     318                 :     int nCode;
     319              10 :     CPLString osSection, osTable, osEntity;
     320                 : 
     321            8132 :     while( (nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 
     322                 :            && osSection != "ENTITIES" )
     323                 :     {
     324            8112 :         if( nCode == 0 && EQUAL(szLineBuf,"ENDTAB") )
     325                 :         {
     326                 :             // If we are at the end of the LAYER TABLE consider inserting 
     327                 :             // missing definitions.
     328              90 :             if( osTable == "LAYER" )
     329                 :             {
     330              10 :                 if( !WriteNewLayerDefinitions( fp ) )
     331               0 :                     return FALSE;
     332                 :             }
     333                 : 
     334                 :             // If at the end of the BLOCK_RECORD TABLE consider inserting 
     335                 :             // missing definitions.
     336              90 :             if( osTable == "BLOCK_RECORD" && poBlocksLayer )
     337                 :             {
     338               2 :                 if( !WriteNewBlockRecords( fp ) )
     339               0 :                     return FALSE;
     340                 :             }
     341                 : 
     342                 :             // If at the end of the LTYPE TABLE consider inserting 
     343                 :             // missing layer type definitions.
     344              90 :             if( osTable == "LTYPE" )
     345                 :             {
     346              10 :                 if( !WriteNewLineTypeRecords( fp ) )
     347               0 :                     return FALSE;
     348                 :             }
     349                 : 
     350              90 :             osTable = "";
     351                 :         }
     352                 : 
     353                 :         // If we are at the end of the BLOCKS section, consider inserting
     354                 :         // suplementary blocks. 
     355            8112 :         if( nCode == 0 && osSection == "BLOCKS" && EQUAL(szLineBuf,"ENDSEC") 
     356                 :             && poBlocksLayer != NULL )
     357                 :         {
     358               2 :             if( !WriteNewBlockDefinitions( fp ) )
     359               0 :                 return FALSE;
     360                 :         }
     361                 : 
     362                 :         // We need to keep track of where $HANDSEED is so that we can
     363                 :         // come back and fix it up when we have generated all entity ids. 
     364            8112 :         if( nCode == 9 && EQUAL(szLineBuf,"$HANDSEED") )
     365                 :         {
     366              10 :             if( !WriteValue( fpOut, nCode, szLineBuf ) )
     367               0 :                 return FALSE;
     368                 : 
     369              10 :             nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
     370                 : 
     371                 :             // ensure we have room to overwrite with a longer value.
     372              80 :             while( strlen(szLineBuf) < 8 )
     373                 :             {
     374              60 :                 memmove( szLineBuf+1, szLineBuf, strlen(szLineBuf)+1 );
     375              60 :                 szLineBuf[0] = '0';
     376                 :             }
     377                 : 
     378              10 :             nHANDSEEDOffset = VSIFTellL( fpOut );
     379                 :         }
     380                 : 
     381                 :         // Copy over the source line.
     382            8112 :         if( !WriteValue( fpOut, nCode, szLineBuf ) )
     383               0 :             return FALSE;
     384                 : 
     385                 :         // Track what entity we are in - that is the last "code 0" object.
     386            8112 :         if( nCode == 0  )
     387             514 :             osEntity = szLineBuf;
     388                 : 
     389                 :         // Track what section we are in.
     390            8112 :         if( nCode == 0 && EQUAL(szLineBuf,"SECTION") )
     391                 :         {
     392              50 :             nCode = oHeaderDS.ReadValue( szLineBuf );
     393              50 :             if( nCode == -1 )
     394               0 :                 break;
     395                 : 
     396              50 :             if( !WriteValue( fpOut, nCode, szLineBuf ) )
     397               0 :                 return FALSE;
     398                 :                 
     399              50 :             osSection = szLineBuf;
     400                 :         }
     401                 : 
     402                 :         // Track what TABLE we are in.
     403            8112 :         if( nCode == 0 && EQUAL(szLineBuf,"TABLE") )
     404                 :         {
     405              90 :             nCode = oHeaderDS.ReadValue( szLineBuf );
     406              90 :             if( !WriteValue( fpOut, nCode, szLineBuf ) )
     407               0 :                 return FALSE;
     408                 : 
     409              90 :             osTable = szLineBuf;
     410                 :         }
     411                 :         
     412                 :         // If we are starting the first layer, then capture
     413                 :         // the layer contents while copying so we can duplicate
     414                 :         // it for any new layer definitions.
     415            8112 :         if( nCode == 0 && EQUAL(szLineBuf,"LAYER")
     416                 :             && osTable == "LAYER" && aosDefaultLayerText.size() == 0 )
     417                 :         {
     418             110 :             do { 
     419             110 :                 anDefaultLayerCode.push_back( nCode );
     420             110 :                 aosDefaultLayerText.push_back( szLineBuf );
     421                 : 
     422             110 :                 if( nCode != 0 && !WriteValue( fpOut, nCode, szLineBuf ) )
     423               0 :                     return FALSE;
     424                 : 
     425             110 :                 nCode = oHeaderDS.ReadValue( szLineBuf );
     426                 : 
     427             110 :                 if( nCode == 2 && !EQUAL(szLineBuf,"0") )
     428                 :                 {
     429               0 :                     anDefaultLayerCode.resize(0);
     430               0 :                     aosDefaultLayerText.resize(0);
     431               0 :                     break;
     432                 :                 }
     433                 :             } while( nCode != 0 );
     434                 : 
     435              10 :             oHeaderDS.UnreadValue();
     436                 :         }
     437                 :     }
     438                 : 
     439              10 :     return TRUE;
     440                 : }    
     441                 : 
     442                 : /************************************************************************/
     443                 : /*                       TransferUpdateTrailer()                        */
     444                 : /************************************************************************/
     445                 : 
     446              10 : int OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
     447                 : {
     448              10 :     OGRDXFReader oReader;
     449                 :     VSILFILE *fp;
     450                 : 
     451                 : /* -------------------------------------------------------------------- */
     452                 : /*      Open the file and setup a reader.                               */
     453                 : /* -------------------------------------------------------------------- */
     454              10 :     fp = VSIFOpenL( osTrailerFile, "r" );
     455                 : 
     456              10 :     if( fp == NULL )
     457               0 :         return FALSE;
     458                 : 
     459              10 :     oReader.Initialize( fp );
     460                 : 
     461                 : /* -------------------------------------------------------------------- */
     462                 : /*      Scan ahead to find the OBJECTS section.                         */
     463                 : /* -------------------------------------------------------------------- */
     464                 :     char szLineBuf[257];
     465                 :     int  nCode;
     466                 : 
     467              30 :     while( (nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 )
     468                 :     {
     469              20 :         if( nCode == 0 && EQUAL(szLineBuf,"SECTION") )
     470                 :         {
     471              10 :             nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) );
     472              10 :             if( nCode == 2 && EQUAL(szLineBuf,"OBJECTS") )
     473              10 :                 break;
     474                 :         }
     475                 :     }
     476                 : 
     477              10 :     if( nCode == -1 )
     478                 :     {
     479                 :         CPLError( CE_Failure, CPLE_AppDefined,
     480                 :                   "Failed to find OBJECTS section in trailer file '%s'.",
     481               0 :                   osTrailerFile.c_str() );
     482               0 :         return FALSE;
     483                 :     }
     484                 : 
     485                 : /* -------------------------------------------------------------------- */
     486                 : /*      Insert the "end of section" for ENTITIES, and the start of      */
     487                 : /*      the OBJECTS section.                                            */
     488                 : /* -------------------------------------------------------------------- */
     489              10 :     WriteValue( fpOut, 0, "ENDSEC" );
     490              10 :     WriteValue( fpOut, 0, "SECTION" );
     491              10 :     WriteValue( fpOut, 2, "OBJECTS" );
     492                 : 
     493                 : /* -------------------------------------------------------------------- */
     494                 : /*      Copy the remainder of the file.                                 */
     495                 : /* -------------------------------------------------------------------- */
     496           10800 :     while( (nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 )
     497                 :     {
     498           10780 :         if( !WriteValue( fpOut, nCode, szLineBuf ) )
     499                 :         {
     500               0 :             VSIFCloseL( fp );
     501               0 :             return FALSE;
     502                 :         }
     503                 :     }
     504                 : 
     505              10 :     VSIFCloseL( fp );
     506                 : 
     507              10 :     return TRUE;
     508                 : }
     509                 : 
     510                 : /************************************************************************/
     511                 : /*                           FixupHANDSEED()                            */
     512                 : /*                                                                      */
     513                 : /*      Fixup the next entity id information in the $HANDSEED header    */
     514                 : /*      variable.                                                       */
     515                 : /************************************************************************/
     516                 : 
     517              10 : int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fp )
     518                 : 
     519                 : {
     520                 : /* -------------------------------------------------------------------- */
     521                 : /*      What is a good next handle seed?  Scan existing values.         */
     522                 : /* -------------------------------------------------------------------- */
     523              10 :     unsigned int   nHighestHandle = 0;
     524              10 :     std::set<CPLString>::iterator it;
     525                 : 
     526             666 :     for( it = aosUsedEntities.begin(); it != aosUsedEntities.end(); it++ ) 
     527                 :     {
     528                 :         unsigned int nHandle;
     529             656 :         if( sscanf( (*it).c_str(), "%x", &nHandle ) == 1 )
     530                 :         {
     531             656 :             if( nHandle > nHighestHandle )
     532             412 :                 nHighestHandle = nHandle;
     533                 :         }
     534                 :     }
     535                 : 
     536                 : /* -------------------------------------------------------------------- */
     537                 : /*      Read the existing handseed value, replace it, and write back.   */
     538                 : /* -------------------------------------------------------------------- */
     539                 :     char szWorkBuf[30];
     540              10 :     int  i = 0;
     541                 : 
     542              10 :     if( nHANDSEEDOffset == 0 )
     543               0 :         return FALSE;
     544                 : 
     545              10 :     VSIFSeekL( fp, nHANDSEEDOffset, SEEK_SET );
     546              10 :     VSIFReadL( szWorkBuf, 1, sizeof(szWorkBuf), fp );
     547                 :     
     548              50 :     while( szWorkBuf[i] != '\n' )
     549              30 :         i++;
     550                 : 
     551              10 :     i++;
     552              10 :     if( szWorkBuf[i] == '\r' )
     553               0 :         i++;
     554                 :     
     555              10 :     CPLString osNewValue;
     556                 : 
     557              10 :     osNewValue.Printf( "%08X", nHighestHandle + 1 );
     558              10 :     strncpy( szWorkBuf + i, osNewValue.c_str(), osNewValue.size() );
     559                 : 
     560              10 :     VSIFSeekL( fp, nHANDSEEDOffset, SEEK_SET );
     561              10 :     VSIFWriteL( szWorkBuf, 1, sizeof(szWorkBuf), fp );
     562                 : 
     563              10 :     return TRUE;
     564                 : }
     565                 : 
     566                 : /************************************************************************/
     567                 : /*                      WriteNewLayerDefinitions()                      */
     568                 : /************************************************************************/
     569                 : 
     570              10 : int  OGRDXFWriterDS::WriteNewLayerDefinitions( VSILFILE * fpOut )
     571                 : 
     572                 : {                                               
     573              10 :     int iLayer, nNewLayers = CSLCount(papszLayersToCreate);
     574                 : 
     575              16 :     for( iLayer = 0; iLayer < nNewLayers; iLayer++ )
     576                 :     {
     577              72 :         for( unsigned i = 0; i < aosDefaultLayerText.size(); i++ )
     578                 :         {
     579              66 :             if( anDefaultLayerCode[i] == 2 )
     580                 :             {
     581               6 :                 if( !WriteValue( fpOut, 2, papszLayersToCreate[iLayer] ) )
     582               0 :                     return FALSE;
     583                 :             }
     584              60 :             else if( anDefaultLayerCode[i] == 5 )
     585                 :             {
     586               6 :                 WriteEntityID( fpOut );
     587                 :             }
     588                 :             else
     589                 :             {
     590              54 :                 if( !WriteValue( fpOut,
     591                 :                                  anDefaultLayerCode[i],
     592                 :                                  aosDefaultLayerText[i] ) )
     593               0 :                     return FALSE;
     594                 :             }
     595                 :         }
     596                 :     }
     597                 : 
     598              10 :     return TRUE;
     599                 : }
     600                 : 
     601                 : /************************************************************************/
     602                 : /*                      WriteNewLineTypeRecords()                       */
     603                 : /************************************************************************/
     604                 : 
     605              10 : int OGRDXFWriterDS::WriteNewLineTypeRecords( VSILFILE *fp )
     606                 : 
     607                 : {
     608              10 :     if( poLayer == NULL )
     609               0 :         return TRUE;
     610                 : 
     611              10 :     std::map<CPLString,CPLString>::iterator oIt;
     612                 :     std::map<CPLString,CPLString>& oNewLineTypes = 
     613              10 :         poLayer->GetNewLineTypeMap();
     614                 : 
     615              14 :     for( oIt = oNewLineTypes.begin(); 
     616                 :          oIt != oNewLineTypes.end(); oIt++ )
     617                 :     {
     618               4 :         WriteValue( fp, 0, "LTYPE" );
     619               4 :         WriteEntityID( fp );
     620               4 :         WriteValue( fp, 100, "AcDbSymbolTableRecord" );
     621               4 :         WriteValue( fp, 100, "AcDbLinetypeTableRecord" );
     622               4 :         WriteValue( fp, 2, (*oIt).first );
     623               4 :         WriteValue( fp, 70, "0" );
     624               4 :         WriteValue( fp, 3, "" );
     625               4 :         WriteValue( fp, 72, "65" );
     626               4 :         VSIFWriteL( (*oIt).second.c_str(), 1, (*oIt).second.size(), fp );
     627                 : 
     628                 :         CPLDebug( "DXF", "Define Line type '%s'.", 
     629               4 :                   (*oIt).first.c_str() );
     630                 :     }
     631                 : 
     632              10 :     return TRUE;
     633                 : }
     634                 : 
     635                 : /************************************************************************/
     636                 : /*                        WriteNewBlockRecords()                        */
     637                 : /************************************************************************/
     638                 : 
     639               2 : int OGRDXFWriterDS::WriteNewBlockRecords( VSILFILE * fp )
     640                 : 
     641                 : {
     642               2 :     std::set<CPLString> aosAlreadyHandled;
     643                 : 
     644                 : /* ==================================================================== */
     645                 : /*      Loop over all block objects written via the blocks layer.       */
     646                 : /* ==================================================================== */
     647               2 :     for( size_t iBlock=0; iBlock < poBlocksLayer->apoBlocks.size(); iBlock++ )
     648                 :     {
     649               2 :         OGRFeature* poThisBlockFeat = poBlocksLayer->apoBlocks[iBlock];
     650                 : 
     651                 : /* -------------------------------------------------------------------- */
     652                 : /*      Is this block already defined in the template header?           */
     653                 : /* -------------------------------------------------------------------- */
     654               2 :         CPLString osBlockName = poThisBlockFeat->GetFieldAsString("BlockName");
     655                 : 
     656               2 :         if( oHeaderDS.LookupBlock( osBlockName ) != NULL )
     657               0 :             continue;
     658                 : 
     659                 : /* -------------------------------------------------------------------- */
     660                 : /*      Have we already written a BLOCK_RECORD for this block?          */
     661                 : /* -------------------------------------------------------------------- */
     662               2 :         if( aosAlreadyHandled.find(osBlockName) != aosAlreadyHandled.end() )
     663               0 :             continue;
     664                 : 
     665               2 :         aosAlreadyHandled.insert( osBlockName );
     666                 : 
     667                 : /* -------------------------------------------------------------------- */
     668                 : /*      Write the block record.                                         */
     669                 : /* -------------------------------------------------------------------- */
     670               2 :         WriteValue( fp, 0, "BLOCK_RECORD" );
     671               2 :         WriteEntityID( fp );
     672               2 :         WriteValue( fp, 100, "AcDbSymbolTableRecord" );
     673               2 :         WriteValue( fp, 100, "AcDbBlockTableRecord" );
     674               2 :         WriteValue( fp, 2, poThisBlockFeat->GetFieldAsString("BlockName") );
     675               2 :         if( !WriteValue( fp, 340, "0" ) )
     676               0 :             return FALSE;
     677                 :     }
     678                 : 
     679               2 :     return TRUE;
     680                 : }
     681                 : 
     682                 : /************************************************************************/
     683                 : /*                      WriteNewBlockDefinitions()                      */
     684                 : /************************************************************************/
     685                 : 
     686               2 : int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fp )
     687                 : 
     688                 : {
     689               2 :     poLayer->ResetFP( fp );
     690                 : 
     691                 : /* ==================================================================== */
     692                 : /*      Loop over all block objects written via the blocks layer.       */
     693                 : /* ==================================================================== */
     694               2 :     for( size_t iBlock=0; iBlock < poBlocksLayer->apoBlocks.size(); iBlock++ )
     695                 :     {
     696               2 :         OGRFeature* poThisBlockFeat = poBlocksLayer->apoBlocks[iBlock];
     697                 : 
     698                 : /* -------------------------------------------------------------------- */
     699                 : /*      Is this block already defined in the template header?           */
     700                 : /* -------------------------------------------------------------------- */
     701               2 :         CPLString osBlockName = poThisBlockFeat->GetFieldAsString("BlockName");
     702                 : 
     703               2 :         if( oHeaderDS.LookupBlock( osBlockName ) != NULL )
     704               0 :             continue;
     705                 : 
     706                 : /* -------------------------------------------------------------------- */
     707                 : /*      Write the block definition preamble.                            */
     708                 : /* -------------------------------------------------------------------- */
     709                 :         CPLDebug( "DXF", "Writing BLOCK definition for '%s'.",
     710               2 :                   poThisBlockFeat->GetFieldAsString("BlockName") );
     711                 : 
     712               2 :         WriteValue( fp, 0, "BLOCK" );
     713               2 :         WriteEntityID( fp );
     714               2 :         WriteValue( fp, 100, "AcDbEntity" );
     715               2 :         if( strlen(poThisBlockFeat->GetFieldAsString("Layer")) > 0 )
     716               0 :             WriteValue( fp, 8, poThisBlockFeat->GetFieldAsString("Layer") );
     717                 :         else
     718               2 :             WriteValue( fp, 8, "0" );
     719               2 :         WriteValue( fp, 100, "AcDbBlockBegin" );
     720               2 :         WriteValue( fp, 2, poThisBlockFeat->GetFieldAsString("BlockName") );
     721               2 :         WriteValue( fp, 70, "0" );
     722                 : 
     723                 :         // Origin
     724               2 :         WriteValue( fp, 10, "0.0" );
     725               2 :         WriteValue( fp, 20, "0.0" );
     726               2 :         WriteValue( fp, 30, "0.0" );
     727                 : 
     728               2 :         WriteValue( fp, 3, poThisBlockFeat->GetFieldAsString("BlockName") );
     729               2 :         WriteValue( fp, 1, "" );
     730                 : 
     731                 : /* -------------------------------------------------------------------- */
     732                 : /*      Write out the feature entities.                                 */
     733                 : /* -------------------------------------------------------------------- */
     734               2 :         if( poLayer->CreateFeature( poThisBlockFeat ) != OGRERR_NONE )
     735               0 :             return FALSE;
     736                 : 
     737                 : /* -------------------------------------------------------------------- */
     738                 : /*      Write out following features if they are the same block.        */
     739                 : /* -------------------------------------------------------------------- */
     740               4 :         while( iBlock < poBlocksLayer->apoBlocks.size()-1 
     741                 :             && EQUAL(poBlocksLayer->apoBlocks[iBlock+1]->GetFieldAsString("BlockName"),
     742                 :                      osBlockName) )
     743                 :         {
     744               0 :             iBlock++;
     745                 :             
     746               0 :             if( poLayer->CreateFeature( poBlocksLayer->apoBlocks[iBlock] )
     747                 :                 != OGRERR_NONE )
     748               0 :                 return FALSE;
     749                 :         }
     750                 :         
     751                 : /* -------------------------------------------------------------------- */
     752                 : /*      Write out the block definition postamble.                       */
     753                 : /* -------------------------------------------------------------------- */
     754               2 :         WriteValue( fp, 0, "ENDBLK" );
     755               2 :         WriteEntityID( fp );
     756               2 :         WriteValue( fp, 100, "AcDbEntity" );
     757               2 :         if( strlen(poThisBlockFeat->GetFieldAsString("Layer")) > 0 )
     758               0 :             WriteValue( fp, 8, poThisBlockFeat->GetFieldAsString("Layer") );
     759                 :         else
     760               2 :             WriteValue( fp, 8, "0" );
     761               2 :         WriteValue( fp, 100, "AcDbBlockEnd" );
     762                 :     }
     763                 : 
     764               2 :     return TRUE;
     765                 : }
     766                 : 
     767                 : /************************************************************************/
     768                 : /*                          ScanForEntities()                           */
     769                 : /*                                                                      */
     770                 : /*      Scan the indicated file for entity ids ("5" records) and        */
     771                 : /*      build them up as a set so we can be careful to avoid            */
     772                 : /*      creating new entities with conflicting ids.                     */
     773                 : /************************************************************************/
     774                 : 
     775              20 : void OGRDXFWriterDS::ScanForEntities( const char *pszFilename,
     776                 :                                       const char *pszTarget )
     777                 : 
     778                 : {
     779              20 :     OGRDXFReader oReader;
     780                 :     VSILFILE *fp;
     781                 : 
     782                 : /* -------------------------------------------------------------------- */
     783                 : /*      Open the file and setup a reader.                               */
     784                 : /* -------------------------------------------------------------------- */
     785              20 :     fp = VSIFOpenL( pszFilename, "r" );
     786                 : 
     787              20 :     if( fp == NULL )
     788                 :         return;
     789                 : 
     790              20 :     oReader.Initialize( fp );
     791                 : 
     792                 : /* -------------------------------------------------------------------- */
     793                 : /*      Add every code "5" line to our entities list.                   */
     794                 : /* -------------------------------------------------------------------- */
     795                 :     char szLineBuf[257];
     796                 :     int  nCode;
     797              20 :     const char *pszPortion = "HEADER";
     798                 : 
     799           19152 :     while( (nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 )
     800                 :     {
     801           19112 :         if( (nCode == 5 || nCode == 105) && EQUAL(pszTarget,pszPortion) )
     802                 :         {
     803             624 :             CPLString osEntity( szLineBuf );
     804                 : 
     805             624 :             if( CheckEntityID( osEntity ) )
     806                 :                 CPLDebug( "DXF", "Encounted entity '%s' multiple times.",
     807              12 :                           osEntity.c_str() );
     808                 :             else
     809             612 :                 aosUsedEntities.insert( osEntity );
     810                 :         }
     811                 : 
     812           19112 :         if( nCode == 0 && EQUAL(szLineBuf,"SECTION") )
     813                 :         {
     814              60 :             nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) );
     815              60 :             if( nCode == 2 && EQUAL(szLineBuf,"ENTITIES") )
     816              10 :                 pszPortion = "BODY";
     817              60 :             if( nCode == 2 && EQUAL(szLineBuf,"OBJECTS") )
     818              10 :                 pszPortion = "TRAILER";
     819                 :         }
     820                 :     }
     821                 : 
     822              20 :     VSIFCloseL( fp );
     823                 : }
     824                 : 
     825                 : /************************************************************************/
     826                 : /*                           CheckEntityID()                            */
     827                 : /*                                                                      */
     828                 : /*      Does the mentioned entity already exist?                        */
     829                 : /************************************************************************/
     830                 : 
     831             670 : int OGRDXFWriterDS::CheckEntityID( const char *pszEntityID )
     832                 : 
     833                 : {
     834             670 :     std::set<CPLString>::iterator it;
     835                 : 
     836             670 :     it = aosUsedEntities.find( pszEntityID );
     837             670 :     if( it != aosUsedEntities.end() )
     838              14 :         return TRUE;
     839                 :     else
     840             656 :         return FALSE;
     841                 : }
     842                 : 
     843                 : /************************************************************************/
     844                 : /*                           WriteEntityID()                            */
     845                 : /************************************************************************/
     846                 : 
     847              44 : long OGRDXFWriterDS::WriteEntityID( VSILFILE *fp, long nPreferredFID )
     848                 : 
     849                 : {
     850              44 :     CPLString osEntityID;
     851                 : 
     852              44 :     if( nPreferredFID != OGRNullFID )
     853                 :     {
     854                 :         
     855               2 :         osEntityID.Printf( "%X", (unsigned int) nPreferredFID );
     856               2 :         if( !CheckEntityID( osEntityID ) )
     857                 :         {
     858               0 :             aosUsedEntities.insert( osEntityID );
     859               0 :             WriteValue( fp, 5, osEntityID );
     860               0 :             return nPreferredFID;
     861                 :         }
     862                 :     }
     863                 : 
     864              44 :     do 
     865                 :     {
     866              44 :         osEntityID.Printf( "%X", nNextFID++ );
     867                 :     }
     868                 :     while( CheckEntityID( osEntityID ) );
     869                 :     
     870              44 :     aosUsedEntities.insert( osEntityID );
     871              44 :     WriteValue( fp, 5, osEntityID );
     872                 : 
     873              44 :     return nNextFID - 1;
     874                 : }

Generated by: LCOV version 1.7