Subversion Repositories Scribus

Rev

Rev 6376 | Rev 6379 | 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;
469
        Bvie = vi;
470
        BookMinUse = false;
471
        UsedFontsP.clear();
4264 craig 472
        if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 473
                ObjCounter = 10;
474
        else
475
                ObjCounter = 9;
4264 craig 476
        switch (Options.Version)
3133 fschmid 477
        {
478
                case 12:
479
                case 13:
4229 craig 480
                        PutDoc("%PDF-1.3\n");
3133 fschmid 481
                        break;
482
                case 14:
483
                        PutDoc("%PDF-1.4\n");
484
                        break;
485
                case 15:
486
                        PutDoc("%PDF-1.5\n");
487
                        break;
488
        }
4264 craig 489
        if (Options.Version == 12)
3133 fschmid 490
                ObjCounter++;
4229 craig 491
        PutDoc("%\xc7\xec\x8f\xa2\n");
3133 fschmid 492
        StartObj(1);
493
        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 494
        if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 495
                PutDoc("/OCProperties 9 0 R\n");
4264 craig 496
        if (Options.Version == 12)
4229 craig 497
                PutDoc("/OutputIntents [ "+QString::number(ObjCounter-1)+" 0 R ]\n");
4197 fschmid 498
        PutDoc("/PageLayout ");
4264 craig 499
        switch (Options.PageLayout)
3133 fschmid 500
        {
4197 fschmid 501
                case PDFOptions::SinglePage:
502
                        PutDoc("/SinglePage\n");
503
                        break;
504
                case PDFOptions::OneColumn:
505
                        PutDoc("/OneColumn\n");
506
                        break;
507
                case PDFOptions::TwoColumnLeft:
508
                        PutDoc("/TwoColumnLeft\n");
509
                        break;
510
                case PDFOptions::TwoColumnRight:
511
                        PutDoc("/TwoColumnRight\n");
512
                        break;
513
        }
4264 craig 514
        if (Options.displayBookmarks)
4197 fschmid 515
                PutDoc("/PageMode /UseOutlines\n");
4264 craig 516
        else if (Options.displayFullscreen)
4197 fschmid 517
                PutDoc("/PageMode /FullScreen\n");
4264 craig 518
        else if (Options.displayThumbs)
4197 fschmid 519
                PutDoc("/PageMode /UseThumbs\n");
4264 craig 520
        else if ((Options.Version == 15) && (Options.displayLayers))
4197 fschmid 521
                        PutDoc("/PageMode /UseOC\n");
4264 craig 522
        if (!Options.openAction.isEmpty())
4197 fschmid 523
        {
4264 craig 524
                PutDoc("/OpenAction << /S /JavaScript /JS (this."+Options.openAction+"\\(\\)) >>\n");
3133 fschmid 525
        }
526
        PutDoc("/ViewerPreferences\n<<\n/PageDirection ");
4264 craig 527
        PutDoc( Options.Binding == 0 ? "/L2R\n" : "/R2L\n");
528
        if (Options.hideToolBar)
4201 fschmid 529
                PutDoc("/HideToolbar true\n");
4264 craig 530
        if (Options.hideMenuBar)
4201 fschmid 531
                PutDoc("/HideMenubar true\n");
4264 craig 532
        if (Options.fitWindow)
4201 fschmid 533
                PutDoc("/FitWindow true\n");
3133 fschmid 534
        PutDoc(" >>\n>>\nendobj\n");
3829 cbradney 535
        QString IDg(Datum);
4264 craig 536
        IDg += Options.Datei;
3133 fschmid 537
        IDg += "Scribus "+QString(VERSION);
538
        IDg += "Libpdf for Scribus "+QString(VERSION);
4264 craig 539
        IDg += doc.documentInfo.getTitle();
540
        IDg += doc.documentInfo.getAuthor();
3133 fschmid 541
        IDg += "/False";
542
        FileID = ComputeMD5(IDg);
4264 craig 543
        if (Options.Encrypt)
3133 fschmid 544
        {
6166 fschmid 545
                if ((Options.Version == 14) || (Options.Version == 15))
546
                        KeyLen = 16;
547
                else
548
                        KeyLen = 5;
4264 craig 549
                CalcOwnerKey(Options.PassOwner, Options.PassUser);
550
                CalcUserKey(Options.PassUser, Options.Permissions);
3133 fschmid 551
                for (uint cl2 = 0; cl2 < 32; ++cl2)
552
                        ok += QChar(OwnerKey[cl2]);
553
                if (KeyLen > 5)
554
                {
555
                        for (uint cl3 = 0; cl3 < 16; ++cl3)
556
                                uk += QChar(UserKey[cl3]);
557
                        for (uint cl3r = 0; cl3r < 16; ++cl3r)
558
                                uk += QChar(KeyGen[cl3r]);
559
                }
560
                else
561
                {
562
                        for (uint cl = 0; cl < 32; ++cl)
563
                                uk += QChar(UserKey[cl]);
564
                }
565
        }
566
        QDate d = QDate::currentDate();
567
        Datum = "D:";
568
        tmp.sprintf("%4d", d.year());
569
        tmp.replace(QRegExp(" "), "0");
570
        Datum += tmp;
571
        tmp.sprintf("%2d", d.month());
572
        tmp.replace(QRegExp(" "), "0");
573
        Datum += tmp;
574
        tmp.sprintf("%2d", d.day());
575
        tmp.replace(QRegExp(" "), "0");
576
        Datum += tmp;
4229 craig 577
        tmp = QTime::currentTime().toString();
3133 fschmid 578
        tmp.replace(QRegExp(":"), "");
579
        Datum += tmp;
580
        StartObj(2);
581
        PutDoc("<<\n/Creator "+EncString("(Scribus "+QString(VERSION)+")",2)+"\n");
582
        PutDoc("/Producer "+EncString("(Libpdf for Scribus "+QString(VERSION)+")",2)+"\n");
4718 fschmid 583
        QString docTitle = doc.documentInfo.getTitle();
584
        if ((Options.Version == 12) && (docTitle.isEmpty()))
585
                PutDoc("/Title "+EncString("("+doc.DocName+")",2)+"\n");
586
        else
587
                PutDoc("/Title "+EncString("("+doc.documentInfo.getTitle()+")",2)+"\n");
4264 craig 588
        PutDoc("/Author "+EncString("("+doc.documentInfo.getAuthor()+")",2)+"\n");
589
        PutDoc("/Keywords "+EncString("("+doc.documentInfo.getKeywords()+")",2)+"\n");
3133 fschmid 590
        PutDoc("/CreationDate "+EncString("("+Datum+")",2)+"\n");
591
        PutDoc("/ModDate "+EncString("("+Datum+")",2)+"\n");
4264 craig 592
        if (Options.Version == 12)
3133 fschmid 593
                PutDoc("/GTS_PDFXVersion (PDF/X-3:2002)\n");
594
        PutDoc("/Trapped /False\n>>\nendobj\n");
4229 craig 595
        for (int t = 0; t < 6; ++t)
596
                XRef.append(bytesWritten());
4264 craig 597
        if ((Options.Version == 15) && (Options.useLayers))
4229 craig 598
                XRef.append(bytesWritten());
4264 craig 599
        if (Options.Version == 12)
4229 craig 600
                XRef.append(bytesWritten());
4264 craig 601
        if (Options.Encrypt)
3133 fschmid 602
        {
603
                StartObj(ObjCounter);
604
                Encrypt = ObjCounter;
605
                ObjCounter++;
606
                PutDoc("<<\n/Filter /Standard\n");
607
                PutDoc( KeyLen > 5 ? "/R 3\n/V 2\n/Length 128\n" : "/R 2\n/V 1\n");
608
                PutDoc("/O <"+String2Hex(&ok)+">\n");
609
                PutDoc("/U <"+String2Hex(&uk)+">\n");
4264 craig 610
                PutDoc("/P "+QString::number(Options.Permissions)+"\n>>\nendobj\n");
3133 fschmid 611
        }
5387 avox 612
        QMap<QString, QMap<uint, FPointArray> > ReallyUsed;
3133 fschmid 613
        ReallyUsed.clear();
614
        PageItem* pgit;
4017 fschmid 615
        QMap<int, QString> ind2PDFabr;
