Subversion Repositories Scribus

Rev

Rev 6407 | Rev 6417 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 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
*/
3133 fschmid 7
/***************************************************************************
8
                          pdflib.cpp  -  description
9
                             -------------------
10
    begin                : Sat Jan 19 2002
11
    copyright            : (C) 2002 by Franz Schmid
12
    email                : Franz.Schmid@altmuehlnet.de
13
 ***************************************************************************/
14
 
15
/***************************************************************************
16
 *                                                                         *
17
 *   This program is free software; you can redistribute it and/or modify  *
18
 *   it under the terms of the GNU General Public License as published by  *
19
 *   the Free Software Foundation; either version 2 of the License, or     *
20
 *   (at your option) any later version.                                   *
21
 *                                                                         *
22
 ***************************************************************************/
23
 
24
#include "pdflib.h"
25
#include "pdflib.moc"
26
 
27
#include "scconfig.h"
28
 
4229 craig 29
#include <string>
3133 fschmid 30
#include <qstring.h>
31
#include <qrect.h>
32
#include <qimage.h>
33
#include <qregexp.h>
34
#include <qdatetime.h>
35
#include <qfileinfo.h>
36
#include <qtextstream.h>
37
#include <qdir.h>
38
#include <cstdlib>
39
#include <cmath>
40
#ifdef HAVE_UNISTD_H
41
#include <unistd.h>
42
#endif
43
#include "rc4.h"
44
 
4028 cbradney 45
#include "commonstrings.h"
3670 cbradney 46
#include "page.h"
3133 fschmid 47
#include "pageitem.h"
48
#include "bookmwin.h"
5917 jghali 49
#include "scpaths.h"
3133 fschmid 50
#include "scribus.h"
5243 cbradney 51
#include "scribuscore.h"
3699 cbradney 52
#include "scribusdoc.h"
4028 cbradney 53
#include "multiprogressdialog.h"
3133 fschmid 54
#include "bookpalette.h"
5993 avox 55
#include "scfonts.h"
3133 fschmid 56
#include "util.h"
57
#include "prefsmanager.h"
3252 craig 58
#include "prefscontext.h"
3133 fschmid 59
#include "pdfoptions.h"
4007 fschmid 60
#include "sccolor.h"
6378 fschmid 61
#include "scpattern.h"
3133 fschmid 62
 
5184 avox 63
#include "text/nlsconfig.h"
64
 
3133 fschmid 65
using namespace std;
66
 
67
#ifdef HAVE_TIFF
68
        #include <tiffio.h>
69
#endif
70
 
4264 craig 71
PDFlib::PDFlib(ScribusDoc & docu)
72
        : QObject(&docu),
4223 craig 73
        doc(docu),
74
        ActPageP(0),
4264 craig 75
        Options(doc.PDF_Options),
4223 craig 76
        Bvie(0),
77
        ObjCounter(7),
78
        ResNam("RE"),
79
        ResCount(0),
80
        NDnam("LI"),
81
        NDnum(0),
82
        KeyGen(32),
83
        OwnerKey(32),
84
        UserKey(32),
85
        FileID(16),
86
        EncryKey(5),
87
        Encrypt(0),
88
        KeyLen(5),
89
        colorsToUse(),
90
        spotNam("Spot"),
91
        spotCount(0),
4225 craig 92
        progressDialog(0),
4223 craig 93
        abortExport(false),
5243 cbradney 94
        usingGUI(ScCore->usingGUI())
3133 fschmid 95
{
96
        Catalog.Outlines = 2;
97
        Catalog.PageTree = 3;
98
        Catalog.Dest = 4;
99
        PageTree.Count = 0;
100
        Outlines.First = 0;
101
        Outlines.Last = 0;
102
        Outlines.Count = 0;
103
        Seite.ObjNum = 0;
104
        Seite.Thumb = 0;
105
#ifdef HAVE_LIBZ
106
        CompAvail = true;
107
#else
108
        CompAvail = false;
109
#endif
110
        int kg_array[] = {0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa,
111
                          0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe,
112
                          0x64, 0x53, 0x69, 0x7a};
113
        for (int a = 0; a < 32; ++a)
114
                KeyGen[a] = kg_array[a];
4028 cbradney 115
        if (usingGUI)
116
        {
6260 fschmid 117
                progressDialog = new MultiProgressDialog( tr("Saving PDF"), CommonStrings::tr_Cancel, doc.scMW(), "pdfexportprogress");
4224 craig 118
                Q_CHECK_PTR(progressDialog);
119
                QStringList barNames, barTexts;
120
                barNames << "EMP" << "EP" << "ECPI";
5370 cbradney 121
                barTexts << tr("Exporting Master Page:") << tr("Exporting Page:") << tr("Exporting Items on Current Page:");
122
                QValueList<bool> barsNumeric;
123
                barsNumeric << true << true << false;
124
                progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
4224 craig 125
                connect(progressDialog->buttonCancel, SIGNAL(clicked()), this, SLOT(cancelRequested()));
4028 cbradney 126
        }
3133 fschmid 127
}
128
 
4224 craig 129
PDFlib::~PDFlib()
130
{
131
        delete progressDialog;
132
}
133
 
4229 craig 134
static inline QString FToStr(double c)
135
{
136
        return QString::number(c, 'f', 5);
137
};
138
 
4264 craig 139
bool PDFlib::doExport(const QString& fn, const QString& nam, int Components,
140
                                          const std::vector<int> & pageNs, const QMap<int,QPixmap> & thumbs)
3133 fschmid 141
{
142
        QPixmap pm;
143
        bool ret = false;
4028 cbradney 144
        int pc_exportpages=0;
145
        int pc_exportmasterpages=0;
4224 craig 146
        if (usingGUI)
147
                progressDialog->show();
5387 avox 148
        QMap<QString, QMap<uint, FPointArray> > usedFonts;
149
        usedFonts.clear();
150
        doc.getUsedFonts(usedFonts);
5781 cbradney 151
        if (PDF_Begin_Doc(fn, PrefsManager::instance()->appPrefs.AvailFonts, usedFonts, doc.scMW()->bookmarkPalette->BView))
3133 fschmid 152
        {
153
                QMap<int, int> pageNsMpa;
154
                for (uint a = 0; a < pageNs.size(); ++a)
155
                {
4264 craig 156
                        pageNsMpa.insert(doc.MasterNames[doc.Pages->at(pageNs[a]-1)->MPageNam], 0);
3133 fschmid 157
                }
4028 cbradney 158
                if (usingGUI)
3133 fschmid 159
                {
4028 cbradney 160
                        progressDialog->setOverallTotalSteps(pageNsMpa.count()+pageNs.size());
161
                        progressDialog->setTotalSteps("EMP", pageNsMpa.count());
162
                        progressDialog->setTotalSteps("EP", pageNs.size());
163
                        progressDialog->setOverallProgress(0);
164
                        progressDialog->setProgress("EMP", 0);
165
                        progressDialog->setProgress("EP", 0);
166
                }
4264 craig 167
                for (uint ap = 0; ap < doc.MasterPages.count() && !abortExport; ++ap)
4028 cbradney 168
                {
4264 craig 169
                        if (doc.MasterItems.count() != 0)
3133 fschmid 170
                        {
171
                                if (pageNsMpa.contains(ap))
172
                                {
5243 cbradney 173
                                        qApp->processEvents();
4264 craig 174
                                        PDF_TemplatePage(doc.MasterPages.at(ap));
4028 cbradney 175
                                        ++pc_exportmasterpages;
3133 fschmid 176
                                }
177
                        }
4546 subik 178
 
179
                        if (usingGUI)
180
                        {
4028 cbradney 181
                                progressDialog->setProgress("EMP", pc_exportmasterpages);
182
                                progressDialog->setOverallProgress(pc_exportmasterpages+pc_exportpages);
183
                        }
3133 fschmid 184
                }
4028 cbradney 185
                for (uint a = 0; a < pageNs.size() && !abortExport; ++a)
3133 fschmid 186
                {
4264 craig 187
                        if (doc.PDF_Options.Thumbnails)
3133 fschmid 188
                                pm = thumbs[pageNs[a]];
5243 cbradney 189
                        qApp->processEvents();
4028 cbradney 190
                        if (abortExport) break;
4264 craig 191
                        PDF_Begin_Page(doc.Pages->at(pageNs[a]-1), pm);
5243 cbradney 192
                        qApp->processEvents();
4028 cbradney 193
                        if (abortExport) break;
4649 fschmid 194
                        PDF_ProcessPage(doc.Pages->at(pageNs[a]-1), pageNs[a]-1, doc.PDF_Options.doClip);
5243 cbradney 195
                        qApp->processEvents();
4028 cbradney 196
                        if (abortExport) break;
3133 fschmid 197
                        PDF_End_Page();
4028 cbradney 198
                        pc_exportpages++;
199
                        if (usingGUI)
200
                        {
201
                                progressDialog->setProgress("EP", pc_exportpages);
202
                                progressDialog->setOverallProgress(pc_exportmasterpages+pc_exportpages);
203
                        }
3133 fschmid 204
                }
4028 cbradney 205
                ret = true;//Even when aborting we return true. Dont want that "couldnt write msg"
206
                if (!abortExport)
207
                {
4264 craig 208
                        if (doc.PDF_Options.Version == PDFOptions::PDFVersion_X3)
5243 cbradney 209
                                PDF_End_Doc(ScCore->PrinterProfiles[doc.PDF_Options.PrintProf], nam, Components);
4028 cbradney 210
                        else
211
                                PDF_End_Doc();
212
                }
3133 fschmid 213
                else
4028 cbradney 214
                        closeAndCleanup();
3133 fschmid 215
        }
4029 cbradney 216
        if (usingGUI)
217
                progressDialog->close();
3133 fschmid 218
        return ret;
219
}
220
 
221
void PDFlib::StartObj(int nr)
222
{
4229 craig 223
        XRef.append(bytesWritten());
224
        PutDoc(QString::number(nr)+ " 0 obj\n");
3133 fschmid 225
}
226
 
4229 craig 227
// Encode a string for inclusion in a
228
// PDF (literal) .
229
QString PDFlib::PDFEncode(const QString & in)
3133 fschmid 230
{
4229 craig 231
        QString tmp("");
3133 fschmid 232
        for (uint d = 0; d < in.length(); ++d)
233
        {
4229 craig 234
                QChar cc(in.at(d));
4230 craig 235
                if ((cc == '(') || (cc == ')') || (cc == '\\'))
236
                        tmp += '\\';
3133 fschmid 237
                tmp += cc;
238
        }
239
        return tmp;
240
}
241
 
