From 8daa854ffebab5d56c554730c5f98bc72b7015c9 Mon Sep 17 00:00:00 2001 From: Matteo Bernardini Date: Sun, 4 Apr 2021 11:53:28 +0200 Subject: office/scribus: Updated for version 1.5.6.1. Patched for the newer poppler Signed-off-by: Matteo Bernardini --- office/scribus/README | 3 +- office/scribus/poppler-21.4.0.patch | 4347 +++++++++++++++++++++++++++++++++++ office/scribus/scribus.SlackBuild | 14 +- office/scribus/scribus.info | 6 +- 4 files changed, 4360 insertions(+), 10 deletions(-) create mode 100644 office/scribus/poppler-21.4.0.patch (limited to 'office') diff --git a/office/scribus/README b/office/scribus/README index 2add995c89e2..8a9f355ec70d 100644 --- a/office/scribus/README +++ b/office/scribus/README @@ -2,4 +2,5 @@ Scribus is an open-source program that brings award-winning professional page layout to Linux/Unix, MacOS X and Windows desktops with a combination of "press-ready" output and new approaches to page layout. -podofo is an optional dependency used for embedded pdfs in AI files. +podofo, libpagemaker, libfreehand, libcdr, libzmf, libqxp and libmspub are +optional dependencies. diff --git a/office/scribus/poppler-21.4.0.patch b/office/scribus/poppler-21.4.0.patch new file mode 100644 index 000000000000..7eedbd73c98a --- /dev/null +++ b/office/scribus/poppler-21.4.0.patch @@ -0,0 +1,4347 @@ +diff -Naur scribus-1.5.6.1.orig/scribus/plugins/import/pdf/slaoutput.cpp scribus-1.5.6.1/scribus/plugins/import/pdf/slaoutput.cpp +--- scribus-1.5.6.1.orig/scribus/plugins/import/pdf/slaoutput.cpp 2020-11-14 23:37:11.000000000 +0100 ++++ scribus-1.5.6.1/scribus/plugins/import/pdf/slaoutput.cpp 2021-04-04 11:27:44.315404000 +0200 +@@ -2291,9 +2291,19 @@ + return gTrue; + } + +-GBool SlaOutputDev::tilingPatternFill(GfxState *state, Gfx * /*gfx*/, Catalog *cat, Object *str, POPPLER_CONST_070 double *pmat, int paintType, int tilingType, Dict *resDict, POPPLER_CONST_070 double *mat, POPPLER_CONST_070 double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep) ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(21, 3, 0) ++bool SlaOutputDev::tilingPatternFill(GfxState *state, Gfx * /*gfx*/, Catalog *cat, GfxTilingPattern *tPat, const double *mat, int x0, int y0, int x1, int y1, double xStep, double yStep) ++#else ++GBool SlaOutputDev::tilingPatternFill(GfxState *state, Gfx * /*gfx*/, Catalog *cat, Object *str, POPPLER_CONST_070 double *pmat, int /*paintType*/, int /*tilingType*/, Dict *resDict, POPPLER_CONST_070 double *mat, POPPLER_CONST_070 double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep) ++#endif + { + // qDebug() << "SlaOutputDev::tilingPatternFill"; ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(21, 3, 0) ++ const double *bbox = tPat->getBBox(); ++ const double *pmat = tPat->getMatrix(); ++ Dict *resDict = tPat->getResDict(); ++#endif ++ + PDFRectangle box; + Gfx *gfx; + QString id; +@@ -2325,7 +2335,11 @@ + // Unset the clip path as it is unrelated to the pattern's coordinate space. + QPainterPath savedClip = m_currentClipPath; + m_currentClipPath = QPainterPath(); ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(21, 3, 0) ++ gfx->display(tPat->getContentStream()); ++#else + gfx->display(str); ++#endif + m_currentClipPath = savedClip; + inPattern--; + gElements = m_groupStack.pop(); +diff -Naur scribus-1.5.6.1.orig/scribus/plugins/import/pdf/slaoutput.cpp.orig scribus-1.5.6.1/scribus/plugins/import/pdf/slaoutput.cpp.orig +--- scribus-1.5.6.1.orig/scribus/plugins/import/pdf/slaoutput.cpp.orig 1970-01-01 01:00:00.000000000 +0100 ++++ scribus-1.5.6.1/scribus/plugins/import/pdf/slaoutput.cpp.orig 2020-11-14 23:37:11.000000000 +0100 +@@ -0,0 +1,3898 @@ ++/* ++For general Scribus (>=1.3.2) copyright and licensing information please refer ++to the COPYING file provided with the program. Following this notice may exist ++a copyright and/or license notice that predates the release of Scribus 1.3.2 ++for which a new license (GPL+exception) is in place. ++*/ ++ ++#include "slaoutput.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "commonstrings.h" ++#include "loadsaveplugin.h" ++#include "sccolorengine.h" ++#include "util.h" ++#include "util_math.h" ++#include ++ ++namespace ++{ ++ // Compute the intersection of two paths while considering the fillrule of each of them. ++ // QPainterPath has the right interface to do the operation but is currently buggy. ++ // See for example https://bugreports.qt.io/browse/QTBUG-83102. Thus this function ++ // applies some heuristics to find the best result. As soon QPainterPath is fixed ++ // one can just use a.intersected(b) wherever this function is called. ++ // TODO: Find an alternative to QPainterPath that works for different fill rules. ++ QPainterPath intersection(QPainterPath const &a, QPainterPath const &b) ++ { ++ // An empty path is treated like the whole area. ++ if (a.elementCount() == 0) ++ return b; ++ if (b.elementCount() == 0) ++ return a; ++ ++ QPainterPath ret_a = a.intersected(b); ++ QPainterPath ret_b = b.intersected(a); ++ // Sometimes the resulting paths are not closed even though they should. ++ // Close them now. ++ ret_a.closeSubpath(); ++ ret_b.closeSubpath(); ++ ++ // Most of the time one of the two operations returns an empty path while the other ++ // gives us the desired result. Return the non-empty one. ++ if (ret_a.elementCount() == 0) ++ return ret_b; ++ if (ret_b.elementCount() == 0) ++ return ret_a; ++ ++ // There are cases where both intersections are not empty but one of them is quite ++ // complicated with several subpaths, etc. We return the simpler one. ++ return (ret_a.elementCount() <= ret_b.elementCount()) ? ret_a : ret_b; ++ } ++ ++ // Invert preblending matte values into the color values. Assuming that c and alpha are RGBA components ++ // between 0 and 255. ++ int unblendMatte(int c, int alpha, int matte) ++ { ++ if (alpha == 0) ++ return matte; ++ int ret = matte + ((c - matte) * 255) / alpha; ++ if (ret < 0) ++ return 0; ++ if (ret > 255) ++ return 255; ++ return ret; ++ } ++} ++ ++LinkSubmitForm::LinkSubmitForm(Object *actionObj) ++{ ++ if (!actionObj->isDict()) ++ return; ++ ++ Object obj1 = actionObj->dictLookup("F"); ++ if (!obj1.isNull()) ++ { ++ if (obj1.isDict()) ++ { ++ Object obj3 = obj1.dictLookup("FS"); ++ if (!obj3.isNull()) ++ { ++ if (obj3.isName()) ++ { ++ POPPLER_CONST char *name = obj3.getName(); ++ if (!strcmp(name, "URL")) ++ { ++ Object obj2 = obj1.dictLookup("F"); ++ if (!obj2.isNull()) ++ fileName = obj2.getString()->copy(); ++ } ++ } ++ } ++ } ++ } ++ obj1 = actionObj->dictLookup("Flags"); ++ if (!obj1.isNull()) ++ { ++ if (obj1.isNum()) ++ m_flags = obj1.getInt(); ++ } ++} ++ ++LinkSubmitForm::~LinkSubmitForm() ++{ ++ delete fileName; ++} ++ ++LinkImportData::LinkImportData(Object *actionObj) ++{ ++ if (!actionObj->isDict()) ++ return; ++ Object obj1 = actionObj->dictLookup("F"); ++ if (obj1.isNull()) ++ return; ++ ++ Object obj3 = getFileSpecNameForPlatform(&obj1); ++ if (!obj3.isNull()) ++ fileName = obj3.getString()->copy(); ++} ++ ++LinkImportData::~LinkImportData() ++{ ++ delete fileName; ++} ++ ++AnoOutputDev::~AnoOutputDev() ++{ ++ delete m_fontName; ++ delete m_itemText; ++} ++ ++AnoOutputDev::AnoOutputDev(ScribusDoc* doc, QStringList *importedColors) ++{ ++ m_doc = doc; ++ m_importedColors = importedColors; ++ CurrColorText = "Black"; ++ CurrColorFill = CommonStrings::None; ++ CurrColorStroke = CommonStrings::None; ++} ++ ++void AnoOutputDev::eoFill(GfxState *state) ++{ ++ int shade = 100; ++ CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); ++} ++ ++void AnoOutputDev::fill(GfxState *state) ++{ ++ int shade = 100; ++ CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); ++} ++ ++void AnoOutputDev::stroke(GfxState *state) ++{ ++ int shade = 100; ++ CurrColorStroke = getColor(state->getStrokeColorSpace(), state->getStrokeColor(), &shade); ++} ++ ++void AnoOutputDev::drawString(GfxState *state, POPPLER_CONST GooString *s) ++{ ++ int shade = 100; ++ CurrColorText = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); ++ m_fontSize = state->getFontSize(); ++ if (state->getFont()) ++ m_fontName = state->getFont()->getName()->copy(); ++ m_itemText = s->copy(); ++} ++ ++QString AnoOutputDev::getColor(GfxColorSpace *color_space, POPPLER_CONST_070 GfxColor *color, int *shade) ++{ ++ QString fNam; ++ QString namPrefix = "FromPDF"; ++ ScColor tmp; ++ tmp.setSpotColor(false); ++ tmp.setRegistrationColor(false); ++ *shade = 100; ++ if ((color_space->getMode() == csDeviceRGB) || (color_space->getMode() == csCalRGB)) ++ { ++ GfxRGB rgb; ++ color_space->getRGB(color, &rgb); ++ double Rc = colToDbl(rgb.r); ++ double Gc = colToDbl(rgb.g); ++ double Bc = colToDbl(rgb.b); ++ tmp.setRgbColorF(Rc, Gc, Bc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ } ++ else if (color_space->getMode() == csDeviceCMYK) ++ { ++ GfxCMYK cmyk; ++ color_space->getCMYK(color, &cmyk); ++ double Cc = colToDbl(cmyk.c); ++ double Mc = colToDbl(cmyk.m); ++ double Yc = colToDbl(cmyk.y); ++ double Kc = colToDbl(cmyk.k); ++ tmp.setCmykColorF(Cc, Mc, Yc, Kc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ } ++ else if ((color_space->getMode() == csCalGray) || (color_space->getMode() == csDeviceGray)) ++ { ++ GfxGray gray; ++ color_space->getGray(color, &gray); ++ double Kc = 1.0 - colToDbl(gray); ++ tmp.setCmykColorF(0, 0, 0, Kc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ } ++ else if (color_space->getMode() == csSeparation) ++ { ++ GfxSeparationColorSpace* sepColorSpace = (GfxSeparationColorSpace*)color_space; ++ GfxColorSpace* altColorSpace = sepColorSpace->getAlt(); ++ QString name = QString(sepColorSpace->getName()->getCString()); ++ bool isRegistrationColor = (name == "All"); ++ if (isRegistrationColor) ++ { ++ tmp.setCmykColorF(1.0, 1.0, 1.0, 1.0); ++ tmp.setRegistrationColor(true); ++ name = "Registration"; ++ } ++ else if ((altColorSpace->getMode() == csDeviceRGB) || (altColorSpace->getMode() == csCalRGB)) ++ { ++ double x = 1.0; ++ double comps[gfxColorMaxComps]; ++ sepColorSpace->getFunc()->transform(&x, comps); ++ tmp.setRgbColorF(comps[0], comps[1], comps[2]); ++ } ++ else if ((altColorSpace->getMode() == csCalGray) || (altColorSpace->getMode() == csDeviceGray)) ++ { ++ double x = 1.0; ++ double comps[gfxColorMaxComps]; ++ sepColorSpace->getFunc()->transform(&x, comps); ++ tmp.setCmykColorF(0.0, 0.0, 0.0, 1.0 - comps[0]); ++ } ++ else if (altColorSpace->getMode() == csLab) ++ { ++ double x = 1.0; ++ double comps[gfxColorMaxComps]; ++ sepColorSpace->getFunc()->transform(&x, comps); ++ tmp.setLabColor(comps[0], comps[1], comps[2]); ++ } ++ else ++ { ++ GfxCMYK cmyk; ++ color_space->getCMYK(color, &cmyk); ++ double Cc = colToDbl(cmyk.c); ++ double Mc = colToDbl(cmyk.m); ++ double Yc = colToDbl(cmyk.y); ++ double Kc = colToDbl(cmyk.k); ++ tmp.setCmykColorF(Cc, Mc, Yc, Kc); ++ } ++ tmp.setSpotColor(true); ++ ++ fNam = m_doc->PageColors.tryAddColor(name, tmp); ++ *shade = qRound(colToDbl(color->c[0]) * 100); ++ } ++ else ++ { ++ GfxRGB rgb; ++ color_space->getRGB(color, &rgb); ++ double Rc = colToDbl(rgb.r); ++ double Gc = colToDbl(rgb.g); ++ double Bc = colToDbl(rgb.b); ++ tmp.setRgbColorF(Rc, Gc, Bc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ // qDebug() << "update fill color other colorspace" << color_space->getMode() << "treating as rgb" << Rc << Gc << Bc; ++ } ++ if (fNam == namPrefix+tmp.name()) ++ m_importedColors->append(fNam); ++ return fNam; ++} ++ ++SlaOutputDev::SlaOutputDev(ScribusDoc* doc, QList *Elements, QStringList *importedColors, int flags) ++{ ++ m_doc = doc; ++ m_Elements = Elements; ++ pushGroup(); ++ m_importedColors = importedColors; ++ CurrColorStroke = "Black"; ++ CurrColorFill = "Black"; ++ tmpSel = new Selection(m_doc, false); ++ importerFlags = flags; ++ currentLayer = m_doc->activeLayer(); ++ layersSetByOCG = false; ++} ++ ++SlaOutputDev::~SlaOutputDev() ++{ ++ m_groupStack.clear(); ++ tmpSel->clear(); ++ delete tmpSel; ++ delete m_fontEngine; ++} ++ ++/* get Actions not implemented by Poppler */ ++LinkAction* SlaOutputDev::SC_getAction(AnnotWidget *ano) ++{ ++ LinkAction *linkAction = nullptr; ++ Object obj; ++ Ref refa = ano->getRef(); ++ ++ obj = xref->fetch(refa.num, refa.gen); ++ if (obj.isDict()) ++ { ++ Dict* adic = obj.getDict(); ++ POPPLER_CONST_075 Object POPPLER_REF additionalActions = adic->lookupNF("A"); ++ Object additionalActionsObject = additionalActions.fetch(pdfDoc->getXRef()); ++ if (additionalActionsObject.isDict()) ++ { ++ Object actionObject = additionalActionsObject.dictLookup("S"); ++ if (actionObject.isName("ImportData")) ++ { ++ linkAction = new LinkImportData(&additionalActionsObject); ++ } ++ else if (actionObject.isName("SubmitForm")) ++ { ++ linkAction = new LinkSubmitForm(&additionalActionsObject); ++ } ++ } ++ } ++ return linkAction; ++} ++ ++/* Replacement for the crippled Poppler function LinkAction* AnnotWidget::getAdditionalAction(AdditionalActionsType type) */ ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++std::unique_ptr SlaOutputDev::SC_getAdditionalAction(const char *key, AnnotWidget *ano) ++{ ++ std::unique_ptr linkAction; ++#else ++LinkAction* SlaOutputDev::SC_getAdditionalAction(const char *key, AnnotWidget *ano) ++{ ++ LinkAction *linkAction = nullptr; ++#endif ++ Object obj; ++ Ref refa = ano->getRef(); ++ ++ obj = xref->fetch(refa.num, refa.gen); ++ if (obj.isDict()) ++ { ++ Dict* adic = obj.getDict(); ++ POPPLER_CONST_075 Object POPPLER_REF additionalActions = adic->lookupNF("AA"); ++ Object additionalActionsObject = additionalActions.fetch(pdfDoc->getXRef()); ++ if (additionalActionsObject.isDict()) ++ { ++ Object actionObject = additionalActionsObject.dictLookup(key); ++ if (actionObject.isDict()) ++ linkAction = LinkAction::parseAction(&actionObject, pdfDoc->getCatalog()->getBaseURI()); ++ } ++ } ++ return linkAction; ++} ++ ++GBool SlaOutputDev::annotations_callback(Annot *annota, void *user_data) ++{ ++ SlaOutputDev *dev = (SlaOutputDev*)user_data; ++ PDFRectangle *box = annota->getRect(); ++ double xCoor = dev->m_doc->currentPage()->xOffset() + box->x1 - dev->cropOffsetX; ++ double yCoor = dev->m_doc->currentPage()->yOffset() + dev->m_doc->currentPage()->height() - box->y2 + dev->cropOffsetY; ++ double width = box->x2 - box->x1; ++ double height = box->y2 - box->y1; ++ if (dev->rotate == 90) ++ { ++ xCoor = dev->m_doc->currentPage()->xOffset() - dev->cropOffsetX + box->y2; ++ yCoor = dev->m_doc->currentPage()->yOffset() + dev->cropOffsetY + box->x1; ++ } ++ else if (dev->rotate == 180) ++ { ++ xCoor = dev->m_doc->currentPage()->xOffset() - dev->cropOffsetX + dev->m_doc->currentPage()->width() - box->x1; ++ yCoor = dev->m_doc->currentPage()->yOffset() + dev->cropOffsetY + box->y2; ++ } ++ else if (dev->rotate == 270) ++ { ++ xCoor = dev->m_doc->currentPage()->xOffset() - dev->cropOffsetX + dev->m_doc->currentPage()->width() - box->y2; ++ yCoor = dev->m_doc->currentPage()->yOffset() + dev->cropOffsetY + dev->m_doc->currentPage()->height() - box->x1; ++ } ++ bool retVal = true; ++ if (annota->getType() == Annot::typeText) ++ retVal = !dev->handleTextAnnot(annota, xCoor, yCoor, width, height); ++ else if (annota->getType() == Annot::typeLink) ++ retVal = !dev->handleLinkAnnot(annota, xCoor, yCoor, width, height); ++ else if (annota->getType() == Annot::typeWidget) ++ retVal = !dev->handleWidgetAnnot(annota, xCoor, yCoor, width, height); ++ return retVal; ++} ++ ++bool SlaOutputDev::handleTextAnnot(Annot* annota, double xCoor, double yCoor, double width, double height) ++{ ++ AnnotText *anl = (AnnotText*)annota; ++ int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None); ++ PageItem *ite = m_doc->Items->at(z); ++ int flg = annota->getFlags(); ++ if (!(flg & 16)) ++ ite->setRotation(rotate, true); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setFillEvenOdd(false); ++ ite->Clip = flattenPath(ite->PoLine, ite->Segments); ++ ite->ContourLine = ite->PoLine.copy(); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ ite->setIsAnnotation(true); ++ ite->AutoName = false; ++ ite->annotation().setType(Annotation::Text); ++ ite->annotation().setActionType(Annotation::Action_None); ++ ite->annotation().setAnOpen(anl->getOpen()); ++ QString iconName = UnicodeParsedString(anl->getIcon()); ++ if (iconName == "Note") ++ ite->annotation().setIcon(Annotation::Icon_Note); ++ else if (iconName == "Comment") ++ ite->annotation().setIcon(Annotation::Icon_Comment); ++ else if (iconName == "Key") ++ ite->annotation().setIcon(Annotation::Icon_Key); ++ else if (iconName == "Help") ++ ite->annotation().setIcon(Annotation::Icon_Help); ++ else if (iconName == "NewParagraph") ++ ite->annotation().setIcon(Annotation::Icon_NewParagraph); ++ else if (iconName == "Paragraph") ++ ite->annotation().setIcon(Annotation::Icon_Paragraph); ++ else if (iconName == "Insert") ++ ite->annotation().setIcon(Annotation::Icon_Insert); ++ else if (iconName == "Cross") ++ ite->annotation().setIcon(Annotation::Icon_Cross); ++ else if (iconName == "Circle") ++ ite->annotation().setIcon(Annotation::Icon_Circle); ++ else ++ ite->annotation().setIcon(Annotation::Icon_Note); ++ ite->setItemName( CommonStrings::itemName_TextAnnotation + QString("%1").arg(m_doc->TotalItems)); ++ ite->itemText.insertChars(UnicodeParsedString(annota->getContents())); ++ ite->itemText.trim(); ++ return true; ++} ++ ++bool SlaOutputDev::handleLinkAnnot(Annot* annota, double xCoor, double yCoor, double width, double height) ++{ ++ AnnotLink *anl = (AnnotLink*)annota; ++ LinkAction *act = anl->getAction(); ++ if (!act) ++ return false; ++ bool validLink = false; ++ int pagNum = 0; ++ int xco = 0; ++ int yco = 0; ++ QString fileName = ""; ++ if (act->getKind() == actionGoTo) ++ { ++ LinkGoTo *gto = (LinkGoTo*) act; ++ POPPLER_CONST LinkDest *dst = gto->getDest(); ++ if (dst) ++ { ++ if (dst->getKind() == destXYZ) ++ { ++ if (dst->isPageRef()) ++ { ++ Ref dstr = dst->getPageRef(); ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 76, 0) ++ pagNum = pdfDoc->findPage(dstr); ++#else ++ pagNum = pdfDoc->findPage(dstr.num, dstr.gen); ++#endif ++ } ++ else ++ pagNum = dst->getPageNum(); ++ xco = dst->getLeft(); ++ yco = dst->getTop(); ++ validLink = true; ++ } ++ } ++ else ++ { ++ POPPLER_CONST GooString *ndst = gto->getNamedDest(); ++ if (ndst) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ std::unique_ptr dstn = pdfDoc->findDest(ndst); ++#else ++ LinkDest *dstn = pdfDoc->findDest(ndst); ++#endif ++ if (dstn) ++ { ++ if (dstn->getKind() == destXYZ) ++ { ++ if (dstn->isPageRef()) ++ { ++ Ref dstr = dstn->getPageRef(); ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 76, 0) ++ pagNum = pdfDoc->findPage(dstr); ++#else ++ pagNum = pdfDoc->findPage(dstr.num, dstr.gen); ++#endif ++ } ++ else ++ pagNum = dstn->getPageNum(); ++ xco = dstn->getLeft(); ++ yco = dstn->getTop(); ++ validLink = true; ++ } ++ } ++ } ++ } ++ } ++ else if (act->getKind() == actionGoToR) ++ { ++ LinkGoToR *gto = (LinkGoToR*)act; ++ fileName = UnicodeParsedString(gto->getFileName()); ++ POPPLER_CONST LinkDest *dst = gto->getDest(); ++ if (dst) ++ { ++ if (dst->getKind() == destXYZ) ++ { ++ pagNum = dst->getPageNum(); ++ xco = dst->getLeft(); ++ yco = dst->getTop(); ++ validLink = true; ++ } ++ } ++ else ++ { ++ POPPLER_CONST GooString *ndst = gto->getNamedDest(); ++ if (ndst) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ std::unique_ptr dstn = pdfDoc->findDest(ndst); ++#else ++ LinkDest *dstn = pdfDoc->findDest(ndst); ++#endif ++ if (dstn) ++ { ++ if (dstn->getKind() == destXYZ) ++ { ++ pagNum = dstn->getPageNum(); ++ xco = dstn->getLeft(); ++ yco = dstn->getTop(); ++ validLink = true; ++ } ++ } ++ } ++ } ++ } ++ else if (act->getKind() == actionURI) ++ { ++ LinkURI *gto = (LinkURI*)act; ++ validLink = true; ++ fileName = UnicodeParsedString(gto->getURI()); ++ } ++ if (validLink) ++ { ++ int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None); ++ PageItem *ite = m_doc->Items->at(z); ++ int flg = annota->getFlags(); ++ if (!(flg & 16)) ++ ite->setRotation(rotate, true); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setFillEvenOdd(false); ++ ite->Clip = flattenPath(ite->PoLine, ite->Segments); ++ ite->ContourLine = ite->PoLine.copy(); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ ite->setIsAnnotation(true); ++ ite->AutoName = false; ++ if (act->getKind() == actionGoTo) ++ { ++ ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1)); ++ ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco)); ++ ite->annotation().setActionType(2); ++ } ++ else if (act->getKind() == actionGoToR) ++ { ++ ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1)); ++ ite->annotation().setExtern(fileName); ++ ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco)); ++ ite->annotation().setActionType(9); ++ } ++ else if (act->getKind() == actionURI) ++ { ++ ite->annotation().setAction(""); ++ ite->annotation().setExtern(fileName); ++ ite->annotation().setActionType(8); ++ } ++ ite->annotation().setType(Annotation::Link); ++ ite->setItemName( CommonStrings::itemName_LinkAnnotation + QString("%1").arg(m_doc->TotalItems)); ++ } ++ return validLink; ++} ++ ++bool SlaOutputDev::handleWidgetAnnot(Annot* annota, double xCoor, double yCoor, double width, double height) ++{ ++ bool retVal = false; ++ bool found = false; ++ ++ if (!m_formWidgets) ++ return false; ++ ++ int formcount = m_formWidgets->getNumWidgets(); ++ for (int i = 0; i < formcount; ++i) ++ { ++ FormWidget *fm = m_formWidgets->getWidget(i); ++ if (!fm) ++ continue; ++ AnnotWidget *ano = fm->getWidgetAnnotation(); ++ if (!ano) ++ continue; ++ if (ano != (AnnotWidget*) annota) ++ continue; ++ found = true; ++ int wtyp = -1; ++ if (fm->getType() == formButton) ++ { ++ FormWidgetButton *btn = (FormWidgetButton*)fm; ++ if (btn) ++ { ++ if (btn->getButtonType() == formButtonCheck) ++ { ++ wtyp = Annotation::Checkbox; ++ retVal = true; ++ } ++ else if (btn->getButtonType() == formButtonPush) ++ { ++ wtyp = Annotation::Button; ++ retVal = true; ++ } ++ else if (btn->getButtonType() == formButtonRadio) ++ { ++ wtyp = Annotation::RadioButton; ++ retVal = true; ++ } ++ } ++ } ++ else if (fm->getType() == formText) ++ { ++ wtyp = Annotation::Textfield; ++ retVal = true; ++ } ++ else if (fm->getType() == formChoice) ++ { ++ FormWidgetChoice *btn = (FormWidgetChoice*)fm; ++ if (btn) ++ { ++ if (btn->isCombo()) ++ { ++ wtyp = Annotation::Combobox; ++ retVal = true; ++ } ++ else if (btn->isListBox()) ++ { ++ wtyp = Annotation::Listbox; ++ retVal = true; ++ } ++ } ++ } ++ if (retVal) ++ { ++ AnnotAppearanceCharacs *achar = ano->getAppearCharacs(); ++ bool fgFound = false; ++ bool bgFound = false; ++ if (achar) ++ { ++ POPPLER_CONST AnnotColor *bgCol = achar->getBackColor(); ++ if (bgCol) ++ { ++ bgFound = true; ++ CurrColorFill = getAnnotationColor(bgCol); ++ } ++ else ++ CurrColorFill = CommonStrings::None; ++ POPPLER_CONST AnnotColor *fgCol = achar->getBorderColor(); ++ if (fgCol) ++ { ++ fgFound = true; ++ CurrColorStroke = getAnnotationColor(fgCol); ++ } ++ else ++ { ++ fgCol = achar->getBackColor(); ++ if (fgCol) ++ CurrColorStroke = getAnnotationColor(fgCol); ++ else ++ CurrColorStroke = CommonStrings::None; ++ } ++ } ++ QString CurrColorText = "Black"; ++ double fontSize = 12; ++ QString fontName = ""; ++ QString itemText = ""; ++ AnnotAppearance *apa = annota->getAppearStreams(); ++ if (apa || !achar) ++ { ++ AnoOutputDev *Adev = new AnoOutputDev(m_doc, m_importedColors); ++ Gfx *gfx = new Gfx(pdfDoc, Adev, pdfDoc->getPage(m_actPage)->getResourceDict(), annota->getRect(), nullptr); ++ ano->draw(gfx, false); ++ if (!bgFound) ++ CurrColorFill = Adev->CurrColorFill; ++ if (!fgFound) ++ CurrColorStroke = Adev->CurrColorStroke; ++ CurrColorText = Adev->CurrColorText; ++ fontSize = Adev->m_fontSize; ++ fontName = UnicodeParsedString(Adev->m_fontName); ++ itemText = UnicodeParsedString(Adev->m_itemText); ++ delete gfx; ++ delete Adev; ++ } ++ int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CurrColorFill, CommonStrings::None); ++ PageItem *ite = m_doc->Items->at(z); ++ int flg = annota->getFlags(); ++ if (!(flg & 16)) ++ ite->setRotation(rotate, true); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setFillEvenOdd(false); ++ ite->Clip = flattenPath(ite->PoLine, ite->Segments); ++ ite->ContourLine = ite->PoLine.copy(); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ ite->setIsAnnotation(true); ++ ite->AutoName = false; ++ AnnotBorder *brd = annota->getBorder(); ++ if (brd) ++ { ++ int bsty = brd->getStyle(); ++ if (bsty == AnnotBorder::borderDashed) ++ bsty = 1; ++ else if (bsty == AnnotBorder::borderBeveled) ++ bsty = 3; ++ else if (bsty == AnnotBorder::borderInset) ++ bsty = 4; ++ else if (bsty == AnnotBorder::borderUnderlined) ++ bsty = 2; ++ ite->annotation().setBorderStyle(bsty); ++ ite->annotation().setBorderColor(CurrColorStroke); ++ ite->annotation().setBorderWidth(qRound(brd->getWidth())); ++ } ++ else ++ { ++ ite->annotation().setBorderStyle(0); ++ ite->annotation().setBorderColor(CommonStrings::None); ++ ite->annotation().setBorderWidth(0); ++ } ++ QString tmTxt = ""; ++ tmTxt = UnicodeParsedString(fm->getPartialName()); ++ if (!tmTxt.isEmpty()) ++ ite->setItemName(tmTxt); ++ tmTxt = ""; ++ tmTxt = UnicodeParsedString(fm->getAlternateUiName()); ++ if (!tmTxt.isEmpty()) ++ ite->annotation().setToolTip(tmTxt); ++ tmTxt = ""; ++ if (achar) ++ { ++ tmTxt = UnicodeParsedString(achar->getRolloverCaption()); ++ if (!tmTxt.isEmpty()) ++ ite->annotation().setRollOver(tmTxt); ++ tmTxt = ""; ++ tmTxt = UnicodeParsedString(achar->getAlternateCaption()); ++ if (!tmTxt.isEmpty()) ++ ite->annotation().setDown(tmTxt); ++ } ++ ite->annotation().setType(wtyp); ++ ite->annotation().setFlag(0); ++ if (flg & 2) ++ ite->annotation().setVis(1); ++ if (flg & 32) ++ ite->annotation().setVis(3); ++ if (wtyp == Annotation::Button) ++ { ++ ite->setFillColor(CurrColorFill); ++ if (achar) ++ ite->itemText.insertChars(UnicodeParsedString(achar->getNormalCaption())); ++ else ++ ite->itemText.insertChars(itemText); ++ applyTextStyle(ite, fontName, CurrColorText, fontSize); ++ ite->annotation().addToFlag(Annotation::Flag_PushButton); ++ FormWidgetButton *btn = (FormWidgetButton*)fm; ++ if (!btn->isReadOnly()) ++ ite->annotation().addToFlag(Annotation::Flag_Edit); ++ handleActions(ite, ano); ++ } ++ else if (wtyp == Annotation::Textfield) ++ { ++ FormWidgetText *btn = (FormWidgetText*)fm; ++ if (btn) ++ { ++ ite->itemText.insertChars(UnicodeParsedString(btn->getContent())); ++ applyTextStyle(ite, fontName, CurrColorText, fontSize); ++ ite->itemText.trim(); ++ if (btn->isMultiline()) ++ ite->annotation().addToFlag(Annotation::Flag_Multiline); ++ if (btn->isPassword()) ++ ite->annotation().addToFlag(Annotation::Flag_Password); ++ if (btn->noSpellCheck()) ++ ite->annotation().addToFlag(Annotation::Flag_DoNotSpellCheck); ++ if (btn->noScroll()) ++ ite->annotation().addToFlag(Annotation::Flag_DoNotScroll); ++ int mxLen = btn->getMaxLen(); ++ if (mxLen > 0) ++ ite->annotation().setMaxChar(mxLen); ++ else ++ ite->annotation().setMaxChar(-1); ++ if (!btn->isReadOnly()) ++ ite->annotation().addToFlag(Annotation::Flag_Edit); ++ handleActions(ite, ano); ++ } ++ } ++ else if (wtyp == Annotation::Checkbox) ++ { ++ FormWidgetButton *btn = (FormWidgetButton*)fm; ++ if (btn) ++ { ++ ite->annotation().setIsChk(btn->getState()); ++ ite->annotation().setCheckState(ite->annotation().IsChk()); ++ handleActions(ite, ano); ++ if (itemText == "4") ++ ite->annotation().setChkStil(0); ++ else if (itemText == "5") ++ ite->annotation().setChkStil(1); ++ else if (itemText == "F") ++ ite->annotation().setChkStil(2); ++ else if (itemText == "l") ++ ite->annotation().setChkStil(3); ++ else if (itemText == "H") ++ ite->annotation().setChkStil(4); ++ else if (itemText == "n") ++ ite->annotation().setChkStil(5); ++ else ++ ite->annotation().setChkStil(0); ++ if (!btn->isReadOnly()) ++ ite->annotation().addToFlag(Annotation::Flag_Edit); ++ } ++ } ++ else if ((wtyp == Annotation::Combobox) || (wtyp == Annotation::Listbox)) ++ { ++ FormWidgetChoice *btn = (FormWidgetChoice*)fm; ++ if (btn) ++ { ++ if (wtyp == 5) ++ ite->annotation().addToFlag(Annotation::Flag_Combo); ++ int co = btn->getNumChoices(); ++ if (co > 0) ++ { ++ QString inh = UnicodeParsedString(btn->getChoice(0)); ++ for (int a = 1; a < co; a++) ++ { ++ inh += "\n" + UnicodeParsedString(btn->getChoice(a)); ++ } ++ ite->itemText.insertChars(inh); ++ } ++ applyTextStyle(ite, fontName, CurrColorText, fontSize); ++ if (!btn->isReadOnly()) ++ ite->annotation().addToFlag(Annotation::Flag_Edit); ++ handleActions(ite, ano); ++ } ++ } ++ else if (wtyp == Annotation::RadioButton) ++ { ++ FormWidgetButton *btn = (FormWidgetButton*)fm; ++ if (btn) ++ { ++ ite->setItemName( CommonStrings::itemName_RadioButton + QString("%1").arg(m_doc->TotalItems)); ++ ite->annotation().setIsChk(btn->getState()); ++ ite->annotation().setCheckState(ite->annotation().IsChk()); ++ handleActions(ite, ano); ++ m_radioButtons.insert(annota->getRef().num, ite); ++ } ++ } ++ } ++ break; ++ } ++ if (!found) ++ { ++ Object obj1; ++ Ref refa = annota->getRef(); ++ obj1 = xref->fetch(refa.num, refa.gen); ++ if (obj1.isDict()) ++ { ++ Dict* dict = obj1.getDict(); ++ Object obj2 = dict->lookup("Kids"); ++ //childs ++ if (obj2.isArray()) ++ { ++ // Load children ++ QList radList; ++ for (int i = 0; i < obj2.arrayGetLength(); i++) ++ { ++ POPPLER_CONST_075 Object POPPLER_REF childRef = obj2.arrayGetNF(i); ++ if (!childRef.isRef()) ++ continue; ++ Object childObj = obj2.arrayGet(i); ++ if (!childObj.isDict()) ++ continue; ++ const Ref ref = childRef.getRef(); ++ radList.append(ref.num); ++ } ++ QString tmTxt = UnicodeParsedString(annota->getName()); ++ m_radioMap.insert(tmTxt, radList); ++ } ++ } ++ } ++ return retVal; ++} ++ ++void SlaOutputDev::applyTextStyle(PageItem* ite, const QString& fontName, const QString& textColor, double fontSize) ++{ ++ CharStyle newStyle; ++ newStyle.setFillColor(textColor); ++ newStyle.setFontSize(fontSize * 10); ++ if (!fontName.isEmpty()) ++ { ++ SCFontsIterator it(*m_doc->AllFonts); ++ for ( ; it.hasNext() ; it.next()) ++ { ++ ScFace& face(it.current()); ++ if ((face.psName() == fontName) && (face.usable()) && (face.type() == ScFace::TTF)) ++ { ++ newStyle.setFont(face); ++ break; ++ } ++ if ((face.family() == fontName) && (face.usable()) && (face.type() == ScFace::TTF)) ++ { ++ newStyle.setFont(face); ++ break; ++ } ++ if ((face.scName() == fontName) && (face.usable()) && (face.type() == ScFace::TTF)) ++ { ++ newStyle.setFont(face); ++ break; ++ } ++ } ++ } ++ ParagraphStyle dstyle(ite->itemText.defaultStyle()); ++ dstyle.charStyle().applyCharStyle(newStyle); ++ ite->itemText.setDefaultStyle(dstyle); ++ ite->itemText.applyCharStyle(0, ite->itemText.length(), newStyle); ++ ite->invalid = true; ++} ++ ++void SlaOutputDev::handleActions(PageItem* ite, AnnotWidget *ano) ++{ ++ LinkAction *Lact = ano->getAction(); ++ if (Lact) ++ { ++ if (Lact->getKind() == actionJavaScript) ++ { ++ LinkJavaScript *jsa = (LinkJavaScript*)Lact; ++ if (jsa->isOk()) ++ { ++ ite->annotation().setActionType(1); ++ ite->annotation().setAction(UnicodeParsedString(jsa->getScript())); ++ } ++ } ++ else if (Lact->getKind() == actionGoTo) ++ { ++ int pagNum = 0; ++ int xco = 0; ++ int yco = 0; ++ LinkGoTo *gto = (LinkGoTo*)Lact; ++ POPPLER_CONST LinkDest *dst = gto->getDest(); ++ if (dst) ++ { ++ if (dst->getKind() == destXYZ) ++ { ++ if (dst->isPageRef()) ++ { ++ Ref dstr = dst->getPageRef(); ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 76, 0) ++ pagNum = pdfDoc->findPage(dstr); ++#else ++ pagNum = pdfDoc->findPage(dstr.num, dstr.gen); ++#endif ++ } ++ else ++ pagNum = dst->getPageNum(); ++ xco = dst->getLeft(); ++ yco = dst->getTop(); ++ ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1)); ++ ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco)); ++ ite->annotation().setActionType(2); ++ } ++ } ++ else ++ { ++ POPPLER_CONST GooString *ndst = gto->getNamedDest(); ++ if (ndst) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ std::unique_ptr dstn = pdfDoc->findDest(ndst); ++#else ++ LinkDest *dstn = pdfDoc->findDest(ndst); ++#endif ++ if (dstn) ++ { ++ if (dstn->getKind() == destXYZ) ++ { ++ if (dstn->isPageRef()) ++ { ++ Ref dstr = dstn->getPageRef(); ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 76, 0) ++ pagNum = pdfDoc->findPage(dstr); ++#else ++ pagNum = pdfDoc->findPage(dstr.num, dstr.gen); ++#endif ++ } ++ else ++ pagNum = dstn->getPageNum(); ++ xco = dstn->getLeft(); ++ yco = dstn->getTop(); ++ ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1)); ++ ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco)); ++ ite->annotation().setActionType(2); ++ } ++ } ++ } ++ } ++ } ++ else if (Lact->getKind() == actionGoToR) ++ { ++ int pagNum = 0; ++ int xco = 0; ++ int yco = 0; ++ LinkGoToR *gto = (LinkGoToR*)Lact; ++ QString fileName = UnicodeParsedString(gto->getFileName()); ++ POPPLER_CONST LinkDest *dst = gto->getDest(); ++ if (dst) ++ { ++ if (dst->getKind() == destXYZ) ++ { ++ pagNum = dst->getPageNum(); ++ xco = dst->getLeft(); ++ yco = dst->getTop(); ++ ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1)); ++ ite->annotation().setExtern(fileName); ++ ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco)); ++ ite->annotation().setActionType(9); ++ } ++ } ++ else ++ { ++ POPPLER_CONST GooString *ndst = gto->getNamedDest(); ++ if (ndst) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ std::unique_ptr dstn = pdfDoc->findDest(ndst); ++#else ++ LinkDest *dstn = pdfDoc->findDest(ndst); ++#endif ++ if (dstn) ++ { ++ if (dstn->getKind() == destXYZ) ++ { ++ pagNum = dstn->getPageNum(); ++ xco = dstn->getLeft(); ++ yco = dstn->getTop(); ++ ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1)); ++ ite->annotation().setExtern(fileName); ++ ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco)); ++ ite->annotation().setActionType(9); ++ } ++ } ++ } ++ } ++ } ++ else if (Lact->getKind() == actionUnknown) ++ { ++ LinkUnknown *uno = (LinkUnknown*)Lact; ++ QString actString = UnicodeParsedString(uno->getAction()); ++ if (actString == "ResetForm") ++ { ++ ite->annotation().setActionType(4); ++ } ++ else ++ { ++ LinkAction* scact = SC_getAction(ano); ++ if (scact) ++ { ++ if (actString == "ImportData") ++ { ++ LinkImportData *impo = (LinkImportData*)scact; ++ if (impo->isOk()) ++ { ++ ite->annotation().setActionType(5); ++ ite->annotation().setAction(UnicodeParsedString(impo->getFileName())); ++ } ++ } ++ else if (actString == "SubmitForm") ++ { ++ LinkSubmitForm *impo = (LinkSubmitForm*)scact; ++ if (impo->isOk()) ++ { ++ ite->annotation().setActionType(3); ++ ite->annotation().setAction(UnicodeParsedString(impo->getFileName())); ++ int fl = impo->getFlags(); ++ if (fl == 0) ++ ite->annotation().setHTML(0); ++ else if (fl == 4) ++ ite->annotation().setHTML(1); ++ else if (fl == 64) ++ ite->annotation().setHTML(2); ++ else if (fl == 512) ++ ite->annotation().setHTML(3); ++ } ++ } ++ } ++ } ++ } ++ else if (Lact->getKind() == actionNamed) ++ { ++ LinkNamed *uno = (LinkNamed*)Lact; ++ ite->annotation().setActionType(10); ++ ite->annotation().setAction(UnicodeParsedString(uno->getName())); ++ } ++ else ++ qDebug() << "Found unsupported Action of type" << Lact->getKind(); ++ } ++ auto Aact = SC_getAdditionalAction("D", ano); ++ if (Aact) ++ { ++ if (Aact->getKind() == actionJavaScript) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact.get(); ++#else ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact; ++#endif ++ if (jsa->isOk()) ++ { ++ ite->annotation().setD_act(UnicodeParsedString(jsa->getScript())); ++ ite->annotation().setAAact(true); ++ } ++ } ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ Aact.reset(); ++#else ++ Aact = nullptr; ++#endif ++ } ++ Aact = SC_getAdditionalAction("E", ano); ++ if (Aact) ++ { ++ if (Aact->getKind() == actionJavaScript) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact.get(); ++#else ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact; ++#endif ++ if (jsa->isOk()) ++ { ++ ite->annotation().setE_act(UnicodeParsedString(jsa->getScript())); ++ ite->annotation().setAAact(true); ++ } ++ } ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ Aact.reset(); ++#else ++ Aact = nullptr; ++#endif ++ } ++ Aact = SC_getAdditionalAction("X", ano); ++ if (Aact) ++ { ++ if (Aact->getKind() == actionJavaScript) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact.get(); ++#else ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact; ++#endif ++ if (jsa->isOk()) ++ { ++ ite->annotation().setX_act(UnicodeParsedString(jsa->getScript())); ++ ite->annotation().setAAact(true); ++ } ++ } ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ Aact.reset(); ++#else ++ Aact = nullptr; ++#endif ++ } ++ Aact = SC_getAdditionalAction("Fo", ano); ++ if (Aact) ++ { ++ if (Aact->getKind() == actionJavaScript) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact.get(); ++#else ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact; ++#endif ++ if (jsa->isOk()) ++ { ++ ite->annotation().setFo_act(UnicodeParsedString(jsa->getScript())); ++ ite->annotation().setAAact(true); ++ } ++ } ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ Aact.reset(); ++#else ++ Aact = nullptr; ++#endif ++ } ++ Aact = SC_getAdditionalAction("Bl", ano); ++ if (Aact) ++ { ++ if (Aact->getKind() == actionJavaScript) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact.get(); ++#else ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact; ++#endif ++ if (jsa->isOk()) ++ { ++ ite->annotation().setBl_act(UnicodeParsedString(jsa->getScript())); ++ ite->annotation().setAAact(true); ++ } ++ } ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ Aact.reset(); ++#else ++ Aact = nullptr; ++#endif ++ } ++ Aact = SC_getAdditionalAction("C", ano); ++ if (Aact) ++ { ++ if (Aact->getKind() == actionJavaScript) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact.get(); ++#else ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact; ++#endif ++ if (jsa->isOk()) ++ { ++ ite->annotation().setC_act(UnicodeParsedString(jsa->getScript())); ++ ite->annotation().setAAact(true); ++ } ++ } ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ Aact.reset(); ++#else ++ Aact = nullptr; ++#endif ++ } ++ Aact = SC_getAdditionalAction("F", ano); ++ if (Aact) ++ { ++ if (Aact->getKind() == actionJavaScript) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact.get(); ++#else ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact; ++#endif ++ if (jsa->isOk()) ++ { ++ ite->annotation().setF_act(UnicodeParsedString(jsa->getScript())); ++ ite->annotation().setAAact(true); ++ ite->annotation().setFormat(5); ++ } ++ } ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ Aact.reset(); ++#else ++ Aact = nullptr; ++#endif ++ } ++ Aact = SC_getAdditionalAction("K", ano); ++ if (Aact) ++ { ++ if (Aact->getKind() == actionJavaScript) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact.get(); ++#else ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact; ++#endif ++ if (jsa->isOk()) ++ { ++ ite->annotation().setK_act(UnicodeParsedString(jsa->getScript())); ++ ite->annotation().setAAact(true); ++ ite->annotation().setFormat(5); ++ } ++ } ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ Aact.reset(); ++#else ++ Aact = nullptr; ++#endif ++ } ++ Aact = SC_getAdditionalAction("V", ano); ++ if (Aact) ++ { ++ if (Aact->getKind() == actionJavaScript) ++ { ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact.get(); ++#else ++ LinkJavaScript *jsa = (LinkJavaScript*) Aact; ++#endif ++ if (jsa->isOk()) ++ { ++ ite->annotation().setV_act(UnicodeParsedString(jsa->getScript())); ++ ite->annotation().setAAact(true); ++ } ++ } ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ Aact.reset(); ++#else ++ Aact = nullptr; ++#endif ++ } ++} ++ ++void SlaOutputDev::startDoc(PDFDoc *doc, XRef *xrefA, Catalog *catA) ++{ ++ xref = xrefA; ++ catalog = catA; ++ pdfDoc = doc; ++ updateGUICounter = 0; ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 84, 0) ++ m_fontEngine = new SplashFontEngine(true, false, false, true); ++#else ++ m_fontEngine = new SplashFontEngine(globalParams->getEnableFreeType(), false, false, true); ++#endif ++} ++ ++void SlaOutputDev::startPage(int pageNum, GfxState *, XRef *) ++{ ++ m_formWidgets = pdfDoc->getPage(pageNum)->getFormWidgets(); ++ m_radioMap.clear(); ++ m_radioButtons.clear(); ++ m_actPage = pageNum; ++ m_groupStack.clear(); ++ pushGroup(); ++ m_currentClipPath = QPainterPath(); ++ m_clipPaths.clear(); ++} ++ ++void SlaOutputDev::endPage() ++{ ++ if (!m_radioMap.isEmpty()) ++ { ++ for (auto it = m_radioMap.begin(); it != m_radioMap.end(); ++it) ++ { ++ tmpSel->clear(); ++ QList refList = it.value(); ++ for (int a = 0; a < refList.count(); a++) ++ { ++ if (m_radioButtons.contains(refList[a])) ++ { ++ tmpSel->addItem(m_radioButtons[refList[a]], true); ++ m_Elements->removeAll(m_radioButtons[refList[a]]); ++ } ++ } ++ if (!tmpSel->isEmpty()) ++ { ++ PageItem *ite = m_doc->groupObjectsSelection(tmpSel); ++ ite->setItemName(it.key()); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ m_groupStack.top().Items.append(ite); ++ } ++ } ++ } ++ m_radioMap.clear(); ++ m_radioButtons.clear(); ++// qDebug() << "ending page"; ++} ++ ++void SlaOutputDev::saveState(GfxState *state) ++{ ++ m_clipPaths.push(m_currentClipPath); ++ pushGroup(); ++} ++ ++void SlaOutputDev::restoreState(GfxState *state) ++{ ++ if (m_groupStack.count() != 0) ++ { ++ groupEntry gElements = m_groupStack.pop(); ++ if (gElements.Items.count() > 0) ++ { ++ if ((gElements.Items.count() > 1) && (checkClip())) ++ { ++ tmpSel->clear(); ++ for (int dre = 0; dre < gElements.Items.count(); ++dre) ++ { ++ tmpSel->addItem(gElements.Items.at(dre), true); ++ m_Elements->removeAll(gElements.Items.at(dre)); ++ } ++ PageItem *ite = m_doc->groupObjectsSelection(tmpSel); ++ if (ite) ++ { ++ QPainterPath clippath = m_currentClipPath; ++ clippath.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset()); ++ clippath.translate(-ite->xPos(), -ite->yPos()); ++ ite->PoLine.fromQPainterPath(clippath, true); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ // Comment out temporarily, there are some bad interactions between adjustItemSize() and ++ // resizeGroupToContents() since fixing resizing of multiple selections ++ //m_doc->adjustItemSize(ite, true); ++ m_doc->resizeGroupToContents(ite); ++ ite->OldB2 = ite->width(); ++ ite->OldH2 = ite->height(); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ applyMask(ite); ++ m_groupStack.top().Items.append(ite); ++ } ++ } ++ else ++ { ++ if (m_groupStack.count() != 0) ++ { ++ for (int dre = 0; dre < gElements.Items.count(); ++dre) ++ { ++ PageItem *ite = gElements.Items.at(dre); ++ applyMask(ite); ++ m_groupStack.top().Items.append(ite); ++ } ++ } ++ } ++ tmpSel->clear(); ++ } ++ else ++ { ++ if (m_groupStack.count() != 0) ++ { ++ for (int dre = 0; dre < gElements.Items.count(); ++dre) ++ { ++ PageItem *ite = gElements.Items.at(dre); ++ applyMask(ite); ++ m_groupStack.top().Items.append(ite); ++ } ++ } ++ } ++ } ++ } ++ if (m_clipPaths.count() != 0) ++ m_currentClipPath = m_clipPaths.pop(); ++} ++ ++void SlaOutputDev::beginTransparencyGroup(GfxState *state, POPPLER_CONST_070 double *bbox, GfxColorSpace * /*blendingColorSpace*/, GBool isolated, GBool knockout, GBool forSoftMask) ++{ ++// qDebug() << "SlaOutputDev::beginTransparencyGroup isolated:" << isolated << "knockout:" << knockout << "forSoftMask:" << forSoftMask; ++ pushGroup("", forSoftMask); ++ m_groupStack.top().isolated = isolated; ++} ++ ++void SlaOutputDev::paintTransparencyGroup(GfxState *state, POPPLER_CONST_070 double *bbox) ++{ ++// qDebug() << "SlaOutputDev::paintTransparencyGroup"; ++ if (m_groupStack.count() != 0) ++ { ++ if ((m_groupStack.top().Items.count() != 0) && (!m_groupStack.top().forSoftMask)) ++ { ++ PageItem *ite = m_groupStack.top().Items.last(); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ } ++ } ++} ++ ++void SlaOutputDev::endTransparencyGroup(GfxState *state) ++{ ++// qDebug() << "SlaOutputDev::endTransparencyGroup"; ++ if (m_groupStack.count() <= 0) ++ return; ++ ++ tmpSel->clear(); ++ ++ groupEntry gElements = m_groupStack.pop(); ++ if (gElements.Items.count() <= 0) ++ return; ++ ++ if (gElements.forSoftMask) ++ { ++ for (int dre = 0; dre < gElements.Items.count(); ++dre) ++ { ++ tmpSel->addItem(gElements.Items.at(dre), true); ++ m_Elements->removeAll(gElements.Items.at(dre)); ++ } ++ PageItem *ite = m_doc->groupObjectsSelection(tmpSel); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ ScPattern pat = ScPattern(); ++ pat.setDoc(m_doc); ++ m_doc->DoDrawing = true; ++ pat.pattern = ite->DrawObj_toImage(qMin(qMax(ite->width(), ite->height()), 500.0)); ++ pat.xoffset = 0; ++ pat.yoffset = 0; ++ m_doc->DoDrawing = false; ++ pat.width = ite->width(); ++ pat.height = ite->height(); ++ m_currentMaskPosition = QPointF(ite->xPos(), ite->yPos()); ++ ite->gXpos = 0; ++ ite->gYpos = 0; ++ ite->setXYPos(ite->gXpos, ite->gYpos, true); ++ pat.items.append(ite); ++ m_doc->Items->removeAll(ite); ++ QString id = QString("Pattern_from_PDF_%1S").arg(m_doc->docPatterns.count() + 1); ++ m_doc->addPattern(id, pat); ++ m_currentMask = id; ++ tmpSel->clear(); ++ return; ++ } ++ PageItem *ite; ++ for (int dre = 0; dre < gElements.Items.count(); ++dre) ++ { ++ tmpSel->addItem(gElements.Items.at(dre), true); ++ m_Elements->removeAll(gElements.Items.at(dre)); ++ } ++ if ((gElements.Items.count() != 1) || (gElements.isolated)) ++ ite = m_doc->groupObjectsSelection(tmpSel); ++ else ++ ite = gElements.Items.first(); ++ if (ite->isGroup()) ++ { ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ if (checkClip()) ++ { ++ QPainterPath clippath = m_currentClipPath; ++ clippath.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset()); ++ clippath.translate(-ite->xPos(), -ite->yPos()); ++ ite->PoLine.fromQPainterPath(clippath, true); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ // Comment out temporarily, there are some bad interactions between adjustItemSize() and ++ // resizeGroupToContents() since fixing resizing of multiple selections ++ //m_doc->adjustItemSize(ite, true); ++ m_doc->resizeGroupToContents(ite); ++ ite->OldB2 = ite->width(); ++ ite->OldH2 = ite->height(); ++ } ++ } ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ applyMask(ite); ++ m_groupStack.top().Items.append(ite); ++ } ++ ++ tmpSel->clear(); ++} ++ ++void SlaOutputDev::setSoftMask(GfxState * /*state*/, POPPLER_CONST_070 double * bbox, GBool alpha, Function *transferFunc, GfxColor * /*backdropColor*/) ++{ ++ if (m_groupStack.count() <= 0) ++ return; ++ ++ double lum = 0; ++ double lum2 = 0; ++ if (transferFunc) ++ transferFunc->transform(&lum, &lum2); ++ else ++ lum2 = lum; ++ if (lum == lum2) ++ m_groupStack.top().inverted = false; ++ else ++ m_groupStack.top().inverted = true; ++ m_groupStack.top().maskName = m_currentMask; ++ // Remember the mask's position as it might not align with the image to which the mask is later assigned. ++ m_groupStack.top().maskPos = m_currentMaskPosition; ++ m_groupStack.top().alpha = alpha; ++ if (m_groupStack.top().Items.count() != 0) ++ applyMask(m_groupStack.top().Items.last()); ++} ++ ++void SlaOutputDev::clearSoftMask(GfxState * /*state*/) ++{ ++ if (m_groupStack.count() != 0) ++ m_groupStack.top().maskName = ""; ++} ++ ++void SlaOutputDev::updateFillColor(GfxState *state) ++{ ++ CurrFillShade = 100; ++ CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &CurrFillShade); ++} ++ ++void SlaOutputDev::updateStrokeColor(GfxState *state) ++{ ++ CurrStrokeShade = 100; ++ CurrColorStroke = getColor(state->getStrokeColorSpace(), state->getStrokeColor(), &CurrStrokeShade); ++} ++ ++void SlaOutputDev::clip(GfxState *state) ++{ ++// qDebug() << "Clip"; ++ adjustClip(state, Qt::WindingFill); ++} ++ ++void SlaOutputDev::eoClip(GfxState *state) ++{ ++// qDebug() << "EoClip"; ++ adjustClip(state, Qt::OddEvenFill); ++} ++ ++void SlaOutputDev::adjustClip(GfxState *state, Qt::FillRule fillRule) ++{ ++ const double *ctm = state->getCTM(); ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ QString output = convertPath(state->getPath()); ++ if (output.isEmpty()) ++ return; ++ FPointArray out; ++ out.parseSVG(output); ++ out.svgClosePath(); ++ out.map(m_ctm); ++ if (checkClip()) ++ { ++ // "clip" (WindingFill) and "eoClip" (OddEvenFill) only the determine ++ // the fill rule of the new clipping path. The new clip should be the ++ // intersection of the old and new area. QPainterPath determines on ++ // its own which fill rule to use for the result. We should not loose ++ // this information. ++ QPainterPath pathN = out.toQPainterPath(false); ++ pathN.setFillRule(fillRule); ++ m_currentClipPath = intersection(pathN, m_currentClipPath); ++ } ++ else ++ m_currentClipPath = out.toQPainterPath(false); ++} ++ ++void SlaOutputDev::stroke(GfxState *state) ++{ ++// qDebug() << "Stroke"; ++ const double *ctm; ++ ctm = state->getCTM(); ++ double xCoor = m_doc->currentPage()->xOffset(); ++ double yCoor = m_doc->currentPage()->yOffset(); ++ QString output = convertPath(state->getPath()); ++ getPenState(state); ++ if ((m_Elements->count() != 0) && (output == Coords)) // Path is the same as in last fill ++ { ++ PageItem* ite = m_Elements->last(); ++ ite->setLineColor(CurrColorStroke); ++ ite->setLineShade(CurrStrokeShade); ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setLineWidth(state->getTransformedLineWidth()); ++ ite->setDashes(DashValues); ++ ite->setDashOffset(DashOffset); ++ ite->setLineTransparency(1.0 - state->getStrokeOpacity()); ++ } ++ else ++ { ++ FPointArray out; ++ out.parseSVG(output); ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ out.map(m_ctm); ++ FPoint wh = out.widthHeight(); ++ if ((out.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0))) ++ { ++ CurrColorStroke = getColor(state->getStrokeColorSpace(), state->getStrokeColor(), &CurrStrokeShade); ++ int z; ++ if (pathIsClosed) ++ z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, CurrColorStroke); ++ else ++ z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, CurrColorStroke); ++ PageItem* ite = m_doc->Items->at(z); ++ ite->PoLine = out.copy(); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setWidthHeight(wh.x(), wh.y()); ++ m_doc->adjustItemSize(ite); ++ if (m_Elements->count() != 0) ++ { ++ PageItem* lItem = m_Elements->last(); ++ if ((lItem->lineColor() == CommonStrings::None) && (lItem->PoLine == ite->PoLine)) ++ { ++ lItem->setLineColor(CurrColorStroke); ++ lItem->setLineWidth(state->getTransformedLineWidth()); ++ lItem->setLineShade(CurrStrokeShade); ++ lItem->setLineTransparency(1.0 - state->getStrokeOpacity()); ++ lItem->setLineBlendmode(getBlendMode(state)); ++ lItem->setLineEnd(PLineEnd); ++ lItem->setLineJoin(PLineJoin); ++ lItem->setDashes(DashValues); ++ lItem->setDashOffset(DashOffset); ++ lItem->setTextFlowMode(PageItem::TextFlowDisabled); ++ m_doc->Items->removeAll(ite); ++ } ++ else ++ { ++ ite->setLineShade(CurrStrokeShade); ++ ite->setLineTransparency(1.0 - state->getStrokeOpacity()); ++ ite->setLineBlendmode(getBlendMode(state)); ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setDashes(DashValues); ++ ite->setDashOffset(DashOffset); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ m_groupStack.top().Items.append(ite); ++ } ++ } ++ else ++ { ++ ite->setLineShade(CurrStrokeShade); ++ ite->setLineTransparency(1.0 - state->getStrokeOpacity()); ++ ite->setLineBlendmode(getBlendMode(state)); ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setDashes(DashValues); ++ ite->setDashOffset(DashOffset); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ m_groupStack.top().Items.append(ite); ++ } ++ } ++ } ++} ++ ++void SlaOutputDev::fill(GfxState *state) ++{ ++// qDebug() << "Fill"; ++ createFillItem(state, Qt::WindingFill); ++} ++ ++void SlaOutputDev::eoFill(GfxState *state) ++{ ++// qDebug() << "EoFill"; ++ createFillItem(state, Qt::OddEvenFill); ++} ++ ++void SlaOutputDev::createFillItem(GfxState *state, Qt::FillRule fillRule) ++{ ++ const double *ctm; ++ ctm = state->getCTM(); ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ double xCoor = m_doc->currentPage()->xOffset(); ++ double yCoor = m_doc->currentPage()->yOffset(); ++ FPointArray out; ++ QString output = convertPath(state->getPath()); ++ out.parseSVG(output); ++ out.map(m_ctm); ++ ++ // Clip the new path first and only add it if it is not empty. ++ QPainterPath path = out.toQPainterPath(false); ++ path.setFillRule(fillRule); ++ QPainterPath clippedPath = intersection(m_currentClipPath, path); ++ ++ // Undo the rotation of the clipping path as it is rotated together with the item. ++ double angle = m_ctm.map(QLineF(0, 0, 1, 0)).angle(); ++ QTransform mm; ++ mm.rotate(angle); ++ clippedPath = mm.map(clippedPath); ++ ++ Coords = output; ++ QRectF bbox = clippedPath.boundingRect(); ++ if (!clippedPath.isEmpty() && !bbox.isNull()) ++ { ++ CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &CurrFillShade); ++ int z; ++ if (pathIsClosed) ++ z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CurrColorFill, CommonStrings::None); ++ else ++ z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CurrColorFill, CommonStrings::None); ++ PageItem* ite = m_doc->Items->at(z); ++ ite->PoLine.fromQPainterPath(clippedPath, true); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setFillShade(CurrFillShade); ++ ite->setLineShade(100); ++ ite->setRotation(-angle); ++ // Only the new path has to be interpreted according to fillRule. QPainterPath ++ // could decide to create a final path according to the other rule. Thus ++ // we have to set this from the final path. ++ ite->setFillEvenOdd(clippedPath.fillRule() == Qt::OddEvenFill); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setWidthHeight(bbox.width(),bbox.height()); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ m_doc->adjustItemSize(ite); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ } ++} ++ ++GBool SlaOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) ++{ ++// qDebug() << "SlaOutputDev::axialShadedFill"; ++ double GrStartX; ++ double GrStartY; ++ double GrEndX; ++ double GrEndY; ++ int shade = 100; ++ POPPLER_CONST_070 Function *func = shading->getFunc(0); ++ VGradient FillGradient = VGradient(VGradient::linear); ++ FillGradient.clearStops(); ++ GfxColorSpace *color_space = shading->getColorSpace(); ++ if (func->getType() == 3) ++ { ++ StitchingFunction *stitchingFunc = (StitchingFunction*)func; ++ const double *bounds = stitchingFunc->getBounds(); ++ int num_funcs = stitchingFunc->getNumFuncs(); ++ double domain_min = stitchingFunc->getDomainMin(0); ++ double domain_max = stitchingFunc->getDomainMax(0); ++ if (fabs(domain_max - domain_min) < 1e-6) ++ { ++ domain_min = 0.0; ++ domain_max = 1.0; ++ } ++ // Add stops from all the stitched functions ++ for (int i = 0 ; i <= num_funcs ; i++) ++ { ++ GfxColor temp; ++ shading->getColor(bounds[i], &temp); ++ QString stopColor = getColor(color_space, &temp, &shade); ++ double stopPoint = (bounds[i] - domain_min) / (domain_max - domain_min); ++ FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor], m_doc, shade), stopPoint, 0.5, 1.0, stopColor, shade ); ++ } ++ } ++ else if ((func->getType() == 2) || (func->getType() == 0)) ++ { ++ GfxColor stop1; ++ shading->getColor(0.0, &stop1); ++ QString stopColor1 = getColor(color_space, &stop1, &shade); ++ FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor1], m_doc, shade), 0.0, 0.5, 1.0, stopColor1, shade ); ++ GfxColor stop2; ++ shading->getColor(1.0, &stop2); ++ QString stopColor2 = getColor(color_space, &stop2, &shade); ++ FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor2], m_doc, shade), 1.0, 0.5, 1.0, stopColor2, shade ); ++ } ++ shading->getCoords(&GrStartX, &GrStartY, &GrEndX, &GrEndY); ++ double xmin, ymin, xmax, ymax; ++ // get the clip region bbox ++ state->getClipBBox(&xmin, &ymin, &xmax, &ymax); ++ QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); ++ crect = crect.normalized(); ++ QPainterPath out; ++ out.addRect(crect); ++ if (checkClip()) ++ { ++ // Apply the clip path early to adjust the gradient vector to the ++ // smaller boundign box. ++ out = intersection(m_currentClipPath, out); ++ crect = out.boundingRect(); ++ } ++ const double *ctm = state->getCTM(); ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ FPointArray gr; ++ gr.addPoint(GrStartX, GrStartY); ++ gr.addPoint(GrEndX, GrEndY); ++ gr.map(m_ctm); ++ gr.translate(-crect.x(), -crect.y()); ++ ++ // Undo the rotation and translation of the gradient vector. ++ double angle = m_ctm.map(QLineF(0, 0, 1, 0)).angle(); ++ QTransform mm; ++ mm.rotate(angle); ++ out.translate(-crect.x(), -crect.y()); ++ out = mm.map(out); ++ QRectF bb = out.boundingRect(); ++ gr.map(mm); ++ gr.translate(-bb.left(), -bb.top()); ++ GrStartX = gr.point(0).x(); ++ GrStartY = gr.point(0).y(); ++ GrEndX = gr.point(1).x(); ++ GrEndY = gr.point(1).y(); ++ ++ double xCoor = m_doc->currentPage()->xOffset(); ++ double yCoor = m_doc->currentPage()->yOffset(); ++ QString output = QString("M %1 %2").arg(0.0).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(0.0); ++ output += QString("Z"); ++ pathIsClosed = true; ++ Coords = output; ++ int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), bb.width(), bb.height(), 0, CurrColorFill, CommonStrings::None); ++ PageItem* ite = m_doc->Items->at(z); ++ if (checkClip()) ++ { ++ ite->PoLine.fromQPainterPath(out, true); ++ ite->setFillEvenOdd(out.fillRule() == Qt::OddEvenFill); ++ } ++ ite->setRotation(-angle); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setFillShade(CurrFillShade); ++ ite->setLineShade(100); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ ite->GrType = 6; ++ if (!shading->getExtend0() || !shading->getExtend1()) ++ { ++ FillGradient.setRepeatMethod(VGradient::none); ++ ite->setGradientExtend(VGradient::none); ++ } ++ else ++ { ++ FillGradient.setRepeatMethod(VGradient::pad); ++ ite->setGradientExtend(VGradient::pad); ++ } ++ ite->fill_gradient = FillGradient; ++ ite->setGradientVector(GrStartX, GrStartY, GrEndX, GrEndY, 0, 0, 1, 0); ++ m_doc->adjustItemSize(ite); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ return gTrue; ++} ++ ++GBool SlaOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) ++{ ++// qDebug() << "SlaOutputDev::radialShadedFill"; ++ double GrStartX; ++ double GrStartY; ++ double GrEndX; ++ double GrEndY; ++ int shade = 100; ++ POPPLER_CONST_070 Function *func = shading->getFunc(0); ++ VGradient FillGradient = VGradient(VGradient::linear); ++ FillGradient.clearStops(); ++ GfxColorSpace *color_space = shading->getColorSpace(); ++ if (func->getType() == 3) ++ { ++ StitchingFunction *stitchingFunc = (StitchingFunction*)func; ++ const double *bounds = stitchingFunc->getBounds(); ++ int num_funcs = stitchingFunc->getNumFuncs(); ++ double domain_min = stitchingFunc->getDomainMin(0); ++ double domain_max = stitchingFunc->getDomainMax(0); ++ if (fabs(domain_max - domain_min) < 1e-6) ++ { ++ domain_min = 0.0; ++ domain_max = 1.0; ++ } ++ // Add stops from all the stitched functions ++ for (int i = 0 ; i <= num_funcs ; i++) ++ { ++ GfxColor temp; ++ shading->getColor(bounds[i], &temp); ++ QString stopColor = getColor(color_space, &temp, &shade); ++ double stopPoint = (bounds[i] - domain_min) / (domain_max - domain_min); ++ FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor], m_doc, shade), stopPoint, 0.5, 1.0, stopColor, shade ); ++ } ++ } ++ else if ((func->getType() == 2) || (func->getType() == 0)) ++ { ++ GfxColor stop1; ++ shading->getColor(0.0, &stop1); ++ QString stopColor1 = getColor(color_space, &stop1, &shade); ++ FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor1], m_doc, shade), 0.0, 0.5, 1.0, stopColor1, shade ); ++ GfxColor stop2; ++ shading->getColor(1.0, &stop2); ++ QString stopColor2 = getColor(color_space, &stop2, &shade); ++ FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor2], m_doc, shade), 1.0, 0.5, 1.0, stopColor2, shade ); ++ } ++ double r0, x1, y1, r1; ++ shading->getCoords(&GrStartX, &GrStartY, &r0, &x1, &y1, &r1); ++ double xmin, ymin, xmax, ymax; ++ // get the clip region bbox ++ state->getClipBBox(&xmin, &ymin, &xmax, &ymax); ++ QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); ++ crect = crect.normalized(); ++ double GrFocalX = x1; ++ double GrFocalY = y1; ++ GrEndX = GrFocalX + r1; ++ GrEndY = GrFocalY; ++ const double *ctm = state->getCTM(); ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ FPointArray gr; ++ gr.addPoint(GrStartX, GrStartY); ++ gr.addPoint(GrEndX, GrEndY); ++ gr.addPoint(GrFocalX, GrFocalY); ++ gr.map(m_ctm); ++ GrStartX = gr.point(0).x() - crect.x(); ++ GrStartY = gr.point(0).y() - crect.y(); ++ GrEndX = gr.point(1).x() - crect.x(); ++ GrEndY = gr.point(1).y() - crect.y(); ++ GrFocalX = gr.point(2).x() - crect.x(); ++ GrFocalY = gr.point(2).y() - crect.y(); ++ double xCoor = m_doc->currentPage()->xOffset(); ++ double yCoor = m_doc->currentPage()->yOffset(); ++ QString output = QString("M %1 %2").arg(0.0).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(0.0); ++ output += QString("Z"); ++ pathIsClosed = true; ++ Coords = output; ++ int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None); ++ PageItem* ite = m_doc->Items->at(z); ++ if (checkClip()) ++ { ++ QPainterPath out = m_currentClipPath; ++ out.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset()); ++ out.translate(-ite->xPos(), -ite->yPos()); ++ ite->PoLine.fromQPainterPath(out, true); ++ ite->setFillEvenOdd(out.fillRule() == Qt::OddEvenFill); ++ } ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setFillShade(CurrFillShade); ++ ite->setLineShade(100); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ ite->GrType = 7; ++ if (!shading->getExtend0() || !shading->getExtend1()) ++ { ++ FillGradient.setRepeatMethod(VGradient::none); ++ ite->setGradientExtend(VGradient::none); ++ } ++ else ++ { ++ FillGradient.setRepeatMethod(VGradient::pad); ++ ite->setGradientExtend(VGradient::pad); ++ } ++ ite->fill_gradient = FillGradient; ++ ite->setGradientVector(GrStartX, GrStartY, GrEndX, GrEndY, GrFocalX, GrFocalY, 1, 0); ++ m_doc->adjustItemSize(ite); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ return gTrue; ++} ++ ++GBool SlaOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) ++{ ++// qDebug() << "SlaOutputDev::gouraudTriangleShadedFill"; ++ double xCoor = m_doc->currentPage()->xOffset(); ++ double yCoor = m_doc->currentPage()->yOffset(); ++ double xmin, ymin, xmax, ymax; ++ // get the clip region bbox ++ state->getClipBBox(&xmin, &ymin, &xmax, &ymax); ++ QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); ++ crect = crect.normalized(); ++ QString output = QString("M %1 %2").arg(0.0).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(0.0); ++ output += QString("Z"); ++ pathIsClosed = true; ++ Coords = output; ++ const double *ctm = state->getCTM(); ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None); ++ PageItem* ite = m_doc->Items->at(z); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setFillShade(CurrFillShade); ++ ite->setLineShade(100); ++ ite->setFillEvenOdd(false); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ m_doc->adjustItemSize(ite); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ GfxColor color[3]; ++ double x0, y0, x1, y1, x2, y2; ++ for (int i = 0; i < shading->getNTriangles(); i++) ++ { ++ int shade = 100; ++ meshGradientPatch patchM; ++ shading->getTriangle(i, &x0, &y0, &color[0], &x1, &y1, &color[1], &x2, &y2, &color[2]); ++ patchM.BL.resetTo(FPoint(x0, y0)); ++ patchM.BL.shade = 100; ++ patchM.BL.transparency = 1.0; ++ patchM.BL.colorName = getColor(shading->getColorSpace(), &color[0], &shade); ++ patchM.BL.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.BL.colorName], m_doc, shade); ++ patchM.TL.resetTo(FPoint(x1, y1)); ++ patchM.TL.shade = 100; ++ patchM.TL.transparency = 1.0; ++ patchM.TL.colorName = getColor(shading->getColorSpace(), &color[1], &shade); ++ patchM.TL.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.TL.colorName], m_doc, shade); ++ patchM.TR.resetTo(FPoint(x2, y2)); ++ patchM.TR.shade = 100; ++ patchM.TR.transparency = 1.0; ++ patchM.TR.colorName = getColor(shading->getColorSpace(), &color[2], &shade); ++ patchM.TR.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.TR.colorName], m_doc, shade); ++ patchM.BR.resetTo(FPoint(x0, y0)); ++ patchM.BR.shade = 100; ++ patchM.BR.transparency = 1.0; ++ patchM.BR.colorName = getColor(shading->getColorSpace(), &color[0], &shade); ++ patchM.BR.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.BR.colorName], m_doc, shade); ++ patchM.TL.transform(m_ctm); ++ patchM.TL.moveRel(-crect.x(), -crect.y()); ++ patchM.TR.transform(m_ctm); ++ patchM.TR.moveRel(-crect.x(), -crect.y()); ++ patchM.BR.transform(m_ctm); ++ patchM.BR.moveRel(-crect.x(), -crect.y()); ++ patchM.BL.transform(m_ctm); ++ patchM.BL.moveRel(-crect.x(), -crect.y()); ++ ite->meshGradientPatches.append(patchM); ++ } ++ ite->GrType = 12; ++ return gTrue; ++} ++ ++GBool SlaOutputDev::patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading) ++{ ++// qDebug() << "SlaOutputDev::patchMeshShadedFill"; ++ double xCoor = m_doc->currentPage()->xOffset(); ++ double yCoor = m_doc->currentPage()->yOffset(); ++ double xmin, ymin, xmax, ymax; ++ // get the clip region bbox ++ state->getClipBBox(&xmin, &ymin, &xmax, &ymax); ++ QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); ++ crect = crect.normalized(); ++ QString output = QString("M %1 %2").arg(0.0).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(0.0); ++ output += QString("Z"); ++ pathIsClosed = true; ++ Coords = output; ++ const double *ctm = state->getCTM(); ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None); ++ PageItem* ite = m_doc->Items->at(z); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setFillShade(CurrFillShade); ++ ite->setLineShade(100); ++ ite->setFillEvenOdd(false); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ m_doc->adjustItemSize(ite); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ ite->meshGradientPatches.clear(); ++ for (int i = 0; i < shading->getNPatches(); i++) ++ { ++ int shade = 100; ++ const GfxPatch *patch = shading->getPatch(i); ++ GfxColor color; ++ meshGradientPatch patchM; ++ int u, v; ++ patchM.BL.resetTo(FPoint(patch->x[0][0], patch->y[0][0])); ++ patchM.BL.controlTop = FPoint(patch->x[0][1], patch->y[0][1]); ++ patchM.BL.controlRight = FPoint(patch->x[1][0], patch->y[1][0]); ++ patchM.BL.controlColor = FPoint(patch->x[1][1], patch->y[1][1]); ++ u = 0; ++ v = 0; ++ if (shading->isParameterized()) ++ { ++ shading->getParameterizedColor (patch->color[u][v].c[0], &color); ++ } ++ else ++ { ++ for (int k = 0; k < shading->getColorSpace()->getNComps(); k++) ++ { ++ color.c[k] = GfxColorComp (patch->color[u][v].c[k]); ++ } ++ } ++ patchM.BL.colorName = getColor(shading->getColorSpace(), &color, &shade); ++ patchM.BL.shade = 100; ++ patchM.BL.transparency = 1.0; ++ patchM.BL.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.BL.colorName], m_doc, shade); ++ ++ u = 0; ++ v = 1; ++ patchM.TL.resetTo(FPoint(patch->x[0][3], patch->y[0][3])); ++ patchM.TL.controlRight = FPoint(patch->x[1][3], patch->y[1][3]); ++ patchM.TL.controlBottom = FPoint(patch->x[0][2], patch->y[0][2]); ++ patchM.TL.controlColor = FPoint(patch->x[1][2], patch->y[1][2]); ++ if (shading->isParameterized()) ++ { ++ shading->getParameterizedColor (patch->color[u][v].c[0], &color); ++ } ++ else ++ { ++ for (int k = 0; k < shading->getColorSpace()->getNComps(); k++) ++ { ++ color.c[k] = GfxColorComp (patch->color[u][v].c[k]); ++ } ++ } ++ patchM.TL.colorName = getColor(shading->getColorSpace(), &color, &shade); ++ patchM.TL.shade = 100; ++ patchM.TL.transparency = 1.0; ++ patchM.TL.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.TL.colorName], m_doc, shade); ++ ++ u = 1; ++ v = 1; ++ patchM.TR.resetTo(FPoint(patch->x[3][3], patch->y[3][3])); ++ patchM.TR.controlBottom = FPoint(patch->x[3][2], patch->y[3][2]); ++ patchM.TR.controlLeft = FPoint(patch->x[2][3], patch->y[2][3]); ++ patchM.TR.controlColor = FPoint(patch->x[2][2], patch->y[2][2]); ++ if (shading->isParameterized()) ++ { ++ shading->getParameterizedColor (patch->color[u][v].c[0], &color); ++ } ++ else ++ { ++ for (int k = 0; k < shading->getColorSpace()->getNComps(); k++) ++ { ++ color.c[k] = GfxColorComp (patch->color[u][v].c[k]); ++ } ++ } ++ patchM.TR.colorName = getColor(shading->getColorSpace(), &color, &shade); ++ patchM.TR.shade = 100; ++ patchM.TR.transparency = 1.0; ++ patchM.TR.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.TR.colorName], m_doc, shade); ++ ++ u = 1; ++ v = 0; ++ patchM.BR.resetTo(FPoint(patch->x[3][0], patch->y[3][0])); ++ patchM.BR.controlLeft = FPoint(patch->x[2][0], patch->y[2][0]); ++ patchM.BR.controlTop = FPoint(patch->x[3][1], patch->y[3][1]); ++ patchM.BR.controlColor = FPoint(patch->x[2][1], patch->y[2][1]); ++ if (shading->isParameterized()) ++ { ++ shading->getParameterizedColor (patch->color[u][v].c[0], &color); ++ } ++ else ++ { ++ for (int k = 0; k < shading->getColorSpace()->getNComps(); k++) ++ { ++ color.c[k] = GfxColorComp (patch->color[u][v].c[k]); ++ } ++ } ++ patchM.BR.colorName = getColor(shading->getColorSpace(), &color, &shade); ++ patchM.BR.shade = 100; ++ patchM.BR.transparency = 1.0; ++ patchM.BR.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.BR.colorName], m_doc, shade); ++ ++ patchM.TL.transform(m_ctm); ++ patchM.TL.moveRel(-crect.x(), -crect.y()); ++ patchM.TR.transform(m_ctm); ++ patchM.TR.moveRel(-crect.x(), -crect.y()); ++ patchM.BR.transform(m_ctm); ++ patchM.BR.moveRel(-crect.x(), -crect.y()); ++ patchM.BL.transform(m_ctm); ++ patchM.BL.moveRel(-crect.x(), -crect.y()); ++ ite->meshGradientPatches.append(patchM); ++ } ++ ite->GrType = 12; ++ return gTrue; ++} ++ ++GBool SlaOutputDev::tilingPatternFill(GfxState *state, Gfx * /*gfx*/, Catalog *cat, Object *str, POPPLER_CONST_070 double *pmat, int paintType, int tilingType, Dict *resDict, POPPLER_CONST_070 double *mat, POPPLER_CONST_070 double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep) ++{ ++// qDebug() << "SlaOutputDev::tilingPatternFill"; ++ PDFRectangle box; ++ Gfx *gfx; ++ QString id; ++ PageItem *ite; ++ groupEntry gElements; ++ gElements.forSoftMask = gFalse; ++ gElements.alpha = gFalse; ++ gElements.inverted = false; ++ gElements.maskName = ""; ++ gElements.Items.clear(); ++ m_groupStack.push(gElements); ++ double width, height; ++ width = bbox[2] - bbox[0]; ++ height = bbox[3] - bbox[1]; ++ if (xStep != width || yStep != height) ++ return gFalse; ++ box.x1 = bbox[0]; ++ box.y1 = bbox[1]; ++ box.x2 = bbox[2]; ++ box.y2 = bbox[3]; ++ ++ const double *ctm = state->getCTM(); ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ QTransform mm = QTransform(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); ++ QTransform mmx = mm * m_ctm; ++ ++ gfx = new Gfx(pdfDoc, this, resDict, &box, nullptr); ++ inPattern++; ++ // Unset the clip path as it is unrelated to the pattern's coordinate space. ++ QPainterPath savedClip = m_currentClipPath; ++ m_currentClipPath = QPainterPath(); ++ gfx->display(str); ++ m_currentClipPath = savedClip; ++ inPattern--; ++ gElements = m_groupStack.pop(); ++ m_doc->m_Selection->clear(); ++// double pwidth = 0; ++// double pheight = 0; ++ if (gElements.Items.count() > 0) ++ { ++ for (int dre = 0; dre < gElements.Items.count(); ++dre) ++ { ++ m_doc->m_Selection->addItem(gElements.Items.at(dre), true); ++ m_Elements->removeAll(gElements.Items.at(dre)); ++ } ++ m_doc->itemSelection_FlipV(); ++ PageItem *ite; ++ if (m_doc->m_Selection->count() > 1) ++ ite = m_doc->groupObjectsSelection(); ++ else ++ ite = m_doc->m_Selection->itemAt(0); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ m_doc->m_Selection->clear(); ++ ScPattern pat = ScPattern(); ++ pat.setDoc(m_doc); ++ m_doc->DoDrawing = true; ++ pat.pattern = ite->DrawObj_toImage(qMin(qMax(ite->width(), ite->height()), 500.0)); ++ pat.xoffset = 0; ++ pat.yoffset = 0; ++ m_doc->DoDrawing = false; ++ pat.width = ite->width(); ++ pat.height = ite->height(); ++ // pwidth = ite->width(); ++ // pheight = ite->height(); ++ ite->gXpos = 0; ++ ite->gYpos = 0; ++ ite->setXYPos(ite->gXpos, ite->gYpos, true); ++ pat.items.append(ite); ++ m_doc->Items->removeAll(ite); ++ id = QString("Pattern_from_PDF_%1").arg(m_doc->docPatterns.count() + 1); ++ m_doc->addPattern(id, pat); ++ } ++ double xCoor = m_doc->currentPage()->xOffset(); ++ double yCoor = m_doc->currentPage()->yOffset(); ++ double xmin, ymin, xmax, ymax; ++ // get the clip region bbox ++ state->getClipBBox(&xmin, &ymin, &xmax, &ymax); ++ QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); ++ crect = crect.normalized(); ++ QString output = QString("M %1 %2").arg(0.0).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(0.0); ++ output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(crect.height()); ++ output += QString("L %1 %2").arg(0.0).arg(0.0); ++ output += QString("Z"); ++ pathIsClosed = true; ++ Coords = output; ++ int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None); ++ ite = m_doc->Items->at(z); ++ ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ double angle = m_ctm.map(QLineF(0, 0, 1, 0)).angle(); ++ ite->setRotation(-angle); ++ if (checkClip()) ++ { ++ QPainterPath outline = m_currentClipPath; ++ outline.translate(xCoor - ite->xPos(), yCoor - ite->yPos()); ++ // Undo the rotation of the clipping path as it is rotated together with the item. ++ QTransform mm; ++ mm.rotate(angle); ++ outline = mm.map(outline); ++ ite->PoLine.fromQPainterPath(outline, true); ++ ite->setFillEvenOdd(outline.fillRule() == Qt::OddEvenFill); ++ } ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setFillShade(CurrFillShade); ++ ite->setLineShade(100); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ ite->GrType = 8; ++ ite->setPattern(id); ++ ite->setPatternTransform(fabs(pmat[0]) * 100, fabs(pmat[3]) * 100, mmx.dx() - ctm[4], mmx.dy() - ctm[5], 0, -1 * pmat[1], pmat[2]); ++ m_doc->adjustItemSize(ite); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ delete gfx; ++ return gTrue; ++} ++ ++void SlaOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool interpolate, GBool inlineImg) ++{ ++// qDebug() << "Draw Image Mask"; ++ QImage * image = nullptr; ++ int invert_bit; ++ int row_stride; ++ int x, y, i, bit; ++ unsigned char *dest = nullptr; ++ unsigned char *buffer; ++ Guchar *pix; ++ ImageStream * imgStr = new ImageStream(str, width, 1, 1); ++ imgStr->reset(); ++#ifdef WORDS_BIGENDIAN ++ image = new QImage(width, height, QImage::Format_Mono); ++#else ++ image = new QImage(width, height, QImage::Format_MonoLSB); ++#endif ++ if (image == nullptr || image->isNull()) ++ { ++ delete imgStr; ++ delete image; ++ return; ++ } ++ invert_bit = invert ? 1 : 0; ++ buffer = image->bits(); ++ row_stride = image->bytesPerLine(); ++ for (y = 0; y < height; y++) ++ { ++ pix = imgStr->getLine(); ++ dest = buffer + y * row_stride; ++ i = 0; ++ bit = 0; ++ for (x = 0; x < width; x++) ++ { ++ if (bit == 0) ++ dest[i] = 0; ++ if (!(pix[x] ^ invert_bit)) ++ { ++#ifdef WORDS_BIGENDIAN ++ dest[i] |= (1 << (7 - bit)); ++#else ++ dest[i] |= (1 << bit); ++#endif ++ } ++ bit++; ++ if (bit > 7) ++ { ++ bit = 0; ++ i++; ++ } ++ } ++ } ++ QColor backColor = ScColorEngine::getShadeColorProof(m_doc->PageColors[CurrColorFill], m_doc, CurrFillShade); ++ QImage res = QImage(width, height, QImage::Format_ARGB32); ++ res.fill(backColor.rgb()); ++ unsigned char cc, cm, cy, ck; ++ for (int yi = 0; yi < res.height(); ++yi) ++ { ++ QRgb *t = (QRgb*)(res.scanLine( yi )); ++ for (int xi = 0; xi < res.width(); ++xi) ++ { ++ cc = qRed(*t); ++ cm = qGreen(*t); ++ cy = qBlue(*t); ++ ck = image->pixel(xi, yi); ++ if (ck == 0) ++ (*t) = qRgba(cc, cm, cy, 0); ++ else ++ (*t) = qRgba(cc, cm, cy, 255); ++ t++; ++ } ++ } ++ ++ createImageFrame(res, state, 3); ++ ++ imgStr->close(); ++ delete imgStr; ++ delete image; ++} ++ ++void SlaOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, Stream *maskStr, int maskWidth, int maskHeight, ++ GfxImageColorMap *maskColorMap, GBool maskInterpolate) ++{ ++// qDebug() << "SlaOutputDev::drawSoftMaskedImage Masked Image Components" << colorMap->getNumPixelComps(); ++ ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits()); ++ imgStr->reset(); ++ unsigned int *dest = nullptr; ++ unsigned char * buffer = new unsigned char[width * height * 4]; ++ QImage * image = nullptr; ++ for (int y = 0; y < height; y++) ++ { ++ dest = (unsigned int *)(buffer + y * 4 * width); ++ Guchar * pix = imgStr->getLine(); ++ colorMap->getRGBLine(pix, dest, width); ++ } ++ image = new QImage(buffer, width, height, QImage::Format_RGB32); ++ if (image == nullptr || image->isNull()) ++ { ++ delete imgStr; ++ delete[] buffer; ++ delete image; ++ return; ++ } ++ ImageStream *mskStr = new ImageStream(maskStr, maskWidth, maskColorMap->getNumPixelComps(), maskColorMap->getBits()); ++ mskStr->reset(); ++ Guchar *mdest = nullptr; ++ unsigned char * mbuffer = new unsigned char[maskWidth * maskHeight]; ++ memset(mbuffer, 0, maskWidth * maskHeight); ++ for (int y = 0; y < maskHeight; y++) ++ { ++ mdest = (Guchar *)(mbuffer + y * maskWidth); ++ Guchar * pix = mskStr->getLine(); ++ maskColorMap->getGrayLine(pix, mdest, maskWidth); ++ } ++ if ((maskWidth != width) || (maskHeight != height)) ++ *image = image->scaled(maskWidth, maskHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); ++ QImage res = image->convertToFormat(QImage::Format_ARGB32); ++ ++ int matteRc, matteGc, matteBc; ++ POPPLER_CONST_070 GfxColor *matteColor = maskColorMap->getMatteColor(); ++ if (matteColor != nullptr) ++ { ++ GfxRGB matteRgb; ++ colorMap->getColorSpace()->getRGB(matteColor, &matteRgb); ++ matteRc = qRound(colToDbl(matteRgb.r) * 255); ++ matteGc = qRound(colToDbl(matteRgb.g) * 255); ++ matteBc = qRound(colToDbl(matteRgb.b) * 255); ++ } ++ ++ unsigned char cr, cg, cb, ca; ++ int s = 0; ++ for (int yi=0; yi < res.height(); ++yi) ++ { ++ QRgb *t = (QRgb*)(res.scanLine( yi )); ++ for (int xi=0; xi < res.width(); ++xi) ++ { ++ cr = qRed(*t); ++ cg = qGreen(*t); ++ cb = qBlue(*t); ++ ca = mbuffer[s]; ++ if (matteColor != nullptr) ++ { ++ cr = unblendMatte(cr, ca, matteRc); ++ cg = unblendMatte(cg, ca, matteGc); ++ cb = unblendMatte(cb, ca, matteBc); ++ } ++ (*t) = qRgba(cr, cg, cb, ca); ++ s++; ++ t++; ++ } ++ } ++ ++ createImageFrame(res, state, 3); ++ ++ delete imgStr; ++ delete[] buffer; ++ delete image; ++ delete mskStr; ++ delete[] mbuffer; ++} ++ ++void SlaOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GBool maskInterpolate) ++{ ++// qDebug() << "SlaOutputDev::drawMaskedImage"; ++ ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits()); ++ imgStr->reset(); ++ unsigned int *dest = nullptr; ++ unsigned char * buffer = new unsigned char[width * height * 4]; ++ QImage * image = nullptr; ++ for (int y = 0; y < height; y++) ++ { ++ dest = (unsigned int *)(buffer + y * 4 * width); ++ Guchar * pix = imgStr->getLine(); ++ colorMap->getRGBLine(pix, dest, width); ++ } ++ image = new QImage(buffer, width, height, QImage::Format_RGB32); ++ if (image == nullptr || image->isNull()) ++ { ++ delete imgStr; ++ delete[] buffer; ++ delete image; ++ return; ++ } ++ ImageStream *mskStr = new ImageStream(maskStr, maskWidth, 1, 1); ++ mskStr->reset(); ++ Guchar *mdest = nullptr; ++ int invert_bit = maskInvert ? 1 : 0; ++ unsigned char * mbuffer = new unsigned char[maskWidth * maskHeight]; ++ memset(mbuffer, 0, maskWidth * maskHeight); ++ for (int y = 0; y < maskHeight; y++) ++ { ++ mdest = (Guchar *)(mbuffer + y * maskWidth); ++ Guchar * pix = mskStr->getLine(); ++ for (int x = 0; x < maskWidth; x++) ++ { ++ if (pix[x] ^ invert_bit) ++ *mdest++ = 0; ++ else ++ *mdest++ = 255; ++ } ++ } ++ if ((maskWidth != width) || (maskHeight != height)) ++ *image = image->scaled(maskWidth, maskHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); ++ QImage res = image->convertToFormat(QImage::Format_ARGB32); ++ unsigned char cc, cm, cy, ck; ++ int s = 0; ++ for (int yi=0; yi < res.height(); ++yi) ++ { ++ QRgb *t = (QRgb*)(res.scanLine( yi )); ++ for (int xi=0; xi < res.width(); ++xi) ++ { ++ cc = qRed(*t); ++ cm = qGreen(*t); ++ cy = qBlue(*t); ++ ck = mbuffer[s]; ++ (*t) = qRgba(cc, cm, cy, ck); ++ s++; ++ t++; ++ } ++ } ++ ++ createImageFrame(res, state, colorMap->getNumPixelComps()); ++ ++ delete imgStr; ++ delete[] buffer; ++ delete image; ++ delete mskStr; ++ delete[] mbuffer; ++} ++ ++void SlaOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, POPPLER_CONST_082 int* maskColors, GBool inlineImg) ++{ ++ ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits()); ++// qDebug() << "SlaOutputDev::drawImage Image Components" << colorMap->getNumPixelComps() << "Mask" << maskColors; ++ imgStr->reset(); ++ QImage* image = nullptr; ++ if (maskColors) ++ { ++ image = new QImage(width, height, QImage::Format_ARGB32); ++ for (int y = 0; y < height; y++) ++ { ++ QRgb *s = (QRgb*)(image->scanLine(y)); ++ Guchar *pix = imgStr->getLine(); ++ for (int x = 0; x < width; x++) ++ { ++ GfxRGB rgb; ++ colorMap->getRGB(pix, &rgb); ++ int Rc = qRound(colToDbl(rgb.r) * 255); ++ int Gc = qRound(colToDbl(rgb.g) * 255); ++ int Bc = qRound(colToDbl(rgb.b) * 255); ++ *s = qRgba(Rc, Gc, Bc, 255); ++ for (int i = 0; i < colorMap->getNumPixelComps(); ++i) ++ { ++ if (pix[i] < maskColors[2*i] * 255 || pix[i] > maskColors[2*i+1] * 255) ++ { ++ *s = *s | 0xff000000; ++ break; ++ } ++ } ++ s++; ++ pix += colorMap->getNumPixelComps(); ++ } ++ } ++ } ++ else ++ { ++ image = new QImage(width, height, QImage::Format_ARGB32); ++ for (int y = 0; y < height; y++) ++ { ++ QRgb *s = (QRgb*)(image->scanLine(y)); ++ Guchar *pix = imgStr->getLine(); ++ for (int x = 0; x < width; x++) ++ { ++ if (colorMap->getNumPixelComps() == 4) ++ { ++ GfxCMYK cmyk; ++ colorMap->getCMYK(pix, &cmyk); ++ int Cc = qRound(colToDbl(cmyk.c) * 255); ++ int Mc = qRound(colToDbl(cmyk.m) * 255); ++ int Yc = qRound(colToDbl(cmyk.y) * 255); ++ int Kc = qRound(colToDbl(cmyk.k) * 255); ++ *s = qRgba(Yc, Mc, Cc, Kc); ++ } ++ else ++ { ++ GfxRGB rgb; ++ colorMap->getRGB(pix, &rgb); ++ int Rc = qRound(colToDbl(rgb.r) * 255); ++ int Gc = qRound(colToDbl(rgb.g) * 255); ++ int Bc = qRound(colToDbl(rgb.b) * 255); ++ *s = qRgba(Rc, Gc, Bc, 255); ++ } ++ s++; ++ pix += colorMap->getNumPixelComps(); ++ } ++ } ++ } ++ ++ if (image != nullptr && !image->isNull()) { ++ createImageFrame(*image, state, colorMap->getNumPixelComps()); ++ } ++ ++ delete imgStr; ++ delete image; ++} ++ ++void SlaOutputDev::createImageFrame(QImage& image, GfxState *state, int numColorComponents) ++{ ++// qDebug() << "SlaOutputDev::createImageFrame"; ++ const double *ctm = state->getCTM(); ++ double xCoor = m_doc->currentPage()->xOffset(); ++ double yCoor = m_doc->currentPage()->yOffset(); ++ ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ double angle = m_ctm.map(QLineF(0, 0, 1, 0)).angle(); ++ QPointF torigin; ++ // In PDF all images considered squares with unit length that are transformed into the proper ++ // dimensions by ctm. ++ // A positive determinant retains orientation. Thus orientation is the same as in the PDF ++ // coordinate system (y-axis increases upwards). As Scribus uses the inverse orientation the ++ // image needs to be flipped (a horizontal flip is applied later). For a flipped image the ++ // corner that will be origin in Scribus is the upper right corner (1, 1) of the image. ++ // A negative determinant changes the orientation such that the image is already in the Scribus ++ // coordinate orientation and no flip is necessary. The origin will be the upper left corner (0, 1). ++ if (m_ctm.determinant() > 0) { ++ torigin = m_ctm.map(QPointF(1, 1)); ++ } else { ++ torigin = m_ctm.map(QPointF(0, 1)); ++ } ++ ++ // Determine the visible area of the picture after clipping it. If it is empty, no item ++ // needs to be created. ++ QPainterPath outline; ++ outline.addRect(0, 0, 1, 1); ++ outline = m_ctm.map(outline); ++ outline = intersection(outline, m_currentClipPath); ++ ++ if ((inPattern == 0) && (outline.isEmpty() || outline.boundingRect().isNull())) ++ return; ++ ++ // Determine the width and height of the image by undoing the rotation part ++ // of the CTM and applying the result to the unit square. ++ QTransform without_rotation; ++ without_rotation = m_ctm * without_rotation.rotate(angle); ++ QRectF trect_wr = without_rotation.mapRect(QRectF(0, 0, 1, 1)); ++ ++ int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Rectangle, xCoor + torigin.x(), yCoor + torigin.y(), trect_wr.width(), trect_wr.height(), 0, CommonStrings::None, CommonStrings::None); ++ PageItem* ite = m_doc->Items->at(z); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ m_doc->setRedrawBounding(ite); ++ ite->Clip = flattenPath(ite->PoLine, ite->Segments); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ ite->setFillShade(100); ++ ite->setLineShade(100); ++ ite->setFillEvenOdd(false); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ if (m_ctm.determinant() > 0) ++ { ++ ite->setRotation(-(angle - 180)); ++ ite->setImageFlippedH(true); ++ } ++ else ++ ite->setRotation(-angle); ++ m_doc->adjustItemSize(ite); ++ ++ if (numColorComponents == 4) ++ { ++ QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pdf_XXXXXX.tif"); ++ tempFile->setAutoRemove(false); ++ if (tempFile->open()) ++ { ++ QString fileName = getLongPathName(tempFile->fileName()); ++ if (!fileName.isEmpty()) ++ { ++ tempFile->close(); ++ ite->isInlineImage = true; ++ ite->isTempFile = true; ++ ite->AspectRatio = false; ++ ite->ScaleType = false; ++ TIFF* tif = TIFFOpen(fileName.toLocal8Bit().data(), "w"); ++ if (tif) ++ { ++ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, image.width()); ++ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, image.height()); ++ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); ++ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 4); ++ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); ++ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED); ++ TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); ++ for (int y = 0; y < image.height(); ++y) ++ { ++ TIFFWriteScanline(tif, image.scanLine(y), y); ++ } ++ TIFFClose(tif); ++ m_doc->loadPict(fileName, ite); ++ } ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ } ++ else ++ m_doc->Items->removeAll(ite); ++ } ++ delete tempFile; ++ } ++ else ++ { ++ QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pdf_XXXXXX.png"); ++ tempFile->setAutoRemove(false); ++ if (tempFile->open()) ++ { ++ QString fileName = getLongPathName(tempFile->fileName()); ++ if (!fileName.isEmpty()) ++ { ++ tempFile->close(); ++ ite->isInlineImage = true; ++ ite->isTempFile = true; ++ ite->AspectRatio = false; ++ ite->ScaleType = false; ++ image.save(fileName, "PNG"); ++ m_doc->loadPict(fileName, ite); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ } ++ else ++ m_doc->Items->removeAll(ite); ++ } ++ delete tempFile; ++ } ++ if (inPattern == 0) ++ { ++ outline.translate(xCoor - ite->xPos(), yCoor - ite->yPos()); ++ // Undo the rotation of the clipping path as it is rotated together with the iamge. ++ QTransform mm; ++ mm.rotate(-ite->rotation()); ++ outline = mm.map(outline); ++ ite->PoLine.fromQPainterPath(outline, true); ++ ite->setFillEvenOdd(outline.fillRule() == Qt::OddEvenFill); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ ite->ScaleType = true; ++ m_doc->adjustItemSize(ite); ++ ite->OldB2 = ite->width(); ++ ite->OldH2 = ite->height(); ++ ite->updateClip(); ++ } ++} ++ ++void SlaOutputDev::beginMarkedContent(POPPLER_CONST char *name, Object *dictRef) ++{ ++ mContent mSte; ++ mSte.name = QString(name); ++ mSte.ocgName = ""; ++ if (importerFlags & LoadSavePlugin::lfCreateDoc) ++ { ++ if (dictRef->isNull()) ++ return; ++ Object dictObj; ++ Dict *dict; ++ Object dictType; ++ OCGs *contentConfig = catalog->getOptContentConfig(); ++ OptionalContentGroup *oc; ++ if (dictRef->isRef()) ++ { ++ oc = contentConfig->findOcgByRef(dictRef->getRef()); ++ if (oc) ++ { ++// qDebug() << "Begin OCG Content (Ref) with Name " << QString(name) << "Layer" << UnicodeParsedString(oc->getName()); ++ m_doc->setActiveLayer(UnicodeParsedString(oc->getName())); ++ mSte.ocgName = UnicodeParsedString(oc->getName()); ++ } ++ } ++ else ++ { ++ dictObj = dictRef->fetch(xref); ++ if (!dictObj.isDict()) ++ return; ++ dict = dictObj.getDict(); ++ dictType = dict->lookup("Type"); ++ if (dictType.isName("OCG")) ++ { ++ oc = contentConfig->findOcgByRef(dictRef->getRef()); ++ if (oc) ++ { ++ // qDebug() << "Begin OCG Content with Name " << UnicodeParsedString(oc->getName()); ++ m_doc->setActiveLayer(UnicodeParsedString(oc->getName())); ++ mSte.ocgName = UnicodeParsedString(oc->getName()); ++ } ++ } ++ } ++ } ++ m_mcStack.push(mSte); ++} ++ ++void SlaOutputDev::beginMarkedContent(POPPLER_CONST char *name, Dict *properties) ++{ ++// qDebug() << "Begin Marked Content with Name " << QString(name); ++ QString nam = QString(name); ++ mContent mSte; ++ mSte.name = nam; ++ mSte.ocgName = ""; ++ m_mcStack.push(mSte); ++ if (importerFlags & LoadSavePlugin::lfCreateDoc) ++ { ++ if (nam == "Layer") // Handle Adobe Illustrator Layer command ++ { ++ if (layersSetByOCG) ++ return; ++ QString lName = QString("Layer_%1").arg(layerNum + 1); ++ Object obj = properties->lookup((char*) "Title"); ++ if (obj.isString()) ++ lName = QString(obj.getString()->getCString()); ++ for (ScLayers::iterator it = m_doc->Layers.begin(); it != m_doc->Layers.end(); ++it) ++ { ++ if (it->Name == lName) ++ { ++ m_doc->setActiveLayer(lName); ++ return; ++ } ++ } ++ layerNum++; ++ if (!firstLayer) ++ currentLayer = m_doc->addLayer(lName, true); ++ firstLayer = false; ++ ++ obj = properties->lookup((char*) "Visible"); ++ if (obj.isBool()) ++ m_doc->setLayerVisible(currentLayer, obj.getBool()); ++ obj = properties->lookup((char*) "Editable"); ++ if (obj.isBool()) ++ m_doc->setLayerLocked(currentLayer, !obj.getBool()); ++ obj = properties->lookup((char*) "Printed"); ++ if (obj.isBool()) ++ m_doc->setLayerPrintable(currentLayer, obj.getBool()); ++ obj = properties->lookup((char*)"Color"); ++ if (obj.isArray()) ++ { ++ Object obj1; ++ obj1 = obj.arrayGet(0); ++ int r = obj1.getNum() / 256; ++ obj1 = obj.arrayGet(1); ++ int g = obj1.getNum() / 256; ++ obj1 = obj.arrayGet(2); ++ int b = obj1.getNum() / 256; ++ m_doc->setLayerMarker(currentLayer, QColor(r, g, b)); ++ } ++ } ++ } ++} ++ ++void SlaOutputDev::endMarkedContent(GfxState *state) ++{ ++// qDebug() << "End Marked Content"; ++ if (m_mcStack.count() > 0) ++ { ++ mContent mSte = m_mcStack.pop(); ++ if (importerFlags & LoadSavePlugin::lfCreateDoc) ++ { ++ if (mSte.name == "OC") ++ { ++ for (ScLayers::iterator it = m_doc->Layers.begin(); it != m_doc->Layers.end(); ++it) ++ { ++ if (it->Name == mSte.ocgName) ++ { ++ m_doc->setActiveLayer(mSte.ocgName); ++ return; ++ } ++ } ++ } ++ } ++ } ++} ++ ++void SlaOutputDev::markPoint(POPPLER_CONST char *name) ++{ ++// qDebug() << "Begin Marked Point with Name " << QString(name); ++} ++ ++void SlaOutputDev::markPoint(POPPLER_CONST char *name, Dict *properties) ++{ ++// qDebug() << "Begin Marked Point with Name " << QString(name) << "and Properties"; ++ beginMarkedContent(name, properties); ++} ++ ++void SlaOutputDev::updateFont(GfxState *state) ++{ ++ GfxFont *gfxFont; ++ GfxFontLoc *fontLoc; ++ GfxFontType fontType; ++ SlaOutFontFileID *id; ++ SplashFontFile *fontFile; ++ SplashFontSrc *fontsrc = nullptr; ++ FoFiTrueType *ff; ++ Object refObj, strObj; ++ GooString *fileName; ++ char *tmpBuf; ++ int tmpBufLen = 0; ++ int *codeToGID; ++ const double *textMat; ++ double m11, m12, m21, m22, fontSize; ++ SplashCoord mat[4]; ++ int n = 0; ++ int faceIndex = 0; ++ SplashCoord matrix[6]; ++ ++ m_font = nullptr; ++ fileName = nullptr; ++ tmpBuf = nullptr; ++ fontLoc = nullptr; ++ ++ if (!(gfxFont = state->getFont())) { ++ goto err1; ++ } ++ fontType = gfxFont->getType(); ++ if (fontType == fontType3) { ++ goto err1; ++ } ++ ++ // check the font file cache ++ id = new SlaOutFontFileID(gfxFont->getID()); ++ if ((fontFile = m_fontEngine->getFontFile(id))) ++ delete id; ++ else ++ { ++ if (!(fontLoc = gfxFont->locateFont(xref, nullptr))) ++ { ++ error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'", ++ gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); ++ goto err2; ++ } ++ ++ // embedded font ++ if (fontLoc->locType == gfxFontLocEmbedded) ++ { ++ // if there is an embedded font, read it to memory ++ tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen); ++ if (! tmpBuf) ++ goto err2; ++ ++ // external font ++ } ++ else ++ { // gfxFontLocExternal ++ fileName = fontLoc->path; ++ fontType = fontLoc->fontType; ++ } ++ ++ fontsrc = new SplashFontSrc; ++ if (fileName) ++ fontsrc->setFile(fileName, gFalse); ++ else ++ fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue); ++ ++ // load the font file ++ switch (fontType) { ++ case fontType1: ++ if (!(fontFile = m_fontEngine->loadType1Font( ++ id, ++ fontsrc, ++ (const char **)((Gfx8BitFont *) gfxFont)->getEncoding()))) ++ { ++ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", ++ gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); ++ goto err2; ++ } ++ break; ++ case fontType1C: ++ if (!(fontFile = m_fontEngine->loadType1CFont( ++ id, ++ fontsrc, ++ (const char **)((Gfx8BitFont *) gfxFont)->getEncoding()))) ++ { ++ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", ++ gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); ++ goto err2; ++ } ++ break; ++ case fontType1COT: ++ if (!(fontFile = m_fontEngine->loadOpenTypeT1CFont( ++ id, ++ fontsrc, ++ (const char **)((Gfx8BitFont *) gfxFont)->getEncoding()))) ++ { ++ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", ++ gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); ++ goto err2; ++ } ++ break; ++ case fontTrueType: ++ case fontTrueTypeOT: ++ if (fileName) ++ ff = FoFiTrueType::load(fileName->getCString()); ++ else ++ ff = FoFiTrueType::make(tmpBuf, tmpBufLen); ++ if (ff) ++ { ++ codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff); ++ n = 256; ++ delete ff; ++ } ++ else ++ { ++ codeToGID = nullptr; ++ n = 0; ++ } ++ if (!(fontFile = m_fontEngine->loadTrueTypeFont( ++ id, ++ fontsrc, ++ codeToGID, n))) ++ { ++ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", ++ gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); ++ goto err2; ++ } ++ break; ++ case fontCIDType0: ++ case fontCIDType0C: ++ if (!(fontFile = m_fontEngine->loadCIDFont( ++ id, ++ fontsrc))) ++ { ++ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", ++ gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); ++ goto err2; ++ } ++ break; ++ case fontCIDType0COT: ++ if (((GfxCIDFont *) gfxFont)->getCIDToGID()) ++ { ++ n = ((GfxCIDFont *) gfxFont)->getCIDToGIDLen(); ++ codeToGID = (int *) gmallocn(n, sizeof(*codeToGID)); ++ memcpy(codeToGID, ((GfxCIDFont *) gfxFont)->getCIDToGID(), n * sizeof(*codeToGID)); ++ } ++ else ++ { ++ codeToGID = nullptr; ++ n = 0; ++ } ++ if (!(fontFile = m_fontEngine->loadOpenTypeCFFFont( ++ id, ++ fontsrc, ++ codeToGID, n))) ++ { ++ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", ++ gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); ++ goto err2; ++ } ++ break; ++ case fontCIDType2: ++ case fontCIDType2OT: ++ codeToGID = nullptr; ++ n = 0; ++ if (((GfxCIDFont *) gfxFont)->getCIDToGID()) ++ { ++ n = ((GfxCIDFont *) gfxFont)->getCIDToGIDLen(); ++ if (n) ++ { ++ codeToGID = (int *)gmallocn(n, sizeof(*codeToGID)); ++ memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(), n * sizeof(*codeToGID)); ++ } ++ } ++ else ++ { ++ if (fileName) ++ ff = FoFiTrueType::load(fileName->getCString()); ++ else ++ ff = FoFiTrueType::make(tmpBuf, tmpBufLen); ++ if (! ff) ++ goto err2; ++ codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n); ++ delete ff; ++ } ++ if (!(fontFile = m_fontEngine->loadTrueTypeFont( ++ id, ++ fontsrc, ++ codeToGID, n, faceIndex))) ++ { ++ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", ++ gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); ++ goto err2; ++ } ++ break; ++ default: ++ // this shouldn't happen ++ goto err2; ++ } ++ } ++ // get the font matrix ++ textMat = state->getTextMat(); ++ fontSize = state->getFontSize(); ++ m11 = textMat[0] * fontSize * state->getHorizScaling(); ++ m12 = textMat[1] * fontSize * state->getHorizScaling(); ++ m21 = textMat[2] * fontSize; ++ m22 = textMat[3] * fontSize; ++ matrix[0] = 1; ++ matrix[1] = 0; ++ matrix[2] = 0; ++ matrix[3] = 1; ++ matrix[4] = 0; ++ matrix[5] = 0; ++ // create the scaled font ++ mat[0] = m11; ++ mat[1] = -m12; ++ mat[2] = m21; ++ mat[3] = -m22; ++ m_font = m_fontEngine->getFont(fontFile, mat, matrix); ++ ++ delete fontLoc; ++ if (fontsrc && !fontsrc->isFile) ++ fontsrc->unref(); ++ return; ++ ++err2: ++ delete id; ++ delete fontLoc; ++err1: ++ if (fontsrc && !fontsrc->isFile) ++ fontsrc->unref(); ++} ++ ++void SlaOutputDev::drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, CharCode code, int nBytes, POPPLER_CONST_082 Unicode *u, int uLen) ++{ ++// qDebug() << "SlaOutputDev::drawChar code:" << code << "bytes:" << nBytes << "Unicode:" << u << "ulen:" << uLen << "render:" << state->getRender(); ++ double x1, y1, x2, y2; ++ updateFont(state); ++ if (!m_font) ++ return; ++ ++ // PDF 1.7 Section 9.3.6 defines eight text rendering modes. ++ // 0 - Fill ++ // 1 - Stroke ++ // 2 - First fill and then stroke ++ // 3 - Invisible ++ // 4 - Fill and use as a clipping path ++ // 5 - Stroke and use as a clipping path ++ // 6 - First fill, then stroke and add as a clipping path ++ // 7 - Only use as a clipping path. ++ // TODO Implement the clipping operations. At least the characters are shown. ++ int textRenderingMode = state->getRender(); ++ // Invisible or only used for clipping ++ if (textRenderingMode == 3) ++ return; ++ if (textRenderingMode < 8) ++ { ++ SplashPath * fontPath; ++ fontPath = m_font->getGlyphPath(code); ++ if (fontPath) ++ { ++ QPainterPath qPath; ++ qPath.setFillRule(Qt::WindingFill); ++ for (int i = 0; i < fontPath->getLength(); ++i) ++ { ++ Guchar f; ++ fontPath->getPoint(i, &x1, &y1, &f); ++ if (f & splashPathFirst) ++ qPath.moveTo(x1,y1); ++ else if (f & splashPathCurve) ++ { ++ double x3, y3; ++ ++i; ++ fontPath->getPoint(i, &x2, &y2, &f); ++ ++i; ++ fontPath->getPoint(i, &x3, &y3, &f); ++ qPath.cubicTo(x1,y1,x2,y2,x3,y3); ++ } ++ else ++ qPath.lineTo(x1,y1); ++ if (f & splashPathLast) ++ qPath.closeSubpath(); ++ } ++ const double *ctm = state->getCTM(); ++ m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); ++ double xCoor = m_doc->currentPage()->xOffset(); ++ double yCoor = m_doc->currentPage()->yOffset(); ++ FPointArray textPath; ++ textPath.fromQPainterPath(qPath); ++ FPoint wh = textPath.widthHeight(); ++ if (textRenderingMode > 3) ++ { ++ QTransform mm; ++ mm.scale(1, -1); ++ mm.translate(x, -y); ++ // Remember the glyph for later clipping ++ m_clipTextPath.addPath(m_ctm.map(mm.map(qPath))); ++ } ++ if ((textPath.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0)) && (textRenderingMode != 7)) ++ { ++ int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CommonStrings::None, CommonStrings::None); ++ PageItem* ite = m_doc->Items->at(z); ++ QTransform mm; ++ mm.scale(1, -1); ++ mm.translate(x, -y); ++ textPath.map(mm); ++ textPath.map(m_ctm); ++ ite->PoLine = textPath.copy(); ++ ite->ClipEdited = true; ++ ite->FrameType = 3; ++ ite->setLineEnd(PLineEnd); ++ ite->setLineJoin(PLineJoin); ++ ite->setTextFlowMode(PageItem::TextFlowDisabled); ++ // Fill text rendering modes. See above ++ if (textRenderingMode == 0 || textRenderingMode == 2 || textRenderingMode == 4 || textRenderingMode == 6) ++ { ++ CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &CurrFillShade); ++ ite->setFillColor(CurrColorFill); ++ ite->setFillShade(CurrFillShade); ++ ite->setFillEvenOdd(false); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ } ++ // Stroke text rendering modes. See above ++ if (textRenderingMode == 1 || textRenderingMode == 2 || textRenderingMode == 5 || textRenderingMode == 6) ++ { ++ CurrColorStroke = getColor(state->getStrokeColorSpace(), state->getStrokeColor(), &CurrStrokeShade); ++ ite->setLineColor(CurrColorStroke); ++ ite->setLineWidth(state->getTransformedLineWidth()); ++ ite->setLineTransparency(1.0 - state->getStrokeOpacity()); ++ ite->setLineBlendmode(getBlendMode(state)); ++ ite->setLineShade(CurrStrokeShade); ++ } ++ m_doc->adjustItemSize(ite); ++ m_Elements->append(ite); ++ if (m_groupStack.count() != 0) ++ { ++ m_groupStack.top().Items.append(ite); ++ applyMask(ite); ++ } ++ delete fontPath; ++ } ++ } ++ } ++} ++ ++GBool SlaOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, POPPLER_CONST_082 Unicode *u, int uLen) ++{ ++// qDebug() << "beginType3Char"; ++ GfxFont *gfxFont; ++ if (!(gfxFont = state->getFont())) ++ return gTrue; ++ if (gfxFont->getType() != fontType3) ++ return gTrue; ++ F3Entry f3e; ++ f3e.colored = false; ++ m_F3Stack.push(f3e); ++ pushGroup(); ++ return gFalse; ++} ++ ++void SlaOutputDev::endType3Char(GfxState *state) ++{ ++// qDebug() << "endType3Char"; ++ F3Entry f3e = m_F3Stack.pop(); ++ groupEntry gElements = m_groupStack.pop(); ++ m_doc->m_Selection->clear(); ++ if (gElements.Items.count() > 0) ++ { ++ m_doc->m_Selection->delaySignalsOn(); ++ for (int dre = 0; dre < gElements.Items.count(); ++dre) ++ { ++ m_doc->m_Selection->addItem(gElements.Items.at(dre), true); ++ m_Elements->removeAll(gElements.Items.at(dre)); ++ } ++ PageItem *ite; ++ if (m_doc->m_Selection->count() > 1) ++ ite = m_doc->groupObjectsSelection(); ++ else ++ ite = m_doc->m_Selection->itemAt(0); ++ if (!f3e.colored) ++ { ++ m_doc->itemSelection_SetItemBrush(CurrColorFill); ++ m_doc->itemSelection_SetItemBrushShade(CurrFillShade); ++ m_doc->itemSelection_SetItemFillTransparency(1.0 - state->getFillOpacity()); ++ m_doc->itemSelection_SetItemFillBlend(getBlendMode(state)); ++ } ++ m_Elements->append(ite); ++ m_doc->m_Selection->clear(); ++ m_doc->m_Selection->delaySignalsOff(); ++ } ++} ++ ++void SlaOutputDev::type3D0(GfxState * /*state*/, double /*wx*/, double /*wy*/) ++{ ++// qDebug() << "type3D0"; ++ if (m_F3Stack.count() > 0) ++ m_F3Stack.top().colored = true; ++} ++ ++void SlaOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) ++{ ++// qDebug() << "type3D1"; ++ if (m_F3Stack.count() > 0) ++ m_F3Stack.top().colored = false; ++} ++ ++void SlaOutputDev::beginTextObject(GfxState *state) ++{ ++ pushGroup(); ++} ++ ++void SlaOutputDev::endTextObject(GfxState *state) ++{ ++// qDebug() << "SlaOutputDev::endTextObject"; ++ if (!m_clipTextPath.isEmpty()) ++ { ++ m_currentClipPath = intersection(m_currentClipPath, m_clipTextPath); ++ m_clipTextPath = QPainterPath(); ++ } ++ if (m_groupStack.count() != 0) ++ { ++ groupEntry gElements = m_groupStack.pop(); ++ tmpSel->clear(); ++ if (gElements.Items.count() > 0) ++ { ++ for (int dre = 0; dre < gElements.Items.count(); ++dre) ++ { ++ tmpSel->addItem(gElements.Items.at(dre), true); ++ m_Elements->removeAll(gElements.Items.at(dre)); ++ } ++ PageItem *ite; ++ if (gElements.Items.count() != 1) ++ ite = m_doc->groupObjectsSelection(tmpSel); ++ else ++ ite = gElements.Items.first(); ++ ite->setGroupClipping(false); ++ ite->setFillTransparency(1.0 - state->getFillOpacity()); ++ ite->setFillBlendmode(getBlendMode(state)); ++ for (int as = 0; as < tmpSel->count(); ++as) ++ { ++ m_Elements->append(tmpSel->itemAt(as)); ++ } ++ if (m_groupStack.count() != 0) ++ applyMask(ite); ++ } ++ if (m_groupStack.count() != 0) ++ { ++ for (int as = 0; as < tmpSel->count(); ++as) ++ { ++ m_groupStack.top().Items.append(tmpSel->itemAt(as)); ++ } ++ } ++ tmpSel->clear(); ++ } ++} ++ ++QString SlaOutputDev::getColor(GfxColorSpace *color_space, POPPLER_CONST_070 GfxColor *color, int *shade) ++{ ++ QString fNam; ++ QString namPrefix = "FromPDF"; ++ ScColor tmp; ++ tmp.setSpotColor(false); ++ tmp.setRegistrationColor(false); ++ *shade = 100; ++ /*if (m_F3Stack.count() > 0) ++ { ++ if (!m_F3Stack.top().colored) ++ return "Black"; ++ }*/ ++ ++ if ((color_space->getMode() == csDeviceRGB) || (color_space->getMode() == csCalRGB)) ++ { ++ GfxRGB rgb; ++ color_space->getRGB(color, &rgb); ++ double Rc = colToDbl(rgb.r); ++ double Gc = colToDbl(rgb.g); ++ double Bc = colToDbl(rgb.b); ++ tmp.setRgbColorF(Rc, Gc, Bc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ } ++ else if (color_space->getMode() == csDeviceCMYK) ++ { ++ GfxCMYK cmyk; ++ color_space->getCMYK(color, &cmyk); ++ double Cc = colToDbl(cmyk.c); ++ double Mc = colToDbl(cmyk.m); ++ double Yc = colToDbl(cmyk.y); ++ double Kc = colToDbl(cmyk.k); ++ tmp.setCmykColorF(Cc, Mc, Yc, Kc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ } ++ else if ((color_space->getMode() == csCalGray) || (color_space->getMode() == csDeviceGray)) ++ { ++ GfxGray gray; ++ color_space->getGray(color, &gray); ++ double Kc = 1.0 - colToDbl(gray); ++ tmp.setCmykColorF(0, 0, 0, Kc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ } ++ else if (color_space->getMode() == csSeparation) ++ { ++ GfxSeparationColorSpace* sepColorSpace = (GfxSeparationColorSpace*) color_space; ++ GfxColorSpace* altColorSpace = sepColorSpace->getAlt(); ++ QString name = QString(sepColorSpace->getName()->getCString()); ++ bool isRegistrationColor = (name == "All"); ++ if (isRegistrationColor) ++ { ++ tmp.setCmykColorF(1.0, 1.0, 1.0, 1.0); ++ tmp.setRegistrationColor(true); ++ name = "Registration"; ++ } ++ else if ((altColorSpace->getMode() == csDeviceRGB) || (altColorSpace->getMode() == csCalRGB)) ++ { ++ double x = 1.0; ++ double comps[gfxColorMaxComps]; ++ sepColorSpace->getFunc()->transform(&x, comps); ++ tmp.setRgbColorF(comps[0], comps[1], comps[2]); ++ } ++ else if ((altColorSpace->getMode() == csCalGray) || (altColorSpace->getMode() == csDeviceGray)) ++ { ++ double x = 1.0; ++ double comps[gfxColorMaxComps]; ++ sepColorSpace->getFunc()->transform(&x, comps); ++ tmp.setCmykColorF(0.0, 0.0, 0.0, 1.0 - comps[0]); ++ } ++ else if (altColorSpace->getMode() == csLab) ++ { ++ double x = 1.0; ++ double comps[gfxColorMaxComps]; ++ sepColorSpace->getFunc()->transform(&x, comps); ++ tmp.setLabColor(comps[0], comps[1], comps[2]); ++ } ++ else ++ { ++ GfxCMYK cmyk; ++ color_space->getCMYK(color, &cmyk); ++ double Cc = colToDbl(cmyk.c); ++ double Mc = colToDbl(cmyk.m); ++ double Yc = colToDbl(cmyk.y); ++ double Kc = colToDbl(cmyk.k); ++ tmp.setCmykColorF(Cc, Mc, Yc, Kc); ++ } ++ tmp.setSpotColor(true); ++ ++ fNam = m_doc->PageColors.tryAddColor(name, tmp); ++ *shade = qRound(colToDbl(color->c[0]) * 100); ++ } ++ else ++ { ++ GfxRGB rgb; ++ color_space->getRGB(color, &rgb); ++ double Rc = colToDbl(rgb.r); ++ double Gc = colToDbl(rgb.g); ++ double Bc = colToDbl(rgb.b); ++ tmp.setRgbColorF(Rc, Gc, Bc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++// qDebug() << "update fill color other colorspace" << color_space->getMode() << "treating as rgb" << Rc << Gc << Bc; ++ } ++ if (fNam == namPrefix+tmp.name()) ++ m_importedColors->append(fNam); ++ return fNam; ++} ++ ++QString SlaOutputDev::getAnnotationColor(const AnnotColor *color) ++{ ++ QString fNam; ++ QString namPrefix = "FromPDF"; ++ ScColor tmp; ++ tmp.setSpotColor(false); ++ tmp.setRegistrationColor(false); ++ if (color->getSpace() == AnnotColor::colorTransparent) ++ return CommonStrings::None; ++ if (color->getSpace() == AnnotColor::colorRGB) ++ { ++ const double *color_data = color->getValues(); ++ double Rc = color_data[0]; ++ double Gc = color_data[1]; ++ double Bc = color_data[2]; ++ tmp.setRgbColorF(Rc, Gc, Bc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ } ++ else if (color->getSpace() == AnnotColor::colorCMYK) ++ { ++ const double *color_data = color->getValues(); ++ double Cc = color_data[0]; ++ double Mc = color_data[1]; ++ double Yc = color_data[2]; ++ double Kc = color_data[3]; ++ tmp.setCmykColorF(Cc, Mc, Yc, Kc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ } ++ else if (color->getSpace() == AnnotColor::colorGray) ++ { ++ const double *color_data = color->getValues(); ++ double Kc = 1.0 - color_data[0]; ++ tmp.setCmykColorF(0, 0, 0, Kc); ++ fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); ++ } ++ if (fNam == namPrefix+tmp.name()) ++ m_importedColors->append(fNam); ++ return fNam; ++} ++ ++QString SlaOutputDev::convertPath(POPPLER_CONST_083 GfxPath *path) ++{ ++// qDebug() << "SlaOutputDev::convertPath"; ++ if (! path) ++ return QString(); ++ ++ QString output; ++ pathIsClosed = false; ++ ++ for (int i = 0; i < path->getNumSubpaths(); ++i) ++ { ++ POPPLER_CONST_083 GfxSubpath * subpath = path->getSubpath(i); ++ if (subpath->getNumPoints() > 0) ++ { ++ output += QString("M %1 %2").arg(subpath->getX(0)).arg(subpath->getY(0)); ++ int j = 1; ++ while (j < subpath->getNumPoints()) ++ { ++ if (subpath->getCurve(j)) ++ { ++ output += QString("C %1 %2 %3 %4 %5 %6") ++ .arg(subpath->getX(j)).arg(subpath->getY(j)) ++ .arg(subpath->getX(j + 1)).arg(subpath->getY(j + 1)) ++ .arg(subpath->getX(j + 2)).arg(subpath->getY(j + 2)); ++ j += 3; ++ } ++ else ++ { ++ output += QString("L %1 %2").arg(subpath->getX(j)).arg(subpath->getY(j)); ++ ++j; ++ } ++ } ++ if (subpath->isClosed()) ++ { ++ output += QString("Z"); ++ pathIsClosed = true; ++ } ++ } ++ } ++ return output; ++} ++ ++void SlaOutputDev::getPenState(GfxState *state) ++{ ++ switch (state->getLineCap()) ++ { ++ case 0: ++ PLineEnd = Qt::FlatCap; ++ break; ++ case 1: ++ PLineEnd = Qt::RoundCap; ++ break; ++ case 2: ++ PLineEnd = Qt::SquareCap; ++ break; ++ } ++ switch (state->getLineJoin()) ++ { ++ case 0: ++ PLineJoin = Qt::MiterJoin; ++ break; ++ case 1: ++ PLineJoin = Qt::RoundJoin; ++ break; ++ case 2: ++ PLineJoin = Qt::BevelJoin; ++ break; ++ } ++ double lw = state->getLineWidth(); ++ double *dashPattern; ++ int dashLength; ++ state->getLineDash(&dashPattern, &dashLength, &DashOffset); ++ QVector pattern(dashLength); ++ for (int i = 0; i < dashLength; ++i) ++ { ++ pattern[i] = dashPattern[i] / lw; ++ } ++ DashValues = pattern; ++} ++ ++int SlaOutputDev::getBlendMode(GfxState *state) ++{ ++ int mode = 0; ++ switch (state->getBlendMode()) ++ { ++ default: ++ case gfxBlendNormal: ++ mode = 0; ++ break; ++ case gfxBlendDarken: ++ mode = 1; ++ break; ++ case gfxBlendLighten: ++ mode = 2; ++ break; ++ case gfxBlendMultiply: ++ mode = 3; ++ break; ++ case gfxBlendScreen: ++ mode = 4; ++ break; ++ case gfxBlendOverlay: ++ mode = 5; ++ break; ++ case gfxBlendHardLight: ++ mode = 6; ++ break; ++ case gfxBlendSoftLight: ++ mode = 7; ++ break; ++ case gfxBlendDifference: ++ mode = 8; ++ break; ++ case gfxBlendExclusion: ++ mode = 9; ++ break; ++ case gfxBlendColorDodge: ++ mode = 10; ++ break; ++ case gfxBlendColorBurn: ++ mode = 11; ++ break; ++ case gfxBlendHue: ++ mode = 12; ++ break; ++ case gfxBlendSaturation: ++ mode = 13; ++ break; ++ case gfxBlendColor: ++ mode = 14; ++ break; ++ case gfxBlendLuminosity: ++ mode = 15; ++ break; ++ } ++ return mode; ++} ++ ++void SlaOutputDev::applyMask(PageItem *ite) ++{ ++ if (m_groupStack.count() != 0) ++ { ++ if (!m_groupStack.top().maskName.isEmpty()) ++ { ++ ite->setPatternMask(m_groupStack.top().maskName); ++ QPointF maskPos = m_groupStack.top().maskPos; ++ double sx, sy, px, py, r, shx, shy; ++ ite->maskTransform(sx, sy, px, py, r, shx, shy); ++ ite->setMaskTransform(sx, sy, maskPos.x() - ite->xPos(), maskPos.y() - ite->yPos(), r, shx, shy); ++ if (m_groupStack.top().alpha) ++ { ++ if (m_groupStack.top().inverted) ++ ite->setMaskType(8); ++ else ++ ite->setMaskType(3); ++ } ++ else ++ { ++ if (m_groupStack.top().inverted) ++ ite->setMaskType(7); ++ else ++ ite->setMaskType(6); ++ } ++ } ++ } ++ // Code for updating our Progressbar, needs to be called this way, as we have no ++ // possibility to get the current fileposition. ++ updateGUICounter++; ++ if (updateGUICounter > 20) ++ { ++ qApp->processEvents(); ++ updateGUICounter = 0; ++ } ++} ++ ++void SlaOutputDev::pushGroup(const QString& maskName, GBool forSoftMask, GBool alpha, bool inverted) ++{ ++ groupEntry gElements; ++ gElements.forSoftMask = forSoftMask; ++ gElements.alpha = alpha; ++ gElements.inverted = inverted; ++ gElements.maskName = maskName; ++ m_groupStack.push(gElements); ++} ++ ++QString SlaOutputDev::UnicodeParsedString(POPPLER_CONST GooString *s1) ++{ ++ if ( !s1 || s1->getLength() == 0 ) ++ return QString(); ++ GBool isUnicode; ++ int i; ++ Unicode u; ++ QString result; ++ if ((s1->getChar(0) & 0xff) == 0xfe && (s1->getLength() > 1 && (s1->getChar(1) & 0xff) == 0xff)) ++ { ++ isUnicode = gTrue; ++ i = 2; ++ result.reserve((s1->getLength() - 2) / 2); ++ } ++ else ++ { ++ isUnicode = gFalse; ++ i = 0; ++ result.reserve(s1->getLength()); ++ } ++ while (i < s1->getLength()) ++ { ++ if (isUnicode) ++ { ++ u = ((s1->getChar(i) & 0xff) << 8) | (s1->getChar(i+1) & 0xff); ++ i += 2; ++ } ++ else ++ { ++ u = s1->getChar(i) & 0xff; ++ ++i; ++ } ++ result += QChar( u ); ++ } ++ return result; ++} ++ ++QString SlaOutputDev::UnicodeParsedString(const std::string& s1) ++{ ++ if (s1.length() == 0) ++ return QString(); ++ GBool isUnicode; ++ size_t i; ++ Unicode u; ++ QString result; ++ if ((s1.at(0) & 0xff) == 0xfe && (s1.length() > 1 && (s1.at(1) & 0xff) == 0xff)) ++ { ++ isUnicode = gTrue; ++ i = 2; ++ result.reserve((s1.length() - 2) / 2); ++ } ++ else ++ { ++ isUnicode = gFalse; ++ i = 0; ++ result.reserve(s1.length()); ++ } ++ while (i < s1.length()) ++ { ++ if (isUnicode) ++ { ++ u = ((s1.at(i) & 0xff) << 8) | (s1.at(i+1) & 0xff); ++ i += 2; ++ } ++ else ++ { ++ u = s1.at(i) & 0xff; ++ ++i; ++ } ++ // #15616: imagemagick may write unicode strings incorrectly in PDF ++ if (u == 0) ++ continue; ++ result += QChar(u); ++ } ++ return result; ++} ++ ++bool SlaOutputDev::checkClip() ++{ ++ bool ret = false; ++ if (!m_currentClipPath.isEmpty()) ++ { ++ QRectF bbox = m_currentClipPath.boundingRect(); ++ if ((bbox.width() > 0) && (bbox.height() > 0)) ++ ret = true; ++ } ++ return ret; ++} +diff -Naur scribus-1.5.6.1.orig/scribus/plugins/import/pdf/slaoutput.h scribus-1.5.6.1/scribus/plugins/import/pdf/slaoutput.h +--- scribus-1.5.6.1.orig/scribus/plugins/import/pdf/slaoutput.h 2020-11-14 23:37:11.000000000 +0100 ++++ scribus-1.5.6.1/scribus/plugins/import/pdf/slaoutput.h 2021-04-04 11:46:37.053404000 +0200 +@@ -196,7 +196,11 @@ + void stroke(GfxState *state) override; + void fill(GfxState *state) override; + void eoFill(GfxState *state) override; ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(21, 3, 0) ++ bool tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *cat, GfxTilingPattern *tPat, const double *mat, int x0, int y0, int x1, int y1, double xStep, double yStep) override; ++#else + GBool tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *cat, Object *str, POPPLER_CONST_070 double *pmat, int paintType, int tilingType, Dict *resDict, POPPLER_CONST_070 double *mat, POPPLER_CONST_070 double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep) override; ++#endif + GBool functionShadedFill(GfxState * /*state*/, GfxFunctionShading * /*shading*/) override { qDebug() << "Function Shaded Fill"; return gFalse; } + GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) override; + GBool axialShadedSupportExtend(GfxState *state, GfxAxialShading *shading) override { return (shading->getExtend0() == shading->getExtend1()); } +@@ -368,7 +372,11 @@ + Catalog *catalog {nullptr}; + SplashFontEngine *m_fontEngine {nullptr}; + SplashFont *m_font {nullptr}; +- FormPageWidgets *m_formWidgets {nullptr}; ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(21, 4, 0) ++ std::unique_ptr m_formWidgets {nullptr}; ++#else ++ FormPageWidgets *m_formWidgets {nullptr}; ++#endif + QHash > m_radioMap; + QHash m_radioButtons; + int m_actPage; +diff -Naur scribus-1.5.6.1.orig/scribus/plugins/import/pdf/slaoutput.h.orig scribus-1.5.6.1/scribus/plugins/import/pdf/slaoutput.h.orig +--- scribus-1.5.6.1.orig/scribus/plugins/import/pdf/slaoutput.h.orig 1970-01-01 01:00:00.000000000 +0100 ++++ scribus-1.5.6.1/scribus/plugins/import/pdf/slaoutput.h.orig 2020-11-14 23:37:11.000000000 +0100 +@@ -0,0 +1,377 @@ ++/* ++For general Scribus (>=1.3.2) copyright and licensing information please refer ++to the COPYING file provided with the program. Following this notice may exist ++a copyright and/or license notice that predates the release of Scribus 1.3.2 ++for which a new license (GPL+exception) is in place. ++*/ ++#ifndef SLAOUTPUT_H ++#define SLAOUTPUT_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "fpointarray.h" ++#include "importpdfconfig.h" ++#include "pageitem.h" ++#include "scribusdoc.h" ++#include "scribusview.h" ++#include "selection.h" ++#include "vgradient.h" ++ ++#if POPPLER_ENCODED_VERSION < POPPLER_VERSION_ENCODE(0, 73, 0) ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++//------------------------------------------------------------------------ ++// LinkSubmitData ++//------------------------------------------------------------------------ ++ ++class LinkSubmitForm: public LinkAction ++{ ++public: ++ // Build a LinkImportData from an action dictionary. ++ LinkSubmitForm(Object *actionObj); ++ // Destructor. ++ virtual ~LinkSubmitForm(); ++ ++ // Was the LinkImportData created successfully? ++ GBool isOk() POPPLER_CONST override { return fileName != nullptr; } ++ // Accessors. ++ LinkActionKind getKind() POPPLER_CONST override { return actionUnknown; } ++ GooString *getFileName() { return fileName; } ++ int getFlags() { return m_flags; } ++ ++private: ++ GooString *fileName {nullptr}; // file name ++ int m_flags {0}; ++}; ++ ++//------------------------------------------------------------------------ ++// LinkImportData ++//------------------------------------------------------------------------ ++ ++class LinkImportData: public LinkAction ++{ ++public: ++ // Build a LinkImportData from an action dictionary. ++ LinkImportData(Object *actionObj); ++ // Destructor. ++ virtual ~LinkImportData(); ++ ++ // Was the LinkImportData created successfully? ++ GBool isOk() POPPLER_CONST override { return fileName != nullptr; } ++ // Accessors. ++ LinkActionKind getKind() POPPLER_CONST override { return actionUnknown; } ++ GooString *getFileName() { return fileName; } ++ ++private: ++ GooString *fileName {nullptr}; // file name ++}; ++ ++//------------------------------------------------------------------------ ++// SlaOutFontFileID ++//------------------------------------------------------------------------ ++ ++class SlaOutFontFileID: public SplashFontFileID ++{ ++public: ++ SlaOutFontFileID(const Ref *rA) { r = *rA; } ++ ~SlaOutFontFileID() {} ++ ++ GBool matches(SplashFontFileID *id) override ++ { ++ return ((SlaOutFontFileID*) id)->r.num == r.num && ((SlaOutFontFileID *) id)->r.gen == r.gen; ++ } ++ ++private: ++ Ref r; ++}; ++ ++ ++class AnoOutputDev : public OutputDev ++{ ++public: ++ AnoOutputDev(ScribusDoc* doc, QStringList *importedColors); ++ virtual ~AnoOutputDev(); ++ ++ GBool isOk() { return gTrue; } ++ GBool upsideDown() override { return gTrue; } ++ GBool useDrawChar() override { return gFalse; } ++ GBool interpretType3Chars() override { return gFalse; } ++ GBool useTilingPatternFill() override { return gFalse; } ++ GBool useShadedFills(int type) override { return gFalse; } ++ GBool useFillColorStop() override { return gFalse; } ++ GBool useDrawForm() override { return gFalse; } ++ ++ void stroke(GfxState *state) override; ++ void eoFill(GfxState *state) override; ++ void fill(GfxState *state) override; ++ void drawString(GfxState *state, POPPLER_CONST GooString *s) override; ++ ++ QString CurrColorText; ++ QString CurrColorFill; ++ QString CurrColorStroke; ++ double m_fontSize {12}; ++ GooString *m_fontName {nullptr}; ++ GooString *m_itemText {nullptr}; ++ ++private: ++ QString getColor(GfxColorSpace *color_space, POPPLER_CONST_070 GfxColor *color, int *shade); ++ ScribusDoc* m_doc; ++ QStringList *m_importedColors; ++}; ++ ++ ++class SlaOutputDev : public OutputDev ++{ ++public: ++ SlaOutputDev(ScribusDoc* doc, QList *Elements, QStringList *importedColors, int flags); ++ virtual ~SlaOutputDev(); ++ ++ LinkAction* SC_getAction(AnnotWidget *ano); ++#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) ++ std::unique_ptr SC_getAdditionalAction(const char *key, AnnotWidget *ano); ++#else ++ LinkAction* SC_getAdditionalAction(const char *key, AnnotWidget *ano); ++#endif ++ static GBool annotations_callback(Annot *annota, void *user_data); ++ bool handleTextAnnot(Annot* annota, double xCoor, double yCoor, double width, double height); ++ bool handleLinkAnnot(Annot* annota, double xCoor, double yCoor, double width, double height); ++ bool handleWidgetAnnot(Annot* annota, double xCoor, double yCoor, double width, double height); ++ void applyTextStyle(PageItem* ite, const QString& fontName, const QString& textColor, double fontSize); ++ void handleActions(PageItem* ite, AnnotWidget *ano); ++ void startDoc(PDFDoc *doc, XRef *xrefA, Catalog *catA); ++ ++ GBool isOk() { return gTrue; } ++ GBool upsideDown() override { return gTrue; } ++ GBool useDrawChar() override { return gTrue; } ++ GBool interpretType3Chars() override { return gTrue; } ++ GBool useTilingPatternFill() override { return gTrue; } ++ GBool useShadedFills(int type) override { return type <= 7; } ++ GBool useFillColorStop() override { return gTrue; } ++ GBool useDrawForm() override { return gFalse; } ++ ++// virtual GBool needClipToCropBox() { return gTrue; } ++ void startPage(int pageNum, GfxState *, XRef *) override; ++ void endPage() override; ++ ++ // graphics state ++ void saveState(GfxState *state) override; ++ void restoreState(GfxState *state) override; ++ ++ //----- path painting ++ void stroke(GfxState *state) override; ++ void fill(GfxState *state) override; ++ void eoFill(GfxState *state) override; ++ GBool tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *cat, Object *str, POPPLER_CONST_070 double *pmat, int paintType, int tilingType, Dict *resDict, POPPLER_CONST_070 double *mat, POPPLER_CONST_070 double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep) override; ++ GBool functionShadedFill(GfxState * /*state*/, GfxFunctionShading * /*shading*/) override { qDebug() << "Function Shaded Fill"; return gFalse; } ++ GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) override; ++ GBool axialShadedSupportExtend(GfxState *state, GfxAxialShading *shading) override { return (shading->getExtend0() == shading->getExtend1()); } ++ GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) override; ++ GBool radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading) override { return (shading->getExtend0() == shading->getExtend1()); } ++ GBool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) override; ++ GBool patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading) override; ++ ++ //----- path clipping ++ void clip(GfxState *state) override; ++ void eoClip(GfxState *state) override; ++ void clipToStrokePath(GfxState * /*state*/) override { qDebug() << "Clip to StrokePath"; } ++ virtual GBool deviceHasTextClip(GfxState *state) { return gFalse; } ++ ++ // If current colorspace is pattern, ++ // does this device support text in pattern colorspace? ++ virtual GBool supportTextCSPattern(GfxState *state) ++ { ++ return state->getFillColorSpace()->getMode() == csPattern; ++ } ++ ++ // If current colorspace is pattern, ++ // need this device special handling for masks in pattern colorspace? ++ virtual GBool fillMaskCSPattern(GfxState * state) ++ { ++ return state->getFillColorSpace()->getMode() == csPattern; ++ } ++ ++ virtual void endMaskClip(GfxState *state) { qDebug() << "End Mask Clip"; } ++ ++ //----- grouping operators ++ void beginMarkedContent(POPPLER_CONST char *name, Dict *properties) override; ++ virtual void beginMarkedContent(POPPLER_CONST char *name, Object *dictRef); ++ void endMarkedContent(GfxState *state) override; ++ void markPoint(POPPLER_CONST char *name) override; ++ void markPoint(POPPLER_CONST char *name, Dict *properties) override; ++ ++ //----- image drawing ++ void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool interpolate, GBool inlineImg) override; ++ void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, POPPLER_CONST_082 int *maskColors, GBool inlineImg) override; ++ void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, ++ int width, int height, ++ GfxImageColorMap *colorMap, ++ GBool interpolate, ++ Stream *maskStr, ++ int maskWidth, int maskHeight, ++ GfxImageColorMap *maskColorMap, ++ GBool maskInterpolate) override; ++ ++ void drawMaskedImage(GfxState *state, Object *ref, Stream *str, ++ int width, int height, ++ GfxImageColorMap *colorMap, ++ GBool interpolate, ++ Stream *maskStr, ++ int maskWidth, int maskHeight, ++ GBool maskInvert, GBool maskInterpolate) override; // { qDebug() << "Draw Masked Image"; } ++ ++ //----- transparency groups and soft masks ++ void beginTransparencyGroup(GfxState *state, POPPLER_CONST_070 double *bbox, GfxColorSpace * /*blendingColorSpace*/, GBool /*isolated*/, GBool /*knockout*/, GBool /*forSoftMask*/) override; ++ void paintTransparencyGroup(GfxState *state, POPPLER_CONST_070 double *bbox) override; ++ void endTransparencyGroup(GfxState *state) override; ++ void setSoftMask(GfxState * /*state*/, POPPLER_CONST_070 double * /*bbox*/, GBool /*alpha*/, Function * /*transferFunc*/, GfxColor * /*backdropColor*/) override; ++ void clearSoftMask(GfxState * /*state*/) override; ++ ++ void updateFillColor(GfxState *state) override; ++ void updateStrokeColor(GfxState *state) override; ++ void updateFont(GfxState *state) override; ++ ++ //----- text drawing ++ void beginTextObject(GfxState *state) override; ++ void endTextObject(GfxState *state) override; ++ void drawChar(GfxState *state, double /*x*/, double /*y*/, double /*dx*/, double /*dy*/, double /*originX*/, double /*originY*/, CharCode /*code*/, int /*nBytes*/, POPPLER_CONST_082 Unicode * /*u*/, int /*uLen*/) override; ++ GBool beginType3Char(GfxState * /*state*/, double /*x*/, double /*y*/, double /*dx*/, double /*dy*/, CharCode /*code*/, POPPLER_CONST_082 Unicode * /*u*/, int /*uLen*/) override; ++ void endType3Char(GfxState * /*state*/) override; ++ void type3D0(GfxState * /*state*/, double /*wx*/, double /*wy*/) override; ++ void type3D1(GfxState * /*state*/, double /*wx*/, double /*wy*/, double /*llx*/, double /*lly*/, double /*urx*/, double /*ury*/) override; ++ ++ //----- form XObjects ++ void drawForm(Ref /*id*/) override { qDebug() << "Draw Form"; } ++ ++ //----- links ++ void processLink(AnnotLink * /*link*/) override { qDebug() << "Draw Link"; } ++ ++ bool layersSetByOCG; ++ double cropOffsetX {0.0}; ++ double cropOffsetY {0.0}; ++ int rotate; ++ ++private: ++ void getPenState(GfxState *state); ++ QString getColor(GfxColorSpace *color_space, POPPLER_CONST_070 GfxColor *color, int *shade); ++ QString getAnnotationColor(const AnnotColor *color); ++ QString convertPath(POPPLER_CONST_083 GfxPath *path); ++ int getBlendMode(GfxState *state); ++ void applyMask(PageItem *ite); ++ void pushGroup(const QString& maskName = "", GBool forSoftMask = gFalse, GBool alpha = gFalse, bool inverted = false); ++ QString UnicodeParsedString(POPPLER_CONST GooString *s1); ++ QString UnicodeParsedString(const std::string& s1); ++ bool checkClip(); ++ ++ // Intersect the current clip path with the new path in state where filled areas ++ // are interpreted according to fillRule. ++ void adjustClip(GfxState *state, Qt::FillRule fillRule); ++ ++ // Take the current path of state and interpret it according to fillRule, ++ // intersect it with the clipping path and create a new pageitem for it. ++ void createFillItem(GfxState *state, Qt::FillRule fillRule); ++ ++ void createImageFrame(QImage& image, GfxState *state, int numColorComponents); ++ ++ bool pathIsClosed {false}; ++ QString CurrColorFill; ++ int CurrFillShade {100}; ++ QString CurrColorStroke; ++ int CurrStrokeShade {100}; ++ Qt::PenCapStyle PLineEnd {Qt::FlatCap}; ++ Qt::PenJoinStyle PLineJoin {Qt::MiterJoin}; ++ QVector DashValues; ++ double DashOffset {0.0}; ++ QString Coords; ++ // The currently visible area. If it is empty, everything is visible. ++ // QPainterPath has the drawback that it sometimes approximates Bezier curves ++ // by line segments for numerical stability. If available, a better class ++ // should be used. However, it is important that the used class knows which ++ // areas are covered and does not rely on external information about the fill ++ // rule to use. ++ QPainterPath m_currentClipPath; ++ QStack m_clipPaths; ++ // Collect the paths of character glyphs for clipping of a whole text group. ++ QPainterPath m_clipTextPath; ++ ++ struct groupEntry ++ { ++ QList Items; ++ GBool forSoftMask; ++ GBool isolated; ++ GBool alpha; ++ QString maskName; ++ QPointF maskPos; ++ bool inverted; ++ }; ++ QStack m_groupStack; ++ QString m_currentMask; ++ QPointF m_currentMaskPosition; ++ ScribusDoc* m_doc; ++ Selection* tmpSel; ++ QList *m_Elements; ++ QStringList *m_importedColors; ++ QTransform m_ctm; ++ struct F3Entry ++ { ++ bool colored; ++ }; ++ QStack m_F3Stack; ++ struct mContent ++ { ++ QString name; ++ QString ocgName; ++ }; ++ QStack m_mcStack; ++ int inPattern {0}; ++ int layerNum {1}; ++ int currentLayer; ++ bool firstLayer {true}; ++ int importerFlags; ++ int updateGUICounter {0}; ++ XRef *xref {nullptr}; // xref table for current document ++ PDFDoc *pdfDoc {nullptr}; ++ Catalog *catalog {nullptr}; ++ SplashFontEngine *m_fontEngine {nullptr}; ++ SplashFont *m_font {nullptr}; ++ FormPageWidgets *m_formWidgets {nullptr}; ++ QHash > m_radioMap; ++ QHash m_radioButtons; ++ int m_actPage; ++}; ++ ++#endif diff --git a/office/scribus/scribus.SlackBuild b/office/scribus/scribus.SlackBuild index 5842344c68dc..c3bdeacf407c 100644 --- a/office/scribus/scribus.SlackBuild +++ b/office/scribus/scribus.SlackBuild @@ -27,13 +27,13 @@ # Including input by Yalla-One and some code cleanup by rworkman PRGNAM=scribus -VERSION=${VERSION:-1.4.6} +VERSION=${VERSION:-1.5.6.1} BUILD=${BUILD:-1} TAG=${TAG:-_SBo} if [ -z "$ARCH" ]; then case "$( uname -m )" in - i?86) ARCH=i486 ;; + i?86) ARCH=i586 ;; arm*) ARCH=arm ;; *) ARCH=$( uname -m ) ;; esac @@ -44,8 +44,8 @@ TMP=${TMP:-/tmp/SBo} PKG=$TMP/package-$PRGNAM OUTPUT=${OUTPUT:-/tmp} -if [ "$ARCH" = "i486" ]; then - SLKCFLAGS="-O2 -march=i486 -mtune=i686" +if [ "$ARCH" = "i586" ]; then + SLKCFLAGS="-O2 -march=i586 -mtune=i686" LIBDIRSUFFIX="" elif [ "$ARCH" = "i686" ]; then SLKCFLAGS="-O2 -march=i686 -mtune=i686" @@ -73,12 +73,14 @@ find -L . \ \( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \ -o -perm 440 -o -perm 400 \) -exec chmod 644 {} \; +# thanks archlinux! +patch -p1 < $CWD/poppler-21.4.0.patch + cmake \ -DCMAKE_C_FLAGS="$SLKCFLAGS" \ -DCMAKE_CXX_FLAGS="$SLKCFLAGS" \ -DCMAKE_INSTALL_PREFIX:PATH=/usr \ - -DLIB_SUFFIX=${LIBDIRSUFFIX} \ - -DRENDER_LIB=CAIRO + -DLIB_SUFFIX=${LIBDIRSUFFIX} make make install DESTDIR=$PKG diff --git a/office/scribus/scribus.info b/office/scribus/scribus.info index 10e5f6a05fbc..b5f450fb1e2a 100644 --- a/office/scribus/scribus.info +++ b/office/scribus/scribus.info @@ -1,8 +1,8 @@ PRGNAM="scribus" -VERSION="1.4.6" +VERSION="1.5.6.1" HOMEPAGE="https://www.scribus.net" -DOWNLOAD="https://downloads.sourceforge.net/scribus/scribus-1.4.6.tar.xz" -MD5SUM="f6161785e24755ea77c8f14b319ff1aa" +DOWNLOAD="https://downloads.sourceforge.net/scribus/scribus-1.5.6.1.tar.xz" +MD5SUM="12700cd8c6f08ef02f50495d2ef2d3ce" DOWNLOAD_x86_64="" MD5SUM_x86_64="" REQUIRES="" -- cgit v1.2.3