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) 2012-2019, Even Rouault <even dot rouault at spatialys dot com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #ifndef PDFCREATECOPY_H_INCLUDED
15 : #define PDFCREATECOPY_H_INCLUDED
16 :
17 : #include "pdfobject.h"
18 : #include "gdal_priv.h"
19 : #include <vector>
20 : #include <map>
21 :
22 : #include "ogr_api.h"
23 : #include "ogr_spatialref.h"
24 :
25 : /* Cf PDF reference v1.7, Appendix C, page 993 */
26 : #define MAXIMUM_SIZE_IN_UNITS 14400
27 :
28 : #define APPLY_GT_X(gt, x, y) ((gt)[0] + (x) * (gt)[1] + (y) * (gt)[2])
29 : #define APPLY_GT_Y(gt, x, y) ((gt)[3] + (x) * (gt)[4] + (y) * (gt)[5])
30 :
31 : typedef enum
32 : {
33 : COMPRESS_NONE,
34 : COMPRESS_DEFLATE,
35 : COMPRESS_JPEG,
36 : COMPRESS_JPEG2000,
37 : COMPRESS_DEFAULT
38 : } PDFCompressMethod;
39 :
40 : struct PDFMargins
41 : {
42 : int nLeft = 0;
43 : int nRight = 0;
44 : int nTop = 0;
45 : int nBottom = 0;
46 : };
47 :
48 : class GDALFakePDFDataset final : public GDALDataset
49 : {
50 : public:
51 10 : GDALFakePDFDataset() = default;
52 : };
53 :
54 : /************************************************************************/
55 : /* GDALPDFWriter */
56 : /************************************************************************/
57 :
58 : class GDALXRefEntry
59 : {
60 : public:
61 : vsi_l_offset nOffset = 0;
62 : int nGen = 0;
63 : int bFree = FALSE;
64 :
65 2882 : GDALXRefEntry() = default;
66 :
67 : explicit GDALXRefEntry(vsi_l_offset nOffsetIn, int nGenIn = 0)
68 : : nOffset(nOffsetIn), nGen(nGenIn)
69 : {
70 : }
71 :
72 5971 : GDALXRefEntry(const GDALXRefEntry &oOther)
73 5971 : : nOffset(oOther.nOffset), nGen(oOther.nGen), bFree(oOther.bFree)
74 : {
75 5971 : }
76 :
77 : GDALXRefEntry &operator=(const GDALXRefEntry &oOther)
78 : {
79 : nOffset = oOther.nOffset;
80 : nGen = oOther.nGen;
81 : bFree = oOther.bFree;
82 : return *this;
83 : }
84 : };
85 :
86 : class GDALPDFImageDesc
87 : {
88 : public:
89 : GDALPDFObjectNum nImageId{};
90 : double dfXOff = 0;
91 : double dfYOff = 0;
92 : double dfXSize = 0;
93 : double dfYSize = 0;
94 : };
95 :
96 : class GDALPDFLayerDesc
97 : {
98 : public:
99 : GDALPDFObjectNum nOCGId{};
100 : GDALPDFObjectNum nOCGTextId{};
101 : GDALPDFObjectNum nFeatureLayerId{};
102 : CPLString osLayerName{};
103 : int bWriteOGRAttributes{false};
104 : std::vector<GDALPDFObjectNum> aIds{};
105 : std::vector<GDALPDFObjectNum> aIdsText{};
106 : std::vector<GDALPDFObjectNum> aUserPropertiesIds{};
107 : std::vector<CPLString> aFeatureNames{};
108 : std::vector<CPLString> aosIncludedFields{};
109 : };
110 :
111 : class GDALPDFRasterDesc
112 : {
113 : public:
114 : GDALPDFObjectNum nOCGRasterId{};
115 : std::vector<GDALPDFImageDesc> asImageDesc{};
116 : };
117 :
118 : class GDALPDFPageContext
119 : {
120 : public:
121 : GDALDataset *poClippingDS = nullptr;
122 : PDFCompressMethod eStreamCompressMethod = COMPRESS_NONE;
123 : double dfDPI{0};
124 : PDFMargins sMargins{};
125 : GDALPDFObjectNum nPageId{};
126 : GDALPDFObjectNum nContentId{};
127 : GDALPDFObjectNum nResourcesId{};
128 : std::vector<GDALPDFLayerDesc> asVectorDesc{};
129 : std::vector<GDALPDFRasterDesc> asRasterDesc{};
130 : GDALPDFObjectNum nAnnotsId{};
131 : std::vector<GDALPDFObjectNum> anAnnotationsId{};
132 : };
133 :
134 : class GDALPDFOCGDesc
135 : {
136 : public:
137 : GDALPDFObjectNum nId{};
138 : GDALPDFObjectNum nParentId{};
139 : CPLString osLayerName{};
140 : };
141 :
142 : class GDALPDFBaseWriter
143 : {
144 : protected:
145 : VSILFILE *m_fp = nullptr;
146 : bool m_bInWriteObj = false;
147 : std::vector<GDALXRefEntry> m_asXRefEntries{};
148 : GDALPDFObjectNum m_nPageResourceId{};
149 : GDALPDFObjectNum m_nCatalogId{};
150 : int m_nCatalogGen = 0;
151 : GDALPDFObjectNum m_nInfoId{};
152 : int m_nInfoGen = 0;
153 : GDALPDFObjectNum m_nXMPId{};
154 : int m_nXMPGen = 0;
155 : GDALPDFObjectNum m_nStructTreeRootId{};
156 : GDALPDFObjectNum m_nNamesId{};
157 :
158 : GDALPDFObjectNum m_nContentLengthId{};
159 : VSILFILE *m_fpBack = nullptr;
160 : VSILFILE *m_fpGZip = nullptr;
161 : vsi_l_offset m_nStreamStart = 0;
162 :
163 : std::vector<GDALPDFObjectNum> m_asPageId{};
164 : std::vector<GDALPDFOCGDesc> m_asOCGs{};
165 : std::map<CPLString, GDALPDFImageDesc> m_oMapSymbolFilenameToDesc{};
166 :
167 : public:
168 : struct ObjectStyle
169 : {
170 : unsigned int nPenR = 0;
171 : unsigned int nPenG = 0;
172 : unsigned int nPenB = 0;
173 : unsigned int nPenA = 255;
174 : unsigned int nBrushR = 127;
175 : unsigned int nBrushG = 127;
176 : unsigned int nBrushB = 127;
177 : unsigned int nBrushA = 127;
178 : unsigned int nTextR = 0;
179 : unsigned int nTextG = 0;
180 : unsigned int nTextB = 0;
181 : unsigned int nTextA = 255;
182 : int bSymbolColorDefined = FALSE;
183 : unsigned int nSymbolR = 0;
184 : unsigned int nSymbolG = 0;
185 : unsigned int nSymbolB = 0;
186 : unsigned int nSymbolA = 255;
187 : bool bHasPenBrushOrSymbol = false;
188 : CPLString osTextFont{};
189 : bool bTextBold = false;
190 : bool bTextItalic = false;
191 : double dfTextSize = 12.0;
192 : double dfTextAngle = 0.0;
193 : double dfTextStretch = 1.0;
194 : double dfTextDx = 0.0;
195 : double dfTextDy = 0.0;
196 : int nTextAnchor = 1;
197 : double dfPenWidth = 1.0;
198 : double dfSymbolSize = 5.0;
199 : CPLString osDashArray{};
200 : CPLString osLabelText{};
201 : CPLString osSymbolId{};
202 : GDALPDFObjectNum nImageSymbolId{};
203 : int nImageWidth = 0;
204 : int nImageHeight = 0;
205 : };
206 :
207 : protected:
208 : explicit GDALPDFBaseWriter(VSILFILE *fp);
209 : ~GDALPDFBaseWriter();
210 :
211 : GDALPDFObjectNum AllocNewObject();
212 :
213 : void StartObj(const GDALPDFObjectNum &nObjectId, int nGen = 0);
214 : void EndObj();
215 :
216 : void StartObjWithStream(const GDALPDFObjectNum &nObjectId,
217 : GDALPDFDictionaryRW &oDict, bool bDeflate);
218 : void EndObjWithStream();
219 :
220 : void StartNewDoc();
221 : void Close();
222 :
223 : void WriteXRefTableAndTrailer(bool bUpdate, vsi_l_offset nLastStartXRef);
224 :
225 : GDALPDFObjectNum WriteSRS_ISO32000(GDALDataset *poSrcDS, double dfUserUnit,
226 : const char *pszNEATLINE,
227 : PDFMargins *psMargins,
228 : int bWriteViewport);
229 : GDALPDFObjectNum WriteSRS_OGC_BP(GDALDataset *poSrcDS, double dfUserUnit,
230 : const char *pszNEATLINE,
231 : PDFMargins *psMargins);
232 : static GDALPDFDictionaryRW *
233 : GDALPDFBuildOGC_BP_Projection(const OGRSpatialReference *poSRS);
234 :
235 : GDALPDFObjectNum
236 : WriteOCG(const char *pszLayerName,
237 : const GDALPDFObjectNum &nParentId = GDALPDFObjectNum());
238 :
239 : GDALPDFObjectNum
240 : WriteBlock(GDALDataset *poSrcDS, int nXOff, int nYOff, int nReqXSize,
241 : int nReqYSize, const GDALPDFObjectNum &nColorTableIdIn,
242 : PDFCompressMethod eCompressMethod, int nPredictor,
243 : int nJPEGQuality, const char *pszJPEG2000_DRIVER,
244 : GDALProgressFunc pfnProgress, void *pProgressData);
245 : GDALPDFObjectNum WriteMask(GDALDataset *poSrcDS, int nXOff, int nYOff,
246 : int nReqXSize, int nReqYSize,
247 : PDFCompressMethod eCompressMethod);
248 :
249 : GDALPDFObjectNum WriteColorTable(GDALDataset *poSrcDS);
250 :
251 : void GetObjectStyle(
252 : const char *pszStyleString, OGRFeatureH hFeat,
253 : const double adfMatrix[4],
254 : std::map<CPLString, GDALPDFImageDesc> oMapSymbolFilenameToDesc,
255 : ObjectStyle &os);
256 : static CPLString GenerateDrawingStream(OGRGeometryH hGeom,
257 : const double adfMatrix[4],
258 : ObjectStyle &os, double dfRadius);
259 : GDALPDFObjectNum
260 : WriteAttributes(OGRFeatureH hFeat,
261 : const std::vector<CPLString> &aosIncludedFields,
262 : const char *pszOGRDisplayField, int nMCID,
263 : const GDALPDFObjectNum &oParent,
264 : const GDALPDFObjectNum &oPage, CPLString &osOutFeatureName);
265 :
266 : GDALPDFObjectNum WriteLabel(OGRGeometryH hGeom, const double adfMatrix[4],
267 : ObjectStyle &os,
268 : PDFCompressMethod eStreamCompressMethod,
269 : double bboxXMin, double bboxYMin,
270 : double bboxXMax, double bboxYMax);
271 :
272 : GDALPDFObjectNum WriteLink(OGRFeatureH hFeat, const char *pszOGRLinkField,
273 : const double adfMatrix[4], int bboxXMin,
274 : int bboxYMin, int bboxXMax, int bboxYMax);
275 :
276 : static void ComputeIntBBox(OGRGeometryH hGeom, const OGREnvelope &sEnvelope,
277 : const double adfMatrix[4], const ObjectStyle &os,
278 : double dfRadius, int &bboxXMin, int &bboxYMin,
279 : int &bboxXMax, int &bboxYMax);
280 :
281 : GDALPDFObjectNum WriteJavascript(const char *pszJavascript, bool bDeflate);
282 :
283 : public:
284 : GDALPDFObjectNum SetInfo(GDALDataset *poSrcDS, char **papszOptions);
285 : GDALPDFObjectNum SetInfo(const char *pszAUTHOR, const char *pszPRODUCER,
286 : const char *pszCREATOR,
287 : const char *pszCREATION_DATE,
288 : const char *pszSUBJECT, const char *pszTITLE,
289 : const char *pszKEYWORDS);
290 : GDALPDFObjectNum SetXMP(GDALDataset *poSrcDS, const char *pszXMP);
291 :
292 : private:
293 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFBaseWriter)
294 : };
295 :
296 : class GDALPDFUpdateWriter final : public GDALPDFBaseWriter
297 : {
298 : bool m_bUpdateNeeded = false;
299 : vsi_l_offset m_nLastStartXRef = 0;
300 : int m_nLastXRefSize = 0;
301 :
302 : public:
303 : explicit GDALPDFUpdateWriter(VSILFILE *fpIn);
304 : ~GDALPDFUpdateWriter();
305 :
306 : void Close();
307 :
308 : const GDALPDFObjectNum &GetCatalogNum() const
309 : {
310 : return m_nCatalogId;
311 : }
312 :
313 : int GetCatalogGen() const
314 : {
315 : return m_nCatalogGen;
316 : }
317 :
318 : int ParseTrailerAndXRef();
319 : void UpdateProj(GDALDataset *poSrcDS, double dfDPI,
320 : GDALPDFDictionaryRW *poPageDict,
321 : const GDALPDFObjectNum &nPageId, int nPageGen);
322 : void UpdateInfo(GDALDataset *poSrcDS);
323 : void UpdateXMP(GDALDataset *poSrcDS, GDALPDFDictionaryRW *poCatalogDict);
324 : };
325 :
326 : class GDALPDFWriter final : public GDALPDFBaseWriter
327 : {
328 : GDALPDFPageContext oPageContext{};
329 :
330 : CPLString m_osOffLayers{};
331 : CPLString m_osExclusiveLayers{};
332 :
333 : void WritePages();
334 :
335 : public:
336 : explicit GDALPDFWriter(VSILFILE *fpIn);
337 : ~GDALPDFWriter();
338 :
339 : void Close();
340 :
341 : bool StartPage(GDALDataset *poSrcDS, double dfDPI, bool bWriteUserUnit,
342 : const char *pszGEO_ENCODING, const char *pszNEATLINE,
343 : PDFMargins *psMargins,
344 : PDFCompressMethod eStreamCompressMethod, int bHasOGRData);
345 :
346 : bool WriteImagery(GDALDataset *poDS, const char *pszLayerName,
347 : PDFCompressMethod eCompressMethod, int nPredictor,
348 : int nJPEGQuality, const char *pszJPEG2000_DRIVER,
349 : int nBlockXSize, int nBlockYSize,
350 : GDALProgressFunc pfnProgress, void *pProgressData);
351 :
352 : bool WriteClippedImagery(GDALDataset *poDS, const char *pszLayerName,
353 : PDFCompressMethod eCompressMethod, int nPredictor,
354 : int nJPEGQuality, const char *pszJPEG2000_DRIVER,
355 : int nBlockXSize, int nBlockYSize,
356 : GDALProgressFunc pfnProgress, void *pProgressData);
357 : bool WriteOGRDataSource(const char *pszOGRDataSource,
358 : const char *pszOGRDisplayField,
359 : const char *pszOGRDisplayLayerNames,
360 : const char *pszOGRLinkField,
361 : int bWriteOGRAttributes);
362 :
363 : GDALPDFLayerDesc StartOGRLayer(const std::string &osLayerName,
364 : int bWriteOGRAttributes);
365 : void EndOGRLayer(GDALPDFLayerDesc &osVectorDesc);
366 :
367 : int WriteOGRLayer(GDALDatasetH hDS, int iLayer,
368 : const char *pszOGRDisplayField,
369 : const char *pszOGRLinkField,
370 : const std::string &osLayerName, int bWriteOGRAttributes,
371 : int &iObj);
372 :
373 : int WriteOGRFeature(GDALPDFLayerDesc &osVectorDesc, OGRFeatureH hFeat,
374 : OGRCoordinateTransformationH hCT,
375 : const char *pszOGRDisplayField,
376 : const char *pszOGRLinkField, int bWriteOGRAttributes,
377 : int &iObj);
378 :
379 : GDALPDFObjectNum WriteJavascript(const char *pszJavascript);
380 : GDALPDFObjectNum WriteJavascriptFile(const char *pszJavascriptFile);
381 :
382 : int EndPage(const char *pszExtraImages, const char *pszExtraStream,
383 : const char *pszExtraLayerName, const char *pszOffLayers,
384 : const char *pszExclusiveLayers);
385 : };
386 :
387 : GDALDataset *GDALPDFCreateCopy(const char *, GDALDataset *, int, char **,
388 : GDALProgressFunc pfnProgress,
389 : void *pProgressData);
390 :
391 : #endif // PDFCREATECOPY_H_INCLUDED
|