Coverage Report

Created: 2026-03-30 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/mitab/mitab.h
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * Name:     mitab.h
4
 * Project:  MapInfo TAB Read/Write library
5
 * Language: C++
6
 * Purpose:  Header file containing public definitions for the library.
7
 * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
8
 *
9
 **********************************************************************
10
 * Copyright (c) 1999-2005, Daniel Morissette
11
 * Copyright (c) 2014, Even Rouault <even.rouault at spatialys.com>
12
 *
13
 * SPDX-License-Identifier: MIT
14
 **********************************************************************/
15
16
#ifndef MITAB_H_INCLUDED_
17
#define MITAB_H_INCLUDED_
18
19
#include "mitab_priv.h"
20
#include "ogr_feature.h"
21
#include "ogr_featurestyle.h"
22
#include "ogrsf_frmts.h"
23
24
#include <set>
25
26
/*---------------------------------------------------------------------
27
 * Current version of the MITAB library... always useful!
28
 *--------------------------------------------------------------------*/
29
#define MITAB_VERSION "2.0.0-dev (2008-10)"
30
#define MITAB_VERSION_INT 2000000 /* version x.y.z -> xxxyyyzzz */
31
32
#ifndef ROUND_INT
33
141k
#define ROUND_INT(dX) static_cast<int>((dX) < 0.0 ? (dX) - 0.5 : (dX) + 0.5)
34
#endif
35
36
#define MITAB_AREA(x1, y1, x2, y2)                                             \
37
8.51k
    ((static_cast<double>(x2) - (x1)) * (static_cast<double>(y2) - (y1)))
38
39
class TABFeature;
40
41
/*---------------------------------------------------------------------
42
 * Codes for the GetFileClass() in the IMapInfoFile-derived  classes
43
 *--------------------------------------------------------------------*/
44
typedef enum
45
{
46
    TABFC_IMapInfoFile = 0,
47
    TABFC_TABFile,
48
    TABFC_TABView,
49
    TABFC_TABSeamless,
50
    TABFC_MIFFile
51
} TABFileClass;
52
53
/*---------------------------------------------------------------------
54
 *                      class IMapInfoFile
55
 *
56
 * Virtual base class for the TABFile and MIFFile classes.
57
 *
58
 * This is the definition of the public interface methods that should
59
 * be available for any type of MapInfo dataset.
60
 *--------------------------------------------------------------------*/
61
62
class IMapInfoFile CPL_NON_FINAL : public OGRLayer
63
{
64
    CPL_DISALLOW_COPY_ASSIGN(IMapInfoFile)
65
66
  protected:
67
    GDALDataset *m_poDS = nullptr;
68
    GIntBig m_nCurFeatureId;
69
    TABFeature *m_poCurFeature;
70
    GBool m_bBoundsSet;
71
72
    char *m_pszCharset;
73
    bool m_bStrictLaundering = true;
74
    std::set<CPLString> m_oSetFields{};
75
    TABFeature *CreateTABFeature(OGRFeature *poFeature);
76
77
  public:
78
    IMapInfoFile(GDALDataset *poDS);
79
    ~IMapInfoFile() override;
80
81
    virtual TABFileClass GetFileClass()
82
0
    {
83
0
        return TABFC_IMapInfoFile;
84
0
    }
85
86
    virtual int Open(const char *pszFname, const char *pszAccess,
87
                     GBool bTestOpenNoError = FALSE,
88
                     const char *pszCharset = nullptr);
89
90
    virtual int Open(const char *pszFname, TABAccess eAccess,
91
                     GBool bTestOpenNoError = FALSE,
92
                     const char *pszCharset = nullptr) = 0;
93
    virtual int Close() = 0;
94
95
    virtual int
96
    SetQuickSpatialIndexMode(CPL_UNUSED GBool bQuickSpatialIndexMode = TRUE)
97
0
    {
98
0
        return -1;
99
0
    }
100
101
    virtual const char *GetTableName() = 0;
102
103
    ///////////////
104
    // Static method to detect file type, create an object to read that
105
    // file and open it.
106
    static IMapInfoFile *SmartOpen(GDALDataset *poDS, const char *pszFname,
107
                                   GBool bUpdate = FALSE,
108
                                   GBool bTestOpenNoError = FALSE);
109
110
    ///////////////
111
    //  OGR methods for read support
112
    void ResetReading() override = 0;
113
    GIntBig GetFeatureCount(int bForce) override = 0;
114
    OGRFeature *GetNextFeature() override;
115
    OGRFeature *GetFeature(GIntBig nFeatureId) override;
116
    OGRErr ICreateFeature(OGRFeature *poFeature) override;
117
    int TestCapability(const char *pszCap) const override = 0;
118
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
119
                      bool bForce) override = 0;
120
121
    GDALDataset *GetDataset() override
122
0
    {
123
0
        return m_poDS;
124
0
    }
125
126
    ///////////////
127
    // Read access specific stuff
128
    //
129
    virtual GIntBig GetNextFeatureId(GIntBig nPrevId) = 0;
130
    virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) = 0;
131
    const OGRFeatureDefn *GetLayerDefn() const override = 0;
132
133
    virtual TABFieldType GetNativeFieldType(int nFieldId) = 0;
134
135
    virtual int GetBounds(double &dXMin, double &dYMin, double &dXMax,
136
                          double &dYMax, GBool bForce = TRUE) = 0;
137
138
    const OGRSpatialReference *GetSpatialRef() const override = 0;
139
140
    virtual int GetFeatureCountByType(int &numPoints, int &numLines,
141
                                      int &numRegions, int &numTexts,
142
                                      GBool bForce = TRUE) = 0;
143
144
    virtual GBool IsFieldIndexed(int nFieldId) = 0;
145
    virtual GBool IsFieldUnique(int nFieldId) = 0;
146
147
    ///////////////
148
    // Write access specific stuff
149
    //
150
    GBool IsBoundsSet()
151
324
    {
152
324
        return m_bBoundsSet;
153
324
    }
154
155
    virtual int SetBounds(double dXMin, double dYMin, double dXMax,
156
                          double dYMax) = 0;
157
    virtual int
158
    SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
159
                   TABFieldType *paeMapInfoNativeFieldTypes = nullptr) = 0;
160
    virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
161
                               int nWidth = 0, int nPrecision = 0,
162
                               GBool bIndexed = FALSE, GBool bUnique = FALSE,
163
                               int bApproxOK = TRUE) = 0;
164
    virtual OGRErr CreateField(const OGRFieldDefn *poField,
165
                               int bApproxOK = TRUE) override;
166
167
    virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) = 0;
168
169
    virtual OGRErr CreateFeature(TABFeature *poFeature) = 0;
170
171
    virtual int SetFieldIndexed(int nFieldId) = 0;
172
173
    virtual int SetCharset(const char *charset);
174
175
    virtual const char *GetCharset() const;
176
177
    static const char *CharsetToEncoding(const char *);
178
    static const char *EncodingToCharset(const char *);
179
180
    void SetEncoding(const char *);
181
    const char *GetEncoding() const;
182
    virtual void SetStrictLaundering(bool);
183
    int TestUtf8Capability() const;
184
    CPLString NormalizeFieldName(const char *pszName) const;
185
    ///////////////
186
    // semi-private.
187
    virtual int GetProjInfo(TABProjInfo *poPI) = 0;
188
    virtual int SetProjInfo(TABProjInfo *poPI) = 0;
189
    virtual int SetMIFCoordSys(const char *pszMIFCoordSys) = 0;
190
191
    static int GetTABType(const OGRFieldDefn *poField, TABFieldType *peTABType,
192
                          int *pnWidth, int *pnPrecision);
193
194
#ifdef DEBUG
195
    virtual void Dump(FILE *fpOut = nullptr) = 0;
196
#endif
197
};
198
199
/*---------------------------------------------------------------------
200
 *                      class TABFile
201
 *
202
 * The main class for TAB datasets.  External programs should use this
203
 * class to open a TAB dataset and read/write features from/to it.
204
 *
205
 *--------------------------------------------------------------------*/
206
class TABFile final : public IMapInfoFile
207
{
208
    CPL_DISALLOW_COPY_ASSIGN(TABFile)
209
210
  private:
211
    char *m_pszFname;
212
    TABAccess m_eAccessMode;
213
    char **m_papszTABFile;
214
    int m_nVersion;
215
    int *m_panIndexNo;
216
    TABTableType m_eTableType;  // NATIVE (.DAT) or DBF
217
218
    TABDATFile *m_poDATFile;  // Attributes file
219
    TABMAPFile *m_poMAPFile;  // Object Geometry file
220
    TABINDFile *m_poINDFile;  // Attributes index file
221
222
    OGRFeatureDefn *m_poDefn;
223
    mutable OGRSpatialReference *m_poSpatialRef;
224
    int bUseSpatialTraversal;
225
226
    int m_nLastFeatureId;
227
228
    GIntBig *m_panMatchingFIDs;
229
    int m_iMatchingFID;
230
231
    int m_bNeedTABRewrite;
232
233
    int m_bLastOpWasRead;
234
    int m_bLastOpWasWrite;
235
    ///////////////
236
    // Private Read access specific stuff
237
    //
238
    int ParseTABFileFirstPass(GBool bTestOpenNoError);
239
    int ParseTABFileFields();
240
241
    ///////////////
242
    // Private Write access specific stuff
243
    //
244
    int WriteTABFile();
245
246
  public:
247
    explicit TABFile(GDALDataset *poDS);
248
    ~TABFile() override;
249
250
    TABFileClass GetFileClass() override
251
240
    {
252
240
        return TABFC_TABFile;
253
240
    }
254
255
    virtual int Open(const char *pszFname, const char *pszAccess,
256
                     GBool bTestOpenNoError = FALSE,
257
                     const char *pszCharset = nullptr) override
258
0
    {
259
0
        return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError,
260
0
                                  pszCharset);
261
0
    }
262
263
    virtual int Open(const char *pszFname, TABAccess eAccess,
264
                     GBool bTestOpenNoError = FALSE,
265
                     const char *pszCharset = nullptr) override
