Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/inc/pdf/pdfwriter_impl.hxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#pragma once
21
22
#include <sal/config.h>
23
24
#include <map>
25
#include <list>
26
#include <unordered_map>
27
#include <unordered_set>
28
#include <memory>
29
#include <string_view>
30
#include <vector>
31
#include <stack>
32
#include <variant>
33
34
#include <pdf/ResourceDict.hxx>
35
#include <pdf/BitmapID.hxx>
36
#include <pdf/Matrix3.hxx>
37
38
#include <com/sun/star/lang/Locale.hpp>
39
#include <com/sun/star/util/XURLTransformer.hpp>
40
#include <osl/file.hxx>
41
#include <rtl/strbuf.hxx>
42
#include <rtl/ustring.hxx>
43
#include <tools/gen.hxx>
44
#include <vcl/alpha.hxx>
45
#include <vcl/bitmap.hxx>
46
#include <vcl/gradient.hxx>
47
#include <vcl/graphictools.hxx>
48
#include <vcl/hatch.hxx>
49
#include <vcl/virdev.hxx>
50
#include <vcl/pdfwriter.hxx>
51
#include <vcl/wall.hxx>
52
#include <o3tl/safeint.hxx>
53
#include <o3tl/typed_flags_set.hxx>
54
#include <o3tl/lru_map.hxx>
55
#include <comphelper/hash.hxx>
56
#include <tools/stream.hxx>
57
#include <vcl/BinaryDataContainer.hxx>
58
#include <vcl/pdf/PDFNote.hxx>
59
60
#include <vcl/filter/pdfobjectcontainer.hxx>
61
#include <vcl/settings.hxx>
62
#include <pdf/ExternalPDFStreams.hxx>
63
#include <pdf/pdfbuildin_fonts.hxx>
64
#include <salgdi.hxx>
65
66
class FontSubsetInfo;
67
class ZCodec;
68
69
namespace vcl::pdf
70
{
71
72
enum class GraphicsStateUpdateFlags {
73
    Font                  = 0x0001,
74
    MapMode               = 0x0002,
75
    LineColor             = 0x0004,
76
    FillColor             = 0x0008,
77
    ClipRegion            = 0x0040,
78
    LayoutMode            = 0x0100,
79
    TransparentPercent    = 0x0200,
80
    DigitLanguage         = 0x0400,
81
    All                   = 0x077f
82
};
83
84
} // end vcl::pdf
85
86
namespace o3tl {
87
    template<> struct typed_flags<vcl::pdf::GraphicsStateUpdateFlags> : is_typed_flags<vcl::pdf::GraphicsStateUpdateFlags, 0x077f> {};
88
}
89
90
namespace vcl
91
{
92
93
using namespace vcl::pdf;
94
95
namespace filter
96
{
97
class PDFObjectElement;
98
}
99
100
namespace pdf
101
{
102
struct PDFPage
103
{
104
    VclPtr<PDFWriterImpl>       m_pWriter;
105
    double                      m_nPageWidth;           // in inch/72
106
    double                      m_nPageHeight;          // in inch/72
107
    /**
108
     * A positive number that gives the size of default user space units, in multiples of points.
109
     * Typically 1, larger if page size is > 508 cm.
110
     */
111
    sal_Int32 m_nUserUnit;
112
    PDFWriter::Orientation      m_eOrientation;
113
    sal_Int32                   m_nPageObject;
114
    std::vector<sal_Int32>      m_aStreamObjects;
115
    sal_Int32                   m_nStreamLengthObject;
116
    sal_uInt64                  m_nBeginStreamPos;
117
    std::vector<sal_Int32>      m_aAnnotations;
118
    std::vector<sal_Int32>      m_aMCIDParents;
119
    PDFWriter::PageTransition   m_eTransition;
120
    sal_uInt32                  m_nTransTime;
121
122
    PDFPage( PDFWriterImpl* pWriter, double nPageWidth, double nPageHeight, PDFWriter::Orientation eOrientation );
123
124
    void beginStream();
125
    void endStream();
126
    bool emit( sal_Int32 nParentPage );
127
128
    // converts point from ref device coordinates to
129
    // page coordinates and appends the point to the buffer
130
    // if pOutPoint is set it will be updated to the emitted point
131
    // (in PDF map mode, that is 10th of point)
132
    void appendPoint( const Point& rPoint, OStringBuffer& rBuffer ) const;
133
    // appends a B2DPoint without further transformation
134
    void appendPixelPoint( const basegfx::B2DPoint& rPoint, OStringBuffer& rBuffer ) const;
135
    // appends a rectangle
136
    void appendRect( const tools::Rectangle& rRect, OStringBuffer& rBuffer ) const;
137
    // converts a rectangle to 10th points page space
138
    void convertRect( tools::Rectangle& rRect ) const;
139
    // appends a polygon optionally closing it
140
    void appendPolygon( const tools::Polygon& rPoly, OStringBuffer& rBuffer, bool bClose = true ) const;
141
    // appends a polygon optionally closing it
142
    void appendPolygon( const basegfx::B2DPolygon& rPoly, OStringBuffer& rBuffer ) const;
143
    // appends a polypolygon optionally closing the subpaths
144
    void appendPolyPolygon( const tools::PolyPolygon& rPolyPoly, OStringBuffer& rBuffer ) const;
145
    // appends a polypolygon optionally closing the subpaths
146
    void appendPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly, OStringBuffer& rBuffer ) const;
147
    // converts a length (either vertical or horizontal; this
148
    // can be important if the source MapMode is not
149
    // symmetrical) to page length and appends it to the buffer
150
    // if pOutLength is set it will be updated to the emitted length
151
    // (in PDF map mode, that is 10th of point)
152
    void appendMappedLength( sal_Int32 nLength, OStringBuffer& rBuffer, bool bVertical = true, sal_Int32* pOutLength = nullptr ) const;
153
    // the same for double values
154
    void appendMappedLength( double fLength, OStringBuffer& rBuffer, bool bVertical = true, sal_Int32 nPrecision = 5 ) const;
155
    // appends LineInfo
156
    // returns false if too many dash array entry were created for
157
    // the implementation limits of some PDF readers
158
    bool appendLineInfo( const LineInfo& rInfo, OStringBuffer& rBuffer ) const;
159
    // appends a horizontal waveline with vertical offset (helper for drawWaveLine)
160
    void appendWaveLine( sal_Int32 nLength, sal_Int32 nYOffset, sal_Int32 nDelta, OStringBuffer& rBuffer ) const;
161
162
    void appendMatrix3(Matrix3 const & rMatrix, OStringBuffer& rBuffer);
163
164
    double getHeight() const;
165
};
166
167
/// Contains information to emit a reference XObject.
168
struct ReferenceXObjectEmit
169
{
170
    /// ID of the Form XObject, if any.
171
    sal_Int32 m_nFormObject;
172
    /// ID of the vector/embedded object, if m_nFormObject is used.
173
    sal_Int32 m_nEmbeddedObject;
174
    /// ID of the bitmap object, if m_nFormObject is used.
175
    sal_Int32 m_nBitmapObject;
176
    /// Size of the bitmap replacement, in pixels.
177
    Size m_aPixelSize;
178
    /// PDF data from the graphic object, if not writing a reference XObject.
179
    sal_Int32 m_nExternalPDFDataIndex;
180
    sal_Int32 m_nExternalPDFPageIndex;
181
182
    ReferenceXObjectEmit()
183
0
        : m_nFormObject(0)
184
0
        , m_nEmbeddedObject(0)
185
0
        , m_nBitmapObject(0)
186
0
        , m_nExternalPDFDataIndex(-1)
187
0
        , m_nExternalPDFPageIndex(-1)
188
0
    {
189
0
    }
190
191
    /// Returns the ID one should use when referring to this bitmap.
192
    sal_Int32 getObject() const;
193
194
    bool hasExternalPDFData() const
195
0
    {
196
0
        return m_nExternalPDFDataIndex >= 0;
197
0
    }
198
};
199
200
struct BitmapEmit
201
{
202
    BitmapID    m_aID;
203
    Bitmap      m_aBitmap;
204
    sal_Int32   m_nObject;
205
    ReferenceXObjectEmit m_aReferenceXObject;
206
207
    BitmapEmit()
208
0
        : m_nObject(0)
209
0
    {
210
0
    }
211
};
212
213
struct JPGEmit
214
{
215
    BitmapID            m_aID;
216
    std::unique_ptr<SvMemoryStream>
217
                        m_pStream;
218
    AlphaMask           m_aAlphaMask;
219
    sal_Int32           m_nObject;
220
    bool                m_bTrueColor;
221
    ReferenceXObjectEmit m_aReferenceXObject;
222
223
    JPGEmit()
224
0
        : m_nObject(0)
225
0
        , m_bTrueColor(false)
226
0
    {
227
0
    }
228
};
229
230
struct GradientEmit
231
{
232
    Gradient    m_aGradient;
233
    Size        m_aSize;
234
    sal_Int32   m_nObject;
235
};
236
237
// for tilings (drawWallpaper, begin/endPattern)
238
struct TilingEmit
239
{
240
    sal_Int32                   m_nObject;
241
    tools::Rectangle                   m_aRectangle;
242
    Size                        m_aCellSize;
243
    SvtGraphicFill::Transform   m_aTransform;
244
    ResourceDict                m_aResources;
245
    std::unique_ptr<SvMemoryStream> m_pTilingStream;
246
247
    TilingEmit()
248
0
            : m_nObject( 0 )
249
0
    {}
250
};
251
252
// for transparency group XObjects
253
struct TransparencyEmit
254
{
255
    sal_Int32           m_nObject;
256
    sal_Int32           m_nExtGStateObject;
257
    double              m_fAlpha;
258
    tools::Rectangle    m_aBoundRect;
259
    std::unique_ptr<SvMemoryStream>  m_pContentStream;
260
261
    TransparencyEmit()
262
8
            : m_nObject( 0 ),
263
8
              m_nExtGStateObject( -1 ),
264
8
              m_fAlpha( 0.0 )
265
8
    {}
266
};
267
268
// font subsets
269
270
struct ColorLayer
271
{
272
    sal_Int32 m_nFontID;
273
    sal_uInt8 m_nSubsetGlyphID;
274
    uint32_t m_nColorIndex;
275
};
276
277
class GlyphEmit
278
{
279
    // performance: actually this should probably a vector;
280
    std::vector<sal_Ucs>            m_CodeUnits;
281
    sal_uInt8                       m_nSubsetGlyphID;
282
    sal_Int32                       m_nGlyphWidth;
283
    std::vector<ColorLayer>         m_aColorLayers;
284
    font::RawFontData               m_aColorBitmap;
285
    tools::Rectangle                m_aRect;
286
    basegfx::B2DPolyPolygon         m_aOutline;
287
288
public:
289
210k
    GlyphEmit() : m_nSubsetGlyphID(0), m_nGlyphWidth(0)
290
210k
    {
291
210k
    }
292
293
210k
    void setGlyphId( sal_uInt8 i_nId ) { m_nSubsetGlyphID = i_nId; }
294
210k
    sal_uInt8 getGlyphId() const { return m_nSubsetGlyphID; }
295
296
210k
    void setGlyphWidth( sal_Int32 nWidth ) { m_nGlyphWidth = nWidth; }
297
210k
    sal_Int32 getGlyphWidth() const { return m_nGlyphWidth; }
298
299
0
    void addColorLayer(ColorLayer aLayer) { m_aColorLayers.push_back(aLayer); }
300
0
    const std::vector<ColorLayer>& getColorLayers() const { return m_aColorLayers; }
301
302
    void setColorBitmap(font::RawFontData aData, tools::Rectangle aRect)
303
0
    {
304
0
        m_aColorBitmap = aData;
305
0
        m_aRect = aRect;
306
0
    }
307
    const font::RawFontData& getColorBitmap(tools::Rectangle& rRect) const
308
0
    {
309
0
        rRect = m_aRect;
310
0
        return m_aColorBitmap;
311
0
    }
312
313
0
    void setOutline(const basegfx::B2DPolyPolygon& rOutline) { m_aOutline = rOutline; }
314
0
    const basegfx::B2DPolyPolygon& getOutline() const { return m_aOutline; }
315
316
    void addCode( sal_Ucs i_cCode )
317
210k
    {
318
210k
        m_CodeUnits.push_back(i_cCode);
319
210k
    }
320
210k
    sal_Int32 countCodes() const { return m_CodeUnits.size(); }
321
11.0M
    const std::vector<sal_Ucs>& codes() const { return m_CodeUnits; }
322
    sal_Ucs getCode( sal_Int32 i_nIndex ) const
323
421k
    {
324
421k
        sal_Ucs nRet = 0;
325
421k
        if (o3tl::make_unsigned(i_nIndex) < m_CodeUnits.size())
326
421k
            nRet = m_CodeUnits[i_nIndex];
327
421k
        return nRet;
328
421k
    }
329
};
330
331
struct FontEmit
332
{
333
    sal_Int32           m_nFontID;
334
    std::map<sal_GlyphId, GlyphEmit>     m_aMapping;
335
336
6.81k
    explicit FontEmit( sal_Int32 nID ) : m_nFontID( nID ) {}
337
};
338
339
struct Glyph
340
{
341
    sal_Int32   m_nFontID;
342
    sal_uInt8   m_nSubsetGlyphID;
343
};
344
345
struct FontSubset
346
{
347
    std::vector< FontEmit >        m_aSubsets;
348
    std::map<sal_GlyphId, Glyph>         m_aMapping;
349
};
350
351
struct FontSubsetKey
352
{
353
    const vcl::font::PhysicalFontFace* m_pFace;
354
    const std::vector<vcl::font::Variation>& m_rVariations;
355
    size_t m_nHash;
356
357
    FontSubsetKey(const vcl::font::PhysicalFontFace* pFace, const LogicalFontInstance* pFont)
358
22.5M
        : m_pFace(pFace)
359
22.5M
        , m_rVariations(pFont->GetVariations())
360
22.5M
        , m_nHash(0)
361
22.5M
    {
362
22.5M
        o3tl::hash_combine(m_nHash, m_rVariations.size());
363
22.5M
        for (const auto& rVar : m_rVariations)
364
22.5M
        {
365
22.5M
            o3tl::hash_combine(m_nHash, rVar.nTag);
366
22.5M
            o3tl::hash_combine(m_nHash, rVar.fValue);
367
22.5M
        }
368
22.5M
    }
369
370
    bool operator<(const FontSubsetKey& rOther) const
371
74.3M
    {
372
74.3M
        if (m_pFace != rOther.m_pFace)
373
1.12M
            return m_pFace < rOther.m_pFace;
374
73.2M
        return m_nHash < rOther.m_nHash;
375
74.3M
    }
376
};
377
378
struct EmbedFont
379
{
380
    sal_Int32                       m_nNormalFontID;
381
    LogicalFontInstance*            m_pFontInstance;
382
383
    EmbedFont()
384
0
        : m_nNormalFontID(0)
385
0
        , m_pFontInstance(nullptr) {}
386
};
387
388
struct PDFDest
389
{
390
    sal_Int32                   m_nPage;
391
    PDFWriter::DestAreaType     m_eType;
392
    tools::Rectangle                   m_aRect;
393
};
394
395
//--->i56629
396
struct PDFNamedDest
397
{
398
    OUString               m_aDestName;
399
    sal_Int32                   m_nPage;
400
    PDFWriter::DestAreaType     m_eType;
401
    tools::Rectangle                   m_aRect;
402
};
403
404
struct PDFOutlineEntry
405
{
406
    sal_Int32                   m_nObject;
407
    sal_Int32                   m_nParentObject;
408
    sal_Int32                   m_nNextObject;
409
    sal_Int32                   m_nPrevObject;
410
    std::vector< sal_Int32 >    m_aChildren;
411
    OUString               m_aTitle;
412
    sal_Int32                   m_nDestID;
413
414
    PDFOutlineEntry()
415
4.90k
            : m_nObject( 0 ),
416
4.90k
              m_nParentObject( 0 ),
417
4.90k
              m_nNextObject( 0 ),
418
4.90k
              m_nPrevObject( 0 ),
419
4.90k
              m_nDestID( -1 )
420
4.90k
    {}
421
};
422
423
struct PDFAnnotation
424
{
425
    sal_Int32                   m_nObject;
426
    tools::Rectangle                   m_aRect;
427
    sal_Int32                   m_nPage;
428
429
    PDFAnnotation()
430
1.77k
            : m_nObject( -1 ),
431
1.77k
              m_nPage( -1 )
432
1.77k
    {}
433
};
434
435
struct PDFLink : public PDFAnnotation
436
{
437
    sal_Int32                   m_nDest; // set to -1 for URL, to a dest else
438
    OUString               m_aURL;
439
    sal_Int32                   m_nStructParent; // struct parent entry
440
    OUString m_AltText;
441
442
    PDFLink(OUString const& rAltText)
443
1.71k
            : m_nDest( -1 ),
444
1.71k
              m_nStructParent( -1 )
445
1.71k
            , m_AltText(rAltText)
446
1.71k
    {}
447
};
448
449
/// A PDF embedded file.
450
struct PDFEmbeddedFile
451
{
452
    /// ID of the file.
453
    sal_Int32 m_nObject;
454
    OUString m_aSubType;
455
    /// Contents of the file.
456
    BinaryDataContainer m_aDataContainer;
457
    std::unique_ptr<PDFOutputStream> m_pStream;
458
459
    PDFEmbeddedFile()
460
0
        : m_nObject(0)
461
0
    {
462
0
    }
463
};
464
465
struct PDFPopupAnnotation : public PDFAnnotation
466
{
467
    /// ID of the parent object.
468
    sal_Int32 m_nParentObject;
469
};
470
471
struct PDFNoteEntry : public PDFAnnotation
472
{
473
    vcl::pdf::PDFNote m_aContents;
474
475
    PDFPopupAnnotation m_aPopUpAnnotation;
476
477
    sal_Int32 m_nStructParent;
478
479
    PDFNoteEntry()
480
26
        : m_nStructParent(-1)
481
26
    {}
482
};
483
484
/// A PDF Screen annotation.
485
struct PDFScreen : public PDFAnnotation
486
{
487
    /// Linked video.
488
    OUString m_aURL;
489
    /// Embedded video.
490
    OUString m_aTempFileURL;
491
    /// ID of the EmbeddedFile object.
492
    sal_Int32 m_nTempFileObject;
493
    /// alternative text description
494
    OUString m_AltText;
495
    sal_Int32 m_nStructParent;
496
    OUString m_MimeType;
497
498
    PDFScreen(OUString const& rAltText, OUString const& rMimeType)
499
0
        : m_nTempFileObject(0)
500
0
        , m_AltText(rAltText)
501
0
        , m_nStructParent(-1)
502
0
        , m_MimeType(rMimeType)
503
0
    {
504
0
    }
505
};
506
507
struct PDFWidgetCopy
508
{
509
    sal_Int32 m_nObject = -1;
510
};
511
512
struct PDFWidget : public PDFAnnotation
513
{
514
    PDFWriter::WidgetType       m_eType;
515
    OString                m_aName;
516
    OUString               m_aDescription;
517
    OUString               m_aText;
518
    DrawTextFlags          m_nTextStyle;
519
    OUString               m_aValue;
520
    OString                m_aDAString;
521
    OString                m_aDRDict;
522
    OString                m_aMKDict;
523
    OString                m_aMKDictCAString;  // i12626, added to be able to encrypt the /CA text string
524
                                                    // since the object number is not known at the moment
525
                                                    // of filling m_aMKDict, the string will be encrypted when emitted.
526
                                                    // the /CA string MUST BE the last added to m_aMKDict
527
                                                    // see code for details
528
    sal_Int32                   m_nFlags;
529
    sal_Int32                   m_nParent; // if not 0, parent's object number
530
    std::vector<sal_Int32>      m_aKids; // widget children, contains object numbers
531
    std::vector<sal_Int32>      m_aKidsIndex; // widget children, contains index to m_aWidgets
532
    OUString                    m_aOnValue;
533
    OUString                    m_aOffValue;
534
    sal_Int32                   m_nTabOrder; // lowest number gets first in tab order
535
    sal_Int32                   m_nRadioGroup;
536
    sal_Int32                   m_nMaxLen;
537
    PDFWriter::FormatType       m_nFormat;
538
    OUString                    m_aCurrencySymbol;
539
    sal_Int32                   m_nDecimalAccuracy;
540
    bool                        m_bPrependCurrencySymbol;
541
    OUString                    m_aTimeFormat;
542
    OUString                    m_aDateFormat;
543
    bool                        m_bSubmit;
544
    bool                        m_bSubmitGet;
545
    sal_Int32                   m_nDest;
546
    std::vector<OUString>  m_aListEntries;
547
    std::vector<sal_Int32>      m_aSelectedEntries;
548
    typedef std::unordered_map<OString, SvMemoryStream*> PDFAppearanceStreams;
549
    std::unordered_map<OString, PDFAppearanceStreams> m_aAppearances;
550
    sal_Int32 m_nStructParent = -1;
551
552
    PDFWidget()
553
0
            : m_eType( PDFWriter::PushButton ),
554
0
              m_nTextStyle( DrawTextFlags::NONE ),
555
0
              m_nFlags( 0 ),
556
0
              m_nParent( 0 ),
557
0
              m_nTabOrder( 0 ),
558
0
              m_nRadioGroup( -1 ),
559
0
              m_nMaxLen( 0 ),
560
0
              m_nFormat( PDFWriter::FormatType::Text ),
561
0
              m_nDecimalAccuracy ( 0 ),
562
0
              m_bPrependCurrencySymbol( false ),
563
0
              m_bSubmit( false ),
564
0
              m_bSubmitGet( false ),
565
0
              m_nDest( -1 )
566
0
    {}
567
};
568
569
struct PDFStructureAttribute
570
{
571
    PDFWriter::StructAttributeValue     eValue;
572
    sal_Int32                           nValue;
573
574
    PDFStructureAttribute()
575
0
            : eValue( PDFWriter::Invalid ),
576
0
              nValue( 0 )
577
0
    {}
578
579
    explicit PDFStructureAttribute( PDFWriter::StructAttributeValue eVal )
580
0
            : eValue( eVal ),
581
0
              nValue( 0 )
582
0
    {}
583
584
    explicit PDFStructureAttribute( sal_Int32 nVal )
585
0
            : eValue( PDFWriter::Invalid ),
586
0
              nValue( nVal )
587
0
    {}
588
};
589
590
struct ObjReference { sal_Int32 const nObject; };
591
struct ObjReferenceObj { sal_Int32 const nObject; };
592
struct MCIDReference { sal_Int32 const nPageObj; sal_Int32 const nMCID; };
593
typedef ::std::variant<ObjReference, ObjReferenceObj, MCIDReference> PDFStructureElementKid;
594
595
struct PDFStructureElement
596
{
597
    sal_Int32                                           m_nObject;
598
    std::optional<vcl::pdf::StructElement> m_oType;
599
    OString                                        m_aAlias;
600
    sal_Int32                                           m_nOwnElement; // index into structure vector
601
    sal_Int32                                           m_nParentElement; // index into structure vector
602
    sal_Int32                                           m_nFirstPageObject;
603
    bool                                                m_bOpenMCSeq;
604
    std::vector< sal_Int32 >                            m_aChildren; // indexes into structure vector
605
    std::list< PDFStructureElementKid >                 m_aKids;
606
    std::map<PDFWriter::StructAttribute, PDFStructureAttribute >
607
                                                        m_aAttributes;
608
    ::std::vector<sal_Int32>                            m_AnnotIds;
609
    tools::Rectangle                                    m_aBBox;
610
    OUString                                            m_aActualText;
611
    OUString                                            m_aAltText;
612
    css::lang::Locale                                   m_aLocale;
613
614
    // m_aContents contains the element's marked content sequence
615
    // as pairs of (page nr, MCID)
616
617
    PDFStructureElement()
618
4.16k
            : m_nObject( 0 ),
619
4.16k
              m_nOwnElement( -1 ),
620
4.16k
              m_nParentElement( -1 ),
621
4.16k
              m_nFirstPageObject( 0 ),
622
4.16k
              m_bOpenMCSeq( false )
623
4.16k
    {
624
4.16k
    }
625
626
    PDFStructureElement(sal_Int32 nOwnElement, sal_Int32 nParentElement, sal_Int32 nFirstPageObject)
627
0
        : m_nObject(0)
628
0
        , m_nOwnElement(nOwnElement)
629
0
        , m_nParentElement(nParentElement)
630
0
        , m_nFirstPageObject(nFirstPageObject)
631
0
        , m_bOpenMCSeq(false )
632
0
    {
633
0
    }
634
};
635
636
// helper structure for drawLayout and friends
637
struct PDFGlyph
638
{
639
    basegfx::B2DPoint const m_aPos;
640
    const GlyphItem* m_pGlyph;
641
    const LogicalFontInstance* m_pFont;
642
    sal_Int32 const   m_nNativeWidth;
643
    sal_Int32 const   m_nMappedFontId;
644
    sal_uInt8 const   m_nMappedGlyphId;
645
    int const         m_nCharPos;
646
647
    PDFGlyph( const basegfx::B2DPoint& rPos,
648
              const GlyphItem* pGlyph,
649
              const LogicalFontInstance* pFont,
650
              sal_Int32 nNativeWidth,
651
              sal_Int32 nFontId,
652
              sal_uInt8 nMappedGlyphId,
653
              int nCharPos )
654
11.2M
    : m_aPos( rPos ), m_pGlyph(pGlyph), m_pFont(pFont), m_nNativeWidth( nNativeWidth ),
655
11.2M
      m_nMappedFontId( nFontId ), m_nMappedGlyphId( nMappedGlyphId ),
656
11.2M
      m_nCharPos(nCharPos)
657
11.2M
    {}
658
};
659
660
struct StreamRedirect
661
{
662
    SvStream*       m_pStream;
663
    MapMode         m_aMapMode;
664
    tools::Rectangle       m_aTargetRect;
665
    ResourceDict    m_aResourceDict;
666
};
667
668
// graphics state
669
struct GraphicsState
670
{
671
    vcl::Font                        m_aFont;
672
    MapMode                          m_aMapMode;
673
    Color                            m_aLineColor;
674
    Color                            m_aFillColor;
675
    Color                            m_aTextLineColor;
676
    Color                            m_aOverlineColor;
677
    basegfx::B2DPolyPolygon          m_aClipRegion;
678
    bool                             m_bClipRegion;
679
    vcl::text::ComplexTextLayoutFlags m_nLayoutMode;
680
    LanguageType                     m_aDigitLanguage;
681
    PushFlags                        m_nFlags;
682
    GraphicsStateUpdateFlags         m_nUpdateFlags;
683
684
    GraphicsState() :
685
128k
            m_aLineColor( COL_TRANSPARENT ),
686
128k
            m_aFillColor( COL_TRANSPARENT ),
687
128k
            m_aTextLineColor( COL_TRANSPARENT ),
688
128k
            m_aOverlineColor( COL_TRANSPARENT ),
689
128k
            m_bClipRegion( false ),
690
128k
            m_nLayoutMode( vcl::text::ComplexTextLayoutFlags::Default ),
691
128k
            m_aDigitLanguage( 0 ),
692
128k
            m_nFlags( PushFlags::ALL ),
693
128k
            m_nUpdateFlags( GraphicsStateUpdateFlags::All )
694
128k
    {}
695
};
696
697
enum class Mode { DEFAULT, NOWRITE };
698
699
struct PDFDocumentAttachedFile
700
{
701
    OUString maFilename;
702
    OUString maMimeType;
703
    OUString maDescription;
704
    sal_Int32 mnEmbeddedFileObjectId;
705
    sal_Int32 mnObjectId;
706
};
707
708
class IPDFEncryptor;
709
710
} // end pdf namespace
711
712
class PDFWriterImpl final : public VirtualDevice, public PDFObjectContainer
713
{
714
    friend class PDFStreamIf;
715
716
public:
717
    friend struct vcl::pdf::PDFPage;
718
719
    const char* getStructureTag(vcl::pdf::StructElement eElement);
720
    static const char* getAttributeTag(PDFWriter::StructAttribute eAtr );
721
    static const char* getAttributeValueTag( PDFWriter::StructAttributeValue eVal );
722
723
    // returns true if compression was done
724
    // else false
725
    static bool compressStream( SvMemoryStream* );
726
727
    static void convertLineInfoToExtLineInfo( const LineInfo& rIn, PDFWriter::ExtLineInfo& rOut );
728
729
private:
730
    bool ImplNewFont() const override;
731
    void ImplClearFontData(bool bNewFontLists) override;
732
    void ImplRefreshFontData(bool bNewFontLists) override;
733
    vcl::Region ClipToDeviceBounds(vcl::Region aRegion) const override;
734
    void DrawHatchLine_DrawLine(const Point& rStartPoint, const Point& rEndPoint) override;
735
736
    MapMode                             m_aMapMode; // PDFWriterImpl scaled units
737
    StyleSettings                       m_aWidgetStyleSettings;
738
    std::vector< PDFPage >              m_aPages;
739
    /* maps object numbers to file offsets (needed for xref) */
740
    std::vector< sal_uInt64 >           m_aObjects;
741
    /* contains Bitmaps until they are written to the
742
     *  file stream as XObjects*/
743
    std::list< BitmapEmit >             m_aBitmaps;
744
    /* contains JPG streams until written to file     */
745
    std::vector<JPGEmit>                m_aJPGs;
746
    /*--->i56629 contains all named destinations ever set during the PDF creation,
747
       destination id is always the destination's position in this vector
748
     */
749
    std::vector<PDFNamedDest>           m_aNamedDests;
750
    /* contains all dests ever set during the PDF creation,
751
       dest id is always the dest's position in this vector
752
     */
753
    std::vector<PDFDest>                m_aDests;
754
    /** contains destinations accessible via a public Id, instead of being linked to by an ordinary link
755
    */
756
    ::std::map< sal_Int32, sal_Int32 >  m_aDestinationIdTranslation;
757
    /* contains all links ever set during PDF creation,
758
       link id is always the link's position in this vector
759
    */
760
    std::vector<PDFLink>                m_aLinks;
761
    /// Contains all screen annotations.
762
    std::vector<PDFScreen> m_aScreens;
763
    /// Contains embedded files.
764
    std::vector<PDFEmbeddedFile> m_aEmbeddedFiles;
765
766
    std::vector<PDFDocumentAttachedFile> m_aDocumentAttachedFiles;
767
768
    /* makes correctly encoded for export to PDF URLS
769
    */
770
    css::uno::Reference< css::util::XURLTransformer > m_xTrans;
771
    /* maps arbitrary link ids for structure attributes to real link ids
772
       (for setLinkPropertyId)
773
    */
774
    std::map<sal_Int32, sal_Int32>      m_aLinkPropertyMap;
775
    /* contains all outline items,
776
       object 0 is the outline root
777
     */
778
    std::vector<PDFOutlineEntry>        m_aOutline;
779
    /* contains all notes set during PDF creation
780
     */
781
    std::vector<PDFNoteEntry>           m_aNotes;
782
    /* the root of the structure tree
783
     */
784
    std::vector<PDFStructureElement>    m_aStructure;
785
    /* current object in the structure hierarchy
786
     */
787
    sal_Int32                           m_nCurrentStructElement;
788
    std::stack<sal_Int32> m_StructElementStack;
789
    /* structure parent tree */
790
    std::vector< OString >         m_aStructParentTree;
791
    /* emit structure marks currently (aka. NonStructElement or not)
792
     */
793
    bool                                m_bEmitStructure;
794
    /* role map of struct tree root */
795
    std::unordered_map< OString, OString >
796
                                        m_aRoleMap;
797
    /* structure elements (object ids) that should have ID */
798
    std::unordered_set<sal_Int32> m_StructElemObjsWithID;
799
800
    /* contains all widgets used in the PDF */
801
    std::vector<PDFWidget> m_aWidgets;
802
    std::vector<PDFWidgetCopy> m_aCopiedWidgets;
803
804
    /* maps radio group id to index of radio group control in m_aWidgets */
805
    std::map< sal_Int32, sal_Int32 >    m_aRadioGroupWidgets;
806
    /* unordered_map for field names, used to ensure unique field names */
807
    std::unordered_map< OString, sal_Int32 > m_aFieldNameMap;
808
809
    /* contains Bitmaps for gradient functions until they are written
810
     *  to the file stream */
811
    std::list< GradientEmit >           m_aGradients;
812
    /* contains bitmap tiling patterns */
813
    std::vector< TilingEmit >           m_aTilings;
814
    std::vector< TransparencyEmit >     m_aTransparentObjects;
815
    /*  contains all font subsets in use */
816
    std::map<FontSubsetKey, FontSubset> m_aSubsets;
817
    std::map<const vcl::font::PhysicalFontFace*, EmbedFont> m_aSystemFonts;
818
    std::map<const vcl::font::PhysicalFontFace*, FontSubset> m_aType3Fonts;
819
    sal_Int32                           m_nNextFID;
820
821
    /// Cache some most recent bitmaps we've exported, in case we encounter them again..
822
    o3tl::lru_map<BitmapChecksum,
823
                  std::shared_ptr<SvMemoryStream>> m_aPDFBmpCache;
824
825
    sal_Int32                           m_nCurrentPage;
826
827
    sal_Int32                           m_nCatalogObject;
828
    // object number of the main signature dictionary
829
    sal_Int32                           m_nSignatureObject;
830
    sal_Int64                           m_nSignatureContentOffset;
831
    sal_Int64                           m_nSignatureLastByteRangeNoOffset;
832
    sal_Int32                           m_nResourceDict;
833
    ResourceDict                        m_aGlobalResourceDict;
834
    sal_Int32                           m_nFontDictObject;
835
    std::map< sal_Int32, sal_Int32 >    m_aBuildinFontToObjectMap;
836
837
    PDFWriter::PDFWriterContext         m_aContext;
838
    osl::File                           m_aFile;
839
    bool                                m_bOpen;
840
841
    ExternalPDFStreams m_aExternalPDFStreams;
842
843
    std::shared_ptr<IPDFEncryptor> m_pPDFEncryptor;
844
845
    /* output redirection; e.g. to accumulate content streams for
846
       XObjects
847
     */
848
    std::list< StreamRedirect >         m_aOutputStreams;
849
850
    std::list< GraphicsState >              m_aGraphicsStack;
851
    GraphicsState                           m_aCurrentPDFState;
852
853
    std::unique_ptr<ZCodec>                 m_pCodec;
854
    std::unique_ptr<SvMemoryStream>         m_pMemStream;
855
856
    std::set< PDFWriter::ErrorCode >        m_aErrors;
857
858
    ::comphelper::Hash                      m_DocDigest;
859
860
    std::unordered_map<std::string_view, sal_Int32> m_aNamespacesMap;
861
862
    // reduce repeated allocations
863
    OStringBuffer                           updateGraphicsStateLine{256};
864
    OStringBuffer                           drawBitmapLine{80};
865
866
    sal_uInt64 getCurrentFilePosition()
867
0
    {
868
0
        sal_uInt64 nPosition{};
869
0
        if (osl::File::E_None != m_aFile.getPos(nPosition))
870
0
        {
871
0
            m_aFile.close();
872
0
            m_bOpen = false;
873
0
        }
874
0
        return nPosition;
875
0
    }
876
877
    /* string to hold the PDF creation date */
878
    OString                            m_aCreationDateString;
879
    /* string to hold the PDF creation date, for PDF/A metadata */
880
    OString                            m_aCreationMetaDateString;
881
    /* the buffer where the data are encrypted, dynamically allocated */
882
    std::vector<sal_uInt8>                  m_vEncryptionBuffer;
883
884
    void addRoleMap(const OString& aAlias, vcl::pdf::StructElement eType);
885
886
    void checkAndEnableStreamEncryption( sal_Int32 nObject ) override;
887
888
    void disableStreamEncryption() override;
889
890
    /* */
891
    void enableStringEncryption( sal_Int32 nObject );
892
893
private:
894
    /* creates fonts and subsets that will be emitted later */
895
    void registerGlyph(const sal_GlyphId, const vcl::font::PhysicalFontFace*, const LogicalFontInstance* pFont, const std::vector<sal_Ucs>&, sal_Int32, sal_uInt8&, sal_Int32&);
896
    void registerSimpleGlyph(const sal_GlyphId, const vcl::font::PhysicalFontFace*, const LogicalFontInstance*, const std::vector<sal_Ucs>&, sal_Int32, sal_uInt8&, sal_Int32&);
897
898
    /*  emits a text object according to the passed layout */
899
    /* TODO: remove rText as soon as SalLayout will change so that rText is not necessary anymore */
900
    void drawVerticalGlyphs( const std::vector<PDFGlyph>& rGlyphs, OStringBuffer& rLine, const Point& rAlignOffset, const Matrix3& rRotScale, double fAngle, double fXScale, sal_Int32 nFontHeight );
901
    void drawHorizontalGlyphs( const std::vector<PDFGlyph>& rGlyphs, OStringBuffer& rLine, const Point& rAlignOffset, bool bFirst, double fAngle, double fXScale, sal_Int32 nFontHeight, sal_Int32 nPixelFontHeight );
902
    void drawLayout( SalLayout& rLayout, const OUString& rText, bool bTextLines );
903
    void drawRelief( SalLayout& rLayout, const OUString& rText, bool bTextLines );
904
    void drawShadow( SalLayout& rLayout, const OUString& rText, bool bTextLines );
905
906
    /*  writes differences between graphics stack and current real PDF
907
     *   state to the file
908
     */
909
    void updateGraphicsState(Mode mode = Mode::DEFAULT);
910
911
    /* writes a transparency group object */
912
    void writeTransparentObject( TransparencyEmit& rObject );
913
914
    /* writes an XObject of type image, may create
915
       a second for the mask
916
     */
917
    bool writeBitmapObject( const BitmapEmit& rObject );
918
    /* writes an XObject of type mask image
919
     */
920
    bool writeBitmapMaskObject( sal_Int32 nMaskObject, const AlphaMask& rAlphaMask );
921
922
    void writeJPG( const JPGEmit& rEmit );
923
    /// Writes the form XObject proxy for the image.
924
    void writeReferenceXObject(const ReferenceXObjectEmit& rEmit);
925
926
    void mergeAnnotationsFromExternalPage(filter::PDFObjectElement* pPage,  std::map<sal_Int32, sal_Int32>& rCopiedResourcesMap);
927
928
    /* tries to find the bitmap by its id and returns its emit data if exists,
929
       else creates a new emit data block */
930
    const BitmapEmit& createBitmapEmit( const Bitmap& rBitmap, const Graphic& rGraphic, std::list<BitmapEmit>& rBitmaps, ResourceDict& rResourceDict, std::list<StreamRedirect>& rOutputStreams );
931
    const BitmapEmit& createBitmapEmit( const Bitmap& rBitmap, const Graphic& rGraphic );
932
933
    /* writes the Do operation inside the content stream */
934
    void drawBitmap( const Point& rDestPt, const Size& rDestSize, const BitmapEmit& rBitmap, const Color& rFillColor );
935
    /* write the function object for a Gradient */
936
    bool writeGradientFunction( GradientEmit const & rObject );
937
    /* creates a GradientEmit and returns its object number */
938
    sal_Int32 createGradient(  const Gradient& rGradient, const Size& rSize );
939
940
    /* writes all tilings */
941
    bool emitTilings();
942
    /* writes all gradient patterns */
943
    bool emitGradients();
944
    /* writes a builtin font object and returns its objectid (or 0 in case of failure ) */
945
    sal_Int32 emitBuildinFont( const pdf::BuildinFontFace*, sal_Int32 nObject );
946
    /* writes a type1 system font object and returns its mapping from font ids to object ids (or 0 in case of failure ) */
947
    std::map< sal_Int32, sal_Int32 > emitSystemFont(const vcl::font::PhysicalFontFace*, EmbedFont const &);
948
    /* writes a type3 font object and appends it to the font id mapping, or returns false in case of failure */
949
    bool emitType3Font(const vcl::font::PhysicalFontFace*, const FontSubset&, std::map<sal_Int32, sal_Int32>&);
950
    /* writes a font descriptor and returns its object id (or 0) */
951
    sal_Int32 emitFontDescriptor(const vcl::font::PhysicalFontFace*, FontSubsetInfo const &, sal_Int32 nSubsetID, sal_Int32 nStream);
952
    /* writes a ToUnicode cmap, returns the corresponding stream object */
953
    sal_Int32 createToUnicodeCMap( sal_uInt8 const * pEncoding, const std::vector<sal_Ucs>& CodeUnits, const sal_Int32* pCodeUnitsPerGlyph,
954
                                   const sal_Int32* pEncToUnicodeIndex, uint32_t nGlyphs );
955
956
    /* get resource dict object number */
957
    sal_Int32 getResourceDictObj()
958
68.4k
    {
959
68.4k
        if( m_nResourceDict <= 0 )
960
4.16k
            m_nResourceDict = createObject();
961
68.4k
        return m_nResourceDict;
962
68.4k
    }
963
    /* get the font dict object */
964
    sal_Int32 getFontDictObject()
965
12.4k
    {
966
12.4k
        if( m_nFontDictObject <= 0 )
967
4.16k
            m_nFontDictObject = createObject();
968
12.4k
        return m_nFontDictObject;
969
12.4k
    }
970
    /* push resource into current (redirected) resource dict */
971
    static void pushResource( ResourceKind eKind, const OString& rResource, sal_Int32 nObject, ResourceDict& rResourceDict, std::list<StreamRedirect>& rOutputStreams );
972
    void pushResource( ResourceKind eKind, const OString& rResource, sal_Int32 nObject );
973
974
    void appendBuildinFontsToDict( OStringBuffer& rDict ) const;
975
    /* writes the font dictionary and emits all font objects
976
     * returns object id of font directory (or 0 on error)
977
     */
978
    bool emitFonts();
979
    /* writes the Resource dictionary;
980
     * returns dict object id (or 0 on error)
981
     */
982
    sal_Int32 emitResources();
983
    // appends a dest
984
    bool appendDest( sal_Int32 nDestID, OStringBuffer& rBuffer );
985
    // write all links
986
    bool emitLinkAnnotations();
987
    // Write all screen annotations.
988
    bool emitScreenAnnotations();
989
990
    void emitTextAnnotationLine(OStringBuffer & aLine, PDFNoteEntry const & rNote);
991
    static void emitPopupAnnotationLine(OStringBuffer & aLine, PDFPopupAnnotation const & rPopUp);
992
    // write all notes
993
    bool emitNoteAnnotations();
994
995
    // write the appearance streams of a widget
996
    bool emitAppearances( PDFWidget& rWidget, OStringBuffer& rAnnotDict );
997
    // clean up radio button "On" values
998
    void ensureUniqueRadioOnValues();
999
    // write all widgets
1000
    bool emitWidgetAnnotations();
1001
    // writes all annotation objects
1002
    bool emitAnnotations();
1003
    /// Writes embedded files.
1004
    bool emitEmbeddedFiles();
1005
    //write the named destination stuff
1006
    sal_Int32 emitNamedDestinations();//i56629
1007
    // writes outline dict and tree
1008
    sal_Int32 emitOutline();
1009
    template<typename T> void AppendAnnotKid(PDFStructureElement& i_rEle, T & rAnnot);
1010
    // puts the attribute objects of a structure element into the returned string,
1011
    // helper for emitStructure
1012
    OString emitStructureAttributes( PDFStructureElement& rEle );
1013
    //--->i94258
1014
    // the maximum array elements allowed for PDF array object
1015
    static const sal_uInt32 ncMaxPDFArraySize = 8191;
1016
    //check if internal dummy container are needed in the structure elements
1017
    void addInternalStructureContainer( PDFStructureElement& rEle );
1018
    //<---i94258
1019
    // writes namespaces
1020
    void emitNamespaces();
1021
    // writes document structure
1022
    sal_Int32 emitStructure( PDFStructureElement& rEle );
1023
    // writes structure parent tree
1024
    sal_Int32 emitStructParentTree( sal_Int32 nTreeObject );
1025
    // writes structure IDTree
1026
    sal_Int32 emitStructIDTree(sal_Int32 nTreeObject);
1027
    // writes page tree and catalog
1028
    bool emitCatalog();
1029
    // writes signature dictionary object
1030
    bool emitSignature();
1031
    // creates a PKCS7 object using the ByteRange and overwrite /Contents
1032
    // of the signature dictionary
1033
    bool finalizeSignature();
1034
    //writes encrypt
1035
    sal_Int32 emitEncrypt();
1036
    // writes xref and trailer
1037
    bool emitTrailer();
1038
    // emits info dict (if applicable)
1039
    sal_Int32 emitInfoDict( );
1040
1041
    // acrobat reader 5 and 6 use the order of the annotations
1042
    // as their tab order; since PDF1.5 one can make the
1043
    // tab order explicit by using the structure tree
1044
    void sortWidgets();
1045
1046
    // updates the count numbers of outline items
1047
    sal_Int32 updateOutlineItemCount( std::vector< sal_Int32 >& rCounts,
1048
                                      sal_Int32 nItemLevel,
1049
                                      sal_Int32 nCurrentItemId );
1050
    // default appearances for widgets
1051
    sal_Int32 findRadioGroupWidget( const PDFWriter::RadioButtonWidget& rRadio );
1052
    Font replaceFont( const Font& rControlFont, const Font& rAppSetFont );
1053
    sal_Int32 getBestBuildinFont( const Font& rFont );
1054
    sal_Int32 getSystemFont( const Font& i_rFont );
1055
1056
    // used for edit and listbox
1057
    Font drawFieldBorder( PDFWidget&, const PDFWriter::AnyWidget&, const StyleSettings& );
1058
1059
    void createDefaultPushButtonAppearance( PDFWidget&, const PDFWriter::PushButtonWidget& rWidget );
1060
    void createDefaultCheckBoxAppearance( PDFWidget&, const PDFWriter::CheckBoxWidget& rWidget );
1061
    void createDefaultRadioButtonAppearance( PDFWidget&, const PDFWriter::RadioButtonWidget& rWidget );
1062
    void createDefaultEditAppearance( PDFWidget&, const PDFWriter::EditWidget& rWidget );
1063
    void createDefaultListBoxAppearance( PDFWidget&, const PDFWriter::ListBoxWidget& rWidget );
1064
1065
    /* ensure proper escapement and uniqueness of field names */
1066
    void createWidgetFieldName( sal_Int32 i_nWidgetsIndex, const PDFWriter::AnyWidget& i_rInWidget );
1067
    /// See vcl::PDFObjectContainer::createObject().
1068
    sal_Int32 createObject() override;
1069
    /// See vcl::PDFObjectContainer::updateObject().
1070
    bool updateObject( sal_Int32 n ) override;
1071
1072
    /// See vcl::PDFObjectContainer::writeBuffer().
1073
    bool writeBufferBytes( const void* pBuffer, sal_uInt64 nBytes ) override;
1074
    void beginCompression();
1075
    void endCompression();
1076
    void beginRedirect( SvStream* pStream, const tools::Rectangle& );
1077
    SvStream* endRedirect();
1078
1079
    void endPage();
1080
1081
    void beginStructureElementMCSeq();
1082
    enum class EndMode { Default, OnlyStruct };
1083
    void endStructureElementMCSeq(EndMode = EndMode::Default);
1084
    /** checks whether a non struct element lies in the ancestor hierarchy
1085
        of the current structure element
1086
1087
        @returns
1088
        true if no NonStructElement was found in ancestor path and tagged
1089
        PDF output is enabled
1090
        false else
1091
     */
1092
    bool checkEmitStructure();
1093
1094
    /* draws an emphasis mark */
1095
    void drawEmphasisMark(  tools::Long nX, tools::Long nY, const tools::PolyPolygon& rPolyPoly, bool bPolyLine, const tools::Rectangle& rRect1, const tools::Rectangle& rRect2 );
1096
1097
    /* true if PDF/A-1a or PDF/A-1b is output */
1098
    bool m_bIsPDF_A1 = false;
1099
    /* true if PDF/A-2a is output */
1100
    bool m_bIsPDF_A2 = false;
1101
    /* true if PDF/A-3 is output */
1102
    bool m_bIsPDF_A3 = false;
1103
    /* true if PDF/A-4 is output */
1104
    bool m_bIsPDF_A4 = false;
1105
1106
    sal_Int32 m_nPDFA_Version = 0;
1107
1108
    /* PDF/UA support enabled */
1109
    bool m_bIsPDF_UA = false;
1110
1111
    PDFWriter&      m_rOuterFace;
1112
1113
    /*
1114
    i12626
1115
    methods for PDF security
1116
1117
    pad a password according  algorithm 3.2, step 1 */
1118
    void setupDocInfo();
1119
1120
    // helper for playMetafile
1121
    void implWriteGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient,
1122
                            VirtualDevice* pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& );
