summaryrefslogtreecommitdiff
path: root/vcl/source
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2024-11-05 12:40:40 +0100
committerLászló Németh <nemeth@numbertext.org>2024-11-06 17:46:59 +0100
commit3056c75db5b2a8a945621349fea9ee1183872989 (patch)
tree55fa447665353f3f520791d317a5dc6a8871dc7e /vcl/source
parent315180b2a3977aadb0de3ff6d20774e87eaf9ffd (diff)
tdf#95239 sw: fix wrong order of PDF ToC, if headings put in text frames
PDF outlines (called also as PDF bookmarks or ToC) contained headings in the wrong order if they were placed in a text frame: Heading 2 (frame) ... 2 Heading 3 (frame) ... 2 Heading 1 ........... 1 Now PDF export didn't list text frame headings only at the start of the ToC, but in their correct position and hierarchy, based on the page and vertical position of the headings: Heading 1 ................ 1 Heading 2 (frame) ...... 2 Heading 3 (frame) ... 2 This is useful for the recently implemented inline headings, where e.g. APA Style Heading 4 and Heading 5 are there in text frames anchored as characters, see tdf#48459. Extend PDFium test environment for bookmarks, and add tdf#131728 DOCX and an APA Style .fodt unit tests. Note: if the higher headings are only in text frames, but not the lower ones, only the order corrected, but not the full hierarchy, yet. This is a follow-up to commit d87cf67f8f3346a1e380383917a3a4552fd9248e "tdf#131728 sw inline heading: fix missing/broken DOCX export", commit a1dcbd1d1ce6071d48bb5df26d7839aeb21b75a8 "tdf#48459 sw inline heading: add Inline Heading frame style" and commit 49765a9e7be41d4908729ff7d838755276b244cb "tdf#48459 tdf#131728 sw inline heading: new frame style: fix DOCX export". Change-Id: I87dffb9244d8aea553c98bf16c70955bb9b732d3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176050 Reviewed-by: László Németh <nemeth@numbertext.org> Tested-by: Jenkins
Diffstat (limited to 'vcl/source')
-rw-r--r--vcl/source/pdf/PDFiumLibrary.cxx52
1 files changed, 52 insertions, 0 deletions
diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx
index dd7abd5defd5..f48d02595453 100644
--- a/vcl/source/pdf/PDFiumLibrary.cxx
+++ b/vcl/source/pdf/PDFiumLibrary.cxx
@@ -26,6 +26,7 @@
#include <tools/stream.hxx>
#include <tools/UnitConversion.hxx>
#include <o3tl/string_view.hxx>
+#include <rtl/ustrbuf.hxx>
#include <vcl/BitmapWriteAccess.hxx>
#include <vcl/bitmapex.hxx>
@@ -484,6 +485,7 @@ public:
std::unique_ptr<PDFiumPage> openPage(int nIndex) override;
std::unique_ptr<PDFiumSignature> getSignature(int nIndex) override;
std::vector<unsigned int> getTrailerEnds() override;
+ OUString getBookmarks() override;
};
class PDFiumImpl : public PDFium
@@ -746,6 +748,56 @@ std::vector<unsigned int> PDFiumDocumentImpl::getTrailerEnds()
return aTrailerEnds;
}
+static void lcl_getBookmarks(int nLevel, OUStringBuffer& rBuf, FPDF_DOCUMENT pDoc,
+ FPDF_BOOKMARK pBookmark)
+{
+ // no first child or too much levels
+ if (!pBookmark || nLevel > 10)
+ return;
+
+ OUString aString;
+ int nBytes = FPDFBookmark_GetTitle(pBookmark, nullptr, 0);
+ assert(nBytes % 2 == 0);
+ nBytes /= 2;
+
+ std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nBytes]);
+
+ int nActualBytes = FPDFBookmark_GetTitle(pBookmark, pText.get(), nBytes * 2);
+ assert(nActualBytes % 2 == 0);
+ nActualBytes /= 2;
+ if (nActualBytes > 1)
+ {
+#if defined OSL_BIGENDIAN
+ // The data returned by FPDFTextObj_GetText is documented to always be UTF-16LE:
+ for (int i = 0; i != nActualBytes; ++i)
+ {
+ pText[i] = OSL_SWAPWORD(pText[i]);
+ }
+#endif
+ // insert nLevel spaces before the title
+ rBuf.append(OUString(" ").subView(0, nLevel));
+ aString = OUString(pText.get());
+ }
+
+ rBuf.append(aString);
+ rBuf.append("\n");
+
+ // get children
+ lcl_getBookmarks(nLevel + 1, rBuf, pDoc, FPDFBookmark_GetFirstChild(pDoc, pBookmark));
+
+ // get siblings
+ while (nullptr != (pBookmark = FPDFBookmark_GetNextSibling(pDoc, pBookmark)))
+ lcl_getBookmarks(nLevel, rBuf, pDoc, pBookmark);
+}
+
+OUString PDFiumDocumentImpl::getBookmarks()
+{
+ OUStringBuffer aBuf;
+ FPDF_BOOKMARK pBookmark = FPDFBookmark_GetFirstChild(mpPdfDocument, nullptr);
+ lcl_getBookmarks(0, aBuf, mpPdfDocument, pBookmark);
+ return aBuf.makeStringAndClear();
+}
+
basegfx::B2DSize PDFiumDocumentImpl::getPageSize(int nIndex)
{
basegfx::B2DSize aSize;