266
2.97k
    {
267
2.97k
        return Open(pszFname, eAccess, bTestOpenNoError, 512, pszCharset);
268
2.97k
    }
269
270
    int Open(const char *pszFname, TABAccess eAccess, GBool bTestOpenNoError,
271
             int nBlockSizeForCreate, const char *pszCharset);
272
273
    int Close() override;
274
275
    virtual int
276
    SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode = TRUE) override;
277
278
    const char *GetTableName() override
279
0
    {
280
0
        return m_poDefn ? m_poDefn->GetName() : "";
281
0
    }
282
283
    void ResetReading() override;
284
    int TestCapability(const char *pszCap) const override;
285
    GIntBig GetFeatureCount(int bForce) override;
286
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
287
                      bool bForce) override;
288
289
    /* Implement OGRLayer's SetFeature() for random write, only with TABFile */
290
    OGRErr ISetFeature(OGRFeature *) override;
291
    OGRErr DeleteFeature(GIntBig nFeatureId) override;
292
293
    OGRErr DeleteField(int iField) override;
294
    OGRErr ReorderFields(int *panMap) override;
295
    virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
296
                                  int nFlags) override;
297
298
    OGRErr SyncToDisk() override;
299
300
    CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
301
                           const char *pszDomain = "") override;
302
303
    ///////////////
304
    // Read access specific stuff
305
    //
306
307
    int GetNextFeatureId_Spatial(int nPrevId);
308
309
    GIntBig GetNextFeatureId(GIntBig nPrevId) override;
310
    TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
311
    const OGRFeatureDefn *GetLayerDefn() const override;
312
313
    TABFieldType GetNativeFieldType(int nFieldId) override;
314
315
    virtual int GetBounds(double &dXMin, double &dYMin, double &dXMax,
316
                          double &dYMax, GBool bForce = TRUE) override;
317
318
    const OGRSpatialReference *GetSpatialRef() const override;
319
320
    virtual int GetFeatureCountByType(int &numPoints, int &numLines,
321
                                      int &numRegions, int &numTexts,
322
                                      GBool bForce = TRUE) override;
323
324
    GBool IsFieldIndexed(int nFieldId) override;
325
326
    GBool IsFieldUnique(int /*nFieldId*/) override
327
0
    {
328
0
        return FALSE;
329
0
    }
330
331
    int GetVersion()
332
0
    {
333
0
        return m_nVersion;
334
0
    }
335
336
    ///////////////
337
    // Write access specific stuff
338
    //
339
    virtual int SetBounds(double dXMin, double dYMin, double dXMax,
340
                          double dYMax) override;
341
    virtual int
342
    SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
343
                   TABFieldType *paeMapInfoNativeFieldTypes = nullptr) override;
344
    virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
345
                               int nWidth = 0, int nPrecision = 0,
346
                               GBool bIndexed = FALSE, GBool bUnique = FALSE,
347
                               int bApproxOK = TRUE) override;
348
    int SetSpatialRef(OGRSpatialReference *poSpatialRef) override;
349
350
    OGRErr CreateFeature(TABFeature *poFeature) override;
351
352
    int SetFieldIndexed(int nFieldId) override;
353
354
    ///////////////
355
    // semi-private.
356
    int GetProjInfo(TABProjInfo *poPI) override
357
0
    {
358
0
        return m_poMAPFile->GetHeaderBlock()->GetProjInfo(poPI);
359
0
    }
360
361
    int SetProjInfo(TABProjInfo *poPI) override;
362
    int SetMIFCoordSys(const char *pszMIFCoordSys) override;
363
364
    int GetFieldIndexNumber(int nFieldId);
365
    TABINDFile *GetINDFileRef();
366
367
    TABMAPFile *GetMAPFileRef()
368
0
    {
369
0
        return m_poMAPFile;
370
0
    }
371
372
    int WriteFeature(TABFeature *poFeature);
373
    int SetCharset(const char *pszCharset) override;
374
    void SetStrictLaundering(bool bStrictLaundering) override;
375
#ifdef DEBUG
376
    void Dump(FILE *fpOut = nullptr) override;
377
#endif
378
};
379
380
/*---------------------------------------------------------------------
381
 *                      class TABView
382
 *
383
 * TABView is used to handle special type of .TAB files that are
384
 * composed of a number of .TAB datasets linked through some indexed
385
 * fields.
386
 *
387
 * NOTE: The current implementation supports only TABViews composed
388
 *       of 2 TABFiles linked through an indexed field of integer type.
389
 *       It is unclear if any other type of views could exist anyways.
390
 *--------------------------------------------------------------------*/
391
class TABView final : public IMapInfoFile
392
{
393
    CPL_DISALLOW_COPY_ASSIGN(TABView)
394
395
  private:
396
    char *m_pszFname;
397
    TABAccess m_eAccessMode;
398
    char **m_papszTABFile;
399
    char *m_pszVersion;
400
401
    char **m_papszTABFnames;
402
    TABFile **m_papoTABFiles;
403
    int m_numTABFiles;
404
    int m_nMainTableIndex;  // The main table is the one that also
405
                            // contains the geometries
406
    char **m_papszFieldNames;
407
    char **m_papszWhereClause;
408
409
    TABRelation *m_poRelation;
410
    GBool m_bRelFieldsCreated;
411
412
    ///////////////
413
    // Private Read access specific stuff
414
    //
415
    int ParseTABFile(const char *pszDatasetPath,
416
                     GBool bTestOpenNoError = FALSE);
417
418
    int OpenForRead(const char *pszFname, GBool bTestOpenNoError = FALSE);
419
420
    ///////////////
421
    // Private Write access specific stuff
422
    //
423
    int OpenForWrite(const char *pszFname);
424
    int WriteTABFile();
425
426
  public:
427
    explicit TABView(GDALDataset *poDS);
428
    ~TABView() override;
429
430
    TABFileClass GetFileClass() override
431
0
    {
432
0
        return TABFC_TABView;
433
0
    }
434
435
    virtual int Open(const char *pszFname, const char *pszAccess,
436
                     GBool bTestOpenNoError = FALSE,
437
                     const char *pszCharset = nullptr) override
438
0
    {
439
0
        return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError,
440
0
                                  pszCharset);
441
0
    }
442
443
    virtual int Open(const char *pszFname, TABAccess eAccess,
444
                     GBool bTestOpenNoError = FALSE,
445
                     const char *pszCharset = nullptr) override;
446
    int Close() override;
447
448
    virtual int
449
    SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode = TRUE) override;
450
451
    const char *GetTableName() override
452
0
    {
453
0
        return m_poRelation ? m_poRelation->GetFeatureDefn()->GetName() : "";
454
0
    }
455
456
    void ResetReading() override;
457
    int TestCapability(const char *pszCap) const override;
458
    GIntBig GetFeatureCount(int bForce) override;
459
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
460
                      bool bForce) override;
461
462
    ///////////////
463
    // Read access specific stuff
464
    //
465
466
    GIntBig GetNextFeatureId(GIntBig nPrevId) override;
467
    TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
468
    const OGRFeatureDefn *GetLayerDefn() const override;
469
470
    TABFieldType GetNativeFieldType(int nFieldId) override;
471
472
    virtual int GetBounds(double &dXMin, double &dYMin, double &dXMax,
473
                          double &dYMax, GBool bForce = TRUE) override;
474
475
    const OGRSpatialReference *GetSpatialRef() const override;
476
477
    virtual int GetFeatureCountByType(int &numPoints, int &numLines,
478
                                      int &numRegions, int &numTexts,
479
                                      GBool bForce = TRUE) override;
480
481
    GBool IsFieldIndexed(int nFieldId) override;
482
    GBool IsFieldUnique(int nFieldId) override;
483
484
    ///////////////
485
    // Write access specific stuff
486
    //
487
    virtual int SetBounds(double dXMin, double dYMin, double dXMax,
488
                          double dYMax) override;
489
    virtual int
490
    SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
491
                   TABFieldType *paeMapInfoNativeFieldTypes = nullptr) override;
492
    virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
493
                               int nWidth = 0, int nPrecision = 0,
494
                               GBool bIndexed = FALSE, GBool bUnique = FALSE,
495
                               int bApproxOK = TRUE) override;
496
    int SetSpatialRef(OGRSpatialReference *poSpatialRef) override;
497
498
    OGRErr CreateFeature(TABFeature *poFeature) override;
499
500
    int SetFieldIndexed(int nFieldId) override;
501
502
    ///////////////
503
    // semi-private.
504
    int GetProjInfo(TABProjInfo *poPI) override
505
0
    {
506
0
        return m_nMainTableIndex != -1
507
0
                   ? m_papoTABFiles[m_nMainTableIndex]->GetProjInfo(poPI)
508
0
                   : -1;
509
0
    }
510
511
    int SetProjInfo(TABProjInfo *poPI) override
512
0
    {
513
0
        return m_nMainTableIndex != -1
514
0
                   ? m_papoTABFiles[m_nMainTableIndex]->SetProjInfo(poPI)
515
0
                   : -1;
516
0
    }
517
518
    int SetMIFCoordSys(const char * /*pszMIFCoordSys*/) override
519
0
    {
520
0
        return -1;
521
0
    }
522
523
    int SetCharset(const char *pszCharset) override;
524
525
#ifdef DEBUG
526
    void Dump(FILE *fpOut = nullptr) override;
527
#endif
528
};
529
530
/*---------------------------------------------------------------------
531
 *                      class TABSeamless
532
 *
533
 * TABSeamless is used to handle seamless .TAB files that are
534
 * composed of a main .TAB file in which each feature is the MBR of
535
 * a base table.
536
 *
537
 * TABSeamless are supported for read access only.
538
 *--------------------------------------------------------------------*/