1123
    void implWriteBitmapEx( const Point& rPoint, const Size& rSize, const Bitmap& rBitmap, const Graphic& i_pGraphic,
1124
                           VirtualDevice const * pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& );
1125
1126
    // color helper functions
1127
    void appendStrokingColor( const Color& rColor, OStringBuffer& rBuffer );
1128
    void appendNonStrokingColor( const Color& rColor, OStringBuffer& rBuffer );
1129
public:
1130
    PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, const css::uno::Reference< css::beans::XMaterialHolder >&, PDFWriter& );
1131
    ~PDFWriterImpl() override;
1132
    void dispose() override;
1133
1134
    /* document structure */
1135
    void newPage( double nPageWidth , double nPageHeight, PDFWriter::Orientation eOrientation );
1136
    bool emit();
1137
4.16k
    const std::set< PDFWriter::ErrorCode > & getErrors() const { return m_aErrors;}
1138
0
    void insertError( PDFWriter::ErrorCode eErr ) { m_aErrors.insert( eErr ); }
1139
    void playMetafile( const GDIMetaFile&, vcl::PDFExtOutDevData*, const vcl::PDFWriter::PlayMetafileContext&, VirtualDevice* pDummyDev = nullptr );
1140
1141
    Size getCurPageSize() const
1142
0
    {
1143
0
        Size aSize;
1144
0
        if( m_nCurrentPage >= 0 && o3tl::make_unsigned(m_nCurrentPage) < m_aPages.size() )
1145
0
            aSize = Size( m_aPages[ m_nCurrentPage ].m_nPageWidth, m_aPages[ m_nCurrentPage ].m_nPageHeight );
1146
0
        return aSize;
1147
0
    }
