summaryrefslogtreecommitdiffstats
path: root/office/scribus/poppler-21.4.0.patch
diff options
context:
space:
mode:
Diffstat (limited to 'office/scribus/poppler-21.4.0.patch')
-rw-r--r--office/scribus/poppler-21.4.0.patch4347
1 files changed, 4347 insertions, 0 deletions
diff --git a/office/scribus/poppler-21.4.0.patch b/office/scribus/poppler-21.4.0.patch
new file mode 100644
index 0000000000..7eedbd73c9
--- /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 <poppler/GlobalParams.h>
++#include <poppler/poppler-config.h>
++#include <poppler/FileSpec.h>
++#include <poppler/fofi/FoFiTrueType.h>
++#include <QApplication>
++#include <QFile>
++#include "commonstrings.h"
++#include "loadsaveplugin.h"
++#include "sccolorengine.h"
++#include "util.h"
++#include "util_math.h"
++#include <tiffio.h>
++
++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<PageItem*> *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<LinkAction> SlaOutputDev::SC_getAdditionalAction(const char *key, AnnotWidget *ano)
++{
++ std::unique_ptr<LinkAction> 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<LinkDest> 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<LinkDest> 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<int> 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<LinkDest> 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<LinkDest> 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<int> 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<double> 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<FormPageWidgets> m_formWidgets {nullptr};
++#else
++ FormPageWidgets *m_formWidgets {nullptr};
++#endif
+ QHash<QString, QList<int> > m_radioMap;
+ QHash<int, PageItem*> 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 <QBuffer>
++#include <QColor>
++#include <QBrush>
++#include <QDebug>
++#include <QImage>
++#include <QPen>
++#include <QList>
++#include <QSizeF>
++#include <QStack>
++#include <QString>
++#include <QTextStream>
++#include <QTransform>
++
++#include <memory>
++
++#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 <poppler/goo/gtypes.h>
++#endif
++#include <poppler/Object.h>
++#include <poppler/OutputDev.h>
++#include <poppler/Gfx.h>
++#include <poppler/GfxState.h>
++#include <poppler/Stream.h>
++#include <poppler/GfxFont.h>
++#include <poppler/Link.h>
++#include <poppler/PDFDoc.h>
++#include <poppler/Error.h>
++#include <poppler/Form.h>
++#include <poppler/Page.h>
++#include <poppler/Catalog.h>
++#include <poppler/CharCodeToUnicode.h>
++#include <poppler/FontEncodingTables.h>
++#include <poppler/splash/SplashFontFileID.h>
++#include <poppler/splash/SplashFontFile.h>
++#include <poppler/splash/SplashFontEngine.h>
++#include <poppler/splash/SplashFont.h>
++#include <poppler/splash/SplashMath.h>
++#include <poppler/splash/SplashPath.h>
++#include <poppler/splash/SplashGlyphBitmap.h>
++
++//------------------------------------------------------------------------
++// 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<PageItem*> *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<LinkAction> 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<double> 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<QPainterPath> m_clipPaths;
++ // Collect the paths of character glyphs for clipping of a whole text group.
++ QPainterPath m_clipTextPath;
++
++ struct groupEntry
++ {
++ QList<PageItem*> Items;
++ GBool forSoftMask;
++ GBool isolated;
++ GBool alpha;
++ QString maskName;
++ QPointF maskPos;
++ bool inverted;
++ };
++ QStack<groupEntry> m_groupStack;
++ QString m_currentMask;
++ QPointF m_currentMaskPosition;
++ ScribusDoc* m_doc;
++ Selection* tmpSel;
++ QList<PageItem*> *m_Elements;
++ QStringList *m_importedColors;
++ QTransform m_ctm;
++ struct F3Entry
++ {
++ bool colored;
++ };
++ QStack<F3Entry> m_F3Stack;
++ struct mContent
++ {
++ QString name;
++ QString ocgName;
++ };
++ QStack<mContent> 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<QString, QList<int> > m_radioMap;
++ QHash<int, PageItem*> m_radioButtons;
++ int m_actPage;
++};
++
++#endif