4546 subik 616
        const QString tmpf[] = {"/Courier", "/Courier-Bold", "/Courier-Oblique", "/Courier-BoldOblique",
4017 fschmid 617
                                                                                                "/Helvetica", "/Helvetica-Bold", "/Helvetica-Oblique", "/Helvetica-BoldOblique",
4546 subik 618
                                                                                                "/Times-Roman", "/Times-Bold", "/Times-Italic", "/Times-BoldItalic",
4017 fschmid 619
                                                                                                "/ZapfDingbats", "/Symbol"};
620
        size_t ar = sizeof(tmpf) / sizeof(*tmpf);
621
        for (uint ax = 0; ax < ar; ++ax)
622
                ind2PDFabr[ax] = tmpf[ax];
4264 craig 623
        for (uint c = 0; c < doc.FrameItems.count(); ++c)
3133 fschmid 624
        {
4264 craig 625
                pgit = doc.FrameItems.at(c);
3133 fschmid 626
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
627
                {
4084 cbradney 628
                        if (pgit->isAnnotation())
629
                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
5292 fschmid 630
                        for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
3133 fschmid 631
                        {
5980 avox 632
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().scName(), DocFonts[pgit->itemText.charStyle(e).font().scName()]);
3133 fschmid 633
                        }
634
                }
635
        }
4264 craig 636
        for (uint c = 0; c < doc.MasterItems.count(); ++c)
3133 fschmid 637
        {
4264 craig 638
                pgit = doc.MasterItems.at(c);
3133 fschmid 639
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
640
                {
4084 cbradney 641
                        if (pgit->isAnnotation())
642
                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
5292 fschmid 643
                        for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
3133 fschmid 644
                        {
5980 avox 645
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().scName(), DocFonts[pgit->itemText.charStyle(e).font().scName()]);
3133 fschmid 646
                        }
647
                }
648
        }
4264 craig 649
        for (uint d = 0; d < doc.Items->count(); ++d)
3133 fschmid 650
        {
4264 craig 651
                pgit = doc.Items->at(d);
3133 fschmid 652
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
653
                {
4084 cbradney 654
                        if (pgit->isAnnotation())
655
                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
5292 fschmid 656
                        for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
3133 fschmid 657
                        {
5980 avox 658
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().scName(), DocFonts[pgit->itemText.charStyle(e).font().scName()]);
3133 fschmid 659
                        }
660
                }
661
        }
4017 fschmid 662
        a = 0;
663
        QMap<QString, QString>::Iterator itStd;
664
        for (itStd = StdFonts.begin(); itStd != StdFonts.end(); ++itStd)
665
        {
666
                StartObj(ObjCounter);
667
                PutDoc("<<\n/Type /Font\n/Subtype /Type1\n");
668
                PutDoc("/BaseFont "+itStd.key()+"\n");
669
                PutDoc(">>\nendobj\n");
4229 craig 670
                Seite.FObjects["FoStd"+QString::number(a)] = ObjCounter;
671
                itStd.data() = "FoStd"+QString::number(a);
4017 fschmid 672
                ObjCounter++;
673
                a++;
674
        }
5387 avox 675
        QMap<QString,QMap<uint, FPointArray> >::Iterator it;
3133 fschmid 676
        a = 0;
677
        for (it = ReallyUsed.begin(); it != ReallyUsed.end(); ++it)
678
        {
5980 avox 679
                ScFace::FontFormat fformat = AllFonts[it.key()].format();
680
                if ((AllFonts[it.key()].isOTF()) || (!AllFonts[it.key()].hasNames()) || (AllFonts[it.key()].subset()) || (Options.SubsetList.contains(it.key())))
3133 fschmid 681
                {
3829 cbradney 682
                        QString fon("");
5387 avox 683
                        QMap<uint,FPointArray>& RealGlyphs(it.data());
3133 fschmid 684
                        QMap<uint,FPointArray>::Iterator ig;
5387 avox 685
                        for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
3133 fschmid 686
                        {
687
                                FPoint np, np1, np2;
688
                                bool nPath = true;
5606 fschmid 689
                                fon = "";
3133 fschmid 690
                                if (ig.data().size() > 3)
691
                                {
5387 avox 692
                                        FPointArray gly = ig.data();
3133 fschmid 693
                                        QWMatrix mat;
694
                                        mat.scale(0.1, 0.1);
695
                                        gly.map(mat);
696
                                        for (uint poi = 0; poi < gly.size()-3; poi += 4)
697
                                        {
698
                                                if (gly.point(poi).x() > 900000)
699
                                                {
700
                                                        fon += "h\n";
701
                                                        nPath = true;
702
                                                        continue;
703
                                                }
704
                                                if (nPath)
705
                                                {
706
                                                        np = gly.point(poi);
707
                                                        fon += FToStr(np.x())+" "+FToStr(-np.y())+" m\n";
708
                                                        nPath = false;
709
                                                }
710
                                                np = gly.point(poi+1);
711
                                                np1 = gly.point(poi+3);
712
                                                np2 = gly.point(poi+2);
713
                                                fon += FToStr(np.x()) + " " + FToStr(-np.y()) + " " +
714
                                                         FToStr(np1.x()) + " " + FToStr(-np1.y()) + " " +
715
                                                         FToStr(np2.x()) + " " + FToStr(-np2.y()) + " c\n";
716
                                        }
717
                                        fon += "h f*\n";
718
                                        np = getMinClipF(&gly);
719
                                        np1 = getMaxClipF(&gly);
720
                                }
5606 fschmid 721
                                else
722
                                {
723
                                        fon = "h";
724
                                        np = FPoint(0, 0);
725
                                        np1 = FPoint(0, 0);
726
                                }
727
                                StartObj(ObjCounter);
728
                                ObjCounter++;
729
                                PutDoc("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1\n");
730
                                PutDoc("/BBox [ "+FToStr(np.x())+" "+FToStr(-np.y())+" "+FToStr(np1.x())+ " "+FToStr(-np1.y())+" ]\n");
731
                                PutDoc("/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
732
                                PutDoc(">>\n");
733
                                if ((Options.Compress) && (CompAvail))
734
                                        fon = CompressStr(&fon);
735
                                PutDoc("/Length "+QString::number(fon.length()+1));
736
                                if ((Options.Compress) && (CompAvail))
737
                                        PutDoc("\n/Filter /FlateDecode");
738
                                PutDoc(" >>\nstream\n"+EncStream(fon, ObjCounter-1)+"\nendstream\nendobj\n");
5980 avox 739
                                Seite.XObjects[AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+QString::number(ig.key())] = ObjCounter-1;
3133 fschmid 740
                        }
741
                }
742
                else
743
                {
4229 craig 744
                        UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
5980 avox 745
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
3133 fschmid 746
                        {
3829 cbradney 747
                                QString fon("");
3133 fschmid 748
                                StartObj(ObjCounter);
749
                                QByteArray bb;
5980 avox 750
                                AllFonts[it.key()].RawData(bb);
3133 fschmid 751
                                uint posi;
752
                                for (posi = 6; posi < bb.size(); ++posi)
753
                                {
754
                                        if ((bb[posi] == static_cast<char>(0x80)) && (static_cast<int>(bb[posi+1]) == 2))
755
                                                break;
756
                                        fon += QChar(bb[posi]);
757
                                }
758
                                int len1 = fon.length();
759
                                uint ulen;
760
                                ulen = bb[posi+2] & 0xff;
761
                                ulen |= (bb[posi+3] << 8) & 0xff00;
762
                                ulen |= (bb[posi+4] << 16) & 0xff0000;
763
                                ulen |= (bb[posi+5] << 24) & 0xff000000;
764
                                if (ulen > bb.size())
765
                                        ulen = bb.size()-7;
766
                                posi += 6;
767
                                for (uint j = 0; j < ulen; ++j)
768
                                        fon += QChar(bb[posi++]);
769
                                posi += 6;
770
                                int len2 = fon.length()-len1;
771
                                for (uint j = posi; j < bb.size(); ++j)
772
                                {
773
                                        if ((bb[j] == static_cast<char>(0x80)) && (static_cast<int>(bb[j+1]) == 3))
774
                                                break;
775
                                        if (bb[j] == '\r')
776
                                                fon += "\n";
777
                                        else
778
                                                fon += QChar(bb[j]);
779
                                }
780
                                int len3 = fon.length()-len2-len1;
4264 craig 781
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 782
                                        fon = CompressStr(&fon);
4229 craig 783
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
784
                                PutDoc("/Length1 "+QString::number(len1)+"\n");
785
                                PutDoc("/Length2 "+QString::number(len2)+"\n");
786
                                PutDoc("/Length3 "+QString::number(len3)+"\n");
4264 craig 787
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 788
                                        PutDoc("/Filter /FlateDecode\n");
4229 craig 789
                                PutDoc(">>\nstream\n"+EncStream(fon,ObjCounter)+"\nendstream\nendobj\n");
3133 fschmid 790
                                ObjCounter++;
791
                        }
5980 avox 792
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
3133 fschmid 793
                        {
3829 cbradney 794
                                QString fon("");
795
                                QString fon2("");
796
                                QString tm("");
3133 fschmid 797
                                uint value;
798
                                bool ok = true;
799
                                StartObj(ObjCounter);
5980 avox 800
                                AllFonts[it.key()].EmbedFont(fon);
3133 fschmid 801
                                int len1 = fon.find("eexec")+5;
802
                                fon2 = fon.left(len1)+"\n";
803
                                int len2 = fon.find("0000000000000000000000000");
804
                                if (len2 == -1)
805
                                        len2 = fon.length()+1;
806
                                int count = 0;
807
                                for (int xx = len1; xx < len2-1; ++xx)
808
                                {
809
                                        tm = fon.at(xx);
810
                                        if ((tm == QChar(13)) || (tm == QChar(10)))
811
                                                continue;
812
                                        xx++;
813
                                        count++;
814
                                        tm += fon.at(xx);
815
                                        value = tm.toUInt(&ok, 16);
816
                                        fon2 += QChar(value);
817
                                }
818
                                fon2 += fon.mid(len2);
4264 craig 819
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 820
                                        fon2 = CompressStr(&fon2);
4229 craig 821
                                PutDoc("<<\n/Length "+QString::number(fon2.length()+1)+"\n");
822
                                PutDoc("/Length1 "+QString::number(len1+1)+"\n");
823
                                PutDoc("/Length2 "+QString::number(count)+"\n");
824
                                PutDoc(static_cast<int>(fon.length()-len2) == -1 ? QString("/Length3 0\n") : "/Length3 "+QString::number(fon.length()-len2)+"\n");
4264 craig 825
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 826
                                        PutDoc("/Filter /FlateDecode\n");
4229 craig 827
                                PutDoc(">>\nstream\n"+EncStream(fon2, ObjCounter)+"\nendstream\nendobj\n");
3133 fschmid 828
                                ObjCounter++;
829
                        }
5980 avox 830
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
3133 fschmid 831
                        {
3829 cbradney 832
                                QString fon("");
3133 fschmid 833
                                StartObj(ObjCounter);
834
                                QByteArray bb;
5980 avox 835
                                AllFonts[it.key()].RawData(bb);
3133 fschmid 836
                                //AV: += and append() dont't work because they stop at '\0' :-(
837
                                for (unsigned int i=0; i < bb.size(); i++)
838
                                        fon += QChar(bb[i]);
839
                                int len = fon.length();
4264 craig 840
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 841
                                        fon = CompressStr(&fon);
842
                                //qDebug(QString("sfnt data: size=%1 before=%2 compressed=%3").arg(bb.size()).arg(len).arg(fon.length()));
4229 craig 843
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
844
                                PutDoc("/Length1 "+QString::number(len)+"\n");
4264 craig 845
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 846
                                        PutDoc("/Filter /FlateDecode\n");
4229 craig 847
                                PutDoc(">>\nstream\n"+EncStream(fon, ObjCounter)+"\nendstream\nendobj\n");
3133 fschmid 848
                                ObjCounter++;
849
                        }
850
                        StartObj(ObjCounter);
5387 avox 851
                        // TODO: think about QByteArray ScFace::getFontDescriptor() -- AV
3133 fschmid 852
                        PutDoc("<<\n/Type /FontDescriptor\n");
5980 avox 853
                        PutDoc("/FontName /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
6213 fschmid 854
                        PutDoc("/FontBBox [ "+AllFonts[it.key()].FontBBoxAsString()+" ]\n");
3133 fschmid 855
                        PutDoc("/Flags ");
5980 avox 856
                        //FIXME: isItalic() should be queried from ScFace, not from Qt -- AV
3544 avox 857
                        //QFontInfo fo = QFontInfo(it.data());
3133 fschmid 858
                        int pfl = 0;
5980 avox 859
                        if (AllFonts[it.key()].isFixedPitch())
3133 fschmid 860
                                pfl = pfl ^ 1;
3544 avox 861
                        //if (fo.italic())
6213 fschmid 862
                        if (AllFonts[it.key()].ItalicAngleAsString() != "0")
3133 fschmid 863
                                pfl = pfl ^ 64;
864
//                      pfl = pfl ^ 4;
865
                        pfl = pfl ^ 32;
4229 craig 866
                        PutDoc(QString::number(pfl)+"\n");
6213 fschmid 867
                        PutDoc("/Ascent "+AllFonts[it.key()].ascentAsString()+"\n");
868
                        PutDoc("/Descent "+AllFonts[it.key()].descentAsString()+"\n");
869
                        PutDoc("/CapHeight "+AllFonts[it.key()].capHeightAsString()+"\n");
870
                        PutDoc("/ItalicAngle "+AllFonts[it.key()].ItalicAngleAsString()+"\n");
871
//                      PutDoc("/Ascent "+QString::number(static_cast<int>(AllFonts[it.key()].ascent()))+"\n");
872
//                      PutDoc("/Descent "+QString::number(static_cast<int>(AllFonts[it.key()].descent()))+"\n");
873
//                      PutDoc("/CapHeight "+QString::number(static_cast<int>(AllFonts[it.key()].capHeight()))+"\n");
874
//                      PutDoc("/ItalicAngle "+AllFonts[it.key()].italicAngle()+"\n");
875
//                      PutDoc("/StemV "+ AllFonts[it.key()].stemV() + "\n");
876
                        PutDoc("/StemV 1\n");
5980 avox 877
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
4229 craig 878
                                PutDoc("/FontFile2 "+QString::number(ObjCounter-1)+" 0 R\n");
5980 avox 879
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
4229 craig 880
                                PutDoc("/FontFile "+QString::number(ObjCounter-1)+" 0 R\n");
5980 avox 881
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
4229 craig 882
                                PutDoc("/FontFile "+QString::number(ObjCounter-1)+" 0 R\n");
3133 fschmid 883
                        PutDoc(">>\nendobj\n");
884
                        ObjCounter++;
4546 subik 885
/*                      if (!FT_Has_PS_Glyph_Names(AllFonts[it.key()])
3133 fschmid 886
                        {
887
                                StartObj(ObjCounter);
888
                                int chCount = 31;
889
                                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 ");
890
                                for (int ww = 31; ww < 256; ++ww)
891
                                {
4229 craig 892
                                        PutDoc(QString::number(static_cast<int>(AllFonts[it.key()]->CharWidth[itg.key()]*
3133 fschmid 893
                                                        1000))+" ");
894
                                        if (itg == gl.end())
895
                                                break;
896
                                        ++itg;
897
                                        chCount++;
898
                                }
899
                                PutDoc("]\nendobj\n");
900
                                ObjCounter++;
901
                                // put widths object
902
                                // encoding dictionary w/ base encoding w/o differences
903
                                StartObj(ObjCounter);
904
                                PutDoc("<<\n/Type /Font\n/Subtype ");
5980 avox 905
                                PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
4229 craig 906
                                PutDoc("/Name /Fo"+QString::number(a)+"\n");
5980 avox 907
                                PutDoc("/BaseFont /"+AllFonts[it.key()]->psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "" )+"\n");
3133 fschmid 908
                                //cf. widths:
909
                                PutDoc("/FirstChar 0\n");
4229 craig 910
                                PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
911
                                PutDoc("/Widths "+QString::number(ObjCounter-1)+" 0 R\n");
912
                                PutDoc("/FontDescriptor "+QString::number(ObjCounter-2)+" 0 R\n");
3133 fschmid 913
                                PutDoc(">>\nendobj\n");
4229 craig 914
                                Seite.FObjects["Fo"+QString::number(a)] = ObjCounter;
3133 fschmid 915
                                ObjCounter++;
916
                        }
917
                        else */
918
//                      {
6301 avox 919
                                QMap<uint,std::pair<QChar,QString> > gl;
920
                                AllFonts[it.key()].glyphNames(gl);
921
                                int nglyphs = 0;
922
                                QMap<uint,std::pair<QChar,QString> >::Iterator gli;
923
                                for (gli = gl.begin(); gli != gl.end(); ++gli) {
924
                                        if (gli.key() > nglyphs)
925
                                                nglyphs = gli.key();
926
                                }
927
                                ++nglyphs;
6302 avox 928
//                              qDebug(QString("pdflib: nglyphs %1 max %2").arg(nglyphs).arg(AllFonts[it.key()].maxGlyph()));
3133 fschmid 929
                                uint FontDes = ObjCounter - 1;
6301 avox 930
                                uint Fcc = nglyphs / 224;
931
                                if ((nglyphs % 224) != 0)
3133 fschmid 932
                                        Fcc += 1;
933
                                for (uint Fc = 0; Fc < Fcc; ++Fc)
934
                                {
935
                                        StartObj(ObjCounter);
6301 avox 936
                                        int chCount = 32;
937
                                        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 ");
938
                                        for (int ww = 32; ww < 256; ++ww)
3133 fschmid 939
                                        {
6301 avox 940
                                                uint glyph = 224 * Fc + ww - 32;
941
                                                if (gl.contains(glyph))
942
                                                        PutDoc(QString::number(static_cast<int>(AllFonts[it.key()].glyphWidth(glyph)* 1000))+" ");
943
                                                else
944
                                                        PutDoc("0 ");
945
 
6302 avox 946
                                                chCount++;
6301 avox 947
                                                if (signed(glyph) == nglyphs-1)
3133 fschmid 948
                                                        break;
949
                                        }
950
                                        PutDoc("]\nendobj\n");
951
                                        ObjCounter++;
952
                                        StartObj(ObjCounter);
953
                                        ObjCounter++;
954
                                        PutDoc("<< /Type /Encoding\n");
955
//                                      PutDoc("/BaseEncoding /" + AllFonts[it.key()]->FontEnc + "\n");
6301 avox 956
                                        PutDoc("/Differences [ \n");
3133 fschmid 957
                                        int crc = 0;
6301 avox 958
                                        bool startOfSeq = true;
3133 fschmid 959
                                        for (int ww2 = 32; ww2 < 256; ++ww2)
960
                                        {
6301 avox 961
                                                uint glyph = 224 * Fc + ww2 - 32;
962
                                                if (gl[glyph].second != "")
6213 fschmid 963
                                                {
6301 avox 964
                                                        if (startOfSeq) {
965
                                                                PutDoc(QString::number(ww2)+" ");
966
                                                                startOfSeq = false;
967
                                                        }
968
                                                        PutDoc("/"+gl[glyph].second+" ");
969
                                                        crc++;
6213 fschmid 970
                                                }
6301 avox 971
                                                else {
972
                                                        startOfSeq = true;
973
                                                }
974
                                                if (signed(glyph) == nglyphs-1)
3133 fschmid 975
                                                        break;
976
                                                if (crc > 8)
977
                                                {
978
                                                        PutDoc("\n");
979
                                                        crc = 0;
980
                                                }
981
                                        }
982
                                        PutDoc("]\n");
4546 subik 983
 
3133 fschmid 984
                                        PutDoc(">>\nendobj\n");
985
                                        StartObj(ObjCounter);
986
                                        PutDoc("<<\n/Type /Font\n/Subtype ");
5980 avox 987
                                        PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
4229 craig 988
                                        PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(Fc)+"\n");
5980 avox 989
                                        PutDoc("/BaseFont /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
3133 fschmid 990
                                        PutDoc("/FirstChar 0\n");
4229 craig 991
                                        PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
992
                                        PutDoc("/Widths "+QString::number(ObjCounter-2)+" 0 R\n");
993
                                        PutDoc("/Encoding "+QString::number(ObjCounter-1)+" 0 R\n");
994
                                        PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
3133 fschmid 995
                                        PutDoc(">>\nendobj\n");
4229 craig 996
                                        Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(Fc)] = ObjCounter;
3133 fschmid 997
                                        ObjCounter++;
998
                                } // for(Fc)
999
//                      } // FT_Has_PS_Glyph_Names
1000
                }
1001
                a++;
1002
        }
4264 craig 1003
        if (Options.UseLPI)
3133 fschmid 1004
        {
1005
                StartObj(ObjCounter);
1006
                PutDoc("<<\n/Type /Halftone\n/HalftoneType 5\n");
4264 craig 1007
                QMap<QString,LPIData>::const_iterator itlp;
1008
                for (itlp = Options.LPISettings.constBegin(); itlp != Options.LPISettings.constEnd(); ++itlp)
3133 fschmid 1009
                {
1010
                        PutDoc("/"+itlp.key()+"\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency ");
4229 craig 1011
                        PutDoc(QString::number(itlp.data().Frequency)+"\n/Angle "+QString::number(itlp.data().Angle)+"\n/SpotFunction ");
3829 cbradney 1012
                        QString func ("");
3133 fschmid 1013
                        switch (itlp.data().SpotFunc)
1014
                        {
1015
                                case 0:
1016
                                        func = "/SimpleDot";
1017
                                        break;
1018
                                case 1:
1019
                                        func = "/Line";
1020
                                        break;
1021
                                case 2:
1022
                                        func = "/Round";
1023
                                        break;
1024
                                case 3:
1025
                                        func = "/Ellipse";
1026
                                        break;
1027
                                default:
1028
                                        func = "/SimpleDot";
1029
                                        break;
1030
                        }
1031
                        PutDoc(func+"\n>>\n");
1032
                }
1033
                PutDoc("/Default\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency 50\n/Angle 45\n/SpotFunction /Round\n>>\n");
1034
                PutDoc(">>\nendobj\n");
1035
                ObjCounter++;
1036
                StartObj(ObjCounter);
4229 craig 1037
                HTName = ResNam+QString::number(ResCount);
3133 fschmid 1038
                Transpar[HTName] = ObjCounter;
4229 craig 1039
                PutDoc("<< /Type /ExtGState\n/HT "+QString::number(ObjCounter-1)+" 0 R\n>>\nendobj\n");
3133 fschmid 1040
                ResCount++;
1041
                ObjCounter++;
1042
        }
1043
#ifdef HAVE_CMS
5880 jghali 1044
        if ((doc.HasCMS) && (Options.UseProfiles))
3133 fschmid 1045
        {
1046
                StartObj(ObjCounter);
1047
                ObjCounter++;
1048
                QString dataP;
1049
                struct ICCD dataD;
5243 cbradney 1050
                loadText(ScCore->InputProfiles[Options.SolidProf], &dataP);
3133 fschmid 1051
                PutDoc("<<\n");
4264 craig 1052
                if ((Options.Compress) && (CompAvail))
3133 fschmid 1053
                {
1054
                        PutDoc("/Filter /FlateDecode\n");
1055
                        dataP = CompressStr(&dataP);
1056
                }
4229 craig 1057
                PutDoc("/Length "+QString::number(dataP.length()+1)+"\n");
4264 craig 1058
                PutDoc("/N "+QString::number(Options.SComp)+"\n");
4229 craig 1059
                PutDoc(">>\nstream\n"+EncStream(dataP, ObjCounter-1)+"\nendstream\nendobj\n");
3133 fschmid 1060
                StartObj(ObjCounter);
4229 craig 1061
                dataD.ResName = ResNam+QString::number(ResCount);
1062
                dataD.ICCArray = "[ /ICCBased "+QString::number(ObjCounter-1)+" 0 R ]";
3133 fschmid 1063
                dataD.ResNum = ObjCounter;
4264 craig 1064
                ICCProfiles[Options.SolidProf] = dataD;
4229 craig 1065
                PutDoc("[ /ICCBased "+QString::number(ObjCounter-1)+" 0 R ]\n");
3133 fschmid 1066
                PutDoc("endobj\n");
1067
                ResCount++;
1068
                ObjCounter++;
1069
        }
1070
#endif
4264 craig 1071
        if (((Options.isGrayscale == false) && (Options.UseRGB == false)) && (Options.UseSpotColors))
3133 fschmid 1072
        {
4264 craig 1073
                doc.getUsedColors(colorsToUse);
3133 fschmid 1074
                ColorList::Iterator itf;
1075
                for (itf = colorsToUse.begin(); itf != colorsToUse.end(); ++itf)
1076
                {
1077
                        if ((colorsToUse[itf.key()].isSpotColor()) || (colorsToUse[itf.key()].isRegistrationColor()))
1078
                        {
1079
                                int cc, cm, cy, ck;
1080
                                struct SpotC spotD;
1081
                                colorsToUse[itf.key()].getCMYK(&cc, &cm, &cy, &ck);
1082
                                QString colorDesc = "{\ndup "+FToStr(static_cast<double>(cc) / 255)+"\nmul exch dup ";
1083
                                colorDesc += FToStr(static_cast<double>(cm) / 255)+"\nmul exch dup ";
1084
                                colorDesc += FToStr(static_cast<double>(cy) / 255)+"\nmul exch ";
1085
                                colorDesc += FToStr(static_cast<double>(ck) / 255)+" mul }";
1086
                                StartObj(ObjCounter);
1087
                                ObjCounter++;
1088
                                PutDoc("<<\n/FunctionType 4\n");
1089
                                PutDoc("/Domain [0.0 1.0]\n");
1090
                                PutDoc("/Range [0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]\n");
4229 craig 1091
                                PutDoc("/Length "+QString::number(colorDesc.length()+1)+"\n");
1092
                                PutDoc(">>\nstream\n"+EncStream(colorDesc, ObjCounter-1)+"\nendstream\nendobj\n");
3133 fschmid 1093
                                StartObj(ObjCounter);
1094
                                PutDoc("[ /Separation /");
1095
                                if (colorsToUse[itf.key()].isRegistrationColor())
1096
                                        PutDoc("All");
1097
                                else
3440 fschmid 1098
                                        PutDoc(itf.key().simplifyWhiteSpace().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ).replace("#", "_"));
4229 craig 1099
                                PutDoc(" /DeviceCMYK "+QString::number(ObjCounter-1)+" 0 R ]\nendobj\n");
1100
                                spotD.ResName = spotNam+QString::number(spotCount);
3133 fschmid 1101
                                spotD.ResNum = ObjCounter;
1102
                                spotMap.insert(itf.key(), spotD);
1103
                                spotCount++;
1104
                                ObjCounter++;
1105
                        }
1106
                }
1107
        }