4229 craig 242
QString PDFlib::EncStream(const QString & in, int ObjNum)
3133 fschmid 243
{
4229 craig 244
        if (in.length() < 1)
245
                return QString("");
4264 craig 246
        else if (!Options.Encrypt)
4229 craig 247
                return in;
248
        rc4_context_t rc4;
3133 fschmid 249
        int dlen = 0;
4229 craig 250
        QString tmp(in);
251
        QByteArray us(tmp.length());
252
        QByteArray ou(tmp.length());
253
        for (uint a = 0; a < tmp.length(); ++a)
254
                us[a] = uchar(QChar(tmp.at(a)));
255
        QByteArray data(10);
256
        if (KeyLen > 5)
257
                data.resize(21);
258
        for (int cd = 0; cd < KeyLen; ++cd)
3133 fschmid 259
        {
4229 craig 260
                data[cd] = EncryKey[cd];
261
                dlen++;
3133 fschmid 262
        }
4229 craig 263
        data[dlen++] = ObjNum;
264
        data[dlen++] = ObjNum >> 8;
265
        data[dlen++] = ObjNum >> 16;
266
        data[dlen++] = 0;
267
        data[dlen++] = 0;
268
        QByteArray step1(16);
269
        step1 = ComputeMD5Sum(&data);
270
        rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), QMIN(KeyLen+5, 16));
271
        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(us.data()), reinterpret_cast<uchar*>(ou.data()), tmp.length());
272
        QString uk = "";
273
        for (uint cl = 0; cl < tmp.length(); ++cl)
274
                uk += QChar(ou[cl]);
275
        return uk;
3133 fschmid 276
}
277
 
5234 fschmid 278
QByteArray PDFlib::EncStreamArray(const QByteArray & in, int ObjNum)
279
{
280
        if (in.size() < 1)
281
                return QByteArray();
282
        else if (!Options.Encrypt)
283
                return in;
284
        rc4_context_t rc4;
285
        int dlen = 0;
286
        QByteArray out(in.size());
287
        QByteArray data(10);
288
        if (KeyLen > 5)
289
                data.resize(21);
290
        for (int cd = 0; cd < KeyLen; ++cd)
291
        {
292
                data[cd] = EncryKey[cd];
293
                dlen++;
294
        }
295
        data[dlen++] = ObjNum;
296
        data[dlen++] = ObjNum >> 8;
297
        data[dlen++] = ObjNum >> 16;
298
        data[dlen++] = 0;
299
        data[dlen++] = 0;
300
        QByteArray step1(16);
301
        step1 = ComputeMD5Sum(&data);
302
        rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), QMIN(KeyLen+5, 16));
303
        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(in.data()), reinterpret_cast<uchar*>(out.data()), in.size());
304
        return out;
305
}
306
 
4229 craig 307
QString PDFlib::EncString(const QString & in, int ObjNum)
3133 fschmid 308
{
4264 craig 309
        if (!Options.Encrypt)
4229 craig 310
                return in;
311
        rc4_context_t rc4;
3133 fschmid 312
        QString tmp;
313
        int dlen = 0;
4229 craig 314
        if (in.length() < 3)
315
                return "<>";
316
        tmp = in.mid(1, in.length()-2);
317
        QByteArray us(tmp.length());
318
        QByteArray ou(tmp.length());
319
        for (uint a = 0; a < tmp.length(); ++a)
320
                us[a] = static_cast<uchar>(QChar(tmp.at(a)));
321
        QByteArray data(10);
322
        if (KeyLen > 5)
323
                data.resize(21);
324
        for (int cd = 0; cd < KeyLen; ++cd)
3133 fschmid 325
        {
4229 craig 326
                data[cd] = EncryKey[cd];
327
                dlen++;
3133 fschmid 328
        }
4229 craig 329
        data[dlen++] = ObjNum;
330
        data[dlen++] = ObjNum >> 8;
331
        data[dlen++] = ObjNum >> 16;
332
        data[dlen++] = 0;
333
        data[dlen++] = 0;
334
        QByteArray step1(16);
335
        step1 = ComputeMD5Sum(&data);
336
        rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), QMIN(KeyLen+5, 16));
337
        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(us.data()), reinterpret_cast<uchar*>(ou.data()), tmp.length());
338
        QString uk = "";
339
        for (uint cl = 0; cl < tmp.length(); ++cl)
340
                uk += QChar(ou[cl]);
341
        tmp = "<"+String2Hex(&uk, false)+">";
3133 fschmid 342
        return tmp;
343
}
344
 
4229 craig 345
QString PDFlib::FitKey(const QString & pass)
3133 fschmid 346
{
4229 craig 347
        QString pw(pass);
3133 fschmid 348
        if (pw.length() < 32)
349
        {
350
                uint l = pw.length();
351
                for (uint a = 0; a < 32 - l; ++a)
352
                        pw += QChar(KeyGen[a]);
353
        }
354
        else
355
                pw = pw.left(32);
356
        return pw;
357
}
358
 
4229 craig 359
void PDFlib::CalcOwnerKey(const QString & Owner, const QString & User)
3133 fschmid 360
{
4229 craig 361
        rc4_context_t rc4;
362
        QString pw(FitKey(User));
363
        QString pw2(FitKey(Owner.isEmpty() ? User : Owner));
3133 fschmid 364
        QByteArray step1(16);
365
        step1 = ComputeMD5(pw2);
366
        if (KeyLen > 5)
367
        {
368
                for (int kl = 0; kl < 50; ++kl)
369
                        step1 = ComputeMD5Sum(&step1);
370
        }
371
        QByteArray us(32);
372
        QByteArray enk(16);
373
        if (KeyLen > 5)
374
        {
375
                for (uint a2 = 0; a2 < 32; ++a2)
376
                        OwnerKey[a2] = static_cast<uchar>(QChar(pw.at(a2)));
377
                for (int rl = 0; rl < 20; rl++)
378
                {
4229 craig 379
                        for (int j = 0; j < 16; j ++)
380
                                enk[j] = step1[j] ^ rl;
3133 fschmid 381
                        rc4_init(&rc4, reinterpret_cast<uchar*>(enk.data()), 16);
4229 craig 382
                        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(OwnerKey.data()),
3133 fschmid 383
                                         reinterpret_cast<uchar*>(OwnerKey.data()), 32);
384
                }
385
        }
386
        else
387
        {
388
                for (uint a = 0; a < 32; ++a)
389
                        us[a] = static_cast<uchar>(QChar(pw.at(a)));
390
                rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), 5);
4546 subik 391
                rc4_encrypt(&rc4, reinterpret_cast<uchar*>(us.data()),
3133 fschmid 392
                                        reinterpret_cast<uchar*>(OwnerKey.data()), 32);
393
        }
394
}
395
 
4229 craig 396
void PDFlib::CalcUserKey(const QString & User, int Permission)
3133 fschmid 397
{
398
        rc4_context_t   rc4;
4229 craig 399
        QString pw(FitKey(User));
3133 fschmid 400
        QByteArray step1(16);
401
        QByteArray perm(4);
402
        uint perm_value = static_cast<uint>(Permission);
403
        perm[0] = perm_value;
404
        perm[1] = perm_value >> 8;
405
        perm[2] = perm_value >> 16;
406
        perm[3] = perm_value >> 24;
407
        for (uint a = 0; a < 32; ++a)
408
                pw += QChar(OwnerKey[a]);
409
        for (uint a1 = 0; a1 < 4; ++a1)
410
                pw += QChar(perm[a1]);
411
        for (uint a3 = 0; a3 < 16; ++a3)
412
                pw += QChar(FileID[a3]);
413
        step1 = ComputeMD5(pw);
414
        if (KeyLen > 5)
415
        {
416
                for (int kl = 0; kl < 50; ++kl)
417
                        step1 = ComputeMD5Sum(&step1);
418
                EncryKey.resize(16);
419
        }
420
        for (int a2 = 0; a2 < KeyLen; ++a2)
421
                EncryKey[a2] = step1[a2];
422
        if (KeyLen > 5)
423
        {
4229 craig 424
                QString pr2("");
3133 fschmid 425
                for (int kl3 = 0; kl3 < 32; ++kl3)
426
                        pr2 += QChar(KeyGen[kl3]);
427
                for (uint a4 = 0; a4 < 16; ++a4)
428
                        pr2 += QChar(FileID[a4]);
429
                step1 = ComputeMD5(pr2);
430
                QByteArray enk(16);
431
                for (uint a3 = 0; a3 < 16; ++a3)
432
                        UserKey[a3] = step1[a3];
433
                for (int rl = 0; rl < 20; rl++)
434
                {
4229 craig 435
                        for (int j = 0; j < 16; j ++)
436
                                enk[j] = EncryKey[j] ^ rl;
3133 fschmid 437
                        rc4_init(&rc4, reinterpret_cast<uchar*>(enk.data()), 16);
4229 craig 438
                        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(UserKey.data()), reinterpret_cast<uchar*>(UserKey.data()), 16);
3133 fschmid 439
                }
440
        }
441
        else
442
        {
443
                rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), 5);
4229 craig 444
                rc4_encrypt(&rc4, reinterpret_cast<uchar*>(KeyGen.data()), reinterpret_cast<uchar*>(UserKey.data()), 32);
3133 fschmid 445
        }
446
}
447
 
3829 cbradney 448
QByteArray PDFlib::ComputeMD5(const QString& in)
3133 fschmid 449
{
3829 cbradney 450
        uint inlen=in.length();
451
        QByteArray TBytes(inlen);
452
        for (uint a = 0; a < inlen; ++a)
3133 fschmid 453
                TBytes[a] = static_cast<uchar>(QChar(in.at(a)));
454
        return ComputeMD5Sum(&TBytes);
455
}
456
 
5387 avox 457
bool PDFlib::PDF_Begin_Doc(const QString& fn, SCFonts &AllFonts, QMap<QString, QMap<uint, FPointArray> > DocFonts, BookMView* vi)
3133 fschmid 458
{
4229 craig 459
        Spool.setName(fn);
3133 fschmid 460
        if (!Spool.open(IO_WriteOnly))
461
                return false;
4229 craig 462
        outStream.setDevice(&Spool);
3133 fschmid 463
        QString tmp;
464
        QString ok = "";
465
        QString uk = "";
466
        QFileInfo fd;
467
        QString fext;
468
        int a;
6407 fschmid 469
        inPattern = 0;
3133 fschmid 470
        Bvie = vi;
471
        BookMinUse = false;
472
        UsedFontsP.clear();
4264 craig 473
        if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 474
                ObjCounter = 10;
475
        else
476
                ObjCounter = 9;
4264 craig 477
        switch (Options.Version)
3133 fschmid 478
        {
479
                case 12:
480
                case 13:
4229 craig 481
                        PutDoc("%PDF-1.3\n");
3133 fschmid 482
                        break;
483
                case 14:
484
                        PutDoc("%PDF-1.4\n");
485
                        break;
486
                case 15:
487
                        PutDoc("%PDF-1.5\n");
488
                        break;
489
        }
4264 craig 490
        if (Options.Version == 12)
3133 fschmid 491
                ObjCounter++;
4229 craig 492
        PutDoc("%\xc7\xec\x8f\xa2\n");
3133 fschmid 493
        StartObj(1);
494
        PutDoc("<<\n/Type /Catalog\n/Outlines 3 0 R\n/Pages 4 0 R\n/Dests 5 0 R\n/AcroForm 6 0 R\n/Names 7 0 R\n/Threads 8 0 R\n");
4264 craig 495
        if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 496
                PutDoc("/OCProperties 9 0 R\n");
4264 craig 497
        if (Options.Version == 12)
4229 craig 498
                PutDoc("/OutputIntents [ "+QString::number(ObjCounter-1)+" 0 R ]\n");
4197 fschmid 499
        PutDoc("/PageLayout ");
4264 craig 500
        switch (Options.PageLayout)
3133 fschmid 501
        {
4197 fschmid 502
                case PDFOptions::SinglePage:
503
                        PutDoc("/SinglePage\n");
504
                        break;
505
                case PDFOptions::OneColumn:
506
                        PutDoc("/OneColumn\n");
507
                        break;
508
                case PDFOptions::TwoColumnLeft:
509
                        PutDoc("/TwoColumnLeft\n");
510
                        break;
511
                case PDFOptions::TwoColumnRight:
512
                        PutDoc("/TwoColumnRight\n");
513
                        break;
514
        }
4264 craig 515
        if (Options.displayBookmarks)
4197 fschmid 516
                PutDoc("/PageMode /UseOutlines\n");
4264 craig 517
        else if (Options.displayFullscreen)
4197 fschmid 518
                PutDoc("/PageMode /FullScreen\n");
4264 craig 519
        else if (Options.displayThumbs)
4197 fschmid 520
                PutDoc("/PageMode /UseThumbs\n");
4264 craig 521
        else if ((Options.Version == 15) && (Options.displayLayers))
4197 fschmid 522
                        PutDoc("/PageMode /UseOC\n");
4264 craig 523
        if (!Options.openAction.isEmpty())
4197 fschmid 524
        {
4264 craig 525
                PutDoc("/OpenAction << /S /JavaScript /JS (this."+Options.openAction+"\\(\\)) >>\n");
3133 fschmid 526
        }
527
        PutDoc("/ViewerPreferences\n<<\n/PageDirection ");
4264 craig 528
        PutDoc( Options.Binding == 0 ? "/L2R\n" : "/R2L\n");
529
        if (Options.hideToolBar)
4201 fschmid 530
                PutDoc("/HideToolbar true\n");
4264 craig 531
        if (Options.hideMenuBar)
4201 fschmid 532
                PutDoc("/HideMenubar true\n");
4264 craig 533
        if (Options.fitWindow)
4201 fschmid 534
                PutDoc("/FitWindow true\n");
3133 fschmid 535
        PutDoc(" >>\n>>\nendobj\n");
3829 cbradney 536
        QString IDg(Datum);
4264 craig 537
        IDg += Options.Datei;
3133 fschmid 538
        IDg += "Scribus "+QString(VERSION);
539
        IDg += "Libpdf for Scribus "+QString(VERSION);
4264 craig 540
        IDg += doc.documentInfo.getTitle();
541
        IDg += doc.documentInfo.getAuthor();
3133 fschmid 542
        IDg += "/False";
543
        FileID = ComputeMD5(IDg);
4264 craig 544
        if (Options.Encrypt)
3133 fschmid 545
        {
6166 fschmid 546
                if ((Options.Version == 14) || (Options.Version == 15))
547
                        KeyLen = 16;
548
                else
549
                        KeyLen = 5;
4264 craig 550
                CalcOwnerKey(Options.PassOwner, Options.PassUser);
551
                CalcUserKey(Options.PassUser, Options.Permissions);
3133 fschmid 552
                for (uint cl2 = 0; cl2 < 32; ++cl2)
553
                        ok += QChar(OwnerKey[cl2]);
554
                if (KeyLen > 5)
555
                {
556
                        for (uint cl3 = 0; cl3 < 16; ++cl3)
557
                                uk += QChar(UserKey[cl3]);
558
                        for (uint cl3r = 0; cl3r < 16; ++cl3r)
559
                                uk += QChar(KeyGen[cl3r]);
560
                }
561
                else
562
                {
563
                        for (uint cl = 0; cl < 32; ++cl)
564
                                uk += QChar(UserKey[cl]);
565
                }
566
        }
567
        QDate d = QDate::currentDate();
568
        Datum = "D:";
569
        tmp.sprintf("%4d", d.year());
570
        tmp.replace(QRegExp(" "), "0");
571
        Datum += tmp;
572
        tmp.sprintf("%2d", d.month());
573
        tmp.replace(QRegExp(" "), "0");
574
        Datum += tmp;
575
        tmp.sprintf("%2d", d.day());
576
        tmp.replace(QRegExp(" "), "0");
577
        Datum += tmp;
4229 craig 578
        tmp = QTime::currentTime().toString();
3133 fschmid 579
        tmp.replace(QRegExp(":"), "");
580
        Datum += tmp;
581
        StartObj(2);
582
        PutDoc("<<\n/Creator "+EncString("(Scribus "+QString(VERSION)+")",2)+"\n");
583
        PutDoc("/Producer "+EncString("(Libpdf for Scribus "+QString(VERSION)+")",2)+"\n");
4718 fschmid 584
        QString docTitle = doc.documentInfo.getTitle();
585
        if ((Options.Version == 12) && (docTitle.isEmpty()))
586
                PutDoc("/Title "+EncString("("+doc.DocName+")",2)+"\n");
587
        else
588
                PutDoc("/Title "+EncString("("+doc.documentInfo.getTitle()+")",2)+"\n");
4264 craig 589
        PutDoc("/Author "+EncString("("+doc.documentInfo.getAuthor()+")",2)+"\n");
590
        PutDoc("/Keywords "+EncString("("+doc.documentInfo.getKeywords()+")",2)+"\n");
3133 fschmid 591
        PutDoc("/CreationDate "+EncString("("+Datum+")",2)+"\n");
592
        PutDoc("/ModDate "+EncString("("+Datum+")",2)+"\n");
4264 craig 593
        if (Options.Version == 12)
3133 fschmid 594
                PutDoc("/GTS_PDFXVersion (PDF/X-3:2002)\n");
595
        PutDoc("/Trapped /False\n>>\nendobj\n");
4229 craig 596
        for (int t = 0; t < 6; ++t)
597
                XRef.append(bytesWritten());
4264 craig 598
        if ((Options.Version == 15) && (Options.useLayers))
4229 craig 599
                XRef.append(bytesWritten());
4264 craig 600
        if (Options.Version == 12)
4229 craig 601
                XRef.append(bytesWritten());
4264 craig 602
        if (Options.Encrypt)
3133 fschmid 603
        {
604
                StartObj(ObjCounter);
605
                Encrypt = ObjCounter;
606
                ObjCounter++;
607
                PutDoc("<<\n/Filter /Standard\n");
608
                PutDoc( KeyLen > 5 ? "/R 3\n/V 2\n/Length 128\n" : "/R 2\n/V 1\n");
609
                PutDoc("/O <"+String2Hex(&ok)+">\n");
610
                PutDoc("/U <"+String2Hex(&uk)+">\n");
4264 craig 611
                PutDoc("/P "+QString::number(Options.Permissions)+"\n>>\nendobj\n");
3133 fschmid 612
        }
5387 avox 613
        QMap<QString, QMap<uint, FPointArray> > ReallyUsed;
3133 fschmid 614
        ReallyUsed.clear();
615
        PageItem* pgit;
4017 fschmid 616
        QMap<int, QString> ind2PDFabr;
4546 subik 617
        const QString tmpf[] = {"/Courier", "/Courier-Bold", "/Courier-Oblique", "/Courier-BoldOblique",
4017 fschmid 618
                                                                                                "/Helvetica", "/Helvetica-Bold", "/Helvetica-Oblique", "/Helvetica-BoldOblique",
4546 subik 619
                                                                                                "/Times-Roman", "/Times-Bold", "/Times-Italic", "/Times-BoldItalic",
4017 fschmid 620
                                                                                                "/ZapfDingbats", "/Symbol"};
621
        size_t ar = sizeof(tmpf) / sizeof(*tmpf);
622
        for (uint ax = 0; ax < ar; ++ax)
623
                ind2PDFabr[ax] = tmpf[ax];
4264 craig 624
        for (uint c = 0; c < doc.FrameItems.count(); ++c)
3133 fschmid 625
        {
4264 craig 626
                pgit = doc.FrameItems.at(c);
3133 fschmid 627
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
628
                {
4084 cbradney 629
                        if (pgit->isAnnotation())
630
                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
5292 fschmid 631
                        for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
3133 fschmid 632
                        {
5980 avox 633
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().scName(), DocFonts[pgit->itemText.charStyle(e).font().scName()]);
3133 fschmid 634
                        }
635
                }
636
        }
4264 craig 637
        for (uint c = 0; c < doc.MasterItems.count(); ++c)
3133 fschmid 638
        {
4264 craig 639
                pgit = doc.MasterItems.at(c);
3133 fschmid 640
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
641
                {
4084 cbradney 642
                        if (pgit->isAnnotation())
643
                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
5292 fschmid 644
                        for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
3133 fschmid 645
                        {
5980 avox 646
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().scName(), DocFonts[pgit->itemText.charStyle(e).font().scName()]);
3133 fschmid 647
                        }
648
                }
649
        }
4264 craig 650
        for (uint d = 0; d < doc.Items->count(); ++d)
3133 fschmid 651
        {
4264 craig 652
                pgit = doc.Items->at(d);
3133 fschmid 653
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
654
                {
4084 cbradney 655
                        if (pgit->isAnnotation())
656
                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
5292 fschmid 657
                        for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
3133 fschmid 658
                        {
5980 avox 659
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().scName(), DocFonts[pgit->itemText.charStyle(e).font().scName()]);
3133 fschmid 660
                        }
661
                }
662
        }
6407 fschmid 663
        QStringList patterns = doc.getUsedPatterns();
664
        for (uint c = 0; c < patterns.count(); ++c)
665
        {
666
                ScPattern pa = doc.docPatterns[patterns[c]];
667
                for (uint o = 0; o < pa.items.count(); o++)
668
                {
669
                        pgit = pa.items.at(o);
670
                        if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
671
                        {
672
                                if (pgit->isAnnotation())
673
                                        StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
674
                                for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
675
                                {
676
                                        ReallyUsed.insert(pgit->itemText.charStyle(e).font().scName(), DocFonts[pgit->itemText.charStyle(e).font().scName()]);
677
                                }
678
                        }
679
                }
680
        }
4017 fschmid 681
        a = 0;
682
        QMap<QString, QString>::Iterator itStd;
683
        for (itStd = StdFonts.begin(); itStd != StdFonts.end(); ++itStd)
684
        {
685
                StartObj(ObjCounter);
686
                PutDoc("<<\n/Type /Font\n/Subtype /Type1\n");
687
                PutDoc("/BaseFont "+itStd.key()+"\n");
688
                PutDoc(">>\nendobj\n");
4229 craig 689
                Seite.FObjects["FoStd"+QString::number(a)] = ObjCounter;
690
                itStd.data() = "FoStd"+QString::number(a);
4017 fschmid 691
                ObjCounter++;
692
                a++;
693
        }
5387 avox 694
        QMap<QString,QMap<uint, FPointArray> >::Iterator it;
3133 fschmid 695
        a = 0;
696
        for (it = ReallyUsed.begin(); it != ReallyUsed.end(); ++it)
697
        {
5980 avox 698
                ScFace::FontFormat fformat = AllFonts[it.key()].format();
699
                if ((AllFonts[it.key()].isOTF()) || (!AllFonts[it.key()].hasNames()) || (AllFonts[it.key()].subset()) || (Options.SubsetList.contains(it.key())))
3133 fschmid 700
                {
3829 cbradney 701
                        QString fon("");
5387 avox 702
                        QMap<uint,FPointArray>& RealGlyphs(it.data());
3133 fschmid 703
                        QMap<uint,FPointArray>::Iterator ig;
5387 avox 704
                        for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
3133 fschmid 705
                        {
706
                                FPoint np, np1, np2;
707
                                bool nPath = true;
5606 fschmid 708
                                fon = "";
3133 fschmid 709
                                if (ig.data().size() > 3)
710
                                {
5387 avox 711
                                        FPointArray gly = ig.data();
3133 fschmid 712
                                        QWMatrix mat;
713
                                        mat.scale(0.1, 0.1);
714
                                        gly.map(mat);
715
                                        for (uint poi = 0; poi < gly.size()-3; poi += 4)
716
                                        {
717
                                                if (gly.point(poi).x() > 900000)
718
                                                {
719
                                                        fon += "h\n";
720
                                                        nPath = true;
721
                                                        continue;
722
                                                }
723
                                                if (nPath)
724
                                                {
725
                                                        np = gly.point(poi);
726
                                                        fon += FToStr(np.x())+" "+FToStr(-np.y())+" m\n";
727
                                                        nPath = false;
728
                                                }
729
                                                np = gly.point(poi+1);
730
                                                np1 = gly.point(poi+3);
731
                                                np2 = gly.point(poi+2);
732
                                                fon += FToStr(np.x()) + " " + FToStr(-np.y()) + " " +
733
                                                         FToStr(np1.x()) + " " + FToStr(-np1.y()) + " " +
734
                                                         FToStr(np2.x()) + " " + FToStr(-np2.y()) + " c\n";
735
                                        }
736
                                        fon += "h f*\n";
737
                                        np = getMinClipF(&gly);
738
                                        np1 = getMaxClipF(&gly);
739
                                }
5606 fschmid 740
                                else
741
                                {
742
                                        fon = "h";
743
                                        np = FPoint(0, 0);
744
                                        np1 = FPoint(0, 0);
745
                                }
746
                                StartObj(ObjCounter);
747
                                ObjCounter++;
748
                                PutDoc("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1\n");
749
                                PutDoc("/BBox [ "+FToStr(np.x())+" "+FToStr(-np.y())+" "+FToStr(np1.x())+ " "+FToStr(-np1.y())+" ]\n");
750
                                PutDoc("/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
751
                                PutDoc(">>\n");
752
                                if ((Options.Compress) && (CompAvail))
753
                                        fon = CompressStr(&fon);
754
                                PutDoc("/Length "+QString::number(fon.length()+1));
755
                                if ((Options.Compress) && (CompAvail))
756
                                        PutDoc("\n/Filter /FlateDecode");
757
                                PutDoc(" >>\nstream\n"+EncStream(fon, ObjCounter-1)+"\nendstream\nendobj\n");
5980 avox 758
                                Seite.XObjects[AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+QString::number(ig.key())] = ObjCounter-1;
3133 fschmid 759
                        }
760
                }
761
                else
762
                {
4229 craig 763
                        UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
5980 avox 764
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
3133 fschmid 765
                        {
3829 cbradney 766
                                QString fon("");
3133 fschmid 767
                                StartObj(ObjCounter);
768
                                QByteArray bb;
5980 avox 769
                                AllFonts[it.key()].RawData(bb);
3133 fschmid 770
                                uint posi;
771
                                for (posi = 6; posi < bb.size(); ++posi)
772
                                {
773
                                        if ((bb[posi] == static_cast<char>(0x80)) && (static_cast<int>(bb[posi+1]) == 2))
774
                                                break;
775
                                        fon += QChar(bb[posi]);
776
                                }
777
                                int len1 = fon.length();
778
                                uint ulen;
779
                                ulen = bb[posi+2] & 0xff;
780
                                ulen |= (bb[posi+3] << 8) & 0xff00;
781
                                ulen |= (bb[posi+4] << 16) & 0xff0000;
782
                                ulen |= (bb[posi+5] << 24) & 0xff000000;
783
                                if (ulen > bb.size())
784
                                        ulen = bb.size()-7;
785
                                posi += 6;
786
                                for (uint j = 0; j < ulen; ++j)
787
                                        fon += QChar(bb[posi++]);
788
                                posi += 6;
789
                                int len2 = fon.length()-len1;
790
                                for (uint j = posi; j < bb.size(); ++j)
791
                                {
792
                                        if ((bb[j] == static_cast<char>(0x80)) && (static_cast<int>(bb[j+1]) == 3))
793
                                                break;
794
                                        if (bb[j] == '\r')
795
                                                fon += "\n";
796
                                        else
797
                                                fon += QChar(bb[j]);
798
                                }
799
                                int len3 = fon.length()-len2-len1;
4264 craig 800
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 801
                                        fon = CompressStr(&fon);
4229 craig 802
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
803
                                PutDoc("/Length1 "+QString::number(len1)+"\n");
804
                                PutDoc("/Length2 "+QString::number(len2)+"\n");
805
                                PutDoc("/Length3 "+QString::number(len3)+"\n");
4264 craig 806
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 807
                                        PutDoc("/Filter /FlateDecode\n");
4229 craig 808
                                PutDoc(">>\nstream\n"+EncStream(fon,ObjCounter)+"\nendstream\nendobj\n");
3133 fschmid 809
                                ObjCounter++;
810
                        }
5980 avox 811
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
3133 fschmid 812
                        {
3829 cbradney 813
                                QString fon("");
814
                                QString fon2("");
815
                                QString tm("");
3133 fschmid 816
                                uint value;
817
                                bool ok = true;
818
                                StartObj(ObjCounter);
5980 avox 819
                                AllFonts[it.key()].EmbedFont(fon);
3133 fschmid 820
                                int len1 = fon.find("eexec")+5;
821
                                fon2 = fon.left(len1)+"\n";
822
                                int len2 = fon.find("0000000000000000000000000");
823
                                if (len2 == -1)
824
                                        len2 = fon.length()+1;
825
                                int count = 0;
826
                                for (int xx = len1; xx < len2-1; ++xx)
827
                                {
828
                                        tm = fon.at(xx);
829
                                        if ((tm == QChar(13)) || (tm == QChar(10)))
830
                                                continue;
831
                                        xx++;
832
                                        count++;
833
                                        tm += fon.at(xx);
834
                                        value = tm.toUInt(&ok, 16);
835
                                        fon2 += QChar(value);
836
                                }
837
                                fon2 += fon.mid(len2);
4264 craig 838
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 839
                                        fon2 = CompressStr(&fon2);
4229 craig 840
                                PutDoc("<<\n/Length "+QString::number(fon2.length()+1)+"\n");
841
                                PutDoc("/Length1 "+QString::number(len1+1)+"\n");
842
                                PutDoc("/Length2 "+QString::number(count)+"\n");
843
                                PutDoc(static_cast<int>(fon.length()-len2) == -1 ? QString("/Length3 0\n") : "/Length3 "+QString::number(fon.length()-len2)+"\n");
4264 craig 844
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 845
                                        PutDoc("/Filter /FlateDecode\n");
4229 craig 846
                                PutDoc(">>\nstream\n"+EncStream(fon2, ObjCounter)+"\nendstream\nendobj\n");
3133 fschmid 847
                                ObjCounter++;
848
                        }
5980 avox 849
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
3133 fschmid 850
                        {
3829 cbradney 851
                                QString fon("");
3133 fschmid 852
                                StartObj(ObjCounter);
853
                                QByteArray bb;
5980 avox 854
                                AllFonts[it.key()].RawData(bb);
3133 fschmid 855
                                //AV: += and append() dont't work because they stop at '\0' :-(
856
                                for (unsigned int i=0; i < bb.size(); i++)
857
                                        fon += QChar(bb[i]);
858
                                int len = fon.length();
4264 craig 859
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 860
                                        fon = CompressStr(&fon);
861
                                //qDebug(QString("sfnt data: size=%1 before=%2 compressed=%3").arg(bb.size()).arg(len).arg(fon.length()));
4229 craig 862
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
863
                                PutDoc("/Length1 "+QString::number(len)+"\n");
4264 craig 864
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 865
                                        PutDoc("/Filter /FlateDecode\n");
4229 craig 866
                                PutDoc(">>\nstream\n"+EncStream(fon, ObjCounter)+"\nendstream\nendobj\n");
3133 fschmid 867
                                ObjCounter++;
868
                        }
869
                        StartObj(ObjCounter);
5387 avox 870
                        // TODO: think about QByteArray ScFace::getFontDescriptor() -- AV
3133 fschmid 871
                        PutDoc("<<\n/Type /FontDescriptor\n");
5980 avox 872
                        PutDoc("/FontName /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
6213 fschmid 873
                        PutDoc("/FontBBox [ "+AllFonts[it.key()].FontBBoxAsString()+" ]\n");
3133 fschmid 874
                        PutDoc("/Flags ");
5980 avox 875
                        //FIXME: isItalic() should be queried from ScFace, not from Qt -- AV
3544 avox 876
                        //QFontInfo fo = QFontInfo(it.data());
3133 fschmid 877
                        int pfl = 0;
5980 avox 878
                        if (AllFonts[it.key()].isFixedPitch())
3133 fschmid 879
                                pfl = pfl ^ 1;
3544 avox 880
                        //if (fo.italic())
6213 fschmid 881
                        if (AllFonts[it.key()].ItalicAngleAsString() != "0")
3133 fschmid 882
                                pfl = pfl ^ 64;
883
//                      pfl = pfl ^ 4;
884
                        pfl = pfl ^ 32;
4229 craig 885
                        PutDoc(QString::number(pfl)+"\n");
6213 fschmid 886
                        PutDoc("/Ascent "+AllFonts[it.key()].ascentAsString()+"\n");
887
                        PutDoc("/Descent "+AllFonts[it.key()].descentAsString()+"\n");
888
                        PutDoc("/CapHeight "+AllFonts[it.key()].capHeightAsString()+"\n");
889
                        PutDoc("/ItalicAngle "+AllFonts[it.key()].ItalicAngleAsString()+"\n");
890
//                      PutDoc("/Ascent "+QString::number(static_cast<int>(AllFonts[it.key()].ascent()))+"\n");
891
//                      PutDoc("/Descent "+QString::number(static_cast<int>(AllFonts[it.key()].descent()))+"\n");
892
//                      PutDoc("/CapHeight "+QString::number(static_cast<int>(AllFonts[it.key()].capHeight()))+"\n");
893
//                      PutDoc("/ItalicAngle "+AllFonts[it.key()].italicAngle()+"\n");
894
//                      PutDoc("/StemV "+ AllFonts[it.key()].stemV() + "\n");
895
                        PutDoc("/StemV 1\n");
5980 avox 896
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
4229 craig 897
                                PutDoc("/FontFile2 "+QString::number(ObjCounter-1)+" 0 R\n");
5980 avox 898
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
4229 craig 899
                                PutDoc("/FontFile "+QString::number(ObjCounter-1)+" 0 R\n");
5980 avox 900
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
4229 craig 901
                                PutDoc("/FontFile "+QString::number(ObjCounter-1)+" 0 R\n");
3133 fschmid 902
                        PutDoc(">>\nendobj\n");
903
                        ObjCounter++;
4546 subik 904
/*                      if (!FT_Has_PS_Glyph_Names(AllFonts[it.key()])
3133 fschmid 905
                        {
906
                                StartObj(ObjCounter);
907
                                int chCount = 31;
908
                                PutDoc("[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ");
909
                                for (int ww = 31; ww < 256; ++ww)
910
                                {
4229 craig 911
                                        PutDoc(QString::number(static_cast<int>(AllFonts[it.key()]->CharWidth[itg.key()]*
3133 fschmid 912
                                                        1000))+" ");
913
                                        if (itg == gl.end())
914
                                                break;
915
                                        ++itg;
916
                                        chCount++;
917
                                }
918
                                PutDoc("]\nendobj\n");
919
                                ObjCounter++;
920
                                // put widths object
921
                                // encoding dictionary w/ base encoding w/o differences
922
                                StartObj(ObjCounter);
923
                                PutDoc("<<\n/Type /Font\n/Subtype ");
5980 avox 924
                                PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
4229 craig 925
                                PutDoc("/Name /Fo"+QString::number(a)+"\n");
5980 avox 926
                                PutDoc("/BaseFont /"+AllFonts[it.key()]->psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "" )+"\n");
3133 fschmid 927
                                //cf. widths:
928
                                PutDoc("/FirstChar 0\n");
4229 craig 929
                                PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
930
                                PutDoc("/Widths "+QString::number(ObjCounter-1)+" 0 R\n");
931
                                PutDoc("/FontDescriptor "+QString::number(ObjCounter-2)+" 0 R\n");
3133 fschmid 932
                                PutDoc(">>\nendobj\n");
4229 craig 933
                                Seite.FObjects["Fo"+QString::number(a)] = ObjCounter;
3133 fschmid 934
                                ObjCounter++;
935
                        }
936
                        else */
937
//                      {
6301 avox 938
                                QMap<uint,std::pair<QChar,QString> > gl;
939
                                AllFonts[it.key()].glyphNames(gl);
940
                                int nglyphs = 0;
941
                                QMap<uint,std::pair<QChar,QString> >::Iterator gli;
942
                                for (gli = gl.begin(); gli != gl.end(); ++gli) {
943
                                        if (gli.key() > nglyphs)
944
                                                nglyphs = gli.key();
945
                                }
946
                                ++nglyphs;
6302 avox 947
//                              qDebug(QString("pdflib: nglyphs %1 max %2").arg(nglyphs).arg(AllFonts[it.key()].maxGlyph()));
3133 fschmid 948
                                uint FontDes = ObjCounter - 1;
6301 avox 949
                                uint Fcc = nglyphs / 224;
950
                                if ((nglyphs % 224) != 0)
3133 fschmid 951
                                        Fcc += 1;
952
                                for (uint Fc = 0; Fc < Fcc; ++Fc)
953
                                {
954
                                        StartObj(ObjCounter);
6301 avox 955
                                        int chCount = 32;
956
                                        PutDoc("[ 0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 ");
957
                                        for (int ww = 32; ww < 256; ++ww)
3133 fschmid 958
                                        {
6301 avox 959
                                                uint glyph = 224 * Fc + ww - 32;
960
                                                if (gl.contains(glyph))
961
                                                        PutDoc(QString::number(static_cast<int>(AllFonts[it.key()].glyphWidth(glyph)* 1000))+" ");
962
                                                else
963
                                                        PutDoc("0 ");
964
 
6302 avox 965
                                                chCount++;
6301 avox 966
                                                if (signed(glyph) == nglyphs-1)
3133 fschmid 967
                                                        break;
968
                                        }
969
                                        PutDoc("]\nendobj\n");
970
                                        ObjCounter++;
971
                                        StartObj(ObjCounter);
972
                                        ObjCounter++;
973
                                        PutDoc("<< /Type /Encoding\n");
974
//                                      PutDoc("/BaseEncoding /" + AllFonts[it.key()]->FontEnc + "\n");
6301 avox 975
                                        PutDoc("/Differences [ \n");
3133 fschmid 976
                                        int crc = 0;
6301 avox 977
                                        bool startOfSeq = true;
3133 fschmid 978
                                        for (int ww2 = 32; ww2 < 256; ++ww2)
979
                                        {
6301 avox 980
                                                uint glyph = 224 * Fc + ww2 - 32;
981
                                                if (gl[glyph].second != "")
6213 fschmid 982
                                                {
6301 avox 983
                                                        if (startOfSeq) {
984
                                                                PutDoc(QString::number(ww2)+" ");
985
                                                                startOfSeq = false;
986
                                                        }
987
                                                        PutDoc("/"+gl[glyph].second+" ");
988
                                                        crc++;
6213 fschmid 989
                                                }
6301 avox 990
                                                else {
991
                                                        startOfSeq = true;
992
                                                }
993
                                                if (signed(glyph) == nglyphs-1)
3133 fschmid 994
                                                        break;
995
                                                if (crc > 8)
996
                                                {
997
                                                        PutDoc("\n");
998
                                                        crc = 0;
999
                                                }
1000
                                        }
1001
                                        PutDoc("]\n");
4546 subik 1002
 
3133 fschmid 1003
                                        PutDoc(">>\nendobj\n");
1004
                                        StartObj(ObjCounter);
1005
                                        PutDoc("<<\n/Type /Font\n/Subtype ");
5980 avox 1006
                                        PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
4229 craig 1007
                                        PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(Fc)+"\n");
5980 avox 1008
                                        PutDoc("/BaseFont /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
3133 fschmid 1009
                                        PutDoc("/FirstChar 0\n");
4229 craig 1010
                                        PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
1011
                                        PutDoc("/Widths "+QString::number(ObjCounter-2)+" 0 R\n");
1012
                                        PutDoc("/Encoding "+QString::number(ObjCounter-1)+" 0 R\n");
1013
                                        PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
3133 fschmid 1014
                                        PutDoc(">>\nendobj\n");
4229 craig 1015
                                        Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(Fc)] = ObjCounter;
3133 fschmid 1016
                                        ObjCounter++;
1017
                                } // for(Fc)
1018
//                      } // FT_Has_PS_Glyph_Names
1019
                }
1020
                a++;
1021
        }
4264 craig 1022
        if (Options.UseLPI)
3133 fschmid 1023
        {
1024
                StartObj(ObjCounter);
1025
                PutDoc("<<\n/Type /Halftone\n/HalftoneType 5\n");
4264 craig 1026
                QMap<QString,LPIData>::const_iterator itlp;
1027
                for (itlp = Options.LPISettings.constBegin(); itlp != Options.LPISettings.constEnd(); ++itlp)
3133 fschmid 1028
                {
1029
                        PutDoc("/"+itlp.key()+"\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency ");
4229 craig 1030
                        PutDoc(QString::number(itlp.data().Frequency)+"\n/Angle "+QString::number(itlp.data().Angle)+"\n/SpotFunction ");
3829 cbradney 1031
                        QString func ("");
3133 fschmid 1032
                        switch (itlp.data().SpotFunc)
1033
                        {
1034
                                case 0:
1035
                                        func = "/SimpleDot";
1036
                                        break;
1037
                                case 1:
1038
                                        func = "/Line";
1039
                                        break;
1040
                                case 2:
1041
                                        func = "/Round";
1042
                                        break;
1043
                                case 3:
1044
                                        func = "/Ellipse";
1045
                                        break;
1046
                                default:
1047
                                        func = "/SimpleDot";
1048
                                        break;
1049
                        }
1050
                        PutDoc(func+"\n>>\n");
1051
                }
1052
                PutDoc("/Default\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency 50\n/Angle 45\n/SpotFunction /Round\n>>\n");
1053
                PutDoc(">>\nendobj\n");
1054
                ObjCounter++;
1055
                StartObj(ObjCounter);
4229 craig 1056
                HTName = ResNam+QString::number(ResCount);
3133 fschmid 1057
                Transpar[HTName] = ObjCounter;
4229 craig 1058
                PutDoc("<< /Type /ExtGState\n/HT "+QString::number(ObjCounter-1)+" 0 R\n>>\nendobj\n");
3133 fschmid 1059
                ResCount++;
1060
                ObjCounter++;
1061
        }
1062
#ifdef HAVE_CMS
5880 jghali 1063
        if ((doc.HasCMS) && (Options.UseProfiles))
3133 fschmid 1064
        {
1065
                StartObj(ObjCounter);
1066
                ObjCounter++;
1067
                QString dataP;
1068
                struct ICCD dataD;
5243 cbradney 1069
                loadText(ScCore->InputProfiles[Options.SolidProf], &dataP);
3133 fschmid 1070
                PutDoc("<<\n");
4264 craig 1071
                if ((Options.Compress) && (CompAvail))
3133 fschmid 1072
                {
1073
                        PutDoc("/Filter /FlateDecode\n");
1074
                        dataP = CompressStr(&dataP);
1075
                }
4229 craig 1076
                PutDoc("/Length "+QString::number(dataP.length()+1)+"\n");
4264 craig 1077
                PutDoc("/N "+QString::number(Options.SComp)+"\n");
4229 craig 1078
                PutDoc(">>\nstream\n"+EncStream(dataP, ObjCounter-1)+"\nendstream\nendobj\n");
3133 fschmid 1079
                StartObj(ObjCounter);
4229 craig 1080
                dataD.ResName = ResNam+QString::number(ResCount);
1081
                dataD.ICCArray = "[ /ICCBased "+QString::number(ObjCounter-1)+" 0 R ]";
3133 fschmid 1082
                dataD.ResNum = ObjCounter;
4264 craig 1083
                ICCProfiles[Options.SolidProf] = dataD;
4229 craig 1084
                PutDoc("[ /ICCBased "+QString::number(ObjCounter-1)+" 0 R ]\n");
3133 fschmid 1085
                PutDoc("endobj\n");
1086
                ResCount++;
1087
                ObjCounter++;
1088
        }
1089
#endif
4264 craig 1090
        if (((Options.isGrayscale == false) && (Options.UseRGB == false)) && (Options.UseSpotColors))
3133 fschmid 1091
        {
4264 craig 1092
                doc.getUsedColors(colorsToUse);
3133 fschmid 1093
                ColorList::Iterator itf;
1094
                for (itf = colorsToUse.begin(); itf != colorsToUse.end(); ++itf)
1095
                {
1096
                        if ((colorsToUse[itf.key()].isSpotColor()) || (colorsToUse[itf.key()].isRegistrationColor()))
1097
                        {
1098
                                int cc, cm, cy, ck;
1099
                                struct SpotC spotD;
1100
                                colorsToUse[itf.key()].getCMYK(&cc, &cm, &cy, &ck);
1101
                                QString colorDesc = "{\ndup "+FToStr(static_cast<double>(cc) / 255)+"\nmul exch dup ";
1102
                                colorDesc += FToStr(static_cast<double>(cm) / 255)+"\nmul exch dup ";
1103
                                colorDesc += FToStr(static_cast<double>(cy) / 255)+"\nmul exch ";
1104
                                colorDesc += FToStr(static_cast<double>(ck) / 255)+" mul }";
1105
                                StartObj(ObjCounter);
1106
                                ObjCounter++;
1107
                                PutDoc("<<\n/FunctionType 4\n");
1108
                                PutDoc("/Domain [0.0 1.0]\n");
1109
                                PutDoc("/Range [0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]\n");
4229 craig 1110
                                PutDoc("/Length "+QString::number(colorDesc.length()+1)+"\n");
1111
                                PutDoc(">>\nstream\n"+EncStream(colorDesc, ObjCounter-1)+"\nendstream\nendobj\n");
3133 fschmid 1112
                                StartObj(ObjCounter);
1113
                                PutDoc("[ /Separation /");
1114
                                if (colorsToUse[itf.key()].isRegistrationColor())
1115
                                        PutDoc("All");
1116
                                else
3440 fschmid 1117
                                        PutDoc(itf.key().simplifyWhiteSpace().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ).replace("#", "_"));
4229 craig 1118
                                PutDoc(" /DeviceCMYK "+QString::number(ObjCounter-1)+" 0 R ]\nendobj\n");
1119
                                spotD.ResName = spotNam+QString::number(spotCount);
3133 fschmid 1120
                                spotD.ResNum = ObjCounter;
1121
                                spotMap.insert(itf.key(), spotD);
1122
                                spotCount++;
1123
                                ObjCounter++;
1124
                        }
1125
                }
1126
        }
