Subversion Repositories Scribus

Rev

Rev 25124 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
19590 jghali 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
 
8
#include "slaoutput.h"
22513 jghali 9
 
24884 jghali 10
#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(22, 2, 0)
11
#include <memory>
12
#include <optional>
13
#endif
14
 
19590 jghali 15
#include <poppler/GlobalParams.h>
16
#include <poppler/poppler-config.h>
17
#include <poppler/FileSpec.h>
18
#include <poppler/fofi/FoFiTrueType.h>
25120 jghali 19
 
19590 jghali 20
#include <QApplication>
21
#include <QFile>
25120 jghali 22
 
19590 jghali 23
#include "commonstrings.h"
24
#include "loadsaveplugin.h"
25
#include "sccolorengine.h"
26
#include "util.h"
27
#include "util_math.h"
28
#include <tiffio.h>
29
 
24374 jghali 30
//#ifndef DEBUG_TEXT_IMPORT
31
//      #define DEBUG_TEXT_IMPORT
32
//#endif
33
 
23550 jghali 34
namespace
35
{
36
        // Compute the intersection of two paths while considering the fillrule of each of them.
37
        // QPainterPath has the right interface to do the operation but is currently buggy.
38
        // See for example https://bugreports.qt.io/browse/QTBUG-83102. Thus this function
39
        // applies some heuristics to find the best result. As soon QPainterPath is fixed
40
        // one can just use a.intersected(b) wherever this function is called.
41
        // TODO: Find an alternative to QPainterPath that works for different fill rules.
42
        QPainterPath intersection(QPainterPath const &a, QPainterPath const &b)
43
        {
44
                // An empty path is treated like the whole area.
45
                if (a.elementCount() == 0)
46
                        return b;
47
                if (b.elementCount() == 0)
48
                        return a;
49
 
50
                QPainterPath ret_a = a.intersected(b);
51
                QPainterPath ret_b = b.intersected(a);
52
                // Sometimes the resulting paths are not closed even though they should.
53
                // Close them now.
54
                ret_a.closeSubpath();
55
                ret_b.closeSubpath();
56
 
57
                // Most of the time one of the two operations returns an empty path while the other
58
                // gives us the desired result. Return the non-empty one.
59
                if (ret_a.elementCount() == 0)
60
                        return ret_b;
61
                if (ret_b.elementCount() == 0)
62
                        return ret_a;
63
 
64
                // There are cases where both intersections are not empty but one of them is quite
65
                // complicated with several subpaths, etc. We return the simpler one.
66
                return (ret_a.elementCount() <= ret_b.elementCount()) ? ret_a : ret_b;
67
        }
23589 jghali 68
 
69
        // Invert preblending matte values into the color values. Assuming that c and alpha are RGBA components
70
        // between 0 and 255.
71
        int unblendMatte(int c, int alpha, int matte)
72
        {
73
                if (alpha == 0)
74
                        return matte;
75
                int ret = matte + ((c - matte) * 255) / alpha;
76
                if (ret < 0)
77
                        return 0;
78
                if (ret > 255)
79
                        return 255;
80
                return ret;
81
        }
23550 jghali 82
}
83
 
19590 jghali 84
LinkSubmitForm::LinkSubmitForm(Object *actionObj)
85
{
23377 craig 86
        if (!actionObj->isDict())
87
                return;
22738 jghali 88
 
23377 craig 89
        Object obj1 = actionObj->dictLookup("F");
90
        if (!obj1.isNull())
19590 jghali 91
        {
23377 craig 92
                if (obj1.isDict())
22154 jghali 93
                {
23377 craig 94
                        Object obj3 = obj1.dictLookup("FS");
95
                        if (!obj3.isNull())
22154 jghali 96
                        {
23377 craig 97
                                if (obj3.isName())
22154 jghali 98
                                {
25123 jghali 99
                                        const char *name = obj3.getName();
23377 craig 100
                                        if (!strcmp(name, "URL"))
22154 jghali 101
                                        {
23377 craig 102
                                                Object obj2 = obj1.dictLookup("F");
103
                                                if (!obj2.isNull())
104
                                                        fileName = obj2.getString()->copy();
22154 jghali 105
                                        }
106
                                }
107
                        }
108
                }
109
        }
23377 craig 110
        obj1 = actionObj->dictLookup("Flags");
111
        if (!obj1.isNull())
112
        {
113
                if (obj1.isNum())
114
                        m_flags = obj1.getInt();
115
        }
19590 jghali 116
}
117
 
118
LinkSubmitForm::~LinkSubmitForm()
119
{
22609 craig 120
        delete fileName;
19590 jghali 121
}
122
 
123
LinkImportData::LinkImportData(Object *actionObj)
124
{
23377 craig 125
        if (!actionObj->isDict())
126
                return;
127
        Object obj1 = actionObj->dictLookup("F");
128
        if (obj1.isNull())
129
                return;
22738 jghali 130
 
23377 craig 131
        Object obj3 = getFileSpecNameForPlatform(&obj1);
132
        if (!obj3.isNull())
133
                fileName = obj3.getString()->copy();
19590 jghali 134
}
135
 
136
LinkImportData::~LinkImportData()
137
{
22609 craig 138
        delete fileName;
19590 jghali 139
}
140
 
141
AnoOutputDev::~AnoOutputDev()
142
{
24374 jghali 143
        delete fontName;
144
        delete itemText;
19590 jghali 145
}
146
 
147
AnoOutputDev::AnoOutputDev(ScribusDoc* doc, QStringList *importedColors)
148
{
149
        m_doc = doc;
150
        m_importedColors = importedColors;
24374 jghali 151
        currColorText = "Black";
152
        currColorFill = CommonStrings::None;
153
        currColorStroke = CommonStrings::None;
19590 jghali 154
}
155
 
156
void AnoOutputDev::eoFill(GfxState *state)
157
{
158
        int shade = 100;
24374 jghali 159
        currColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade);
19590 jghali 160
}
161
 
162
void AnoOutputDev::fill(GfxState *state)
163
{
164
        int shade = 100;
24374 jghali 165
        currColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade);
19590 jghali 166
}
167
 
168
void AnoOutputDev::stroke(GfxState *state)
169
{
170
        int shade = 100;
24374 jghali 171
        currColorStroke = getColor(state->getStrokeColorSpace(), state->getStrokeColor(), &shade);
19590 jghali 172
}
173
 
25123 jghali 174
void AnoOutputDev::drawString(GfxState *state, const GooString *s)
19590 jghali 175
{
176
        int shade = 100;
24374 jghali 177
        currColorText = getColor(state->getFillColorSpace(), state->getFillColor(), &shade);
178
        fontSize = state->getFontSize();
25074 jghali 179
#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(22, 4, 0)
180
        if (state->getFont() && state->getFont()->getName())
181
                fontName = new GooString(state->getFont()->getName().value());
182
#else
19590 jghali 183
        if (state->getFont())
24374 jghali 184
                fontName = state->getFont()->getName()->copy();
25074 jghali 185
#endif
24374 jghali 186
        itemText = s->copy();
19590 jghali 187
}
188
 
25123 jghali 189
QString AnoOutputDev::getColor(GfxColorSpace *color_space, const GfxColor *color, int *shade)
19590 jghali 190
{
191
        QString fNam;
192
        QString namPrefix = "FromPDF";
193
        ScColor tmp;
194
        tmp.setSpotColor(false);
195
        tmp.setRegistrationColor(false);
196
        *shade = 100;
197
        if ((color_space->getMode() == csDeviceRGB) || (color_space->getMode() == csCalRGB))
198
        {
199
                GfxRGB rgb;
200
                color_space->getRGB(color, &rgb);
22212 jghali 201
                double Rc = colToDbl(rgb.r);
202
                double Gc = colToDbl(rgb.g);
203
                double Bc = colToDbl(rgb.b);
204
                tmp.setRgbColorF(Rc, Gc, Bc);
19590 jghali 205
                fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp);
206
        }
207
        else if (color_space->getMode() == csDeviceCMYK)
208
        {
209
                GfxCMYK cmyk;
210
                color_space->getCMYK(color, &cmyk);
22212 jghali 211
                double Cc = colToDbl(cmyk.c);
212
                double Mc = colToDbl(cmyk.m);
213
                double Yc = colToDbl(cmyk.y);
214
                double Kc = colToDbl(cmyk.k);
22593 jghali 215
                tmp.setCmykColorF(Cc, Mc, Yc, Kc);
19590 jghali 216
                fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp);
217
        }
218
        else if ((color_space->getMode() == csCalGray) || (color_space->getMode() == csDeviceGray))
219
        {
220
                GfxGray gray;
221
                color_space->getGray(color, &gray);
22212 jghali 222
                double Kc = 1.0 - colToDbl(gray);
22593 jghali 223
                tmp.setCmykColorF(0, 0, 0, Kc);
19590 jghali 224
                fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp);
225
        }
226
        else if (color_space->getMode() == csSeparation)
227
        {
22596 jghali 228
                GfxSeparationColorSpace* sepColorSpace = (GfxSeparationColorSpace*)color_space;
229
                GfxColorSpace* altColorSpace = sepColorSpace->getAlt();
25123 jghali 230
                QString name = QString(sepColorSpace->getName()->c_str());
22596 jghali 231
                bool isRegistrationColor = (name == "All");
232
                if (isRegistrationColor)
233
                {
234
                        tmp.setCmykColorF(1.0, 1.0, 1.0, 1.0);
235
                        tmp.setRegistrationColor(true);
236
                        name = "Registration";
237
                }
238
                else if ((altColorSpace->getMode() == csDeviceRGB) || (altColorSpace->getMode() == csCalRGB))
239
                {
240
                        double x = 1.0;
241
                        double comps[gfxColorMaxComps];
242
                        sepColorSpace->getFunc()->transform(&x, comps);
243
                        tmp.setRgbColorF(comps[0], comps[1], comps[2]);
244
                }
245
                else if ((altColorSpace->getMode() == csCalGray) || (altColorSpace->getMode() == csDeviceGray))
246
                {
247
                        double x = 1.0;
248
                        double comps[gfxColorMaxComps];
249
                        sepColorSpace->getFunc()->transform(&x, comps);
250
                        tmp.setCmykColorF(0.0, 0.0, 0.0, 1.0 - comps[0]);
251
                }
252
                else if (altColorSpace->getMode() == csLab)
253
                {
254
                        double x = 1.0;
255
                        double comps[gfxColorMaxComps];
256
                        sepColorSpace->getFunc()->transform(&x, comps);
257
                        tmp.setLabColor(comps[0], comps[1], comps[2]);
258
                }
259
                else
260
                {
261
                        GfxCMYK cmyk;
262
                        color_space->getCMYK(color, &cmyk);
263
                        double Cc = colToDbl(cmyk.c);
264
                        double Mc = colToDbl(cmyk.m);
265
                        double Yc = colToDbl(cmyk.y);
266
                        double Kc = colToDbl(cmyk.k);
267
                        tmp.setCmykColorF(Cc, Mc, Yc, Kc);
268
                }
269
                tmp.setSpotColor(true);
22592 jghali 270
 
22596 jghali 271
                fNam = m_doc->PageColors.tryAddColor(name, tmp);
272
                *shade = qRound(colToDbl(color->c[0]) * 100);
19590 jghali 273
        }
274
        else
275
        {
276
                GfxRGB rgb;
277
                color_space->getRGB(color, &rgb);
22212 jghali 278
                double Rc = colToDbl(rgb.r);
279
                double Gc = colToDbl(rgb.g);
280
                double Bc = colToDbl(rgb.b);
281
                tmp.setRgbColorF(Rc, Gc, Bc);
19590 jghali 282
                fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp);
283
        //      qDebug() << "update fill color other colorspace" << color_space->getMode() << "treating as rgb" << Rc << Gc << Bc;
284
        }
285
        if (fNam == namPrefix+tmp.name())
286
                m_importedColors->append(fNam);
287
        return fNam;
288
}
289
 
290
SlaOutputDev::SlaOutputDev(ScribusDoc* doc, QList<PageItem*> *Elements, QStringList *importedColors, int flags)
291
{
292
        m_doc = doc;
293
        m_Elements = Elements;
294
        pushGroup();
295
        m_importedColors = importedColors;
25122 jghali 296
        m_tmpSel = new Selection(m_doc, false);
297
        m_importerFlags = flags;
298
        m_currentLayer = m_doc->activeLayer();
19590 jghali 299
        layersSetByOCG = false;
300
}
301
 
302
SlaOutputDev::~SlaOutputDev()
303
{
304
        m_groupStack.clear();
25122 jghali 305
        m_tmpSel->clear();
306
        delete m_tmpSel;
19590 jghali 307
        delete m_fontEngine;
308
}
309
 
310
/* get Actions not implemented by Poppler */
311
LinkAction* SlaOutputDev::SC_getAction(AnnotWidget *ano)
312
{
22527 craig 313
        LinkAction *linkAction = nullptr;
19590 jghali 314
        Object obj;
315
        Ref refa = ano->getRef();
22906 jghali 316
 
25122 jghali 317
        obj = m_xref->fetch(refa.num, refa.gen);
22154 jghali 318
        if (obj.isDict())
319
        {
320
                Dict* adic = obj.getDict();
25123 jghali 321
                const Object & additionalActions = adic->lookupNF("A");
25122 jghali 322
                Object additionalActionsObject = additionalActions.fetch(m_pdfDoc->getXRef());
22154 jghali 323
                if (additionalActionsObject.isDict())
324
                {
325
                        Object actionObject = additionalActionsObject.dictLookup("S");
326
                        if (actionObject.isName("ImportData"))
327
                        {
328
                                linkAction = new LinkImportData(&additionalActionsObject);
329
                        }
330
                        else if (actionObject.isName("SubmitForm"))
331
                        {
332
                                linkAction = new LinkSubmitForm(&additionalActionsObject);
333
                        }
334
                }
335
        }
19590 jghali 336
        return linkAction;
337
}
338
 
339
/* Replacement for the crippled Poppler function LinkAction* AnnotWidget::getAdditionalAction(AdditionalActionsType type) */
23478 jghali 340
std::unique_ptr<LinkAction> SlaOutputDev::SC_getAdditionalAction(const char *key, AnnotWidget *ano)
341
{
342
        std::unique_ptr<LinkAction> linkAction;
19590 jghali 343
        Object obj;
344
        Ref refa = ano->getRef();
22154 jghali 345
 
25122 jghali 346
        obj = m_xref->fetch(refa.num, refa.gen);
22154 jghali 347
        if (obj.isDict())
348
        {
349
                Dict* adic = obj.getDict();
25123 jghali 350
                const Object & additionalActions = adic->lookupNF("AA");
25122 jghali 351
                Object additionalActionsObject = additionalActions.fetch(m_pdfDoc->getXRef());
22154 jghali 352
                if (additionalActionsObject.isDict())
353
                {
354
                        Object actionObject = additionalActionsObject.dictLookup(key);
355
                        if (actionObject.isDict())
25122 jghali 356
                                linkAction = LinkAction::parseAction(&actionObject, m_pdfDoc->getCatalog()->getBaseURI());
22154 jghali 357
                }
358
        }
19590 jghali 359
        return linkAction;
360
}
361
 
25123 jghali 362
bool SlaOutputDev::annotations_callback(Annot *annota, void *user_data)
19590 jghali 363
{
364
        SlaOutputDev *dev = (SlaOutputDev*)user_data;
25074 jghali 365
#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(22, 4, 0)
366
        const PDFRectangle& annotRect = annota->getRect();;
367
        const PDFRectangle* box = &annotRect;
368
#else
19590 jghali 369
        PDFRectangle *box = annota->getRect();
25074 jghali 370
#endif
19590 jghali 371
        double xCoor = dev->m_doc->currentPage()->xOffset() + box->x1 - dev->cropOffsetX;
372
        double yCoor = dev->m_doc->currentPage()->yOffset() + dev->m_doc->currentPage()->height() - box->y2 + dev->cropOffsetY;
373
        double width = box->x2 - box->x1;
374
        double height = box->y2 - box->y1;
375
        if (dev->rotate == 90)
376
        {
377
                xCoor = dev->m_doc->currentPage()->xOffset() - dev->cropOffsetX + box->y2;
378
                yCoor = dev->m_doc->currentPage()->yOffset() + dev->cropOffsetY + box->x1;
379
        }
380
        else if (dev->rotate == 180)
381
        {
382
                xCoor = dev->m_doc->currentPage()->xOffset() - dev->cropOffsetX + dev->m_doc->currentPage()->width() - box->x1;
383
                yCoor = dev->m_doc->currentPage()->yOffset() + dev->cropOffsetY + box->y2;
384
        }
385
        else if (dev->rotate == 270)
386
        {
387
                xCoor = dev->m_doc->currentPage()->xOffset() - dev->cropOffsetX + dev->m_doc->currentPage()->width() - box->y2;
388
                yCoor = dev->m_doc->currentPage()->yOffset() + dev->cropOffsetY + dev->m_doc->currentPage()->height() - box->x1;
389
        }
390
        bool retVal = true;
391
        if (annota->getType() == Annot::typeText)
392
                retVal = !dev->handleTextAnnot(annota, xCoor, yCoor, width, height);
393
        else if (annota->getType() == Annot::typeLink)
394
                retVal = !dev->handleLinkAnnot(annota, xCoor, yCoor, width, height);
395
        else if (annota->getType() == Annot::typeWidget)
396
                retVal = !dev->handleWidgetAnnot(annota, xCoor, yCoor, width, height);
397
        return retVal;
398
}
399
 
400
bool SlaOutputDev::handleTextAnnot(Annot* annota, double xCoor, double yCoor, double width, double height)
401
{
402
        AnnotText *anl = (AnnotText*)annota;
20561 jghali 403
        int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
19590 jghali 404
        PageItem *ite = m_doc->Items->at(z);
405
        int flg = annota->getFlags();
406
        if (!(flg & 16))
407
                ite->setRotation(rotate, true);
408
        ite->ClipEdited = true;
409
        ite->FrameType = 3;
410
        ite->setFillEvenOdd(false);
23040 jghali 411
        ite->Clip = flattenPath(ite->PoLine, ite->Segments);
19590 jghali 412
        ite->ContourLine = ite->PoLine.copy();
413
        ite->setTextFlowMode(PageItem::TextFlowDisabled);
414
        m_Elements->append(ite);
415
        if (m_groupStack.count() != 0)
416
        {
417
                m_groupStack.top().Items.append(ite);
418
                applyMask(ite);
419
        }
420
        ite->setIsAnnotation(true);
421
        ite->AutoName = false;
422
        ite->annotation().setType(Annotation::Text);
423
        ite->annotation().setActionType(Annotation::Action_None);
424
        ite->annotation().setAnOpen(anl->getOpen());
425
        QString iconName = UnicodeParsedString(anl->getIcon());
426
        if (iconName == "Note")
427
                ite->annotation().setIcon(Annotation::Icon_Note);
428
        else if (iconName == "Comment")
429
                ite->annotation().setIcon(Annotation::Icon_Comment);
430
        else if (iconName == "Key")
431
                ite->annotation().setIcon(Annotation::Icon_Key);
432
        else if (iconName == "Help")
433
                ite->annotation().setIcon(Annotation::Icon_Help);
434
        else if (iconName == "NewParagraph")
435
                ite->annotation().setIcon(Annotation::Icon_NewParagraph);
436
        else if (iconName == "Paragraph")
437
                ite->annotation().setIcon(Annotation::Icon_Paragraph);
438
        else if (iconName == "Insert")
439
                ite->annotation().setIcon(Annotation::Icon_Insert);
440
        else if (iconName == "Cross")
441
                ite->annotation().setIcon(Annotation::Icon_Cross);
442
        else if (iconName == "Circle")
443
                ite->annotation().setIcon(Annotation::Icon_Circle);
444
        else
445
                ite->annotation().setIcon(Annotation::Icon_Note);
446
        ite->setItemName( CommonStrings::itemName_TextAnnotation + QString("%1").arg(m_doc->TotalItems));
447
        ite->itemText.insertChars(UnicodeParsedString(annota->getContents()));
448
        ite->itemText.trim();
449
        return true;
450
}
451
 
452
bool SlaOutputDev::handleLinkAnnot(Annot* annota, double xCoor, double yCoor, double width, double height)
453
{
454
        AnnotLink *anl = (AnnotLink*)annota;
455
        LinkAction *act = anl->getAction();
456
        if (!act)
457
                return false;
458
        bool validLink = false;
459
        int pagNum = 0;
460
        int xco = 0;
461
        int yco = 0;
25070 craig 462
        QString fileName;
19590 jghali 463
        if (act->getKind() == actionGoTo)
464
        {
22513 jghali 465
                LinkGoTo *gto = (LinkGoTo*) act;
25123 jghali 466
                const LinkDest *dst = gto->getDest();
19590 jghali 467
                if (dst)
468
                {
469
                        if (dst->getKind() == destXYZ)
470
                        {
471
                                if (dst->isPageRef())
472
                                {
473
                                        Ref dstr = dst->getPageRef();
25122 jghali 474
                                        pagNum = m_pdfDoc->findPage(dstr);
19590 jghali 475
                                }
476
                                else
477
                                        pagNum = dst->getPageNum();
478
                                xco = dst->getLeft();
479
                                yco = dst->getTop();
480
                                validLink = true;
481
                        }
482
                }
483
                else
484
                {
25123 jghali 485
                        const GooString *ndst = gto->getNamedDest();
19590 jghali 486
                        if (ndst)
487
                        {
25122 jghali 488
                                std::unique_ptr<LinkDest> dstn = m_pdfDoc->findDest(ndst);
19590 jghali 489
                                if (dstn)
490
                                {
491
                                        if (dstn->getKind() == destXYZ)
492
                                        {
493
                                                if (dstn->isPageRef())
494
                                                {
495
                                                        Ref dstr = dstn->getPageRef();
25122 jghali 496
                                                        pagNum = m_pdfDoc->findPage(dstr);
19590 jghali 497
                                                }
498
                                                else
499
                                                        pagNum = dstn->getPageNum();
500
                                                xco = dstn->getLeft();
501
                                                yco = dstn->getTop();
502
                                                validLink = true;
503
                                        }
504
                                }
505
                        }
506
                }
507
        }
508
        else if (act->getKind() == actionGoToR)
509
        {
510
                LinkGoToR *gto = (LinkGoToR*)act;
511
                fileName = UnicodeParsedString(gto->getFileName());
25123 jghali 512
                const LinkDest *dst = gto->getDest();
19590 jghali 513
                if (dst)
514
                {
515
                        if (dst->getKind() == destXYZ)
516
                        {
517
                                pagNum = dst->getPageNum();
518
                                xco = dst->getLeft();
519
                                yco = dst->getTop();
520
                                validLink = true;
521
                        }
522
                }
523
                else
524
                {
25123 jghali 525
                        const GooString *ndst = gto->getNamedDest();
19590 jghali 526
                        if (ndst)
527
                        {
25122 jghali 528
                                std::unique_ptr<LinkDest> dstn = m_pdfDoc->findDest(ndst);
19590 jghali 529
                                if (dstn)
530
                                {
531
                                        if (dstn->getKind() == destXYZ)
532
                                        {
533
                                                pagNum = dstn->getPageNum();
534
                                                xco = dstn->getLeft();
535
                                                yco = dstn->getTop();
536
                                                validLink = true;
537
                                        }
538
                                }
539
                        }
540
                }
541
        }
542
        else if (act->getKind() == actionURI)
543
        {
544
                LinkURI *gto = (LinkURI*)act;
545
                validLink = true;
546
                fileName = UnicodeParsedString(gto->getURI());
547
        }
548
        if (validLink)
549
        {
20561 jghali 550
                int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
19590 jghali 551
                PageItem *ite = m_doc->Items->at(z);
552
                int flg = annota->getFlags();
553
                if (!(flg & 16))
554
                        ite->setRotation(rotate, true);
555
                ite->ClipEdited = true;
556
                ite->FrameType = 3;
557
                ite->setFillEvenOdd(false);
23040 jghali 558
                ite->Clip = flattenPath(ite->PoLine, ite->Segments);
19590 jghali 559
                ite->ContourLine = ite->PoLine.copy();
560
                ite->setTextFlowMode(PageItem::TextFlowDisabled);
561
                m_Elements->append(ite);
562
                if (m_groupStack.count() != 0)
563
                {
564
                        m_groupStack.top().Items.append(ite);
565
                        applyMask(ite);
566
                }
567
                ite->setIsAnnotation(true);
568
                ite->AutoName = false;
569
                if (act->getKind() == actionGoTo)
570
                {
21458 jghali 571
                        ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1));
19590 jghali 572
                        ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco));
573
                        ite->annotation().setActionType(2);
574
                }
575
                else if (act->getKind() == actionGoToR)
576
                {
21458 jghali 577
                        ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1));
19590 jghali 578
                        ite->annotation().setExtern(fileName);
579
                        ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco));
580
                        ite->annotation().setActionType(9);
581
                }
582
                else if (act->getKind() == actionURI)
583
                {
584
                        ite->annotation().setAction("");
585
                        ite->annotation().setExtern(fileName);
586
                        ite->annotation().setActionType(8);
587
                }
588
                ite->annotation().setType(Annotation::Link);
589
                ite->setItemName( CommonStrings::itemName_LinkAnnotation + QString("%1").arg(m_doc->TotalItems));
590
        }
591
        return validLink;
592
}
593
 
594
bool SlaOutputDev::handleWidgetAnnot(Annot* annota, double xCoor, double yCoor, double width, double height)
595
{
596
        bool retVal = false;
597
        bool found = false;
598
 
599
        if (!m_formWidgets)
600
                return false;
601
 
602
        int formcount = m_formWidgets->getNumWidgets();
603
        for (int i = 0; i < formcount; ++i)
604
        {
605
                FormWidget *fm = m_formWidgets->getWidget(i);
606
                if (!fm)
607
                        continue;
608
                AnnotWidget *ano = fm->getWidgetAnnotation();
609
                if (!ano)
610
                        continue;
611
                if (ano != (AnnotWidget*) annota)
612
                        continue;
613
                found = true;
614
                int wtyp = -1;
615
                if (fm->getType() == formButton)
616
                {
617
                        FormWidgetButton *btn = (FormWidgetButton*)fm;
618
                        if (btn)
619
                        {
620
                                if (btn->getButtonType() == formButtonCheck)
621
                                {
622
                                        wtyp = Annotation::Checkbox;
623
                                        retVal = true;
624
                                }
625
                                else if (btn->getButtonType() == formButtonPush)
626
                                {
627
                                        wtyp = Annotation::Button;
628
                                        retVal = true;
629
                                }
630
                                else if (btn->getButtonType() == formButtonRadio)
631
                                {
632
                                        wtyp = Annotation::RadioButton;
633
                                        retVal = true;
634
                                }
635
                        }
636
                }
637
                else if (fm->getType() == formText)
638
                {
639
                        wtyp = Annotation::Textfield;
640
                        retVal = true;
641
                }
642
                else if (fm->getType() == formChoice)
643
                {
644
                        FormWidgetChoice *btn = (FormWidgetChoice*)fm;
645
                        if (btn)
646
                        {
647
                                if (btn->isCombo())
648
                                {
649
                                        wtyp = Annotation::Combobox;
650
                                        retVal = true;
651
                                }
652
                                else if (btn->isListBox())
653
                                {
654
                                        wtyp = Annotation::Listbox;
655
                                        retVal = true;
656
                                }
657
                        }
658
                }
659
                if (retVal)
660
                {
661
                        AnnotAppearanceCharacs *achar = ano->getAppearCharacs();
662
                        bool fgFound = false;
663
                        bool bgFound = false;
664
                        if (achar)
665
                        {
25123 jghali 666
                                const AnnotColor *bgCol = achar->getBackColor();
19590 jghali 667
                                if (bgCol)
668
                                {
669
                                        bgFound = true;
25120 jghali 670
                                        m_graphicStack.top().fillColor = getAnnotationColor(bgCol);
19590 jghali 671
                                }
672
                                else
25120 jghali 673
                                        m_graphicStack.top().fillColor = CommonStrings::None;
25123 jghali 674
                                const AnnotColor *fgCol = achar->getBorderColor();
19590 jghali 675
                                if (fgCol)
676
                                {
677
                                        fgFound = true;
25120 jghali 678
                                        m_graphicStack.top().strokeColor = getAnnotationColor(fgCol);
19590 jghali 679
                                }
680
                                else
681
                                {
682
                                        fgCol = achar->getBackColor();
683
                                        if (fgCol)
25120 jghali 684
                                                m_graphicStack.top().strokeColor = getAnnotationColor(fgCol);
19590 jghali 685
                                        else
25120 jghali 686
                                                m_graphicStack.top().strokeColor = CommonStrings::None;
19590 jghali 687
                                }
688
                        }
25122 jghali 689
                        QString currTextColor = "Black";
19590 jghali 690
                        double fontSize = 12;
25070 craig 691
                        QString fontName;
692
                        QString itemText;
19590 jghali 693
                        AnnotAppearance *apa = annota->getAppearStreams();
694
                        if (apa || !achar)
695
                        {
24374 jghali 696
                                AnoOutputDev *annotOutDev = new AnoOutputDev(m_doc, m_importedColors);
25074 jghali 697
#if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(22, 4, 0)
698
                                const PDFRectangle& annotaRect = annota->getRect();
25122 jghali 699
                                Gfx* gfx = new Gfx(m_pdfDoc, annotOutDev, m_pdfDoc->getPage(m_actPage)->getResourceDict(), &annotaRect, nullptr);
25074 jghali 700
#else
25122 jghali 701
                                Gfx *gfx = new Gfx(m_pdfDoc, annotOutDev, m_pdfDoc->getPage(m_actPage)->getResourceDict(), annota->getRect(), nullptr);
25074 jghali 702
#endif
19590 jghali 703
                                ano->draw(gfx, false);
704
                                if (!bgFound)
25120 jghali 705
                                        m_graphicStack.top().fillColor = annotOutDev->currColorFill;
19590 jghali 706
                                if (!fgFound)
25120 jghali 707
                                        m_graphicStack.top().strokeColor = annotOutDev->currColorStroke;
25122 jghali 708
                                currTextColor = annotOutDev->currColorText;
24374 jghali 709
                                fontSize = annotOutDev->fontSize;
710
                                fontName = UnicodeParsedString(annotOutDev->fontName);
711
                                itemText = UnicodeParsedString(annotOutDev->itemText);
19590 jghali 712
                                delete gfx;
24374 jghali 713
                                delete annotOutDev;
19590 jghali 714
                        }
25120 jghali 715
                        const auto& graphicState = m_graphicStack.top();
716
                        int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, graphicState.fillColor, CommonStrings::None);
19590 jghali 717
                        PageItem *ite = m_doc->Items->at(z);
718
                        int flg = annota->getFlags();
719
                        if (!(flg & 16))
720
                                ite->setRotation(rotate, true);
721
                        ite->ClipEdited = true;
722
                        ite->FrameType = 3;
723
                        ite->setFillEvenOdd(false);
23040 jghali 724
                        ite->Clip = flattenPath(ite->PoLine, ite->Segments);
19590 jghali 725
                        ite->ContourLine = ite->PoLine.copy();
726
                        ite->setTextFlowMode(PageItem::TextFlowDisabled);
727
                        m_Elements->append(ite);
728
                        if (m_groupStack.count() != 0)
729
                        {
730
                                m_groupStack.top().Items.append(ite);
731
                                applyMask(ite);
732
                        }
733
                        ite->setIsAnnotation(true);
734
                        ite->AutoName = false;
735
                        AnnotBorder *brd = annota->getBorder();
736
                        if (brd)
737
                        {
738
                                int bsty = brd->getStyle();
739
                                if (bsty == AnnotBorder::borderDashed)
740
                                        bsty = 1;
741
                                else if (bsty == AnnotBorder::borderBeveled)
742
                                        bsty = 3;
743
                                else if (bsty == AnnotBorder::borderInset)
744
                                        bsty = 4;
745
                                else if (bsty == AnnotBorder::borderUnderlined)
746
                                        bsty = 2;
22748 jghali 747
                                ite->annotation().setBorderStyle(bsty);
25120 jghali 748
                                ite->annotation().setBorderColor(graphicState.strokeColor);
22748 jghali 749
                                ite->annotation().setBorderWidth(qRound(brd->getWidth()));
19590 jghali 750
                        }
751
                        else
752
                        {
22748 jghali 753
                                ite->annotation().setBorderStyle(0);
19590 jghali 754
                                ite->annotation().setBorderColor(CommonStrings::None);
22748 jghali 755
                                ite->annotation().setBorderWidth(0);
19590 jghali 756
                        }
25070 craig 757
                        QString tmTxt(UnicodeParsedString(fm->getPartialName()));
19590 jghali 758
                        if (!tmTxt.isEmpty())
759
                                ite->setItemName(tmTxt);
25070 craig 760
                        tmTxt.clear();
19590 jghali 761
                        tmTxt = UnicodeParsedString(fm->getAlternateUiName());
762
                        if (!tmTxt.isEmpty())
763
                                ite->annotation().setToolTip(tmTxt);
25070 craig 764
                        tmTxt.clear();
19590 jghali 765
                        if (achar)
766
                        {
767
                                tmTxt = UnicodeParsedString(achar->getRolloverCaption());
768
                                if (!tmTxt.isEmpty())
769
                                        ite->annotation().setRollOver(tmTxt);
770
                                tmTxt = "";
771
                                tmTxt = UnicodeParsedString(achar->getAlternateCaption());
772
                                if (!tmTxt.isEmpty())
773
                                        ite->annotation().setDown(tmTxt);
774
                        }
775
                        ite->annotation().setType(wtyp);
776
                        ite->annotation().setFlag(0);
777
                        if (flg & 2)
778
                                ite->annotation().setVis(1);
779
                        if (flg & 32)
780
                                ite->annotation().setVis(3);
781
                        if (wtyp == Annotation::Button)
782
                        {
25120 jghali 783
                                ite->setFillColor(graphicState.fillColor);
19590 jghali 784
                                if (achar)
785
                                        ite->itemText.insertChars(UnicodeParsedString(achar->getNormalCaption()));
786
                                else
787
                                        ite->itemText.insertChars(itemText);
25122 jghali 788
                                applyTextStyle(ite, fontName, currTextColor, fontSize);
19590 jghali 789
                                ite->annotation().addToFlag(Annotation::Flag_PushButton);
790
                                FormWidgetButton *btn = (FormWidgetButton*)fm;
791
                                if (!btn->isReadOnly())
792
                                        ite->annotation().addToFlag(Annotation::Flag_Edit);
793
                                handleActions(ite, ano);
794
                        }
795
                        else if (wtyp == Annotation::Textfield)
796
                        {
797
                                FormWidgetText *btn = (FormWidgetText*)fm;
798
                                if (btn)
799
                                {
800
                                        ite->itemText.insertChars(UnicodeParsedString(btn->getContent()));
25122 jghali 801
                                        applyTextStyle(ite, fontName, currTextColor, fontSize);
19590 jghali 802
                                        ite->itemText.trim();
803
                                        if (btn->isMultiline())
804
                                                ite->annotation().addToFlag(Annotation::Flag_Multiline);
805
                                        if (btn->isPassword())
806
                                                ite->annotation().addToFlag(Annotation::Flag_Password);
807
                                        if (btn->noSpellCheck())
808
                                                ite->annotation().addToFlag(Annotation::Flag_DoNotSpellCheck);
809
                                        if (btn->noScroll())
810
                                                ite->annotation().addToFlag(Annotation::Flag_DoNotScroll);
811
                                        int mxLen = btn->getMaxLen();
812
                                        if (mxLen > 0)
813
                                                ite->annotation().setMaxChar(mxLen);
814
                                        else
815
                                                ite->annotation().setMaxChar(-1);
816
                                        if (!btn->isReadOnly())
817
                                                ite->annotation().addToFlag(Annotation::Flag_Edit);
818
                                        handleActions(ite, ano);
819
                                }
820
                        }
821
                        else if (wtyp == Annotation::Checkbox)
822
                        {
823
                                FormWidgetButton *btn = (FormWidgetButton*)fm;
824
                                if (btn)
825
                                {
826
                                        ite->annotation().setIsChk(btn->getState());
827
                                        ite->annotation().setCheckState(ite->annotation().IsChk());
828
                                        handleActions(ite, ano);
829
                                        if (itemText == "4")
830
                                                ite->annotation().setChkStil(0);
831
                                        else if (itemText == "5")
832
                                                ite->annotation().setChkStil(1);
833
                                        else if (itemText == "F")
834
                                                ite->annotation().setChkStil(2);
835
                                        else if (itemText == "l")
836
                                                ite->annotation().setChkStil(3);
837
                                        else if (itemText == "H")
838
                                                ite->annotation().setChkStil(4);
839
                                        else if (itemText == "n")
840
                                                ite->annotation().setChkStil(5);
841
                                        else
842
                                                ite->annotation().setChkStil(0);
843
                                        if (!btn->isReadOnly())
844
                                                ite->annotation().addToFlag(Annotation::Flag_Edit);
845
                                }
846
                        }
847
                        else if ((wtyp == Annotation::Combobox) || (wtyp == Annotation::Listbox))
848
                        {
849
                                FormWidgetChoice *btn = (FormWidgetChoice*)fm;
850
                                if (btn)
851
                                {
852
                                        if (wtyp == 5)
853
                                                ite->annotation().addToFlag(Annotation::Flag_Combo);
854
                                        int co = btn->getNumChoices();
855
                                        if (co > 0)
856
                                        {
857
                                                QString inh = UnicodeParsedString(btn->getChoice(0));
858
                                                for (int a = 1; a < co; a++)
859
                                                {
860
                                                        inh += "\n" + UnicodeParsedString(btn->getChoice(a));
861
                                                }
862
                                                ite->itemText.insertChars(inh);
863
                                        }
25122 jghali 864
                                        applyTextStyle(ite, fontName, currTextColor, fontSize);
19590 jghali 865
                                        if (!btn->isReadOnly())
866
                                                ite->annotation().addToFlag(Annotation::Flag_Edit);
867
                                        handleActions(ite, ano);
868
                                }
869
                        }
870
                        else if (wtyp == Annotation::RadioButton)
871
                        {
872
                                FormWidgetButton *btn = (FormWidgetButton*)fm;
873
                                if (btn)
874
                                {
875
                                        ite->setItemName( CommonStrings::itemName_RadioButton + QString("%1").arg(m_doc->TotalItems));
876
                                        ite->annotation().setIsChk(btn->getState());
877
                                        ite->annotation().setCheckState(ite->annotation().IsChk());
878
                                        handleActions(ite, ano);
879
                                        m_radioButtons.insert(annota->getRef().num, ite);
880
                                }
881
                        }
882
                }
883
                break;
884
        }
