:orphan:

##########
PDF Reader
##########

.. rst-class:: format-title-block

+----------------------------------------------------------------------+
|                **Portable Document Format (PDF)**                    |
+-----------------------------------------+----------------------------+
| **File Extension**                      | PDF [#ext]_                |
+-----------------------------------------+----------------------------+
| **Supported Versions**                  | All versions               |
+-----------------------------------------+----------------------------+
| **Platforms**                           | |wy| |ly| |my| |ay| |iy|   |
+-----------------------------------------+----------------------------+
| :ref:`Tessellation <pdf_support>`       | |t_green| Read from file   |
+-----------------------------------------+----------------------------+
| :ref:`B-rep <pdf_support>`              | |c_green| Supported        |
+-----------------------------------------+----------------------------+
| :ref:`PMI <pdf_support>`                | |c_green| Supported        |
+-----------------------------------------+----------------------------+

Portable Document Format (PDF) is a versatile file format developed by Adobe.
It is commonly used for documents, including text, images, and vector graphics.
The format can also include embedded 3D models, mentioned as **3D annotations**..

Our support for PDF covers reading 3D annotations in :doc:`PRC <prc_reader>` or :doc:`U3D <u3d_reader>` streams stored within any version of a PDF file on all platforms.

.. [#ext] While *.pdf* is the usual extension for PDF files, HOOPS Exchange identifies and reads from PDF files with any extension.

.. _loading_pdf:

Loading a PDF Model
===================

PDF files can contain multiple data streams, each encoding a 3D annotation.
As a result, using basic functions like :cpp:func:`A3DAsmModelFileLoadFromFile` or :cpp:func:`A3DAsmModelFileGet` :ref:`will only work if you are interested in the first 3D annotation stored in the PDF file <pdf_reader_use_load>`, because these functions are designed to handle only a single data stream.

To load 3D content from a PDF file, you first need to extract the 3D data streams using :cpp:func:`A3DGet3DPDFStreams`.
This function retrieves an array of 3D streams, allowing you to choose which one to process.

Handling PRC and U3D Data
-------------------------

Once the 3D streams are extracted, they are stored in a C-style array of :cpp:struct:`A3DStream3DPDFData` objects.
For each stream, you can determine if it contains PRC data by checking the :cpp:member:`~A3DStream3DPDFData::m_bIsPrc` flag.
If the stream is not PRC, it contains U3D data.

You can then dump each stream into files and load them into model files using :cpp:func:`A3DAsmModelFileLoadFromFile`.
PRC streams, however, can be loaded directly from memory using :cpp:func:`A3DAsmModelFileLoadFromPrcStream`.

The following example demonstrates how to load the first 3D stream from a PDF, check its format, and handle the stream appropriately:

.. code-block:: c

   A3DStream3DPDFData* pStream3DPDFData;
   A3DInt32 iNumStreams;
   A3DGet3DPDFStreams((char*) pcFileName, &pStream3DPDFData, &iNumStreams);

   // a real use case might parse every stream in the input file. Here, we just take the first one (pStream3DPDFData[0]).
   if (pStream3DPDFData[0].m_bIsPrc) // test whether the data is PRC or U3D
   {
           // even an input PRC file must be read in memory and mapped into modelfile data structures
           A3DRWParamsPrcReadHelper* pPrcReadHelper;
           A3DAsmModelFileLoadFromPrcStream(pStream3DPDFData[0].m_pcStream, pStream3DPDFData[0].m_iLength, &pPrcReadHelper, ppModelFile);
   }
   else
   {
           // A U3D stream must first be stored as a physical file, then read by A3DAsmModelFileLoadFromFile
           sprintf(tempfilename, "%s.u3d", OUT_FILE);
           FILE * pFile = fopen(tempfilename , "wb");

           fwrite(pStream3DPDFData[0].m_pcStream, 1, pStream3DPDFData[0].m_iLength , pFile);
           fclose(pFile);

           // physical file to stream
           A3DAsmModelFileLoadFromFile(tempfilename, sReadParam, ppModelFile);

           // the temp file can be disposed of afterwards
           remove(tempfilename);
   }

   // Release memory for stream array
   A3DGet3DPDFStreams(0, &pStream3DPDFData, &iNumStreams);

.. _pdf_reader_use_load:

Loading a PDF with A3DAsmModelFileLoadFromFile
----------------------------------------------

You can load a PDF file containing PRC or U3D streams using :cpp:func:`A3DAsmModelFileLoadFromFile`, but there are some limitations:

* Only the first stream in the PDF will be read; additional streams will be ignored.
* If the stream includes annotations, only the first annotation is processed, and subsequent annotations are disregarded.

To load a PDF file using :cpp:func:`A3DAsmModelFileLoadFromFile`, use the :cpp:struct:`A3DParamsLoadData` structure to customize the loading behavior:

.. code-block:: c

   A3DAsmModelFile* pModelFile = 0;

   A3DRWParamsLoadData sReadParam;
   A3D_INITIALIZE_DATA(A3DRWParamsLoadData, sReadParam);
   sReadParam.m_sGeneral.m_bReadSolids = true;

   // ... set other A3DRWParamsLoadData fields as necessary

   A3DAsmModelFileLoadFromFile("path/to/file.pdf", &sReadParam, &pModelFile);

See :doc:`/guide/basic_operations/load_model` for more information about loading model files.

.. _pdf_support:

Support Capabilities
====================

Since our PDF reader reads streams in either a PRC or and U3D format, the support for reading tessellation data, B-rep and PMI depends on these specific readers.

For more information about their support, see :doc:`prc_reader` and :doc:`u3d_reader`.

Limitations
===========

Our PDF reader does not read 3D streams from password-protected PDF files.
