From 996e976a9cc9ec2720d9653fe151e8dc44d353c1 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sun, 26 Nov 2017 20:43:15 +1030 Subject: [PATCH 3/8] cairo: copy pdf page labels if outputting to pdf Add setInteractive() to enable this and in future other pdf interactive features. Added -inter option to pdftocairo to enable interactive features. Bug #103912 --- poppler/CairoOutputDev.cc | 19 ++++++++++++++++++- poppler/CairoOutputDev.h | 2 ++ poppler/Catalog.cc | 4 +++- poppler/Catalog.h | 7 ++++++- utils/pdftocairo.1 | 5 +++++ utils/pdftocairo.cc | 9 +++++++++ 6 files changed, 43 insertions(+), 3 deletions(-) diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index afdd3a21..1fc184a7 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -46,6 +46,9 @@ #include #include #include +#if CAIRO_HAS_PDF_SURFACE +#include +#endif #include #include "goo/gfile.h" @@ -168,7 +171,8 @@ CairoOutputDev::CairoOutputDev() { text = NULL; actualText = NULL; - logicalStruct = false; + logicalStruct = gFalse; + interactive = gFalse; pdfPageNum = 0; cairoPageNum = 0; forwardLinkCount = 0; @@ -365,6 +369,19 @@ void CairoOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) { pdfPageNum = pageNum; cairoPageNum++; + if (interactive && isPDF()) { + GooString label; + if (doc->getCatalog()->indexToLabel(pageNum-1, &label, gTrue)) { + char *utf8 = TextStringToUtf8 (&label); + if (utf8) { +#if defined(CAIRO_HAS_PDF_SURFACE) && CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 8) + cairo_pdf_surface_set_page_label (cairo_get_target (cairo), utf8); +#endif + gfree (utf8); + } + } + } + if (logicalStruct && isPDF()) { if (annotations) delete annotations; diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h index 01ba43b8..4c33202a 100644 --- a/poppler/CairoOutputDev.h +++ b/poppler/CairoOutputDev.h @@ -279,6 +279,7 @@ public: void setPrinting (GBool printing) { this->printing = printing; needFontUpdate = gTrue; } void setAntialias(cairo_antialias_t antialias); void setLogicalStructure(GBool logStruct) { this->logicalStruct = logStruct; } + void setInteractive(GBool inter) { this->interactive = inter; } void setInType3Char(GBool inType3Char) { this->inType3Char = inType3Char; } void getType3GlyphWidth (double *wx, double *wy) { *wx = t3_glyph_wx; *wy = t3_glyph_wy; } @@ -366,6 +367,7 @@ protected: cairo_antialias_t antialias; GBool prescaleImages; GBool logicalStruct; + GBool interactive; GBool firstPage; int pdfPageNum; // page number of the PDF file int cairoPageNum; // page number in cairo output diff --git a/poppler/Catalog.cc b/poppler/Catalog.cc index eebbbb42..56e4cbe8 100644 --- a/poppler/Catalog.cc +++ b/poppler/Catalog.cc @@ -736,7 +736,7 @@ GBool Catalog::labelToIndex(GooString *label, int *index) return gTrue; } -GBool Catalog::indexToLabel(int index, GooString *label) +GBool Catalog::indexToLabel(int index, GooString *label, GBool noFallback) { char buffer[32]; @@ -746,6 +746,8 @@ GBool Catalog::indexToLabel(int index, GooString *label) PageLabelInfo *pli = getPageLabelInfo(); if (pli != NULL) { return pli->indexToLabel(index, label); + } else if (noFallback) { + return gFalse; } else { snprintf(buffer, sizeof (buffer), "%d", index + 1); label->append(buffer); diff --git a/poppler/Catalog.h b/poppler/Catalog.h index a2dd7fde..a60c7c00 100644 --- a/poppler/Catalog.h +++ b/poppler/Catalog.h @@ -184,7 +184,12 @@ public: // Convert between page indices and page labels. GBool labelToIndex(GooString *label, int *index); - GBool indexToLabel(int index, GooString *label); + + // Get page label for specified page. If noFallback is false, always + // returns a page label (unless page num invalid), creating one from + // the page number if necessary. + GBool indexToLabel(int index, GooString *label, GBool noFallback = gFalse); + GBool hasLabel(int index); Object *getOutline(); diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1 index 356111c8..158a21e5 100644 --- a/utils/pdftocairo.1 +++ b/utils/pdftocairo.1 @@ -215,6 +215,11 @@ shading patterns and masked images. This is the default setting. If the input file contains structural information about the document's content, write this information to the output file (PDF only). .TP +.B \-inter +If the input file contains interactive features, where supported by cairo, +write this information to the output file (PDF only). Currently supported +features: page labels. +.TP .B \-origpagesizes This option is the same as "\-paper match". .TP diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc index 9f1c3ca4..9c452421 100644 --- a/utils/pdftocairo.cc +++ b/utils/pdftocairo.cc @@ -123,6 +123,7 @@ static GBool noCenter = gFalse; static GBool duplex = gFalse; static char tiffCompressionStr[16] = ""; static GBool docStruct = gFalse; +static GBool docInteractive = gFalse; static char ownerPassword[33] = ""; static char userPassword[33] = ""; @@ -260,6 +261,8 @@ static const ArgDesc argDesc[] = { #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 8) {"-struct", argFlag, &docStruct, 0, "enable logical document structure (PDF)"}, + {"-inter", argFlag, &docInteractive, 0, + "enable interactive features (PDF)"}, #endif {"-opw", argString, ownerPassword, sizeof(ownerPassword), @@ -1075,6 +1078,11 @@ int main(int argc, char *argv[]) { exit(99); } + if (docInteractive && !pdf) { + fprintf(stderr, "Error: -inter may only be used with pdf output.\n"); + exit(99); + } + if (eps && (origPageSizes || paperSize[0] || paperWidth > 0 || paperHeight > 0)) { fprintf(stderr, "Error: page size options may not be used with eps output.\n"); exit(99); @@ -1226,6 +1234,7 @@ int main(int argc, char *argv[]) { cairoOut = new CairoOutputDev(); cairoOut->setLogicalStructure(docStruct); + cairoOut->setInteractive(docInteractive); cairoOut->startDoc(doc); if (sz != 0) crop_w = crop_h = sz; -- 2.11.0