Coverage Report

Created: 2025-06-09 07:43

/src/gdal/frmts/pdf/ogrpdflayer.cpp
Line
Count
Source (jump to first uncovered line)
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
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "gdal_pdf.h"
14
15
#ifdef HAVE_PDF_READ_SUPPORT
16
17
/************************************************************************/
18
/*                            OGRPDFLayer()                             */
19
/************************************************************************/
20
21
OGRPDFLayer::OGRPDFLayer(PDFDataset *poDSIn, const char *pszName,
22
                         OGRSpatialReference *poSRS,
23
                         OGRwkbGeometryType eGeomType)
24
0
    : OGRMemLayer(pszName, poSRS, eGeomType), poDS(poDSIn), bGeomTypeSet(FALSE),
25
0
      bGeomTypeMixed(FALSE)
26
0
{
27
0
}
28
29
/************************************************************************/
30
/*                              Fill()                                  */
31
/************************************************************************/
32
33
void OGRPDFLayer::Fill(GDALPDFArray *poArray)
34
0
{
35
0
    for (int i = 0; i < poArray->GetLength(); i++)
36
0
    {
37
0
        GDALPDFObject *poFeatureObj = poArray->Get(i);
38
0
        if (poFeatureObj == nullptr ||
39
0
            poFeatureObj->GetType() != PDFObjectType_Dictionary)
40
0
            continue;
41
42
0
        GDALPDFObject *poA = poFeatureObj->GetDictionary()->Get("A");
43
0
        if (!(poA != nullptr && poA->GetType() == PDFObjectType_Dictionary))
44
0
            continue;
45
46
0
        auto poO = poA->GetDictionary()->Get("O");
47
0
        if (!(poO && poO->GetType() == PDFObjectType_Name &&
48
0
              poO->GetName() == "UserProperties"))
49
0
            continue;
50
51
        // P is supposed to be required in A, but past GDAL versions could
52
        // generate features without attributes without a P array
53
0
        GDALPDFObject *poP = poA->GetDictionary()->Get("P");
54
0
        GDALPDFArray *poPArray = nullptr;
55
0
        if (poP != nullptr && poP->GetType() == PDFObjectType_Array)
56
0
            poPArray = poP->GetArray();
57
0
        else
58
0
            poP = nullptr;
59
60
0
        GDALPDFObject *poK = poFeatureObj->GetDictionary()->Get("K");
61
0
        int nK = -1;
62
0
        if (poK != nullptr && poK->GetType() == PDFObjectType_Int)
63
0
            nK = poK->GetInt();
64
65
0
        if (poP)
66
0
        {
67
0
            for (int j = 0; j < poPArray->GetLength(); j++)
68
0
            {
69
0
                GDALPDFObject *poKV = poPArray->Get(j);
70
0
                if (poKV && poKV->GetType() == PDFObjectType_Dictionary)
71
0
                {
72
0
                    GDALPDFObject *poN = poKV->GetDictionary()->Get("N");
73
0
                    GDALPDFObject *poV = poKV->GetDictionary()->Get("V");
74
0
                    if (poN != nullptr &&
75
0
                        poN->GetType() == PDFObjectType_String &&
76
0
                        poV != nullptr)
77
0
                    {
78
0
                        int nIdx = GetLayerDefn()->GetFieldIndex(
79
0
                            poN->GetString().c_str());
80
0
                        OGRFieldType eType = OFTString;
81
0
                        if (poV->GetType() == PDFObjectType_Int)
82
0
                            eType = OFTInteger;
83
0
                        else if (poV->GetType() == PDFObjectType_Real)
84
0
                            eType = OFTReal;
85
0
                        if (nIdx < 0)
86
0
                        {
87
0
                            OGRFieldDefn oField(poN->GetString().c_str(),
88
0
                                                eType);
89
0
                            CreateField(&oField);
90
0
                        }
91
0
                        else if (GetLayerDefn()
92
0
                                         ->GetFieldDefn(nIdx)
93
0
                                         ->GetType() != eType &&
94
0
                                 GetLayerDefn()
95
0
                                         ->GetFieldDefn(nIdx)
96
0
                                         ->GetType() != OFTString)
97
0
                        {
98
0
                            OGRFieldDefn oField(poN->GetString().c_str(),
99
0
                                                OFTString);
100
0
                            AlterFieldDefn(nIdx, &oField, ALTER_TYPE_FLAG);
101
0
                        }
102
0
                    }
103
0
                }
104
0
            }
105
0
        }
106
107
0
        OGRFeature *poFeature = new OGRFeature(GetLayerDefn());
108
0
        if (poPArray)
109
0
        {
110
0
            for (int j = 0; j < poPArray->GetLength(); j++)
111
0
            {
112
0
                GDALPDFObject *poKV = poPArray->Get(j);
113
0
                if (poKV && poKV->GetType() == PDFObjectType_Dictionary)
114
0
                {
115
0
                    GDALPDFObject *poN = poKV->GetDictionary()->Get("N");
116
0
                    GDALPDFObject *poV = poKV->GetDictionary()->Get("V");
117
0
                    if (poN != nullptr &&
118
0
                        poN->GetType() == PDFObjectType_String &&
119
0
                        poV != nullptr)
120
0
                    {
121
0
                        if (poV->GetType() == PDFObjectType_String)
122
0
                            poFeature->SetField(poN->GetString().c_str(),
123
0
                                                poV->GetString().c_str());
124
0
                        else if (poV->GetType() == PDFObjectType_Int)
125
0
                            poFeature->SetField(poN->GetString().c_str(),
126
0
                                                poV->GetInt());
127
0
                        else if (poV->GetType() == PDFObjectType_Real)
128
0
                            poFeature->SetField(poN->GetString().c_str(),
129
0
                                                poV->GetReal());
130
0
                    }
131
0
                }
132
0
            }
133
0
        }
134
135
0
        if (nK >= 0)
136
0
        {
137
0
            OGRGeometry *poGeom = poDS->GetGeometryFromMCID(nK);
138
0
            if (poGeom)
139
0
            {
140
0
                poGeom->assignSpatialReference(GetSpatialRef());
141
0
                poFeature->SetGeometry(poGeom);
142
0
            }
143
0
        }
144
145
0
        OGRGeometry *poGeom = poFeature->GetGeometryRef();
146
0
        if (!bGeomTypeMixed && poGeom != nullptr)
147
0
        {
148
0
            auto poLayerDefn = GetLayerDefn();
149
0
            if (!bGeomTypeSet)
150
0
            {
151
0
                bGeomTypeSet = TRUE;
152
0
                whileUnsealing(poLayerDefn)
153
0
                    ->SetGeomType(poGeom->getGeometryType());
154
0
            }
155
0
            else if (poLayerDefn->GetGeomType() != poGeom->getGeometryType())
156
0
            {
157
0
                bGeomTypeMixed = TRUE;
158
0
                whileUnsealing(poLayerDefn)->SetGeomType(wkbUnknown);
159
0
            }
160
0
        }
161
0
        ICreateFeature(poFeature);
162
163
0
        delete poFeature;
164
0
    }
165
0
}
166
167
/************************************************************************/
168
/*                           TestCapability()                           */
169
/************************************************************************/
170
171
int OGRPDFLayer::TestCapability(const char *pszCap)
172
173
0
{
174
0
    if (EQUAL(pszCap, OLCStringsAsUTF8))
175
0
        return TRUE;
176
0
    else
177
0
        return OGRMemLayer::TestCapability(pszCap);
178
0
}
179
180
/************************************************************************/
181
/*                             GetDataset()                             */
182
/************************************************************************/
183
184
GDALDataset *OGRPDFLayer::GetDataset()
185
0
{
186
0
    return poDS;
187
0
}
188
189
#endif /* HAVE_PDF_READ_SUPPORT */
190
191
/************************************************************************/
192
/*                        OGRPDFWritableLayer()                         */
193
/************************************************************************/
194
195
OGRPDFWritableLayer::OGRPDFWritableLayer(PDFWritableVectorDataset *poDSIn,
196
                                         const char *pszName,
197
                                         OGRSpatialReference *poSRS,
198
                                         OGRwkbGeometryType eGeomType)
199
0
    : OGRMemLayer(pszName, poSRS, eGeomType), poDS(poDSIn)
200
0
{
201
0
}
202
203
/************************************************************************/
204
/*                           ICreateFeature()                           */
205
/************************************************************************/
206
207
OGRErr OGRPDFWritableLayer::ICreateFeature(OGRFeature *poFeature)
208
0
{
209
0
    poDS->SetModified();
210
0
    return OGRMemLayer::ICreateFeature(poFeature);
211
0
}
212
213
/************************************************************************/
214
/*                           TestCapability()                           */
215
/************************************************************************/
216
217
int OGRPDFWritableLayer::TestCapability(const char *pszCap)
218
219
0
{
220
0
    if (EQUAL(pszCap, OLCStringsAsUTF8))
221
0
        return TRUE;
222
0
    else
223
0
        return OGRMemLayer::TestCapability(pszCap);
224
0
}
225
226
/************************************************************************/
227
/*                             GetDataset()                             */
228
/************************************************************************/
229
230
GDALDataset *OGRPDFWritableLayer::GetDataset()
231
0
{
232
0
    return poDS;
233
0
}