1148
1149
    void setDocumentLocale( const css::lang::Locale& rLoc )
1150
4.16k
    { m_aContext.DocumentLocale = rLoc; }
1151
1152
    /* graphics state */
1153
    void push( PushFlags nFlags );
1154
    void pop();
1155
1156
    void setFont( const Font& rFont );
1157
1158
    void setMapMode( const MapMode& rMapMode );
1159
1160
0
    const MapMode& getMapMode() { return m_aGraphicsStack.front().m_aMapMode; }
1161
1162
    void setLineColor( const Color& rColor )
1163
455k
    {
1164
455k
        m_aGraphicsStack.front().m_aLineColor = rColor.IsTransparent() ? COL_TRANSPARENT : rColor;
1165
455k
        m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::LineColor;
1166
455k
    }
1167
1168
    void setFillColor( const Color& rColor )
1169
456k
    {
1170
456k
        m_aGraphicsStack.front().m_aFillColor = rColor.IsTransparent() ? COL_TRANSPARENT : rColor;
1171
456k
        m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::FillColor;
1172
456k
    }
1173
1174
    void setTextLineColor()
1175
0
    {
1176
0
        m_aGraphicsStack.front().m_aTextLineColor = COL_TRANSPARENT;
1177
0
    }
1178
1179
    void setTextLineColor( const Color& rColor )