885
        if (!found)
886
        {
887
                Object obj1;
888
                Ref refa = annota->getRef();
25122 jghali 889
                obj1 = m_xref->fetch(refa.num, refa.gen);
22154 jghali 890
                if (obj1.isDict())
891
                {
892
                        Dict* dict = obj1.getDict();
893
                        Object obj2 = dict->lookup("Kids");
894
                        //childs
895
                        if (obj2.isArray())
896
                        {
897
                                // Load children
898
                                QList<int> radList;
899
                                for (int i = 0; i < obj2.arrayGetLength(); i++)
900
                                {
25123 jghali 901
                                        const Object & childRef = obj2.arrayGetNF(i);
22154 jghali 902
                                        if (!childRef.isRef())
903
                                                continue;
904
                                        Object childObj = obj2.arrayGet(i);
905
                                        if (!childObj.isDict())
906
                                                continue;
907
                                        const Ref ref = childRef.getRef();
908
                                        radList.append(ref.num);
909
                                }
910
                                QString tmTxt = UnicodeParsedString(annota->getName());
911
                                m_radioMap.insert(tmTxt, radList);
912
                        }
913
                }
19590 jghali 914
        }
915
        return retVal;
916
}
917
 
22609 craig 918
void SlaOutputDev::applyTextStyle(PageItem* ite, const QString& fontName, const QString& textColor, double fontSize)
19590 jghali 919
{
920
        CharStyle newStyle;
921
        newStyle.setFillColor(textColor);
922
        newStyle.setFontSize(fontSize * 10);
923
        if (!fontName.isEmpty())
924
        {
925
                SCFontsIterator it(*m_doc->AllFonts);
926
                for ( ; it.hasNext() ; it.next())
927
                {
928
                        ScFace& face(it.current());
929
                        if ((face.psName() == fontName) && (face.usable()) && (face.type() == ScFace::TTF))
930
                        {
931
                                newStyle.setFont(face);
932
                                break;
933
                        }
22609 craig 934
                        if ((face.family() == fontName) && (face.usable()) && (face.type() == ScFace::TTF))
19590 jghali 935
                        {
936
                                newStyle.setFont(face);
937
                                break;
938
                        }
22609 craig 939
                        if ((face.scName() == fontName) && (face.usable()) && (face.type() == ScFace::TTF))
19590 jghali 940
                        {
941
                                newStyle.setFont(face);
942
                                break;
943
                        }
944
                }
945
        }
946
        ParagraphStyle dstyle(ite->itemText.defaultStyle());
947
        dstyle.charStyle().applyCharStyle(newStyle);
948
        ite->itemText.setDefaultStyle(dstyle);
949
        ite->itemText.applyCharStyle(0, ite->itemText.length(), newStyle);
950
        ite->invalid = true;
951
}
952
 
953
void SlaOutputDev::handleActions(PageItem* ite, AnnotWidget *ano)
954
{
955
        LinkAction *Lact = ano->getAction();
956
        if (Lact)
957
        {
958
                if (Lact->getKind() == actionJavaScript)
959
                {
960
                        LinkJavaScript *jsa = (LinkJavaScript*)Lact;
961
                        if (jsa->isOk())
962
                        {
963
                                ite->annotation().setActionType(1);
964
                                ite->annotation().setAction(UnicodeParsedString(jsa->getScript()));
965
                        }
966
                }
967
                else if (Lact->getKind() == actionGoTo)
968
                {
969
                        int pagNum = 0;
970
                        int xco = 0;
971
                        int yco = 0;
972
                        LinkGoTo *gto = (LinkGoTo*)Lact;
25123 jghali 973
                        const LinkDest *dst = gto->getDest();
19590 jghali 974
                        if (dst)
975
                        {
976
                                if (dst->getKind() == destXYZ)
977
                                {
978
                                        if (dst->isPageRef())
979
                                        {
980
                                                Ref dstr = dst->getPageRef();
25122 jghali 981
                                                pagNum = m_pdfDoc->findPage(dstr);
19590 jghali 982
                                        }
983
                                        else
984
                                                pagNum = dst->getPageNum();
985
                                        xco = dst->getLeft();
986
                                        yco = dst->getTop();
21458 jghali 987
                                        ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1));
19590 jghali 988
                                        ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco));
989
                                        ite->annotation().setActionType(2);
990
                                }
991
                        }
992
                        else
993
                        {
25123 jghali 994
                                const GooString *ndst = gto->getNamedDest();
19590 jghali 995
                                if (ndst)
996
                                {
25122 jghali 997
                                        std::unique_ptr<LinkDest> dstn = m_pdfDoc->findDest(ndst);
19590 jghali 998
                                        if (dstn)
999
                                        {
1000
                                                if (dstn->getKind() == destXYZ)
1001
                                                {
1002
                                                        if (dstn->isPageRef())
1003
                                                        {
1004
                                                                Ref dstr = dstn->getPageRef();
25122 jghali 1005
                                                                pagNum = m_pdfDoc->findPage(dstr);
19590 jghali 1006
                                                        }
1007
                                                        else
1008
                                                                pagNum = dstn->getPageNum();
1009
                                                        xco = dstn->getLeft();
1010
                                                        yco = dstn->getTop();
21458 jghali 1011
                                                        ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1));
19590 jghali 1012
                                                        ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco));
1013
                                                        ite->annotation().setActionType(2);
1014
                                                }
1015
                                        }
1016
                                }
1017
                        }
1018
                }
1019
                else if (Lact->getKind() == actionGoToR)
1020
                {
1021
                        int pagNum = 0;
1022
                        int xco = 0;
1023
                        int yco = 0;
1024
                        LinkGoToR *gto = (LinkGoToR*)Lact;
1025
                        QString fileName = UnicodeParsedString(gto->getFileName());
25123 jghali 1026
                        const LinkDest *dst = gto->getDest();
19590 jghali 1027
                        if (dst)
1028
                        {
1029
                                if (dst->getKind() == destXYZ)
1030
                                {
1031
                                        pagNum = dst->getPageNum();
1032
                                        xco = dst->getLeft();
1033
                                        yco = dst->getTop();
21458 jghali 1034
                                        ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1));
19590 jghali 1035
                                        ite->annotation().setExtern(fileName);
1036
                                        ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco));
1037
                                        ite->annotation().setActionType(9);
1038
                                }
1039
                        }
1040
                        else
1041
                        {
25123 jghali 1042
                                const GooString *ndst = gto->getNamedDest();
19590 jghali 1043
                                if (ndst)
1044
                                {
25122 jghali 1045
                                        std::unique_ptr<LinkDest> dstn = m_pdfDoc->findDest(ndst);
19590 jghali 1046
                                        if (dstn)
1047
                                        {
1048
                                                if (dstn->getKind() == destXYZ)
1049
                                                {
1050
                                                        pagNum = dstn->getPageNum();
1051
                                                        xco = dstn->getLeft();
1052
                                                        yco = dstn->getTop();
21458 jghali 1053
                                                        ite->annotation().setZiel((pagNum > 0) ? (pagNum - 1) : (m_actPage - 1));
19590 jghali 1054
                                                        ite->annotation().setExtern(fileName);
1055
                                                        ite->annotation().setAction(QString("%1 %2").arg(xco).arg(yco));
1056
                                                        ite->annotation().setActionType(9);
1057
                                                }
1058
                                        }
1059
                                }
1060
                        }
1061
                }
1062
                else if (Lact->getKind() == actionUnknown)