4264 craig 1127
        if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 1128
        {
1129
                struct Layer ll;
1130
                struct OCGInfo ocg;
1131
                ll.isPrintable = false;
1132
                ll.LNr = 0;
1133
                int Lnr = 0;
3829 cbradney 1134
                QString ocgNam("oc");
4264 craig 1135
                uint docLayersCount=doc.Layers.count();
3829 cbradney 1136
                for (uint la = 0; la < docLayersCount; ++la)
3133 fschmid 1137
                {
3829 cbradney 1138
                        QString tmp("");
4264 craig 1139
                        Level2Layer(&doc, &ll, Lnr);
3133 fschmid 1140
                        ocg.Name = ocgNam+tmp.setNum(ll.LNr);
1141
                        ocg.ObjNum = ObjCounter;
1142
                        ocg.visible = ll.isViewable;
1143
                        OCGEntries.insert(ll.Name, ocg);
1144
                        StartObj(ObjCounter);
1145
                        ObjCounter++;
1146
                        PutDoc("<<\n");
1147
                        PutDoc("/Type /OCG\n");
1148
                        PutDoc("/Name ("+ll.Name+")\n");
1149
                        PutDoc(">>\nendobj\n");
1150
                        Lnr++;
1151
                }
1152
        }
1153
        return true;
