Subversion Repositories Scribus

Rev

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

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