4264 craig 1108
        if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 1109
        {
1110
                struct Layer ll;
1111
                struct OCGInfo ocg;
1112
                ll.isPrintable = false;
1113
                ll.LNr = 0;
1114
                int Lnr = 0;
3829 cbradney 1115
                QString ocgNam("oc");
4264 craig 1116
                uint docLayersCount=doc.Layers.count();
3829 cbradney 1117
                for (uint la = 0; la < docLayersCount; ++la)
3133 fschmid 1118
                {
3829 cbradney 1119
                        QString tmp("");
4264 craig 1120
                        Level2Layer(&doc, &ll, Lnr);
3133 fschmid 1121
                        ocg.Name = ocgNam+tmp.setNum(ll.LNr);
1122
                        ocg.ObjNum = ObjCounter;
1123
                        ocg.visible = ll.isViewable;
1124
                        OCGEntries.insert(ll.Name, ocg);
1125
                        StartObj(ObjCounter);
1126
                        ObjCounter++;
1127
                        PutDoc("<<\n");
1128
                        PutDoc("/Type /OCG\n");
1129
                        PutDoc("/Name ("+ll.Name+")\n");
1130
                        PutDoc(">>\nendobj\n");
1131
                        Lnr++;
1132
                }
1133
        }
1134
        return true;