1154
}
1155
 
4241 craig 1156
void PDFlib::PDF_TemplatePage(const Page* pag, bool )
3133 fschmid 1157
{
1158
        QString tmp;
1159
        ActPageP = pag;
1160
        PageItem* ite;
1161
        QPtrList<PageItem> PItems;
1162
        int Lnr = 0;
1163
        struct Layer ll;
1164
        ll.isPrintable = false;
1165
        ll.LNr = 0;
1166
        Inhalt = "";
1167
        Seite.AObjects.clear();
4264 craig 1168
        for (uint la = 0; la < doc.Layers.count(); ++la)
3133 fschmid 1169
        {
4264 craig 1170
                Level2Layer(&doc, &ll, Lnr);
1171
                PItems = doc.MasterItems;
3133 fschmid 1172
                if (ll.isPrintable)
1173
                {
4264 craig 1174
                        if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 1175
                                PutPage("/OC /"+OCGEntries[ll.Name].Name+" BDC\n");
1176
                        for (uint a = 0; a < PItems.count(); ++a)
1177
                        {
1178
                                Inhalt = "";
1179
                                ite =PItems.at(a);
1180
                                if (ite->LayerNr != ll.LNr)
1181
                                        continue;
4726 fschmid 1182
                                double x = pag->xOffset();
1183
                                double y = pag->yOffset();
1184
                                double w = pag->width();
1185
                                double h1 = pag->height();
4580 cbradney 1186
                                double ilw=ite->lineWidth();
4726 fschmid 1187
                                double x2 = ite->BoundingX - ilw / 2.0;
1188
                                double y2 = ite->BoundingY - ilw / 2.0;
1189
                                double w2 = ite->BoundingW + ilw;
1190
                                double h2 = ite->BoundingH + ilw;
1191
                                if (!( QMAX( x, x2 ) <= QMIN( x+w, x2+w2 ) && QMAX( y, y2 ) <= QMIN( y+h1, y2+h2 )))
3133 fschmid 1192
                                        continue;
1193
                                if (ite->ChangedMasterItem)
1194
                                        continue;
5685 cbradney 1195
                                if ((!pag->pageName().isEmpty()) && (ite->OwnPage != static_cast<int>(pag->pageNr())) && (ite->OwnPage != -1))
3133 fschmid 1196
                                        continue;
1197
                                PutPage("q\n");
5320 fschmid 1198
                                if ((ite->doOverprint) && (!Options.doOverprint) && (!Options.UseRGB))
1199
                                {
1200
                                        StartObj(ObjCounter);
1201
                                        QString ShName = ResNam+QString::number(ResCount);
1202
                                        Transpar[ShName] = ObjCounter;
1203
                                        ResCount++;
1204
                                        ObjCounter++;
1205
                                        PutDoc("<< /Type /ExtGState\n");
1206
                                        PutDoc("/OP true\n");
1207
                                        PutDoc("/op true\n");
1208
                                        PutDoc("/OPM 1\n");
1209
                                        PutDoc(">>\nendobj\n");
1210
                                        PutPage("/"+ShName+" gs\n");
1211
                                }
4679 fschmid 1212
/* Bookmarks on Master Pages do not make any sense */
1213
//                              if ((ite->isBookmark) && (Options.Bookmarks))
1214
//                                      PDF_Bookmark(ite, pag->height() - (ite->yPos() - pag->yOffset()));
5685 cbradney 1215
                                if (!ite->printEnabled() || ((ite->itemType() == PageItem::TextFrame) && (!pag->pageName().isEmpty())))
3133 fschmid 1216
                                {
1217
                                        PutPage("Q\n");
1218
                                        continue;
1219
                                }
4546 subik 1220
                                if (ite->fillColor() != CommonStrings::None)
3133 fschmid 1221
                                        PutPage(putColor(ite->fillColor(), ite->fillShade(), true));
4546 subik 1222
                                if (ite->lineColor() != CommonStrings::None)
3133 fschmid 1223
                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), false));
4580 cbradney 1224
                                Inhalt += FToStr(fabs(ite->lineWidth()))+" w\n";
3133 fschmid 1225
                                if (ite->DashValues.count() != 0)
1226
                                {
1227
                                        PutPage("[ ");
1228
                                        QValueList<double>::iterator it;
1229
                                        for ( it = ite->DashValues.begin(); it != ite->DashValues.end(); ++it )
1230
                                        {
1231
                                                int da = static_cast<int>(*it);
1232
                                                if (da != 0)
4229 craig 1233
                                                        PutPage(QString::number(da)+" ");
3133 fschmid 1234
                                        }
4229 craig 1235
                                        PutPage("] "+QString::number(static_cast<int>(ite->DashOffset))+" d\n");
3133 fschmid 1236
                                }
1237
                                else
1238
                                {
4580 cbradney 1239
                                        QString Dt = FToStr(QMAX(2*fabs(ite->lineWidth()), 1));
1240
                                        QString Da = FToStr(QMAX(6*fabs(ite->lineWidth()), 1));
3133 fschmid 1241
                                        switch (ite->PLineArt)
1242
                                        {
1243
                                                case Qt::SolidLine:
1244
                                                        PutPage("[] 0 d\n");
1245
                                                        break;
1246
                                                case Qt::DashLine:
1247
                                                        PutPage("["+Da+" "+Dt+"] 0 d\n");
1248
                                                        break;
1249
                                                case Qt::DotLine:
1250
                                                        PutPage("["+Dt+"] 0 d\n");
1251
                                                        break;
1252
                                                case Qt::DashDotLine:
1253
                                                        PutPage("["+Da+" "+Dt+" "+Dt+" "+Dt+"] 0 d\n");
1254
                                                        break;
1255
                                                case Qt::DashDotDotLine:
1256
                                                        PutPage("["+Da+" "+Dt+" "+Dt+" "+Dt+" "+Dt+" "+Dt+"] 0 d\n");
1257
                                                        break;
1258
                                                default:
1259
                                                        PutPage("[] 0 d\n");
1260
                                                        break;
1261
                                        }
1262
                                }
1263
                                switch (ite->PLineEnd)
1264
                                {
1265
                                        case Qt::FlatCap:
1266
                                                PutPage("0 J\n");
1267
                                                break;
1268
                                        case Qt::SquareCap:
1269
                                                PutPage("2 J\n");
1270
                                                break;
1271
                                        case Qt::RoundCap:
1272
                                                PutPage("1 J\n");
1273
                                                break;
1274
                                        default:
1275
                                                PutPage("0 J\n");
1276
                                                break;
1277
                                }
1278
                                switch (ite->PLineJoin)
1279
                                {
1280
                                        case Qt::MiterJoin:
1281
                                                PutPage("0 j\n");
1282
                                                break;
1283
                                        case Qt::BevelJoin:
1284
                                                PutPage("2 j\n");
1285
                                                break;
1286
                                        case Qt::RoundJoin:
1287
                                                PutPage("1 j\n");
1288
                                                break;
1289
                                        default:
1290
                                                PutPage("0 j\n");
1291
                                                break;
1292
                                }
3903 cbradney 1293
                                PutPage("1 0 0 1 "+FToStr(ite->xPos() - pag->xOffset())+" "+FToStr(pag->height() - (ite->yPos()  - pag->yOffset()))+" cm\n");
3934 cbradney 1294
                                if (ite->rotation() != 0)
3133 fschmid 1295
                                {
3934 cbradney 1296
                                        double sr = sin(-ite->rotation()* M_PI / 180.0);
1297
                                        double cr = cos(-ite->rotation()* M_PI / 180.0);
3133 fschmid 1298
                                        if ((cr * cr) < 0.000001)
1299
                                                cr = 0;
1300
                                        if ((sr * sr) < 0.000001)
1301
                                                sr = 0;
1302
                                        PutPage(FToStr(cr)+" "+FToStr(sr)+" "+FToStr(-sr)+" "+FToStr(cr)+" 0 0 cm\n");
1303
                                }
1304
                                switch (ite->itemType())
1305
                                {
1306
                                        case PageItem::ImageFrame:
5748 fschmid 1307
                                                if (((ite->fillTransparency() != 0) || (ite->fillBlendmode() != 0)) && (Options.Version >= 14))
1308
                                                        PutPage(PDF_TransparenzFill(ite));
4546 subik 1309
                                                if ((ite->fillColor() != CommonStrings::None) || (ite->GrType != 0))
3133 fschmid 1310
                                                {
1311
                                                        if (ite->GrType != 0)
1312
                                                                PutPage(PDF_Gradient(ite));
1313
                                                        else
1314
                                                        {
1315
                                                                PutPage(SetClipPath(ite));
1316
                                                                PutPage("h\nf*\n");
1317
                                                        }
1318
                                                }
1319
                                                PutPage("q\n");
1320
                                                if (ite->imageClip.size() != 0)
4744 fschmid 1321
                                                {
3133 fschmid 1322
                                                        PutPage(SetClipPathImage(ite));
4744 fschmid 1323
                                                        PutPage("h\nW*\nn\n");
1324
                                                }
1325
                                                PutPage(SetClipPath(ite));
3133 fschmid 1326
                                                PutPage("h\nW*\nn\n");
1327
                                                if (ite->imageFlippedH())
3934 cbradney 1328
                                                        PutPage("-1 0 0 1 "+FToStr(ite->width())+" 0 cm\n");
3133 fschmid 1329
                                                if (ite->imageFlippedV())
3934 cbradney 1330
                                                        PutPage("1 0 0 -1 0 "+FToStr(-ite->height())+" cm\n");
3133 fschmid 1331
                                                if ((ite->PicAvail) && (!ite->Pfile.isEmpty()))
3985 cbradney 1332
                                                        PutPage(PDF_Image(ite, ite->Pfile, ite->imageXScale(), ite->imageYScale(), ite->imageXOffset(), -ite->imageYOffset(), false, ite->IProfile, ite->UseEmbedded, ite->IRender));
3133 fschmid 1333
                                                PutPage("Q\n");
4546 subik 1334
                                                if (((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty())) && (!ite->isTableItem))
3133 fschmid 1335
                                                {
5748 fschmid 1336
                                                        if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1337
                                                                PutPage(PDF_TransparenzStroke(ite));
4580 cbradney 1338
                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1339
                                                        {
1340
                                                                PutPage(SetClipPath(ite));
1341
                                                                PutPage("h\nS\n");
1342
                                                        }
1343
                                                        else
1344
                                                        {
4264 craig 1345
                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1346
                                                                for (int it = ml.size()-1; it > -1; it--)
1347
                                                                {
1348
                                                                        PutPage(setStrokeMulti(&ml[it]));
1349
                                                                        PutPage(SetClipPath(ite));
1350
                                                                        PutPage("h\nS\n");
1351
                                                                }
1352
                                                        }
1353
                                                }
1354
                                                break;
1355
                                        case PageItem::TextFrame:
1356
                                                break;
1357
                                        case PageItem::Line:
5748 fschmid 1358
                                                if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1359
                                                        PutPage(PDF_TransparenzStroke(ite));
3133 fschmid 1360
                                                if (ite->NamedLStyle.isEmpty())
1361
                                                {
1362
                                                        PutPage("0 0 m\n");
3934 cbradney 1363
                                                        PutPage(FToStr(ite->width())+" 0 l\n");
3133 fschmid 1364
                                                        PutPage("S\n");
1365
                                                }
1366
                                                else
1367
                                                {
4264 craig 1368
                                                        multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1369
                                                        for (int it = ml.size()-1; it > -1; it--)
1370
                                                        {
1371
                                                                PutPage(setStrokeMulti(&ml[it]));
1372
                                                                PutPage("0 0 m\n");
3934 cbradney 1373
                                                                PutPage(FToStr(ite->width())+" 0 l\n");
3133 fschmid 1374
                                                                PutPage("S\n");
1375
                                                        }
1376
                                                }
4061 craig 1377
                                                if (ite->startArrowIndex() != 0)
3133 fschmid 1378
                                                {
1379
                                                        QWMatrix arrowTrans;
4264 craig 1380
                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->startArrowIndex()-1)).points.copy();
3133 fschmid 1381
                                                        arrowTrans.translate(0, 0);
4580 cbradney 1382
                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1383
                                                        arrowTrans.scale(-1,1);
1384
                                                        arrow.map(arrowTrans);
4264 craig 1385
                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1386
                                                        {
1387
                                                                StartObj(ObjCounter);
4229 craig 1388
                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1389
                                                                Transpar[ShName] = ObjCounter;
1390
                                                                ResCount++;
1391
                                                                ObjCounter++;
1392
                                                                PutDoc("<< /Type /ExtGState\n");
1393
                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1394
                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1395
                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1396
                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1397
                                                                PutPage("/"+ShName+" gs\n");
1398
                                                        }
4016 fschmid 1399
                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1400
                                                        PutPage(SetClipPathArray(&arrow));
1401
                                                        PutPage("h\nf*\n");
1402
                                                }
