summaryrefslogtreecommitdiffstats
path: root/vcl/inc/pdf
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /vcl/inc/pdf
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl/inc/pdf')
-rw-r--r--vcl/inc/pdf/BitmapID.hxx41
-rw-r--r--vcl/inc/pdf/ExternalPDFStreams.hxx75
-rw-r--r--vcl/inc/pdf/Matrix3.hxx51
-rw-r--r--vcl/inc/pdf/PdfConfig.hxx18
-rw-r--r--vcl/inc/pdf/ResourceDict.hxx39
-rw-r--r--vcl/inc/pdf/XmpMetadata.hxx48
-rw-r--r--vcl/inc/pdf/objectcopier.hxx65
-rw-r--r--vcl/inc/pdf/pdfbuildin_fonts.hxx81
-rw-r--r--vcl/inc/pdf/pdfcompat.hxx42
-rw-r--r--vcl/inc/pdf/pdffontcache.hxx71
-rw-r--r--vcl/inc/pdf/pdfwriter_impl.hxx1291
11 files changed, 1822 insertions, 0 deletions
diff --git a/vcl/inc/pdf/BitmapID.hxx b/vcl/inc/pdf/BitmapID.hxx
new file mode 100644
index 000000000..afc9aff9f
--- /dev/null
+++ b/vcl/inc/pdf/BitmapID.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <vcl/dllapi.h>
+#include <vcl/checksum.hxx>
+#include <tools/gen.hxx>
+
+namespace vcl::pdf
+{
+struct BitmapID
+{
+ Size m_aPixelSize;
+ sal_Int32 m_nSize;
+ BitmapChecksum m_nChecksum;
+ BitmapChecksum m_nMaskChecksum;
+
+ BitmapID()
+ : m_nSize(0)
+ , m_nChecksum(0)
+ , m_nMaskChecksum(0)
+ {
+ }
+
+ bool operator==(const BitmapID& rComp) const
+ {
+ return (m_aPixelSize == rComp.m_aPixelSize && m_nSize == rComp.m_nSize
+ && m_nChecksum == rComp.m_nChecksum && m_nMaskChecksum == rComp.m_nMaskChecksum);
+ }
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/ExternalPDFStreams.hxx b/vcl/inc/pdf/ExternalPDFStreams.hxx
new file mode 100644
index 000000000..45b15f7a7
--- /dev/null
+++ b/vcl/inc/pdf/ExternalPDFStreams.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <sal/log.hxx>
+#include <vcl/dllapi.h>
+
+#include <map>
+#include <vector>
+#include <memory>
+
+#include <vcl/filter/pdfdocument.hxx>
+#include <vcl/BinaryDataContainer.hxx>
+
+namespace vcl
+{
+// A external PDF stream, which stores the PDF stream data as byte array.
+// This struct is also responsible to parsing the stream as a PDFDocument,
+// and store its instance for the life-cycle of the struct, so that it
+// reused to avoid unnecessary parsing.
+struct VCL_DLLPUBLIC ExternalPDFStream
+{
+ BinaryDataContainer maDataContainer;
+ std::shared_ptr<filter::PDFDocument> mpPDFDocument;
+ std::map<sal_Int32, sal_Int32> maCopiedResources;
+
+ std::map<sal_Int32, sal_Int32>& getCopiedResources() { return maCopiedResources; }
+
+ std::shared_ptr<filter::PDFDocument>& getPDFDocument()
+ {
+ if (!mpPDFDocument)
+ {
+ SvMemoryStream aPDFStream;
+ aPDFStream.WriteBytes(maDataContainer.getData(), maDataContainer.getSize());
+ aPDFStream.Seek(0);
+ auto pPDFDocument = std::make_shared<filter::PDFDocument>();
+ if (!pPDFDocument->ReadWithPossibleFixup(aPDFStream))
+ {
+ SAL_WARN("vcl.pdfwriter",
+ "PDFWriterImpl::writeReferenceXObject: reading the PDF document failed");
+ }
+ else
+ {
+ mpPDFDocument = pPDFDocument;
+ }
+ }
+ return mpPDFDocument;
+ }
+};
+
+// Class to manage external PDF streams, for the de-duplication purpose.
+class ExternalPDFStreams
+{
+private:
+ std::map<std::vector<sal_uInt8>, sal_Int32> maStreamIndexMap;
+ std::vector<ExternalPDFStream> maStreamList;
+
+public:
+ ExternalPDFStreams() {}
+
+ sal_Int32 store(BinaryDataContainer const& rDataContainer);
+
+ ExternalPDFStream& get(sal_uInt32 nIndex);
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/Matrix3.hxx b/vcl/inc/pdf/Matrix3.hxx
new file mode 100644
index 000000000..795b2af4b
--- /dev/null
+++ b/vcl/inc/pdf/Matrix3.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <vcl/dllapi.h>
+#include <tools/gen.hxx>
+
+namespace vcl::pdf
+{
+// matrix helper class
+// TODO: use basegfx matrix class instead or derive from it
+
+/* for sparse matrices of the form (2D linear transformations)
+ * f[0] f[1] 0
+ * f[2] f[3] 0
+ * f[4] f[5] 1
+ */
+class Matrix3
+{
+ double f[6];
+
+ void set(const double* pn)
+ {
+ for (int i = 0; i < 6; i++)
+ f[i] = pn[i];
+ }
+
+public:
+ Matrix3();
+
+ void skew(double alpha, double beta);
+ void scale(double sx, double sy);
+ void rotate(double angle);
+ void translate(double tx, double ty);
+ void invert();
+
+ double get(size_t i) const { return f[i]; }
+
+ Point transform(const Point& rPoint) const;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/PdfConfig.hxx b/vcl/inc/pdf/PdfConfig.hxx
new file mode 100644
index 000000000..235fd008e
--- /dev/null
+++ b/vcl/inc/pdf/PdfConfig.hxx
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+namespace vcl::pdf
+{
+double getDefaultPdfResolutionDpi();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/ResourceDict.hxx b/vcl/inc/pdf/ResourceDict.hxx
new file mode 100644
index 000000000..57ecb8e0f
--- /dev/null
+++ b/vcl/inc/pdf/ResourceDict.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <vcl/dllapi.h>
+#include <rtl/strbuf.hxx>
+#include <map>
+
+namespace vcl::pdf
+{
+enum class ResourceKind
+{
+ XObject,
+ ExtGState,
+ Shading,
+ Pattern
+};
+
+struct ResourceDict
+{
+ // note: handle fonts globally for performance
+ std::map<OString, sal_Int32> m_aXObjects;
+ std::map<OString, sal_Int32> m_aExtGStates;
+ std::map<OString, sal_Int32> m_aShadings;
+ std::map<OString, sal_Int32> m_aPatterns;
+
+ void append(OStringBuffer& rBuffer, sal_Int32 nFontDictObject);
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/XmpMetadata.hxx b/vcl/inc/pdf/XmpMetadata.hxx
new file mode 100644
index 000000000..7526d2bf9
--- /dev/null
+++ b/vcl/inc/pdf/XmpMetadata.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <vcl/dllapi.h>
+#include <rtl/string.hxx>
+#include <tools/stream.hxx>
+#include <memory>
+
+namespace vcl::pdf
+{
+class XmpMetadata
+{
+private:
+ bool mbWritten;
+ std::unique_ptr<SvMemoryStream> mpMemoryStream;
+
+public:
+ OString msTitle;
+ OString msAuthor;
+ OString msSubject;
+ OString msProducer;
+ OString msKeywords;
+ OString m_sCreatorTool;
+ OString m_sCreateDate;
+
+ sal_Int32 mnPDF_A;
+ bool mbPDF_UA;
+
+public:
+ XmpMetadata();
+ sal_uInt64 getSize();
+ const void* getData();
+
+private:
+ void write();
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/objectcopier.hxx b/vcl/inc/pdf/objectcopier.hxx
new file mode 100644
index 000000000..f9b05725c
--- /dev/null
+++ b/vcl/inc/pdf/objectcopier.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <map>
+#include <vector>
+
+#include <rtl/strbuf.hxx>
+#include <rtl/string.hxx>
+#include <sal/types.h>
+#include <vcl/dllapi.h>
+
+class SvMemoryStream;
+
+namespace vcl
+{
+class PDFObjectContainer;
+namespace filter
+{
+class PDFObjectElement;
+class PDFElement;
+}
+
+/// Copies objects from one PDF file into another one.
+class PDFObjectCopier
+{
+ PDFObjectContainer& m_rContainer;
+
+ void copyRecursively(OStringBuffer& rLine, filter::PDFElement& rInputElement,
+ SvMemoryStream& rDocBuffer,
+ std::map<sal_Int32, sal_Int32>& rCopiedResources);
+
+public:
+ PDFObjectCopier(PDFObjectContainer& rContainer);
+
+ /// Copies resources of a given kind from an external page to the output,
+ /// returning what has to be included in the new resource dictionary.
+ OString copyExternalResources(filter::PDFObjectElement& rPage, const OString& rKind,
+ std::map<sal_Int32, sal_Int32>& rCopiedResources);
+
+ /// Copies a single resource from an external document, returns the new
+ /// object ID in our document.
+ sal_Int32 copyExternalResource(SvMemoryStream& rDocBuffer, filter::PDFObjectElement& rObject,
+ std::map<sal_Int32, sal_Int32>& rCopiedResources);
+
+ /// Copies resources of pPage into rLine.
+ void copyPageResources(filter::PDFObjectElement* pPage, OStringBuffer& rLine);
+
+ void copyPageResources(filter::PDFObjectElement* pPage, OStringBuffer& rLine,
+ std::map<sal_Int32, sal_Int32>& rCopiedResources);
+
+ /// Copies page one or more page streams from rContentStreams into rStream.
+ static sal_Int32 copyPageStreams(std::vector<filter::PDFObjectElement*>& rContentStreams,
+ SvMemoryStream& rStream, bool& rCompressed);
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/pdfbuildin_fonts.hxx b/vcl/inc/pdf/pdfbuildin_fonts.hxx
new file mode 100644
index 000000000..fbcc04a9e
--- /dev/null
+++ b/vcl/inc/pdf/pdfbuildin_fonts.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <font/PhysicalFontFace.hxx>
+#include <fontinstance.hxx>
+
+namespace vcl::pdf
+{
+struct BuildinFont
+{
+ const char* m_pName;
+ const char* m_pStyleName;
+ const char* m_pPSName;
+ int const m_nAscent;
+ int const m_nDescent;
+ FontFamily const m_eFamily;
+ rtl_TextEncoding const m_eCharSet;
+ FontPitch const m_ePitch;
+ FontWidth const m_eWidthType;
+ FontWeight const m_eWeight;
+ FontItalic const m_eItalic;
+ int const m_aWidths[256];
+ mutable FontCharMapRef m_xFontCharMap;
+
+ OString getNameObject() const;
+ const FontCharMapRef& GetFontCharMap() const;
+ FontAttributes GetFontAttributes() const;
+};
+
+class BuildinFontInstance final : public LogicalFontInstance
+{
+ bool ImplGetGlyphBoundRect(sal_GlyphId nID, tools::Rectangle& rRect, bool) const override;
+
+public:
+ BuildinFontInstance(const vcl::font::PhysicalFontFace&, const vcl::font::FontSelectPattern&);
+
+ bool GetGlyphOutline(sal_GlyphId nId, basegfx::B2DPolyPolygon& rPoly, bool) const override;
+};
+
+class BuildinFontFace final : public vcl::font::PhysicalFontFace
+{
+ static const BuildinFont m_aBuildinFonts[14];
+ const BuildinFont& mrBuildin;
+
+ rtl::Reference<LogicalFontInstance>
+ CreateFontInstance(const vcl::font::FontSelectPattern& rFSD) const override;
+
+public:
+ explicit BuildinFontFace(int nId);
+
+ const BuildinFont& GetBuildinFont() const { return mrBuildin; }
+ sal_IntPtr GetFontId() const override { return reinterpret_cast<sal_IntPtr>(&mrBuildin); }
+ FontCharMapRef GetFontCharMap() const override { return mrBuildin.GetFontCharMap(); }
+ bool GetFontCapabilities(vcl::FontCapabilities&) const override { return false; }
+
+ static const BuildinFont& Get(int nId) { return m_aBuildinFonts[nId]; }
+};
+
+} // namespace vcl::pdf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/pdfcompat.hxx b/vcl/inc/pdf/pdfcompat.hxx
new file mode 100644
index 000000000..8f629b3bc
--- /dev/null
+++ b/vcl/inc/pdf/pdfcompat.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <config_features.h>
+#include <tools/gen.hxx>
+#include <tools/stream.hxx>
+#include <tools/UnitConversion.hxx>
+#include <vcl/graph.hxx>
+
+namespace vcl::pdf
+{
+/// Convert to inch, then assume 96 DPI.
+inline double pointToPixel(const double fPoint, const double fResolutionDPI)
+{
+ return o3tl::convert(fPoint, o3tl::Length::pt, o3tl::Length::in) * fResolutionDPI;
+}
+
+/// Decide if PDF data is old enough to be compatible.
+bool isCompatible(SvStream& rInStream, sal_uInt64 nPos, sal_uInt64 nSize);
+
+/// Converts to highest supported format version (currently 1.6).
+/// Usually used to deal with missing referenced objects in the
+/// source pdf stream.
+bool convertToHighestSupported(SvStream& rInStream, SvStream& rOutStream);
+
+/// Takes care of transparently downgrading the version of the PDF stream in
+/// case it's too new for our PDF export.
+bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream);
+
+BinaryDataContainer createBinaryDataContainer(SvStream& rStream);
+
+} // end of vcl::filter::ipdf namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/pdffontcache.hxx b/vcl/inc/pdf/pdffontcache.hxx
new file mode 100644
index 000000000..a6b58d8e7
--- /dev/null
+++ b/vcl/inc/pdf/pdffontcache.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <typeinfo>
+
+#include <sal/types.h>
+
+#include <salgdi.hxx>
+
+namespace vcl
+{
+ class PDFFontCache
+ {
+ struct FontIdentifier
+ {
+ sal_IntPtr m_nFontId;
+ bool m_bVertical;
+ std::type_info* m_typeFontFace;
+
+ FontIdentifier( const vcl::font::PhysicalFontFace*, bool bVertical );
+
+ // Less than needed for std::set and std::map
+ bool operator<( const FontIdentifier& rRight ) const
+ {
+ std::type_info *pType = rRight.m_typeFontFace;
+
+ return m_nFontId < rRight.m_nFontId ||
+ ( m_nFontId == rRight.m_nFontId &&
+ ( m_typeFontFace->before( *pType ) ||
+ ( *m_typeFontFace == *pType && m_bVertical < rRight.m_bVertical ) ) );
+ }
+ };
+ struct FontData
+ {
+ std::vector< sal_Int32 > m_nWidths;
+ Ucs2UIntMap m_aGlyphIdToIndex;
+ };
+ typedef std::map< FontIdentifier, sal_uInt32 > FontToIndexMap;
+
+ std::vector< FontData > m_aFonts;
+ FontToIndexMap m_aFontToIndex;
+
+ FontData& getFont( const vcl::font::PhysicalFontFace*, bool bVertical );
+ public:
+ PDFFontCache() {}
+
+ sal_Int32 getGlyphWidth( const vcl::font::PhysicalFontFace*, sal_GlyphId, bool bVertical, SalGraphics* );
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx
new file mode 100644
index 000000000..274f65f23
--- /dev/null
+++ b/vcl/inc/pdf/pdfwriter_impl.hxx
@@ -0,0 +1,1291 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <map>
+#include <list>
+#include <unordered_map>
+#include <memory>
+#include <string_view>
+#include <vector>
+
+#include <pdf/ResourceDict.hxx>
+#include <pdf/BitmapID.hxx>
+#include <pdf/Matrix3.hxx>
+
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/uno/Sequence.h>
+#include <osl/file.hxx>
+#include <rtl/cipher.h>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <tools/gen.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/graphictools.hxx>
+#include <vcl/hatch.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/pdfwriter.hxx>
+#include <vcl/wall.hxx>
+#include <o3tl/safeint.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <o3tl/lru_map.hxx>
+#include <comphelper/hash.hxx>
+#include <tools/stream.hxx>
+#include <vcl/BinaryDataContainer.hxx>
+
+#include <vcl/filter/pdfobjectcontainer.hxx>
+#include <vcl/settings.hxx>
+#include <pdf/ExternalPDFStreams.hxx>
+#include <pdf/pdfbuildin_fonts.hxx>
+#include <pdf/pdffontcache.hxx>
+
+class FontSubsetInfo;
+class ZCodec;
+class EncHashTransporter;
+struct BitStreamState;
+namespace vcl::font { class PhysicalFontFace; }
+class SvStream;
+class SvMemoryStream;
+
+// the maximum password length
+constexpr sal_Int32 ENCRYPTED_PWD_SIZE = 32;
+constexpr sal_Int32 MD5_DIGEST_SIZE = 16;
+// security 128 bit
+constexpr sal_Int32 SECUR_128BIT_KEY = 16;
+// maximum length of MD5 digest input, in step 2 of algorithm 3.1
+// PDF spec ver. 1.4: see there for details
+constexpr sal_Int32 MAXIMUM_RC4_KEY_LENGTH = SECUR_128BIT_KEY + 3 + 2;
+
+namespace vcl::pdf
+{
+
+enum class GraphicsStateUpdateFlags {
+ Font = 0x0001,
+ MapMode = 0x0002,
+ LineColor = 0x0004,
+ FillColor = 0x0008,
+ ClipRegion = 0x0040,
+ LayoutMode = 0x0100,
+ TransparentPercent = 0x0200,
+ DigitLanguage = 0x0400,
+ All = 0x077f
+};
+
+} // end vcl::pdf
+
+namespace o3tl {
+ template<> struct typed_flags<vcl::pdf::GraphicsStateUpdateFlags> : is_typed_flags<vcl::pdf::GraphicsStateUpdateFlags, 0x077f> {};
+}
+
+namespace vcl
+{
+
+using namespace vcl::pdf;
+
+class PDFStreamIf;
+
+namespace filter
+{
+class PDFObjectElement;
+}
+
+namespace pdf
+{
+constexpr sal_Int32 g_nInheritedPageWidth = 595; // default A4 in inch/72
+constexpr sal_Int32 g_nInheritedPageHeight = 842; // default A4 in inch/72
+
+struct PDFPage
+{
+ VclPtr<PDFWriterImpl> m_pWriter;
+ double m_nPageWidth; // in inch/72
+ double m_nPageHeight; // in inch/72
+ /**
+ * A positive number that gives the size of default user space units, in multiples of points.
+ * Typically 1, larger if page size is > 508 cm.
+ */
+ sal_Int32 m_nUserUnit;
+ PDFWriter::Orientation m_eOrientation;
+ sal_Int32 m_nPageObject;
+ std::vector<sal_Int32> m_aStreamObjects;
+ sal_Int32 m_nStreamLengthObject;
+ sal_uInt64 m_nBeginStreamPos;
+ std::vector<sal_Int32> m_aAnnotations;
+ std::vector<sal_Int32> m_aMCIDParents;
+ PDFWriter::PageTransition m_eTransition;
+ sal_uInt32 m_nTransTime;
+
+ PDFPage( PDFWriterImpl* pWriter, double nPageWidth, double nPageHeight, PDFWriter::Orientation eOrientation );
+
+ void beginStream();
+ void endStream();
+ bool emit( sal_Int32 nParentPage );
+
+ // converts point from ref device coordinates to
+ // page coordinates and appends the point to the buffer
+ // if pOutPoint is set it will be updated to the emitted point
+ // (in PDF map mode, that is 10th of point)
+ void appendPoint( const Point& rPoint, OStringBuffer& rBuffer ) const;
+ // appends a B2DPoint without further transformation
+ void appendPixelPoint( const basegfx::B2DPoint& rPoint, OStringBuffer& rBuffer ) const;
+ // appends a rectangle
+ void appendRect( const tools::Rectangle& rRect, OStringBuffer& rBuffer ) const;
+ // converts a rectangle to 10th points page space
+ void convertRect( tools::Rectangle& rRect ) const;
+ // appends a polygon optionally closing it
+ void appendPolygon( const tools::Polygon& rPoly, OStringBuffer& rBuffer, bool bClose = true ) const;
+ // appends a polygon optionally closing it
+ void appendPolygon( const basegfx::B2DPolygon& rPoly, OStringBuffer& rBuffer ) const;
+ // appends a polypolygon optionally closing the subpaths
+ void appendPolyPolygon( const tools::PolyPolygon& rPolyPoly, OStringBuffer& rBuffer ) const;
+ // appends a polypolygon optionally closing the subpaths
+ void appendPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly, OStringBuffer& rBuffer ) const;
+ // converts a length (either vertical or horizontal; this
+ // can be important if the source MapMode is not
+ // symmetrical) to page length and appends it to the buffer
+ // if pOutLength is set it will be updated to the emitted length
+ // (in PDF map mode, that is 10th of point)
+ void appendMappedLength( sal_Int32 nLength, OStringBuffer& rBuffer, bool bVertical = true, sal_Int32* pOutLength = nullptr ) const;
+ // the same for double values
+ void appendMappedLength( double fLength, OStringBuffer& rBuffer, bool bVertical = true, sal_Int32 nPrecision = 5 ) const;
+ // appends LineInfo
+ // returns false if too many dash array entry were created for
+ // the implementation limits of some PDF readers
+ bool appendLineInfo( const LineInfo& rInfo, OStringBuffer& rBuffer ) const;
+ // appends a horizontal waveline with vertical offset (helper for drawWaveLine)
+ void appendWaveLine( sal_Int32 nLength, sal_Int32 nYOffset, sal_Int32 nDelta, OStringBuffer& rBuffer ) const;
+
+ void appendMatrix3(Matrix3 const & rMatrix, OStringBuffer& rBuffer);
+
+ double getHeight() const;
+};
+
+/// Contains information to emit a reference XObject.
+struct ReferenceXObjectEmit
+{
+ /// ID of the Form XObject, if any.
+ sal_Int32 m_nFormObject;
+ /// ID of the vector/embedded object, if m_nFormObject is used.
+ sal_Int32 m_nEmbeddedObject;
+ /// ID of the bitmap object, if m_nFormObject is used.
+ sal_Int32 m_nBitmapObject;
+ /// Size of the bitmap replacement, in pixels.
+ Size m_aPixelSize;
+ /// PDF data from the graphic object, if not writing a reference XObject.
+ sal_Int32 m_nExternalPDFDataIndex;
+ sal_Int32 m_nExternalPDFPageIndex;
+
+ ReferenceXObjectEmit()
+ : m_nFormObject(0)
+ , m_nEmbeddedObject(0)
+ , m_nBitmapObject(0)
+ , m_nExternalPDFDataIndex(-1)
+ , m_nExternalPDFPageIndex(-1)
+ {
+ }
+
+ /// Returns the ID one should use when referring to this bitmap.
+ sal_Int32 getObject() const;
+
+ bool hasExternalPDFData() const
+ {
+ return m_nExternalPDFDataIndex >= 0;
+ }
+};
+
+struct BitmapEmit
+{
+ BitmapID m_aID;
+ BitmapEx m_aBitmap;
+ sal_Int32 m_nObject;
+ ReferenceXObjectEmit m_aReferenceXObject;
+
+ BitmapEmit()
+ : m_nObject(0)
+ {
+ }
+};
+
+struct JPGEmit
+{
+ BitmapID m_aID;
+ std::unique_ptr<SvMemoryStream>
+ m_pStream;
+ AlphaMask m_aAlphaMask;
+ sal_Int32 m_nObject;
+ bool m_bTrueColor;
+ ReferenceXObjectEmit m_aReferenceXObject;
+
+ JPGEmit()
+ : m_nObject(0)
+ , m_bTrueColor(false)
+ {
+ }
+};
+
+struct GradientEmit
+{
+ Gradient m_aGradient;
+ Size m_aSize;
+ sal_Int32 m_nObject;
+};
+
+// for tilings (drawWallpaper, begin/endPattern)
+struct TilingEmit
+{
+ sal_Int32 m_nObject;
+ tools::Rectangle m_aRectangle;
+ Size m_aCellSize;
+ SvtGraphicFill::Transform m_aTransform;
+ ResourceDict m_aResources;
+ std::unique_ptr<SvMemoryStream> m_pTilingStream;
+
+ TilingEmit()
+ : m_nObject( 0 )
+ {}
+};
+
+// for transparency group XObjects
+struct TransparencyEmit
+{
+ sal_Int32 m_nObject;
+ sal_Int32 m_nExtGStateObject;
+ double m_fAlpha;
+ tools::Rectangle m_aBoundRect;
+ std::unique_ptr<SvMemoryStream> m_pContentStream;
+
+ TransparencyEmit()
+ : m_nObject( 0 ),
+ m_nExtGStateObject( -1 ),
+ m_fAlpha( 0.0 )
+ {}
+};
+
+// font subsets
+class GlyphEmit
+{
+ // performance: actually this should probably a vector;
+ std::vector<sal_Ucs> m_CodeUnits;
+ sal_uInt8 m_nSubsetGlyphID;
+ sal_Int32 m_nGlyphWidth;
+
+public:
+ GlyphEmit() : m_nSubsetGlyphID(0), m_nGlyphWidth(0)
+ {
+ }
+
+ void setGlyphId( sal_uInt8 i_nId ) { m_nSubsetGlyphID = i_nId; }
+ sal_uInt8 getGlyphId() const { return m_nSubsetGlyphID; }
+
+ void setGlyphWidth( sal_Int32 nWidth ) { m_nGlyphWidth = nWidth; }
+ sal_Int32 getGlyphWidth() const { return m_nGlyphWidth; }
+
+ void addCode( sal_Ucs i_cCode )
+ {
+ m_CodeUnits.push_back(i_cCode);
+ }
+ sal_Int32 countCodes() const { return m_CodeUnits.size(); }
+ const std::vector<sal_Ucs>& codes() const { return m_CodeUnits; }
+ sal_Ucs getCode( sal_Int32 i_nIndex ) const
+ {
+ sal_Ucs nRet = 0;
+ if (o3tl::make_unsigned(i_nIndex) < m_CodeUnits.size())
+ nRet = m_CodeUnits[i_nIndex];
+ return nRet;
+ }
+};
+
+struct FontEmit
+{
+ sal_Int32 m_nFontID;
+ std::map<sal_GlyphId, GlyphEmit> m_aMapping;
+
+ explicit FontEmit( sal_Int32 nID ) : m_nFontID( nID ) {}
+};
+
+struct Glyph
+{
+ sal_Int32 m_nFontID;
+ sal_uInt8 m_nSubsetGlyphID;
+};
+
+struct FontSubset
+{
+ std::vector< FontEmit > m_aSubsets;
+ std::map<sal_GlyphId, Glyph> m_aMapping;
+};
+
+struct EmbedFont
+{
+ sal_Int32 m_nNormalFontID;
+
+ EmbedFont() : m_nNormalFontID( 0 ) {}
+};
+
+struct PDFDest
+{
+ sal_Int32 m_nPage;
+ PDFWriter::DestAreaType m_eType;
+ tools::Rectangle m_aRect;
+};
+
+//--->i56629
+struct PDFNamedDest
+{
+ OUString m_aDestName;
+ sal_Int32 m_nPage;
+ PDFWriter::DestAreaType m_eType;
+ tools::Rectangle m_aRect;
+};
+
+struct PDFOutlineEntry
+{
+ sal_Int32 m_nObject;
+ sal_Int32 m_nParentObject;
+ sal_Int32 m_nNextObject;
+ sal_Int32 m_nPrevObject;
+ std::vector< sal_Int32 > m_aChildren;
+ OUString m_aTitle;
+ sal_Int32 m_nDestID;
+
+ PDFOutlineEntry()
+ : m_nObject( 0 ),
+ m_nParentObject( 0 ),
+ m_nNextObject( 0 ),
+ m_nPrevObject( 0 ),
+ m_nDestID( -1 )
+ {}
+};
+
+struct PDFAnnotation
+{
+ sal_Int32 m_nObject;
+ tools::Rectangle m_aRect;
+ sal_Int32 m_nPage;
+
+ PDFAnnotation()
+ : m_nObject( -1 ),
+ m_nPage( -1 )
+ {}
+};
+
+struct PDFLink : public PDFAnnotation
+{
+ sal_Int32 m_nDest; // set to -1 for URL, to a dest else
+ OUString m_aURL;
+ sal_Int32 m_nStructParent; // struct parent entry
+ OUString m_AltText;
+
+ PDFLink(OUString const& rAltText)
+ : m_nDest( -1 ),
+ m_nStructParent( -1 )
+ , m_AltText(rAltText)
+ {}
+};
+
+/// A PDF embedded file.
+struct PDFEmbeddedFile
+{
+ /// ID of the file.
+ sal_Int32 m_nObject;
+ /// Contents of the file.
+ BinaryDataContainer m_aDataContainer;
+
+ PDFEmbeddedFile()
+ : m_nObject(0)
+ {
+ }
+};
+
+struct PDFPopupAnnotation : public PDFAnnotation
+{
+ /// ID of the parent object.
+ sal_Int32 m_nParentObject;
+};
+
+struct PDFNoteEntry : public PDFAnnotation
+{
+ PDFNote m_aContents;
+
+ PDFPopupAnnotation m_aPopUpAnnotation;
+
+ PDFNoteEntry()
+ {}
+};
+
+/// A PDF Screen annotation.
+struct PDFScreen : public PDFAnnotation
+{
+ /// Linked video.
+ OUString m_aURL;
+ /// Embedded video.
+ OUString m_aTempFileURL;
+ /// ID of the EmbeddedFile object.
+ sal_Int32 m_nTempFileObject;
+
+ PDFScreen()
+ : m_nTempFileObject(0)
+ {
+ }
+};
+
+struct PDFWidget : public PDFAnnotation
+{
+ PDFWriter::WidgetType m_eType;
+ OString m_aName;
+ OUString m_aDescription;
+ OUString m_aText;
+ DrawTextFlags m_nTextStyle;
+ OUString m_aValue;
+ OString m_aDAString;
+ OString m_aDRDict;
+ OString m_aMKDict;
+ OString m_aMKDictCAString; // i12626, added to be able to encrypt the /CA text string
+ // since the object number is not known at the moment
+ // of filling m_aMKDict, the string will be encrypted when emitted.
+ // the /CA string MUST BE the last added to m_aMKDict
+ // see code for details
+ sal_Int32 m_nFlags;
+ sal_Int32 m_nParent; // if not 0, parent's object number
+ std::vector<sal_Int32> m_aKids; // widget children, contains object numbers
+ std::vector<sal_Int32> m_aKidsIndex; // widget children, contains index to m_aWidgets
+ OUString m_aOnValue;
+ OUString m_aOffValue;
+ sal_Int32 m_nTabOrder; // lowest number gets first in tab order
+ sal_Int32 m_nRadioGroup;
+ sal_Int32 m_nMaxLen;
+ PDFWriter::FormatType m_nFormat;
+ OUString m_aCurrencySymbol;
+ sal_Int32 m_nDecimalAccuracy;
+ bool m_bPrependCurrencySymbol;
+ OUString m_aTimeFormat;
+ OUString m_aDateFormat;
+ bool m_bSubmit;
+ bool m_bSubmitGet;
+ sal_Int32 m_nDest;
+ std::vector<OUString> m_aListEntries;
+ std::vector<sal_Int32> m_aSelectedEntries;
+ typedef std::unordered_map<OString, SvMemoryStream*> PDFAppearanceStreams;
+ std::unordered_map<OString, PDFAppearanceStreams> m_aAppearances;
+ PDFWidget()
+ : m_eType( PDFWriter::PushButton ),
+ m_nTextStyle( DrawTextFlags::NONE ),
+ m_nFlags( 0 ),
+ m_nParent( 0 ),
+ m_nTabOrder( 0 ),
+ m_nRadioGroup( -1 ),
+ m_nMaxLen( 0 ),
+ m_nFormat( PDFWriter::FormatType::Text ),
+ m_nDecimalAccuracy ( 0 ),
+ m_bPrependCurrencySymbol( false ),
+ m_bSubmit( false ),
+ m_bSubmitGet( false ),
+ m_nDest( -1 )
+ {}
+};
+
+struct PDFStructureAttribute
+{
+ PDFWriter::StructAttributeValue eValue;
+ sal_Int32 nValue;
+
+ PDFStructureAttribute()
+ : eValue( PDFWriter::Invalid ),
+ nValue( 0 )
+ {}
+
+ explicit PDFStructureAttribute( PDFWriter::StructAttributeValue eVal )
+ : eValue( eVal ),
+ nValue( 0 )
+ {}
+
+ explicit PDFStructureAttribute( sal_Int32 nVal )
+ : eValue( PDFWriter::Invalid ),
+ nValue( nVal )
+ {}
+};
+
+struct PDFStructureElementKid // for Kids entries
+{
+ sal_Int32 const nObject; // an object number if nMCID is -1,
+ // else the page object relevant to MCID
+ sal_Int32 const nMCID; // an MCID if >= 0
+
+ explicit PDFStructureElementKid( sal_Int32 nObj ) : nObject( nObj ), nMCID( -1 ) {}
+ PDFStructureElementKid( sal_Int32 MCID, sal_Int32 nPage ) : nObject( nPage ), nMCID( MCID ) {}
+};
+
+struct PDFStructureElement
+{
+ sal_Int32 m_nObject;
+ PDFWriter::StructElement m_eType;
+ OString m_aAlias;
+ sal_Int32 m_nOwnElement; // index into structure vector
+ sal_Int32 m_nParentElement; // index into structure vector
+ sal_Int32 m_nFirstPageObject;
+ bool m_bOpenMCSeq;
+ std::list< sal_Int32 > m_aChildren; // indexes into structure vector
+ std::list< PDFStructureElementKid > m_aKids;
+ std::map<PDFWriter::StructAttribute, PDFStructureAttribute >
+ m_aAttributes;
+ tools::Rectangle m_aBBox;
+ OUString m_aActualText;
+ OUString m_aAltText;
+ css::lang::Locale m_aLocale;
+
+ // m_aContents contains the element's marked content sequence
+ // as pairs of (page nr, MCID)
+
+ PDFStructureElement()
+ : m_nObject( 0 ),
+ m_eType( PDFWriter::NonStructElement ),
+ m_nOwnElement( -1 ),
+ m_nParentElement( -1 ),
+ m_nFirstPageObject( 0 ),
+ m_bOpenMCSeq( false )
+ {
+ }
+
+};
+
+struct PDFAddStream
+{
+ OUString m_aMimeType;
+ PDFOutputStream* m_pStream;
+ sal_Int32 m_nStreamObject;
+ bool m_bCompress;
+
+ PDFAddStream() : m_pStream( nullptr ), m_nStreamObject( 0 ), m_bCompress( true ) {}
+};
+
+// helper structure for drawLayout and friends
+struct PDFGlyph
+{
+ Point const m_aPos;
+ const GlyphItem* m_pGlyph;
+ sal_Int32 const m_nNativeWidth;
+ sal_Int32 const m_nMappedFontId;
+ sal_uInt8 const m_nMappedGlyphId;
+ int const m_nCharPos;
+
+ PDFGlyph( const Point& rPos,
+ const GlyphItem* pGlyph,
+ sal_Int32 nNativeWidth,
+ sal_Int32 nFontId,
+ sal_uInt8 nMappedGlyphId,
+ int nCharPos )
+ : m_aPos( rPos ), m_pGlyph(pGlyph), m_nNativeWidth( nNativeWidth ),
+ m_nMappedFontId( nFontId ), m_nMappedGlyphId( nMappedGlyphId ),
+ m_nCharPos(nCharPos)
+ {}
+};
+
+struct StreamRedirect
+{
+ SvStream* m_pStream;
+ MapMode m_aMapMode;
+ tools::Rectangle m_aTargetRect;
+ ResourceDict m_aResourceDict;
+};
+
+// graphics state
+struct GraphicsState
+{
+ vcl::Font m_aFont;
+ MapMode m_aMapMode;
+ Color m_aLineColor;
+ Color m_aFillColor;
+ Color m_aTextLineColor;
+ Color m_aOverlineColor;
+ basegfx::B2DPolyPolygon m_aClipRegion;
+ bool m_bClipRegion;
+ vcl::text::ComplexTextLayoutFlags m_nLayoutMode;
+ LanguageType m_aDigitLanguage;
+ PushFlags m_nFlags;
+ GraphicsStateUpdateFlags m_nUpdateFlags;
+
+ GraphicsState() :
+ m_aLineColor( COL_TRANSPARENT ),
+ m_aFillColor( COL_TRANSPARENT ),
+ m_aTextLineColor( COL_TRANSPARENT ),
+ m_aOverlineColor( COL_TRANSPARENT ),
+ m_bClipRegion( false ),
+ m_nLayoutMode( vcl::text::ComplexTextLayoutFlags::Default ),
+ m_aDigitLanguage( 0 ),
+ m_nFlags( PushFlags::ALL ),
+ m_nUpdateFlags( GraphicsStateUpdateFlags::All )
+ {}
+};
+
+enum class Mode { DEFAULT, NOWRITE };
+
+}
+
+class PDFWriterImpl final : public VirtualDevice, public PDFObjectContainer
+{
+ friend class PDFStreamIf;
+
+public:
+ friend struct vcl::pdf::PDFPage;
+
+ static const char* getStructureTag( PDFWriter::StructElement );
+ static const char* getAttributeTag( PDFWriter::StructAttribute eAtr );
+ static const char* getAttributeValueTag( PDFWriter::StructAttributeValue eVal );
+
+ // returns true if compression was done
+ // else false
+ static bool compressStream( SvMemoryStream* );
+
+ static void convertLineInfoToExtLineInfo( const LineInfo& rIn, PDFWriter::ExtLineInfo& rOut );
+
+private:
+ bool ImplNewFont() const override;
+ void ImplClearFontData(bool bNewFontLists) override;
+ void ImplRefreshFontData(bool bNewFontLists) override;
+ vcl::Region ClipToDeviceBounds(vcl::Region aRegion) const override;
+ void DrawHatchLine_DrawLine(const Point& rStartPoint, const Point& rEndPoint) override;
+
+ MapMode m_aMapMode; // PDFWriterImpl scaled units
+ StyleSettings m_aWidgetStyleSettings;
+ std::vector< PDFPage > m_aPages;
+ /* maps object numbers to file offsets (needed for xref) */
+ std::vector< sal_uInt64 > m_aObjects;
+ /* contains Bitmaps until they are written to the
+ * file stream as XObjects*/
+ std::list< BitmapEmit > m_aBitmaps;
+ /* contains JPG streams until written to file */
+ std::vector<JPGEmit> m_aJPGs;
+ /*--->i56629 contains all named destinations ever set during the PDF creation,
+ destination id is always the destination's position in this vector
+ */
+ std::vector<PDFNamedDest> m_aNamedDests;
+ /* contains all dests ever set during the PDF creation,
+ dest id is always the dest's position in this vector
+ */
+ std::vector<PDFDest> m_aDests;
+ /** contains destinations accessible via a public Id, instead of being linked to by an ordinary link
+ */
+ ::std::map< sal_Int32, sal_Int32 > m_aDestinationIdTranslation;
+ /* contains all links ever set during PDF creation,
+ link id is always the link's position in this vector
+ */
+ std::vector<PDFLink> m_aLinks;
+ /// Contains all screen annotations.
+ std::vector<PDFScreen> m_aScreens;
+ /// Contains embedded files.
+ std::vector<PDFEmbeddedFile> m_aEmbeddedFiles;
+ /* makes correctly encoded for export to PDF URLS
+ */
+ css::uno::Reference< css::util::XURLTransformer > m_xTrans;
+ /* maps arbitrary link ids for structure attributes to real link ids
+ (for setLinkPropertyId)
+ */
+ std::map<sal_Int32, sal_Int32> m_aLinkPropertyMap;
+ /* contains all outline items,
+ object 0 is the outline root
+ */
+ std::vector<PDFOutlineEntry> m_aOutline;
+ /* contains all notes set during PDF creation
+ */
+ std::vector<PDFNoteEntry> m_aNotes;
+ /* the root of the structure tree
+ */
+ std::vector<PDFStructureElement> m_aStructure;
+ /* current object in the structure hierarchy
+ */
+ sal_Int32 m_nCurrentStructElement;
+ /* structure parent tree */
+ std::vector< OString > m_aStructParentTree;
+ /* emit structure marks currently (aka. NonStructElement or not)
+ */
+ bool m_bEmitStructure;
+ /* role map of struct tree root */
+ std::unordered_map< OString, OString >
+ m_aRoleMap;
+
+ /* contains all widgets used in the PDF
+ */
+ std::vector<PDFWidget> m_aWidgets;
+ /* maps radio group id to index of radio group control in m_aWidgets */
+ std::map< sal_Int32, sal_Int32 > m_aRadioGroupWidgets;
+ /* unordered_map for field names, used to ensure unique field names */
+ std::unordered_map< OString, sal_Int32 > m_aFieldNameMap;
+
+ /* contains Bitmaps for gradient functions until they are written
+ * to the file stream */
+ std::list< GradientEmit > m_aGradients;
+ /* contains bitmap tiling patterns */
+ std::vector< TilingEmit > m_aTilings;
+ std::vector< TransparencyEmit > m_aTransparentObjects;
+ /* contains all font subsets in use */
+ std::map<const vcl::font::PhysicalFontFace*, FontSubset> m_aSubsets;
+ std::map<const vcl::font::PhysicalFontFace*, EmbedFont> m_aSystemFonts;
+ sal_Int32 m_nNextFID;
+ PDFFontCache m_aFontCache;
+
+ /// Cache some most recent bitmaps we've exported, in case we encounter them again..
+ o3tl::lru_map<BitmapChecksum,
+ std::shared_ptr<SvMemoryStream>> m_aPDFBmpCache;
+
+ sal_Int32 m_nCurrentPage;
+
+ sal_Int32 m_nCatalogObject;
+ // object number of the main signature dictionary
+ sal_Int32 m_nSignatureObject;
+ sal_Int64 m_nSignatureContentOffset;
+ sal_Int64 m_nSignatureLastByteRangeNoOffset;
+ sal_Int32 m_nResourceDict;
+ ResourceDict m_aGlobalResourceDict;
+ sal_Int32 m_nFontDictObject;
+ std::map< sal_Int32, sal_Int32 > m_aBuildinFontToObjectMap;
+
+ PDFWriter::PDFWriterContext m_aContext;
+ osl::File m_aFile;
+ bool m_bOpen;
+
+ ExternalPDFStreams m_aExternalPDFStreams;
+
+ /* output redirection; e.g. to accumulate content streams for
+ XObjects
+ */
+ std::list< StreamRedirect > m_aOutputStreams;
+
+ std::list< GraphicsState > m_aGraphicsStack;
+ GraphicsState m_aCurrentPDFState;
+
+ std::unique_ptr<ZCodec> m_pCodec;
+ std::unique_ptr<SvMemoryStream> m_pMemStream;
+
+ std::vector< PDFAddStream > m_aAdditionalStreams;
+ std::set< PDFWriter::ErrorCode > m_aErrors;
+
+ ::comphelper::Hash m_DocDigest;
+
+/*
+variables for PDF security
+i12626
+*/
+/* used to cipher the stream data and for password management */
+ rtlCipher m_aCipher;
+ /* pad string used for password in Standard security handler */
+ static const sal_uInt8 s_nPadString[ENCRYPTED_PWD_SIZE];
+
+ /* the encryption key, formed with the user password according to algorithm 3.2, maximum length is 16 bytes + 3 + 2
+ for 128 bit security */
+ sal_Int32 m_nKeyLength; // key length, 16 or 5
+ sal_Int32 m_nRC4KeyLength; // key length, 16 or 10, to be input to the algorithm 3.1
+
+ /* set to true if the following stream must be encrypted, used inside writeBuffer() */
+ bool m_bEncryptThisStream;
+
+ /* the numerical value of the access permissions, according to PDF spec, must be signed */
+ sal_Int32 m_nAccessPermissions;
+ /* string to hold the PDF creation date */
+ OString m_aCreationDateString;
+ /* string to hold the PDF creation date, for PDF/A metadata */
+ OString m_aCreationMetaDateString;
+ /* the buffer where the data are encrypted, dynamically allocated */
+ std::vector<sal_uInt8> m_vEncryptionBuffer;
+
+ void addRoleMap(OString aAlias, PDFWriter::StructElement eType);
+
+ /* this function implements part of the PDF spec algorithm 3.1 in encryption, the rest (the actual encryption) is in PDFWriterImpl::writeBuffer */
+ void checkAndEnableStreamEncryption( sal_Int32 nObject ) override;
+
+ void disableStreamEncryption() override { m_bEncryptThisStream = false; };
+
+ /* */
+ void enableStringEncryption( sal_Int32 nObject );
+
+// test if the encryption is active, if yes than encrypt the unicode string and add to the OStringBuffer parameter
+ void appendUnicodeTextStringEncrypt( const OUString& rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer );
+
+ void appendLiteralStringEncrypt( std::u16string_view rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer, rtl_TextEncoding nEnc = RTL_TEXTENCODING_ASCII_US );
+ void appendLiteralStringEncrypt( std::string_view rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer );
+
+ /* creates fonts and subsets that will be emitted later */
+ void registerGlyph(const GlyphItem* pGlyph, const vcl::font::PhysicalFontFace* pFont, const std::vector<sal_Ucs>& rCodeUnits, sal_Int32 nGlyphWidth, sal_uInt8& nMappedGlyph, sal_Int32& nMappedFontObject);
+
+ /* emits a text object according to the passed layout */
+ /* TODO: remove rText as soon as SalLayout will change so that rText is not necessary anymore */
+ void drawVerticalGlyphs( const std::vector<PDFGlyph>& rGlyphs, OStringBuffer& rLine, const Point& rAlignOffset, const Matrix3& rRotScale, double fAngle, double fXScale, double fSkew, sal_Int32 nFontHeight );
+ void drawHorizontalGlyphs( const std::vector<PDFGlyph>& rGlyphs, OStringBuffer& rLine, const Point& rAlignOffset, bool bFirst, double fAngle, double fXScale, double fSkew, sal_Int32 nFontHeight, sal_Int32 nPixelFontHeight );
+ void drawLayout( SalLayout& rLayout, const OUString& rText, bool bTextLines );
+ void drawRelief( SalLayout& rLayout, const OUString& rText, bool bTextLines );
+ void drawShadow( SalLayout& rLayout, const OUString& rText, bool bTextLines );
+
+ /* writes differences between graphics stack and current real PDF
+ * state to the file
+ */
+ void updateGraphicsState(Mode mode = Mode::DEFAULT);
+
+ /* writes a transparency group object */
+ void writeTransparentObject( TransparencyEmit& rObject );
+
+ /* writes an XObject of type image, may create
+ a second for the mask
+ */
+ bool writeBitmapObject( const BitmapEmit& rObject, bool bMask = false );
+
+ void writeJPG( const JPGEmit& rEmit );
+ /// Writes the form XObject proxy for the image.
+ void writeReferenceXObject(const ReferenceXObjectEmit& rEmit);
+
+ /* tries to find the bitmap by its id and returns its emit data if exists,
+ else creates a new emit data block */
+ const BitmapEmit& createBitmapEmit( const BitmapEx& rBitmapEx, const Graphic& rGraphic );
+
+ /* writes the Do operation inside the content stream */
+ void drawBitmap( const Point& rDestPt, const Size& rDestSize, const BitmapEmit& rBitmap, const Color& rFillColor );
+ /* write the function object for a Gradient */
+ bool writeGradientFunction( GradientEmit const & rObject );
+ /* creates a GradientEmit and returns its object number */
+ sal_Int32 createGradient( const Gradient& rGradient, const Size& rSize );
+
+ /* writes all tilings */
+ bool emitTilings();
+ /* writes all gradient patterns */
+ bool emitGradients();
+ /* writes a builtin font object and returns its objectid (or 0 in case of failure ) */
+ sal_Int32 emitBuildinFont( const pdf::BuildinFontFace*, sal_Int32 nObject );
+ /* writes a type1 system font object and returns its mapping from font ids to object ids (or 0 in case of failure ) */
+ std::map< sal_Int32, sal_Int32 > emitSystemFont(const vcl::font::PhysicalFontFace*, EmbedFont const &);
+ /* writes a font descriptor and returns its object id (or 0) */
+ sal_Int32 emitFontDescriptor(const vcl::font::PhysicalFontFace*, FontSubsetInfo const &, sal_Int32 nSubsetID, sal_Int32 nStream);
+ /* writes a ToUnicode cmap, returns the corresponding stream object */
+ sal_Int32 createToUnicodeCMap( sal_uInt8 const * pEncoding, const sal_Ucs* pCodeUnits, const sal_Int32* pCodeUnitsPerGlyph,
+ const sal_Int32* pEncToUnicodeIndex, int nGlyphs );
+
+ /* get resource dict object number */
+ sal_Int32 getResourceDictObj()
+ {
+ if( m_nResourceDict <= 0 )
+ m_nResourceDict = createObject();
+ return m_nResourceDict;
+ }
+ /* get the font dict object */
+ sal_Int32 getFontDictObject()
+ {
+ if( m_nFontDictObject <= 0 )
+ m_nFontDictObject = createObject();
+ return m_nFontDictObject;
+ }
+ /* push resource into current (redirected) resource dict */
+ void pushResource( ResourceKind eKind, const OString& rResource, sal_Int32 nObject );
+
+ void appendBuildinFontsToDict( OStringBuffer& rDict ) const;
+ /* writes the font dictionary and emits all font objects
+ * returns object id of font directory (or 0 on error)
+ */
+ bool emitFonts();
+ /* writes the Resource dictionary;
+ * returns dict object id (or 0 on error)
+ */
+ sal_Int32 emitResources();
+ // appends a dest
+ bool appendDest( sal_Int32 nDestID, OStringBuffer& rBuffer );
+ // write all links
+ bool emitLinkAnnotations();
+ // Write all screen annotations.
+ bool emitScreenAnnotations();
+
+ void emitTextAnnotationLine(OStringBuffer & aLine, PDFNoteEntry const & rNote);
+ static void emitPopupAnnotationLine(OStringBuffer & aLine, PDFPopupAnnotation const & rPopUp);
+ // write all notes
+ bool emitNoteAnnotations();
+
+ // write the appearance streams of a widget
+ bool emitAppearances( PDFWidget& rWidget, OStringBuffer& rAnnotDict );
+ // clean up radio button "On" values
+ void ensureUniqueRadioOnValues();
+ // write all widgets
+ bool emitWidgetAnnotations();
+ // writes all annotation objects
+ bool emitAnnotations();
+ /// Writes embedded files.
+ bool emitEmbeddedFiles();
+ //write the named destination stuff
+ sal_Int32 emitNamedDestinations();//i56629
+ // writes outline dict and tree
+ sal_Int32 emitOutline();
+ // puts the attribute objects of a structure element into the returned string,
+ // helper for emitStructure
+ OString emitStructureAttributes( PDFStructureElement& rEle );
+ //--->i94258
+ // the maximum array elements allowed for PDF array object
+ static const sal_uInt32 ncMaxPDFArraySize = 8191;
+ //check if internal dummy container are needed in the structure elements
+ void addInternalStructureContainer( PDFStructureElement& rEle );
+ //<---i94258
+ // writes document structure
+ sal_Int32 emitStructure( PDFStructureElement& rEle );
+ // writes structure parent tree
+ sal_Int32 emitStructParentTree( sal_Int32 nTreeObject );
+ // writes page tree and catalog
+ bool emitCatalog();
+ // writes signature dictionary object
+ bool emitSignature();
+ // creates a PKCS7 object using the ByteRange and overwrite /Contents
+ // of the signature dictionary
+ bool finalizeSignature();
+ // writes xref and trailer
+ bool emitTrailer();
+ // emit additional streams collected; also create there object numbers
+ bool emitAdditionalStreams();
+ // emits info dict (if applicable)
+ sal_Int32 emitInfoDict( );
+
+ // acrobat reader 5 and 6 use the order of the annotations
+ // as their tab order; since PDF1.5 one can make the
+ // tab order explicit by using the structure tree
+ void sortWidgets();
+
+ // updates the count numbers of outline items
+ sal_Int32 updateOutlineItemCount( std::vector< sal_Int32 >& rCounts,
+ sal_Int32 nItemLevel,
+ sal_Int32 nCurrentItemId );
+ // default appearances for widgets
+ sal_Int32 findRadioGroupWidget( const PDFWriter::RadioButtonWidget& rRadio );
+ Font replaceFont( const Font& rControlFont, const Font& rAppSetFont );
+ sal_Int32 getBestBuildinFont( const Font& rFont );
+ sal_Int32 getSystemFont( const Font& i_rFont );
+
+ // used for edit and listbox
+ Font drawFieldBorder( PDFWidget&, const PDFWriter::AnyWidget&, const StyleSettings& );
+
+ void createDefaultPushButtonAppearance( PDFWidget&, const PDFWriter::PushButtonWidget& rWidget );
+ void createDefaultCheckBoxAppearance( PDFWidget&, const PDFWriter::CheckBoxWidget& rWidget );
+ void createDefaultRadioButtonAppearance( PDFWidget&, const PDFWriter::RadioButtonWidget& rWidget );
+ void createDefaultEditAppearance( PDFWidget&, const PDFWriter::EditWidget& rWidget );
+ void createDefaultListBoxAppearance( PDFWidget&, const PDFWriter::ListBoxWidget& rWidget );
+
+ /* ensure proper escapement and uniqueness of field names */
+ void createWidgetFieldName( sal_Int32 i_nWidgetsIndex, const PDFWriter::AnyWidget& i_rInWidget );
+ /// See vcl::PDFObjectContainer::createObject().
+ sal_Int32 createObject() override;
+ /// See vcl::PDFObjectContainer::updateObject().
+ bool updateObject( sal_Int32 n ) override;
+
+ /// See vcl::PDFObjectContainer::writeBuffer().
+ bool writeBuffer( const void* pBuffer, sal_uInt64 nBytes ) override;
+ void beginCompression();
+ void endCompression();
+ void beginRedirect( SvStream* pStream, const tools::Rectangle& );
+ SvStream* endRedirect();
+
+ void endPage();
+
+ void beginStructureElementMCSeq();
+ void endStructureElementMCSeq();
+ /** checks whether a non struct element lies in the ancestor hierarchy
+ of the current structure element
+
+ @returns
+ true if no NonStructElement was found in ancestor path and tagged
+ PDF output is enabled
+ false else
+ */
+ bool checkEmitStructure();
+
+ /* draws an emphasis mark */
+ void drawEmphasisMark( tools::Long nX, tools::Long nY, const tools::PolyPolygon& rPolyPoly, bool bPolyLine, const tools::Rectangle& rRect1, const tools::Rectangle& rRect2 );
+
+ /* true if PDF/A-1a or PDF/A-1b is output */
+ bool m_bIsPDF_A1;
+ /* true if PDF/A-2a is output */
+ bool m_bIsPDF_A2;
+
+ /* PDF/UA support enabled */
+ bool m_bIsPDF_UA;
+
+ bool m_bIsPDF_A3;
+
+ PDFWriter& m_rOuterFace;
+
+ /*
+ i12626
+ methods for PDF security
+
+ pad a password according algorithm 3.2, step 1 */
+ static void padPassword( std::u16string_view i_rPassword, sal_uInt8* o_pPaddedPW );
+ /* algorithm 3.2: compute an encryption key */
+ static bool computeEncryptionKey( EncHashTransporter*,
+ vcl::PDFWriter::PDFEncryptionProperties& io_rProperties,
+ sal_Int32 i_nAccessPermissions
+ );
+ /* algorithm 3.3: computing the encryption dictionary'ss owner password value ( /O ) */
+ static bool computeODictionaryValue( const sal_uInt8* i_pPaddedOwnerPassword, const sal_uInt8* i_pPaddedUserPassword,
+ std::vector< sal_uInt8 >& io_rOValue,
+ sal_Int32 i_nKeyLength
+ );
+ /* algorithm 3.4 or 3.5: computing the encryption dictionary's user password value ( /U ) revision 2 or 3 of the standard security handler */
+ static bool computeUDictionaryValue( EncHashTransporter* i_pTransporter,
+ vcl::PDFWriter::PDFEncryptionProperties& io_rProperties,
+ sal_Int32 i_nKeyLength,
+ sal_Int32 i_nAccessPermissions
+ );
+
+ static void computeDocumentIdentifier( std::vector< sal_uInt8 >& o_rIdentifier,
+ const vcl::PDFWriter::PDFDocInfo& i_rDocInfo,
+ const OString& i_rCString1,
+ OString& o_rCString2
+ );
+ static sal_Int32 computeAccessPermissions( const vcl::PDFWriter::PDFEncryptionProperties& i_rProperties,
+ sal_Int32& o_rKeyLength, sal_Int32& o_rRC4KeyLength );
+ void setupDocInfo();
+ bool prepareEncryption( const css::uno::Reference< css::beans::XMaterialHolder >& );
+
+ // helper for playMetafile
+ void implWriteGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient,
+ VirtualDevice* pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& );
+ void implWriteBitmapEx( const Point& rPoint, const Size& rSize, const BitmapEx& rBitmapEx, const Graphic& i_pGraphic,
+ VirtualDevice const * pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& );
+
+ // helpers for CCITT 1bit bitmap stream
+ void putG4Bits( sal_uInt32 i_nLength, sal_uInt32 i_nCode, BitStreamState& io_rState );
+ void putG4Span( tools::Long i_nSpan, bool i_bWhitePixel, BitStreamState& io_rState );
+ void writeG4Stream( BitmapReadAccess const * i_pBitmap );
+
+ // color helper functions
+ void appendStrokingColor( const Color& rColor, OStringBuffer& rBuffer );
+ void appendNonStrokingColor( const Color& rColor, OStringBuffer& rBuffer );
+public:
+ PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, const css::uno::Reference< css::beans::XMaterialHolder >&, PDFWriter& );
+ ~PDFWriterImpl() override;
+ void dispose() override;
+
+ static css::uno::Reference< css::beans::XMaterialHolder >
+ initEncryption( const OUString& i_rOwnerPassword,
+ const OUString& i_rUserPassword );
+
+ /* document structure */
+ void newPage( double nPageWidth , double nPageHeight, PDFWriter::Orientation eOrientation );
+ bool emit();
+ const std::set< PDFWriter::ErrorCode > & getErrors() const { return m_aErrors;}
+ void insertError( PDFWriter::ErrorCode eErr ) { m_aErrors.insert( eErr ); }
+ void playMetafile( const GDIMetaFile&, vcl::PDFExtOutDevData*, const vcl::PDFWriter::PlayMetafileContext&, VirtualDevice* pDummyDev = nullptr );
+
+ Size getCurPageSize() const
+ {
+ Size aSize;
+ if( m_nCurrentPage >= 0 && o3tl::make_unsigned(m_nCurrentPage) < m_aPages.size() )
+ aSize = Size( m_aPages[ m_nCurrentPage ].m_nPageWidth, m_aPages[ m_nCurrentPage ].m_nPageHeight );
+ return aSize;
+ }
+
+ void setDocumentLocale( const css::lang::Locale& rLoc )
+ { m_aContext.DocumentLocale = rLoc; }
+
+ /* graphics state */
+ void push( PushFlags nFlags );
+ void pop();
+
+ void setFont( const Font& rFont );
+
+ void setMapMode( const MapMode& rMapMode );
+
+ const MapMode& getMapMode() { return m_aGraphicsStack.front().m_aMapMode; }
+
+ void setLineColor( const Color& rColor )
+ {
+ m_aGraphicsStack.front().m_aLineColor = rColor.IsTransparent() ? COL_TRANSPARENT : rColor;
+ m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::LineColor;
+ }
+
+ void setFillColor( const Color& rColor )
+ {
+ m_aGraphicsStack.front().m_aFillColor = rColor.IsTransparent() ? COL_TRANSPARENT : rColor;
+ m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::FillColor;
+ }
+
+ void setTextLineColor()
+ {
+ m_aGraphicsStack.front().m_aTextLineColor = COL_TRANSPARENT;
+ }
+
+ void setTextLineColor( const Color& rColor )
+ {
+ m_aGraphicsStack.front().m_aTextLineColor = rColor;
+ }
+
+ void setOverlineColor()
+ {
+ m_aGraphicsStack.front().m_aOverlineColor = COL_TRANSPARENT;
+ }
+
+ void setOverlineColor( const Color& rColor )
+ {
+ m_aGraphicsStack.front().m_aOverlineColor = rColor;
+ }
+
+ void setTextFillColor( const Color& rColor )
+ {
+ m_aGraphicsStack.front().m_aFont.SetFillColor( rColor );
+ m_aGraphicsStack.front().m_aFont.SetTransparent( rColor.IsTransparent() );
+ m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::Font;
+ }
+ void setTextFillColor()
+ {
+ m_aGraphicsStack.front().m_aFont.SetFillColor( COL_TRANSPARENT );
+ m_aGraphicsStack.front().m_aFont.SetTransparent( true );
+ m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::Font;
+ }
+ void setTextColor( const Color& rColor )
+ {
+ m_aGraphicsStack.front().m_aFont.SetColor( rColor );
+ m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::Font;
+ }
+
+ void clearClipRegion()
+ {
+ m_aGraphicsStack.front().m_aClipRegion.clear();
+ m_aGraphicsStack.front().m_bClipRegion = false;
+ m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::ClipRegion;
+ }
+
+ void setClipRegion( const basegfx::B2DPolyPolygon& rRegion );
+
+ void moveClipRegion( sal_Int32 nX, sal_Int32 nY );
+
+ void intersectClipRegion( const tools::Rectangle& rRect );
+
+ void intersectClipRegion( const basegfx::B2DPolyPolygon& rRegion );
+
+ void setLayoutMode( vcl::text::ComplexTextLayoutFlags nLayoutMode )
+ {
+ m_aGraphicsStack.front().m_nLayoutMode = nLayoutMode;
+ m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::LayoutMode;
+ }
+
+ void setDigitLanguage( LanguageType eLang )
+ {
+ m_aGraphicsStack.front().m_aDigitLanguage = eLang;
+ m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::DigitLanguage;
+ }
+
+ void setTextAlign( TextAlign eAlign )
+ {
+ m_aGraphicsStack.front().m_aFont.SetAlignment( eAlign );
+ m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsStateUpdateFlags::Font;
+ }
+
+ /* actual drawing functions */
+ void drawText( const Point& rPos, const OUString& rText, sal_Int32 nIndex, sal_Int32 nLen, bool bTextLines = true );
+ void drawTextArray( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, sal_Int32 nIndex, sal_Int32 nLen );
+ void drawStretchText( const Point& rPos, sal_uLong nWidth, const OUString& rText,
+ sal_Int32 nIndex, sal_Int32 nLen );
+ void drawText( const tools::Rectangle& rRect, const OUString& rOrigStr, DrawTextFlags nStyle );
+ void drawTextLine( const Point& rPos, tools::Long nWidth, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline, bool bUnderlineAbove );
+ void drawWaveTextLine( OStringBuffer& aLine, tools::Long nWidth, FontLineStyle eTextLine, Color aColor, bool bIsAbove );
+ void drawStraightTextLine( OStringBuffer& aLine, tools::Long nWidth, FontLineStyle eTextLine, Color aColor, bool bIsAbove );
+ void drawStrikeoutLine( OStringBuffer& aLine, tools::Long nWidth, FontStrikeout eStrikeout, Color aColor );
+ void drawStrikeoutChar( const Point& rPos, tools::Long nWidth, FontStrikeout eStrikeout );
+
+ void drawLine( const Point& rStart, const Point& rStop );
+ void drawLine( const Point& rStart, const Point& rStop, const LineInfo& rInfo );
+ void drawPolygon( const tools::Polygon& rPoly );
+ void drawPolyPolygon( const tools::PolyPolygon& rPolyPoly );
+ void drawPolyLine( const tools::Polygon& rPoly );
+ void drawPolyLine( const tools::Polygon& rPoly, const LineInfo& rInfo );
+ void drawPolyLine( const tools::Polygon& rPoly, const PDFWriter::ExtLineInfo& rInfo );
+
+ void drawPixel( const Point& rPt, const Color& rColor );
+
+ void drawRectangle( const tools::Rectangle& rRect );
+ void drawRectangle( const tools::Rectangle& rRect, sal_uInt32 nHorzRound, sal_uInt32 nVertRound );
+ void drawEllipse( const tools::Rectangle& rRect );
+ void drawArc( const tools::Rectangle& rRect, const Point& rStart, const Point& rStop, bool bWithPie, bool bWidthChord );
+
+ void drawBitmap( const Point& rDestPoint, const Size& rDestSize, const Bitmap& rBitmap, const Graphic& rGraphic );
+ void drawBitmap( const Point& rDestPoint, const Size& rDestSize, const BitmapEx& rBitmap );
+ void drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const Size& rSizePixel, const tools::Rectangle& rTargetArea, const AlphaMask& rAlphaMask, const Graphic& rGraphic );
+ /// Stores the original PDF data from rGraphic as an embedded file.
+ void createEmbeddedFile(const Graphic& rGraphic, ReferenceXObjectEmit& rEmit, sal_Int32 nBitmapObject);
+
+ void drawGradient( const tools::Rectangle& rRect, const Gradient& rGradient );
+ void drawHatch( const tools::PolyPolygon& rPolyPoly, const Hatch& rHatch );
+ void drawWallpaper( const tools::Rectangle& rRect, const Wallpaper& rWall );
+ void drawTransparent( const tools::PolyPolygon& rPolyPoly, sal_uInt32 nTransparentPercent );
+ void beginTransparencyGroup();
+ void endTransparencyGroup( const tools::Rectangle& rBoundingBox, sal_uInt32 nTransparentPercent );
+
+ void emitComment( const char* pComment );
+
+ //--->i56629 named destinations
+ sal_Int32 createNamedDest( const OUString& sDestName, const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType );
+
+ //--->i59651
+ //emits output intent
+ sal_Int32 emitOutputIntent();
+
+ //emits the document metadata
+ sal_Int32 emitDocumentMetadata();
+
+ // links
+ sal_Int32 createLink(const tools::Rectangle& rRect, sal_Int32 nPageNr, OUString const& rAltText);
+ sal_Int32 createDest( const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType );
+ sal_Int32 registerDestReference( sal_Int32 nDestId, const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType );
+ void setLinkDest( sal_Int32 nLinkId, sal_Int32 nDestId );
+ void setLinkURL( sal_Int32 nLinkId, const OUString& rURL );
+ void setLinkPropertyId( sal_Int32 nLinkId, sal_Int32 nPropertyId );
+
+ // screens
+ sal_Int32 createScreen(const tools::Rectangle& rRect, sal_Int32 nPageNr);
+ void setScreenURL(sal_Int32 nScreenId, const OUString& rURL);
+ void setScreenStream(sal_Int32 nScreenId, const OUString& rURL);
+
+ // outline
+ sal_Int32 createOutlineItem( sal_Int32 nParent, std::u16string_view rText, sal_Int32 nDestID );
+ void setOutlineItemParent( sal_Int32 nItem, sal_Int32 nNewParent );
+ void setOutlineItemText( sal_Int32 nItem, std::u16string_view rText );
+ void setOutlineItemDest( sal_Int32 nItem, sal_Int32 nDestID );
+
+ // notes
+ void createNote( const tools::Rectangle& rRect, const PDFNote& rNote, sal_Int32 nPageNr );
+ // structure elements
+ sal_Int32 beginStructureElement( PDFWriter::StructElement eType, const OUString& rAlias );
+ void endStructureElement();
+ bool setCurrentStructureElement( sal_Int32 nElement );
+ bool setStructureAttribute( enum PDFWriter::StructAttribute eAttr, enum PDFWriter::StructAttributeValue eVal );
+ bool setStructureAttributeNumerical( enum PDFWriter::StructAttribute eAttr, sal_Int32 nValue );
+ void setStructureBoundingBox( const tools::Rectangle& rRect );
+ void setActualText( const OUString& rText );
+ void setAlternateText( const OUString& rText );
+
+ // transitional effects
+ void setPageTransition( PDFWriter::PageTransition eType, sal_uInt32 nMilliSec, sal_Int32 nPageNr );
+
+ // controls
+ sal_Int32 createControl( const PDFWriter::AnyWidget& rControl, sal_Int32 nPageNr = -1 );
+
+ // additional streams
+ void addStream( const OUString& rMimeType, PDFOutputStream* pStream );
+
+ // helper: eventually begin marked content sequence and
+ // emit a comment in debug case
+ void MARK( const char* pString );
+};
+
+} // namespace vcl
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */