Subversion Repositories Scribus

Rev

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