1135
}
1136
 
4241 craig 1137
void PDFlib::PDF_TemplatePage(const Page* pag, bool )
3133 fschmid 1138
{
1139
        QString tmp;
1140
        ActPageP = pag;
1141
        PageItem* ite;
1142
        QPtrList<PageItem> PItems;
1143
        int Lnr = 0;
1144
        struct Layer ll;
1145
        ll.isPrintable = false;
1146
        ll.LNr = 0;
1147
        Inhalt = "";
1148
        Seite.AObjects.clear();
4264 craig 1149
        for (uint la = 0; la < doc.Layers.count(); ++la)
3133 fschmid 1150
        {
4264 craig 1151
                Level2Layer(&doc, &ll, Lnr);
1152
                PItems = doc.MasterItems;
3133 fschmid 1153
                if (ll.isPrintable)
1154
                {
4264 craig 1155
                        if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 1156
                                PutPage("/OC /"+OCGEntries[ll.Name].Name+" BDC\n");
1157
                        for (uint a = 0; a < PItems.count(); ++a)
1158
                        {
1159
                                Inhalt = "";
1160
                                ite =PItems.at(a);
1161
                                if (ite->LayerNr != ll.LNr)
1162
                                        continue;
4726 fschmid 1163
                                double x = pag->xOffset();
1164
                                double y = pag->yOffset();
1165
                                double w = pag->width();
1166
                                double h1 = pag->height();
4580 cbradney 1167
                                double ilw=ite->lineWidth();
4726 fschmid 1168
                                double x2 = ite->BoundingX - ilw / 2.0;
1169
                                double y2 = ite->BoundingY - ilw / 2.0;
1170
                                double w2 = ite->BoundingW + ilw;
1171
                                double h2 = ite->BoundingH + ilw;
1172
                                if (!( QMAX( x, x2 ) <= QMIN( x+w, x2+w2 ) && QMAX( y, y2 ) <= QMIN( y+h1, y2+h2 )))
3133 fschmid 1173
                                        continue;
1174
                                if (ite->ChangedMasterItem)
1175
                                        continue;
5685 cbradney 1176
                                if ((!pag->pageName().isEmpty()) && (ite->OwnPage != static_cast<int>(pag->pageNr())) && (ite->OwnPage != -1))
3133 fschmid 1177
                                        continue;
1178
                                PutPage("q\n");
5320 fschmid 1179
                                if ((ite->doOverprint) && (!Options.doOverprint) && (!Options.UseRGB))
1180
                                {
1181
                                        StartObj(ObjCounter);
1182
                                        QString ShName = ResNam+QString::number(ResCount);
1183
                                        Transpar[ShName] = ObjCounter;
1184
                                        ResCount++;
1185
                                        ObjCounter++;
1186
                                        PutDoc("<< /Type /ExtGState\n");
1187
                                        PutDoc("/OP true\n");
1188
                                        PutDoc("/op true\n");
1189
                                        PutDoc("/OPM 1\n");
1190
                                        PutDoc(">>\nendobj\n");
1191
                                        PutPage("/"+ShName+" gs\n");
1192
                                }
4679 fschmid 1193
/* Bookmarks on Master Pages do not make any sense */
1194
//                              if ((ite->isBookmark) && (Options.Bookmarks))
1195
//                                      PDF_Bookmark(ite, pag->height() - (ite->yPos() - pag->yOffset()));
5685 cbradney 1196
                                if (!ite->printEnabled() || ((ite->itemType() == PageItem::TextFrame) && (!pag->pageName().isEmpty())))
3133 fschmid 1197
                                {
1198
                                        PutPage("Q\n");
1199
                                        continue;
1200
                                }
4546 subik 1201
                                if (ite->fillColor() != CommonStrings::None)
3133 fschmid 1202
                                        PutPage(putColor(ite->fillColor(), ite->fillShade(), true));
4546 subik 1203
                                if (ite->lineColor() != CommonStrings::None)
3133 fschmid 1204
                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), false));
4580 cbradney 1205
                                Inhalt += FToStr(fabs(ite->lineWidth()))+" w\n";
3133 fschmid 1206
                                if (ite->DashValues.count() != 0)
1207
                                {
1208
                                        PutPage("[ ");
1209
                                        QValueList<double>::iterator it;
1210
                                        for ( it = ite->DashValues.begin(); it != ite->DashValues.end(); ++it )
1211
                                        {
1212
                                                int da = static_cast<int>(*it);
1213
                                                if (da != 0)
4229 craig 1214
                                                        PutPage(QString::number(da)+" ");
3133 fschmid 1215
                                        }
4229 craig 1216
                                        PutPage("] "+QString::number(static_cast<int>(ite->DashOffset))+" d\n");
3133 fschmid 1217
                                }
1218
                                else
1219
                                {
4580 cbradney 1220
                                        QString Dt = FToStr(QMAX(2*fabs(ite->lineWidth()), 1));
1221
                                        QString Da = FToStr(QMAX(6*fabs(ite->lineWidth()), 1));
3133 fschmid 1222
                                        switch (ite->PLineArt)
1223
                                        {
1224
                                                case Qt::SolidLine:
1225
                                                        PutPage("[] 0 d\n");
1226
                                                        break;
1227
                                                case Qt::DashLine:
1228
                                                        PutPage("["+Da+" "+Dt+"] 0 d\n");
1229
                                                        break;
1230
                                                case Qt::DotLine:
1231
                                                        PutPage("["+Dt+"] 0 d\n");
1232
                                                        break;
1233
                                                case Qt::DashDotLine:
1234
                                                        PutPage("["+Da+" "+Dt+" "+Dt+" "+Dt+"] 0 d\n");
1235
                                                        break;
1236
                                                case Qt::DashDotDotLine:
1237
                                                        PutPage("["+Da+" "+Dt+" "+Dt+" "+Dt+" "+Dt+" "+Dt+"] 0 d\n");
1238
                                                        break;
1239
                                                default:
1240
                                                        PutPage("[] 0 d\n");
1241
                                                        break;
1242
                                        }
1243
                                }
1244
                                switch (ite->PLineEnd)
1245
                                {
1246
                                        case Qt::FlatCap:
1247
                                                PutPage("0 J\n");
1248
                                                break;
1249
                                        case Qt::SquareCap:
1250
                                                PutPage("2 J\n");
1251
                                                break;
1252
                                        case Qt::RoundCap:
1253
                                                PutPage("1 J\n");
1254
                                                break;
1255
                                        default:
1256
                                                PutPage("0 J\n");
1257
                                                break;
1258
                                }
1259
                                switch (ite->PLineJoin)
1260
                                {
1261
                                        case Qt::MiterJoin:
1262
                                                PutPage("0 j\n");
1263
                                                break;
1264
                                        case Qt::BevelJoin:
1265
                                                PutPage("2 j\n");
1266
                                                break;
1267
                                        case Qt::RoundJoin:
1268
                                                PutPage("1 j\n");
1269
                                                break;
1270
                                        default:
1271
                                                PutPage("0 j\n");
1272
                                                break;
1273
                                }
3903 cbradney 1274
                                PutPage("1 0 0 1 "+FToStr(ite->xPos() - pag->xOffset())+" "+FToStr(pag->height() - (ite->yPos()  - pag->yOffset()))+" cm\n");
3934 cbradney 1275
                                if (ite->rotation() != 0)
3133 fschmid 1276
                                {
3934 cbradney 1277
                                        double sr = sin(-ite->rotation()* M_PI / 180.0);
1278
                                        double cr = cos(-ite->rotation()* M_PI / 180.0);
3133 fschmid 1279
                                        if ((cr * cr) < 0.000001)
1280
                                                cr = 0;
1281
                                        if ((sr * sr) < 0.000001)
1282
                                                sr = 0;
1283
                                        PutPage(FToStr(cr)+" "+FToStr(sr)+" "+FToStr(-sr)+" "+FToStr(cr)+" 0 0 cm\n");
1284
                                }
1285
                                switch (ite->itemType())
1286
                                {
1287
                                        case PageItem::ImageFrame:
5748 fschmid 1288
                                                if (((ite->fillTransparency() != 0) || (ite->fillBlendmode() != 0)) && (Options.Version >= 14))
1289
                                                        PutPage(PDF_TransparenzFill(ite));
4546 subik 1290
                                                if ((ite->fillColor() != CommonStrings::None) || (ite->GrType != 0))
3133 fschmid 1291
                                                {
1292
                                                        if (ite->GrType != 0)
1293
                                                                PutPage(PDF_Gradient(ite));
1294
                                                        else
1295
                                                        {
1296
                                                                PutPage(SetClipPath(ite));
1297
                                                                PutPage("h\nf*\n");
1298
                                                        }
1299
                                                }
1300
                                                PutPage("q\n");
1301
                                                if (ite->imageClip.size() != 0)
4744 fschmid 1302
                                                {
3133 fschmid 1303
                                                        PutPage(SetClipPathImage(ite));
4744 fschmid 1304
                                                        PutPage("h\nW*\nn\n");
1305
                                                }
1306
                                                PutPage(SetClipPath(ite));
3133 fschmid 1307
                                                PutPage("h\nW*\nn\n");
1308
                                                if (ite->imageFlippedH())
3934 cbradney 1309
                                                        PutPage("-1 0 0 1 "+FToStr(ite->width())+" 0 cm\n");
3133 fschmid 1310
                                                if (ite->imageFlippedV())
3934 cbradney 1311
                                                        PutPage("1 0 0 -1 0 "+FToStr(-ite->height())+" cm\n");
3133 fschmid 1312
                                                if ((ite->PicAvail) && (!ite->Pfile.isEmpty()))
3985 cbradney 1313
                                                        PutPage(PDF_Image(ite, ite->Pfile, ite->imageXScale(), ite->imageYScale(), ite->imageXOffset(), -ite->imageYOffset(), false, ite->IProfile, ite->UseEmbedded, ite->IRender));
3133 fschmid 1314
                                                PutPage("Q\n");
4546 subik 1315
                                                if (((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty())) && (!ite->isTableItem))
3133 fschmid 1316
                                                {
5748 fschmid 1317
                                                        if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1318
                                                                PutPage(PDF_TransparenzStroke(ite));
4580 cbradney 1319
                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1320
                                                        {
1321
                                                                PutPage(SetClipPath(ite));
1322
                                                                PutPage("h\nS\n");
1323
                                                        }
1324
                                                        else
1325
                                                        {
4264 craig 1326
                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1327
                                                                for (int it = ml.size()-1; it > -1; it--)
1328
                                                                {
1329
                                                                        PutPage(setStrokeMulti(&ml[it]));
1330
                                                                        PutPage(SetClipPath(ite));
1331
                                                                        PutPage("h\nS\n");
1332
                                                                }
1333
                                                        }
1334
                                                }
1335
                                                break;
1336
                                        case PageItem::TextFrame:
1337
                                                break;
1338
                                        case PageItem::Line:
5748 fschmid 1339
                                                if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1340
                                                        PutPage(PDF_TransparenzStroke(ite));
3133 fschmid 1341
                                                if (ite->NamedLStyle.isEmpty())
1342
                                                {
1343
                                                        PutPage("0 0 m\n");
3934 cbradney 1344
                                                        PutPage(FToStr(ite->width())+" 0 l\n");
3133 fschmid 1345
                                                        PutPage("S\n");
1346
                                                }
1347
                                                else
1348
                                                {
4264 craig 1349
                                                        multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1350
                                                        for (int it = ml.size()-1; it > -1; it--)
1351
                                                        {
1352
                                                                PutPage(setStrokeMulti(&ml[it]));
1353
                                                                PutPage("0 0 m\n");
3934 cbradney 1354
                                                                PutPage(FToStr(ite->width())+" 0 l\n");
3133 fschmid 1355
                                                                PutPage("S\n");
1356
                                                        }
1357
                                                }
4061 craig 1358
                                                if (ite->startArrowIndex() != 0)
3133 fschmid 1359
                                                {
1360
                                                        QWMatrix arrowTrans;
4264 craig 1361
                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->startArrowIndex()-1)).points.copy();
3133 fschmid 1362
                                                        arrowTrans.translate(0, 0);
4580 cbradney 1363
                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1364
                                                        arrowTrans.scale(-1,1);
1365
                                                        arrow.map(arrowTrans);
4264 craig 1366
                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1367
                                                        {
1368
                                                                StartObj(ObjCounter);
4229 craig 1369
                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1370
                                                                Transpar[ShName] = ObjCounter;
1371
                                                                ResCount++;
1372
                                                                ObjCounter++;
1373
                                                                PutDoc("<< /Type /ExtGState\n");
1374
                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1375
                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1376
                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1377
                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1378
                                                                PutPage("/"+ShName+" gs\n");
1379
                                                        }
4016 fschmid 1380
                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1381
                                                        PutPage(SetClipPathArray(&arrow));
1382
                                                        PutPage("h\nf*\n");
1383
                                                }
