1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <pdf/pdfcompat.hxx>
12 #include <o3tl/string_view.hxx>
13 #include <tools/solar.h>
14 #include <vcl/filter/PDFiumLibrary.hxx>
15 #include <sal/log.hxx>
19 /// Decide if PDF data is old enough to be compatible.
20 bool isCompatible(SvStream
& rInStream
, sal_uInt64 nPos
, sal_uInt64 nSize
)
26 sal_uInt8 aFirstBytes
[8];
28 sal_uLong nRead
= rInStream
.ReadBytes(aFirstBytes
, 8);
32 if (aFirstBytes
[0] != '%' || aFirstBytes
[1] != 'P' || aFirstBytes
[2] != 'D'
33 || aFirstBytes
[3] != 'F' || aFirstBytes
[4] != '-')
36 sal_Int32 nMajor
= o3tl::toInt32(std::string_view(reinterpret_cast<char*>(&aFirstBytes
[5]), 1));
37 sal_Int32 nMinor
= o3tl::toInt32(std::string_view(reinterpret_cast<char*>(&aFirstBytes
[7]), 1));
38 return !(nMajor
> 1 || (nMajor
== 1 && nMinor
> 6));
41 /// Converts to highest supported format version (1.6).
42 /// Usually used to deal with missing referenced objects in source
44 bool convertToHighestSupported(SvStream
& rInStream
, SvStream
& rOutStream
)
46 sal_uInt64 nPos
= STREAM_SEEK_TO_BEGIN
;
47 sal_uInt64 nSize
= STREAM_SEEK_TO_END
;
49 // Convert to PDF-1.6.
50 auto pPdfium
= vcl::pdf::PDFiumLibrary::get();
54 // Read input into a buffer.
55 SvMemoryStream aInBuffer
;
56 aInBuffer
.WriteStream(rInStream
, nSize
);
58 SvMemoryStream aSaved
;
60 // Load the buffer using pdfium.
61 std::unique_ptr
<vcl::pdf::PDFiumDocument
> pPdfDocument
62 = pPdfium
->openDocument(aInBuffer
.GetData(), aInBuffer
.GetSize(), OString());
67 if (!pPdfDocument
->saveWithVersion(aSaved
, 16))
71 aSaved
.Seek(STREAM_SEEK_TO_BEGIN
);
72 rOutStream
.WriteStream(aSaved
);
74 return rOutStream
.good();
77 /// Takes care of transparently downgrading the version of the PDF stream in
78 /// case it's too new for our PDF export.
79 bool getCompatibleStream(SvStream
& rInStream
, SvStream
& rOutStream
)
81 sal_uInt64 nPos
= STREAM_SEEK_TO_BEGIN
;
82 sal_uInt64 nSize
= STREAM_SEEK_TO_END
;
83 bool bCompatible
= isCompatible(rInStream
, nPos
, nSize
);
87 rOutStream
.WriteStream(rInStream
, nSize
);
89 convertToHighestSupported(rInStream
, rOutStream
);
91 return rOutStream
.good();
94 BinaryDataContainer
createBinaryDataContainer(SvStream
& rStream
)
96 // Save the original PDF stream for later use.
97 SvMemoryStream aMemoryStream
;
98 if (!getCompatibleStream(rStream
, aMemoryStream
))
101 const sal_uInt64 nStreamLength
= aMemoryStream
.TellEnd();
103 aMemoryStream
.Seek(STREAM_SEEK_TO_BEGIN
);
104 BinaryDataContainer
aPdfData(aMemoryStream
, nStreamLength
);
105 if (aMemoryStream
.GetError())
111 } // end vcl::filter::ipdf namespace
113 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */