1 /******************************************************************************
2  *
3  * Project:  PDF Translator
4  * Purpose:  Implements OGRPDFDataSource class
5  * Author:   Even Rouault, even dot rouault at spatialys.com
6  *
7  ******************************************************************************
8  * Copyright (c) 2012, Even Rouault <even dot rouault at spatialys.com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #include "gdal_pdf.h"
30 
31 CPL_CVSID("$Id: ogrpdflayer.cpp 9c1c4c56303c06d9e18dbfd9412dab3ce58f3f03 2020-05-28 14:16:15 +0200 Even Rouault $")
32 
33 #ifdef HAVE_PDF_READ_SUPPORT
34 
35 /************************************************************************/
36 /*                            OGRPDFLayer()                             */
37 /************************************************************************/
38 
OGRPDFLayer(PDFDataset * poDSIn,const char * pszName,OGRSpatialReference * poSRS,OGRwkbGeometryType eGeomType)39 OGRPDFLayer::OGRPDFLayer( PDFDataset* poDSIn,
40                           const char * pszName,
41                           OGRSpatialReference *poSRS,
42                           OGRwkbGeometryType eGeomType ) :
43     OGRMemLayer(pszName, poSRS, eGeomType ),
44     poDS(poDSIn),
45     bGeomTypeSet(FALSE),
46     bGeomTypeMixed(FALSE)
47 {}
48 
49 /************************************************************************/
50 /*                              Fill()                                  */
51 /************************************************************************/
52 
Fill(GDALPDFArray * poArray)53 void OGRPDFLayer::Fill( GDALPDFArray* poArray )
54 {
55     for(int i=0;i<poArray->GetLength();i++)
56     {
57         GDALPDFObject* poFeatureObj = poArray->Get(i);
58         if (poFeatureObj == nullptr ||
59             poFeatureObj->GetType() != PDFObjectType_Dictionary)
60             continue;
61 
62         GDALPDFObject* poA = poFeatureObj->GetDictionary()->Get("A");
63         if (!(poA != nullptr && poA->GetType() == PDFObjectType_Dictionary))
64             continue;
65 
66         // P is supposed to be required in A, but past GDAL versions could
67         // generate features without attributes without a P array
68         GDALPDFObject* poP = poA->GetDictionary()->Get("P");
69         GDALPDFArray* poPArray = nullptr;
70         if (poP != nullptr && poP->GetType() == PDFObjectType_Array)
71             poPArray = poP->GetArray();
72         else
73             poP = nullptr;
74 
75         GDALPDFObject* poK = poFeatureObj->GetDictionary()->Get("K");
76         int nK = -1;
77         if (poK != nullptr && poK->GetType() == PDFObjectType_Int)
78             nK = poK->GetInt();
79 
80         if( poP )
81         {
82             for(int j = 0;j<poPArray->GetLength();j++)
83             {
84                 GDALPDFObject* poKV = poPArray->Get(j);
85                 if (poKV && poKV->GetType() == PDFObjectType_Dictionary)
86                 {
87                     GDALPDFObject* poN = poKV->GetDictionary()->Get("N");
88                     GDALPDFObject* poV = poKV->GetDictionary()->Get("V");
89                     if (poN != nullptr && poN->GetType() == PDFObjectType_String &&
90                         poV != nullptr)
91                     {
92                         int nIdx = GetLayerDefn()->GetFieldIndex( poN->GetString().c_str() );
93                         OGRFieldType eType = OFTString;
94                         if (poV->GetType() == PDFObjectType_Int)
95                             eType = OFTInteger;
96                         else if (poV->GetType() == PDFObjectType_Real)
97                             eType = OFTReal;
98                         if (nIdx < 0)
99                         {
100                             OGRFieldDefn oField(poN->GetString().c_str(), eType);
101                             CreateField(&oField);
102                         }
103                         else if (GetLayerDefn()->GetFieldDefn(nIdx)->GetType() != eType &&
104                                     GetLayerDefn()->GetFieldDefn(nIdx)->GetType() != OFTString)
105                         {
106                             OGRFieldDefn oField(poN->GetString().c_str(), OFTString);
107                             AlterFieldDefn( nIdx, &oField, ALTER_TYPE_FLAG );
108                         }
109                     }
110                 }
111             }
112         }
113 
114         OGRFeature* poFeature = new OGRFeature(GetLayerDefn());
115         if( poPArray )
116         {
117             for(int j = 0;j<poPArray->GetLength();j++)
118             {
119                 GDALPDFObject* poKV = poPArray->Get(j);
120                 if (poKV && poKV->GetType() == PDFObjectType_Dictionary)
121                 {
122                     GDALPDFObject* poN = poKV->GetDictionary()->Get("N");
123                     GDALPDFObject* poV = poKV->GetDictionary()->Get("V");
124                     if (poN != nullptr && poN->GetType() == PDFObjectType_String &&
125                         poV != nullptr)
126                     {
127                         if (poV->GetType() == PDFObjectType_String)
128                             poFeature->SetField(poN->GetString().c_str(), poV->GetString().c_str());
129                         else if (poV->GetType() == PDFObjectType_Int)
130                             poFeature->SetField(poN->GetString().c_str(), poV->GetInt());
131                         else if (poV->GetType() == PDFObjectType_Real)
132                             poFeature->SetField(poN->GetString().c_str(), poV->GetReal());
133                     }
134                 }
135             }
136         }
137 
138         if (nK >= 0)
139         {
140             OGRGeometry* poGeom = poDS->GetGeometryFromMCID(nK);
141             if (poGeom)
142             {
143                 poGeom->assignSpatialReference(GetSpatialRef());
144                 poFeature->SetGeometry(poGeom);
145             }
146         }
147 
148         OGRGeometry* poGeom = poFeature->GetGeometryRef();
149         if( !bGeomTypeMixed && poGeom != nullptr )
150         {
151             if (!bGeomTypeSet)
152             {
153                 bGeomTypeSet = TRUE;
154                 GetLayerDefn()->SetGeomType(poGeom->getGeometryType());
155             }
156             else if (GetLayerDefn()->GetGeomType() != poGeom->getGeometryType())
157             {
158                 bGeomTypeMixed = TRUE;
159                 GetLayerDefn()->SetGeomType(wkbUnknown);
160             }
161         }
162         ICreateFeature(poFeature);
163 
164         delete poFeature;
165     }
166 }
167 
168 /************************************************************************/
169 /*                           TestCapability()                           */
170 /************************************************************************/
171 
TestCapability(const char * pszCap)172 int OGRPDFLayer::TestCapability( const char * pszCap )
173 
174 {
175     if( EQUAL(pszCap,OLCStringsAsUTF8) )
176         return TRUE;
177     else
178         return OGRMemLayer::TestCapability(pszCap);
179 }
180 
181 #endif /* HAVE_PDF_READ_SUPPORT */
182 
183 /************************************************************************/
184 /*                        OGRPDFWritableLayer()                         */
185 /************************************************************************/
186 
OGRPDFWritableLayer(PDFWritableVectorDataset * poDSIn,const char * pszName,OGRSpatialReference * poSRS,OGRwkbGeometryType eGeomType)187 OGRPDFWritableLayer::OGRPDFWritableLayer( PDFWritableVectorDataset* poDSIn,
188                                           const char * pszName,
189                                           OGRSpatialReference *poSRS,
190                                           OGRwkbGeometryType eGeomType ) :
191     OGRMemLayer(pszName, poSRS, eGeomType ),
192     poDS(poDSIn)
193 {}
194 
195 /************************************************************************/
196 /*                           ICreateFeature()                           */
197 /************************************************************************/
198 
ICreateFeature(OGRFeature * poFeature)199 OGRErr OGRPDFWritableLayer::ICreateFeature( OGRFeature *poFeature )
200 {
201     poDS->SetModified();
202     return OGRMemLayer::ICreateFeature(poFeature);
203 }
204 
205 /************************************************************************/
206 /*                           TestCapability()                           */
207 /************************************************************************/
208 
TestCapability(const char * pszCap)209 int OGRPDFWritableLayer::TestCapability( const char * pszCap )
210 
211 {
212     if( EQUAL(pszCap,OLCStringsAsUTF8) )
213         return TRUE;
214     else
215         return OGRMemLayer::TestCapability(pszCap);
216 }
217