539
class TABSeamless final : public IMapInfoFile
540
{
541
    CPL_DISALLOW_COPY_ASSIGN(TABSeamless)
542
543
  private:
544
    char *m_pszFname;
545
    char *m_pszPath;
546
    TABAccess m_eAccessMode;
547
    OGRFeatureDefn *m_poFeatureDefnRef;
548
549
    TABFile *m_poIndexTable;
550
    int m_nTableNameField;
551
    int m_nCurBaseTableId;
552
    TABFile *m_poCurBaseTable;
553
    GBool m_bEOF;
554
555
    ///////////////
556
    // Private Read access specific stuff
557
    //
558
    int OpenForRead(const char *pszFname, GBool bTestOpenNoError = FALSE);
559
    int OpenBaseTable(TABFeature *poIndexFeature,
560
                      GBool bTestOpenNoError = FALSE);
561
    int OpenBaseTable(int nTableId, GBool bTestOpenNoError = FALSE);
562
    int OpenNextBaseTable(GBool bTestOpenNoError = FALSE);
563
    static GIntBig EncodeFeatureId(int nTableId, int nBaseFeatureId);
564
    static int ExtractBaseTableId(GIntBig nEncodedFeatureId);
565
    static int ExtractBaseFeatureId(GIntBig nEncodedFeatureId);
566
567
  public:
568
    explicit TABSeamless(GDALDataset *poDS);
569
    ~TABSeamless() override;
570
571
    TABFileClass GetFileClass() override
572
0
    {
573
0
        return TABFC_TABSeamless;
574
0
    }
575
576
    virtual int Open(const char *pszFname, const char *pszAccess,
577
                     GBool bTestOpenNoError = FALSE,
578
                     const char *pszCharset = nullptr) override
579
0
    {
580
0
        return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError,
581
0
                                  pszCharset);
582
0
    }
583
584
    virtual int Open(const char *pszFname, TABAccess eAccess,
585
                     GBool bTestOpenNoError = FALSE,
586
                     const char *pszCharset = nullptr) override;
587
    int Close() override;
588
589
    const char *GetTableName() override
590
0
    {
591
0
        return m_poFeatureDefnRef ? m_poFeatureDefnRef->GetName() : "";
592
0
    }
593
594
    virtual OGRErr ISetSpatialFilter(int iGeomField,
595
                                     const OGRGeometry *poGeom) override;
596
597
    void ResetReading() override;
598
    int TestCapability(const char *pszCap) const override;
599
    GIntBig GetFeatureCount(int bForce) override;
600
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
601
                      bool bForce) override;
602
603
    ///////////////
604
    // Read access specific stuff
605
    //
606
607
    GIntBig GetNextFeatureId(GIntBig nPrevId) override;
608
    TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
609
    const OGRFeatureDefn *GetLayerDefn() const override;
610
611
    TABFieldType GetNativeFieldType(int nFieldId) override;
612
613
    virtual int GetBounds(double &dXMin, double &dYMin, double &dXMax,
614
                          double &dYMax, GBool bForce = TRUE) override;
615
616
    const OGRSpatialReference *GetSpatialRef() const override;
617
618
    virtual int GetFeatureCountByType(int &numPoints, int &numLines,
619
                                      int &numRegions, int &numTexts,
620
                                      GBool bForce = TRUE) override;
621
622
    GBool IsFieldIndexed(int nFieldId) override;
623
    GBool IsFieldUnique(int nFieldId) override;
624
625
    ///////////////
626
    // Write access specific stuff
627
    //
628
    virtual int SetBounds(CPL_UNUSED double dXMin, CPL_UNUSED double dYMin,
629
                          CPL_UNUSED double dXMax,
630
                          CPL_UNUSED double dYMax) override
631
0
    {
632
0
        return -1;
633
0
    }
634
635
    virtual int SetFeatureDefn(
636
        CPL_UNUSED OGRFeatureDefn *poFeatureDefn,
637
        CPL_UNUSED TABFieldType *paeMapInfoNativeFieldTypes = nullptr) override
638
0
    {
639
0
        return -1;
640
0
    }
641
642
    virtual int AddFieldNative(CPL_UNUSED const char *pszName,
643
                               CPL_UNUSED TABFieldType eMapInfoType,
644
                               CPL_UNUSED int nWidth = 0,
645
                               CPL_UNUSED int nPrecision = 0,
646
                               CPL_UNUSED GBool bIndexed = FALSE,
647
                               CPL_UNUSED GBool bUnique = FALSE,
648
                               CPL_UNUSED int bApproxOK = TRUE) override
649
0
    {
650
0
        return -1;
651
0
    }
652
653
    virtual int
654
    SetSpatialRef(CPL_UNUSED OGRSpatialReference *poSpatialRef) override
655
0
    {
656
0
        return -1;
657
0
    }
658
659
    OGRErr CreateFeature(CPL_UNUSED TABFeature *poFeature) override
660
0
    {
661
0
        return OGRERR_UNSUPPORTED_OPERATION;
662
0
    }
663
664
    int SetFieldIndexed(CPL_UNUSED int nFieldId) override
665
0
    {
666
0
        return -1;
667
0
    }
668
669
    ///////////////
670
    // semi-private.
671
    int GetProjInfo(TABProjInfo *poPI) override
672
0
    {
673
0
        return m_poIndexTable ? m_poIndexTable->GetProjInfo(poPI) : -1;
674
0
    }
675
676
    int SetProjInfo(CPL_UNUSED TABProjInfo *poPI) override
677
0
    {
678
0
        return -1;
679
0
    }
680
681
    int SetMIFCoordSys(const char * /*pszMIFCoordSys*/) override
682
0
    {
683
0
        return -1;
684
0
    }
685
686
#ifdef DEBUG
687
    void Dump(FILE *fpOut = nullptr) override;
688
#endif
689
};
690
691
/*---------------------------------------------------------------------
692
 *                      class MIFFile
693
 *
694
 * The main class for (MID/MIF) datasets.  External programs should use this
695
 * class to open a (MID/MIF) dataset and read/write features from/to it.
696
 *
697
 *--------------------------------------------------------------------*/
698
class MIFFile final : public IMapInfoFile
699
{
700
    CPL_DISALLOW_COPY_ASSIGN(MIFFile)
701
702
  private:
703
    char *m_pszFname;
704
    TABAccess m_eAccessMode;
705
    int m_nVersion; /* Dataset version: 300, 450, 600, 900, etc. */
706
    char *m_pszDelimiter;
707
    char *m_pszUnique;
708
    char *m_pszIndex;
709
    char *m_pszCoordSys;
710
711
    TABFieldType *m_paeFieldType;
712
    GBool *m_pabFieldIndexed;
713
    GBool *m_pabFieldUnique;
714
715
    double m_dfXMultiplier;
716
    double m_dfYMultiplier;
717
    double m_dfXDisplacement;
718
    double m_dfYDisplacement;
719
720
    /* these are the projection bounds, possibly much broader than extents */
721
    double m_dXMin;
722
    double m_dYMin;
723
    double m_dXMax;
724
    double m_dYMax;
725
726
    /* extents, as cached by MIFFile::PreParseFile() */
727
    int m_bExtentsSet;
728
    OGREnvelope m_sExtents{};
729
730
    int m_nPoints;
731
    int m_nLines;
732
    int m_nRegions;
733
    int m_nTexts;
734
735
    int m_nPreloadedId;        // preloaded mif line is for this feature id
736
    MIDDATAFile *m_poMIDFile;  // Mid file
737
    MIDDATAFile *m_poMIFFile;  // Mif File
738
739
    OGRFeatureDefn *m_poDefn;
740
    mutable OGRSpatialReference *m_poSpatialRef;
741
742
    int m_nFeatureCount;
743
    int m_nWriteFeatureId;
744
    int m_nAttribute;
745
746
    ///////////////
747
    // Private Read access specific stuff
748
    //
749
    int ReadFeatureDefn();
750
    int ParseMIFHeader(int *pbIsEmpty);
751
    void PreParseFile();
752
    int AddFields(const char *pszLine);
753
    int GotoFeature(int nFeatureId);
754
755
    ///////////////
756
    // Private Write access specific stuff
757
    //
758
    GBool m_bPreParsed;
759
    GBool m_bHeaderWrote;
760
761
    int WriteMIFHeader();
762
    void UpdateExtents(double dfX, double dfY);
763
764
  public:
765
    explicit MIFFile(GDALDataset *poDS);
766
    ~MIFFile() override;
767
768
    TABFileClass GetFileClass() override
769
84
    {
770
84
        return TABFC_MIFFile;
771
84
    }
772
773
    virtual int Open(const char *pszFname, const char *pszAccess,
774
                     GBool bTestOpenNoError = FALSE,
775
                     const char *pszCharset = nullptr) override
776
0
    {
777
0
        return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError,
778
0
                                  pszCharset);
779
0
    }
780
781
    virtual int Open(const char *pszFname, TABAccess eAccess,
782
                     GBool bTestOpenNoError = FALSE,
783
                     const char *pszCharset = nullptr) override;
784
    int Close() override;
785
786
    const char *GetTableName() override
787
0
    {
788
0
        return m_poDefn ? m_poDefn->GetName() : "";
789
0
    }
790
791
    int TestCapability(const char *pszCap) const override;
792
    GIntBig GetFeatureCount(int bForce) override;
793
    void ResetReading() override;
794
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
795
                      bool bForce) override;
796
797
    ///////////////
798
    // Read access specific stuff
799
    //
800
801
    GIntBig GetNextFeatureId(GIntBig nPrevId) override;
802
    TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
803
    const OGRFeatureDefn *GetLayerDefn() const override;
804
805
    TABFieldType GetNativeFieldType(int nFieldId) override;
806
807
    virtual int GetBounds(double &dXMin, double &dYMin, double &dXMax,
808
                          double &dYMax, GBool bForce = TRUE) override;
809
810
    const OGRSpatialReference *GetSpatialRef() const override;
811
812
    virtual int GetFeatureCountByType(int &numPoints, int &numLines,
813
                                      int &numRegions, int &numTexts,
814
                                      GBool bForce = TRUE) override;
815
816
    GBool IsFieldIndexed(int nFieldId) override;