1063
                {
1064
                        LinkUnknown *uno = (LinkUnknown*)Lact;
1065
                        QString actString = UnicodeParsedString(uno->getAction());
1066
                        if (actString == "ResetForm")
1067
                        {
1068
                                ite->annotation().setActionType(4);
1069
                        }
1070
                        else
1071
                        {
1072
                                LinkAction* scact = SC_getAction(ano);
1073
                                if (scact)
1074
                                {
1075
                                        if (actString == "ImportData")
1076
                                        {
1077
                                                LinkImportData *impo = (LinkImportData*)scact;
1078
                                                if (impo->isOk())
1079
                                                {
1080
                                                        ite->annotation().setActionType(5);
1081
                                                        ite->annotation().setAction(UnicodeParsedString(impo->getFileName()));
1082
                                                }
1083
                                        }
1084
                                        else if (actString == "SubmitForm")
1085
                                        {
1086
                                                LinkSubmitForm *impo = (LinkSubmitForm*)scact;
1087
                                                if (impo->isOk())
1088
                                                {
1089
                                                        ite->annotation().setActionType(3);
1090
                                                        ite->annotation().setAction(UnicodeParsedString(impo->getFileName()));
1091
                                                        int fl = impo->getFlags();
1092
                                                        if (fl == 0)
1093
                                                                ite->annotation().setHTML(0);
1094
                                                        else if (fl == 4)
1095
                                                                ite->annotation().setHTML(1);
1096
                                                        else if (fl == 64)
1097
                                                                ite->annotation().setHTML(2);
1098
                                                        else if (fl == 512)
1099
                                                                ite->annotation().setHTML(3);
1100
                                                }
1101
                                        }
1102
                                }
1103
                        }
1104
                }
1105
                else if (Lact->getKind() == actionNamed)
1106
                {
1107
                        LinkNamed *uno = (LinkNamed*)Lact;
1108
                        ite->annotation().setActionType(10);
1109
                        ite->annotation().setAction(UnicodeParsedString(uno->getName()));
1110
                }
1111
                else
1112
                        qDebug() << "Found unsupported Action of type" << Lact->getKind();
1113
        }
23478 jghali 1114
        auto Aact = SC_getAdditionalAction("D", ano);
19590 jghali 1115
        if (Aact)
1116
        {
1117
                if (Aact->getKind() == actionJavaScript)
1118
                {
23478 jghali 1119
                        LinkJavaScript *jsa = (LinkJavaScript*) Aact.get();
19590 jghali 1120
                        if (jsa->isOk())
1121
                        {
1122
                                ite->annotation().setD_act(UnicodeParsedString(jsa->getScript()));
1123
                                ite->annotation().setAAact(true);
1124
                        }
1125
                }
23478 jghali 1126
                Aact.reset();
19590 jghali 1127
        }
1128
        Aact = SC_getAdditionalAction("E", ano);
1129
        if (Aact)
1130
        {
1131
                if (Aact->getKind() == actionJavaScript)
1132
                {
23478 jghali 1133
                        LinkJavaScript *jsa = (LinkJavaScript*) Aact.get();
19590 jghali 1134
                        if (jsa->isOk())
1135
                        {
1136
                                ite->annotation().setE_act(UnicodeParsedString(jsa->getScript()));
1137
                                ite->annotation().setAAact(true);
1138
                        }
1139
                }
23478 jghali 1140
                Aact.reset();
19590 jghali 1141
        }
1142
        Aact = SC_getAdditionalAction("X", ano);
1143
        if (Aact)
1144
        {
1145
                if (Aact->getKind() == actionJavaScript)
1146
                {
23478 jghali 1147
                        LinkJavaScript *jsa = (LinkJavaScript*) Aact.get();
19590 jghali 1148
                        if (jsa->isOk())
1149
                        {
1150
                                ite->annotation().setX_act(UnicodeParsedString(jsa->getScript()));
1151
                                ite->annotation().setAAact(true);
1152
                        }
1153
                }
23478 jghali 1154
                Aact.reset();
19590 jghali 1155
        }
1156
        Aact = SC_getAdditionalAction("Fo", ano);
1157
        if (Aact)
1158
        {
1159
                if (Aact->getKind() == actionJavaScript)
1160
                {
23478 jghali 1161
                        LinkJavaScript *jsa = (LinkJavaScript*) Aact.get();
19590 jghali 1162
                        if (jsa->isOk())
1163
                        {
1164
                                ite->annotation().setFo_act(UnicodeParsedString(jsa->getScript()));
1165
                                ite->annotation().setAAact(true);
1166
                        }
1167
                }
23478 jghali 1168
                Aact.reset();
19590 jghali 1169
        }
1170
        Aact = SC_getAdditionalAction("Bl", ano);
1171
        if (Aact)
1172
        {
1173
                if (Aact->getKind() == actionJavaScript)
1174
                {
23478 jghali 1175
                        LinkJavaScript *jsa = (LinkJavaScript*) Aact.get();
19590 jghali 1176
                        if (jsa->isOk())
1177
                        {
1178
                                ite->annotation().setBl_act(UnicodeParsedString(jsa->getScript()));
1179
                                ite->annotation().setAAact(true);
1180
                        }
1181
                }
23478 jghali 1182
                Aact.reset();
19590 jghali 1183
        }
1184
        Aact = SC_getAdditionalAction("C", ano);
1185
        if (Aact)
1186
        {
1187
                if (Aact->getKind() == actionJavaScript)
1188
                {
23478 jghali 1189
                        LinkJavaScript *jsa = (LinkJavaScript*) Aact.get();
19590 jghali 1190
                        if (jsa->isOk())
1191
                        {
1192
                                ite->annotation().setC_act(UnicodeParsedString(jsa->getScript()));
1193
                                ite->annotation().setAAact(true);
1194
                        }
1195
                }
23478 jghali 1196
                Aact.reset();
19590 jghali 1197
        }
1198
        Aact = SC_getAdditionalAction("F", ano);
1199
        if (Aact)
1200
        {
1201
                if (Aact->getKind() == actionJavaScript)
1202
                {
23478 jghali 1203
                        LinkJavaScript *jsa = (LinkJavaScript*) Aact.get();
19590 jghali 1204
                        if (jsa->isOk())
1205
                        {
1206
                                ite->annotation().setF_act(UnicodeParsedString(jsa->getScript()));
1207
                                ite->annotation().setAAact(true);
1208
                                ite->annotation().setFormat(5);
1209
                        }
1210
                }
23478 jghali 1211
                Aact.reset();
19590 jghali 1212
        }
1213
        Aact = SC_getAdditionalAction("K", ano);
1214
        if (Aact)
1215
        {
1216
                if (Aact->getKind() == actionJavaScript)
1217
                {
23478 jghali 1218
                        LinkJavaScript *jsa = (LinkJavaScript*) Aact.get();
19590 jghali 1219
                        if (jsa->isOk())
1220
                        {
1221
                                ite->annotation().setK_act(UnicodeParsedString(jsa->getScript()));
1222
                                ite->annotation().setAAact(true);
1223
                                ite->annotation().setFormat(5);
1224
                        }
1225
                }
23478 jghali 1226
                Aact.reset();
19590 jghali 1227
        }
1228
        Aact = SC_getAdditionalAction("V", ano);
1229
        if (Aact)
1230
        {
1231
                if (Aact->getKind() == actionJavaScript)
1232
                {
23478 jghali 1233
                        LinkJavaScript *jsa = (LinkJavaScript*) Aact.get();
19590 jghali 1234
                        if (jsa->isOk())
1235
                        {
1236
                                ite->annotation().setV_act(UnicodeParsedString(jsa->getScript()));
1237
                                ite->annotation().setAAact(true);
1238
                        }
1239
                }
23478 jghali 1240
                Aact.reset();
19590 jghali 1241
        }
1242
}
1243
 
1244
void SlaOutputDev::startDoc(PDFDoc *doc, XRef *xrefA, Catalog *catA)
1245
{
25122 jghali 1246
        m_xref = xrefA;
1247
        m_catalog = catA;
1248
        m_pdfDoc = doc;
1249
        m_updateGUICounter = 0;
23431 jghali 1250
        m_fontEngine = new SplashFontEngine(true, false, false, true);
19590 jghali 1251
}
1252
 
19595 jghali 1253
void SlaOutputDev::startPage(int pageNum, GfxState *, XRef *)
19590 jghali 1254
{
25122 jghali 1255
        m_formWidgets = m_pdfDoc->getPage(pageNum)->getFormWidgets();
19590 jghali 1256
        m_radioMap.clear();
1257
        m_radioButtons.clear();
1258
        m_actPage = pageNum;
25120 jghali 1259
        m_graphicStack.clear();
20011 fschmid 1260
        m_groupStack.clear();
1261
        pushGroup();
19590 jghali 1262
}
1263
 
1264
void SlaOutputDev::endPage()
1265
{
1266
        if (!m_radioMap.isEmpty())
1267
        {
22509 jghali 1268
                for (auto it = m_radioMap.begin(); it != m_radioMap.end(); ++it)
19590 jghali 1269
                {
25122 jghali 1270
                        m_tmpSel->clear();
19590 jghali 1271
                        QList<int> refList = it.value();
1272
                        for (int a = 0; a < refList.count(); a++)
1273
                        {
1274
                                if (m_radioButtons.contains(refList[a]))
1275
                                {
25122 jghali 1276
                                        m_tmpSel->addItem(m_radioButtons[refList[a]], true);
19590 jghali 1277
                                        m_Elements->removeAll(m_radioButtons[refList[a]]);
1278
                                }
1279
                        }
25122 jghali 1280
                        if (!m_tmpSel->isEmpty())
19590 jghali 1281
                        {
25122 jghali 1282
                                PageItem *ite = m_doc->groupObjectsSelection(m_tmpSel);
19590 jghali 1283
                                ite->setItemName(it.key());
1284
                                m_Elements->append(ite);
1285
                                if (m_groupStack.count() != 0)
1286
                                        m_groupStack.top().Items.append(ite);
1287
                        }
1288
                }
1289
        }
1290
        m_radioMap.clear();
1291
        m_radioButtons.clear();
1292
//      qDebug() << "ending page";
1293
}
1294
 
1295
void SlaOutputDev::saveState(GfxState *state)
1296
{
25120 jghali 1297
        m_graphicStack.save();
20011 fschmid 1298
        pushGroup();
19590 jghali 1299
}
1300
 
1301
void SlaOutputDev::restoreState(GfxState *state)
1302
{
1303
        if (m_groupStack.count() != 0)
1304
        {
20011 fschmid 1305
                groupEntry gElements = m_groupStack.pop();
1306
                if (gElements.Items.count() > 0)
19590 jghali 1307
                {
20625 fschmid 1308
                        if ((gElements.Items.count() > 1) && (checkClip()))
19590 jghali 1309
                        {
25122 jghali 1310
                                m_tmpSel->clear();
20011 fschmid 1311
                                for (int dre = 0; dre < gElements.Items.count(); ++dre)
19590 jghali 1312
                                {
25122 jghali 1313
                                        m_tmpSel->addItem(gElements.Items.at(dre), true);
20011 fschmid 1314
                                        m_Elements->removeAll(gElements.Items.at(dre));
19590 jghali 1315
                                }
25122 jghali 1316
                                PageItem *ite = m_doc->groupObjectsSelection(m_tmpSel);
20625 fschmid 1317
                                if (ite)
19590 jghali 1318
                                {
25120 jghali 1319
                                        QPainterPath clippath = m_graphicStack.top().clipPath;
23536 jghali 1320
                                        clippath.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset());
1321
                                        clippath.translate(-ite->xPos(), -ite->yPos());
1322
                                        ite->PoLine.fromQPainterPath(clippath, true);
23319 jghali 1323
                                        ite->ClipEdited = true;
1324
                                        ite->FrameType = 3;
20625 fschmid 1325
                                        ite->setTextFlowMode(PageItem::TextFlowDisabled);
23319 jghali 1326
                                        // Comment out temporarily, there are some bad interactions between adjustItemSize() and
1327
                                        // resizeGroupToContents() since fixing resizing of multiple selections
1328
                                        //m_doc->adjustItemSize(ite, true);
20625 fschmid 1329
                                        m_doc->resizeGroupToContents(ite);
1330
                                        ite->OldB2 = ite->width();
1331
                                        ite->OldH2 = ite->height();
1332
                                        m_Elements->append(ite);
1333
                                        if (m_groupStack.count() != 0)
1334
                                        {
1335
                                                applyMask(ite);
1336
                                                m_groupStack.top().Items.append(ite);
1337
                                        }
19590 jghali 1338
                                }
20628 fschmid 1339
                                else
1340
                                {
1341
                                        if (m_groupStack.count() != 0)
1342
                                        {
1343
                                                for (int dre = 0; dre < gElements.Items.count(); ++dre)
1344
                                                {
1345
                                                        PageItem *ite = gElements.Items.at(dre);
1346
                                                        applyMask(ite);
1347
                                                        m_groupStack.top().Items.append(ite);
1348
                                                }
1349
                                        }
1350
                                }
25122 jghali 1351
                                m_tmpSel->clear();
19590 jghali 1352
                        }
20011 fschmid 1353
                        else
1354
                        {
1355
                                if (m_groupStack.count() != 0)
1356
                                {
1357
                                        for (int dre = 0; dre < gElements.Items.count(); ++dre)
1358
                                        {
1359
                                                PageItem *ite = gElements.Items.at(dre);
1360
                                                applyMask(ite);
1361
                                                m_groupStack.top().Items.append(ite);
1362
                                        }
1363
                                }
1364
                        }
19590 jghali 1365
                }
1366
        }
