1 /*******************************************************************************
2  *  Project: OGR CAD Driver
3  *  Purpose: Implements driver based on libopencad
4  *  Author: Alexandr Borzykh, mush3d at gmail.com
5  *  Author: Dmitry Baryshnikov, polimax@mail.ru
6  *  Language: C++
7  *******************************************************************************
8  *  The MIT License (MIT)
9  *
10  *  Copyright (c) 2016 Alexandr Borzykh
11  *  Copyright (c) 2016, NextGIS
12  *
13  *  Permission is hereby granted, free of charge, to any person obtaining a copy
14  *  of this software and associated documentation files (the "Software"), to deal
15  *  in the Software without restriction, including without limitation the rights
16  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  *  copies of the Software, and to permit persons to whom the Software is
18  *  furnished to do so, subject to the following conditions:
19  *
20  *  The above copyright notice and this permission notice shall be included in all
21  *  copies or substantial portions of the Software.
22  *
23  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  *  SOFTWARE.
30  *******************************************************************************/
31 #include "ogr_cad.h"
32 #include "vsilfileio.h"
33 
34 /************************************************************************/
35 /*                           OGRCADDriverIdentify()                     */
36 /************************************************************************/
37 
OGRCADDriverIdentify(GDALOpenInfo * poOpenInfo)38 static int OGRCADDriverIdentify( GDALOpenInfo *poOpenInfo )
39 {
40     if ( poOpenInfo->nHeaderBytes < 6 )
41         return FALSE;
42 
43     if ( poOpenInfo->pabyHeader[0] != 'A' ||
44         poOpenInfo->pabyHeader[1] != 'C' )
45         return FALSE;
46 
47     return IdentifyCADFile ( new VSILFileIO( poOpenInfo->pszFilename ), true ) == 0 ?
48         FALSE : TRUE;
49 }
50 
51 /************************************************************************/
52 /*                           OGRCADDriverOpen()                         */
53 /************************************************************************/
54 
OGRCADDriverOpen(GDALOpenInfo * poOpenInfo)55 static GDALDataset *OGRCADDriverOpen( GDALOpenInfo* poOpenInfo )
56 {
57     long nSubRasterLayer = -1;
58     long nSubRasterFID = -1;
59 
60     CADFileIO* pFileIO;
61     if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "CAD:") )
62     {
63         char** papszTokens = CSLTokenizeString2( poOpenInfo->pszFilename, ":", 0 );
64         int nTokens = CSLCount( papszTokens );
65         if( nTokens < 4 )
66         {
67             CSLDestroy(papszTokens);
68             return nullptr;
69         }
70 
71         CPLString osFilename;
72         for( int i = 1; i < nTokens - 2; ++i )
73         {
74             if( osFilename.empty() )
75                 osFilename += ":";
76             osFilename += papszTokens[i];
77         }
78 
79         pFileIO = new VSILFileIO( osFilename );
80         nSubRasterLayer = atol( papszTokens[nTokens - 2] );
81         nSubRasterFID = atol( papszTokens[nTokens - 1] );
82 
83         CSLDestroy( papszTokens );
84     }
85     else
86     {
87         pFileIO = new VSILFileIO( poOpenInfo->pszFilename );
88     }
89 
90     if ( IdentifyCADFile( pFileIO, false ) == FALSE )
91     {
92         delete pFileIO;
93         return nullptr;
94     }
95 
96 
97 /* -------------------------------------------------------------------- */
98 /*      Confirm the requested access is supported.                      */
99 /* -------------------------------------------------------------------- */
100     if( poOpenInfo->eAccess == GA_Update )
101     {
102         CPLError( CE_Failure, CPLE_NotSupported,
103                   "The CAD driver does not support update access to existing"
104                   " datasets.\n" );
105         delete pFileIO;
106         return nullptr;
107     }
108 
109     GDALCADDataset *poDS = new GDALCADDataset();
110     if( !poDS->Open( poOpenInfo, pFileIO, nSubRasterLayer, nSubRasterFID ) )
111     {
112         delete poDS;
113         return nullptr;
114     }
115     else
116         return poDS;
117 }
118 
119 /************************************************************************/
120 /*                           RegisterGDALCAD()                          */
121 /************************************************************************/
122 
RegisterOGRCAD()123 void RegisterOGRCAD()
124 {
125     GDALDriver  *poDriver;
126 
127     if ( GDALGetDriverByName( "CAD" ) == nullptr )
128     {
129         poDriver = new GDALDriver();
130         poDriver->SetDescription( "CAD" );
131         poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
132         poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
133         poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
134         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "AutoCAD Driver" );
135         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dwg" );
136         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drivers/vector/cad.html" );
137 
138         poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList>"
139 "  <Option name='MODE' type='string' description='Open mode. READ_ALL - read all data (slow), READ_FAST - read main data (fast), READ_FASTEST - read less data' default='READ_FAST'/>"
140 "  <Option name='ADD_UNSUPPORTED_GEOMETRIES_DATA' type='string' description='Add unsupported geometries data (color, attributes) to the layer (YES/NO). They will have no geometrical representation.' default='NO'/>"
141 "</OpenOptionList>");
142 
143 
144         poDriver->pfnOpen = OGRCADDriverOpen;
145         poDriver->pfnIdentify = OGRCADDriverIdentify;
146         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
147         poDriver->SetMetadataItem( GDAL_DCAP_FEATURE_STYLES, "YES" );
148         GetGDALDriverManager()->RegisterDriver( poDriver );
149     }
150 }
151 
CADRecode(const CPLString & sString,int CADEncoding)152 CPLString CADRecode( const CPLString& sString, int CADEncoding )
153 {
154     const char* const apszSource[] = {
155         /* 0 UNDEFINED */ "",
156         /* 1 ASCII */ "US-ASCII",
157         /* 2 8859_1 */ "ISO-8859-1",
158         /* 3 8859_2 */ "ISO-8859-2",
159         /* 4 UNDEFINED */ "",
160         /* 5 8859_4 */ "ISO-8859-4",
161         /* 6 8859_5 */ "ISO-8859-5",
162         /* 7 8859_6 */ "ISO-8859-6",
163         /* 8 8859_7 */ "ISO-8859-7",
164         /* 9 8859_8 */ "ISO-8859-8",
165         /* 10 8859_9 */ "ISO-8859-9",
166         /* 11 DOS437 */ "CP437",
167         /* 12 DOS850 */ "CP850",
168         /* 13 DOS852 */ "CP852",
169         /* 14 DOS855 */ "CP855",
170         /* 15 DOS857 */ "CP857",
171         /* 16 DOS860 */ "CP860",
172         /* 17 DOS861 */ "CP861",
173         /* 18 DOS863 */ "CP863",
174         /* 19 DOS864 */ "CP864",
175         /* 20 DOS865 */ "CP865",
176         /* 21 DOS869 */ "CP869",
177         /* 22 DOS932 */ "CP932",
178         /* 23 MACINTOSH */ "MACINTOSH",
179         /* 24 BIG5 */ "BIG5",
180         /* 25 KSC5601 */ "CP949",
181         /* 26 JOHAB */ "JOHAB",
182         /* 27 DOS866 */ "CP866",
183         /* 28 ANSI_1250 */ "CP1250",
184         /* 29 ANSI_1251 */ "CP1251",
185         /* 30 ANSI_1252 */ "CP1252",
186         /* 31 GB2312 */ "GB2312",
187         /* 32 ANSI_1253 */ "CP1253",
188         /* 33 ANSI_1254 */ "CP1254",
189         /* 34 ANSI_1255 */ "CP1255",
190         /* 35 ANSI_1256 */ "CP1256",
191         /* 36 ANSI_1257 */ "CP1257",
192         /* 37 ANSI_874 */ "CP874",
193         /* 38 ANSI_932 */ "CP932",
194         /* 39 ANSI_936 */ "CP936",
195         /* 40 ANSI_949 */ "CP949",
196         /* 41 ANSI_950 */ "CP950",
197         /* 42 ANSI_1361 */ "CP1361",
198         /* 43 ANSI_1200 */ "UTF-16",
199         /* 44 ANSI_1258 */ "CP1258"
200     };
201 
202     if( CADEncoding > 0 &&
203         CADEncoding < static_cast<int>(CPL_ARRAYSIZE(apszSource)) &&
204         CADEncoding != 4 )
205     {
206         char* pszRecoded = CPLRecode( sString, apszSource[CADEncoding], CPL_ENC_UTF8 );
207         CPLString soRecoded(pszRecoded);
208         CPLFree(pszRecoded);
209         return soRecoded;
210     }
211     CPLError( CE_Failure, CPLE_NotSupported,
212             "CADRecode() function does not support provided CADEncoding." );
213     return CPLString("");
214 }
215