1180
454k
    {
1181
454k
        m_aGraphicsStack.front().m_aTextLineColor = rColor;
1182
454k
    }
1183
1184
    void setOverlineColor()
1185
0
    {
1186
0
        m_aGraphicsStack.front().m_aOverlineColor = COL_TRANSPARENT;
1187
0
    }
1188
1189
    void setOverlineColor( const Color& rColor )
1190
454k
    {
1191
454k
        m_aGraphicsStack.front().m_aOverlineColor = rColor;
1192
454k
    }
1193
1194
    void setTextFillColor( const Color& rColor )
1195
454k
    {
1196
454k
        m_aGraphicsStack.front().m_aFont.SetFillColor( rColor );
1197
454k
        m_aGraphicsStack.front().m_aFont.SetTransparent( rColor.IsTransparent() );
1198
454k
        m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::Font;
1199
454k
    }
1200
    void setTextFillColor()
1201
905k
    {
1202
905k
        m_aGraphicsStack.front().m_aFont.SetFillColor( COL_TRANSPARENT );
1203
905k
        m_aGraphicsStack.front().m_aFont.SetTransparent( true );
1204
905k
        m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::Font;
1205
905k
    }
1206
    void setTextColor( const Color& rColor )
1207
840k
    {
1208
840k
        m_aGraphicsStack.front().m_aFont.SetColor( rColor );
1209
840k
        m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::Font;
1210
840k
    }