817
    GBool IsFieldUnique(int nFieldId) override;
818
819
    int GetVersion()
820
0
    {
821
0
        return m_nVersion;
822
0
    }
823
824
    ///////////////
825
    // Write access specific stuff
826
    //
827
    virtual int SetBounds(double dXMin, double dYMin, double dXMax,
828
                          double dYMax) override;
829
    virtual int
830
    SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
831
                   TABFieldType *paeMapInfoNativeFieldTypes = nullptr) override;
832
    virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
833
                               int nWidth = 0, int nPrecision = 0,
834
                               GBool bIndexed = FALSE, GBool bUnique = FALSE,
835
                               int bApproxOK = TRUE) override;
836
    /* TODO */
837
    int SetSpatialRef(OGRSpatialReference *poSpatialRef) override;
838
839
    OGRErr CreateFeature(TABFeature *poFeature) override;
840
841
    int SetFieldIndexed(int nFieldId) override;
842
843
    ///////////////
844
    // semi-private.
845
    int GetProjInfo(TABProjInfo * /*poPI*/) override
846
0
    {
847
0
        return -1;
848
0
    }
849
850
    /*  { return m_poMAPFile->GetHeaderBlock()->GetProjInfo( poPI ); }*/
851
    int SetProjInfo(TABProjInfo * /*poPI*/) override
852
0
    {
853
0
        return -1;
854
0
    }
855
856
    /*  { return m_poMAPFile->GetHeaderBlock()->SetProjInfo( poPI ); }*/
857
    int SetMIFCoordSys(const char *pszMIFCoordSys) override;
858
    int SetCharset(const char *pszCharset) override;
859
    void SetStrictLaundering(bool bStrictLaundering) override;
860
#ifdef DEBUG
861
    void Dump(FILE * /*fpOut*/ = nullptr) override
862
    {
863
    }
864
#endif
865
};
866
867
/*---------------------------------------------------------------------
868
 * Define some error codes specific to this lib.
869
 *--------------------------------------------------------------------*/
870
18
#define TAB_WarningFeatureTypeNotSupported 501
871
7.33k
#define TAB_WarningInvalidFieldName 502
872
162
#define TAB_WarningBoundsOverflow 503
873
874
/*---------------------------------------------------------------------
875
 * Codes for the feature classes
876
 *--------------------------------------------------------------------*/
877
typedef enum
878
{
879
    TABFCNoGeomFeature = 0,
880
    TABFCPoint = 1,
881
    TABFCFontPoint = 2,
882
    TABFCCustomPoint = 3,
883
    TABFCText = 4,
884
    TABFCPolyline = 5,
885
    TABFCArc = 6,
886
    TABFCRegion = 7,
887
    TABFCRectangle = 8,
888
    TABFCEllipse = 9,
889
    TABFCMultiPoint = 10,
890
    TABFCCollection = 11,
891
    TABFCDebugFeature
892
} TABFeatureClass;
893
894
/*---------------------------------------------------------------------
895
 * Definitions for text attributes
896
 *--------------------------------------------------------------------*/
897
typedef enum TABTextJust_t
898
{
899
    TABTJLeft = 0,  // Default: Left Justification
900
    TABTJCenter,
901
    TABTJRight
902
} TABTextJust;
903
904
typedef enum TABTextSpacing_t
905
{
906
    TABTSSingle = 0,  // Default: Single spacing
907
    TABTS1_5,         // 1.5
908
    TABTSDouble
909
} TABTextSpacing;
910
911
typedef enum TABTextLineType_t
912
{
913
    TABTLNoLine = 0,  // Default: No line
914
    TABTLSimple,
915
    TABTLArrow
916
} TABTextLineType;
917
918
typedef enum TABFontStyle_t  // Can be OR'ed
919
{                            // except box and halo are mutually exclusive
920
    TABFSNone = 0,
921
    TABFSBold = 0x0001,
922
    TABFSItalic = 0x0002,
923
    TABFSUnderline = 0x0004,
924
    TABFSStrikeout = 0x0008,
925
    TABFSOutline = 0x0010,
926
    TABFSShadow = 0x0020,
927
    TABFSInverse = 0x0040,
928
    TABFSBlink = 0x0080,
929
    TABFSBox = 0x0100,      // See note about box vs halo below.
930
    TABFSHalo = 0x0200,     // MIF uses 256, see MIF docs, App.A
931
    TABFSAllCaps = 0x0400,  // MIF uses 512
932
    TABFSExpanded = 0x0800  // MIF uses 1024
933
} TABFontStyle;
934
935
/* TABFontStyle enum notes:
936
 *
937
 * The enumeration values above correspond to the values found in a .MAP
938
 * file. However, they differ a little from what is found in a MIF file:
939
 * Values 0x01 to 0x80 are the same in .MIF and .MAP files.
940
 * Values 0x200 to 0x800 in .MAP are 0x100 to 0x400 in .MIF
941
 *
942
 * What about TABFSBox (0x100) ?
943
 * TABFSBox is stored just like the other styles in .MAP files but it is not
944
 * explicitly stored in a MIF file.
945
 * If a .MIF FONT() clause contains the optional BG color, then this implies
946
 * that either Halo or Box was set.  Thus if TABFSHalo (value 256 in MIF)
947
 * is not set in the style, then this implies that TABFSBox should be set.
948
 */
949
950
typedef enum TABCustSymbStyle_t  // Can be OR'ed
951
{
952
    TABCSNone = 0,          // Transparent BG, use default colors
953
    TABCSBGOpaque = 0x01,   // White pixels are opaque
954
    TABCSApplyColor = 0x02  // non-white pixels drawn using symbol color
955
} TABCustSymbStyle;
956
957
/*=====================================================================
958
  Base classes to be used to add supported drawing tools to each feature type
959
 =====================================================================*/
960
961
class ITABFeaturePen /* non final */
962
{
963
  protected:
964
    int m_nPenDefIndex;
965
    TABPenDef m_sPenDef;
966
967
  public:
968
    ITABFeaturePen();
969
970
    virtual ~ITABFeaturePen();
971
972
    int GetPenDefIndex() const
973
0
    {
974
0
        return m_nPenDefIndex;
975
0
    }
976
977
    TABPenDef *GetPenDefRef()
978
0
    {
979
0
        return &m_sPenDef;
980
0
    }
981
982
    const TABPenDef *GetPenDefRef() const
983
0
    {
984
0
        return &m_sPenDef;
985
0
    }
986
987
    GByte GetPenWidthPixel() const;
988
    double GetPenWidthPoint() const;
989
    int GetPenWidthMIF() const;
990
991
    GByte GetPenPattern() const
992
370
    {
993
370
        return m_sPenDef.nLinePattern;
994
370
    }
995
996
    GInt32 GetPenColor() const
997
185
    {
998
185
        return m_sPenDef.rgbColor;
999
185
    }
1000
1001
    void SetPenWidthPixel(GByte val);
1002
    void SetPenWidthPoint(double val);
1003
    void SetPenWidthMIF(int val);
1004
1005
    void SetPenPattern(GByte val)
1006
48.9k
    {
1007
48.9k
        m_sPenDef.nLinePattern = val;
1008
48.9k
    }
1009
1010
    void SetPenColor(GInt32 clr)
1011
48.9k
    {
1012
48.9k
        m_sPenDef.rgbColor = clr;
1013
48.9k
    }
1014
1015
    const char *GetPenStyleString() const;
1016
    void SetPenFromStyleString(const char *pszStyleString);
1017
1018
    void DumpPenDef(FILE *fpOut = nullptr);
1019
};
1020
1021
class ITABFeatureBrush /* non final */
1022
{
1023
  protected:
1024
    int m_nBrushDefIndex;
1025
    TABBrushDef m_sBrushDef;
1026
1027
  public:
1028
    ITABFeatureBrush();
1029
1030
    virtual ~ITABFeatureBrush();
1031
1032
    int GetBrushDefIndex() const
1033
0
    {
1034
0
        return m_nBrushDefIndex;
1035
0
    }
1036
1037
    TABBrushDef *GetBrushDefRef()
1038
0
    {
1039
0
        return &m_sBrushDef;
1040
0
    }
1041
1042
    const TABBrushDef *GetBrushDefRef() const
1043
0
    {
1044
0
        return &m_sBrushDef;
1045
0
    }
1046
1047
    GInt32 GetBrushFGColor() const
1048
40
    {
1049
40
        return m_sBrushDef.rgbFGColor;
1050
40
    }
1051
1052
    GInt32 GetBrushBGColor() const
1053
40
    {
1054
40
        return m_sBrushDef.rgbBGColor;
1055
40
    }
1056
1057
    GByte GetBrushPattern() const
1058
80
    {
1059
80
        return m_sBrushDef.nFillPattern;
1060
80
    }
1061
1062
    GByte GetBrushTransparent() const
1063
40
    {
1064
40
        return m_sBrushDef.bTransparentFill;
1065
40
    }
1066
1067
    void SetBrushFGColor(GInt32 clr)
1068
39.7k
    {
1069
39.7k
        m_sBrushDef.rgbFGColor = clr;
1070
39.7k
    }
1071
1072
    void SetBrushBGColor(GInt32 clr)
1073
30.3k
    {
1074
30.3k
        m_sBrushDef.rgbBGColor = clr;
1075
30.3k
    }
1076
1077
    void SetBrushPattern(GByte val)
1078
39.7k
    {
1079
39.7k
        m_sBrushDef.nFillPattern = val;
1080
39.7k
    }
1081
1082
    void SetBrushTransparent(GByte val)
1083
9.43k
    {
1084
9.43k
        m_sBrushDef.bTransparentFill = val;
1085
9.43k
    }
1086
1087
    const char *GetBrushStyleString() const;
1088
    void SetBrushFromStyleString(const char *pszStyleString);
1089
1090
    void DumpBrushDef(FILE *fpOut = nullptr);
1091
};
1092
1093
class ITABFeatureFont /* non final */
1094
{
1095
  protected:
1096
    int m_nFontDefIndex;
1097
    TABFontDef m_sFontDef;
1098
1099
  public:
1100
    ITABFeatureFont();
1101
1102
    virtual ~ITABFeatureFont();
1103
1104
    int GetFontDefIndex() const
1105
0
    {
1106
0
        return m_nFontDefIndex;
1107
0
    }
1108
1109
    TABFontDef *GetFontDefRef()
1110
0
    {
1111
0
        return &m_sFontDef;
1112
0
    }
1113
1114
    const TABFontDef *GetFontDefRef() const
1115
0
    {
1116
0
        return &m_sFontDef;
1117
0
    }
1118
1119
    const char *GetFontNameRef() const
1120
0
    {
1121
0
        return m_sFontDef.szFontName;
1122
0
    }
1123
1124
    void SetFontName(const char *pszName);
1125
1126
    void DumpFontDef(FILE *fpOut = nullptr);
1127
};
1128
1129
class ITABFeatureSymbol /* non final */
1130
{
1131
  protected:
1132
    int m_nSymbolDefIndex;
1133
    TABSymbolDef m_sSymbolDef;
1134
1135
  public:
1136
    ITABFeatureSymbol();
1137
1138
121k
    virtual ~ITABFeatureSymbol() = default;
1139
1140
    int GetSymbolDefIndex() const
1141
0
    {
1142
0
        return m_nSymbolDefIndex;
1143
0
    }
1144
1145
    TABSymbolDef *GetSymbolDefRef()
1146
6
    {
1147
6
        return &m_sSymbolDef;
1148
6
    }
1149
1150
    const TABSymbolDef *GetSymbolDefRef() const
1151
0
    {
1152
0
        return &m_sSymbolDef;
1153
0
    }
1154
1155
    GInt16 GetSymbolNo() const
1156
10
    {
1157
10
        return m_sSymbolDef.nSymbolNo;
1158
10
    }
1159
1160
    GInt16 GetSymbolSize() const
1161
10
    {
1162
10
        return m_sSymbolDef.nPointSize;
1163
10
    }
1164
1165
    GInt32 GetSymbolColor() const
1166
10
    {
1167
10
        return m_sSymbolDef.rgbColor;
1168
10
    }
1169
1170
    void SetSymbolNo(GInt16 val)
1171
17.9k
    {
1172
17.9k
        m_sSymbolDef.nSymbolNo = val;
1173
17.9k
    }
1174
1175
    void SetSymbolSize(GInt16 val)
1176
28.8k
    {
1177
28.8k
        m_sSymbolDef.nPointSize = val;
1178
28.8k
    }
1179
1180
    void SetSymbolColor(GInt32 clr)
1181
28.8k
    {
1182
28.8k
        m_sSymbolDef.rgbColor = clr;
1183
28.8k
    }
1184
1185
    static TABFeatureClass GetSymbolFeatureClass(const char *pszStyleString);
1186
    virtual const char *GetSymbolStyleString(double dfAngle = 0.0) const;
1187
    void SetSymbolFromStyleString(const char *pszStyleString);
1188
    virtual void SetSymbolFromStyle(OGRStyleSymbol *poSymbolStyle);
1189
1190
    void DumpSymbolDef(FILE *fpOut = nullptr);
1191
};
1192
1193
/*=====================================================================
1194
                        Feature Classes
1195
 =====================================================================*/
