LCOV - code coverage report
Current view: top level - frmts/pdf - pdfdrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 45 46 97.8 %
Date: 2024-05-03 15:49:35 Functions: 4 4 100.0 %

          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

Generated by: LCOV version 1.14