25120 jghali 1367
 
1368
        m_graphicStack.restore();
19590 jghali 1369
}
20011 fschmid 1370
 
25123 jghali 1371
void SlaOutputDev::beginTransparencyGroup(GfxState *state, const double *bbox, GfxColorSpace * /*blendingColorSpace*/, bool isolated, bool knockout, bool forSoftMask)
19590 jghali 1372
{
23550 jghali 1373
//      qDebug() << "SlaOutputDev::beginTransparencyGroup isolated:" << isolated << "knockout:" << knockout << "forSoftMask:" << forSoftMask;
20011 fschmid 1374
        pushGroup("", forSoftMask);
20125 fschmid 1375
        m_groupStack.top().isolated = isolated;
19590 jghali 1376
}
20011 fschmid 1377
 
25123 jghali 1378
void SlaOutputDev::paintTransparencyGroup(GfxState *state, const double *bbox)
19590 jghali 1379
{
23550 jghali 1380
//      qDebug() << "SlaOutputDev::paintTransparencyGroup";
20011 fschmid 1381
        if (m_groupStack.count() != 0)
1382
        {
1383
                if ((m_groupStack.top().Items.count() != 0) && (!m_groupStack.top().forSoftMask))
1384
                {
1385
                        PageItem *ite = m_groupStack.top().Items.last();
1386
                        ite->setFillTransparency(1.0 - state->getFillOpacity());
1387
                        ite->setFillBlendmode(getBlendMode(state));
1388
                }
1389
        }
19590 jghali 1390
}
1391
 
1392
void SlaOutputDev::endTransparencyGroup(GfxState *state)
1393
{
23550 jghali 1394
//      qDebug() << "SlaOutputDev::endTransparencyGroup";
22991 jghali 1395
        if (m_groupStack.count() <= 0)
1396
                return;
1397
 
25122 jghali 1398
        m_tmpSel->clear();
22991 jghali 1399
 
1400
        groupEntry gElements = m_groupStack.pop();
1401
        if (gElements.Items.count() <= 0)
1402
                return;
1403
 
1404
        if (gElements.forSoftMask)
19590 jghali 1405
        {
22991 jghali 1406
                for (int dre = 0; dre < gElements.Items.count(); ++dre)
19590 jghali 1407
                {
25122 jghali 1408
                        m_tmpSel->addItem(gElements.Items.at(dre), true);
22991 jghali 1409
                        m_Elements->removeAll(gElements.Items.at(dre));
19590 jghali 1410
                }
25122 jghali 1411
                PageItem *ite = m_doc->groupObjectsSelection(m_tmpSel);
22991 jghali 1412
                ite->setFillTransparency(1.0 - state->getFillOpacity());
1413
                ite->setFillBlendmode(getBlendMode(state));
24744 jghali 1414
                ScPattern pat(m_doc);
22991 jghali 1415
                m_doc->DoDrawing = true;
1416
                pat.pattern = ite->DrawObj_toImage(qMin(qMax(ite->width(), ite->height()), 500.0));
1417
                pat.xoffset = 0;
1418
                pat.yoffset = 0;
1419
                m_doc->DoDrawing = false;
1420
                pat.width = ite->width();
1421
                pat.height = ite->height();
23550 jghali 1422
                m_currentMaskPosition = QPointF(ite->xPos(), ite->yPos());
22991 jghali 1423
                ite->gXpos = 0;
1424
                ite->gYpos = 0;
1425
                ite->setXYPos(ite->gXpos, ite->gYpos, true);
1426
                pat.items.append(ite);
1427
                m_doc->Items->removeAll(ite);
1428
                QString id = QString("Pattern_from_PDF_%1S").arg(m_doc->docPatterns.count() + 1);
1429
                m_doc->addPattern(id, pat);
1430
                m_currentMask = id;
25122 jghali 1431
                m_tmpSel->clear();
22991 jghali 1432
                return;
19590 jghali 1433
        }
22991 jghali 1434
        PageItem *ite;
1435
        for (int dre = 0; dre < gElements.Items.count(); ++dre)
1436
        {
25122 jghali 1437
                m_tmpSel->addItem(gElements.Items.at(dre), true);
22991 jghali 1438
                m_Elements->removeAll(gElements.Items.at(dre));
1439
        }
1440
        if ((gElements.Items.count() != 1) || (gElements.isolated))
25122 jghali 1441
                ite = m_doc->groupObjectsSelection(m_tmpSel);
22991 jghali 1442
        else
1443
                ite = gElements.Items.first();
1444
        if (ite->isGroup())
1445
        {
1446
                ite->ClipEdited = true;
1447
                ite->FrameType = 3;
1448
                if (checkClip())
1449
                {
25120 jghali 1450
                        QPainterPath clippath = m_graphicStack.top().clipPath;
23536 jghali 1451
                        clippath.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset());
1452
                        clippath.translate(-ite->xPos(), -ite->yPos());
1453
                        ite->PoLine.fromQPainterPath(clippath, true);
23319 jghali 1454
                        ite->ClipEdited = true;
1455
                        ite->FrameType = 3;
22991 jghali 1456
                        ite->setTextFlowMode(PageItem::TextFlowDisabled);
23319 jghali 1457
                        // Comment out temporarily, there are some bad interactions between adjustItemSize() and
1458
                        // resizeGroupToContents() since fixing resizing of multiple selections
1459
                        //m_doc->adjustItemSize(ite, true);
22991 jghali 1460
                        m_doc->resizeGroupToContents(ite);
1461
                        ite->OldB2 = ite->width();
1462
                        ite->OldH2 = ite->height();
1463
                }
1464
        }
1465
        ite->setFillTransparency(1.0 - state->getFillOpacity());
1466
        ite->setFillBlendmode(getBlendMode(state));
1467
        m_Elements->append(ite);
1468
        if (m_groupStack.count() != 0)
1469
        {
1470
                applyMask(ite);
1471
                m_groupStack.top().Items.append(ite);
1472
        }
1473
 
25122 jghali 1474
        m_tmpSel->clear();
19590 jghali 1475
}
1476
 
25123 jghali 1477
void SlaOutputDev::setSoftMask(GfxState * /*state*/, const double * bbox, bool alpha, Function *transferFunc, GfxColor * /*backdropColor*/)
19590 jghali 1478
{
22991 jghali 1479
        if (m_groupStack.count() <= 0)
1480
                return;
1481
 
1482
        double lum = 0;
1483
        double lum2 = 0;
1484
        if (transferFunc)
1485
                transferFunc->transform(&lum, &lum2);
1486
        else
1487
                lum2 = lum;
24257 jghali 1488
        m_groupStack.top().inverted = (lum != lum2);
22991 jghali 1489
        m_groupStack.top().maskName = m_currentMask;
23550 jghali 1490
        // Remember the mask's position as it might not align with the image to which the mask is later assigned.
1491
        m_groupStack.top().maskPos = m_currentMaskPosition;
22991 jghali 1492
        m_groupStack.top().alpha = alpha;
1493
        if (m_groupStack.top().Items.count() != 0)
1494
                applyMask(m_groupStack.top().Items.last());
19590 jghali 1495
}
1496
 
1497
void SlaOutputDev::clearSoftMask(GfxState * /*state*/)
1498
{
1499
        if (m_groupStack.count() != 0)
1500
                m_groupStack.top().maskName = "";
1501
}
1502
 
1503
void SlaOutputDev::updateFillColor(GfxState *state)
1504
{
25120 jghali 1505
        auto& graphicState = m_graphicStack.top();
1506
        graphicState.fillShade = 100;
1507
        graphicState.fillColor = getColor(state->getFillColorSpace(), state->getFillColor(), &graphicState.fillShade);
19590 jghali 1508
}
1509
 
1510
void SlaOutputDev::updateStrokeColor(GfxState *state)
1511
{
25120 jghali 1512
        auto& graphicState = m_graphicStack.top();
1513
        graphicState.strokeShade = 100;
1514
        graphicState.strokeColor = getColor(state->getStrokeColorSpace(), state->getStrokeColor(), &graphicState.strokeShade);
19590 jghali 1515
}
1516
 
1517
void SlaOutputDev::clip(GfxState *state)
1518
{
1519
//      qDebug() << "Clip";
23536 jghali 1520
        adjustClip(state, Qt::WindingFill);
1521
}
1522
 
1523
void SlaOutputDev::eoClip(GfxState *state)
1524
{
1525
//      qDebug() << "EoClip";
1526
        adjustClip(state, Qt::OddEvenFill);
1527
}
1528
 
1529
void SlaOutputDev::adjustClip(GfxState *state, Qt::FillRule fillRule)
1530
{
1531
        const double *ctm = state->getCTM();
19590 jghali 1532
        m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
1533
        QString output = convertPath(state->getPath());
22991 jghali 1534
        if (output.isEmpty())
1535
                return;
19590 jghali 1536
        FPointArray out;
22991 jghali 1537
        out.parseSVG(output);
1538
        out.svgClosePath();
1539
        out.map(m_ctm);
1540
        if (checkClip())
19590 jghali 1541
        {
23536 jghali 1542
                // "clip" (WindingFill) and "eoClip" (OddEvenFill) only the determine
1543
                // the fill rule of the new clipping path. The new clip should be the
1544
                // intersection of the old and new area. QPainterPath determines on
1545
                // its own which fill rule to use for the result. We should not loose
1546
                // this information.
1547
                QPainterPath pathN = out.toQPainterPath(false);
1548
                pathN.setFillRule(fillRule);
25120 jghali 1549
                m_graphicStack.top().clipPath = intersection(pathN, m_graphicStack.top().clipPath);
19590 jghali 1550
        }
22991 jghali 1551
        else
25120 jghali 1552
                m_graphicStack.top().clipPath = out.toQPainterPath(false);
19590 jghali 1553
}
1554
 