1196
1197
/*---------------------------------------------------------------------
1198
 *                      class TABFeature
1199
 *
1200
 * Extend the OGRFeature to support MapInfo specific extensions related
1201
 * to geometry types, representation strings, etc.
1202
 *
1203
 * TABFeature will be used as a base class for all the feature classes.
1204
 *
1205
 * This class will also be used to instantiate objects with no Geometry
1206
 * (i.e. type TAB_GEOM_NONE) which is a valid case in MapInfo.
1207
 *
1208
 * The logic to read/write the object from/to the .DAT and .MAP files is also
1209
 * implemented as part of this class and derived classes.
1210
 *--------------------------------------------------------------------*/
1211
class TABFeature /* non final*/ : public OGRFeature
1212
{
1213
  protected:
1214
    TABGeomType m_nMapInfoType;
1215
1216
    double m_dXMin;
1217
    double m_dYMin;
1218
    double m_dXMax;
1219
    double m_dYMax;
1220
1221
    GBool m_bDeletedFlag;
1222
1223
    void CopyTABFeatureBase(TABFeature *poDestFeature);
1224
1225
    // Compr. Origin is set for TAB files by ValidateCoordType()
1226
    GInt32 m_nXMin;
1227
    GInt32 m_nYMin;
1228
    GInt32 m_nXMax;
1229
    GInt32 m_nYMax;
1230
    GInt32 m_nComprOrgX;
1231
    GInt32 m_nComprOrgY;
1232
1233
    virtual int UpdateMBR(TABMAPFile *poMapFile = nullptr);
1234
1235
  public:
1236
    explicit TABFeature(const OGRFeatureDefn *poDefnIn);
1237
    ~TABFeature() override;
1238
1239
    static TABFeature *CreateFromMapInfoType(int nMapInfoType,
1240
                                             OGRFeatureDefn *poDefn);
1241
1242
    virtual TABFeature *
1243
    CloneTABFeature(const OGRFeatureDefn *pNewDefn = nullptr);
1244
1245
    virtual TABFeatureClass GetFeatureClass()
1246
372k
    {
1247
372k
        return TABFCNoGeomFeature;
1248
372k
    }
1249
1250
    virtual TABGeomType GetMapInfoType()
1251
0
    {
1252
0
        return m_nMapInfoType;
1253
0
    }
1254
1255
    virtual TABGeomType
1256
    ValidateMapInfoType(CPL_UNUSED TABMAPFile *poMapFile = nullptr)
1257
343k
    {
1258
343k
        m_nMapInfoType = TAB_GEOM_NONE;
1259
343k
        return m_nMapInfoType;
1260
343k
    }
1261
1262
    GBool IsRecordDeleted()
1263
0
    {
1264
0
        return m_bDeletedFlag;
1265
0
    }
1266
1267
    void SetRecordDeleted(GBool bDeleted)
1268
28.0k
    {
1269
28.0k
        m_bDeletedFlag = bDeleted;
1270
28.0k
    }
1271
1272
    /*-----------------------------------------------------------------
1273
     * TAB Support
1274
     *----------------------------------------------------------------*/
1275
1276
    virtual int ReadRecordFromDATFile(TABDATFile *poDATFile);
1277
    virtual int
1278
    ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1279
                            GBool bCoordDataOnly = FALSE,
1280
                            TABMAPCoordBlock **ppoCoordBlock = nullptr);
1281
1282
    virtual int WriteRecordToDATFile(TABDATFile *poDATFile,
1283
                                     TABINDFile *poINDFile, int *panIndexNo);
1284
    virtual int
1285
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1286
                           GBool bCoordDataOnly = FALSE,
1287
                           TABMAPCoordBlock **ppoCoordBlock = nullptr);
1288
    GBool ValidateCoordType(TABMAPFile *poMapFile);
1289
    void ForceCoordTypeAndOrigin(TABGeomType nMapInfoType, GBool bCompr,
1290
                                 GInt32 nComprOrgX, GInt32 nComprOrgY,
1291
                                 GInt32 nXMin, GInt32 nYMin, GInt32 nXMax,
1292
                                 GInt32 nYMax);
1293
1294
    /*-----------------------------------------------------------------
1295
     * Mid/Mif Support
1296
     *----------------------------------------------------------------*/
1297
1298
    virtual int ReadRecordFromMIDFile(MIDDATAFile *fp);
1299
    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
1300
1301
    virtual int WriteRecordToMIDFile(MIDDATAFile *fp);
1302
    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
1303
1304
    void ReadMIFParameters(MIDDATAFile *fp);
1305
    void WriteMIFParameters(MIDDATAFile *fp);
1306
1307
    /*-----------------------------------------------------------------
1308
     *----------------------------------------------------------------*/
1309
1310
    void SetMBR(double dXMin, double dYMin, double dXMax, double dYMax);
1311
    void GetMBR(double &dXMin, double &dYMin, double &dXMax, double &dYMax);
1312
    void SetIntMBR(GInt32 nXMin, GInt32 nYMin, GInt32 nXMax, GInt32 nYMax);
1313
    void GetIntMBR(GInt32 &nXMin, GInt32 &nYMin, GInt32 &nXMax, GInt32 &nYMax);
1314
1315
    virtual void DumpMID(FILE *fpOut = nullptr);
1316
    virtual void DumpMIF(FILE *fpOut = nullptr);
1317
};
1318
1319
/*---------------------------------------------------------------------
1320
 *                      class TABPoint
1321
 *
1322
 * Feature class to handle old style MapInfo point symbols:
1323
 *
1324
 *     TAB_GEOM_SYMBOL_C        0x01
1325
 *     TAB_GEOM_SYMBOL          0x02
1326
 *
1327
 * Feature geometry will be a OGRPoint
1328
 *
1329
 * The symbol number is in the range [31..67], with 31=None and corresponds
1330
 * to one of the 35 predefined "Old MapInfo Symbols"
1331
 *
1332
 * NOTE: This class is also used as a base class for the other point
1333
 * symbol types TABFontPoint and TABCustomPoint.
1334
 *--------------------------------------------------------------------*/
