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