1555
void SlaOutputDev::stroke(GfxState *state)
1556
{
1557
//      qDebug() << "Stroke";
25120 jghali 1558
        const double *ctm = state->getCTM();
19590 jghali 1559
        double xCoor = m_doc->currentPage()->xOffset();
1560
        double yCoor = m_doc->currentPage()->yOffset();
25120 jghali 1561
        getPenState(state);
1562
 
1563
        auto& graphicState = m_graphicStack.top();
1564
        graphicState.strokeColor = getColor(state->getStrokeColorSpace(), state->getStrokeColor(), &graphicState.strokeShade);
1565
 
19590 jghali 1566
        QString output = convertPath(state->getPath());
25122 jghali 1567
        if ((m_Elements->count() != 0) && (output == m_coords))                 // Path is the same as in last fill
19590 jghali 1568
        {
1569
                PageItem* ite = m_Elements->last();
25120 jghali 1570
                ite->setLineColor(graphicState.strokeColor);
1571
                ite->setLineShade(graphicState.strokeShade);
24374 jghali 1572
                ite->setLineEnd(m_lineEnd);
1573
                ite->setLineJoin(m_lineJoin);
19590 jghali 1574
                ite->setLineWidth(state->getTransformedLineWidth());
25122 jghali 1575
                ite->setDashes(m_dashValues);
1576
                ite->setDashOffset(m_dashOffset);
19590 jghali 1577
                ite->setLineTransparency(1.0 - state->getStrokeOpacity());
25120 jghali 1578
                return;
19590 jghali 1579
        }
25120 jghali 1580
 
1581
        FPointArray out;
1582
        out.parseSVG(output);
1583
        m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
1584
        out.map(m_ctm);
1585
        FPoint wh = out.widthHeight();
1586
        if ((out.size() <= 3) || ((wh.x() <= 0.0) && (wh.y() <= 0.0)))
1587
                return;
1588
 
1589
        int z;
25123 jghali 1590
        if (m_pathIsClosed)
25120 jghali 1591
                z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
19590 jghali 1592
        else
25120 jghali 1593
                z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
1594
        PageItem* ite = m_doc->Items->at(z);
1595
        ite->PoLine = out.copy();
1596
        ite->ClipEdited = true;
1597
        ite->FrameType = 3;
1598
        ite->setWidthHeight(wh.x(), wh.y());
1599
        m_doc->adjustItemSize(ite);
1600
        if (m_Elements->count() != 0)
19590 jghali 1601
        {
25120 jghali 1602
                PageItem* lItem = m_Elements->last();
1603
                if ((lItem->lineColor() == CommonStrings::None) && (lItem->PoLine == ite->PoLine))
19590 jghali 1604
                {
25120 jghali 1605
                        lItem->setLineColor(graphicState.strokeColor);
1606
                        lItem->setLineWidth(state->getTransformedLineWidth());
1607
                        lItem->setLineShade(graphicState.strokeShade);
1608
                        lItem->setLineTransparency(1.0 - state->getStrokeOpacity());
1609
                        lItem->setLineBlendmode(getBlendMode(state));
1610
                        lItem->setLineEnd(m_lineEnd);
1611
                        lItem->setLineJoin(m_lineJoin);
25122 jghali 1612
                        lItem->setDashes(m_dashValues);
1613
                        lItem->setDashOffset(m_dashOffset);
25120 jghali 1614
                        lItem->setTextFlowMode(PageItem::TextFlowDisabled);
1615
                        m_doc->Items->removeAll(ite);
19590 jghali 1616
                }
25120 jghali 1617
                else
1618
                {
1619
                        ite->setLineShade(graphicState.strokeShade);
1620
                        ite->setLineTransparency(1.0 - state->getStrokeOpacity());
1621
                        ite->setLineBlendmode(getBlendMode(state));
1622
                        ite->setLineEnd(m_lineEnd);
1623
                        ite->setLineJoin(m_lineJoin);
25122 jghali 1624
                        ite->setDashes(m_dashValues);
1625
                        ite->setDashOffset(m_dashOffset);
25120 jghali 1626
                        ite->setTextFlowMode(PageItem::TextFlowDisabled);
1627
                        m_Elements->append(ite);
1628
                        if (m_groupStack.count() != 0)
1629
                                m_groupStack.top().Items.append(ite);
1630
                }
19590 jghali 1631
        }
25120 jghali 1632
        else
1633
        {
1634
                ite->setLineShade(graphicState.strokeShade);
1635
                ite->setLineTransparency(1.0 - state->getStrokeOpacity());
1636
                ite->setLineBlendmode(getBlendMode(state));
1637
                ite->setLineEnd(m_lineEnd);
1638
                ite->setLineJoin(m_lineJoin);
25122 jghali 1639
                ite->setDashes(m_dashValues);
1640
                ite->setDashOffset(m_dashOffset);
25120 jghali 1641
                ite->setTextFlowMode(PageItem::TextFlowDisabled);
1642
                m_Elements->append(ite);
1643
                if (m_groupStack.count() != 0)
1644
                        m_groupStack.top().Items.append(ite);
1645
        }
19590 jghali 1646
}
1647
 
1648
void SlaOutputDev::fill(GfxState *state)
1649
{
1650
//      qDebug() << "Fill";
23536 jghali 1651
        createFillItem(state, Qt::WindingFill);
19590 jghali 1652
}
1653
 
1654
void SlaOutputDev::eoFill(GfxState *state)
1655
{
1656
//      qDebug() << "EoFill";
23536 jghali 1657
        createFillItem(state, Qt::OddEvenFill);
1658
}
1659
 
1660
void SlaOutputDev::createFillItem(GfxState *state, Qt::FillRule fillRule)
1661
{
22741 jghali 1662
        const double *ctm;
19590 jghali 1663
        ctm = state->getCTM();
23550 jghali 1664
        m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
19590 jghali 1665
        double xCoor = m_doc->currentPage()->xOffset();
1666
        double yCoor = m_doc->currentPage()->yOffset();
1667
        FPointArray out;
1668
        QString output = convertPath(state->getPath());
1669
        out.parseSVG(output);
1670
        out.map(m_ctm);
23536 jghali 1671
 
25120 jghali 1672
        auto& graphicState = m_graphicStack.top();
1673
 
23536 jghali 1674
        // Clip the new path first and only add it if it is not empty.
1675
        QPainterPath path = out.toQPainterPath(false);
1676
        path.setFillRule(fillRule);
25120 jghali 1677
        QPainterPath clippedPath = intersection(graphicState.clipPath, path);
23536 jghali 1678
 
23550 jghali 1679
        // Undo the rotation of the clipping path as it is rotated together with the item.
1680
        double angle = m_ctm.map(QLineF(0, 0, 1, 0)).angle();
1681
        QTransform mm;
1682
        mm.rotate(angle);
1683
        clippedPath = mm.map(clippedPath);
1684
 
25122 jghali 1685
        m_coords = output;
23536 jghali 1686
        QRectF bbox = clippedPath.boundingRect();
1687
        if (!clippedPath.isEmpty() && !bbox.isNull())
19590 jghali 1688
        {
25120 jghali 1689
                graphicState.fillColor = getColor(state->getFillColorSpace(), state->getFillColor(), &graphicState.fillShade);
19590 jghali 1690
                int z;
25123 jghali 1691
                if (m_pathIsClosed)
25120 jghali 1692
                        z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
19590 jghali 1693
                else
25120 jghali 1694
                        z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
19590 jghali 1695
                PageItem* ite = m_doc->Items->at(z);
23536 jghali 1696
                ite->PoLine.fromQPainterPath(clippedPath, true);
19590 jghali 1697
                ite->ClipEdited = true;
1698
                ite->FrameType = 3;
25120 jghali 1699
                ite->setFillShade(graphicState.fillShade);
19590 jghali 1700
                ite->setLineShade(100);
23550 jghali 1701
                ite->setRotation(-angle);
23536 jghali 1702
                // Only the new path has to be interpreted according to fillRule. QPainterPath
1703
                // could decide to create a final path according to the other rule. Thus
1704
                // we have to set this from the final path.
1705
                ite->setFillEvenOdd(clippedPath.fillRule() == Qt::OddEvenFill);
19590 jghali 1706
                ite->setFillTransparency(1.0 - state->getFillOpacity());
1707
                ite->setFillBlendmode(getBlendMode(state));
24374 jghali 1708
                ite->setLineEnd(m_lineEnd);
1709
                ite->setLineJoin(m_lineJoin);
23536 jghali 1710
                ite->setWidthHeight(bbox.width(),bbox.height());
19590 jghali 1711
                ite->setTextFlowMode(PageItem::TextFlowDisabled);
20694 craig 1712
                m_doc->adjustItemSize(ite);
19590 jghali 1713
                m_Elements->append(ite);
1714
                if (m_groupStack.count() != 0)
1715
                {
1716
                        m_groupStack.top().Items.append(ite);
1717
                        applyMask(ite);
1718
                }
1719
        }
1720
}
1721
 
25123 jghali 1722
bool SlaOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax)
19590 jghali 1723
{
23536 jghali 1724
//      qDebug() << "SlaOutputDev::axialShadedFill";
19590 jghali 1725
        double GrStartX;
1726
        double GrStartY;
1727
        double GrEndX;
1728
        double GrEndY;
1729
        int shade = 100;
25123 jghali 1730
        const Function *func = shading->getFunc(0);
19590 jghali 1731
        VGradient FillGradient = VGradient(VGradient::linear);
1732
        FillGradient.clearStops();
1733
        GfxColorSpace *color_space = shading->getColorSpace();
1734
        if (func->getType() == 3)
1735
        {
1736
                StitchingFunction *stitchingFunc = (StitchingFunction*)func;
22741 jghali 1737
                const double *bounds = stitchingFunc->getBounds();
19590 jghali 1738
                int num_funcs = stitchingFunc->getNumFuncs();
22978 jghali 1739
                double domain_min = stitchingFunc->getDomainMin(0);
1740
                double domain_max = stitchingFunc->getDomainMax(0);
1741
                if (fabs(domain_max - domain_min) < 1e-6)
1742
                {
1743
                        domain_min = 0.0;
1744
                        domain_max = 1.0;
1745
                }
19590 jghali 1746
                // Add stops from all the stitched functions
22978 jghali 1747
                for (int i = 0 ; i <= num_funcs ; i++)
19590 jghali 1748
                {
1749
                        GfxColor temp;
22978 jghali 1750
                        shading->getColor(bounds[i], &temp);
19590 jghali 1751
                        QString stopColor = getColor(color_space, &temp, &shade);
22978 jghali 1752
                        double stopPoint = (bounds[i] - domain_min) / (domain_max - domain_min);
1753
                        FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor], m_doc, shade), stopPoint, 0.5, 1.0, stopColor, shade );
19590 jghali 1754
                }
1755
        }
1756
        else if ((func->getType() == 2) || (func->getType() == 0))
1757
        {
1758
                GfxColor stop1;
22978 jghali 1759
                shading->getColor(0.0, &stop1);
19590 jghali 1760
                QString stopColor1 = getColor(color_space, &stop1, &shade);
1761
                FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor1], m_doc, shade), 0.0, 0.5, 1.0, stopColor1, shade );
1762
                GfxColor stop2;
22978 jghali 1763
                shading->getColor(1.0, &stop2);
19590 jghali 1764
                QString stopColor2 = getColor(color_space, &stop2, &shade);
1765
                FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor2], m_doc, shade), 1.0, 0.5, 1.0, stopColor2, shade );
1766
        }
22978 jghali 1767
        shading->getCoords(&GrStartX, &GrStartY, &GrEndX, &GrEndY);
19590 jghali 1768
        double xmin, ymin, xmax, ymax;
1769
        // get the clip region bbox
1770
        state->getClipBBox(&xmin, &ymin, &xmax, &ymax);
1771
        QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
1772
        crect = crect.normalized();
23588 jghali 1773
        QPainterPath out;
1774
        out.addRect(crect);
1775
        if (checkClip())
1776
        {
1777
                // Apply the clip path early to adjust the gradient vector to the
1778
                // smaller boundign box.
25120 jghali 1779
                out = intersection(m_graphicStack.top().clipPath, out);
23588 jghali 1780
                crect = out.boundingRect();
1781
        }
22741 jghali 1782
        const double *ctm = state->getCTM();
19590 jghali 1783
        m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
1784
        FPointArray gr;
1785
        gr.addPoint(GrStartX, GrStartY);
1786
        gr.addPoint(GrEndX, GrEndY);
1787
        gr.map(m_ctm);
23588 jghali 1788
        gr.translate(-crect.x(), -crect.y());
1789
 
1790
        // Undo the rotation and translation of the gradient vector.
1791
        double angle = m_ctm.map(QLineF(0, 0, 1, 0)).angle();
1792
        QTransform mm;
1793
        mm.rotate(angle);
1794
        out.translate(-crect.x(), -crect.y());
