LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/mitab - mitab_mapobjectblock.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 672 231 34.4 %
Date: 2012-12-26 Functions: 45 21 46.7 %

       1                 : /**********************************************************************
       2                 :  * $Id: mitab_mapobjectblock.cpp,v 1.23 2010-07-07 19:00:15 aboudreault Exp $
       3                 :  *
       4                 :  * Name:     mitab_mapobjectblock.cpp
       5                 :  * Project:  MapInfo TAB Read/Write library
       6                 :  * Language: C++
       7                 :  * Purpose:  Implementation of the TABMAPObjectBlock class used to handle
       8                 :  *           reading/writing of the .MAP files' object data blocks
       9                 :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
      10                 :  *
      11                 :  **********************************************************************
      12                 :  * Copyright (c) 1999-2001, Daniel Morissette
      13                 :  *
      14                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      15                 :  * copy of this software and associated documentation files (the "Software"),
      16                 :  * to deal in the Software without restriction, including without limitation
      17                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18                 :  * and/or sell copies of the Software, and to permit persons to whom the
      19                 :  * Software is furnished to do so, subject to the following conditions:
      20                 :  * 
      21                 :  * The above copyright notice and this permission notice shall be included
      22                 :  * in all copies or substantial portions of the Software.
      23                 :  * 
      24                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      25                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      27                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      30                 :  * DEALINGS IN THE SOFTWARE.
      31                 :  **********************************************************************
      32                 :  *
      33                 :  * $Log: mitab_mapobjectblock.cpp,v $
      34                 :  * Revision 1.23  2010-07-07 19:00:15  aboudreault
      35                 :  * Cleanup Win32 Compile Warnings (GDAL bug #2930)
      36                 :  *
      37                 :  * Revision 1.22  2008-02-20 21:35:30  dmorissette
      38                 :  * Added support for V800 COLLECTION of large objects (bug 1496)
      39                 :  *
      40                 :  * Revision 1.21  2008/02/05 22:22:48  dmorissette
      41                 :  * Added support for TAB_GEOM_V800_MULTIPOINT (bug 1496)
      42                 :  *
      43                 :  * Revision 1.20  2008/02/01 19:36:31  dmorissette
      44                 :  * Initial support for V800 REGION and MULTIPLINE (bug 1496)
      45                 :  *
      46                 :  * Revision 1.19  2007/09/18 17:43:56  dmorissette
      47                 :  * Fixed another index splitting issue: compr coordinates origin was not
      48                 :  * stored in the TABFeature in ReadGeometry... (bug 1732)
      49                 :  *
      50                 :  * Revision 1.18  2007/06/11 14:52:31  dmorissette
      51                 :  * Return a valid m_nCoordDatasize value for Collection objects to prevent
      52                 :  * trashing of collection data during object splitting (bug 1728)
      53                 :  *
      54                 :  * Revision 1.17  2007/05/22 14:53:10  dmorissette
      55                 :  * Fixed error reading compressed text objects introduced in v1.6.0 (bug 1722)
      56                 :  *
      57                 :  * Revision 1.16  2006/11/28 18:49:08  dmorissette
      58                 :  * Completed changes to split TABMAPObjectBlocks properly and produce an
      59                 :  * optimal spatial index (bug 1585)
      60                 :  *
      61                 :  * Revision 1.15  2005/10/06 19:15:31  dmorissette
      62                 :  * Collections: added support for reading/writing pen/brush/symbol ids and
      63                 :  * for writing collection objects to .TAB/.MAP (bug 1126)
      64                 :  *
      65                 :  * Revision 1.14  2005/10/04 15:44:31  dmorissette
      66                 :  * First round of support for Collection objects. Currently supports reading
      67                 :  * from .TAB/.MAP and writing to .MIF. Still lacks symbol support and write
      68                 :  * support. (Based in part on patch and docs from Jim Hope, bug 1126)
      69                 :  *
      70                 :  * Revision 1.13  2004/06/30 20:29:04  dmorissette
      71                 :  * Fixed refs to old address danmo@videotron.ca
      72                 :  *
      73                 :  * Revision 1.12  2002/03/26 01:48:40  daniel
      74                 :  * Added Multipoint object type (V650)
      75                 :  *
      76                 :  * Revision 1.11  2001/12/05 22:40:27  daniel
      77                 :  * Init MBR to 0 in TABMAPObjHdr and modif. SetMBR() to validate min/max
      78                 :  *
      79                 :  * Revision 1.10  2001/11/19 15:07:06  daniel
      80                 :  * Handle the case of TAB_GEOM_NONE with the new TABMAPObjHdr classes.
      81                 :  *
      82                 :  * Revision 1.9  2001/11/17 21:54:06  daniel
      83                 :  * Made several changes in order to support writing objects in 16 bits 
      84                 :  * coordinate format. New TABMAPObjHdr-derived classes are used to hold 
      85                 :  * object info in mem until block is full.
      86                 :  *
      87                 :  * Revision 1.8  2001/09/19 19:19:11  warmerda
      88                 :  * modified AdvanceToNextObject() to skip deleted objects
      89                 :  *
      90                 :  * Revision 1.7  2001/09/14 03:23:55  warmerda
      91                 :  * Substantial upgrade to support spatial queries using spatial indexes
      92                 :  *
      93                 :  * Revision 1.6  2000/01/15 22:30:44  daniel
      94                 :  * Switch to MIT/X-Consortium OpenSource license
      95                 :  *
      96                 :  * Revision 1.5  1999/10/19 06:07:29  daniel
      97                 :  * Removed obsolete comment.
      98                 :  *
      99                 :  * Revision 1.4  1999/10/18 15:41:00  daniel
     100                 :  * Added WriteIntMBRCoord()
     101                 :  *
     102                 :  * Revision 1.3  1999/09/29 04:23:06  daniel
     103                 :  * Fixed typo in GetMBR()
     104                 :  *
     105                 :  * Revision 1.2  1999/09/26 14:59:37  daniel
     106                 :  * Implemented write support
     107                 :  *
     108                 :  * Revision 1.1  1999/07/12 04:18:25  daniel
     109                 :  * Initial checkin
     110                 :  *
     111                 :  **********************************************************************/
     112                 : 
     113                 : #include "mitab.h"
     114                 : 
     115                 : /*=====================================================================
     116                 :  *                      class TABMAPObjectBlock
     117                 :  *====================================================================*/
     118                 : 
     119                 : #define MAP_OBJECT_HEADER_SIZE   20
     120                 : 
     121                 : /**********************************************************************
     122                 :  *                   TABMAPObjectBlock::TABMAPObjectBlock()
     123                 :  *
     124                 :  * Constructor.
     125                 :  **********************************************************************/
     126               6 : TABMAPObjectBlock::TABMAPObjectBlock(TABAccess eAccessMode /*= TABRead*/):
     127               6 :     TABRawBinBlock(eAccessMode, TRUE)
     128                 : {
     129               6 : }
     130                 : 
     131                 : /**********************************************************************
     132                 :  *                   TABMAPObjectBlock::~TABMAPObjectBlock()
     133                 :  *
     134                 :  * Destructor.
     135                 :  **********************************************************************/
     136               6 : TABMAPObjectBlock::~TABMAPObjectBlock()
     137                 : {
     138                 : 
     139               6 :     m_nMinX = 1000000000;
     140               6 :     m_nMinY = 1000000000;
     141               6 :     m_nMaxX = -1000000000;
     142               6 :     m_nMaxY = -1000000000;
     143               6 : }
     144                 : 
     145                 : 
     146                 : /**********************************************************************
     147                 :  *                   TABMAPObjectBlock::InitBlockFromData()
     148                 :  *
     149                 :  * Perform some initialization on the block after its binary data has
     150                 :  * been set or changed (or loaded from a file).
     151                 :  *
     152                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     153                 :  * CPLError() will have been called.
     154                 :  **********************************************************************/
     155               3 : int     TABMAPObjectBlock::InitBlockFromData(GByte *pabyBuf,
     156                 :                                              int nBlockSize, int nSizeUsed, 
     157                 :                                              GBool bMakeCopy /* = TRUE */,
     158                 :                                              FILE *fpSrc /* = NULL */, 
     159                 :                                              int nOffset /* = 0 */)
     160                 : {
     161                 :     int nStatus;
     162                 : 
     163                 :     /*-----------------------------------------------------------------
     164                 :      * First of all, we must call the base class' InitBlockFromData()
     165                 :      *----------------------------------------------------------------*/
     166                 :     nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf, 
     167                 :                                                 nBlockSize, nSizeUsed, 
     168                 :                                                 bMakeCopy,
     169               3 :                                                 fpSrc, nOffset);
     170               3 :     if (nStatus != 0)   
     171               0 :         return nStatus;
     172                 : 
     173                 :     /*-----------------------------------------------------------------
     174                 :      * Validate block type
     175                 :      *----------------------------------------------------------------*/
     176               3 :     if (m_nBlockType != TABMAP_OBJECT_BLOCK)
     177                 :     {
     178                 :         CPLError(CE_Failure, CPLE_FileIO,
     179                 :                  "InitBlockFromData(): Invalid Block Type: got %d expected %d",
     180               0 :                  m_nBlockType, TABMAP_OBJECT_BLOCK);
     181               0 :         CPLFree(m_pabyBuf);
     182               0 :         m_pabyBuf = NULL;
     183               0 :         return -1;
     184                 :     }
     185                 : 
     186                 :     /*-----------------------------------------------------------------
     187                 :      * Init member variables
     188                 :      *----------------------------------------------------------------*/
     189               3 :     GotoByteInBlock(0x002);
     190               3 :     m_numDataBytes = ReadInt16();       /* Excluding 4 bytes header */
     191                 : 
     192               3 :     m_nCenterX = ReadInt32();
     193               3 :     m_nCenterY = ReadInt32();
     194                 : 
     195               3 :     m_nFirstCoordBlock = ReadInt32();
     196               3 :     m_nLastCoordBlock = ReadInt32();
     197                 : 
     198               3 :     m_nCurObjectOffset = -1;
     199               3 :     m_nCurObjectId = -1;
     200               3 :     m_nCurObjectType = -1;
     201                 : 
     202                 :     /*-----------------------------------------------------------------
     203                 :      * Set real value for m_nSizeUsed to allow random update
     204                 :      * (By default TABRawBinBlock thinks all 512 bytes are used)
     205                 :      *----------------------------------------------------------------*/
     206               3 :     m_nSizeUsed = m_numDataBytes + MAP_OBJECT_HEADER_SIZE;
     207                 : 
     208               3 :     return 0;
     209                 : }
     210                 : 
     211                 : /************************************************************************/
     212                 : /*                        Rewind()                                      */
     213                 : /************************************************************************/
     214               0 : void TABMAPObjectBlock::Rewind( )
     215                 : {
     216               0 :     m_nCurObjectId = -1;
     217               0 :     m_nCurObjectOffset = -1;
     218               0 :     m_nCurObjectType = -1;
     219               0 : }
     220                 : 
     221                 : /************************************************************************/
     222                 : /*                        AdvanceToNextObject()                         */
     223                 : /************************************************************************/
     224                 : 
     225              11 : int TABMAPObjectBlock::AdvanceToNextObject( TABMAPHeaderBlock *poHeader )
     226                 : 
     227                 : {
     228              11 :     if( m_nCurObjectId == -1 ) 
     229                 :     {
     230               1 :         m_nCurObjectOffset = 20;
     231                 :     }
     232                 :     else
     233                 :     {
     234              10 :         m_nCurObjectOffset += poHeader->GetMapObjectSize( m_nCurObjectType );
     235                 :     }
     236                 :     
     237                 :     
     238                 : 
     239              11 :     if( m_nCurObjectOffset + 5 < m_numDataBytes + 20 )
     240                 :     {
     241              10 :         GotoByteInBlock( m_nCurObjectOffset );
     242              10 :         m_nCurObjectType = ReadByte();
     243                 :     }
     244                 :     else
     245                 :     {
     246               1 :         m_nCurObjectType = -1;
     247                 :     }
     248                 : 
     249              12 :     if( m_nCurObjectType <= 0 || m_nCurObjectType >= 0x80 )
     250                 :     {
     251               1 :         m_nCurObjectType = -1;
     252               1 :         m_nCurObjectId = -1;
     253               1 :         m_nCurObjectOffset = -1;
     254                 :     }
     255                 :     else
     256                 :     {
     257              10 :         m_nCurObjectId = ReadInt32();
     258                 : 
     259                 :         // Is this object marked as deleted?  If so, skip it.
     260                 :         // I check both the top bits but I have only seen this occur
     261                 :         // with the second highest bit set (ie. in usa/states.tab). NFW.
     262                 : 
     263              10 :         if( (((GUInt32)m_nCurObjectId) & (GUInt32) 0xC0000000) != 0 )
     264                 :         {
     265               0 :             m_nCurObjectId = AdvanceToNextObject( poHeader );
     266                 :         }
     267                 :     }
     268                 : 
     269              11 :     return m_nCurObjectId;
     270                 : }
     271                 : 
     272                 : /**********************************************************************
     273                 :  *                   TABMAPObjectBlock::CommitToFile()
     274                 :  *
     275                 :  * Commit the current state of the binary block to the file to which 
     276                 :  * it has been previously attached.
     277                 :  *
     278                 :  * This method makes sure all values are properly set in the map object
     279                 :  * block header and then calls TABRawBinBlock::CommitToFile() to do
     280                 :  * the actual writing to disk.
     281                 :  *
     282                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     283                 :  * CPLError() will have been called.
     284                 :  **********************************************************************/
     285               2 : int     TABMAPObjectBlock::CommitToFile()
     286                 : {
     287               2 :     int nStatus = 0;
     288                 : 
     289               2 :     if ( m_pabyBuf == NULL )
     290                 :     {
     291                 :         CPLError(CE_Failure, CPLE_AssertionFailed, 
     292               0 :      "TABMAPObjectBlock::CommitToFile(): Block has not been initialized yet!");
     293               0 :         return -1;
     294                 :     }
     295                 : 
     296                 :     /*-----------------------------------------------------------------
     297                 :      * Make sure 20 bytes block header is up to date.
     298                 :      *----------------------------------------------------------------*/
     299               2 :     GotoByteInBlock(0x000);
     300                 : 
     301               2 :     WriteInt16(TABMAP_OBJECT_BLOCK);    // Block type code
     302               2 :     m_numDataBytes = m_nSizeUsed - MAP_OBJECT_HEADER_SIZE;
     303               2 :     WriteInt16((GInt16)m_numDataBytes);         // num. bytes used
     304                 :     
     305               2 :     WriteInt32(m_nCenterX);
     306               2 :     WriteInt32(m_nCenterY);
     307                 : 
     308               2 :     WriteInt32(m_nFirstCoordBlock);
     309               2 :     WriteInt32(m_nLastCoordBlock);
     310                 : 
     311               2 :     nStatus = CPLGetLastErrorNo();
     312                 : 
     313                 :     /*-----------------------------------------------------------------
     314                 :      * OK, all object data has already been written in the block.
     315                 :      * Call the base class to write the block to disk.
     316                 :      *----------------------------------------------------------------*/
     317               2 :     if (nStatus == 0)
     318               2 :         nStatus = TABRawBinBlock::CommitToFile();
     319                 : 
     320               2 :     return nStatus;
     321                 : }
     322                 : 
     323                 : /**********************************************************************
     324                 :  *                   TABMAPObjectBlock::InitNewBlock()
     325                 :  *
     326                 :  * Initialize a newly created block so that it knows to which file it
     327                 :  * is attached, its block size, etc . and then perform any specific 
     328                 :  * initialization for this block type, including writing a default 
     329                 :  * block header, etc. and leave the block ready to receive data.
     330                 :  *
     331                 :  * This is an alternative to calling ReadFromFile() or InitBlockFromData()
     332                 :  * that puts the block in a stable state without loading any initial
     333                 :  * data in it.
     334                 :  *
     335                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     336                 :  * CPLError() will have been called.
     337                 :  **********************************************************************/
     338               5 : int     TABMAPObjectBlock::InitNewBlock(FILE *fpSrc, int nBlockSize, 
     339                 :                                         int nFileOffset /* = 0*/)
     340                 : {
     341                 :     /*-----------------------------------------------------------------
     342                 :      * Start with the default initialisation
     343                 :      *----------------------------------------------------------------*/
     344               5 :     if ( TABRawBinBlock::InitNewBlock(fpSrc, nBlockSize, nFileOffset) != 0)
     345               0 :         return -1;
     346                 : 
     347                 :     /*-----------------------------------------------------------------
     348                 :      * And then set default values for the block header.
     349                 :      *----------------------------------------------------------------*/
     350                 :     // Set block MBR to extreme values to force an update on the first
     351                 :     // UpdateMBR() call.
     352               5 :     m_nMinX = 1000000000;
     353               5 :     m_nMaxX = -1000000000;
     354               5 :     m_nMinY = 1000000000;
     355               5 :     m_nMaxY = -1000000000;
     356                 : 
     357                 :     // Reset current object refs
     358               5 :     m_nCurObjectId = -1;
     359               5 :     m_nCurObjectOffset = -1;
     360               5 :     m_nCurObjectType = -1;
     361                 : 
     362               5 :     m_numDataBytes = 0;       /* Data size excluding header */
     363               5 :     m_nCenterX = m_nCenterY = 0;
     364               5 :     m_nFirstCoordBlock = 0;
     365               5 :     m_nLastCoordBlock = 0;
     366                 : 
     367               5 :     if (m_eAccess != TABRead)
     368                 :     {
     369               2 :         GotoByteInBlock(0x000);
     370                 : 
     371               2 :         WriteInt16(TABMAP_OBJECT_BLOCK);// Block type code
     372               2 :         WriteInt16(0);                  // num. bytes used, excluding header
     373                 :     
     374                 :         // MBR center here... will be written in CommitToFile()
     375               2 :         WriteInt32(0);
     376               2 :         WriteInt32(0);
     377                 : 
     378                 :         // First/last coord block ref... will be written in CommitToFile()
     379               2 :         WriteInt32(0);
     380               2 :         WriteInt32(0);
     381                 :     }
     382                 : 
     383               5 :     if (CPLGetLastErrorNo() != 0)
     384               0 :         return -1;
     385                 : 
     386               5 :     return 0;
     387                 : }
     388                 : 
     389                 : /**********************************************************************
     390                 :  *                   TABMAPObjectBlock::ReadCoord()
     391                 :  *
     392                 :  * Read the next pair of integer coordinates value from the block, and
     393                 :  * apply the translation relative to to the center of the data block
     394                 :  * if bCompressed=TRUE.
     395                 :  *
     396                 :  * This means that the returned coordinates are always absolute integer
     397                 :  * coordinates, even when the source coords are in compressed form.
     398                 :  *
     399                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     400                 :  * CPLError() will have been called.
     401                 :  **********************************************************************/
     402               2 : int     TABMAPObjectBlock::ReadIntCoord(GBool bCompressed, 
     403                 :                                         GInt32 &nX, GInt32 &nY)
     404                 : {
     405               2 :     if (bCompressed)
     406                 :     {   
     407               0 :         nX = m_nCenterX + ReadInt16();
     408               0 :         nY = m_nCenterY + ReadInt16();
     409                 :     }
     410                 :     else
     411                 :     {
     412               2 :         nX = ReadInt32();
     413               2 :         nY = ReadInt32();
     414                 :     }
     415                 : 
     416               2 :     if (CPLGetLastErrorNo() != 0)
     417               0 :         return -1;
     418                 : 
     419               2 :     return 0;
     420                 : }
     421                 : 
     422                 : /**********************************************************************
     423                 :  *                   TABMAPObjectBlock::WriteIntCoord()
     424                 :  *
     425                 :  * Write a pair of integer coordinates values to the current position in the
     426                 :  * the block.  If bCompr=TRUE then the coordinates are written relative to
     427                 :  * the object block center... otherwise they're written as 32 bits int.
     428                 :  *
     429                 :  * This function does not maintain the block's MBR and center... it is 
     430                 :  * assumed to have been set before the first call to WriteIntCoord()
     431                 :  *
     432                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     433                 :  * CPLError() will have been called.
     434                 :  **********************************************************************/
     435               2 : int     TABMAPObjectBlock::WriteIntCoord(GInt32 nX, GInt32 nY,
     436                 :                                          GBool bCompressed /*=FALSE*/)
     437                 : {
     438                 : 
     439                 :     /*-----------------------------------------------------------------
     440                 :      * Write coords to the file.
     441                 :      *----------------------------------------------------------------*/
     442               2 :     if ((!bCompressed && (WriteInt32(nX) != 0 || WriteInt32(nY) != 0 ) ) ||
     443                 :         (bCompressed && (WriteInt16((GInt16)(nX - m_nCenterX)) != 0 ||
     444                 :                          WriteInt16((GInt16)(nY - m_nCenterY)) != 0) ) )
     445                 :     {
     446               0 :         return -1;
     447                 :     }
     448                 : 
     449               2 :     return 0;
     450                 : }
     451                 : 
     452                 : /**********************************************************************
     453                 :  *                   TABMAPObjectBlock::WriteIntMBRCoord()
     454                 :  *
     455                 :  * Write 2 pairs of integer coordinates values to the current position 
     456                 :  * in the the block after making sure that min values are smaller than
     457                 :  * max values.  Use this function to write MBR coordinates for an object.
     458                 :  *
     459                 :  * If bCompr=TRUE then the coordinates are written relative to
     460                 :  * the object block center... otherwise they're written as 32 bits int.
     461                 :  *
     462                 :  * This function does not maintain the block's MBR and center... it is 
     463                 :  * assumed to have been set before the first call to WriteIntCoord()
     464                 :  *
     465                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     466                 :  * CPLError() will have been called.
     467                 :  **********************************************************************/
     468               0 : int     TABMAPObjectBlock::WriteIntMBRCoord(GInt32 nXMin, GInt32 nYMin,
     469                 :                                             GInt32 nXMax, GInt32 nYMax,
     470                 :                                             GBool bCompressed /*=FALSE*/)
     471                 : {
     472               0 :     if (WriteIntCoord(MIN(nXMin, nXMax), MIN(nYMin, nYMax),
     473                 :                       bCompressed) != 0 ||
     474                 :         WriteIntCoord(MAX(nXMin, nXMax), MAX(nYMin, nYMax), 
     475                 :                       bCompressed) != 0 )
     476                 :     {
     477               0 :         return -1;
     478                 :     }
     479                 : 
     480               0 :     return 0;
     481                 : }
     482                 : 
     483                 : 
     484                 : /**********************************************************************
     485                 :  *                   TABMAPObjectBlock::UpdateMBR()
     486                 :  *
     487                 :  * Update the block's MBR and center.
     488                 :  *
     489                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     490                 :  * CPLError() will have been called.
     491                 :  **********************************************************************/
     492              24 : int     TABMAPObjectBlock::UpdateMBR(GInt32 nX, GInt32 nY)
     493                 : {
     494                 : 
     495              24 :     if (nX < m_nMinX)
     496               5 :         m_nMinX = nX;
     497              24 :     if (nX > m_nMaxX)
     498               7 :         m_nMaxX = nX;
     499                 : 
     500              24 :     if (nY < m_nMinY)
     501               6 :         m_nMinY = nY;
     502              24 :     if (nY > m_nMaxY)
     503               5 :         m_nMaxY = nY;
     504                 :     
     505              24 :     m_nCenterX = (m_nMinX + m_nMaxX) /2;
     506              24 :     m_nCenterY = (m_nMinY + m_nMaxY) /2;
     507                 :     
     508              24 :     return 0;
     509                 : }
     510                 : 
     511                 : /**********************************************************************
     512                 :  *                   TABMAPObjectBlock::AddCoordBlockRef()
     513                 :  *
     514                 :  * Update the first/last coord block fields in this object to contain
     515                 :  * the specified block address.
     516                 :  **********************************************************************/
     517               4 : void     TABMAPObjectBlock::AddCoordBlockRef(GInt32 nNewBlockAddress)
     518                 : {
     519                 :     /*-----------------------------------------------------------------
     520                 :      * Normally, new blocks are added to the end of the list, except
     521                 :      * the first one which is the beginning and the end of the list at 
     522                 :      * the same time.
     523                 :      *----------------------------------------------------------------*/
     524               4 :     if (m_nFirstCoordBlock == 0)
     525               2 :         m_nFirstCoordBlock = nNewBlockAddress;
     526                 : 
     527               4 :     m_nLastCoordBlock = nNewBlockAddress;
     528               4 : }
     529                 : 
     530                 : /**********************************************************************
     531                 :  *                   TABMAPObjectBlock::SetMBR()
     532                 :  *
     533                 :  * Set the MBR for the current block.
     534                 :  **********************************************************************/
     535               0 : void TABMAPObjectBlock::SetMBR(GInt32 nXMin, GInt32 nYMin, 
     536                 :                                GInt32 nXMax, GInt32 nYMax)
     537                 : {
     538               0 :     m_nMinX = nXMin;
     539               0 :     m_nMinY = nYMin;
     540               0 :     m_nMaxX = nXMax;
     541               0 :     m_nMaxY = nYMax; 
     542                 : 
     543               0 :     m_nCenterX = (m_nMinX + m_nMaxX) /2;
     544               0 :     m_nCenterY = (m_nMinY + m_nMaxY) /2;
     545               0 : }
     546                 : 
     547                 : /**********************************************************************
     548                 :  *                   TABMAPObjectBlock::GetMBR()
     549                 :  *
     550                 :  * Return the MBR for the current block.
     551                 :  **********************************************************************/
     552               2 : void TABMAPObjectBlock::GetMBR(GInt32 &nXMin, GInt32 &nYMin, 
     553                 :                                GInt32 &nXMax, GInt32 &nYMax)
     554                 : {
     555               2 :     nXMin = m_nMinX;
     556               2 :     nYMin = m_nMinY;
     557               2 :     nXMax = m_nMaxX;
     558               2 :     nYMax = m_nMaxY; 
     559               2 : }
     560                 : 
     561                 : 
     562                 : /**********************************************************************
     563                 :  *                   TABMAPObjectBlock::PrepareNewObject()
     564                 :  *
     565                 :  * Prepare this block to receive this new object. We only reserve space for
     566                 :  * it in this call. Actual data will be written only when CommitNewObject()
     567                 :  * is called.
     568                 :  *
     569                 :  * Returns the position at which the new object starts
     570                 :  **********************************************************************/
     571              12 : int     TABMAPObjectBlock::PrepareNewObject(TABMAPObjHdr *poObjHdr)
     572                 : {
     573              12 :     int nStartAddress = 0;
     574                 : 
     575                 :     // Nothing to do for NONE objects
     576              12 :     if (poObjHdr->m_nType == TAB_GEOM_NONE)
     577                 :     {
     578               0 :         return 0;
     579                 :     }
     580                 : 
     581                 :     // Maintain MBR of this object block.
     582              12 :     UpdateMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY);
     583              12 :     UpdateMBR(poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
     584                 :    
     585                 :     /*-----------------------------------------------------------------
     586                 :      * Keep track of object type, ID and start address for use by
     587                 :      * CommitNewObject()
     588                 :      *----------------------------------------------------------------*/
     589              12 :     nStartAddress = GetFirstUnusedByteOffset();
     590              12 :     GotoByteInFile(nStartAddress);
     591              12 :     m_nCurObjectOffset = nStartAddress - GetStartAddress();
     592                 : 
     593              12 :     m_nCurObjectType = poObjHdr->m_nType;
     594              12 :     m_nCurObjectId   = poObjHdr->m_nId;
     595                 : 
     596              12 :     return nStartAddress;
     597                 : }
     598                 : 
     599                 : /**********************************************************************
     600                 :  *                   TABMAPObjectBlock::CommitCurObjData()
     601                 :  *
     602                 :  * Write the ObjHdr to this block. This is usually called after 
     603                 :  * PrepareNewObject() once all members of the ObjHdr have
     604                 :  * been set.
     605                 :  *
     606                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     607                 :  * CPLError() will have been called.
     608                 :  **********************************************************************/
     609              14 : int     TABMAPObjectBlock::CommitNewObject(TABMAPObjHdr *poObjHdr)
     610                 : {
     611              14 :     int nStatus = 0;
     612                 : 
     613                 :     // Nothing to do for NONE objects
     614              14 :     if (poObjHdr->m_nType == TAB_GEOM_NONE)
     615                 :     {
     616               2 :         return 0;
     617                 :     }
     618                 : 
     619              12 :     CPLAssert(m_nCurObjectId == poObjHdr->m_nId);
     620              12 :     GotoByteInBlock(m_nCurObjectOffset);
     621                 : 
     622              12 :     nStatus = poObjHdr->WriteObj(this);
     623                 : 
     624              12 :     if (nStatus == 0)
     625              12 :         m_numDataBytes = m_nSizeUsed - MAP_OBJECT_HEADER_SIZE;
     626                 : 
     627              12 :     return nStatus;
     628                 : }
     629                 : 
     630                 : /**********************************************************************
     631                 :  *                   TABMAPObjectBlock::Dump()
     632                 :  *
     633                 :  * Dump block contents... available only in DEBUG mode.
     634                 :  **********************************************************************/
     635                 : #ifdef DEBUG
     636                 : 
     637               0 : void TABMAPObjectBlock::Dump(FILE *fpOut, GBool bDetails)
     638                 : {
     639               0 :     CPLErrorReset();
     640                 : 
     641               0 :     if (fpOut == NULL)
     642               0 :         fpOut = stdout;
     643                 : 
     644               0 :     fprintf(fpOut, "----- TABMAPObjectBlock::Dump() -----\n");
     645               0 :     if (m_pabyBuf == NULL)
     646                 :     {
     647               0 :         fprintf(fpOut, "Block has not been initialized yet.");
     648                 :     }
     649                 :     else
     650                 :     {
     651                 :         fprintf(fpOut,"Object Data Block (type %d) at offset %d.\n", 
     652               0 :                                                 m_nBlockType, m_nFileOffset);
     653               0 :         fprintf(fpOut,"  m_numDataBytes        = %d\n", m_numDataBytes);
     654               0 :         fprintf(fpOut,"  m_nCenterX            = %d\n", m_nCenterX);
     655               0 :         fprintf(fpOut,"  m_nCenterY            = %d\n", m_nCenterY);
     656               0 :         fprintf(fpOut,"  m_nFirstCoordBlock    = %d\n", m_nFirstCoordBlock);
     657               0 :         fprintf(fpOut,"  m_nLastCoordBlock     = %d\n", m_nLastCoordBlock);
     658                 :     }
     659                 : 
     660               0 :     if (bDetails)
     661                 :     {
     662                 :         /* We need the mapfile's header block */
     663                 :         TABRawBinBlock *poBlock;
     664                 :         TABMAPHeaderBlock *poHeader;
     665                 :         TABMAPObjHdr *poObjHdr;
     666                 : 
     667               0 :         poBlock = TABCreateMAPBlockFromFile(m_fp, 0, 512);
     668               0 :         if (poBlock==NULL || poBlock->GetBlockClass() != TABMAP_HEADER_BLOCK)
     669                 :         {
     670                 :             CPLError(CE_Failure, CPLE_AssertionFailed, 
     671               0 :                      "Failed reading header block.");
     672               0 :             return;
     673                 :         }
     674               0 :         poHeader = (TABMAPHeaderBlock *)poBlock;
     675                 : 
     676               0 :         Rewind();
     677               0 :         while((poObjHdr = TABMAPObjHdr::ReadNextObj(this, poHeader)) != NULL)
     678                 :         {
     679                 :             fprintf(fpOut, 
     680                 :                     "   object id=%d, type=%d, offset=%d (%d), size=%d\n"
     681                 :                     "          MBR=(%d, %d, %d, %d)\n",
     682                 :                     m_nCurObjectId, m_nCurObjectType, m_nCurObjectOffset,
     683                 :                     m_nFileOffset + m_nCurObjectOffset,
     684                 :                     poHeader->GetMapObjectSize( m_nCurObjectType ),
     685                 :                     poObjHdr->m_nMinX, poObjHdr->m_nMinY,
     686               0 :                     poObjHdr->m_nMaxX,poObjHdr->m_nMaxY);
     687               0 :             delete poObjHdr;
     688                 :         }
     689                 : 
     690               0 :         delete poHeader;
     691                 :     }
     692                 : 
     693               0 :     fflush(fpOut);
     694                 : }
     695                 : 
     696                 : #endif // DEBUG
     697                 : 
     698                 : 
     699                 : 
     700                 : /*=====================================================================
     701                 :  *                      class TABMAPObjHdr and family
     702                 :  *====================================================================*/
     703                 : 
     704                 : /**********************************************************************
     705                 :  *                   class TABMAPObjHdr
     706                 :  *
     707                 :  * Virtual base class... contains static methods used to allocate instance
     708                 :  * of the derived classes.
     709                 :  *
     710                 :  **********************************************************************/
     711                 : 
     712                 : 
     713                 : /**********************************************************************
     714                 :  *                    TABMAPObjHdr::NewObj()
     715                 :  *
     716                 :  * Alloc a new object of specified type or NULL for NONE types or if type 
     717                 :  * is not supported.
     718                 :  **********************************************************************/
     719              67 : TABMAPObjHdr *TABMAPObjHdr::NewObj(GByte nNewObjType, GInt32 nId /*=0*/)
     720                 : {
     721              67 :     TABMAPObjHdr *poObj = NULL;
     722                 : 
     723              67 :     switch(nNewObjType)
     724                 :     {
     725                 :       case TAB_GEOM_NONE:
     726               3 :         poObj = new TABMAPObjNone;
     727               3 :         break;
     728                 :       case TAB_GEOM_SYMBOL_C:
     729                 :       case TAB_GEOM_SYMBOL:
     730               0 :         poObj = new TABMAPObjPoint;
     731               0 :         break;
     732                 :       case TAB_GEOM_FONTSYMBOL_C:
     733                 :       case TAB_GEOM_FONTSYMBOL:
     734               0 :         poObj = new TABMAPObjFontPoint;
     735               0 :         break;
     736                 :       case TAB_GEOM_CUSTOMSYMBOL_C:
     737                 :       case TAB_GEOM_CUSTOMSYMBOL:
     738               0 :         poObj = new TABMAPObjCustomPoint;
     739               0 :         break;
     740                 :       case TAB_GEOM_LINE_C:
     741                 :       case TAB_GEOM_LINE:
     742               2 :         poObj = new TABMAPObjLine;
     743               2 :         break;
     744                 :       case TAB_GEOM_PLINE_C:
     745                 :       case TAB_GEOM_PLINE:
     746                 :       case TAB_GEOM_REGION_C:
     747                 :       case TAB_GEOM_REGION:
     748                 :       case TAB_GEOM_MULTIPLINE_C:
     749                 :       case TAB_GEOM_MULTIPLINE:
     750                 :       case TAB_GEOM_V450_REGION_C:
     751                 :       case TAB_GEOM_V450_REGION:
     752                 :       case TAB_GEOM_V450_MULTIPLINE_C:
     753                 :       case TAB_GEOM_V450_MULTIPLINE:
     754                 :       case TAB_GEOM_V800_REGION_C:
     755                 :       case TAB_GEOM_V800_REGION:
     756                 :       case TAB_GEOM_V800_MULTIPLINE_C:
     757                 :       case TAB_GEOM_V800_MULTIPLINE:
     758              62 :         poObj = new TABMAPObjPLine;
     759              62 :         break;
     760                 :       case TAB_GEOM_ARC_C:
     761                 :       case TAB_GEOM_ARC:
     762               0 :         poObj = new TABMAPObjArc;
     763               0 :         break;
     764                 :       case TAB_GEOM_RECT_C:
     765                 :       case TAB_GEOM_RECT:
     766                 :       case TAB_GEOM_ROUNDRECT_C:
     767                 :       case TAB_GEOM_ROUNDRECT:
     768                 :       case TAB_GEOM_ELLIPSE_C:
     769                 :       case TAB_GEOM_ELLIPSE:
     770               0 :         poObj = new TABMAPObjRectEllipse;
     771               0 :         break;
     772                 :       case TAB_GEOM_TEXT_C:
     773                 :       case TAB_GEOM_TEXT:
     774               0 :         poObj = new TABMAPObjText;
     775               0 :         break;
     776                 :       case TAB_GEOM_MULTIPOINT_C:
     777                 :       case TAB_GEOM_MULTIPOINT:
     778                 :       case TAB_GEOM_V800_MULTIPOINT_C:
     779                 :       case TAB_GEOM_V800_MULTIPOINT:
     780               0 :         poObj = new TABMAPObjMultiPoint;
     781               0 :         break;
     782                 :       case TAB_GEOM_COLLECTION_C:
     783                 :       case TAB_GEOM_COLLECTION:
     784                 :       case TAB_GEOM_V800_COLLECTION_C:
     785                 :       case TAB_GEOM_V800_COLLECTION:
     786               0 :         poObj = new TABMAPObjCollection();
     787               0 :     break;
     788                 :       default:
     789                 :         CPLError(CE_Failure, CPLE_AssertionFailed, 
     790                 :                  "TABMAPObjHdr::NewObj(): Unsupported object type %d",
     791               0 :                  nNewObjType);
     792                 :     }
     793                 : 
     794              67 :     if (poObj)
     795                 :     {
     796              67 :         poObj->m_nType = nNewObjType;
     797              67 :         poObj->m_nId = nId;
     798              67 :         poObj->m_nMinX = poObj->m_nMinY = poObj->m_nMaxX = poObj->m_nMaxY = 0;
     799                 :     }
     800                 : 
     801              67 :     return poObj;
     802                 : }
     803                 : 
     804                 : 
     805                 : /**********************************************************************
     806                 :  *                    TABMAPObjHdr::ReadNextObj()
     807                 :  *
     808                 :  * Read next object in this block and allocate/init a new object for it
     809                 :  * if succesful.  
     810                 :  * Returns NULL in case of error or if we reached end of block.
     811                 :  **********************************************************************/
     812               0 : TABMAPObjHdr *TABMAPObjHdr::ReadNextObj(TABMAPObjectBlock *poObjBlock,
     813                 :                                         TABMAPHeaderBlock *poHeader)
     814                 : {
     815               0 :     TABMAPObjHdr *poObjHdr = NULL;
     816                 : 
     817               0 :     if (poObjBlock->AdvanceToNextObject(poHeader) != -1)
     818                 :     {
     819               0 :         poObjHdr=TABMAPObjHdr::NewObj((GByte)poObjBlock->GetCurObjectType());
     820               0 :         if (poObjHdr &&
     821                 :             ((poObjHdr->m_nId = poObjBlock->GetCurObjectId()) == -1 ||
     822               0 :              poObjHdr->ReadObj(poObjBlock) != 0 ) )
     823                 :         {
     824                 :             // Failed reading object in block... an error was already produced
     825               0 :             delete poObjHdr;
     826               0 :             return NULL;
     827                 :         }
     828                 :     }
     829                 : 
     830               0 :     return poObjHdr;
     831                 : }
     832                 : 
     833                 : /**********************************************************************
     834                 :  *                    TABMAPObjHdr::IsCompressedType()
     835                 :  *
     836                 :  * Returns TRUE if the current object type uses compressed coordinates
     837                 :  * or FALSE otherwise.
     838                 :  **********************************************************************/
     839             191 : GBool TABMAPObjHdr::IsCompressedType()
     840                 : {
     841                 :     // Compressed types are 1, 4, 7, etc.
     842             191 :     return ((m_nType % 3) == 1 ? TRUE : FALSE);
     843                 : }
     844                 : 
     845                 : /**********************************************************************
     846                 :  *                   TABMAPObjHdr::WriteObjTypeAndId()
     847                 :  *
     848                 :  * Writetype+object id information... should be called only by the derived
     849                 :  * classes' WriteObj() methods.
     850                 :  *
     851                 :  * Returns 0 on success, -1 on error.
     852                 :  **********************************************************************/
     853              12 : int TABMAPObjHdr::WriteObjTypeAndId(TABMAPObjectBlock *poObjBlock)
     854                 : {
     855              12 :     poObjBlock->WriteByte(m_nType);
     856              12 :     return poObjBlock->WriteInt32(m_nId);
     857                 : }
     858                 : 
     859                 : /**********************************************************************
     860                 :  *                   TABMAPObjHdr::SetMBR()
     861                 :  *
     862                 :  **********************************************************************/
     863              13 : void TABMAPObjHdr::SetMBR(GInt32 nMinX, GInt32 nMinY, 
     864                 :                           GInt32 nMaxX, GInt32 nMaxY)
     865                 : {
     866              13 :     m_nMinX = MIN(nMinX, nMaxX);
     867              13 :     m_nMinY = MIN(nMinY, nMaxY);
     868              13 :     m_nMaxX = MAX(nMinX, nMaxX);
     869              13 :     m_nMaxY = MAX(nMinY, nMaxY);
     870              13 : }
     871                 : 
     872                 : 
     873                 : /**********************************************************************
     874                 :  *                   class TABMAPObjLine
     875                 :  *
     876                 :  * Applies to 2-points LINEs only
     877                 :  **********************************************************************/
     878                 : 
     879                 : /**********************************************************************
     880                 :  *                   TABMAPObjLine::ReadObj()
     881                 :  *
     882                 :  * Read Object information starting after the object id which should 
     883                 :  * have been read by TABMAPObjHdr::ReadNextObj() already.
     884                 :  * This function should be called only by TABMAPObjHdr::ReadNextObj().
     885                 :  *
     886                 :  * Returns 0 on success, -1 on error.
     887                 :  **********************************************************************/
     888               1 : int TABMAPObjLine::ReadObj(TABMAPObjectBlock *poObjBlock)
     889                 : {
     890               1 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nX1, m_nY1);
     891               1 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nX2, m_nY2);
     892                 : 
     893               1 :     m_nPenId = poObjBlock->ReadByte();      // Pen index
     894                 : 
     895               1 :     SetMBR(m_nX1, m_nY1, m_nX2, m_nY2);
     896                 : 
     897               1 :     if (CPLGetLastErrorNo() != 0)
     898               0 :         return -1;
     899                 : 
     900               1 :     return 0;
     901                 : }
     902                 : 
     903                 : /**********************************************************************
     904                 :  *                   TABMAPObjLine::WriteObj()
     905                 :  *
     906                 :  * Write Object information with the type+object id
     907                 :  *
     908                 :  * Returns 0 on success, -1 on error.
     909                 :  **********************************************************************/
     910               1 : int TABMAPObjLine::WriteObj(TABMAPObjectBlock *poObjBlock)
     911                 : {
     912                 :     // Write object type and id
     913               1 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
     914                 : 
     915               1 :     poObjBlock->WriteIntCoord(m_nX1, m_nY1, IsCompressedType());
     916               1 :     poObjBlock->WriteIntCoord(m_nX2, m_nY2, IsCompressedType());
     917                 : 
     918               1 :     poObjBlock->WriteByte(m_nPenId);      // Pen index
     919                 : 
     920               1 :     if (CPLGetLastErrorNo() != 0)
     921               0 :         return -1;
     922                 : 
     923               1 :     return 0;
     924                 : }
     925                 : 
     926                 : /**********************************************************************
     927                 :  *                   class TABMAPObjPLine
     928                 :  *
     929                 :  * Applies to PLINE, MULTIPLINE and REGION object types
     930                 :  **********************************************************************/
     931                 : 
     932                 : /**********************************************************************
     933                 :  *                   TABMAPObjPLine::ReadObj()
     934                 :  *
     935                 :  * Read Object information starting after the object id which should 
     936                 :  * have been read by TABMAPObjHdr::ReadNextObj() already.
     937                 :  * This function should be called only by TABMAPObjHdr::ReadNextObj().
     938                 :  *
     939                 :  * Returns 0 on success, -1 on error.
     940                 :  **********************************************************************/
     941              51 : int TABMAPObjPLine::ReadObj(TABMAPObjectBlock *poObjBlock)
     942                 : {
     943              51 :     m_nCoordBlockPtr = poObjBlock->ReadInt32();
     944              51 :     m_nCoordDataSize = poObjBlock->ReadInt32();
     945                 : 
     946              51 :     if (m_nCoordDataSize & 0x80000000)
     947                 :     {
     948               0 :         m_bSmooth = TRUE;
     949               0 :         m_nCoordDataSize &= 0x7FFFFFFF; //Take smooth flag out of the value
     950                 :     }
     951                 :     else
     952                 :     {
     953              51 :         m_bSmooth = FALSE;
     954                 :     }
     955                 : 
     956                 : #ifdef TABDUMP
     957                 :     printf("TABMAPObjPLine::ReadObj: m_nCoordDataSize = %d @ %d\n", 
     958                 :            m_nCoordDataSize, m_nCoordBlockPtr);
     959                 : #endif
     960                 : 
     961                 :     // Number of line segments applies only to MULTIPLINE/REGION but not PLINE
     962              51 :     if (m_nType == TAB_GEOM_PLINE_C ||
     963                 :         m_nType == TAB_GEOM_PLINE )
     964                 :     {
     965               0 :         m_numLineSections = 1;
     966                 :     }
     967              51 :     else if (m_nType == TAB_GEOM_V800_REGION ||
     968                 :              m_nType == TAB_GEOM_V800_REGION_C ||
     969                 :              m_nType == TAB_GEOM_V800_MULTIPLINE ||
     970                 :              m_nType == TAB_GEOM_V800_MULTIPLINE_C )
     971                 :     {
     972                 :         /* V800 REGIONS/MULTIPLINES use an int32 */
     973               0 :         m_numLineSections = poObjBlock->ReadInt32();
     974                 :         /* ... followed by 33 unknown bytes */
     975               0 :         poObjBlock->ReadInt32();
     976               0 :         poObjBlock->ReadInt32();
     977               0 :         poObjBlock->ReadInt32();
     978               0 :         poObjBlock->ReadInt32();
     979               0 :         poObjBlock->ReadInt32();
     980               0 :         poObjBlock->ReadInt32();
     981               0 :         poObjBlock->ReadInt32();
     982               0 :         poObjBlock->ReadInt32();
     983               0 :         poObjBlock->ReadByte();
     984                 :     }
     985                 :     else
     986                 :     {
     987                 :         /* V300 and V450 REGIONS/MULTIPLINES use an int16 */
     988              51 :         m_numLineSections = poObjBlock->ReadInt16();
     989                 :     }
     990                 : 
     991                 : #ifdef TABDUMP
     992                 :     printf("PLINE/REGION: id=%d, type=%d, "
     993                 :            "CoordBlockPtr=%d, CoordDataSize=%d, numLineSect=%d, bSmooth=%d\n",
     994                 :            m_nId, m_nType, m_nCoordBlockPtr, m_nCoordDataSize, 
     995                 :            m_numLineSections, m_bSmooth);
     996                 : #endif
     997                 : 
     998              51 :     if (IsCompressedType())
     999                 :     {
    1000                 :         // Region center/label point, relative to compr. coord. origin
    1001                 :         // No it's not relative to the Object block center
    1002              46 :         m_nLabelX = poObjBlock->ReadInt16();
    1003              46 :         m_nLabelY = poObjBlock->ReadInt16();
    1004                 : 
    1005                 :         // Compressed coordinate origin (present only in compressed case!)
    1006              46 :         m_nComprOrgX = poObjBlock->ReadInt32();
    1007              46 :         m_nComprOrgY = poObjBlock->ReadInt32();
    1008                 : 
    1009              46 :         m_nLabelX += m_nComprOrgX;
    1010              46 :         m_nLabelY += m_nComprOrgY;
    1011                 : 
    1012              46 :         m_nMinX = m_nComprOrgX + poObjBlock->ReadInt16();  // Read MBR
    1013              46 :         m_nMinY = m_nComprOrgY + poObjBlock->ReadInt16();
    1014              46 :         m_nMaxX = m_nComprOrgX + poObjBlock->ReadInt16();
    1015              46 :         m_nMaxY = m_nComprOrgY + poObjBlock->ReadInt16();
    1016                 :     }
    1017                 :     else
    1018                 :     {
    1019                 :         // Region center/label point, relative to compr. coord. origin
    1020                 :         // No it's not relative to the Object block center
    1021               5 :         m_nLabelX = poObjBlock->ReadInt32();
    1022               5 :         m_nLabelY = poObjBlock->ReadInt32();
    1023                 : 
    1024               5 :         m_nMinX = poObjBlock->ReadInt32();    // Read MBR
    1025               5 :         m_nMinY = poObjBlock->ReadInt32();
    1026               5 :         m_nMaxX = poObjBlock->ReadInt32();
    1027               5 :         m_nMaxY = poObjBlock->ReadInt32();
    1028                 :     }
    1029                 : 
    1030                 : 
    1031              51 :     if ( ! IsCompressedType() )
    1032                 :     {
    1033                 :         // Init. Compr. Origin to a default value in case type is ever changed
    1034               5 :         m_nComprOrgX = (m_nMinX + m_nMaxX) / 2;
    1035               5 :         m_nComprOrgY = (m_nMinY + m_nMaxY) / 2;
    1036                 :     }
    1037                 : 
    1038              51 :     m_nPenId = poObjBlock->ReadByte();      // Pen index
    1039                 : 
    1040             102 :     if (m_nType == TAB_GEOM_REGION ||
    1041                 :         m_nType == TAB_GEOM_REGION_C ||
    1042                 :         m_nType == TAB_GEOM_V450_REGION ||
    1043                 :         m_nType == TAB_GEOM_V450_REGION_C ||
    1044                 :         m_nType == TAB_GEOM_V800_REGION ||
    1045                 :         m_nType == TAB_GEOM_V800_REGION_C )
    1046                 :     {
    1047              51 :         m_nBrushId = poObjBlock->ReadByte();    // Brush index... REGION only
    1048                 :     }
    1049                 :     else
    1050                 :     {
    1051               0 :         m_nBrushId = 0;
    1052                 :     }
    1053                 : 
    1054              51 :     if (CPLGetLastErrorNo() != 0)
    1055               0 :         return -1;
    1056                 : 
    1057              51 :     return 0;
    1058                 : }
    1059                 : 
    1060                 : 
    1061                 : /**********************************************************************
    1062                 :  *                   TABMAPObjPLine::WriteObj()
    1063                 :  *
    1064                 :  * Write Object information with the type+object id
    1065                 :  *
    1066                 :  * Returns 0 on success, -1 on error.
    1067                 :  **********************************************************************/
    1068              11 : int TABMAPObjPLine::WriteObj(TABMAPObjectBlock *poObjBlock)
    1069                 : {
    1070                 :     // Write object type and id
    1071              11 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
    1072                 : 
    1073              11 :     poObjBlock->WriteInt32(m_nCoordBlockPtr);
    1074                 : 
    1075                 :     // Combine smooth flag in the coord data size.
    1076              11 :     if (m_bSmooth)
    1077               0 :         poObjBlock->WriteInt32( m_nCoordDataSize | 0x80000000 );
    1078                 :     else
    1079              11 :         poObjBlock->WriteInt32( m_nCoordDataSize );
    1080                 : 
    1081                 :     // Number of line segments applies only to MULTIPLINE/REGION but not PLINE
    1082              11 :     if (m_nType == TAB_GEOM_V800_REGION ||
    1083                 :         m_nType == TAB_GEOM_V800_REGION_C ||
    1084                 :         m_nType == TAB_GEOM_V800_MULTIPLINE ||
    1085                 :         m_nType == TAB_GEOM_V800_MULTIPLINE_C )
    1086                 :     {
    1087                 :         /* V800 REGIONS/MULTIPLINES use an int32 */
    1088               0 :         poObjBlock->WriteInt32(m_numLineSections);
    1089                 :         /* ... followed by 33 unknown bytes */
    1090               0 :         poObjBlock->WriteZeros(33);
    1091                 :     }
    1092              11 :     else if (m_nType != TAB_GEOM_PLINE_C &&
    1093                 :              m_nType != TAB_GEOM_PLINE )
    1094                 :     {
    1095                 :         /* V300 and V450 REGIONS/MULTIPLINES use an int16 */
    1096              11 :         poObjBlock->WriteInt16((GInt16)m_numLineSections);
    1097                 :     }
    1098                 : 
    1099              11 :     if (IsCompressedType())
    1100                 :     {
    1101                 :         // Region center/label point, relative to compr. coord. origin
    1102                 :         // No it's not relative to the Object block center
    1103              10 :         poObjBlock->WriteInt16((GInt16)(m_nLabelX - m_nComprOrgX));
    1104              10 :         poObjBlock->WriteInt16((GInt16)(m_nLabelY - m_nComprOrgY));
    1105                 : 
    1106                 :         // Compressed coordinate origin (present only in compressed case!)
    1107              10 :         poObjBlock->WriteInt32(m_nComprOrgX);
    1108              10 :         poObjBlock->WriteInt32(m_nComprOrgY);
    1109                 :     }
    1110                 :     else
    1111                 :     {
    1112                 :         // Region center/label point
    1113               1 :         poObjBlock->WriteInt32(m_nLabelX);
    1114               1 :         poObjBlock->WriteInt32(m_nLabelY);
    1115                 :     }
    1116                 : 
    1117                 :     // MBR
    1118              11 :     if (IsCompressedType())
    1119                 :     {
    1120                 :         // MBR relative to PLINE origin (and not object block center)
    1121              10 :         poObjBlock->WriteInt16((GInt16)(m_nMinX - m_nComprOrgX));
    1122              10 :         poObjBlock->WriteInt16((GInt16)(m_nMinY - m_nComprOrgY));
    1123              10 :         poObjBlock->WriteInt16((GInt16)(m_nMaxX - m_nComprOrgX));
    1124              10 :         poObjBlock->WriteInt16((GInt16)(m_nMaxY - m_nComprOrgY));
    1125                 :     }
    1126                 :     else
    1127                 :     {
    1128               1 :         poObjBlock->WriteInt32(m_nMinX);
    1129               1 :         poObjBlock->WriteInt32(m_nMinY);
    1130               1 :         poObjBlock->WriteInt32(m_nMaxX);
    1131               1 :         poObjBlock->WriteInt32(m_nMaxY);
    1132                 :     }
    1133                 : 
    1134              11 :     poObjBlock->WriteByte(m_nPenId);      // Pen index
    1135                 : 
    1136              11 :     if (m_nType == TAB_GEOM_REGION ||
    1137                 :         m_nType == TAB_GEOM_REGION_C ||
    1138                 :         m_nType == TAB_GEOM_V450_REGION ||
    1139                 :         m_nType == TAB_GEOM_V450_REGION_C ||
    1140                 :         m_nType == TAB_GEOM_V800_REGION ||
    1141                 :         m_nType == TAB_GEOM_V800_REGION_C )
    1142                 :     {
    1143              11 :         poObjBlock->WriteByte(m_nBrushId);    // Brush index... REGION only
    1144                 :     }
    1145                 : 
    1146              11 :     if (CPLGetLastErrorNo() != 0)
    1147               0 :         return -1;
    1148                 : 
    1149              11 :     return 0;
    1150                 : }
    1151                 : 
    1152                 : 
    1153                 : /**********************************************************************
    1154                 :  *                   class TABMAPObjPoint
    1155                 :  *
    1156                 :  **********************************************************************/
    1157                 : 
    1158                 : /**********************************************************************
    1159                 :  *                   TABMAPObjPoint::ReadObj()
    1160                 :  *
    1161                 :  * Read Object information starting after the object id
    1162                 :  **********************************************************************/
    1163               0 : int TABMAPObjPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
    1164                 : {
    1165               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nX, m_nY);
    1166                 : 
    1167               0 :     m_nSymbolId = poObjBlock->ReadByte();      // Symbol index
    1168                 : 
    1169               0 :     SetMBR(m_nX, m_nY, m_nX, m_nY);
    1170                 : 
    1171               0 :     if (CPLGetLastErrorNo() != 0)
    1172               0 :         return -1;
    1173                 : 
    1174               0 :     return 0;
    1175                 : }
    1176                 : 
    1177                 : /**********************************************************************
    1178                 :  *                   TABMAPObjPoint::WriteObj()
    1179                 :  *
    1180                 :  * Write Object information with the type+object id
    1181                 :  *
    1182                 :  * Returns 0 on success, -1 on error.
    1183                 :  **********************************************************************/
    1184               0 : int TABMAPObjPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
    1185                 : {
    1186                 :     // Write object type and id
    1187               0 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
    1188                 : 
    1189               0 :     poObjBlock->WriteIntCoord(m_nX, m_nY, IsCompressedType());
    1190                 : 
    1191               0 :     poObjBlock->WriteByte(m_nSymbolId);      // Symbol index
    1192                 : 
    1193               0 :     if (CPLGetLastErrorNo() != 0)
    1194               0 :         return -1;
    1195                 : 
    1196               0 :     return 0;
    1197                 : }
    1198                 : 
    1199                 : 
    1200                 : /**********************************************************************
    1201                 :  *                   class TABMAPObjFontPoint
    1202                 :  *
    1203                 :  **********************************************************************/
    1204                 : 
    1205                 : /**********************************************************************
    1206                 :  *                   TABMAPObjFontPoint::ReadObj()
    1207                 :  *
    1208                 :  * Read Object information starting after the object id
    1209                 :  **********************************************************************/
    1210               0 : int TABMAPObjFontPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
    1211                 : {
    1212               0 :     m_nSymbolId  = poObjBlock->ReadByte();      // Symbol index
    1213               0 :     m_nPointSize = poObjBlock->ReadByte();
    1214               0 :     m_nFontStyle = poObjBlock->ReadInt16();     // font style
    1215                 : 
    1216               0 :     m_nR = poObjBlock->ReadByte();
    1217               0 :     m_nG = poObjBlock->ReadByte();
    1218               0 :     m_nB = poObjBlock->ReadByte();
    1219                 : 
    1220               0 :     poObjBlock->ReadByte();         // ??? BG Color ???
    1221               0 :     poObjBlock->ReadByte();         // ???
    1222               0 :     poObjBlock->ReadByte();         // ???
    1223                 : 
    1224               0 :     m_nAngle = poObjBlock->ReadInt16();
    1225                 : 
    1226               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nX, m_nY);
    1227                 : 
    1228               0 :     m_nFontId  = poObjBlock->ReadByte();      // Font name index
    1229                 : 
    1230               0 :     SetMBR(m_nX, m_nY, m_nX, m_nY);
    1231                 : 
    1232               0 :     if (CPLGetLastErrorNo() != 0)
    1233               0 :         return -1;
    1234                 : 
    1235               0 :     return 0;
    1236                 : }
    1237                 : 
    1238                 : /**********************************************************************
    1239                 :  *                   TABMAPObjFontPoint::WriteObj()
    1240                 :  *
    1241                 :  * Write Object information with the type+object id
    1242                 :  *
    1243                 :  * Returns 0 on success, -1 on error.
    1244                 :  **********************************************************************/
    1245               0 : int TABMAPObjFontPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
    1246                 : {
    1247                 :     // Write object type and id
    1248               0 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
    1249                 : 
    1250               0 :     poObjBlock->WriteByte(m_nSymbolId);   // symbol shape
    1251               0 :     poObjBlock->WriteByte(m_nPointSize);
    1252               0 :     poObjBlock->WriteInt16(m_nFontStyle);            // font style
    1253                 : 
    1254               0 :     poObjBlock->WriteByte( m_nR );
    1255               0 :     poObjBlock->WriteByte( m_nG );
    1256               0 :     poObjBlock->WriteByte( m_nB );
    1257                 : 
    1258               0 :     poObjBlock->WriteByte( 0 );
    1259               0 :     poObjBlock->WriteByte( 0 );
    1260               0 :     poObjBlock->WriteByte( 0 );
    1261                 :     
    1262               0 :     poObjBlock->WriteInt16(m_nAngle);
    1263                 : 
    1264               0 :     poObjBlock->WriteIntCoord(m_nX, m_nY, IsCompressedType());
    1265                 : 
    1266               0 :     poObjBlock->WriteByte(m_nFontId);      // Font name index
    1267                 : 
    1268               0 :     if (CPLGetLastErrorNo() != 0)
    1269               0 :         return -1;
    1270                 : 
    1271               0 :     return 0;
    1272                 : }
    1273                 : 
    1274                 : 
    1275                 : /**********************************************************************
    1276                 :  *                   class TABMAPObjCustomPoint
    1277                 :  *
    1278                 :  **********************************************************************/
    1279                 : 
    1280                 : /**********************************************************************
    1281                 :  *                   TABMAPObjCustomPoint::ReadObj()
    1282                 :  *
    1283                 :  * Read Object information starting after the object id
    1284                 :  **********************************************************************/
    1285               0 : int TABMAPObjCustomPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
    1286                 : {
    1287               0 :     m_nUnknown_ = poObjBlock->ReadByte();       // ??? 
    1288               0 :     m_nCustomStyle = poObjBlock->ReadByte(); // 0x01=Show BG, 0x02=Apply Color
    1289                 : 
    1290               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nX, m_nY);
    1291                 : 
    1292               0 :     m_nSymbolId = poObjBlock->ReadByte();      // Symbol index
    1293               0 :     m_nFontId   = poObjBlock->ReadByte();      // Font index
    1294                 : 
    1295               0 :     SetMBR(m_nX, m_nY, m_nX, m_nY);
    1296                 : 
    1297               0 :     if (CPLGetLastErrorNo() != 0)
    1298               0 :         return -1;
    1299                 : 
    1300               0 :     return 0;
    1301                 : }
    1302                 : 
    1303                 : /**********************************************************************
    1304                 :  *                   TABMAPObjCustomPoint::WriteObj()
    1305                 :  *
    1306                 :  * Write Object information with the type+object id
    1307                 :  *
    1308                 :  * Returns 0 on success, -1 on error.
    1309                 :  **********************************************************************/
    1310               0 : int TABMAPObjCustomPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
    1311                 : {
    1312                 :     // Write object type and id
    1313               0 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
    1314                 : 
    1315               0 :     poObjBlock->WriteByte(m_nUnknown_);  // ??? 
    1316               0 :     poObjBlock->WriteByte(m_nCustomStyle); // 0x01=Show BG, 0x02=Apply Color
    1317               0 :     poObjBlock->WriteIntCoord(m_nX, m_nY, IsCompressedType());
    1318                 : 
    1319               0 :     poObjBlock->WriteByte(m_nSymbolId);      // Symbol index
    1320               0 :     poObjBlock->WriteByte(m_nFontId);      // Font index
    1321                 : 
    1322               0 :   if (CPLGetLastErrorNo() != 0)
    1323               0 :         return -1;
    1324                 : 
    1325               0 :     return 0;
    1326                 : }
    1327                 : 
    1328                 : /**********************************************************************
    1329                 :  *                   class TABMAPObjRectEllipse
    1330                 :  *
    1331                 :  **********************************************************************/
    1332                 : 
    1333                 : /**********************************************************************
    1334                 :  *                   TABMAPObjRectEllipse::ReadObj()
    1335                 :  *
    1336                 :  * Read Object information starting after the object id
    1337                 :  **********************************************************************/
    1338               0 : int TABMAPObjRectEllipse::ReadObj(TABMAPObjectBlock *poObjBlock)
    1339                 : {
    1340               0 :     if (m_nType == TAB_GEOM_ROUNDRECT || 
    1341                 :         m_nType == TAB_GEOM_ROUNDRECT_C)
    1342                 :     {
    1343               0 :         if (IsCompressedType())
    1344                 :         {
    1345               0 :             m_nCornerWidth  = poObjBlock->ReadInt16();
    1346               0 :             m_nCornerHeight = poObjBlock->ReadInt16();
    1347                 :         }
    1348                 :         else
    1349                 :         {
    1350               0 :             m_nCornerWidth  = poObjBlock->ReadInt32();
    1351               0 :             m_nCornerHeight = poObjBlock->ReadInt32();
    1352                 :         }
    1353                 :     }
    1354                 : 
    1355               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nMinX, m_nMinY);
    1356               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nMaxX, m_nMaxY);
    1357                 : 
    1358               0 :     m_nPenId    = poObjBlock->ReadByte();      // Pen index
    1359               0 :     m_nBrushId  = poObjBlock->ReadByte();      // Brush index
    1360                 : 
    1361               0 :     if (CPLGetLastErrorNo() != 0)
    1362               0 :         return -1;
    1363                 : 
    1364               0 :     return 0;
    1365                 : }
    1366                 : 
    1367                 : /**********************************************************************
    1368                 :  *                   TABMAPObjRectEllipse::WriteObj()
    1369                 :  *
    1370                 :  * Write Object information with the type+object id
    1371                 :  *
    1372                 :  * Returns 0 on success, -1 on error.
    1373                 :  **********************************************************************/
    1374               0 : int TABMAPObjRectEllipse::WriteObj(TABMAPObjectBlock *poObjBlock)
    1375                 : {
    1376                 :     // Write object type and id
    1377               0 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
    1378                 : 
    1379               0 :     if (m_nType == TAB_GEOM_ROUNDRECT || 
    1380                 :         m_nType == TAB_GEOM_ROUNDRECT_C)
    1381                 :     {
    1382               0 :         if (IsCompressedType())
    1383                 :         {
    1384               0 :             poObjBlock->WriteInt16((GInt16)m_nCornerWidth);
    1385               0 :             poObjBlock->WriteInt16((GInt16)m_nCornerHeight);
    1386                 :         }
    1387                 :         else
    1388                 :         {
    1389               0 :             poObjBlock->WriteInt32(m_nCornerWidth);
    1390               0 :             poObjBlock->WriteInt32(m_nCornerHeight);
    1391                 :         }
    1392                 :     }
    1393                 : 
    1394                 :     poObjBlock->WriteIntMBRCoord(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY, 
    1395               0 :                                  IsCompressedType());
    1396                 : 
    1397               0 :     poObjBlock->WriteByte(m_nPenId);      // Pen index
    1398               0 :     poObjBlock->WriteByte(m_nBrushId);      // Brush index
    1399                 : 
    1400               0 :     if (CPLGetLastErrorNo() != 0)
    1401               0 :         return -1;
    1402                 : 
    1403               0 :     return 0;
    1404                 : }
    1405                 : 
    1406                 : 
    1407                 : /**********************************************************************
    1408                 :  *                   class TABMAPObjArc
    1409                 :  *
    1410                 :  **********************************************************************/
    1411                 : 
    1412                 : /**********************************************************************
    1413                 :  *                   TABMAPObjArc::ReadObj()
    1414                 :  *
    1415                 :  * Read Object information starting after the object id
    1416                 :  **********************************************************************/
    1417               0 : int TABMAPObjArc::ReadObj(TABMAPObjectBlock *poObjBlock)
    1418                 : {
    1419               0 :     m_nStartAngle = poObjBlock->ReadInt16();
    1420               0 :     m_nEndAngle   = poObjBlock->ReadInt16();
    1421                 : 
    1422                 :     // An arc is defined by its defining ellipse's MBR:
    1423                 :     poObjBlock->ReadIntCoord(IsCompressedType(), 
    1424               0 :                              m_nArcEllipseMinX, m_nArcEllipseMinY);
    1425                 :     poObjBlock->ReadIntCoord(IsCompressedType(), 
    1426               0 :                              m_nArcEllipseMaxX, m_nArcEllipseMaxY);
    1427                 : 
    1428                 :     // Read the Arc's actual MBR
    1429               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nMinX, m_nMinY);
    1430               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nMaxX, m_nMaxY);
    1431                 : 
    1432               0 :     m_nPenId = poObjBlock->ReadByte();      // Pen index
    1433                 : 
    1434               0 :     if (CPLGetLastErrorNo() != 0)
    1435               0 :         return -1;
    1436                 : 
    1437               0 :     return 0;
    1438                 : }
    1439                 : 
    1440                 : /**********************************************************************
    1441                 :  *                   TABMAPObjArc::WriteObj()
    1442                 :  *
    1443                 :  * Write Object information with the type+object id
    1444                 :  *
    1445                 :  * Returns 0 on success, -1 on error.
    1446                 :  **********************************************************************/
    1447               0 : int TABMAPObjArc::WriteObj(TABMAPObjectBlock *poObjBlock)
    1448                 : {
    1449                 :     // Write object type and id
    1450               0 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
    1451                 : 
    1452               0 :     poObjBlock->WriteInt16((GInt16)m_nStartAngle);
    1453               0 :     poObjBlock->WriteInt16((GInt16)m_nEndAngle);
    1454                 :     
    1455                 :     // An arc is defined by its defining ellipse's MBR:
    1456                 :     poObjBlock->WriteIntMBRCoord(m_nArcEllipseMinX, m_nArcEllipseMinY, 
    1457                 :                                  m_nArcEllipseMaxX, m_nArcEllipseMaxY, 
    1458               0 :                                  IsCompressedType());
    1459                 : 
    1460                 :     // Write the Arc's actual MBR
    1461                 :     poObjBlock->WriteIntMBRCoord(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY, 
    1462               0 :                                  IsCompressedType());
    1463                 : 
    1464               0 :     poObjBlock->WriteByte(m_nPenId);      // Pen index
    1465                 : 
    1466               0 :     if (CPLGetLastErrorNo() != 0)
    1467               0 :         return -1;
    1468                 : 
    1469               0 :     return 0;
    1470                 : }
    1471                 : 
    1472                 : 
    1473                 : 
    1474                 : /**********************************************************************
    1475                 :  *                   class TABMAPObjText
    1476                 :  *
    1477                 :  **********************************************************************/
    1478                 : 
    1479                 : /**********************************************************************
    1480                 :  *                   TABMAPObjText::ReadObj()
    1481                 :  *
    1482                 :  * Read Object information starting after the object id
    1483                 :  **********************************************************************/
    1484               0 : int TABMAPObjText::ReadObj(TABMAPObjectBlock *poObjBlock)
    1485                 : {
    1486               0 :     m_nCoordBlockPtr  = poObjBlock->ReadInt32();    // String position
    1487               0 :     m_nCoordDataSize  = poObjBlock->ReadInt16();    // String length
    1488               0 :     m_nTextAlignment  = poObjBlock->ReadInt16();    // just./spacing/arrow
    1489                 : 
    1490               0 :     m_nAngle     = poObjBlock->ReadInt16();         // Tenths of degree
    1491                 : 
    1492               0 :     m_nFontStyle = poObjBlock->ReadInt16();         // Font style/effect
    1493                 : 
    1494               0 :     m_nFGColorR  = poObjBlock->ReadByte();
    1495               0 :     m_nFGColorG  = poObjBlock->ReadByte();
    1496               0 :     m_nFGColorB  = poObjBlock->ReadByte();
    1497                 : 
    1498               0 :     m_nBGColorR  = poObjBlock->ReadByte();
    1499               0 :     m_nBGColorG  = poObjBlock->ReadByte();
    1500               0 :     m_nBGColorB  = poObjBlock->ReadByte();
    1501                 : 
    1502                 :     // Label line end point
    1503               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nLineEndX, m_nLineEndY);
    1504                 : 
    1505                 :     // Text Height
    1506               0 :     if (IsCompressedType())
    1507               0 :         m_nHeight = poObjBlock->ReadInt16();
    1508                 :     else
    1509               0 :         m_nHeight = poObjBlock->ReadInt32();
    1510                 : 
    1511                 :     // Font name
    1512               0 :     m_nFontId = poObjBlock->ReadByte();      // Font name index
    1513                 : 
    1514                 :     // MBR after rotation
    1515               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nMinX, m_nMinY);
    1516               0 :     poObjBlock->ReadIntCoord(IsCompressedType(), m_nMaxX, m_nMaxY);
    1517                 : 
    1518               0 :     m_nPenId = poObjBlock->ReadByte();      // Pen index
    1519                 : 
    1520               0 :     if (CPLGetLastErrorNo() != 0)
    1521               0 :         return -1;
    1522                 : 
    1523               0 :     return 0;
    1524                 : }
    1525                 : 
    1526                 : /**********************************************************************
    1527                 :  *                   TABMAPObjText::WriteObj()
    1528                 :  *
    1529                 :  * Write Object information with the type+object id
    1530                 :  *
    1531                 :  * Returns 0 on success, -1 on error.
    1532                 :  **********************************************************************/
    1533               0 : int TABMAPObjText::WriteObj(TABMAPObjectBlock *poObjBlock)
    1534                 : {
    1535                 :     // Write object type and id
    1536               0 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
    1537                 : 
    1538               0 :     poObjBlock->WriteInt32(m_nCoordBlockPtr);     // String position
    1539               0 :     poObjBlock->WriteInt16((GInt16)m_nCoordDataSize);     // String length
    1540               0 :     poObjBlock->WriteInt16((GInt16)m_nTextAlignment);     // just./spacing/arrow
    1541                 : 
    1542               0 :     poObjBlock->WriteInt16((GInt16)m_nAngle);             // Tenths of degree
    1543                 : 
    1544               0 :     poObjBlock->WriteInt16(m_nFontStyle);         // Font style/effect
    1545                 : 
    1546               0 :     poObjBlock->WriteByte(m_nFGColorR );
    1547               0 :     poObjBlock->WriteByte(m_nFGColorG );
    1548               0 :     poObjBlock->WriteByte(m_nFGColorB );
    1549                 : 
    1550               0 :     poObjBlock->WriteByte(m_nBGColorR );
    1551               0 :     poObjBlock->WriteByte(m_nBGColorG );
    1552               0 :     poObjBlock->WriteByte(m_nBGColorB );
    1553                 : 
    1554                 :     // Label line end point
    1555               0 :     poObjBlock->WriteIntCoord(m_nLineEndX, m_nLineEndY, IsCompressedType());
    1556                 : 
    1557                 :     // Text Height
    1558               0 :     if (IsCompressedType())
    1559               0 :         poObjBlock->WriteInt16((GInt16)m_nHeight);
    1560                 :     else
    1561               0 :         poObjBlock->WriteInt32(m_nHeight);
    1562                 : 
    1563                 :     // Font name
    1564               0 :     poObjBlock->WriteByte(m_nFontId);      // Font name index
    1565                 : 
    1566                 :     // MBR after rotation
    1567                 :     poObjBlock->WriteIntMBRCoord(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY, 
    1568               0 :                                  IsCompressedType());
    1569                 : 
    1570               0 :     poObjBlock->WriteByte(m_nPenId);      // Pen index
    1571                 : 
    1572               0 :     if (CPLGetLastErrorNo() != 0)
    1573               0 :         return -1;
    1574                 : 
    1575               0 :     return 0;
    1576                 : }
    1577                 : 
    1578                 : /**********************************************************************
    1579                 :  *                   class TABMAPObjMultiPoint
    1580                 :  *
    1581                 :  * Applies to PLINE, MULTIPLINE and REGION object types
    1582                 :  **********************************************************************/
    1583                 : 
    1584                 : /**********************************************************************
    1585                 :  *                   TABMAPObjMultiPoint::ReadObj()
    1586                 :  *
    1587                 :  * Read Object information starting after the object id which should 
    1588                 :  * have been read by TABMAPObjHdr::ReadNextObj() already.
    1589                 :  * This function should be called only by TABMAPObjHdr::ReadNextObj().
    1590                 :  *
    1591                 :  * Returns 0 on success, -1 on error.
    1592                 :  **********************************************************************/
    1593               0 : int TABMAPObjMultiPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
    1594                 : {
    1595               0 :     m_nCoordBlockPtr = poObjBlock->ReadInt32();
    1596               0 :     m_nNumPoints = poObjBlock->ReadInt32();
    1597                 : 
    1598               0 :     if (IsCompressedType())
    1599                 :     {
    1600               0 :         m_nCoordDataSize = m_nNumPoints * 2 * 2;
    1601                 :     }
    1602                 :     else
    1603                 :     {
    1604               0 :         m_nCoordDataSize = m_nNumPoints * 2 * 4;
    1605                 :     }
    1606                 : 
    1607                 : 
    1608                 : #ifdef TABDUMP
    1609                 :     printf("MULTIPOINT: id=%d, type=%d, "
    1610                 :            "CoordBlockPtr=%d, CoordDataSize=%d, numPoints=%d\n",
    1611                 :            m_nId, m_nType, m_nCoordBlockPtr, m_nCoordDataSize, m_nNumPoints);
    1612                 : #endif
    1613                 : 
    1614                 :     // ?????
    1615               0 :     poObjBlock->ReadInt32();
    1616               0 :     poObjBlock->ReadInt32();
    1617               0 :     poObjBlock->ReadInt32();
    1618               0 :     poObjBlock->ReadByte();
    1619               0 :     poObjBlock->ReadByte();
    1620               0 :     poObjBlock->ReadByte();
    1621                 : 
    1622               0 :     if (m_nType == TAB_GEOM_V800_MULTIPOINT ||
    1623                 :         m_nType == TAB_GEOM_V800_MULTIPOINT_C )
    1624                 :     {
    1625                 :         /* V800 MULTIPOINTS have another 33 unknown bytes... all zeros */
    1626               0 :         poObjBlock->ReadInt32();
    1627               0 :         poObjBlock->ReadInt32();
    1628               0 :         poObjBlock->ReadInt32();
    1629               0 :         poObjBlock->ReadInt32();
    1630               0 :         poObjBlock->ReadInt32();
    1631               0 :         poObjBlock->ReadInt32();
    1632               0 :         poObjBlock->ReadInt32();
    1633               0 :         poObjBlock->ReadInt32();
    1634               0 :         poObjBlock->ReadByte();
    1635                 :     }
    1636                 : 
    1637               0 :     m_nSymbolId = poObjBlock->ReadByte();
    1638                 : 
    1639                 :     // ?????
    1640               0 :     poObjBlock->ReadByte();
    1641                 : 
    1642               0 :     if (IsCompressedType())
    1643                 :     {
    1644                 :         // Region center/label point, relative to compr. coord. origin
    1645                 :         // No it's not relative to the Object block center
    1646               0 :         m_nLabelX = poObjBlock->ReadInt16();
    1647               0 :         m_nLabelY = poObjBlock->ReadInt16();
    1648                 : 
    1649                 :         // Compressed coordinate origin
    1650               0 :         m_nComprOrgX = poObjBlock->ReadInt32();
    1651               0 :         m_nComprOrgY = poObjBlock->ReadInt32();
    1652                 : 
    1653               0 :         m_nLabelX += m_nComprOrgX;
    1654               0 :         m_nLabelY += m_nComprOrgY;
    1655                 : 
    1656               0 :         m_nMinX = m_nComprOrgX + poObjBlock->ReadInt16();  // Read MBR
    1657               0 :         m_nMinY = m_nComprOrgY + poObjBlock->ReadInt16();
    1658               0 :         m_nMaxX = m_nComprOrgX + poObjBlock->ReadInt16();
    1659               0 :         m_nMaxY = m_nComprOrgY + poObjBlock->ReadInt16();
    1660                 :     }
    1661                 :     else
    1662                 :     {
    1663                 :         // Region center/label point
    1664               0 :         m_nLabelX = poObjBlock->ReadInt32();
    1665               0 :         m_nLabelY = poObjBlock->ReadInt32();
    1666                 : 
    1667               0 :         m_nMinX = poObjBlock->ReadInt32();    // Read MBR
    1668               0 :         m_nMinY = poObjBlock->ReadInt32();
    1669               0 :         m_nMaxX = poObjBlock->ReadInt32();
    1670               0 :         m_nMaxY = poObjBlock->ReadInt32();
    1671                 : 
    1672                 :         // Init. Compr. Origin to a default value in case type is ever changed
    1673               0 :         m_nComprOrgX = (m_nMinX + m_nMaxX) / 2;
    1674               0 :         m_nComprOrgY = (m_nMinY + m_nMaxY) / 2;
    1675                 :     }
    1676                 : 
    1677               0 :     if (CPLGetLastErrorNo() != 0)
    1678               0 :         return -1;
    1679                 : 
    1680               0 :     return 0;
    1681                 : }
    1682                 : 
    1683                 : 
    1684                 : /**********************************************************************
    1685                 :  *                   TABMAPObjMultiPoint::WriteObj()
    1686                 :  *
    1687                 :  * Write Object information with the type+object id
    1688                 :  *
    1689                 :  * Returns 0 on success, -1 on error.
    1690                 :  **********************************************************************/
    1691               0 : int TABMAPObjMultiPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
    1692                 : {
    1693                 :     // Write object type and id
    1694               0 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
    1695                 : 
    1696               0 :     poObjBlock->WriteInt32(m_nCoordBlockPtr);
    1697                 : 
    1698                 :     // Number of points
    1699               0 :     poObjBlock->WriteInt32(m_nNumPoints);
    1700                 : 
    1701                 :     //  unknown bytes
    1702               0 :     poObjBlock->WriteZeros(15);
    1703                 : 
    1704               0 :     if (m_nType == TAB_GEOM_V800_MULTIPOINT ||
    1705                 :         m_nType == TAB_GEOM_V800_MULTIPOINT_C )
    1706                 :     {
    1707                 :         /* V800 MULTIPOINTS have another 33 unknown bytes... all zeros */
    1708               0 :         poObjBlock->WriteZeros(33);
    1709                 :     }
    1710                 : 
    1711                 :     // Symbol Id
    1712               0 :     poObjBlock->WriteByte(m_nSymbolId);
    1713                 : 
    1714                 :     // ????
    1715               0 :     poObjBlock->WriteByte(0);
    1716                 : 
    1717                 :     // MBR
    1718               0 :     if (IsCompressedType())
    1719                 :     {
    1720                 :         // Region center/label point, relative to compr. coord. origin
    1721                 :         // No it's not relative to the Object block center
    1722               0 :         poObjBlock->WriteInt16((GInt16)(m_nLabelX - m_nComprOrgX));
    1723               0 :         poObjBlock->WriteInt16((GInt16)(m_nLabelY - m_nComprOrgY));
    1724                 : 
    1725               0 :         poObjBlock->WriteInt32(m_nComprOrgX);
    1726               0 :         poObjBlock->WriteInt32(m_nComprOrgY);
    1727                 : 
    1728                 :         // MBR relative to object origin (and not object block center)
    1729               0 :         poObjBlock->WriteInt16((GInt16)(m_nMinX - m_nComprOrgX));
    1730               0 :         poObjBlock->WriteInt16((GInt16)(m_nMinY - m_nComprOrgY));
    1731               0 :         poObjBlock->WriteInt16((GInt16)(m_nMaxX - m_nComprOrgX));
    1732               0 :         poObjBlock->WriteInt16((GInt16)(m_nMaxY - m_nComprOrgY));
    1733                 :     }
    1734                 :     else
    1735                 :     {
    1736                 :         // Region center/label point
    1737               0 :         poObjBlock->WriteInt32(m_nLabelX);
    1738               0 :         poObjBlock->WriteInt32(m_nLabelY);
    1739                 : 
    1740               0 :         poObjBlock->WriteInt32(m_nMinX);
    1741               0 :         poObjBlock->WriteInt32(m_nMinY);
    1742               0 :         poObjBlock->WriteInt32(m_nMaxX);
    1743               0 :         poObjBlock->WriteInt32(m_nMaxY);
    1744                 :     }
    1745                 : 
    1746               0 :     if (CPLGetLastErrorNo() != 0)
    1747               0 :         return -1;
    1748                 : 
    1749               0 :     return 0;
    1750                 : }
    1751                 : 
    1752                 : /**********************************************************************
    1753                 :  *                   class TABMAPObjCollection
    1754                 :  *
    1755                 :  **********************************************************************/
    1756                 : 
    1757                 : /**********************************************************************
    1758                 :  *                   TABMAPObjCollection::ReadObj()
    1759                 :  *
    1760                 :  * Read Object information starting after the object id which should 
    1761                 :  * have been read by TABMAPObjHdr::ReadNextObj() already.
    1762                 :  * This function should be called only by TABMAPObjHdr::ReadNextObj().
    1763                 :  *
    1764                 :  * Returns 0 on success, -1 on error.
    1765                 :  **********************************************************************/
    1766               0 : int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
    1767                 : {
    1768               0 :     int SIZE_OF_REGION_PLINE_MINI_HDR = 24, SIZE_OF_MPOINT_MINI_HDR = 24;
    1769               0 :     int nVersion = TAB_GEOM_GET_VERSION(m_nType);
    1770                 : 
    1771                 :     /* Figure the size of the mini-header that we find for each of the
    1772                 :      * 3 optional components (center x,y and mbr)
    1773                 :      */
    1774               0 :     if (IsCompressedType())
    1775                 :     {
    1776                 :         /* 6 * int16 */
    1777               0 :         SIZE_OF_REGION_PLINE_MINI_HDR = SIZE_OF_MPOINT_MINI_HDR = 12; 
    1778                 :     }
    1779                 :     else
    1780                 :     {
    1781                 :         /* 6 * int32 */
    1782               0 :         SIZE_OF_REGION_PLINE_MINI_HDR = SIZE_OF_MPOINT_MINI_HDR = 24;
    1783                 :     }
    1784                 :   
    1785               0 :     if (nVersion >= 800)
    1786                 :     {
    1787                 :         /* extra 4 bytes for num_segments in Region/Pline mini-headers */
    1788               0 :         SIZE_OF_REGION_PLINE_MINI_HDR += 4;  
    1789                 :     }
    1790                 : 
    1791               0 :     m_nCoordBlockPtr = poObjBlock->ReadInt32();    // pointer into coord block
    1792               0 :     m_nNumMultiPoints = poObjBlock->ReadInt32();   // no. points in multi point
    1793               0 :     m_nRegionDataSize = poObjBlock->ReadInt32();   // size of region data inc. section hdrs
    1794               0 :     m_nPolylineDataSize = poObjBlock->ReadInt32(); // size of multipline data inc. section hdrs
    1795                 : 
    1796               0 :     if (nVersion < 800)
    1797                 :     {
    1798                 :         // Num Region/Pline section headers (int16 in V650)
    1799               0 :         m_nNumRegSections = poObjBlock->ReadInt16();   
    1800               0 :         m_nNumPLineSections = poObjBlock->ReadInt16();
    1801                 :     }
    1802                 :     else
    1803                 :     {
    1804                 :         // Num Region/Pline section headers (int32 in V800)
    1805               0 :         m_nNumRegSections = poObjBlock->ReadInt32();   
    1806               0 :         m_nNumPLineSections = poObjBlock->ReadInt32();
    1807                 :     }
    1808                 : 
    1809                 : 
    1810               0 :     if (IsCompressedType())
    1811                 :     {
    1812               0 :         m_nMPointDataSize = m_nNumMultiPoints * 2 * 2;
    1813                 :     }
    1814                 :     else
    1815                 :     {
    1816               0 :         m_nMPointDataSize = m_nNumMultiPoints * 2 * 4;
    1817                 :     }
    1818                 : 
    1819                 :     /* NB. MapInfo counts 2 extra bytes per Region and Pline section header
    1820                 :      * in the RegionDataSize and PolylineDataSize values but those 2 extra 
    1821                 :      * bytes are not present in the section hdr (possibly due to an alignment
    1822                 :      * to a 4 byte boundary in memory in MapInfo?). The real data size in 
    1823                 :      * the CoordBlock is actually 2 bytes shorter per section header than 
    1824                 :      * what is written in RegionDataSize and PolylineDataSize values.
    1825                 :      *
    1826                 :      * We'll adjust the values in memory to be the corrected values.
    1827                 :      */
    1828               0 :     m_nRegionDataSize   = m_nRegionDataSize - (2 * m_nNumRegSections);
    1829               0 :     m_nPolylineDataSize = m_nPolylineDataSize - (2 * m_nNumPLineSections);
    1830                 : 
    1831                 :     /* Compute total coord block data size, required when splitting blocks */
    1832               0 :     m_nCoordDataSize = 0;
    1833                 : 
    1834               0 :     if(m_nNumRegSections > 0)
    1835                 :     {
    1836               0 :         m_nCoordDataSize += SIZE_OF_REGION_PLINE_MINI_HDR + m_nRegionDataSize;
    1837                 :     }
    1838               0 :     if(m_nNumPLineSections > 0)
    1839                 :     {
    1840               0 :         m_nCoordDataSize += SIZE_OF_REGION_PLINE_MINI_HDR + m_nPolylineDataSize;
    1841                 :     }
    1842               0 :     if(m_nNumMultiPoints > 0)
    1843                 :     {
    1844               0 :         m_nCoordDataSize += SIZE_OF_MPOINT_MINI_HDR + m_nMPointDataSize;
    1845                 :     }
    1846                 : 
    1847                 : 
    1848                 : #ifdef TABDUMP
    1849                 :     printf("COLLECTION: id=%d, type=%d (0x%x), "
    1850                 :            "CoordBlockPtr=%d, numRegionSections=%d (size=%d+%d), "
    1851                 :            "numPlineSections=%d (size=%d+%d), numPoints=%d (size=%d+%d)\n",
    1852                 :            m_nId, m_nType, m_nType, m_nCoordBlockPtr, 
    1853                 :            m_nNumRegSections, m_nRegionDataSize, SIZE_OF_REGION_PLINE_MINI_HDR,
    1854                 :            m_nNumPLineSections, m_nPolylineDataSize, SIZE_OF_REGION_PLINE_MINI_HDR,
    1855                 :            m_nNumMultiPoints, m_nMPointDataSize, SIZE_OF_MPOINT_MINI_HDR);
    1856                 : #endif
    1857                 : 
    1858               0 :     if (nVersion >= 800)
    1859                 :     {
    1860                 :         // Extra byte in V800 files... value always 4???
    1861               0 :         int nValue = poObjBlock->ReadByte();
    1862               0 :         if (nValue != 4)
    1863                 :         {
    1864                 :             CPLError(CE_Failure, CPLE_AssertionFailed, 
    1865                 :                      "TABMAPObjCollection::ReadObj(): Byte 29 in Collection "
    1866                 :                      "object header not equal to 4 as expected. Value is %d. "
    1867                 :                      "Please report this error to the MITAB list so that "
    1868                 :                      "MITAB can be extended to support this case.",
    1869               0 :                      nValue);
    1870                 :             // We don't return right away, the error should be caught at the
    1871                 :             // end of this function.
    1872                 :         }
    1873                 :     }
    1874                 : 
    1875                 :     // ??? All zeros ???
    1876               0 :     poObjBlock->ReadInt32();
    1877               0 :     poObjBlock->ReadInt32();
    1878               0 :     poObjBlock->ReadInt32();
    1879               0 :     poObjBlock->ReadByte();
    1880               0 :     poObjBlock->ReadByte();
    1881               0 :     poObjBlock->ReadByte();
    1882                 : 
    1883               0 :     m_nMultiPointSymbolId = poObjBlock->ReadByte();
    1884                 : 
    1885               0 :     poObjBlock->ReadByte();  // ???
    1886               0 :     m_nRegionPenId = poObjBlock->ReadByte();
    1887               0 :     m_nPolylinePenId = poObjBlock->ReadByte();
    1888               0 :     m_nRegionBrushId = poObjBlock->ReadByte();
    1889                 : 
    1890               0 :     if (IsCompressedType())
    1891                 :     {
    1892                 : #ifdef TABDUMP
    1893                 :     printf("COLLECTION: READING ComprOrg @ %d\n",
    1894                 :            poObjBlock->GetCurAddress());
    1895                 : #endif
    1896                 :         // Compressed coordinate origin
    1897               0 :         m_nComprOrgX = poObjBlock->ReadInt32();
    1898               0 :         m_nComprOrgY = poObjBlock->ReadInt32();
    1899                 : 
    1900               0 :         m_nMinX = m_nComprOrgX + poObjBlock->ReadInt16();  // Read MBR
    1901               0 :         m_nMinY = m_nComprOrgY + poObjBlock->ReadInt16();
    1902               0 :         m_nMaxX = m_nComprOrgX + poObjBlock->ReadInt16();
    1903               0 :         m_nMaxY = m_nComprOrgY + poObjBlock->ReadInt16();
    1904                 : #ifdef TABDUMP
    1905                 :     printf("COLLECTION: ComprOrgX,Y= (%d,%d)\n",
    1906                 :            m_nComprOrgX, m_nComprOrgY);
    1907                 : #endif
    1908                 :     }
    1909                 :     else
    1910                 :     {
    1911               0 :         m_nMinX = poObjBlock->ReadInt32();    // Read MBR
    1912               0 :         m_nMinY = poObjBlock->ReadInt32();
    1913               0 :         m_nMaxX = poObjBlock->ReadInt32();
    1914               0 :         m_nMaxY = poObjBlock->ReadInt32();
    1915                 : 
    1916                 :         // Init. Compr. Origin to a default value in case type is ever changed
    1917               0 :         m_nComprOrgX = (m_nMinX + m_nMaxX) / 2;
    1918               0 :         m_nComprOrgY = (m_nMinY + m_nMaxY) / 2;
    1919                 :     }
    1920                 : 
    1921               0 :     if (CPLGetLastErrorNo() != 0)
    1922               0 :         return -1;
    1923                 : 
    1924               0 :     return 0;
    1925                 : }
    1926                 : 
    1927                 : 
    1928                 : /**********************************************************************
    1929                 :  *                   TABMAPObjCollection::WriteObj()
    1930                 :  *
    1931                 :  * Write Object information with the type+object id
    1932                 :  *
    1933                 :  * Returns 0 on success, -1 on error.
    1934                 :  **********************************************************************/
    1935               0 : int TABMAPObjCollection::WriteObj(TABMAPObjectBlock *poObjBlock)
    1936                 : {
    1937                 :     // Write object type and id
    1938               0 :     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
    1939                 : 
    1940               0 :     int nVersion = TAB_GEOM_GET_VERSION(m_nType);
    1941                 : 
    1942                 :     /* NB. MapInfo counts 2 extra bytes per Region and Pline section header
    1943                 :      * in the RegionDataSize and PolylineDataSize values but those 2 extra 
    1944                 :      * bytes are not present in the section hdr (possibly due to an alignment
    1945                 :      * to a 4 byte boundary in memory in MapInfo?). The real data size in 
    1946                 :      * the CoordBlock is actually 2 bytes shorter per section header than 
    1947                 :      * what is written in RegionDataSize and PolylineDataSize values.
    1948                 :      *
    1949                 :      * The values in memory are the corrected values so we need to add 2 bytes
    1950                 :      * per section header in the values that we write on disk to emulate 
    1951                 :      * MapInfo's behavior.
    1952                 :      */
    1953               0 :     GInt32 nRegionDataSizeMI = m_nRegionDataSize + (2*m_nNumRegSections);
    1954               0 :     GInt32 nPolylineDataSizeMI = m_nPolylineDataSize+(2*m_nNumPLineSections);
    1955                 : 
    1956               0 :     poObjBlock->WriteInt32(m_nCoordBlockPtr);    // pointer into coord block
    1957               0 :     poObjBlock->WriteInt32(m_nNumMultiPoints);   // no. points in multi point
    1958               0 :     poObjBlock->WriteInt32(nRegionDataSizeMI);   // size of region data inc. section hdrs
    1959               0 :     poObjBlock->WriteInt32(nPolylineDataSizeMI); // size of Mpolyline data inc. sction hdrs
    1960                 : 
    1961               0 :     if (nVersion < 800)
    1962                 :     {
    1963                 :         // Num Region/Pline section headers (int16 in V650)
    1964               0 :         poObjBlock->WriteInt16((GInt16)m_nNumRegSections);
    1965               0 :         poObjBlock->WriteInt16((GInt16)m_nNumPLineSections);
    1966                 :     }
    1967                 :     else
    1968                 :     {
    1969                 :         // Num Region/Pline section headers (int32 in V800)
    1970               0 :         poObjBlock->WriteInt32(m_nNumRegSections);
    1971               0 :         poObjBlock->WriteInt32(m_nNumPLineSections);
    1972                 :     }
    1973                 : 
    1974               0 :     if (nVersion >= 800)
    1975                 :     {
    1976                 :         // Extra byte in V800 files... value always 4???
    1977               0 :         poObjBlock->WriteByte(4);
    1978                 :     }
    1979                 : 
    1980                 :     // Unknown data ?????
    1981               0 :     poObjBlock->WriteInt32(0);
    1982               0 :     poObjBlock->WriteInt32(0);
    1983               0 :     poObjBlock->WriteInt32(0);
    1984               0 :     poObjBlock->WriteByte(0);
    1985               0 :     poObjBlock->WriteByte(0);
    1986               0 :     poObjBlock->WriteByte(0);
    1987                 : 
    1988               0 :     poObjBlock->WriteByte(m_nMultiPointSymbolId);
    1989                 : 
    1990               0 :     poObjBlock->WriteByte(0);
    1991               0 :     poObjBlock->WriteByte(m_nRegionPenId);
    1992               0 :     poObjBlock->WriteByte(m_nPolylinePenId);
    1993               0 :     poObjBlock->WriteByte(m_nRegionBrushId);
    1994                 : 
    1995               0 :     if (IsCompressedType())
    1996                 :     {
    1997                 : #ifdef TABDUMP
    1998                 :     printf("COLLECTION: WRITING ComprOrgX,Y= (%d,%d) @ %d\n",
    1999                 :            m_nComprOrgX, m_nComprOrgY, poObjBlock->GetCurAddress());
    2000                 : #endif
    2001                 :         // Compressed coordinate origin
    2002               0 :         poObjBlock->WriteInt32(m_nComprOrgX);
    2003               0 :         poObjBlock->WriteInt32(m_nComprOrgY);
    2004                 : 
    2005               0 :         poObjBlock->WriteInt16((GInt16)(m_nMinX - m_nComprOrgX));  // MBR
    2006               0 :         poObjBlock->WriteInt16((GInt16)(m_nMinY - m_nComprOrgY));
    2007               0 :         poObjBlock->WriteInt16((GInt16)(m_nMaxX - m_nComprOrgX));
    2008               0 :         poObjBlock->WriteInt16((GInt16)(m_nMaxY - m_nComprOrgY));
    2009                 :     }
    2010                 :     else
    2011                 :     {
    2012               0 :         poObjBlock->WriteInt32(m_nMinX);    // MBR
    2013               0 :         poObjBlock->WriteInt32(m_nMinY);
    2014               0 :         poObjBlock->WriteInt32(m_nMaxX);
    2015               0 :         poObjBlock->WriteInt32(m_nMaxY);
    2016                 :     }
    2017                 : 
    2018               0 :     if (CPLGetLastErrorNo() != 0)
    2019               0 :         return -1;
    2020                 : 
    2021               0 :     return 0;
    2022                 : }

Generated by: LCOV version 1.7