Subversion Repositories Scribus

Rev

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