1795
        out = mm.map(out);
1796
        QRectF bb = out.boundingRect();
1797
        gr.map(mm);
1798
        gr.translate(-bb.left(), -bb.top());
1799
        GrStartX = gr.point(0).x();
1800
        GrStartY = gr.point(0).y();
1801
        GrEndX = gr.point(1).x();
1802
        GrEndY = gr.point(1).y();
1803
 
19590 jghali 1804
        double xCoor = m_doc->currentPage()->xOffset();
1805
        double yCoor = m_doc->currentPage()->yOffset();
1806
        QString output = QString("M %1 %2").arg(0.0).arg(0.0);
1807
        output += QString("L %1 %2").arg(crect.width()).arg(0.0);
1808
        output += QString("L %1 %2").arg(crect.width()).arg(crect.height());
1809
        output += QString("L %1 %2").arg(0.0).arg(crect.height());
1810
        output += QString("L %1 %2").arg(0.0).arg(0.0);
1811
        output += QString("Z");
25123 jghali 1812
        m_pathIsClosed = true;
25122 jghali 1813
        m_coords = output;
25120 jghali 1814
 
1815
        const auto& graphicState = m_graphicStack.top();
1816
        int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), bb.width(), bb.height(), 0, graphicState.fillColor, CommonStrings::None);
19590 jghali 1817
        PageItem* ite = m_doc->Items->at(z);
20011 fschmid 1818
        if (checkClip())
1819
        {
23536 jghali 1820
                ite->PoLine.fromQPainterPath(out, true);
1821
                ite->setFillEvenOdd(out.fillRule() == Qt::OddEvenFill);
20011 fschmid 1822
        }
23588 jghali 1823
        ite->setRotation(-angle);
19590 jghali 1824
        ite->ClipEdited = true;
1825
        ite->FrameType = 3;
25120 jghali 1826
        ite->setFillShade(graphicState.fillShade);
19590 jghali 1827
        ite->setLineShade(100);
1828
        ite->setFillTransparency(1.0 - state->getFillOpacity());
1829
        ite->setFillBlendmode(getBlendMode(state));
24374 jghali 1830
        ite->setLineEnd(m_lineEnd);
1831
        ite->setLineJoin(m_lineJoin);
19590 jghali 1832
        ite->setTextFlowMode(PageItem::TextFlowDisabled);
1833
        ite->GrType = 6;
1834
        if (!shading->getExtend0() || !shading->getExtend1())
1835
        {
1836
                FillGradient.setRepeatMethod(VGradient::none);
1837
                ite->setGradientExtend(VGradient::none);
1838
        }
1839
        else
1840
        {
1841
                FillGradient.setRepeatMethod(VGradient::pad);
1842
                ite->setGradientExtend(VGradient::pad);
1843
        }
1844
        ite->fill_gradient = FillGradient;
1845
        ite->setGradientVector(GrStartX, GrStartY, GrEndX, GrEndY, 0, 0, 1, 0);
20694 craig 1846
        m_doc->adjustItemSize(ite);
19590 jghali 1847
        m_Elements->append(ite);
1848
        if (m_groupStack.count() != 0)
1849
        {
1850
                m_groupStack.top().Items.append(ite);
1851
                applyMask(ite);
1852
        }
25123 jghali 1853
        return true;
19590 jghali 1854
}
1855
 
25123 jghali 1856
bool SlaOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax)
19590 jghali 1857
{
23536 jghali 1858
//      qDebug() << "SlaOutputDev::radialShadedFill";
19590 jghali 1859
        double GrStartX;
1860
        double GrStartY;
1861
        double GrEndX;
1862
        double GrEndY;
1863
        int shade = 100;
25123 jghali 1864
        const Function *func = shading->getFunc(0);
19590 jghali 1865
        VGradient FillGradient = VGradient(VGradient::linear);
1866
        FillGradient.clearStops();
1867
        GfxColorSpace *color_space = shading->getColorSpace();
1868
        if (func->getType() == 3)
1869
        {
1870
                StitchingFunction *stitchingFunc = (StitchingFunction*)func;
22741 jghali 1871
                const double *bounds = stitchingFunc->getBounds();
19590 jghali 1872
                int num_funcs = stitchingFunc->getNumFuncs();
22978 jghali 1873
                double domain_min = stitchingFunc->getDomainMin(0);
1874
                double domain_max = stitchingFunc->getDomainMax(0);
1875
                if (fabs(domain_max - domain_min) < 1e-6)
1876
                {
1877
                        domain_min = 0.0;
1878
                        domain_max = 1.0;
1879
                }
19590 jghali 1880
                // Add stops from all the stitched functions
22978 jghali 1881
                for (int i = 0 ; i <= num_funcs ; i++)
19590 jghali 1882
                {
1883
                        GfxColor temp;
22978 jghali 1884
                        shading->getColor(bounds[i], &temp);
19590 jghali 1885
                        QString stopColor = getColor(color_space, &temp, &shade);
22978 jghali 1886
                        double stopPoint = (bounds[i] - domain_min) / (domain_max - domain_min);
1887
                        FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor], m_doc, shade), stopPoint, 0.5, 1.0, stopColor, shade );
19590 jghali 1888
                }
1889
        }
1890
        else if ((func->getType() == 2) || (func->getType() == 0))
1891
        {
1892
                GfxColor stop1;
22978 jghali 1893
                shading->getColor(0.0, &stop1);
19590 jghali 1894
                QString stopColor1 = getColor(color_space, &stop1, &shade);
1895
                FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor1], m_doc, shade), 0.0, 0.5, 1.0, stopColor1, shade );
1896
                GfxColor stop2;
22978 jghali 1897
                shading->getColor(1.0, &stop2);
19590 jghali 1898
                QString stopColor2 = getColor(color_space, &stop2, &shade);
1899
                FillGradient.addStop( ScColorEngine::getShadeColor(m_doc->PageColors[stopColor2], m_doc, shade), 1.0, 0.5, 1.0, stopColor2, shade );
1900
        }
25120 jghali 1901
 
19590 jghali 1902
        double r0, x1, y1, r1;
22978 jghali 1903
        shading->getCoords(&GrStartX, &GrStartY, &r0, &x1, &y1, &r1);
19590 jghali 1904
        double xmin, ymin, xmax, ymax;
1905
        // get the clip region bbox
1906
        state->getClipBBox(&xmin, &ymin, &xmax, &ymax);
1907
        QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
1908
        crect = crect.normalized();
1909
        double GrFocalX = x1;
1910
        double GrFocalY = y1;
1911
        GrEndX = GrFocalX + r1;
1912
        GrEndY = GrFocalY;
22741 jghali 1913
        const double *ctm = state->getCTM();
19590 jghali 1914
        m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
1915
        FPointArray gr;
1916
        gr.addPoint(GrStartX, GrStartY);
1917
        gr.addPoint(GrEndX, GrEndY);
1918
        gr.addPoint(GrFocalX, GrFocalY);
1919
        gr.map(m_ctm);
1920
        GrStartX = gr.point(0).x() - crect.x();
1921
        GrStartY = gr.point(0).y() - crect.y();
1922
        GrEndX = gr.point(1).x() - crect.x();
1923
        GrEndY = gr.point(1).y() - crect.y();
1924
        GrFocalX = gr.point(2).x() - crect.x();
1925
        GrFocalY = gr.point(2).y() - crect.y();
1926
        double xCoor = m_doc->currentPage()->xOffset();
1927
        double yCoor = m_doc->currentPage()->yOffset();
1928
        QString output = QString("M %1 %2").arg(0.0).arg(0.0);
1929
        output += QString("L %1 %2").arg(crect.width()).arg(0.0);
1930
        output += QString("L %1 %2").arg(crect.width()).arg(crect.height());
1931
        output += QString("L %1 %2").arg(0.0).arg(crect.height());
1932
        output += QString("L %1 %2").arg(0.0).arg(0.0);
1933
        output += QString("Z");
25123 jghali 1934
        m_pathIsClosed = true;
25122 jghali 1935
        m_coords = output;
25120 jghali 1936
 
1937
        const auto& graphicState = m_graphicStack.top();
1938
        int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
19590 jghali 1939
        PageItem* ite = m_doc->Items->at(z);
20011 fschmid 1940
        if (checkClip())
1941
        {
25120 jghali 1942
                QPainterPath out = graphicState.clipPath;
23319 jghali 1943
                out.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset());
1944
                out.translate(-ite->xPos(), -ite->yPos());
23536 jghali 1945
                ite->PoLine.fromQPainterPath(out, true);
1946
                ite->setFillEvenOdd(out.fillRule() == Qt::OddEvenFill);
20011 fschmid 1947
        }
19590 jghali 1948
        ite->ClipEdited = true;
1949
        ite->FrameType = 3;
25120 jghali 1950
        ite->setFillShade(graphicState.fillShade);
19590 jghali 1951
        ite->setLineShade(100);
1952
        ite->setFillTransparency(1.0 - state->getFillOpacity());
1953
        ite->setFillBlendmode(getBlendMode(state));
24374 jghali 1954
        ite->setLineEnd(m_lineEnd);
1955
        ite->setLineJoin(m_lineJoin);
19590 jghali 1956
        ite->setTextFlowMode(PageItem::TextFlowDisabled);
1957
        ite->GrType = 7;
1958
        if (!shading->getExtend0() || !shading->getExtend1())
1959
        {
1960
                FillGradient.setRepeatMethod(VGradient::none);
1961
                ite->setGradientExtend(VGradient::none);
1962
        }
1963
        else
1964
        {
1965
                FillGradient.setRepeatMethod(VGradient::pad);
1966
                ite->setGradientExtend(VGradient::pad);
1967
        }
1968
        ite->fill_gradient = FillGradient;
1969
        ite->setGradientVector(GrStartX, GrStartY, GrEndX, GrEndY, GrFocalX, GrFocalY, 1, 0);
20694 craig 1970
        m_doc->adjustItemSize(ite);
19590 jghali 1971
        m_Elements->append(ite);
1972
        if (m_groupStack.count() != 0)
1973
        {
1974
                m_groupStack.top().Items.append(ite);
1975
                applyMask(ite);
1976
        }
25123 jghali 1977
        return true;
19590 jghali 1978
}
1979
 
25123 jghali 1980
bool SlaOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading)
19590 jghali 1981
{
23536 jghali 1982
//      qDebug() << "SlaOutputDev::gouraudTriangleShadedFill";
19590 jghali 1983
        double xCoor = m_doc->currentPage()->xOffset();
1984
        double yCoor = m_doc->currentPage()->yOffset();
1985
        double xmin, ymin, xmax, ymax;
1986
        // get the clip region bbox
1987
        state->getClipBBox(&xmin, &ymin, &xmax, &ymax);
1988
        QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
1989
        crect = crect.normalized();
1990
        QString output = QString("M %1 %2").arg(0.0).arg(0.0);
1991
        output += QString("L %1 %2").arg(crect.width()).arg(0.0);
1992
        output += QString("L %1 %2").arg(crect.width()).arg(crect.height());
1993
        output += QString("L %1 %2").arg(0.0).arg(crect.height());
1994
        output += QString("L %1 %2").arg(0.0).arg(0.0);
1995
        output += QString("Z");
25123 jghali 1996
        m_pathIsClosed = true;
25122 jghali 1997
        m_coords = output;
22741 jghali 1998
        const double *ctm = state->getCTM();
19590 jghali 1999
        m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
25120 jghali 2000
        const auto& graphicState = m_graphicStack.top();
2001
        int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
19590 jghali 2002
        PageItem* ite = m_doc->Items->at(z);
2003
        ite->ClipEdited = true;
2004
        ite->FrameType = 3;
25120 jghali 2005
        ite->setFillShade(graphicState.fillShade);
19590 jghali 2006
        ite->setLineShade(100);
2007
        ite->setFillEvenOdd(false);
2008
        ite-