4061 craig 1403
                                                if (ite->endArrowIndex() != 0)
3133 fschmid 1404
                                                {
1405
                                                        QWMatrix arrowTrans;
4264 craig 1406
                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->endArrowIndex()-1)).points.copy();
3934 cbradney 1407
                                                        arrowTrans.translate(ite->width(), 0);
4580 cbradney 1408
                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1409
                                                        arrow.map(arrowTrans);
4264 craig 1410
                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1411
                                                        {
1412
                                                                StartObj(ObjCounter);
4229 craig 1413
                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1414
                                                                Transpar[ShName] = ObjCounter;
1415
                                                                ResCount++;
1416
                                                                ObjCounter++;
1417
                                                                PutDoc("<< /Type /ExtGState\n");
1418
                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1419
                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1420
                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1421
                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1422
                                                                PutPage("/"+ShName+" gs\n");
1423
                                                        }
4016 fschmid 1424
                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1425
                                                        PutPage(SetClipPathArray(&arrow));
1426
                                                        PutPage("h\nf*\n");
1427
                                                }
1428
                                                break;
3232 cbradney 1429
                                        case PageItem::ItemType1:
1430
                                        case PageItem::ItemType3:
3133 fschmid 1431
                                        case PageItem::Polygon:
5748 fschmid 1432
                                                if (((ite->fillTransparency() != 0) || (ite->fillBlendmode() != 0)) && (Options.Version >= 14))
1433
                                                        PutPage(PDF_TransparenzFill(ite));
3133 fschmid 1434
                                                if (ite->GrType != 0)
1435
                                                        PutPage(PDF_Gradient(ite));
1436
                                                else
1437
                                                {
4546 subik 1438
                                                        if (ite->fillColor() != CommonStrings::None)
3133 fschmid 1439
                                                        {
1440
                                                                PutPage(SetClipPath(ite));
1441
                                                                PutPage("h\nf*\n");
1442
                                                        }
1443
                                                }
4546 subik 1444
                                                if ((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()))
3133 fschmid 1445
                                                {
5748 fschmid 1446
                                                        if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1447
                                                                PutPage(PDF_TransparenzStroke(ite));
4580 cbradney 1448
                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1449
                                                        {
1450
                                                                PutPage(SetClipPath(ite));
1451
                                                                PutPage("h\nS\n");
1452
                                                        }
1453
                                                        else
1454
                                                        {
4264 craig 1455
                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1456
                                                                for (int it = ml.size()-1; it > -1; it--)
1457
                                                                {
1458
                                                                        PutPage(setStrokeMulti(&ml[it]));
1459
                                                                        PutPage(SetClipPath(ite));
1460
                                                                        PutPage("h\nS\n");
1461
                                                                }
1462
                                                        }
1463
                                                }
1464
                                                break;
1465
                                        case PageItem::PolyLine:
4658 fschmid 1466
                                                if (ite->PoLine.size() > 4) // && ((ite->PoLine.point(0) != ite->PoLine.point(1)) || (ite->PoLine.point(2) != ite->PoLine.point(3))))
3133 fschmid 1467
                                                {
5748 fschmid 1468
                                                        if (((ite->fillTransparency() != 0) || (ite->fillBlendmode() != 0)) && (Options.Version >= 14))
1469
                                                                PutPage(PDF_TransparenzFill(ite));
3133 fschmid 1470
                                                        if (ite->GrType != 0)
1471
                                                                PutPage(PDF_Gradient(ite));
1472
                                                        else
1473
                                                        {
4546 subik 1474
                                                                if (ite->fillColor() != CommonStrings::None)
3133 fschmid 1475
                                                                {
1476
                                                                        PutPage(SetClipPath(ite));
1477
                                                                        PutPage("h\nf*\n");
1478
                                                                }
1479
                                                        }
1480
                                                }
4546 subik 1481
                                                if ((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()))
3133 fschmid 1482
                                                {
5748 fschmid 1483
                                                        if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1484
                                                                PutPage(PDF_TransparenzStroke(ite));
4580 cbradney 1485
                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1486
                                                        {
1487
                                                                PutPage(SetClipPath(ite, false));
1488
                                                                PutPage("S\n");
1489
                                                        }
1490
                                                        else
1491
                                                        {
4264 craig 1492
                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1493
                                                                for (int it = ml.size()-1; it > -1; it--)
1494
                                                                {
1495
                                                                        PutPage(setStrokeMulti(&ml[it]));
1496
                                                                        PutPage(SetClipPath(ite, false));
1497
                                                                        PutPage("S\n");
1498
                                                                }
1499
                                                        }
1500
                                                }
4061 craig 1501
                                                if (ite->startArrowIndex() != 0)
3133 fschmid 1502
                                                {
1503
                                                        FPoint Start = ite->PoLine.point(0);
1504
                                                        for (uint xx = 1; xx < ite->PoLine.size(); xx += 2)
1505
                                                        {
1506
                                                                FPoint Vector = ite->PoLine.point(xx);
1507
                                                                if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
1508
                                                                {
1509
                                                                        double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI);
1510
                                                                        QWMatrix arrowTrans;
4264 craig 1511
                                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->startArrowIndex()-1)).points.copy();