1211
1212
    void clearClipRegion()
1213
671
    {
1214
671
        m_aGraphicsStack.front().m_aClipRegion.clear();
1215
671
        m_aGraphicsStack.front().m_bClipRegion = false;
1216
671
        m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::ClipRegion;
1217
671
    }
1218
1219
    void setClipRegion( const basegfx::B2DPolyPolygon& rRegion );
1220
1221
    void moveClipRegion( sal_Int32 nX, sal_Int32 nY );
1222
1223
    void intersectClipRegion( const tools::Rectangle& rRect );
1224
1225
    void intersectClipRegion( const basegfx::B2DPolyPolygon& rRegion );
1226
1227
    void setLayoutMode( vcl::text::ComplexTextLayoutFlags nLayoutMode )
1228
1.40M
    {
1229
1.40M
        m_aGraphicsStack.front().m_nLayoutMode = nLayoutMode;
1230
1.40M
        m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::LayoutMode;
1231
1.40M
    }
1232
1233
    void setDigitLanguage( LanguageType eLang )
1234
838k
    {
1235
838k
        m_aGraphicsStack.front().m_aDigitLanguage = eLang;
1236
838k
        m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::DigitLanguage;
1237
838k
    }
1238
1239
    void setTextAlign( TextAlign eAlign )