1335
class TABPoint : public TABFeature, public ITABFeatureSymbol
1336
{
1337
    CPL_DISALLOW_COPY_ASSIGN(TABPoint)
1338
1339
  public:
1340
    explicit TABPoint(const OGRFeatureDefn *poDefnIn);
1341
    ~TABPoint() override;
1342
1343
    TABFeatureClass GetFeatureClass() override
1344
34.8k
    {
1345
34.8k
        return TABFCPoint;
1346
34.8k
    }
1347
1348
    virtual TABGeomType
1349
    ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1350
1351
    virtual TABFeature *
1352
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
1353
1354
    double GetX();
1355
    double GetY();
1356
1357
    virtual int ReadGeometryFromMAPFile(
1358
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
1359
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1360
    virtual int
1361
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1362
                           GBool bCoordDataOnly = FALSE,
1363
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1364
1365
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1366
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1367
1368
    const char *GetStyleString() const override;
1369
1370
    void DumpMIF(FILE *fpOut = nullptr) override;
1371
};
1372
1373
/*---------------------------------------------------------------------
1374
 *                      class TABFontPoint
1375
 *
1376
 * Feature class to handle MapInfo Font Point Symbol types:
1377
 *
1378
 *     TAB_GEOM_FONTSYMBOL_C    0x28
1379
 *     TAB_GEOM_FONTSYMBOL      0x29
1380
 *
1381
 * Feature geometry will be a OGRPoint
1382
 *
1383
 * The symbol number refers to a character code in the specified Windows
1384
 * Font (e.g. "Windings").
1385
 *--------------------------------------------------------------------*/
1386
class TABFontPoint final : public TABPoint, public ITABFeatureFont
1387
{
1388
    CPL_DISALLOW_COPY_ASSIGN(TABFontPoint)
1389
1390
  protected:
1391
    double m_dAngle;
1392
    GInt16 m_nFontStyle;  // Bold/shadow/halo/etc.
1393
1394
  public:
1395
    explicit TABFontPoint(const OGRFeatureDefn *poDefnIn);
1396
    ~TABFontPoint() override;
1397
1398
    TABFeatureClass GetFeatureClass() override
1399
15.0k
    {
1400
15.0k
        return TABFCFontPoint;
1401
15.0k
    }
1402
1403
    virtual TABFeature *
1404
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
1405
1406
    virtual int ReadGeometryFromMAPFile(
1407
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
1408
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1409
    virtual int
1410
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1411
                           GBool bCoordDataOnly = FALSE,
1412
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1413
1414
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1415
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1416
1417
    virtual const char *
1418
    GetSymbolStyleString(double dfAngle = 0.0) const override;
1419
    const char *GetStyleString() const override;
1420
    void SetSymbolFromStyle(OGRStyleSymbol *poSymbolStyle) override;
1421
1422
    GBool QueryFontStyle(TABFontStyle eStyleToQuery);
1423
    void ToggleFontStyle(TABFontStyle eStyleToToggle, GBool bStatus);
1424
1425
    int GetFontStyleMIFValue();
1426
    void SetFontStyleMIFValue(int nStyle);
1427
1428
    int GetFontStyleTABValue()
1429
0
    {
1430
0
        return m_nFontStyle;
1431
0
    }
1432
1433
    void SetFontStyleTABValue(int nStyle)
1434
0
    {
1435
0
        m_nFontStyle = static_cast<GInt16>(nStyle);
1436
0
    }
1437
1438
    // GetSymbolAngle(): Return angle in degrees counterclockwise
1439
    double GetSymbolAngle() const
1440
0
    {
1441
0
        return m_dAngle;
1442
0
    }
1443
1444
    void SetSymbolAngle(double dAngle);
1445
};
1446
1447
/*---------------------------------------------------------------------
1448
 *                      class TABCustomPoint
1449
 *
1450
 * Feature class to handle MapInfo Custom Point Symbol (Bitmap) types:
1451
 *
1452
 *     TAB_GEOM_CUSTOMSYMBOL_C  0x2b
1453
 *     TAB_GEOM_CUSTOMSYMBOL    0x2c
1454
 *
1455
 * Feature geometry will be a OGRPoint
1456
 *
1457
 * The symbol name is the name of a BMP file stored in the "CustSymb"
1458
 * directory (e.g. "arrow.BMP").  The symbol number has no meaning for
1459
 * this symbol type.
1460
 *--------------------------------------------------------------------*/
1461
class TABCustomPoint final : public TABPoint, public ITABFeatureFont
1462
{
1463
  protected:
1464
    GByte m_nCustomStyle;  // Show BG/Apply Color
1465
1466
  public:
1467
    GByte m_nUnknown_;
1468
1469
  public:
1470
    explicit TABCustomPoint(const OGRFeatureDefn *poDefnIn);
1471
    ~TABCustomPoint() override;
1472
1473
    TABFeatureClass GetFeatureClass() override
1474
10.9k
    {
1475
10.9k
        return TABFCCustomPoint;
1476
10.9k
    }
1477
1478
    virtual TABFeature *
1479
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
1480
1481
    virtual int ReadGeometryFromMAPFile(
1482
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
1483
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1484
    virtual int
1485
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1486
                           GBool bCoordDataOnly = FALSE,
1487
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1488
1489
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1490
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1491
1492
    virtual const char *
1493
    GetSymbolStyleString(double dfAngle = 0.0) const override;
1494
    const char *GetStyleString() const override;
1495
    void SetSymbolFromStyle(OGRStyleSymbol *poSymbolStyle) override;
1496
1497
    const char *GetSymbolNameRef() const
1498
0
    {
1499
0
        return GetFontNameRef();
1500
0
    }
1501
1502
    void SetSymbolName(const char *pszName)
1503
0
    {
1504
0
        SetFontName(pszName);
1505
0
    }
1506
1507
    GByte GetCustomSymbolStyle()
1508
0
    {
1509
0
        return m_nCustomStyle;
1510
0
    }
1511
1512
    void SetCustomSymbolStyle(GByte nStyle)
1513
0
    {
1514
0
        m_nCustomStyle = nStyle;
1515
0
    }
1516
};
1517
1518
/*---------------------------------------------------------------------
1519
 *                      class TABPolyline
1520
 *
1521
 * Feature class to handle the various MapInfo line types:
1522
 *
1523
 *     TAB_GEOM_LINE_C         0x04
1524
 *     TAB_GEOM_LINE           0x05
1525
 *     TAB_GEOM_PLINE_C        0x07
1526
 *     TAB_GEOM_PLINE          0x08
1527
 *     TAB_GEOM_MULTIPLINE_C   0x25
1528
 *     TAB_GEOM_MULTIPLINE     0x26
1529
 *     TAB_GEOM_V450_MULTIPLINE_C 0x31
1530
 *     TAB_GEOM_V450_MULTIPLINE   0x32
1531
 *
1532
 * Feature geometry can be either a OGRLineString or a OGRMultiLineString
1533
 *--------------------------------------------------------------------*/
1534
class TABPolyline final : public TABFeature, public ITABFeaturePen
1535
{
1536
  private:
1537
    GBool m_bCenterIsSet;
1538
    double m_dCenterX;
1539
    double m_dCenterY;
1540
    GBool m_bWriteTwoPointLineAsPolyline;
1541
1542
  public:
1543
    explicit TABPolyline(const OGRFeatureDefn *poDefnIn);
1544
    ~TABPolyline() override;
1545
1546
    TABFeatureClass GetFeatureClass() override
1547
54.9k
    {
1548
54.9k
        return TABFCPolyline;
1549
54.9k
    }
1550
1551
    virtual TABGeomType
1552
    ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1553
1554
    virtual TABFeature *
1555
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
1556
1557
    /* 2 methods to simplify access to rings in a multiple polyline
1558
     */
1559
    int GetNumParts();
1560
    OGRLineString *GetPartRef(int nPartIndex);
1561
1562
    GBool TwoPointLineAsPolyline();
1563
    void TwoPointLineAsPolyline(GBool bTwoPointLineAsPolyline);
1564
1565
    virtual int ReadGeometryFromMAPFile(
1566
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
1567
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1568
    virtual int
1569
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1570
                           GBool bCoordDataOnly = FALSE,
1571
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1572
1573
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1574
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1575
1576
    const char *GetStyleString() const override;
1577
1578
    void DumpMIF(FILE *fpOut = nullptr) override;
1579
1580
    int GetCenter(double &dX, double &dY);
1581
    void SetCenter(double dX, double dY);
1582
1583
    // MapInfo-specific attributes... made available through public vars
1584
    // for now.
1585
    GBool m_bSmooth;
1586
};
1587
1588
/*---------------------------------------------------------------------
1589
 *                      class TABRegion
1590
 *
1591
 * Feature class to handle the MapInfo region types:
1592
 *
1593
 *     TAB_GEOM_REGION_C         0x0d
1594
 *     TAB_GEOM_REGION           0x0e
1595
 *     TAB_GEOM_V450_REGION_C    0x2e
1596
 *     TAB_GEOM_V450_REGION      0x2f
1597
 *
1598
 * Feature geometry will be returned as OGRPolygon (with a single ring)
1599
 * or OGRMultiPolygon (for multiple rings).
1600
 *
1601
 * REGIONs with multiple rings are returned as OGRMultiPolygon instead of
1602
 * as OGRPolygons since OGRPolygons require that the first ring be the
1603
 * outer ring, and the other all be inner rings, but this is not guaranteed
1604
 * inside MapInfo files.  However, when writing features, OGRPolygons with
1605
 * multiple rings will be accepted without problem.
1606
 *--------------------------------------------------------------------*/
1607
class TABRegion final : public TABFeature,
1608
                        public ITABFeaturePen,
1609
                        public ITABFeatureBrush
1610
{
1611
  private:
1612
    GBool m_bSmooth;
1613
    GBool m_bCenterIsSet;
1614
    double m_dCenterX;
1615
    double m_dCenterY;
1616
1617
    int ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs, TABMAPFile *poMAPFile);
1618
    static int AppendSecHdrs(OGRPolygon *poPolygon,
1619
                             TABMAPCoordSecHdr *&pasSecHdrs,
1620
                             TABMAPFile *poMAPFile, int &iLastRing);
1621
1622
  public:
1623
    explicit TABRegion(const OGRFeatureDefn *poDefnIn);
1624
    ~TABRegion() override;
1625
1626
    TABFeatureClass GetFeatureClass() override
1627
164k
    {
1628
164k
        return TABFCRegion;
1629
164k
    }
1630
1631
    virtual TABGeomType
1632
    ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1633
1634
    virtual TABFeature *
1635
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
1636
1637
    /* 2 methods to make the REGION's geometry look like a single collection
1638
     * of OGRLinearRings
1639
     */
1640
    int GetNumRings();
1641
    OGRLinearRing *GetRingRef(int nRequestedRingIndex);
1642
    GBool IsInteriorRing(int nRequestedRingIndex);
1643
1644
    virtual int ReadGeometryFromMAPFile(
1645
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
1646
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1647
    virtual int
1648
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1649
                           GBool bCoordDataOnly = FALSE,
1650
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1651
1652
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1653
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1654
1655
    const char *GetStyleString() const override;
1656
1657
    void DumpMIF(FILE *fpOut = nullptr) override;
1658
1659
    int GetCenter(double &dX, double &dY);
1660
    void SetCenter(double dX, double dY);
1661
};
1662
1663
/*---------------------------------------------------------------------
1664
 *                      class TABRectangle
1665
 *
1666
 * Feature class to handle the MapInfo rectangle types:
1667
 *
1668
 *     TAB_GEOM_RECT_C         0x13
1669
 *     TAB_GEOM_RECT           0x14
1670
 *     TAB_GEOM_ROUNDRECT_C    0x16
1671
 *     TAB_GEOM_ROUNDRECT      0x17
1672
 *
1673
 * A rectangle is defined by the coords of its 2 opposite corners (the MBR)
1674
 * Its corners can optionally be rounded, in which case a X and Y rounding
1675
 * radius will be defined.
1676
 *
1677
 * Feature geometry will be OGRPolygon
1678
 *--------------------------------------------------------------------*/
1679
class TABRectangle final : public TABFeature,
1680
                           public ITABFeaturePen,
1681
                           public ITABFeatureBrush
1682
{
1683
  private:
1684
    int UpdateMBR(TABMAPFile *poMapFile = nullptr) override;
1685
1686
  public:
1687
    explicit TABRectangle(const OGRFeatureDefn *poDefnIn);
1688
    ~TABRectangle() override;
1689
1690
    TABFeatureClass GetFeatureClass() override
1691
49.9k
    {
1692
49.9k
        return TABFCRectangle;
1693
49.9k
    }
1694
1695
    virtual TABGeomType
1696
    ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1697
1698
    virtual TABFeature *
1699
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
1700
1701
    virtual int ReadGeometryFromMAPFile(
1702
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
1703
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1704
    virtual int
1705
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1706
                           GBool bCoordDataOnly = FALSE,
1707
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1708
1709
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1710
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1711
1712
    const char *GetStyleString() const override;
1713
1714
    void DumpMIF(FILE *fpOut = nullptr) override;
1715
1716
    // MapInfo-specific attributes... made available through public vars
1717
    // for now.
1718
    GBool m_bRoundCorners;
1719
    double m_dRoundXRadius;
1720
    double m_dRoundYRadius;
1721
};
1722
1723
/*---------------------------------------------------------------------
1724
 *                      class TABEllipse
1725
 *
1726
 * Feature class to handle the MapInfo ellipse types:
1727
 *
1728
 *     TAB_GEOM_ELLIPSE_C      0x19
1729
 *     TAB_GEOM_ELLIPSE        0x1a
1730
 *
1731
 * An ellipse is defined by the coords of its 2 opposite corners (the MBR)
1732
 *
1733
 * Feature geometry can be either an OGRPoint defining the center of the
1734
 * ellipse, or an OGRPolygon defining the ellipse itself.
1735
 *
1736
 * When an ellipse is read, the returned geometry is a OGRPolygon representing
1737
 * the ellipse with 2 degrees line segments.
1738
 *
1739
 * In the case of the OGRPoint, then the X/Y Radius MUST be set, but.
1740
 * However with an OGRPolygon, if the X/Y radius are not set (== 0) then
1741
 * the MBR of the polygon will be used to define the ellipse parameters
1742
 * and the center of the MBR is used as the center of the ellipse...
1743
 * (i.e. the polygon vertices themselves will be ignored).
1744
 *--------------------------------------------------------------------*/
1745
class TABEllipse final : public TABFeature,
1746
                         public ITABFeaturePen,
1747
                         public ITABFeatureBrush
1748
{
1749
  private:
1750
    int UpdateMBR(TABMAPFile *poMapFile = nullptr) override;
1751
1752
  public:
1753
    explicit TABEllipse(const OGRFeatureDefn *poDefnIn);
1754
    ~TABEllipse() override;
1755
1756
    TABFeatureClass GetFeatureClass() override
1757
17.0k
    {
1758
17.0k
        return TABFCEllipse;
1759
17.0k
    }
1760
1761
    virtual TABGeomType
1762
    ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1763
1764
    virtual TABFeature *
1765
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
1766
1767
    virtual int ReadGeometryFromMAPFile(
1768
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
1769
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1770
    virtual int
1771
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1772
                           GBool bCoordDataOnly = FALSE,
1773
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1774
1775
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1776
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1777
1778
    const char *GetStyleString() const override;
1779
1780
    void DumpMIF(FILE *fpOut = nullptr) override;
1781
1782
    // MapInfo-specific attributes... made available through public vars
1783
    // for now.
1784
    double m_dCenterX;
1785
    double m_dCenterY;
1786
    double m_dXRadius;
1787
    double m_dYRadius;
1788
};
1789
1790
/*---------------------------------------------------------------------
1791
 *                      class TABArc
1792
 *
1793
 * Feature class to handle the MapInfo arc types:
1794
 *
1795
 *     TAB_GEOM_ARC_C      0x0a
1796
 *     TAB_GEOM_ARC        0x0b
1797
 *
1798
 * In MapInfo, an arc is defined by the coords of the MBR corners of its
1799
 * defining ellipse, which in this case is different from the arc's MBR,
1800
 * and a start and end angle in degrees.
1801
 *
1802
 * Feature geometry can be either an OGRLineString or an OGRPoint.
1803
 *
1804
 * In any case, X/Y radius X/Y center, and start/end angle (in degrees
1805
 * counterclockwise) MUST be set.
1806
 *
1807
 * When an arc is read, the returned geometry is an OGRLineString
1808
 * representing the arc with 2 degrees line segments.
1809
 *--------------------------------------------------------------------*/
1810
class TABArc final : public TABFeature, public ITABFeaturePen
1811
{
1812
  private:
1813
    double m_dStartAngle;  // In degrees, counterclockwise,
1814
    double m_dEndAngle;    // starting at 3 o'clock
1815
1816
    int UpdateMBR(TABMAPFile *poMapFile = nullptr) override;
1817
1818
  public:
1819
    explicit TABArc(const OGRFeatureDefn *poDefnIn);
1820
    ~TABArc() override;
1821
1822
    TABFeatureClass GetFeatureClass() override
1823
32.6k
    {
1824
32.6k
        return TABFCArc;
1825
32.6k
    }
1826
1827
    virtual TABGeomType
1828
    ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1829
1830
    virtual TABFeature *
1831
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
1832
1833
    virtual int ReadGeometryFromMAPFile(
1834
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
1835
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1836
    virtual int
1837
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1838
                           GBool bCoordDataOnly = FALSE,
1839
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1840
1841
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1842
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1843
1844
    const char *GetStyleString() const override;
1845
1846
    void DumpMIF(FILE *fpOut = nullptr) override;
1847
1848
    double GetStartAngle()
1849
0
    {
1850
0
        return m_dStartAngle;
1851
0
    }
1852
1853
    double GetEndAngle()
1854
0
    {
1855
0
        return m_dEndAngle;
1856
0
    }
1857
1858
    void SetStartAngle(double dAngle);
1859
    void SetEndAngle(double dAngle);
1860
1861
    // MapInfo-specific attributes... made available through public vars
1862
    // for now.
1863
    double m_dCenterX;
1864
    double m_dCenterY;
1865
    double m_dXRadius;
1866
    double m_dYRadius;
1867
};
1868
1869
/*---------------------------------------------------------------------
1870
 *                      class TABText
1871
 *
1872
 * Feature class to handle the MapInfo text types:
1873
 *
1874
 *     TAB_GEOM_TEXT_C         0x10
1875
 *     TAB_GEOM_TEXT           0x11
1876
 *
1877
 * Feature geometry is an OGRPoint corresponding to the lower-left
1878
 * corner of the text MBR BEFORE ROTATION.
1879
 *
1880
 * Text string, and box height/width (box before rotation is applied)
1881
 * are required in a valid text feature and MUST be set.
1882
 * Text angle and other styles are optional.
1883
 *--------------------------------------------------------------------*/
1884
class TABText final : public TABFeature,
1885
                      public ITABFeatureFont,
1886
                      public ITABFeaturePen
1887
{
1888
    CPL_DISALLOW_COPY_ASSIGN(TABText)
1889
1890
  protected:
1891
    char *m_pszString;
1892
1893
    double m_dAngle;
1894
    double m_dHeight;
1895
    mutable double m_dWidth;
1896
    double m_dfLineEndX;
1897
    double m_dfLineEndY;
1898
    GBool m_bLineEndSet;
1899
    void UpdateTextMBR();
1900
1901
    GInt32 m_rgbForeground;
1902
    GInt32 m_rgbBackground;
1903
    GInt32 m_rgbOutline;
1904
    GInt32 m_rgbShadow;
1905
1906
    GInt16 m_nTextAlignment;  // Justification/Vert.Spacing/arrow
1907
    GInt16 m_nFontStyle;      // Bold/italic/underlined/shadow/...
1908
1909
    const char *GetLabelStyleString() const;
1910
1911
    int UpdateMBR(TABMAPFile *poMapFile = nullptr) override;
1912
1913
  public:
1914
    explicit TABText(const OGRFeatureDefn *poDefnIn);
1915
    ~TABText() override;
1916
1917
    TABFeatureClass GetFeatureClass() override
1918
78.6k
    {
1919
78.6k
        return TABFCText;
1920
78.6k
    }
1921
1922
    virtual TABGeomType
1923
    ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1924
1925
    virtual TABFeature *
1926
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
1927
1928
    virtual int ReadGeometryFromMAPFile(
1929
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
1930
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1931
    virtual int
1932
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1933
                           GBool bCoordDataOnly = FALSE,
1934
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
1935
1936
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1937
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1938
1939
    const char *GetStyleString() const override;
1940
1941
    void DumpMIF(FILE *fpOut = nullptr) override;
1942
1943
    void SetLabelFromStyleString(const char *pszStyleString);
1944
1945
    const char *GetTextString() const;
1946
    double GetTextAngle() const;
1947
    double GetTextBoxHeight() const;
1948
    double GetTextBoxWidth() const;
1949
    GInt32 GetFontFGColor() const;
1950
    GInt32 GetFontBGColor() const;
1951
    GInt32 GetFontOColor() const;
1952
    GInt32 GetFontSColor() const;
1953
    void GetTextLineEndPoint(double &dX, double &dY);
1954
1955
    TABTextJust GetTextJustification() const;
1956
    TABTextSpacing GetTextSpacing() const;
1957
    TABTextLineType GetTextLineType() const;
1958
    GBool QueryFontStyle(TABFontStyle eStyleToQuery) const;
1959
1960
    void SetTextString(const char *pszStr);
1961
    void SetTextAngle(double dAngle);
1962
    void SetTextBoxHeight(double dHeight);
1963
    void SetTextBoxWidth(double dWidth);
1964
    void SetFontFGColor(GInt32 rgbColor);
1965
    void SetFontBGColor(GInt32 rgbColor);
1966
    void SetFontOColor(GInt32 rgbColor);
1967
    void SetFontSColor(GInt32 rgbColor);
1968
    void SetTextLineEndPoint(double dX, double dY);
1969
1970
    void SetTextJustification(TABTextJust eJust);
1971
    void SetTextSpacing(TABTextSpacing eSpacing);
1972
    void SetTextLineType(TABTextLineType eLineType);
1973
    void ToggleFontStyle(TABFontStyle eStyleToToggle, GBool bStatus);
1974
1975
    int GetFontStyleMIFValue() const;
1976
    void SetFontStyleMIFValue(int nStyle, GBool bBGColorSet = FALSE);
1977
    GBool IsFontBGColorUsed() const;
1978
    GBool IsFontOColorUsed() const;
1979
    GBool IsFontSColorUsed() const;
1980
    GBool IsFontBold() const;
1981
    GBool IsFontItalic() const;
1982
    GBool IsFontUnderline() const;
1983
1984
    int GetFontStyleTABValue() const
1985
0
    {
1986
0
        return m_nFontStyle;
1987
0
    }
1988
1989
    void SetFontStyleTABValue(int nStyle)
1990
0
    {
1991
0
        m_nFontStyle = static_cast<GInt16>(nStyle);
1992
0
    }
1993
};
1994
1995
/*---------------------------------------------------------------------
1996
 *                      class TABMultiPoint
1997
 *
1998
 * Feature class to handle MapInfo Multipoint features:
1999
 *
2000
 *     TAB_GEOM_MULTIPOINT_C        0x34
2001
 *     TAB_GEOM_MULTIPOINT          0x35
2002
 *
2003
 * Feature geometry will be a OGRMultiPoint
2004
 *
2005
 * The symbol number is in the range [31..67], with 31=None and corresponds
2006
 * to one of the 35 predefined "Old MapInfo Symbols"
2007
 *--------------------------------------------------------------------*/
2008
class TABMultiPoint final : public TABFeature, public ITABFeatureSymbol
2009
{
2010
  private:
2011
    // We call it center, but it is more like a label point
2012
    // Its value default to be the location of the first point
2013
    GBool m_bCenterIsSet;
2014
    double m_dCenterX;
2015
    double m_dCenterY;
2016
2017
  public:
2018
    explicit TABMultiPoint(const OGRFeatureDefn *poDefnIn);
2019
    ~TABMultiPoint() override;
2020
2021
    TABFeatureClass GetFeatureClass() override
2022
18.2k
    {
2023
18.2k
        return TABFCMultiPoint;
2024
18.2k
    }
2025
2026
    virtual TABGeomType
2027
    ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
2028
2029
    virtual TABFeature *
2030
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
2031
2032
    int GetXY(int i, double &dX, double &dY);
2033
    int GetNumPoints();
2034
2035
    int GetCenter(double &dX, double &dY);
2036
    void SetCenter(double dX, double dY);
2037
2038
    virtual int ReadGeometryFromMAPFile(
2039
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
2040
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
2041
    virtual int
2042
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
2043
                           GBool bCoordDataOnly = FALSE,
2044
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
2045
2046
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
2047
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
2048
2049
    const char *GetStyleString() const override;
2050
2051
    void DumpMIF(FILE *fpOut = nullptr) override;
2052
};
2053
2054
/*---------------------------------------------------------------------
2055
 *
2056
 *                      class TABCollection
2057
 *
2058
 * Feature class to handle MapInfo Collection features:
2059
 *
2060
 *     TAB_GEOM_COLLECTION_C        0x37
2061
 *     TAB_GEOM_COLLECTION          0x38
2062
 *
2063
 * Feature geometry will be a OGRCollection
2064
 *
2065
 * **** IMPORTANT NOTE: ****
2066
 *
2067
 * The current implementation does not allow setting the Geometry via
2068
 * OGRFeature::SetGeometry*(). The geometries must be set via the
2069
 * TABCollection::SetRegion/Pline/MpointDirectly() methods which will take
2070
 * care of keeping the OGRFeature's geometry in sync.
2071
 *
2072
 * If we ever want to support creating collections via the OGR interface then
2073
 * something should be added in TABCollection::WriteGeometryToMapFile(), or
2074
 * perhaps in ValidateMapInfoType(), or even better in a custom
2075
 * TABCollection::SetGeometry*()... but then this last option may not work
2076
 * unless OGRFeature::SetGeometry*() are made virtual in OGR.
2077
 *
2078
 *--------------------------------------------------------------------*/
2079
class TABCollection final : public TABFeature, public ITABFeatureSymbol
2080
{
2081
    CPL_DISALLOW_COPY_ASSIGN(TABCollection)
2082
2083
  private:
2084
    TABRegion *m_poRegion;
2085
    TABPolyline *m_poPline;
2086
    TABMultiPoint *m_poMpoint;
2087
2088
    void EmptyCollection();
2089
    static int ReadLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
2090
                               GBool bComprCoord, GInt32 nComprOrgX,
2091
                               GInt32 nComprOrgY, GInt32 &pnMinX,
2092
                               GInt32 &pnMinY, GInt32 &pnMaxX, GInt32 &pnMaxY,
2093
                               GInt32 &pnLabelX, GInt32 &pnLabelY);
2094
    static int WriteLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
2095
                                GBool bComprCoord, GInt32 nMinX, GInt32 nMinY,
2096
                                GInt32 nMaxX, GInt32 nMaxY, GInt32 nLabelX,
2097
                                GInt32 nLabelY);
2098
    int SyncOGRGeometryCollection(GBool bSyncRegion, GBool bSyncPline,
2099
                                  GBool bSyncMpoint);
2100
2101
  public:
2102
    explicit TABCollection(const OGRFeatureDefn *poDefnIn);
2103
    ~TABCollection() override;
2104
2105
    TABFeatureClass GetFeatureClass() override
2106
23.5k
    {
2107
23.5k
        return TABFCCollection;
2108
23.5k
    }
2109
2110
    virtual TABGeomType
2111
    ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
2112
2113
    virtual TABFeature *
2114
    CloneTABFeature(const OGRFeatureDefn *poNewDefn = nullptr) override;
2115
2116
    virtual int ReadGeometryFromMAPFile(
2117
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
2118
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
2119
    virtual int
2120
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
2121
                           GBool bCoordDataOnly = FALSE,
2122
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
2123
2124
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
2125
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
2126
2127
    const char *GetStyleString() const override;
2128
2129
    void DumpMIF(FILE *fpOut = nullptr) override;
2130
2131
    TABRegion *GetRegionRef()
2132
0
    {
2133
0
        return m_poRegion;
2134
0
    }
2135
2136
    TABPolyline *GetPolylineRef()
2137
0
    {
2138
0
        return m_poPline;
2139
0
    }
2140
2141
    TABMultiPoint *GetMultiPointRef()
2142
0
    {
2143
0
        return m_poMpoint;
2144
0
    }
2145
2146
    int SetRegionDirectly(TABRegion *poRegion);
2147
    int SetPolylineDirectly(TABPolyline *poPline);
2148
    int SetMultiPointDirectly(TABMultiPoint *poMpoint);
2149
};
2150
2151
/*---------------------------------------------------------------------
2152
 *                      class TABDebugFeature
2153
 *
2154
 * Feature class to use for testing purposes... this one does not
2155
 * correspond to any MapInfo type... it is just used to dump info about
2156
 * feature types that are not implemented yet.
2157
 *--------------------------------------------------------------------*/
2158
class TABDebugFeature final : public TABFeature
2159
{
2160
  private:
2161
    GByte m_abyBuf[512];
2162
    int m_nSize;
2163
    int m_nCoordDataPtr;  // -1 if none
2164
    int m_nCoordDataSize;
2165
2166
  public:
2167
    explicit TABDebugFeature(const OGRFeatureDefn *poDefnIn);
2168
    ~TABDebugFeature() override;
2169
2170
    TABFeatureClass GetFeatureClass() override
2171
0
    {
2172
0
        return TABFCDebugFeature;
2173
0
    }
2174
2175
    virtual int ReadGeometryFromMAPFile(
2176
        TABMAPFile *poMapFile, TABMAPObjHdr *, GBool bCoordDataOnly = FALSE,
2177
        TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
2178
    virtual int
2179
    WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
2180
                           GBool bCoordDataOnly = FALSE,
2181
                           TABMAPCoordBlock **ppoCoordBlock = nullptr) override;
2182
2183
    int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
2184
    int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
2185
2186
    void DumpMIF(FILE *fpOut = nullptr) override;
2187
};
2188
2189
#endif /* MITAB_H_INCLUDED_ */