LibreOffice Module vcl (master) 1
pdfcompat.cxx
Go to the documentation of this file.
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
10#include <pdf/pdfcompat.hxx>
11
12#include <o3tl/string_view.hxx>
14#include <sal/log.hxx>
15
16namespace vcl::pdf
17{
19bool isCompatible(SvStream& rInStream, sal_uInt64 nPos, sal_uInt64 nSize)
20{
21 if (nSize < 8)
22 return false;
23
24 // %PDF-x.y
25 sal_uInt8 aFirstBytes[8];
26 rInStream.Seek(nPos);
27 sal_uLong nRead = rInStream.ReadBytes(aFirstBytes, 8);
28 if (nRead < 8)
29 return false;
30
31 if (aFirstBytes[0] != '%' || aFirstBytes[1] != 'P' || aFirstBytes[2] != 'D'
32 || aFirstBytes[3] != 'F' || aFirstBytes[4] != '-')
33 return false;
34
35 sal_Int32 nMajor = o3tl::toInt32(std::string_view(reinterpret_cast<char*>(&aFirstBytes[5]), 1));
36 sal_Int32 nMinor = o3tl::toInt32(std::string_view(reinterpret_cast<char*>(&aFirstBytes[7]), 1));
37 return !(nMajor > 1 || (nMajor == 1 && nMinor > 6));
38}
39
43bool convertToHighestSupported(SvStream& rInStream, SvStream& rOutStream)
44{
45 sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN;
46 sal_uInt64 nSize = STREAM_SEEK_TO_END;
47 rInStream.Seek(nPos);
48 // Convert to PDF-1.6.
49 auto pPdfium = vcl::pdf::PDFiumLibrary::get();
50 if (!pPdfium)
51 return false;
52
53 // Read input into a buffer.
54 SvMemoryStream aInBuffer;
55 aInBuffer.WriteStream(rInStream, nSize);
56
57 SvMemoryStream aSaved;
58 {
59 // Load the buffer using pdfium.
60 std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
61 = pPdfium->openDocument(aInBuffer.GetData(), aInBuffer.GetSize(), OString());
62 if (!pPdfDocument)
63 return false;
64
65 // 16 means PDF-1.6.
66 if (!pPdfDocument->saveWithVersion(aSaved, 16))
67 return false;
68 }
69
71 rOutStream.WriteStream(aSaved);
72
73 return rOutStream.good();
74}
75
78bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream)
79{
80 sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN;
81 sal_uInt64 nSize = STREAM_SEEK_TO_END;
82 bool bCompatible = isCompatible(rInStream, nPos, nSize);
83 rInStream.Seek(nPos);
84 if (bCompatible)
85 // Not converting.
86 rOutStream.WriteStream(rInStream, nSize);
87 else
88 convertToHighestSupported(rInStream, rOutStream);
89
90 return rOutStream.good();
91}
92
94{
95 // Save the original PDF stream for later use.
96 SvMemoryStream aMemoryStream;
97 if (!getCompatibleStream(rStream, aMemoryStream))
98 return {};
99
100 const sal_uInt32 nStreamLength = aMemoryStream.TellEnd();
101
102 auto aPdfData = std::make_unique<std::vector<sal_uInt8>>(nStreamLength);
103
104 aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
105 aMemoryStream.ReadBytes(aPdfData->data(), aPdfData->size());
106 if (aMemoryStream.GetError())
107 return {};
108
109 return { std::move(aPdfData) };
110}
111
112} // end vcl::filter::ipdf namespace
113
114/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Container for the binary data, whose responsibility is to manage the make it as simple as possible to...
const void * GetData()
sal_uInt64 GetSize()
virtual sal_uInt64 TellEnd() override
bool good() const
sal_uInt64 Seek(sal_uInt64 nPos)
std::size_t ReadBytes(void *pData, std::size_t nSize)
ErrCode GetError() const
SvStream & WriteStream(SvStream &rStream)
sal_uInt16 nPos
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
bool convertToHighestSupported(SvStream &rInStream, SvStream &rOutStream)
Converts to highest supported format version (1.6).
Definition: pdfcompat.cxx:43
BinaryDataContainer createBinaryDataContainer(SvStream &rStream)
Definition: pdfcompat.cxx:93
bool isCompatible(SvStream &rInStream, sal_uInt64 nPos, sal_uInt64 nSize)
Decide if PDF data is old enough to be compatible.
Definition: pdfcompat.cxx:19
bool getCompatibleStream(SvStream &rInStream, SvStream &rOutStream)
Takes care of transparently downgrading the version of the PDF stream in case it's too new for our PD...
Definition: pdfcompat.cxx:78
sal_uIntPtr sal_uLong
#define STREAM_SEEK_TO_END
#define STREAM_SEEK_TO_BEGIN
static std::shared_ptr< PDFium > & get()
unsigned char sal_uInt8