Line data Source code
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 : #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 : ((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 0 : virtual TABFileClass GetFileClass()
82 : {
83 0 : return TABFC_IMapInfoFile;
84 : }
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 0 : SetQuickSpatialIndexMode(CPL_UNUSED GBool bQuickSpatialIndexMode = TRUE)
97 : {
98 0 : return -1;
99 : }
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 23 : GDALDataset *GetDataset() override
122 : {
123 23 : return m_poDS;
124 : }
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 209 : GBool IsBoundsSet()
151 : {
152 209 : return m_bBoundsSet;
153 : }
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 67 : TABFileClass GetFileClass() override
251 : {
252 67 : return TABFC_TABFile;
253 : }
254 :
255 0 : virtual int Open(const char *pszFname, const char *pszAccess,
256 : GBool bTestOpenNoError = FALSE,
257 : const char *pszCharset = nullptr) override
258 : {
259 0 : return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError,
260 0 : pszCharset);
261 : }
262 :
263 1310 : virtual int Open(const char *pszFname, TABAccess eAccess,
264 : GBool bTestOpenNoError = FALSE,
265 : const char *pszCharset = nullptr) override
266 : {
267 1310 : return Open(pszFname, eAccess, bTestOpenNoError, 512, pszCharset);
268 : }
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 0 : const char *GetTableName() override
279 : {
280 0 : return m_poDefn ? m_poDefn->GetName() : "";
281 : }
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 0 : GBool IsFieldUnique(int /*nFieldId*/) override
327 : {
328 0 : return FALSE;
329 : }
330 :
331 : int GetVersion()
332 : {
333 : return m_nVersion;
334 : }
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 0 : int GetProjInfo(TABProjInfo *poPI) override
357 : {
358 0 : return m_poMAPFile->GetHeaderBlock()->GetProjInfo(poPI);
359 : }
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 : {
369 : return m_poMAPFile;
370 : }
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 0 : TABFileClass GetFileClass() override
431 : {
432 0 : return TABFC_TABView;
433 : }
434 :
435 0 : virtual int Open(const char *pszFname, const char *pszAccess,
436 : GBool bTestOpenNoError = FALSE,
437 : const char *pszCharset = nullptr) override
438 : {
439 0 : return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError,
440 0 : pszCharset);
441 : }
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 0 : const char *GetTableName() override
452 : {
453 0 : return m_poRelation ? m_poRelation->GetFeatureDefn()->GetName() : "";
454 : }
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 0 : int GetProjInfo(TABProjInfo *poPI) override
505 : {
506 0 : return m_nMainTableIndex != -1
507 0 : ? m_papoTABFiles[m_nMainTableIndex]->GetProjInfo(poPI)
508 0 : : -1;
509 : }
510 :
511 0 : int SetProjInfo(TABProjInfo *poPI) override
512 : {
513 0 : return m_nMainTableIndex != -1
514 0 : ? m_papoTABFiles[m_nMainTableIndex]->SetProjInfo(poPI)
515 0 : : -1;
516 : }
517 :
518 0 : int SetMIFCoordSys(const char * /*pszMIFCoordSys*/) override
519 : {
520 0 : return -1;
521 : }
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 0 : TABFileClass GetFileClass() override
572 : {
573 0 : return TABFC_TABSeamless;
574 : }
575 :
576 0 : virtual int Open(const char *pszFname, const char *pszAccess,
577 : GBool bTestOpenNoError = FALSE,
578 : const char *pszCharset = nullptr) override
579 : {
580 0 : return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError,
581 0 : pszCharset);
582 : }
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 0 : const char *GetTableName() override
590 : {
591 0 : return m_poFeatureDefnRef ? m_poFeatureDefnRef->GetName() : "";
592 : }
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 0 : virtual int SetBounds(CPL_UNUSED double dXMin, CPL_UNUSED double dYMin,
629 : CPL_UNUSED double dXMax,
630 : CPL_UNUSED double dYMax) override
631 : {
632 0 : return -1;
633 : }
634 :
635 0 : virtual int SetFeatureDefn(
636 : CPL_UNUSED OGRFeatureDefn *poFeatureDefn,
637 : CPL_UNUSED TABFieldType *paeMapInfoNativeFieldTypes = nullptr) override
638 : {
639 0 : return -1;
640 : }
641 :
642 0 : 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 : {
650 0 : return -1;
651 : }
652 :
653 : virtual int
654 0 : SetSpatialRef(CPL_UNUSED OGRSpatialReference *poSpatialRef) override
655 : {
656 0 : return -1;
657 : }
658 :
659 0 : OGRErr CreateFeature(CPL_UNUSED TABFeature *poFeature) override
660 : {
661 0 : return OGRERR_UNSUPPORTED_OPERATION;
662 : }
663 :
664 0 : int SetFieldIndexed(CPL_UNUSED int nFieldId) override
665 : {
666 0 : return -1;
667 : }
668 :
669 : ///////////////
670 : // semi-private.
671 0 : int GetProjInfo(TABProjInfo *poPI) override
672 : {
673 0 : return m_poIndexTable ? m_poIndexTable->GetProjInfo(poPI) : -1;
674 : }
675 :
676 0 : int SetProjInfo(CPL_UNUSED TABProjInfo *poPI) override
677 : {
678 0 : return -1;
679 : }
680 :
681 0 : int SetMIFCoordSys(const char * /*pszMIFCoordSys*/) override
682 : {
683 0 : return -1;
684 : }
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 84 : TABFileClass GetFileClass() override
769 : {
770 84 : return TABFC_MIFFile;
771 : }
772 :
773 0 : virtual int Open(const char *pszFname, const char *pszAccess,
774 : GBool bTestOpenNoError = FALSE,
775 : const char *pszCharset = nullptr) override
776 : {
777 0 : return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError,
778 0 : pszCharset);
779 : }
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 0 : const char *GetTableName() override
787 : {
788 0 : return m_poDefn ? m_poDefn->GetName() : "";
789 : }
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 : {
821 : return m_nVersion;
822 : }
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 0 : int GetProjInfo(TABProjInfo * /*poPI*/) override
846 : {
847 0 : return -1;
848 : }
849 :
850 : /* { return m_poMAPFile->GetHeaderBlock()->GetProjInfo( poPI ); }*/
851 0 : int SetProjInfo(TABProjInfo * /*poPI*/) override
852 : {
853 0 : return -1;
854 : }
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 0 : void Dump(FILE * /*fpOut*/ = nullptr) override
862 : {
863 0 : }
864 : #endif
865 : };
866 :
867 : /*---------------------------------------------------------------------
868 : * Define some error codes specific to this lib.
869 : *--------------------------------------------------------------------*/
870 : #define TAB_WarningFeatureTypeNotSupported 501
871 : #define TAB_WarningInvalidFieldName 502
872 : #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 7777 : 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 : {
974 : return m_nPenDefIndex;
975 : }
976 :
977 0 : TABPenDef *GetPenDefRef()
978 : {
979 0 : return &m_sPenDef;
980 : }
981 :
982 : const TABPenDef *GetPenDefRef() const
983 : {
984 : return &m_sPenDef;
985 : }
986 :
987 : GByte GetPenWidthPixel() const;
988 : double GetPenWidthPoint() const;
989 : int GetPenWidthMIF() const;
990 :
991 240 : GByte GetPenPattern() const
992 : {
993 240 : return m_sPenDef.nLinePattern;
994 : }
995 :
996 21 : GInt32 GetPenColor() const
997 : {
998 21 : return m_sPenDef.rgbColor;
999 : }
1000 :
1001 : void SetPenWidthPixel(GByte val);
1002 : void SetPenWidthPoint(double val);
1003 : void SetPenWidthMIF(int val);
1004 :
1005 2463 : void SetPenPattern(GByte val)
1006 : {
1007 2463 : m_sPenDef.nLinePattern = val;
1008 2463 : }
1009 :
1010 2464 : void SetPenColor(GInt32 clr)
1011 : {
1012 2464 : m_sPenDef.rgbColor = clr;
1013 2464 : }
1014 :
1015 : const char *GetPenStyleString() const;
1016 : void SetPenFromStyleString(const char *pszStyleString);
1017 :
1018 : void DumpPenDef(FILE *fpOut = nullptr);
1019 : };
1020 :
1021 2540 : 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 : {
1034 : return m_nBrushDefIndex;
1035 : }
1036 :
1037 0 : TABBrushDef *GetBrushDefRef()
1038 : {
1039 0 : return &m_sBrushDef;
1040 : }
1041 :
1042 : const TABBrushDef *GetBrushDefRef() const
1043 : {
1044 : return &m_sBrushDef;
1045 : }
1046 :
1047 21 : GInt32 GetBrushFGColor() const
1048 : {
1049 21 : return m_sBrushDef.rgbFGColor;
1050 : }
1051 :
1052 21 : GInt32 GetBrushBGColor() const
1053 : {
1054 21 : return m_sBrushDef.rgbBGColor;
1055 : }
1056 :
1057 42 : GByte GetBrushPattern() const
1058 : {
1059 42 : return m_sBrushDef.nFillPattern;
1060 : }
1061 :
1062 75 : GByte GetBrushTransparent() const
1063 : {
1064 75 : return m_sBrushDef.bTransparentFill;
1065 : }
1066 :
1067 1575 : void SetBrushFGColor(GInt32 clr)
1068 : {
1069 1575 : m_sBrushDef.rgbFGColor = clr;
1070 1575 : }
1071 :
1072 1567 : void SetBrushBGColor(GInt32 clr)
1073 : {
1074 1567 : m_sBrushDef.rgbBGColor = clr;
1075 1567 : }
1076 :
1077 1575 : void SetBrushPattern(GByte val)
1078 : {
1079 1575 : m_sBrushDef.nFillPattern = val;
1080 1575 : }
1081 :
1082 8 : void SetBrushTransparent(GByte val)
1083 : {
1084 8 : m_sBrushDef.bTransparentFill = val;
1085 8 : }
1086 :
1087 : const char *GetBrushStyleString() const;
1088 : void SetBrushFromStyleString(const char *pszStyleString);
1089 :
1090 : void DumpBrushDef(FILE *fpOut = nullptr);
1091 : };
1092 :
1093 1638 : 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 : {
1106 : return m_nFontDefIndex;
1107 : }
1108 :
1109 0 : TABFontDef *GetFontDefRef()
1110 : {
1111 0 : return &m_sFontDef;
1112 : }
1113 :
1114 : const TABFontDef *GetFontDefRef() const
1115 : {
1116 : return &m_sFontDef;
1117 : }
1118 :
1119 38 : const char *GetFontNameRef() const
1120 : {
1121 38 : return m_sFontDef.szFontName;
1122 : }
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 566233 : virtual ~ITABFeatureSymbol() = default;
1139 :
1140 : int GetSymbolDefIndex() const
1141 : {
1142 : return m_nSymbolDefIndex;
1143 : }
1144 :
1145 4 : TABSymbolDef *GetSymbolDefRef()
1146 : {
1147 4 : return &m_sSymbolDef;
1148 : }
1149 :
1150 : const TABSymbolDef *GetSymbolDefRef() const
1151 : {
1152 : return &m_sSymbolDef;
1153 : }
1154 :
1155 82 : GInt16 GetSymbolNo() const
1156 : {
1157 82 : return m_sSymbolDef.nSymbolNo;
1158 : }
1159 :
1160 82 : GInt16 GetSymbolSize() const
1161 : {
1162 82 : return m_sSymbolDef.nPointSize;
1163 : }
1164 :
1165 82 : GInt32 GetSymbolColor() const
1166 : {
1167 82 : return m_sSymbolDef.rgbColor;
1168 : }
1169 :
1170 771 : void SetSymbolNo(GInt16 val)
1171 : {
1172 771 : m_sSymbolDef.nSymbolNo = val;
1173 771 : }
1174 :
1175 1451 : void SetSymbolSize(GInt16 val)
1176 : {
1177 1451 : m_sSymbolDef.nPointSize = val;
1178 1451 : }
1179 :
1180 1451 : void SetSymbolColor(GInt32 clr)
1181 : {
1182 1451 : m_sSymbolDef.rgbColor = clr;
1183 1451 : }
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 82 : virtual TABFeatureClass GetFeatureClass()
1246 : {
1247 82 : return TABFCNoGeomFeature;
1248 : }
1249 :
1250 0 : virtual TABGeomType GetMapInfoType()
1251 : {
1252 0 : return m_nMapInfoType;
1253 : }
1254 :
1255 : virtual TABGeomType
1256 60 : ValidateMapInfoType(CPL_UNUSED TABMAPFile *poMapFile = nullptr)
1257 : {
1258 60 : m_nMapInfoType = TAB_GEOM_NONE;
1259 60 : return m_nMapInfoType;
1260 : }
1261 :
1262 : GBool IsRecordDeleted()
1263 : {
1264 : return m_bDeletedFlag;
1265 : }
1266 :
1267 551214 : void SetRecordDeleted(GBool bDeleted)
1268 : {
1269 551214 : m_bDeletedFlag = bDeleted;
1270 551214 : }
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 15441 : TABFeatureClass GetFeatureClass() override
1344 : {
1345 15441 : return TABFCPoint;
1346 : }
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 637 : TABFeatureClass GetFeatureClass() override
1399 : {
1400 637 : return TABFCFontPoint;
1401 : }
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 0 : int GetFontStyleTABValue()
1429 : {
1430 0 : return m_nFontStyle;
1431 : }
1432 :
1433 0 : void SetFontStyleTABValue(int nStyle)
1434 : {
1435 0 : m_nFontStyle = static_cast<GInt16>(nStyle);
1436 0 : }
1437 :
1438 : // GetSymbolAngle(): Return angle in degrees counterclockwise
1439 7 : double GetSymbolAngle() const
1440 : {
1441 7 : return m_dAngle;
1442 : }
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 680 : TABFeatureClass GetFeatureClass() override
1474 : {
1475 680 : return TABFCCustomPoint;
1476 : }
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 21 : const char *GetSymbolNameRef() const
1498 : {
1499 21 : return GetFontNameRef();
1500 : }
1501 :
1502 2 : void SetSymbolName(const char *pszName)
1503 : {
1504 2 : SetFontName(pszName);
1505 2 : }
1506 :
1507 0 : GByte GetCustomSymbolStyle()
1508 : {
1509 0 : return m_nCustomStyle;
1510 : }
1511 :
1512 2 : void SetCustomSymbolStyle(GByte nStyle)
1513 : {
1514 2 : m_nCustomStyle = nStyle;
1515 2 : }
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 2311 : TABFeatureClass GetFeatureClass() override
1547 : {
1548 2311 : return TABFCPolyline;
1549 : }
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 438 : TABFeatureClass GetFeatureClass() override
1627 : {
1628 438 : return TABFCRegion;
1629 : }
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 921 : TABFeatureClass GetFeatureClass() override
1691 : {
1692 921 : return TABFCRectangle;
1693 : }
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 387 : TABFeatureClass GetFeatureClass() override
1757 : {
1758 387 : return TABFCEllipse;
1759 : }
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 642 : TABFeatureClass GetFeatureClass() override
1823 : {
1824 642 : return TABFCArc;
1825 : }
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 0 : double GetStartAngle()
1849 : {
1850 0 : return m_dStartAngle;
1851 : }
1852 :
1853 0 : double GetEndAngle()
1854 : {
1855 0 : return m_dEndAngle;
1856 : }
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 280 : TABFeatureClass GetFeatureClass() override
1918 : {
1919 280 : return TABFCText;
1920 : }
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 0 : int GetFontStyleTABValue() const
1985 : {
1986 0 : return m_nFontStyle;
1987 : }
1988 :
1989 0 : void SetFontStyleTABValue(int nStyle)
1990 : {
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 149 : TABFeatureClass GetFeatureClass() override
2022 : {
2023 149 : return TABFCMultiPoint;
2024 : }
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 2 : TABFeatureClass GetFeatureClass() override
2106 : {
2107 2 : return TABFCCollection;
2108 : }
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 : {
2133 : return m_poRegion;
2134 : }
2135 :
2136 : TABPolyline *GetPolylineRef()
2137 : {
2138 : return m_poPline;
2139 : }
2140 :
2141 : TABMultiPoint *GetMultiPointRef()
2142 : {
2143 : return m_poMpoint;
2144 : }
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 0 : TABFeatureClass GetFeatureClass() override
2171 : {
2172 0 : return TABFCDebugFeature;
2173 : }
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_ */
|