3133 fschmid 1512
                                                                        arrowTrans.translate(Start.x(), Start.y());
1513
                                                                        arrowTrans.rotate(r);
4580 cbradney 1514
                                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1515
                                                                        arrow.map(arrowTrans);
4264 craig 1516
                                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1517
                                                                        {
1518
                                                                                StartObj(ObjCounter);
4229 craig 1519
                                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1520
                                                                                Transpar[ShName] = ObjCounter;
1521
                                                                                ResCount++;
1522
                                                                                ObjCounter++;
1523
                                                                                PutDoc("<< /Type /ExtGState\n");
1524
                                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1525
                                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1526
                                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1527
                                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1528
                                                                                PutPage("/"+ShName+" gs\n");
1529
                                                                        }
4016 fschmid 1530
                                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1531
                                                                        PutPage(SetClipPathArray(&arrow));
1532
                                                                        PutPage("h\nf*\n");
1533
                                                                        break;
1534
                                                                }
1535
                                                        }
1536
                                                }
4061 craig 1537
                                                if (ite->endArrowIndex() != 0)
3133 fschmid 1538
                                                {
1539
                                                        FPoint End = ite->PoLine.point(ite->PoLine.size()-2);
1540
                                                        for (uint xx = ite->PoLine.size()-1; xx > 0; xx -= 2)
1541
                                                        {
1542
                                                                FPoint Vector = ite->PoLine.point(xx);
1543
                                                                if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
1544
                                                                {
1545
                                                                        double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI);
1546
                                                                        QWMatrix arrowTrans;
4264 craig 1547
                                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->endArrowIndex()-1)).points.copy();
3133 fschmid 1548
                                                                        arrowTrans.translate(End.x(), End.y());
1549
                                                                        arrowTrans.rotate(r);
4580 cbradney 1550
                                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1551
                                                                        arrow.map(arrowTrans);
4264 craig 1552
                                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1553
                                                                        {
1554
                                                                                StartObj(ObjCounter);
4229 craig 1555
                                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1556
                                                                                Transpar[ShName] = ObjCounter;
1557
                                                                                ResCount++;
1558
                                                                                ObjCounter++;
1559
                                                                                PutDoc("<< /Type /ExtGState\n");
1560
                                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1561
                                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1562
                                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1563
                                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1564
                                                                                PutPage("/"+ShName+" gs\n");
1565
                                                                        }
4016 fschmid 1566
                                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1567
                                                                        PutPage(SetClipPathArray(&arrow));
1568
                                                                        PutPage("h\nf*\n");
1569
                                                                        break;
1570
                                                                }
1571
                                                        }
1572
                                                }
1573
                                                break;
1574
                                        case PageItem::PathText:
1575
                                                if (ite->PoShow)
1576
                                                {
1577
                                                        if (ite->PoLine.size() > 3)
1578
                                                        {
1579
                                                                PutPage("q\n");
4546 subik 1580
                                                                if ((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()))
3133 fschmid 1581
                                                                {
5748 fschmid 1582
                                                                        if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1583
                                                                                PutPage(PDF_TransparenzStroke(ite));
4580 cbradney 1584
                                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1585
                                                                        {
1586
                                                                                PutPage(SetClipPath(ite, false));
1587
                                                                                PutPage("S\n");
1588
                                                                        }
1589
                                                                        else
1590
                                                                        {
4264 craig 1591
                                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
4546 subik 1592
                                                                                for (int it = ml.size()-1;
3133 fschmid 1593
                                                                                        it > -1; it--)
1594
                                                                                        {
1595
                                                                                        PutPage(setStrokeMulti(&ml[it]));
1596
                                                                                        PutPage(SetClipPath(ite, false));
1597
                                                                                        PutPage("S\n");
1598
                                                                                        }
1599
                                                                        }
1600
                                                                }
1601
                                                                PutPage("Q\n");
1602
                                                        }
1603
                                                }
5748 fschmid 1604
                                                if (((ite->fillTransparency() != 0) || (ite->fillBlendmode() != 0)) && (Options.Version >= 14))
1605
                                                        PutPage(PDF_TransparenzFill(ite));
3200 cbradney 1606
                                                PutPage(setTextSt(ite, pag->pageNr(), pag));
3133 fschmid 1607
                                                break;
1608
                                        }
1609
                                PutPage("Q\n");
1610
                                StartObj(ObjCounter);
1611
                                ObjCounter++;
1612
                                PutDoc("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1\n");
3200 cbradney 1613
                                PutDoc("/BBox [ 0 0 "+FToStr(ActPageP->width())+" "+FToStr(ActPageP->height())+" ]\n");
3133 fschmid 1614
                                PutDoc("/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
1615
                                if (Seite.ImgObjects.count() != 0)
1616
                                {
1617
                                        PutDoc("/XObject <<\n");
1618
                                        QMap<QString,int>::Iterator it;
1619
                                        for (it = Seite.ImgObjects.begin(); it != Seite.ImgObjects.end(); ++it)
4229 craig 1620
                                                PutDoc("/"+it.key()+" "+QString::number(it.data())+" 0 R\n");
3133 fschmid 1621
                                        PutDoc(">>\n");
1622
                                }
1623
                                if (Seite.FObjects.count() != 0)
1624
                                {
1625
                                        PutDoc("/Font << \n");
1626
                                        QMap<QString,int>::Iterator it2;
1627
                                        for (it2 = Seite.FObjects.begin(); it2 != Seite.FObjects.end(); ++it2)
4229 craig 1628
                                                PutDoc("/"+it2.key()+" "+QString::number(it2.data())+" 0 R\n");
3133 fschmid 1629
                                        PutDoc(">>\n");
1630
                                }
1631
                                if (Shadings.count() != 0)
1632
                                {
1633
                                        PutDoc("/Shading << \n");
1634
                                        QMap<QString,int>::Iterator it3;
1635
                                        for (it3 = Shadings.begin(); it3 != Shadings.end(); ++it3)
4229 craig 1636
                                                PutDoc("/"+it3.key()+" "+QString::number(it3.data())+" 0 R\n");
3133 fschmid 1637
                                        PutDoc(">>\n");
1638
                                }
6378 fschmid 1639
                                if (Patterns.count() != 0)
1640
                                {
1641
                                        PutDoc("/Pattern << \n");
1642
                                        QMap<QString,int>::Iterator it3p;
1643
                                        for (it3p = Patterns.begin(); it3p != Patterns.end(); ++it3p)
1644
                                                PutDoc("/"+it3p.key()+" "+QString::number(it3p.data())+" 0 R\n");
1645
                                        PutDoc(">>\n");
1646
                                }
3133 fschmid 1647
                                if (Transpar.count() != 0)
1648
                                {
1649
                                        PutDoc("/ExtGState << \n");
1650
                                        QMap<QString,int>::Iterator it3t;
1651
                                        for (it3t = Transpar.begin(); it3t != Transpar.end(); ++it3t)
4229 craig 1652
                                                PutDoc("/"+it3t.key()+" "+QString::number(it3t.data())+" 0 R\n");
3133 fschmid 1653
                                        PutDoc(">>\n");
1654
                                }
1655
                                if ((ICCProfiles.count() != 0) || (spotMap.count() != 0))
1656
                                {
1657
                                        PutDoc("/ColorSpace << \n");
1658
                                        QMap<QString,ICCD>::Iterator it3c;
1659
                                        if (ICCProfiles.count() != 0)
1660
                                        {
1661
                                                for (it3c = ICCProfiles.begin(); it3c != ICCProfiles.end(); ++it3c)
4229 craig 1662
                                                        PutDoc("/"+it3c.data().ResName+" "+QString::number(it3c.data().ResNum)+" 0 R\n");
3133 fschmid 1663
                                        }
1664
                                        QMap<QString,SpotC>::Iterator it3sc;
1665
                                        if (spotMap.count() != 0)
1666
                                        {
1667
                                        for (it3sc = spotMap.begin(); it3sc != spotMap.end(); ++it3sc)
4229 craig 1668
                                                PutDoc("/"+it3sc.data().ResName+" "+QString::number(it3sc.data().ResNum)+" 0 R\n");
3133 fschmid 1669
                                        }
1670
                                        PutDoc(">>\n");
1671
                                }
1672
                                PutDoc(">>\n");
4264 craig 1673
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 1674
                                        Inhalt = CompressStr(&Inhalt);
4229 craig 1675
                                PutDoc("/Length "+QString::number(Inhalt.length()+1));
4264 craig 1676
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 1677
                                        PutDoc("\n/Filter /FlateDecode");
4229 craig 1678
                                PutDoc(" >>\nstream\n"+EncStream(Inhalt, ObjCounter-1)+"\nendstream\nendobj\n");
5685 cbradney 1679
                                QString name = pag->pageName().simplifyWhiteSpace().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ) + QString::number(ite->ItemNr);
3133 fschmid 1680
                                Seite.XObjects[name] = ObjCounter-1;
1681
                                }
4264 craig 1682
                                if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 1683
                                        PutPage("EMC\n");
1684
                        }
1685
                Lnr++;
1686
        }
1687
}
1688
 
4241 craig 1689
void PDFlib::PDF_Begin_Page(const Page* pag, QPixmap pm)
3133 fschmid 1690
{
1691
        QString tmp;
1692
        ActPageP = pag;
1693
        Inhalt = "";
1694
        Seite.AObjects.clear();
4264 craig 1695
        if (Options.Thumbnails)
3133 fschmid 1696
        {
5593 avox 1697
                ScImage img(pm.convertToImage());
5234 fschmid 1698
                QByteArray array = img.ImageToArray();
4264 craig 1699
                if ((Options.Compress) && (CompAvail))
5234 fschmid 1700
                        array = CompressArray(&array);
3133 fschmid 1701
                StartObj(ObjCounter);
4229 craig 1702
                PutDoc("<<\n/Width "+QString::number(img.width())+"\n");
1703
                PutDoc("/Height "+QString::number(img.height())+"\n");
3133 fschmid 1704
                PutDoc("/ColorSpace /DeviceRGB\n/BitsPerComponent 8\n");
5234 fschmid 1705
 
1706
                PutDoc("/Length "+QString::number(array.size()+1)+"\n");
4264 craig 1707
                if ((Options.Compress) && (CompAvail))
3133 fschmid 1708
                        PutDoc("/Filter /FlateDecode\n");
5234 fschmid 1709
                PutDoc(">>\nstream\n");
1710
                PutDoc(EncStreamArray(array, ObjCounter));
1711
                PutDoc("\nendstream\nendobj\n");
3133 fschmid 1712
                Seite.Thumb = ObjCounter;
1713
                ObjCounter++;
1714
        }
1715
}
1716
 
1717
void PDFlib::PDF_End_Page()
1718
{
3200 cbradney 1719
        uint PgNr =  ActPageP->pageNr();
3133 fschmid 1720
        Seite.ObjNum = ObjCounter;