Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: PDF driver
5 : * Author: Even Rouault, <even.rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2023, Even Rouault, <even.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 "pdfdrivercore.h"
30 :
31 : static const char *const szOpenOptionList =
32 : "<OpenOptionList>"
33 : #if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
34 : " <Option name='RENDERING_OPTIONS' type='string-select' "
35 : "description='Which graphical elements to render' "
36 : "default='RASTER,VECTOR,TEXT' "
37 : "alt_config_option='GDAL_PDF_RENDERING_OPTIONS'>"
38 : " <Value>RASTER,VECTOR,TEXT</Value>\n"
39 : " <Value>RASTER,VECTOR</Value>\n"
40 : " <Value>RASTER,TEXT</Value>\n"
41 : " <Value>RASTER</Value>\n"
42 : " <Value>VECTOR,TEXT</Value>\n"
43 : " <Value>VECTOR</Value>\n"
44 : " <Value>TEXT</Value>\n"
45 : " </Option>"
46 : #endif
47 : " <Option name='DPI' type='float' description='Resolution in Dot Per "
48 : "Inch' default='72' alt_config_option='GDAL_PDF_DPI'/>"
49 : " <Option name='USER_PWD' type='string' description='Password' "
50 : "alt_config_option='PDF_USER_PWD'/>"
51 : #ifdef HAVE_MULTIPLE_PDF_BACKENDS
52 : " <Option name='PDF_LIB' type='string-select' description='Which "
53 : "underlying PDF library to use' "
54 : #if defined(HAVE_PDFIUM)
55 : "default='PDFIUM'"
56 : #elif defined(HAVE_POPPLER)
57 : "default='POPPLER'"
58 : #elif defined(HAVE_PODOFO)
59 : "default='PODOFO'"
60 : #endif // ~ default PDF_LIB
61 : " alt_config_option='GDAL_PDF_LIB'>"
62 : #if defined(HAVE_POPPLER)
63 : " <Value>POPPLER</Value>\n"
64 : #endif // HAVE_POPPLER
65 : #if defined(HAVE_PODOFO)
66 : " <Value>PODOFO</Value>\n"
67 : #endif // HAVE_PODOFO
68 : #if defined(HAVE_PDFIUM)
69 : " <Value>PDFIUM</Value>\n"
70 : #endif // HAVE_PDFIUM
71 : " </Option>"
72 : #endif // HAVE_MULTIPLE_PDF_BACKENDS
73 : " <Option name='LAYERS' type='string' description='List of layers (comma "
74 : "separated) to turn ON (or ALL to turn all layers ON)' "
75 : "alt_config_option='GDAL_PDF_LAYERS'/>"
76 : " <Option name='LAYERS_OFF' type='string' description='List of layers "
77 : "(comma separated) to turn OFF' alt_config_option='GDAL_PDF_LAYERS_OFF'/>"
78 : " <Option name='BANDS' type='string-select' description='Number of raster "
79 : "bands' default='3' alt_config_option='GDAL_PDF_BANDS'>"
80 : " <Value>3</Value>\n"
81 : " <Value>4</Value>\n"
82 : " </Option>"
83 : " <Option name='NEATLINE' type='string' description='The name of the "
84 : "neatline to select' alt_config_option='GDAL_PDF_NEATLINE'/>"
85 : "</OpenOptionList>";
86 :
87 2625 : const char *PDFGetOpenOptionList()
88 : {
89 2625 : return szOpenOptionList;
90 : }
91 :
92 : /************************************************************************/
93 : /* PDFDatasetIdentify() */
94 : /************************************************************************/
95 :
96 59685 : int PDFDatasetIdentify(GDALOpenInfo *poOpenInfo)
97 : {
98 59685 : if (STARTS_WITH(poOpenInfo->pszFilename, "PDF:"))
99 60 : return TRUE;
100 59625 : if (STARTS_WITH(poOpenInfo->pszFilename, "PDF_IMAGE:"))
101 0 : return TRUE;
102 :
103 59625 : if (poOpenInfo->nHeaderBytes < 128)
104 49948 : return FALSE;
105 :
106 9677 : return STARTS_WITH((const char *)poOpenInfo->pabyHeader, "%PDF");
107 : }
108 :
109 : /************************************************************************/
110 : /* PDFDriverSetCommonMetadata() */
111 : /************************************************************************/
112 :
113 1230 : void PDFDriverSetCommonMetadata(GDALDriver *poDriver)
114 : {
115 1230 : poDriver->SetDescription(DRIVER_NAME);
116 1230 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
117 1230 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
118 1230 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
119 1230 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Geospatial PDF");
120 1230 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/pdf.html");
121 1230 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "pdf");
122 1230 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte");
123 1230 : poDriver->SetMetadataItem(
124 : GDAL_DMD_CREATIONFIELDDATATYPES,
125 1230 : "Integer Integer64 Real String Date DateTime Time");
126 :
127 : #if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
128 1230 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
129 : #endif
130 :
131 1230 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES");
132 1230 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_READ, "YES");
133 1230 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES");
134 1230 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
135 :
136 : #ifdef HAVE_POPPLER
137 1230 : poDriver->SetMetadataItem("HAVE_POPPLER", "YES");
138 : #endif // HAVE_POPPLER
139 : #ifdef HAVE_PODOFO
140 : poDriver->SetMetadataItem("HAVE_PODOFO", "YES");
141 : #endif // HAVE_PODOFO
142 : #ifdef HAVE_PDFIUM
143 1230 : poDriver->SetMetadataItem("HAVE_PDFIUM", "YES");
144 : #endif // HAVE_PDFIUM
145 :
146 1230 : poDriver->SetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST,
147 1230 : "<LayerCreationOptionList/>");
148 :
149 1230 : poDriver->SetMetadataItem(
150 : GDAL_DMD_CREATIONOPTIONLIST,
151 : "<CreationOptionList>\n"
152 : " <Option name='COMPRESS' type='string-select' "
153 : "description='Compression method for raster data' default='DEFLATE'>\n"
154 : " <Value>NONE</Value>\n"
155 : " <Value>DEFLATE</Value>\n"
156 : " <Value>JPEG</Value>\n"
157 : " <Value>JPEG2000</Value>\n"
158 : " </Option>\n"
159 : " <Option name='STREAM_COMPRESS' type='string-select' "
160 : "description='Compression method for stream objects' "
161 : "default='DEFLATE'>\n"
162 : " <Value>NONE</Value>\n"
163 : " <Value>DEFLATE</Value>\n"
164 : " </Option>\n"
165 : " <Option name='GEO_ENCODING' type='string-select' "
166 : "description='Format of geo-encoding' default='ISO32000'>\n"
167 : " <Value>NONE</Value>\n"
168 : " <Value>ISO32000</Value>\n"
169 : " <Value>OGC_BP</Value>\n"
170 : " <Value>BOTH</Value>\n"
171 : " </Option>\n"
172 : " <Option name='NEATLINE' type='string' description='Neatline'/>\n"
173 : " <Option name='DPI' type='float' description='DPI' default='72'/>\n"
174 : " <Option name='WRITE_USERUNIT' type='boolean' description='Whether "
175 : "the UserUnit parameter must be written'/>\n"
176 : " <Option name='PREDICTOR' type='int' description='Predictor Type "
177 : "(for DEFLATE compression)'/>\n"
178 : " <Option name='JPEG_QUALITY' type='int' description='JPEG quality "
179 : "1-100' default='75'/>\n"
180 : " <Option name='JPEG2000_DRIVER' type='string'/>\n"
181 : " <Option name='TILED' type='boolean' description='Switch to tiled "
182 : "format' default='NO'/>\n"
183 : " <Option name='BLOCKXSIZE' type='int' description='Block Width'/>\n"
184 : " <Option name='BLOCKYSIZE' type='int' description='Block Height'/>\n"
185 : " <Option name='LAYER_NAME' type='string' description='Layer name "
186 : "for raster content'/>\n"
187 : " <Option name='CLIPPING_EXTENT' type='string' description='Clipping "
188 : "extent for main and extra rasters. Format: xmin,ymin,xmax,ymax'/>\n"
189 : " <Option name='EXTRA_RASTERS' type='string' description='List of "
190 : "extra (georeferenced) rasters.'/>\n"
191 : " <Option name='EXTRA_RASTERS_LAYER_NAME' type='string' "
192 : "description='List of layer names for the extra (georeferenced) "
193 : "rasters.'/>\n"
194 : " <Option name='EXTRA_STREAM' type='string' description='Extra data "
195 : "to insert into the page content stream'/>\n"
196 : " <Option name='EXTRA_IMAGES' type='string' description='List of "
197 : "image_file_name,x,y,scale[,link=some_url] (possibly repeated)'/>\n"
198 : " <Option name='EXTRA_LAYER_NAME' type='string' description='Layer "
199 : "name for extra content'/>\n"
200 : " <Option name='MARGIN' type='int' description='Margin around image "
201 : "in user units'/>\n"
202 : " <Option name='LEFT_MARGIN' type='int' description='Left margin in "
203 : "user units'/>\n"
204 : " <Option name='RIGHT_MARGIN' type='int' description='Right margin "
205 : "in user units'/>\n"
206 : " <Option name='TOP_MARGIN' type='int' description='Top margin in "
207 : "user units'/>\n"
208 : " <Option name='BOTTOM_MARGIN' type='int' description='Bottom margin "
209 : "in user units'/>\n"
210 : " <Option name='OGR_DATASOURCE' type='string' description='Name of "
211 : "OGR datasource to display on top of the raster layer'/>\n"
212 : " <Option name='OGR_DISPLAY_FIELD' type='string' description='Name "
213 : "of field to use as the display field in the feature tree'/>\n"
214 : " <Option name='OGR_DISPLAY_LAYER_NAMES' type='string' "
215 : "description='Comma separated list of OGR layer names to display in "
216 : "the feature tree'/>\n"
217 : " <Option name='OGR_WRITE_ATTRIBUTES' type='boolean' "
218 : "description='Whether to write attributes of OGR features' "
219 : "default='YES'/>\n"
220 : " <Option name='OGR_LINK_FIELD' type='string' description='Name of "
221 : "field to use as the URL field to make objects clickable.'/>\n"
222 : " <Option name='XMP' type='string' description='xml:XMP metadata'/>\n"
223 : " <Option name='WRITE_INFO' type='boolean' description='to control "
224 : "whether a Info block must be written' default='YES'/>\n"
225 : " <Option name='AUTHOR' type='string'/>\n"
226 : " <Option name='CREATOR' type='string'/>\n"
227 : " <Option name='CREATION_DATE' type='string'/>\n"
228 : " <Option name='KEYWORDS' type='string'/>\n"
229 : " <Option name='PRODUCER' type='string'/>\n"
230 : " <Option name='SUBJECT' type='string'/>\n"
231 : " <Option name='TITLE' type='string'/>\n"
232 : " <Option name='OFF_LAYERS' type='string' description='Comma "
233 : "separated list of layer names that should be initially hidden'/>\n"
234 : " <Option name='EXCLUSIVE_LAYERS' type='string' description='Comma "
235 : "separated list of layer names, such that only one of those layers can "
236 : "be ON at a time.'/>\n"
237 : " <Option name='JAVASCRIPT' type='string' description='Javascript "
238 : "script to embed and run at file opening'/>\n"
239 : " <Option name='JAVASCRIPT_FILE' type='string' description='Filename "
240 : "of the Javascript script to embed and run at file opening'/>\n"
241 : " <Option name='COMPOSITION_FILE' type='string' description='XML "
242 : "file describing how the PDF should be composed'/>\n"
243 1230 : "</CreationOptionList>\n");
244 :
245 : #ifdef HAVE_PDF_READ_SUPPORT
246 1230 : poDriver->SetMetadataItem(GDAL_DMD_OPENOPTIONLIST, szOpenOptionList);
247 1230 : poDriver->pfnIdentify = PDFDatasetIdentify;
248 1230 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
249 1230 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
250 1230 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES");
251 : #endif
252 :
253 1230 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
254 1230 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
255 1230 : }
256 :
257 : /************************************************************************/
258 : /* DeclareDeferredPDFPlugin() */
259 : /************************************************************************/
260 :
261 : #ifdef PLUGIN_FILENAME
262 1511 : void DeclareDeferredPDFPlugin()
263 : {
264 1511 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
265 : {
266 295 : return;
267 : }
268 1216 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
269 : #ifdef PLUGIN_INSTALLATION_MESSAGE
270 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
271 : PLUGIN_INSTALLATION_MESSAGE);
272 : #endif
273 1216 : PDFDriverSetCommonMetadata(poDriver);
274 1216 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
275 : }
276 : #endif
|