Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: PDF driver
4 : * Purpose: GDALDataset driver for PDF dataset.
5 : * Author: Even Rouault, <even dot rouault at spatialys dot com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2019, Even Rouault <even dot rouault at spatialys dot com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef PDFCREATEFROMCOMPOSITION_H_INCLUDED
14 : #define PDFCREATEFROMCOMPOSITION_H_INCLUDED
15 :
16 : #include "gdal_pdf.h"
17 : #include "pdfcreatecopy.h"
18 : #include "cpl_minixml.h"
19 : #include "ogrsf_frmts.h"
20 : #include "ogr_geometry.h"
21 :
22 : #include <map>
23 : #include <memory>
24 : #include <vector>
25 :
26 : class GDALPDFComposerWriter final : public GDALPDFBaseWriter
27 : {
28 : CPLString m_osJPEG2000Driver{};
29 :
30 : struct TreeOfOCG
31 : {
32 : GDALPDFObjectNum m_nNum{};
33 : bool m_bInitiallyVisible{true};
34 : std::vector<std::unique_ptr<TreeOfOCG>> m_children{};
35 : };
36 :
37 : bool m_bDisplayLayersOnlyOnVisiblePages = false;
38 : TreeOfOCG m_oTreeOfOGC{};
39 : std::map<CPLString, std::vector<GDALPDFObjectNum>>
40 : m_oMapExclusiveOCGIdToOCGs{};
41 :
42 : std::map<CPLString, GDALPDFObjectNum> m_oMapLayerIdToOCG{};
43 :
44 : struct xyPair
45 : {
46 : double x = 0;
47 : double y = 0;
48 :
49 10 : explicit xyPair(double xin = 0.0, double yin = 0.0) : x(xin), y(yin)
50 : {
51 10 : }
52 : };
53 :
54 : struct Georeferencing
55 : {
56 : CPLString m_osID{};
57 : OGRSpatialReference m_oSRS{};
58 : double m_bboxX1{};
59 : double m_bboxY1{};
60 : double m_bboxX2{};
61 : double m_bboxY2{};
62 : double m_adfGT[6]{0, 1, 0, 0, 0, 1};
63 : };
64 :
65 : std::vector<GDALPDFObjectNum> m_anParentElements{};
66 : std::vector<GDALPDFObjectNum> m_anFeatureLayerId{};
67 : std::map<CPLString, GDALPDFObjectNum> m_oMapPageIdToObjectNum{};
68 :
69 : struct PageContext
70 : {
71 : double m_dfWidthInUserUnit = 0;
72 : double m_dfHeightInUserUnit = 0;
73 : CPLString m_osDrawingStream{};
74 : std::vector<GDALPDFObjectNum> m_anFeatureUserProperties{};
75 : int m_nMCID = 0;
76 : PDFCompressMethod m_eStreamCompressMethod = COMPRESS_DEFLATE;
77 : std::map<CPLString, GDALPDFObjectNum> m_oXObjects{};
78 : std::map<CPLString, GDALPDFObjectNum> m_oProperties{};
79 : std::map<CPLString, GDALPDFObjectNum> m_oExtGState{};
80 : std::vector<GDALPDFObjectNum> m_anAnnotationsId{};
81 : std::map<CPLString, Georeferencing> m_oMapGeoreferencedId{};
82 : };
83 :
84 : bool CreateLayerTree(const CPLXMLNode *psNode,
85 : const GDALPDFObjectNum &nParentId, TreeOfOCG *parent);
86 :
87 : struct Action
88 : {
89 12 : virtual ~Action() = default;
90 : };
91 :
92 : struct GotoPageAction final : public Action
93 : {
94 : GDALPDFObjectNum m_nPageDestId{};
95 : double m_dfX1 = 0;
96 : double m_dfX2 = 0;
97 : double m_dfY1 = 0;
98 : double m_dfY2 = 0;
99 : };
100 :
101 : struct SetLayerStateAction final : public Action
102 : {
103 : std::set<GDALPDFObjectNum> m_anONLayers{};
104 : std::set<GDALPDFObjectNum> m_anOFFLayers{};
105 : };
106 :
107 : struct JavascriptAction final : public Action
108 : {
109 : CPLString m_osScript{};
110 : };
111 :
112 : bool ParseActions(const CPLXMLNode *psNode,
113 : std::vector<std::unique_ptr<Action>> &actions);
114 : static GDALPDFDictionaryRW *
115 : SerializeActions(GDALPDFDictionaryRW *poDictForDest,
116 : const std::vector<std::unique_ptr<Action>> &actions);
117 :
118 : struct OutlineItem
119 : {
120 : GDALPDFObjectNum m_nObjId{};
121 : CPLString m_osName{};
122 : bool m_bOpen = true;
123 : int m_nFlags = 0;
124 : std::vector<std::unique_ptr<Action>> m_aoActions{};
125 : std::vector<std::unique_ptr<OutlineItem>> m_aoKids{};
126 : int m_nKidsRecCount = 0;
127 : };
128 :
129 : GDALPDFObjectNum m_nOutlinesId{};
130 :
131 : bool CreateOutlineFirstPass(const CPLXMLNode *psNode,
132 : OutlineItem *poParentItem);
133 : bool SerializeOutlineKids(const OutlineItem *poParentItem);
134 : bool CreateOutline(const CPLXMLNode *psNode);
135 :
136 : void WritePages();
137 :
138 : static GDALPDFArrayRW *CreateOCGOrder(const TreeOfOCG *parent);
139 : static void CollectOffOCG(std::vector<GDALPDFObjectNum> &ar,
140 : const TreeOfOCG *parent);
141 : bool GeneratePage(const CPLXMLNode *psPage);
142 : bool GenerateGeoreferencing(const CPLXMLNode *psGeoreferencing,
143 : double dfWidthInUserUnit,
144 : double dfHeightInUserUnit,
145 : GDALPDFObjectNum &nViewportId,
146 : Georeferencing &georeferencing);
147 :
148 : GDALPDFObjectNum GenerateISO32000_Georeferencing(
149 : OGRSpatialReferenceH hSRS, double bboxX1, double bboxY1, double bboxX2,
150 : double bboxY2, const std::vector<gdal::GCP> &aGCPs,
151 : const std::vector<xyPair> &aBoundingPolygon);
152 :
153 : bool ExploreContent(const CPLXMLNode *psNode, PageContext &oPageContext);
154 : bool WriteRaster(const CPLXMLNode *psNode, PageContext &oPageContext);
155 : bool WriteVector(const CPLXMLNode *psNode, PageContext &oPageContext);
156 : bool WriteVectorLabel(const CPLXMLNode *psNode, PageContext &oPageContext);
157 : void StartBlending(const CPLXMLNode *psNode, PageContext &oPageContext,
158 : double &dfOpacity);
159 : static void EndBlending(const CPLXMLNode *psNode,
160 : PageContext &oPageContext);
161 :
162 : static bool SetupVectorGeoreferencing(
163 : const char *pszGeoreferencingId, OGRLayer *poLayer,
164 : const PageContext &oPageContext, double &dfClippingMinX,
165 : double &dfClippingMinY, double &dfClippingMaxX, double &dfClippingMaxY,
166 : double adfMatrix[4],
167 : std::unique_ptr<OGRCoordinateTransformation> &poCT);
168 :
169 : #ifdef HAVE_PDF_READ_SUPPORT
170 : bool WritePDF(const CPLXMLNode *psNode, PageContext &oPageContext);
171 :
172 : typedef std::map<std::pair<int, int>, GDALPDFObjectNum> RemapType;
173 : GDALPDFObjectNum EmitNewObject(GDALPDFObject *poObj,
174 : RemapType &oRemapObjectRefs);
175 : GDALPDFObjectNum SerializeAndRenumber(GDALPDFObject *poObj);
176 : bool SerializeAndRenumber(CPLString &osStr, GDALPDFObject *poObj,
177 : RemapType &oRemapObjectRefs);
178 : bool SerializeAndRenumberIgnoreRef(CPLString &osStr, GDALPDFObject *poObj,
179 : RemapType &oRemapObjectRefs);
180 : #endif
181 :
182 : public:
183 : explicit GDALPDFComposerWriter(VSILFILE *fp);
184 : ~GDALPDFComposerWriter();
185 :
186 : bool Generate(const CPLXMLNode *psComposition);
187 : void Close();
188 : };
189 :
190 : GDALDataset *GDALPDFCreateFromCompositionFile(const char *pszPDFFilename,
191 : const char *pszXMLFilename);
192 :
193 : #endif // PDFCREATEFROMCOMPOSITION_H_INCLUDED
|