4061 craig 1384
                                                if (ite->endArrowIndex() != 0)
3133 fschmid 1385
                                                {
1386
                                                        QWMatrix arrowTrans;
4264 craig 1387
                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->endArrowIndex()-1)).points.copy();
3934 cbradney 1388
                                                        arrowTrans.translate(ite->width(), 0);
4580 cbradney 1389
                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1390
                                                        arrow.map(arrowTrans);
4264 craig 1391
                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1392
                                                        {
1393
                                                                StartObj(ObjCounter);
4229 craig 1394
                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1395
                                                                Transpar[ShName] = ObjCounter;
1396
                                                                ResCount++;
1397
                                                                ObjCounter++;
1398
                                                                PutDoc("<< /Type /ExtGState\n");
1399
                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1400
                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1401
                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1402
                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1403
                                                                PutPage("/"+ShName+" gs\n");
1404
                                                        }
4016 fschmid 1405
                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1406
                                                        PutPage(SetClipPathArray(&arrow));
1407
                                                        PutPage("h\nf*\n");
1408
                                                }
1409
                                                break;
3232 cbradney 1410
                                        case PageItem::ItemType1:
1411
                                        case PageItem::ItemType3:
3133 fschmid 1412
                                        case PageItem::Polygon:
5748 fschmid 1413
                                                if (((ite->fillTransparency() != 0) || (ite->fillBlendmode() != 0)) && (Options.Version >= 14))