1240
1.35M
    {
1241
1.35M
        m_aGraphicsStack.front().m_aFont.SetAlignment( eAlign );
1242
1.35M
        m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::Font;
1243
1.35M
    }
1244
1245
    /* actual drawing functions */
1246
    void drawText( const Point& rPos, const OUString& rText, sal_Int32 nIndex, sal_Int32 nLen, bool bTextLines = true );
1247
    void drawTextArray(const Point& rPos, const OUString& rText, KernArraySpan pDXArray,
1248
                       std::span<const sal_Bool> pKashidaArray, sal_Int32 nIndex, sal_Int32 nLen,
1249
                       sal_Int32 nLayoutContextIndex, sal_Int32 nLayoutContextLen);
1250
    void drawStretchText( const Point& rPos, sal_Int32 nWidth, const OUString& rText,
1251
                          sal_Int32 nIndex, sal_Int32 nLen  );
1252
    void drawText( const tools::Rectangle& rRect, const OUString& rOrigStr, DrawTextFlags nStyle );
1253
    void drawTextLine( const Point& rPos, tools::Long nWidth, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline, bool bUnderlineAbove );
1254
    void drawWaveTextLine( OStringBuffer& aLine, tools::Long nWidth, FontLineStyle eTextLine, Color aColor, bool bIsAbove );
