Coverage Report

Created: 2026-08-11 08:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/pdf/ogrpdflayer.cpp
Line
Count
Source
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
56.5k
    : OGRMemLayer(pszName, poSRS, eGeomType), poDS(poDSIn), bGeomTypeSet(FALSE),
25
56.5k
      bGeomTypeMixed(FALSE)
26
56.5k
{
27
56.5k
}
28
29
/************************************************************************/
30
/*                                Fill()                                */
31
/************************************************************************/
32
33
void OGRPDFLayer::Fill(GDALPDFArray *poArray)
34
2.14k
{
35
32.2k
    for (int i = 0; i < poArray->GetLength(); i++)
36
30.1k
    {
37
30.1k
        GDALPDFObject *poFeatureObj = poArray->Get(i);
38
30.1k
        if (poFeatureObj == nullptr ||
39
29.7k
            poFeatureObj->GetType() != PDFObjectType_Dictionary)
40
3.53k
            continue;
41
42
26.6k
        GDALPDFObject *poA = poFeatureObj->GetDictionary()->Get("A");
43
26.6k
        if (!(poA != nullptr && poA->GetType() == PDFObjectType_Dictionary))
44
129
            continue;
45
46
26.4k
        auto poO = poA->GetDictionary()->Get("O");
47
26.4k
        if (!(poO && poO->GetType() == PDFObjectType_Name &&
48
26.4k
              poO->GetName() == "UserProperties"))
49
37
            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
26.4k
        GDALPDFObject *poP = poA->GetDictionary()->Get("P");
54
26.4k
        GDALPDFArray *poPArray = nullptr;
55
26.4k
        if (poP != nullptr && poP->GetType() == PDFObjectType_Array)
56
26.4k
            poPArray = poP->GetArray();
57
37
        else
58
37
            poP = nullptr;
59
60
26.4k
        GDALPDFObject *poK = poFeatureObj->GetDictionary()->Get("K");
61
26.4k
        int nK = -1;
62
26.4k
        if (poK != nullptr && poK->GetType() == PDFObjectType_Int)
63
26.4k
            nK = poK->GetInt();
64
65
26.4k
        if (poP)
66
26.4k
        {
67
84.3k
            for (int j = 0; j < poPArray->GetLength(); j++)
68
57.9k
            {
69
57.9k
                GDALPDFObject *poKV = poPArray->Get(j);
70
57.9k
                if (poKV && poKV->GetType() == PDFObjectType_Dictionary)
71
53.6k
                {
72
53.6k
                    GDALPDFObject *poN = poKV->GetDictionary()->Get("N");
73
53.6k
                    GDALPDFObject *poV = poKV->GetDictionary()->Get("V");
74
53.6k
                    if (poN != nullptr &&
75
52.1k
                        poN->GetType() == PDFObjectType_String &&
76
52.1k
                        poV != nullptr)
77
52.1k
                    {
78
52.1k
                        int nIdx = GetLayerDefn()->GetFieldIndex(
79
52.1k
                            poN->GetString().c_str());
80
52.1k
                        OGRFieldType eType = OFTString;
81
52.1k
                        if (poV->GetType() == PDFObjectType_Int)
82
510
                            eType = OFTInteger;
83
51.6k
                        else if (poV->GetType() == PDFObjectType_Real)
84
35
                            eType = OFTReal;
85
52.1k
                        if (nIdx < 0)
86
3.92k
                        {
87
3.92k
                            OGRFieldDefn oField(poN->GetString().c_str(),
88
3.92k
                                                eType);
89
3.92k
                            CreateField(&oField);
90
3.92k
                        }
91
48.2k
                        else if (GetLayerDefn()
92
48.2k
                                         ->GetFieldDefn(nIdx)
93
48.2k
                                         ->GetType() != eType &&
94
43
                                 GetLayerDefn()
95
43
                                         ->GetFieldDefn(nIdx)
96
43
                                         ->GetType() != OFTString)
97
20
                        {
98
20
                            OGRFieldDefn oField(poN->GetString().c_str(),
99
20
                                                OFTString);
100
20
                            AlterFieldDefn(nIdx, &oField, ALTER_TYPE_FLAG);
101
20
                        }
102
52.1k
                    }
103
53.6k
                }
104
57.9k
            }
105
26.4k
        }
106
107
26.4k
        OGRFeature *poFeature = new OGRFeature(GetLayerDefn());
108
26.4k
        if (poPArray)
109
26.4k
        {
110
84.3k
            for (int j = 0; j < poPArray->GetLength(); j++)
111
57.9k
            {
112
57.9k
                GDALPDFObject *poKV = poPArray->Get(j);
113
57.9k
                if (poKV && poKV->GetType() == PDFObjectType_Dictionary)
114
53.6k
                {
115
53.6k
                    GDALPDFObject *poN = poKV->GetDictionary()->Get("N");
116
53.6k
                    GDALPDFObject *poV = poKV->GetDictionary()->Get("V");
117
53.6k
                    if (poN != nullptr &&
118
52.1k
                        poN->GetType() == PDFObjectType_String &&
119
52.1k
                        poV != nullptr)
120
52.1k
                    {
121
52.1k
                        if (poV->GetType() == PDFObjectType_String)
122
51.6k
                            poFeature->SetField(poN->GetString().c_str(),
123
51.6k
                                                poV->GetString().c_str());
124
546
                        else if (poV->GetType() == PDFObjectType_Int)
125
510
                            poFeature->SetField(poN->GetString().c_str(),
126
510
                                                poV->GetInt());
127
36
                        else if (poV->GetType() == PDFObjectType_Real)
128
35
                            poFeature->SetField(poN->GetString().c_str(),
129
35
                                                poV->GetReal());
130
52.1k
                    }
131
53.6k
                }
132
57.9k
            }
133
26.4k
        }
134
135
26.4k
        if (nK >= 0)
136
26.4k
        {
137
26.4k
            OGRGeometry *poGeom = poDS->GetGeometryFromMCID(nK);
138
26.4k
            if (poGeom)
139
17.7k
            {
140
17.7k
                poGeom->assignSpatialReference(GetSpatialRef());
141
17.7k
                poFeature->SetGeometry(poGeom);
142
17.7k
            }
143
26.4k
        }
144
145
26.4k
        OGRGeometry *poGeom = poFeature->GetGeometryRef();
146
26.4k
        if (!bGeomTypeMixed && poGeom != nullptr)
147
9.93k
        {
148
9.93k
            auto poLayerDefn = GetLayerDefn();
149
9.93k
            if (!bGeomTypeSet)
150
1.83k
            {
151
1.83k
                bGeomTypeSet = TRUE;
152
1.83k
                whileUnsealing(poLayerDefn)
153
1.83k
                    ->SetGeomType(poGeom->getGeometryType());
154
1.83k
            }
155
8.10k
            else if (poLayerDefn->GetGeomType() != poGeom->getGeometryType())
156
513
            {
157
513
                bGeomTypeMixed = TRUE;
158
513
                whileUnsealing(poLayerDefn)->SetGeomType(wkbUnknown);
159
513
            }
160
9.93k
        }
161
26.4k
        ICreateFeature(poFeature);
162
163
26.4k
        delete poFeature;
164
26.4k
    }
165
2.14k
}
166
167
/************************************************************************/
168
/*                           TestCapability()                           */
169
/************************************************************************/
170
171
int OGRPDFLayer::TestCapability(const char *pszCap) const
172
173
1.32k
{
174
1.32k
    if (EQUAL(pszCap, OLCStringsAsUTF8))
175
0
        return TRUE;
176
1.32k
    else
177
1.32k
        return OGRMemLayer::TestCapability(pszCap);
178
1.32k
}
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
7.69k
    : OGRMemLayer(pszName, poSRS, eGeomType), poDS(poDSIn)
200
7.69k
{
201
7.69k
}
202
203
/************************************************************************/
204
/*                           ICreateFeature()                           */
205
/************************************************************************/
206
207
OGRErr OGRPDFWritableLayer::ICreateFeature(OGRFeature *poFeature)
208
2.59M
{
209
2.59M
    poDS->SetModified();
210
2.59M
    return OGRMemLayer::ICreateFeature(poFeature);
211
2.59M
}
212
213
/************************************************************************/
214
/*                           TestCapability()                           */
215
/************************************************************************/
216
217
int OGRPDFWritableLayer::TestCapability(const char *pszCap) const
218
219
36.5k
{
220
36.5k
    if (EQUAL(pszCap, OLCStringsAsUTF8))
221
0
        return TRUE;
222
36.5k
    else
223
36.5k
        return OGRMemLayer::TestCapability(pszCap);
224
36.5k
}
225
226
/************************************************************************/
227
/*                             GetDataset()                             */
228
/************************************************************************/
229
230
GDALDataset *OGRPDFWritableLayer::GetDataset()
231
0
{
232
0
    return poDS;
233
0
}