1414
                                                        PutPage(PDF_TransparenzFill(ite));
3133 fschmid 1415
                                                if (ite->GrType != 0)
1416
                                                        PutPage(PDF_Gradient(ite));
1417
                                                else
1418
                                                {
4546 subik 1419
                                                        if (ite->fillColor() != CommonStrings::None)
3133 fschmid 1420
                                                        {
1421
                                                                PutPage(SetClipPath(ite));
1422
                                                                PutPage("h\nf*\n");
1423
                                                        }
1424
                                                }
4546 subik 1425
                                                if ((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()))
3133 fschmid 1426
                                                {
5748 fschmid 1427
                                                        if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1428
                                                                PutPage(PDF_TransparenzStroke(ite));
4580 cbradney 1429
                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1430
                                                        {
1431
                                                                PutPage(SetClipPath(ite));
1432
                                                                PutPage("h\nS\n");
1433
                                                        }
1434
                                                        else
1435
                                                        {
4264 craig 1436
                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1437
                                                                for (int it = ml.size()-1; it > -1; it--)
1438
                                                                {
1439
                                                                        PutPage(setStrokeMulti(&ml[it]));
1440
                                                                        PutPage(SetClipPath(ite));
1441
                                                                        PutPage("h\nS\n");
1442
                                                                }
1443
                                                        }
1444
                                                }
1445
                                                break;
1446
                                        case PageItem::PolyLine:
4658 fschmid 1447
                                                if (ite->PoLine.size() > 4) // && ((ite->PoLine.point(0) != ite->PoLine.point(1)) || (ite->PoLine.point(2) != ite->PoLine.point(3))))
3133 fschmid 1448
                                                {
5748 fschmid 1449
                                                        if (((ite->fillTransparency() != 0) || (ite->fillBlendmode() != 0)) && (Options.Version >= 14))
1450
                                                                PutPage(PDF_TransparenzFill(ite));
3133 fschmid 1451
                                                        if (ite->GrType != 0)
1452
                                                                PutPage(PDF_Gradient(ite));
1453
                                                        else
1454
                                                        {
4546 subik 1455
                                                                if (ite->fillColor() != CommonStrings::None)
3133 fschmid 1456
                                                                {
1457
                                                                        PutPage(SetClipPath(ite));
1458
                                                                        PutPage("h\nf*\n");
1459
                                                                }
1460
                                                        }
1461
                                                }
4546 subik 1462
                                                if ((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()))
3133 fschmid 1463
                                                {
5748 fschmid 1464
                                                        if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1465
                                                                PutPage(PDF_TransparenzStroke(ite));
4580 cbradney 1466
                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1467
                                                        {
1468
                                                                PutPage(SetClipPath(ite, false));
1469
                                                                PutPage("S\n");
1470
                                                        }
1471
                                                        else
1472
                                                        {
4264 craig 1473
                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1474
                                                                for (int it = ml.size()-1; it > -1; it--)
1475
                                                                {
1476
                                                                        PutPage(setStrokeMulti(&ml[it]));
1477
                                                                        PutPage(SetClipPath(ite, false));
1478
                                                                        PutPage("S\n");
1479
                                                                }
1480
                                                        }
1481
                                                }
4061 craig 1482
                                                if (ite->startArrowIndex() != 0)
3133 fschmid 1483
                                                {
1484
                                                        FPoint Start = ite->PoLine.point(0);
1485
                                                        for (uint xx = 1; xx < ite->PoLine.size(); xx += 2)
1486
                                                        {
1487
                                                                FPoint Vector = ite->PoLine.point(xx);
1488
                                                                if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
1489
                                                                {
1490
                                                                        double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI);
1491
                                                                        QWMatrix arrowTrans;
4264 craig 1492
                                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->startArrowIndex()-1)).points.copy();
3133 fschmid 1493
                                                                        arrowTrans.translate(Start.x(), Start.y());
1494
                                                                        arrowTrans.rotate(r);
4580 cbradney 1495
                                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1496
                                                                        arrow.map(arrowTrans);
4264 craig 1497
                                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1498
                                                                        {
1499
                                                                                StartObj(ObjCounter);
4229 craig 1500
                                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1501
                                                                                Transpar[ShName] = ObjCounter;
1502
                                                                                ResCount++;
1503
                                                                                ObjCounter++;
1504
                                                                                PutDoc("<< /Type /ExtGState\n");
1505
                                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1506
                                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1507
                                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1508
                                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1509
                                                                                PutPage("/"+ShName+" gs\n");
1510
                                                                        }
4016 fschmid 1511
                                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1512
                                                                        PutPage(SetClipPathArray(&arrow));
1513
                                                                        PutPage("h\nf*\n");
1514
                                                                        break;
1515
                                                                }
1516
                                                        }
1517
                                                }
4061 craig 1518
                                                if (ite->endArrowIndex() != 0)
3133 fschmid 1519
                                                {
1520
                                                        FPoint End = ite->PoLine.point(ite->PoLine.size()-2);
1521
                                                        for (uint xx = ite->PoLine.size()-1; xx > 0; xx -= 2)
1522
                                                        {
1523
                                                                FPoint Vector = ite->PoLine.point(xx);
1524
                                                                if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
1525
                                                                {
1526
                                                                        double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI);
1527
                                                                        QWMatrix arrowTrans;
4264 craig 1528
                                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->endArrowIndex()-1)).points.copy();
3133 fschmid 1529
                                                                        arrowTrans.translate(End.x(), End.y());
1530
                                                                        arrowTrans.rotate(r);
4580 cbradney 1531
                                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1532
                                                                        arrow.map(arrowTrans);
4264 craig 1533
                                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1534
                                                                        {
1535
                                                                                StartObj(ObjCounter);
4229 craig 1536
                                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1537
                                                                                Transpar[ShName] = ObjCounter;
1538
                                                                                ResCount++;
1539
                                                                                ObjCounter++;
1540
                                                                                PutDoc("<< /Type /ExtGState\n");
1541
                                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1542
                                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1543
                                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1544
                                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1545
                                                                                PutPage("/"+ShName+" gs\n");
1546
                                                                        }
4016 fschmid 1547
                                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1548
                                                                        PutPage(SetClipPathArray(&arrow));
1549
                                                                        PutPage("h\nf*\n");
1550
                                                                        break;
1551
                                                                }
1552
                                                        }
1553
                                                }
1554
                                                break;
1555
                                        case PageItem::PathText:
1556
                                                if (ite->PoShow)
1557
                                                {
1558
                                                        if (ite->PoLine.size() > 3)
1559
                                                        {
1560
                                                                PutPage("q\n");
4546 subik 1561
                                                                if ((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()))
3133 fschmid 1562
                                                                {
5748 fschmid 1563
                                                                        if (((ite->lineTransparency() != 0) || (ite->lineBlendmode() != 0)) && (Options.Version >= 14))
1564
                                                                                PutPage(PDF_TransparenzStroke(ite));
4580 cbradney 1565
                                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1566
                                                                        {
1567
                                                                                PutPage(SetClipPath(ite, false));
1568
                                                                                PutPage("S\n");
1569
                                                                        }
1570
                                                                        else
1571
                                                                        {
4264 craig 1572
                                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
4546 subik 1573
                                                                                for (int it = ml.size()-1;
3133 fschmid 1574
                                                                                        it > -1; it--)
1575
                                                                                        {
1576
                                                                                        PutPage(setStrokeMulti(&ml[it]));
1577
                                                                                        PutPage(SetClipPath(ite, false));
1578
                                                                                        PutPage("S\n");
1579
                                                                                        }
1580
                                                                        }
1581
                                                                }
1582
                                                                PutPage("Q\n");
1583
                                                        }
1584
                                                }