1255
    void drawStraightTextLine( OStringBuffer& aLine, tools::Long nWidth, FontLineStyle eTextLine, Color aColor, bool bIsAbove );
1256
    void drawStrikeoutLine( OStringBuffer& aLine, tools::Long nWidth, FontStrikeout eStrikeout, Color aColor );
1257
    void drawStrikeoutChar( const Point& rPos, tools::Long nWidth, FontStrikeout eStrikeout );
1258
1259
    void drawLine( const Point& rStart, const Point& rStop );
1260
    void drawLine( const Point& rStart, const Point& rStop, const LineInfo& rInfo );
1261
    void drawPolygon( const tools::Polygon& rPoly );
1262
    void drawPolyPolygon( const tools::PolyPolygon& rPolyPoly );
1263
    void drawPolyLine( const tools::Polygon& rPoly );
1264
    void drawPolyLine( const tools::Polygon& rPoly, const LineInfo& rInfo );
1265
    void drawPolyLine( const tools::Polygon& rPoly, const PDFWriter::ExtLineInfo& rInfo );
1266
1267
    void drawPixel( const Point& rPt, const Color& rColor );
1268
1269
    void drawRectangle( const tools::Rectangle& rRect );
1270
    void drawRectangle( const tools::Rectangle& rRect, sal_uInt32 nHorzRound, sal_uInt32 nVertRound );
