From fdc5fbac9fba18e7412af5fd20fd345e6b41d919 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Mon, 15 May 2023 17:55:18 -0400 Subject: [PATCH] Fix font engine not available on sub-page processing The font engine was only initialised in the primary page and not available in sub pages. This is fixed by making it a static var. Also fixed the upsidedown text problem in patterns which is caused by the text's own internal matrix being unaware of the initial state. Primary pages are flipped in their state, while sub-pages are not. Fixes https://gitlab.com/inkscape/inkscape/-/issues/3886 --- .../internal/pdfinput/pdf-parser.cpp | 29 +++++++++---------- src/extension/internal/pdfinput/pdf-parser.h | 1 - .../internal/pdfinput/svg-builder.cpp | 8 ++--- src/extension/internal/pdfinput/svg-builder.h | 4 +-- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index 4d606049b6..a923d4aec8 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -267,7 +267,7 @@ PdfParser::PdfParser(std::shared_ptr pdf_doc, Inkscape::Extension::Inter : _pdf_doc(pdf_doc) , xref(pdf_doc->getXRef()) , builder(builderA) - , subPage(gFalse) + , subPage(false) , printCommands(false) , res(new GfxResources(xref, page->getResourceDict(), nullptr)) , // start the resource stack @@ -312,25 +312,17 @@ PdfParser::PdfParser(std::shared_ptr pdf_doc, Inkscape::Extension::Inter formDepth = 0; pushOperator("startPage"); - - // poppler/CairoOutputDev.cc claims the FT Library needs to be kept around - // for a while. It's unclear if this is sure for our case. - static FT_Library ft_lib; - static std::once_flag ft_lib_once_flag; - std::call_once(ft_lib_once_flag, FT_Init_FreeType, &ft_lib); - - _font_engine = std::make_shared(ft_lib); } PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *builderA, Dict *resDict, _POPPLER_CONST PDFRectangle *box) : xref(xrefA) , builder(builderA) - , subPage(gTrue) + , subPage(true) , printCommands(false) , res(new GfxResources(xref, resDict, nullptr)) , // start the resource stack - state(new GfxState(72, 72, box, 0, gFalse)) + state(new GfxState(72, 72, box, 0, false)) , fontChanged(gFalse) , clip(clipNone) , ignoreUndef(0) @@ -2083,7 +2075,7 @@ void PdfParser::opSetWordSpacing(Object args[], int /*numArgs*/) void PdfParser::opSetHorizScaling(Object args[], int /*numArgs*/) { state->setHorizScaling(args[0].getNum()); - builder->updateTextMatrix(state); + builder->updateTextMatrix(state, !subPage); fontChanged = gTrue; } @@ -2122,7 +2114,7 @@ void PdfParser::opSetTextMatrix(Object args[], int /*numArgs*/) args[2].getNum(), args[3].getNum(), args[4].getNum(), args[5].getNum()); state->textMoveTo(0, 0); - builder->updateTextMatrix(state); + builder->updateTextMatrix(state, !subPage); builder->updateTextPosition(0.0, 0.0); fontChanged = gTrue; } @@ -2144,8 +2136,15 @@ void PdfParser::opTextNextLine(Object /*args*/[], int /*numArgs*/) void PdfParser::doUpdateFont() { if (fontChanged) { - auto font = _font_engine->getFont(state->getFont(), _pdf_doc.get(), true, xref); - builder->updateFont(state, font); + // poppler/CairoOutputDev.cc claims the FT Library needs to be kept around + // for a while. It's unclear if this is sure for our case. + static FT_Library ft_lib; + static std::once_flag ft_lib_once_flag; + std::call_once(ft_lib_once_flag, FT_Init_FreeType, &ft_lib); + static auto font_engine = std::make_shared(ft_lib); + + auto font = font_engine->getFont(state->getFont(), _pdf_doc.get(), true, xref); + builder->updateFont(state, font, !subPage); fontChanged = false; } } diff --git a/src/extension/internal/pdfinput/pdf-parser.h b/src/extension/internal/pdfinput/pdf-parser.h index d4324d5831..12d5318e65 100644 --- a/src/extension/internal/pdfinput/pdf-parser.h +++ b/src/extension/internal/pdfinput/pdf-parser.h @@ -155,7 +155,6 @@ public: private: std::shared_ptr _pdf_doc; - std::shared_ptr _font_engine; XRef *xref; // the xref table for this PDF file SvgBuilder *builder; // SVG generator GBool subPage; // is this a sub-page object? diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp index e3e12372ee..7c43bec86d 100644 --- a/src/extension/internal/pdfinput/svg-builder.cpp +++ b/src/extension/internal/pdfinput/svg-builder.cpp @@ -1163,10 +1163,10 @@ void SvgBuilder::updateStyle(GfxState *state) { /** * \brief Updates _font_style according to the font set in parameter state */ -void SvgBuilder::updateFont(GfxState *state, std::shared_ptr cairo_font) +void SvgBuilder::updateFont(GfxState *state, std::shared_ptr cairo_font, bool flip) { TRACE(("updateFont()\n")); - updateTextMatrix(state); // Ensure that we have a text matrix built + updateTextMatrix(state, flip); // Ensure that we have a text matrix built auto font = state->getFont(); auto font_id = font->getID()->num; @@ -1252,9 +1252,9 @@ void SvgBuilder::updateTextPosition(double tx, double ty) { /** * \brief Flushes the buffered characters */ -void SvgBuilder::updateTextMatrix(GfxState *state) { +void SvgBuilder::updateTextMatrix(GfxState *state, bool flip) { // Update text matrix, it contains an extra flip which we must undo. - auto new_matrix = Geom::Scale(1, -1) * ctmToAffine(state->getTextMat()); + auto new_matrix = Geom::Scale(1, flip ? -1 : 1) * ctmToAffine(state->getTextMat()); // TODO: Detect if the text matrix is actually just a rotational kern // this can help stich back together texts where letters are rotated if (new_matrix != _text_matrix) { diff --git a/src/extension/internal/pdfinput/svg-builder.h b/src/extension/internal/pdfinput/svg-builder.h index 15078f66d4..886bad09d0 100644 --- a/src/extension/internal/pdfinput/svg-builder.h +++ b/src/extension/internal/pdfinput/svg-builder.h @@ -155,10 +155,10 @@ public: void saveState(GfxState *state); void restoreState(GfxState *state); void updateStyle(GfxState *state); - void updateFont(GfxState *state, std::shared_ptr cairo_font); + void updateFont(GfxState *state, std::shared_ptr cairo_font, bool flip); void updateTextPosition(double tx, double ty); void updateTextShift(GfxState *state, double shift); - void updateTextMatrix(GfxState *state); + void updateTextMatrix(GfxState *state, bool flip); // Clipping void setClip(GfxState *state, GfxClipType clip); -- GitLab