5748 fschmid 1585
                                                if (((ite->fillTransparency() != 0) || (ite->fillBlendmode() != 0)) && (Options.Version >= 14))
1586
                                                        PutPage(PDF_TransparenzFill(ite));
3200 cbradney 1587
                                                PutPage(setTextSt(ite, pag->pageNr(), pag));
3133 fschmid 1588
                                                break;
1589
                                        }
1590
                                PutPage("Q\n");
1591
                                StartObj(ObjCounter);
1592
                                ObjCounter++;
1593
                                PutDoc("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1\n");
3200 cbradney 1594
                                PutDoc("/BBox [ 0 0 "+FToStr(ActPageP->width())+" "+FToStr(ActPageP->height())+" ]\n");
3133 fschmid 1595
                                PutDoc("/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
1596
                                if (Seite.ImgObjects.count() != 0)
1597
                                {
1598
                                        PutDoc("/XObject <<\n");
1599
                                        QMap<QString,int>::Iterator it;
1600
                                        for (it = Seite.ImgObjects.begin(); it != Seite.ImgObjects.end(); ++it)
4229 craig 1601
                                                PutDoc("/"+it.key()+" "+QString::number(it.data())+" 0 R\n");
3133 fschmid 1602
                                        PutDoc(">>\n");
1603
                                }
1604
                                if (Seite.FObjects.count() != 0)
1605
                                {
1606
                                        PutDoc("/Font << \n");
1607
                                        QMap<QString,int>::Iterator it2;
1608
                                        for (it2 = Seite.FObjects.begin(); it2 != Seite.FObjects.end(); ++it2)
4229 craig 1609
                                                PutDoc("/"+it2.key()+" "+QString::number(it2.data())+" 0 R\n");
3133 fschmid 1610
                                        PutDoc(">>\n");
1611
                                }
1612
                                if (Shadings.count() != 0)
1613
                                {
1614
                                        PutDoc("/Shading << \n");
1615
                                        QMap<QString,int>::Iterator it3;
1616
                                        for (it3 = Shadings.begin(); it3 != Shadings.end(); ++it3)
4229 craig 1617
                                                PutDoc("/"+it3.key()+" "+QString::number(it3.data())+" 0 R\n");
3133 fschmid 1618
                                        PutDoc(">>\n");
1619
                                }
6378 fschmid 1620
                                if (Patterns.count() != 0)
1621
                                {
1622
                                        PutDoc("/Pattern << \n");
1623
                                        QMap<QString,int>::Iterator it3p;
1624
                                        for (it3p = Patterns.begin(); it3p != Patterns.end(); ++it3p)
1625
                                                PutDoc("/"+it3p.key()+" "+QString::number(it3p.data())+" 0 R\n");
1626
                                        PutDoc(">>\n");
1627
                                }
3133 fschmid 1628
                                if (Transpar.count() != 0)
1629
                                {
1630
                                        PutDoc("/ExtGState << \n");
1631
                                        QMap<QString,int>::Iterator it3t;
1632
                                        for (it3t = Transpar.begin(); it3t != Transpar.end(); ++it3t)
4229 craig 1633
                                                PutDoc("/"+it3t.key()+" "+QString::number(it3t.data())+" 0 R\n");
3133 fschmid 1634
                                        PutDoc(">>\n");
1635
                                }
1636
                                if ((ICCProfiles.count() != 0) || (spotMap.count() != 0))
1637
                                {
1638
                                        PutDoc("/ColorSpace << \n");
1639
                                        QMap<QString,ICCD>::Iterator it3c;
1640
                                        if (ICCProfiles.count() != 0)
1641
                                        {
1642
                                                for (it3c = ICCProfiles.begin(); it3c != ICCProfiles.end(); ++it3c)
4229 craig 1643
                                                        PutDoc("/"+it3c.data().ResName+" "+QString::number(it3c.data().ResNum)+" 0 R\n");
3133 fschmid 1644
                                        }
1645
                                        QMap<QString,SpotC>::Iterator it3sc;
1646
                                        if (spotMap.count() != 0)
1647
                                        {
1648
                                        for (it3sc = spotMap.begin(); it3sc != spotMap.end(); ++it3sc)
4229 craig 1649
                                                PutDoc("/"+it3sc.data().ResName+" "+QString::number(it3sc.data().ResNum)+" 0 R\n");
3133 fschmid 1650
                                        }
1651
                                        PutDoc(">>\n");
1652
                                }
1653
                                PutDoc(">>\n");
4264 craig 1654
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 1655
                                        Inhalt = CompressStr(&Inhalt);
4229 craig 1656
                                PutDoc("/Length "+QString::number(Inhalt.length()+1));
4264 craig 1657
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 1658
                                        PutDoc("\n/Filter /FlateDecode");
4229 craig 1659
                                PutDoc(" >>\nstream\n"+EncStream(Inhalt, ObjCounter-1)+"\nendstream\nendobj\n");
5685 cbradney 1660
                                QString name = pag->pageName().simplifyWhiteSpace().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ) + QString::number(ite->ItemNr);
3133 fschmid 1661
                                Seite.XObjects[name] = ObjCounter-1;
1662
                                }
4264 craig 1663
                                if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 1664
                                        PutPage("EMC\n");
1665
                        }
1666
                Lnr++;
1667
        }
1668
}
1669
 
4241 craig 1670
void PDFlib::PDF_Begin_Page(const Page* pag, QPixmap pm)
3133 fschmid 1671
{
1672
        QString tmp;
1673
        ActPageP = pag;
1674
        Inhalt = "";
1675
        Seite.AObjects.clear();
4264 craig 1676
        if (Options.Thumbnails)
3133 fschmid 1677
        {
5593 avox 1678
                ScImage img(pm.convertToImage());
5234 fschmid 1679
                QByteArray array = img.ImageToArray();
4264 craig 1680
                if ((Options.Compress) && (CompAvail))
5234 fschmid 1681
                        array = CompressArray(&array);
3133 fschmid 1682
                StartObj(ObjCounter);
4229 craig 1683
                PutDoc("<<\n/Width "+QString::number(img.width())+"\n");
1684
                PutDoc("/Height "+QString::number(img.height())+"\n");
3133 fschmid 1685
                PutDoc("/ColorSpace /DeviceRGB\n/BitsPerComponent 8\n");
5234 fschmid 1686
 
1687
                PutDoc("/Length "+QString::number(array.size()+1)+"\n");
4264 craig 1688
                if ((Options.Compress) && (CompAvail))
3133 fschmid 1689
                        PutDoc("/Filter /FlateDecode\n");
5234 fschmid 1690
                PutDoc(">>\nstream\n");
1691
                PutDoc(EncStreamArray(array, ObjCounter));
1692
                PutDoc("\nendstream\nendobj\n");
3133 fschmid 1693
                Seite.Thumb = ObjCounter;
1694
                ObjCounter++;
1695
        }
1696
}
1697
 
1698
void PDFlib::PDF_End_Page()
1699
{
3200 cbradney 1700
        uint PgNr =  ActPageP->pageNr();
3133 fschmid 1701
        Seite.ObjNum = ObjCounter;
4084 cbradney 1702
        WritePDFStream(Inhalt);
5604 fschmid 1703
        int Gobj;
6378 fschmid 1704
        if (Options.Version >= 14) //  && (Transpar.count() != 0))
5604 fschmid 1705
        {
1706
                StartObj(ObjCounter);
1707
                Gobj = ObjCounter;
1708
                ObjCounter++;
1709
                PutDoc("<< /S /Transparency\n");
1710
                if (Options.UseRGB)
1711
                        PutDoc("/CS /DeviceRGB\n");
1712
                else
1713
                {
1714
                        if (Options.isGrayscale)
1715
                                PutDoc("/CS /DeviceGray\n");
1716
                        else
1717
#ifdef HAVE_CMS
1718
                        {
5880 jghali 1719
                                if ((doc.HasCMS) && (Options.UseProfiles))
5604 fschmid 1720
                                        PutDoc("/CS "+ICCProfiles[Options.SolidProf].ICCArray+"\n");
1721
                                else
1722
#endif
1723
                                        PutDoc("/CS /DeviceCMYK\n");
1724
#ifdef HAVE_CMS
1725
                        }
1726
#endif
1727
                }
1728
                PutDoc(">>\nendobj\n");
1729
    &