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