1271
    void drawEllipse( const tools::Rectangle& rRect );
1272
    void drawArc( const tools::Rectangle& rRect, const Point& rStart, const Point& rStop, bool bWithPie, bool bWidthChord );
1273
1274
    void drawBitmap( const Point& rDestPoint, const Size& rDestSize, const Bitmap& rBitmap, const Graphic& rGraphic );
1275
    void drawBitmap( const Point& rDestPoint, const Size& rDestSize, const Bitmap& rBitmap );
1276
    void drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const Size& rSizePixel, const tools::Rectangle& rTargetArea, const AlphaMask& rAlphaMask, const Graphic& rGraphic );
1277
    /// Stores the original PDF data from rGraphic as an embedded file.
1278
    void createEmbeddedFile(const Graphic& rGraphic, ReferenceXObjectEmit& rEmit, sal_Int32 nBitmapObject);
1279
1280
    void drawGradient( const tools::Rectangle& rRect, const Gradient& rGradient );
1281
    void drawHatch( const tools::PolyPolygon& rPolyPoly, const Hatch& rHatch );
1282
    void drawWallpaper( const tools::Rectangle& rRect, const Wallpaper& rWall );
1283
    void drawTransparent( const tools::PolyPolygon& rPolyPoly, sal_uInt32 nTransparentPercent );
1284
    void beginTransparencyGroup();
1285
    void endTransparencyGroup( const tools::Rectangle& rBoundingBox, sal_uInt32 nTransparentPercent );
1286
1287
    void emitComment( const char* pComment );
1288
1289
    //--->i56629 named destinations
1290
    sal_Int32 createNamedDest( const OUString& sDestName, const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType );
1291
1292
    //--->i59651
1293
    //emits output intent
1294
    sal_Int32   emitOutputIntent();
1295
1296
    //emits the document metadata
1297
    sal_Int32   emitDocumentMetadata();
1298
1299
    // links
1300
    sal_Int32 createLink(const tools::Rectangle& rRect, sal_Int32 nPageNr, OUString const& rAltText);
1301
    sal_Int32 createDest( const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType );
1302
    sal_Int32 registerDestReference( sal_Int32 nDestId, const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType );
1303
    void      setLinkDest( sal_Int32 nLinkId, sal_Int32 nDestId );
1304
    void      setLinkURL( sal_Int32 nLinkId, const OUString& rURL );
1305
    void      setLinkPropertyId( sal_Int32 nLinkId, sal_Int32 nPropertyId );
1306
1307
    // screens
1308
    sal_Int32 createScreen(const tools::Rectangle& rRect, sal_Int32 nPageNr, OUString const& rAltText, OUString const& rMimeType);
1309
    void setScreenURL(sal_Int32 nScreenId, const OUString& rURL);
1310
    void setScreenStream(sal_Int32 nScreenId, const OUString& rURL);
1311
1312
    // outline
1313
    sal_Int32 createOutlineItem( sal_Int32 nParent, std::u16string_view rText, sal_Int32 nDestID );
1314
    void      setOutlineItemParent( sal_Int32 nItem, sal_Int32 nNewParent );
1315
    void      setOutlineItemText( sal_Int32 nItem, std::u16string_view rText );
1316
    void      setOutlineItemDest( sal_Int32 nItem, sal_Int32 nDestID );
1317
1318
    // notes
1319
    sal_Int32 createNote(const tools::Rectangle& rRect, const tools::Rectangle& rPopupRect, const PDFNote& rNote, sal_Int32 nPageNr);
1320
    // structure elements
1321
    sal_Int32 ensureStructureElement();
1322
    void initStructureElement(sal_Int32 id, vcl::pdf::StructElement eType, std::u16string_view rAlias);
1323
    void beginStructureElement(sal_Int32 id);
1324
    void endStructureElement();
1325
    bool setCurrentStructureElement( sal_Int32 nElement );
1326
    bool setStructureAttribute( enum PDFWriter::StructAttribute eAttr, enum PDFWriter::StructAttributeValue eVal );
1327
    bool setStructureAttributeNumerical( enum PDFWriter::StructAttribute eAttr, sal_Int32 nValue );
1328
    void setStructureBoundingBox( const tools::Rectangle& rRect );
1329
    void setStructureAnnotIds(::std::vector<sal_Int32> const& rAnnotIds);
1330
    void setActualText( const OUString& rText );
1331
    void setAlternateText( const OUString& rText );
1332
1333
    // transitional effects
1334
    void setPageTransition( PDFWriter::PageTransition eType, sal_uInt32 nMilliSec, sal_Int32 nPageNr );
1335
1336
    // controls
1337
    sal_Int32 createControl( const PDFWriter::AnyWidget& rControl, sal_Int32 nPageNr = -1 );
1338
1339
    // attached file
1340
    void addDocumentAttachedFile(OUString const& rFileName, OUString const& rMimeType, OUString const& rDescription, std::unique_ptr<PDFOutputStream> rStream);
1341
1342
    sal_Int32 addEmbeddedFile(BinaryDataContainer const & rDataContainer);
1343
    sal_Int32 addEmbeddedFile(std::unique_ptr<PDFOutputStream> rStream, OUString const& rMimeType);
1344
1345
    // helper: eventually begin marked content sequence and
1346
    // emit a comment in debug case
1347
    void MARK( const char* pString );
1348
};
1349
1350
} // namespace vcl
1351
1352
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */