Subversion Repositories Scribus

Rev

Rev 4582 | Rev 4658 | 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));
4264 craig 1110
                                if ((ite->isBookmark) && (Options.Bookmarks))
3903 cbradney 1111
                                        PDF_Bookmark(ite->BMnr, pag->height() - (ite->yPos() - pag->yOffset()));
3133 fschmid 1112
                                if (!ite->printable() || ((ite->itemType() == PageItem::TextFrame) && (!pag->PageNam.isEmpty())))
1113
                                {
1114
                                        PutPage("Q\n");
1115
                                        continue;
1116
                                }
4546 subik 1117
                                if (ite->fillColor() != CommonStrings::None)
3133 fschmid 1118
                                        PutPage(putColor(ite->fillColor(), ite->fillShade(), true));
4546 subik 1119
                                if (ite->lineColor() != CommonStrings::None)
3133 fschmid 1120
                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), false));
4580 cbradney 1121
                                Inhalt += FToStr(fabs(ite->lineWidth()))+" w\n";
3133 fschmid 1122
                                if (ite->DashValues.count() != 0)
1123
                                {
1124
                                        PutPage("[ ");
1125
                                        QValueList<double>::iterator it;
1126
                                        for ( it = ite->DashValues.begin(); it != ite->DashValues.end(); ++it )
1127
                                        {
1128
                                                int da = static_cast<int>(*it);
1129
                                                if (da != 0)
4229 craig 1130
                                                        PutPage(QString::number(da)+" ");
3133 fschmid 1131
                                        }
4229 craig 1132
                                        PutPage("] "+QString::number(static_cast<int>(ite->DashOffset))+" d\n");
3133 fschmid 1133
                                }
1134
                                else
1135
                                {
4580 cbradney 1136
                                        QString Dt = FToStr(QMAX(2*fabs(ite->lineWidth()), 1));
1137
                                        QString Da = FToStr(QMAX(6*fabs(ite->lineWidth()), 1));
3133 fschmid 1138
                                        switch (ite->PLineArt)
1139
                                        {
1140
                                                case Qt::SolidLine:
1141
                                                        PutPage("[] 0 d\n");
1142
                                                        break;
1143
                                                case Qt::DashLine:
1144
                                                        PutPage("["+Da+" "+Dt+"] 0 d\n");
1145
                                                        break;
1146
                                                case Qt::DotLine:
1147
                                                        PutPage("["+Dt+"] 0 d\n");
1148
                                                        break;
1149
                                                case Qt::DashDotLine:
1150
                                                        PutPage("["+Da+" "+Dt+" "+Dt+" "+Dt+"] 0 d\n");
1151
                                                        break;
1152
                                                case Qt::DashDotDotLine:
1153
                                                        PutPage("["+Da+" "+Dt+" "+Dt+" "+Dt+" "+Dt+" "+Dt+"] 0 d\n");
1154
                                                        break;
1155
                                                default:
1156
                                                        PutPage("[] 0 d\n");
1157
                                                        break;
1158
                                        }
1159
                                }
1160
                                switch (ite->PLineEnd)
1161
                                {
1162
                                        case Qt::FlatCap:
1163
                                                PutPage("0 J\n");
1164
                                                break;
1165
                                        case Qt::SquareCap:
1166
                                                PutPage("2 J\n");
1167
                                                break;
1168
                                        case Qt::RoundCap:
1169
                                                PutPage("1 J\n");
1170
                                                break;
1171
                                        default:
1172
                                                PutPage("0 J\n");
1173
                                                break;
1174
                                }
1175
                                switch (ite->PLineJoin)
1176
                                {
1177
                                        case Qt::MiterJoin:
1178
                                                PutPage("0 j\n");
1179
                                                break;
1180
                                        case Qt::BevelJoin:
1181
                                                PutPage("2 j\n");
1182
                                                break;
1183
                                        case Qt::RoundJoin:
1184
                                                PutPage("1 j\n");
1185
                                                break;
1186
                                        default:
1187
                                                PutPage("0 j\n");
1188
                                                break;
1189
                                }
3903 cbradney 1190
                                PutPage("1 0 0 1 "+FToStr(ite->xPos() - pag->xOffset())+" "+FToStr(pag->height() - (ite->yPos()  - pag->yOffset()))+" cm\n");
3934 cbradney 1191
                                if (ite->rotation() != 0)
3133 fschmid 1192
                                {
3934 cbradney 1193
                                        double sr = sin(-ite->rotation()* M_PI / 180.0);
1194
                                        double cr = cos(-ite->rotation()* M_PI / 180.0);
3133 fschmid 1195
                                        if ((cr * cr) < 0.000001)
1196
                                                cr = 0;
1197
                                        if ((sr * sr) < 0.000001)
1198
                                                sr = 0;
1199
                                        PutPage(FToStr(cr)+" "+FToStr(sr)+" "+FToStr(-sr)+" "+FToStr(cr)+" 0 0 cm\n");
1200
                                }
1201
                                switch (ite->itemType())
1202
                                {
1203
                                        case PageItem::ImageFrame:
4546 subik 1204
                                                if ((ite->fillColor() != CommonStrings::None) || (ite->GrType != 0))
3133 fschmid 1205
                                                {
1206
                                                        if (ite->GrType != 0)
1207
                                                                PutPage(PDF_Gradient(ite));
1208
                                                        else
1209
                                                        {
1210
                                                                PutPage(SetClipPath(ite));
1211
                                                                PutPage("h\nf*\n");
1212
                                                        }
1213
                                                }
1214
                                                PutPage("q\n");
1215
                                                if (ite->imageClip.size() != 0)
1216
                                                        PutPage(SetClipPathImage(ite));
1217
                                                else
1218
                                                        PutPage(SetClipPath(ite));
1219
                                                PutPage("h\nW*\nn\n");
1220
                                                if (ite->imageFlippedH())
3934 cbradney 1221
                                                        PutPage("-1 0 0 1 "+FToStr(ite->width())+" 0 cm\n");
3133 fschmid 1222
                                                if (ite->imageFlippedV())
3934 cbradney 1223
                                                        PutPage("1 0 0 -1 0 "+FToStr(-ite->height())+" cm\n");
3133 fschmid 1224
                                                if ((ite->PicAvail) && (!ite->Pfile.isEmpty()))
3985 cbradney 1225
                                                        PutPage(PDF_Image(ite, ite->Pfile, ite->imageXScale(), ite->imageYScale(), ite->imageXOffset(), -ite->imageYOffset(), false, ite->IProfile, ite->UseEmbedded, ite->IRender));
3133 fschmid 1226
                                                PutPage("Q\n");
4546 subik 1227
                                                if (((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty())) && (!ite->isTableItem))
3133 fschmid 1228
                                                {
4580 cbradney 1229
                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1230
                                                        {
1231
                                                                PutPage(SetClipPath(ite));
1232
                                                                PutPage("h\nS\n");
1233
                                                        }
1234
                                                        else
1235
                                                        {
4264 craig 1236
                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1237
                                                                for (int it = ml.size()-1; it > -1; it--)
1238
                                                                {
1239
                                                                        PutPage(setStrokeMulti(&ml[it]));
1240
                                                                        PutPage(SetClipPath(ite));
1241
                                                                        PutPage("h\nS\n");
1242
                                                                }
1243
                                                        }
1244
                                                }
1245
                                                break;
1246
                                        case PageItem::TextFrame:
1247
                                                break;
1248
                                        case PageItem::Line:
1249
                                                if (ite->NamedLStyle.isEmpty())
1250
                                                {
1251
                                                        PutPage("0 0 m\n");
3934 cbradney 1252
                                                        PutPage(FToStr(ite->width())+" 0 l\n");
3133 fschmid 1253
                                                        PutPage("S\n");
1254
                                                }
1255
                                                else
1256
                                                {
4264 craig 1257
                                                        multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1258
                                                        for (int it = ml.size()-1; it > -1; it--)
1259
                                                        {
1260
                                                                PutPage(setStrokeMulti(&ml[it]));
1261
                                                                PutPage("0 0 m\n");
3934 cbradney 1262
                                                                PutPage(FToStr(ite->width())+" 0 l\n");
3133 fschmid 1263
                                                                PutPage("S\n");
1264
                                                        }
1265
                                                }
4061 craig 1266
                                                if (ite->startArrowIndex() != 0)
3133 fschmid 1267
                                                {
1268
                                                        QWMatrix arrowTrans;
4264 craig 1269
                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->startArrowIndex()-1)).points.copy();
3133 fschmid 1270
                                                        arrowTrans.translate(0, 0);
4580 cbradney 1271
                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1272
                                                        arrowTrans.scale(-1,1);
1273
                                                        arrow.map(arrowTrans);
4264 craig 1274
                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1275
                                                        {
1276
                                                                StartObj(ObjCounter);
4229 craig 1277
                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1278
                                                                Transpar[ShName] = ObjCounter;
1279
                                                                ResCount++;
1280
                                                                ObjCounter++;
1281
                                                                PutDoc("<< /Type /ExtGState\n");
1282
                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1283
                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1284
                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1285
                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1286
                                                                PutPage("/"+ShName+" gs\n");
1287
                                                        }
4016 fschmid 1288
                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1289
                                                        PutPage(SetClipPathArray(&arrow));
1290
                                                        PutPage("h\nf*\n");
1291
                                                }
4061 craig 1292
                                                if (ite->endArrowIndex() != 0)
3133 fschmid 1293
                                                {
1294
                                                        QWMatrix arrowTrans;
4264 craig 1295
                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->endArrowIndex()-1)).points.copy();
3934 cbradney 1296
                                                        arrowTrans.translate(ite->width(), 0);
4580 cbradney 1297
                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1298
                                                        arrow.map(arrowTrans);
4264 craig 1299
                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1300
                                                        {
1301
                                                                StartObj(ObjCounter);
4229 craig 1302
                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1303
                                                                Transpar[ShName] = ObjCounter;
1304
                                                                ResCount++;
1305
                                                                ObjCounter++;
1306
                                                                PutDoc("<< /Type /ExtGState\n");
1307
                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1308
                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1309
                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1310
                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1311
                                                                PutPage("/"+ShName+" gs\n");
1312
                                                        }
4016 fschmid 1313
                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1314
                                                        PutPage(SetClipPathArray(&arrow));
1315
                                                        PutPage("h\nf*\n");
1316
                                                }
1317
                                                break;
3232 cbradney 1318
                                        case PageItem::ItemType1:
1319
                                        case PageItem::ItemType3:
3133 fschmid 1320
                                        case PageItem::Polygon:
1321
                                                if (ite->GrType != 0)
1322
                                                        PutPage(PDF_Gradient(ite));
1323
                                                else
1324
                                                {
4546 subik 1325
                                                        if (ite->fillColor() != CommonStrings::None)
3133 fschmid 1326
                                                        {
1327
                                                                PutPage(SetClipPath(ite));
1328
                                                                PutPage("h\nf*\n");
1329
                                                        }
1330
                                                }
4546 subik 1331
                                                if ((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()))
3133 fschmid 1332
                                                {
4580 cbradney 1333
                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1334
                                                        {
1335
                                                                PutPage(SetClipPath(ite));
1336
                                                                PutPage("h\nS\n");
1337
                                                        }
1338
                                                        else
1339
                                                        {
4264 craig 1340
                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1341
                                                                for (int it = ml.size()-1; it > -1; it--)
1342
                                                                {
1343
                                                                        PutPage(setStrokeMulti(&ml[it]));
1344
                                                                        PutPage(SetClipPath(ite));
1345
                                                                        PutPage("h\nS\n");
1346
                                                                }
1347
                                                        }
1348
                                                }
1349
                                                break;
1350
                                        case PageItem::PolyLine:
1351
                                                if ((ite->PoLine.size() > 3) && ((ite->PoLine.point(0) != ite->PoLine.point(1)) || (ite->PoLine.point(2) != ite->PoLine.point(3))))
1352
                                                {
1353
                                                        if (ite->GrType != 0)
1354
                                                                PutPage(PDF_Gradient(ite));
1355
                                                        else
1356
                                                        {
4546 subik 1357
                                                                if (ite->fillColor() != CommonStrings::None)
3133 fschmid 1358
                                                                {
1359
                                                                        PutPage(SetClipPath(ite));
1360
                                                                        PutPage("h\nf*\n");
1361
                                                                }
1362
                                                        }
1363
                                                }
4546 subik 1364
                                                if ((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()))
3133 fschmid 1365
                                                {
4580 cbradney 1366
                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1367
                                                        {
1368
                                                                PutPage(SetClipPath(ite, false));
1369
                                                                PutPage("S\n");
1370
                                                        }
1371
                                                        else
1372
                                                        {
4264 craig 1373
                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
3133 fschmid 1374
                                                                for (int it = ml.size()-1; it > -1; it--)
1375
                                                                {
1376
                                                                        PutPage(setStrokeMulti(&ml[it]));
1377
                                                                        PutPage(SetClipPath(ite, false));
1378
                                                                        PutPage("S\n");
1379
                                                                }
1380
                                                        }
1381
                                                }
4061 craig 1382
                                                if (ite->startArrowIndex() != 0)
3133 fschmid 1383
                                                {
1384
                                                        FPoint Start = ite->PoLine.point(0);
1385
                                                        for (uint xx = 1; xx < ite->PoLine.size(); xx += 2)
1386
                                                        {
1387
                                                                FPoint Vector = ite->PoLine.point(xx);
1388
                                                                if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
1389
                                                                {
1390
                                                                        double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI);
1391
                                                                        QWMatrix arrowTrans;
4264 craig 1392
                                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->startArrowIndex()-1)).points.copy();
3133 fschmid 1393
                                                                        arrowTrans.translate(Start.x(), Start.y());
1394
                                                                        arrowTrans.rotate(r);
4580 cbradney 1395
                                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1396
                                                                        arrow.map(arrowTrans);
4264 craig 1397
                                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1398
                                                                        {
1399
                                                                                StartObj(ObjCounter);
4229 craig 1400
                                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1401
                                                                                Transpar[ShName] = ObjCounter;
1402
                                                                                ResCount++;
1403
                                                                                ObjCounter++;
1404
                                                                                PutDoc("<< /Type /ExtGState\n");
1405
                                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1406
                                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1407
                                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1408
                                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1409
                                                                                PutPage("/"+ShName+" gs\n");
1410
                                                                        }
4016 fschmid 1411
                                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1412
                                                                        PutPage(SetClipPathArray(&arrow));
1413
                                                                        PutPage("h\nf*\n");
1414
                                                                        break;
1415
                                                                }
1416
                                                        }
1417
                                                }
4061 craig 1418
                                                if (ite->endArrowIndex() != 0)
3133 fschmid 1419
                                                {
1420
                                                        FPoint End = ite->PoLine.point(ite->PoLine.size()-2);
1421
                                                        for (uint xx = ite->PoLine.size()-1; xx > 0; xx -= 2)
1422
                                                        {
1423
                                                                FPoint Vector = ite->PoLine.point(xx);
1424
                                                                if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
1425
                                                                {
1426
                                                                        double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI);
1427
                                                                        QWMatrix arrowTrans;
4264 craig 1428
                                                                        FPointArray arrow = (*doc.arrowStyles.at(ite->endArrowIndex()-1)).points.copy();
3133 fschmid 1429
                                                                        arrowTrans.translate(End.x(), End.y());
1430
                                                                        arrowTrans.rotate(r);
4580 cbradney 1431
                                                                        arrowTrans.scale(ite->lineWidth(), ite->lineWidth());
3133 fschmid 1432
                                                                        arrow.map(arrowTrans);
4264 craig 1433
                                                                        if ((ite->lineTransparency() != 0) && (Options.Version >= 14))
3133 fschmid 1434
                                                                        {
1435
                                                                                StartObj(ObjCounter);
4229 craig 1436
                                                                                QString ShName = ResNam+QString::number(ResCount);
3133 fschmid 1437
                                                                                Transpar[ShName] = ObjCounter;
1438
                                                                                ResCount++;
1439
                                                                                ObjCounter++;
1440
                                                                                PutDoc("<< /Type /ExtGState\n");
1441
                                                                                PutDoc("/CA "+FToStr(1.0 - ite->lineTransparency())+"\n");
1442
                                                                                PutDoc("/ca "+FToStr(1.0 - ite->lineTransparency())+"\n");
1443
                                                                                PutDoc("/SMask /None\n/AIS false\n/OPM 1\n");
1444
                                                                                PutDoc("/BM /Normal\n>>\nendobj\n");
1445
                                                                                PutPage("/"+ShName+" gs\n");
1446
                                                                        }
4016 fschmid 1447
                                                                        PutPage(putColor(ite->lineColor(), ite->lineShade(), true));
3133 fschmid 1448
                                                                        PutPage(SetClipPathArray(&arrow));
1449
                                                                        PutPage("h\nf*\n");
1450
                                                                        break;
1451
                                                                }
1452
                                                        }
1453
                                                }
1454
                                                break;
1455
                                        case PageItem::PathText:
1456
                                                if (ite->PoShow)
1457
                                                {
1458
                                                        if (ite->PoLine.size() > 3)
1459
                                                        {
1460
                                                                PutPage("q\n");
4546 subik 1461
                                                                if ((ite->lineColor() != CommonStrings::None) || (!ite->NamedLStyle.isEmpty()))
3133 fschmid 1462
                                                                {
4580 cbradney 1463
                                                                        if ((ite->NamedLStyle.isEmpty()) && (ite->lineWidth() != 0.0))
3133 fschmid 1464
                                                                        {
1465
                                                                                PutPage(SetClipPath(ite, false));
1466
                                                                                PutPage("S\n");
1467
                                                                        }
1468
                                                                        else
1469
                                                                        {
4264 craig 1470
                                                                                multiLine ml = doc.MLineStyles[ite->NamedLStyle];
4546 subik 1471
                                                                                for (int it = ml.size()-1;
3133 fschmid 1472
                                                                                        it > -1; it--)
1473
                                                                                        {
1474
                                                                                        PutPage(setStrokeMulti(&ml[it]));
1475
                                                                                        PutPage(SetClipPath(ite, false));
1476
                                                                                        PutPage("S\n");
1477
                                                                                        }
1478
                                                                        }
1479
                                                                }
1480
                                                                PutPage("Q\n");
1481
                                                        }
1482
                                                }
3200 cbradney 1483
                                                PutPage(setTextSt(ite, pag->pageNr(), pag));
3133 fschmid 1484
                                                break;
1485
                                        }
1486
                                PutPage("Q\n");
1487
                                StartObj(ObjCounter);
1488
                                ObjCounter++;
1489
                                PutDoc("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1\n");
3200 cbradney 1490
                                PutDoc("/BBox [ 0 0 "+FToStr(ActPageP->width())+" "+FToStr(ActPageP->height())+" ]\n");
3133 fschmid 1491
                                PutDoc("/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
1492
                                if (Seite.ImgObjects.count() != 0)
1493
                                {
1494
                                        PutDoc("/XObject <<\n");
1495
                                        QMap<QString,int>::Iterator it;
1496
                                        for (it = Seite.ImgObjects.begin(); it != Seite.ImgObjects.end(); ++it)
4229 craig 1497
                                                PutDoc("/"+it.key()+" "+QString::number(it.data())+" 0 R\n");
3133 fschmid 1498
                                        PutDoc(">>\n");
1499
                                }
1500
                                if (Seite.FObjects.count() != 0)
1501
                                {
1502
                                        PutDoc("/Font << \n");
1503
                                        QMap<QString,int>::Iterator it2;
1504
                                        for (it2 = Seite.FObjects.begin(); it2 != Seite.FObjects.end(); ++it2)
4229 craig 1505
                                                PutDoc("/"+it2.key()+" "+QString::number(it2.data())+" 0 R\n");
3133 fschmid 1506
                                        PutDoc(">>\n");
1507
                                }
1508
                                if (Shadings.count() != 0)
1509
                                {
1510
                                        PutDoc("/Shading << \n");
1511
                                        QMap<QString,int>::Iterator it3;
1512
                                        for (it3 = Shadings.begin(); it3 != Shadings.end(); ++it3)
4229 craig 1513
                                                PutDoc("/"+it3.key()+" "+QString::number(it3.data())+" 0 R\n");
3133 fschmid 1514
                                        PutDoc(">>\n");
1515
                                }
1516
                                if (Transpar.count() != 0)
1517
                                {
1518
                                        PutDoc("/ExtGState << \n");
1519
                                        QMap<QString,int>::Iterator it3t;
1520
                                        for (it3t = Transpar.begin(); it3t != Transpar.end(); ++it3t)
4229 craig 1521
                                                PutDoc("/"+it3t.key()+" "+QString::number(it3t.data())+" 0 R\n");
3133 fschmid 1522
                                        PutDoc(">>\n");
1523
                                }
1524
                                if ((ICCProfiles.count() != 0) || (spotMap.count() != 0))
1525
                                {
1526
                                        PutDoc("/ColorSpace << \n");
1527
                                        QMap<QString,ICCD>::Iterator it3c;
1528
                                        if (ICCProfiles.count() != 0)
1529
                                        {
1530
                                                for (it3c = ICCProfiles.begin(); it3c != ICCProfiles.end(); ++it3c)
4229 craig 1531
                                                        PutDoc("/"+it3c.data().ResName+" "+QString::number(it3c.data().ResNum)+" 0 R\n");
3133 fschmid 1532
                                        }
1533
                                        QMap<QString,SpotC>::Iterator it3sc;
1534
                                        if (spotMap.count() != 0)
1535
                                        {
1536
                                        for (it3sc = spotMap.begin(); it3sc != spotMap.end(); ++it3sc)
4229 craig 1537
                                                PutDoc("/"+it3sc.data().ResName+" "+QString::number(it3sc.data().ResNum)+" 0 R\n");
3133 fschmid 1538
                                        }
1539
                                        PutDoc(">>\n");
1540
                                }
1541
                                PutDoc(">>\n");
4264 craig 1542
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 1543
                                        Inhalt = CompressStr(&Inhalt);
4229 craig 1544
                                PutDoc("/Length "+QString::number(Inhalt.length()+1));
4264 craig 1545
                                if ((Options.Compress) && (CompAvail))
3133 fschmid 1546
                                        PutDoc("\n/Filter /FlateDecode");
4229 craig 1547
                                PutDoc(" >>\nstream\n"+EncStream(Inhalt, ObjCounter-1)+"\nendstream\nendobj\n");
1548
                                QString name = pag->PageNam.simplifyWhiteSpace().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ) + QString::number(ite->ItemNr);
3133 fschmid 1549
                                Seite.XObjects[name] = ObjCounter-1;
1550
                                }
4264 craig 1551
                                if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 1552
                                        PutPage("EMC\n");
1553
                        }
1554
                Lnr++;
1555
        }
1556
}
1557
 
4241 craig 1558
void PDFlib::PDF_Begin_Page(const Page* pag, QPixmap pm)
3133 fschmid 1559
{
1560
        QString tmp;
1561
        ActPageP = pag;
1562
        Inhalt = "";
1563
        Seite.AObjects.clear();
4264 craig 1564
        if (Options.Thumbnails)
3133 fschmid 1565
        {
1566
                ScImage img = pm.convertToImage();
1567
                QString im = img.ImageToTxt();
4264 craig 1568
                if ((Options.Compress) && (CompAvail))
3133 fschmid 1569
                        im = CompressStr(&im);
1570
                StartObj(ObjCounter);
4229 craig 1571
                PutDoc("<<\n/Width "+QString::number(img.width())+"\n");
1572
                PutDoc("/Height "+QString::number(img.height())+"\n");
3133 fschmid 1573
                PutDoc("/ColorSpace /DeviceRGB\n/BitsPerComponent 8\n");
4229 craig 1574
                PutDoc("/Length "+QString::number(im.length()+1)+"\n");
4264 craig 1575
                if ((Options.Compress) && (CompAvail))
3133 fschmid 1576
                        PutDoc("/Filter /FlateDecode\n");
4229 craig 1577
                PutDoc(">>\nstream\n"+EncStream(im, ObjCounter)+"\nendstream\nendobj\n");
3133 fschmid 1578
                Seite.Thumb = ObjCounter;
1579
                ObjCounter++;
1580
        }
1581
}
1582
 
1583
void PDFlib::PDF_End_Page()
1584
{
3200 cbradney 1585
        uint PgNr =  ActPageP->pageNr();
3133 fschmid 1586
        Seite.ObjNum = ObjCounter;
4084 cbradney 1587
        WritePDFStream(Inhalt);
3133 fschmid 1588
        StartObj(ObjCounter);
1589
        PutDoc("<<\n/Type /Page\n/Parent 4 0 R\n");
3200 cbradney 1590
        PutDoc("/MediaBox [0 0 "+FToStr(ActPageP->width())+" "+FToStr(ActPageP->height())+"]\n");
4264 craig 1591
        PutDoc("/TrimBox ["+FToStr(Options.BleedLeft)+" "+FToStr(Options.BleedBottom)+
1592
                " "+FToStr(ActPageP->width()-Options.BleedRight)+" "+FToStr(ActPageP->height()-Options.BleedTop)+"]\n");
1593
        PutDoc("/Rotate "+QString::number(Options.RotateDeg)+"\n");
4229 craig 1594
        PutDoc("/Contents "+QString::number(Seite.ObjNum)+" 0 R\n");
4264 craig 1595
        if (Options.Thumbnails)
4229 craig 1596
                PutDoc("/Thumb "+QString::number(Seite.Thumb)+" 0 R\n");
3133 fschmid 1597
        if (Seite.AObjects.count() != 0)
1598
        {
1599
                PutDoc("/Annots [ ");
1600
                for (uint b = 0; b < Seite.AObjects.count(); ++b)
4229 craig 1601
                        PutDoc(QString::number(Seite.AObjects[b])+" 0 R ");
3133 fschmid 1602
                PutDoc("]\n");
1603
        }
4264 craig 1604
        if (Options.PresentMode)
3133 fschmid 1605
        {
4264 craig 1606
                PutDoc("/Dur "+QString::number(Options.PresentVals[PgNr].pageViewDuration)+"\n");
1607
                if (Options.PresentVals[PgNr].effectType != 0)
3133 fschmid 1608
                {
1609
                        PutDoc("/Trans << /Type /Trans\n");
4264 craig 1610
                        PutDoc("/D "+QString::number(Options.PresentVals[PgNr].pageEffectDuration)+"\n");
1611
                        switch (Options.PresentVals[PgNr].effectType)
3133 fschmid 1612
                        {
1613
                                case 1:
1614
                                        PutDoc("/S /Blinds\n");
4264 craig 1615
                                        PutDoc(Options.PresentVals[PgNr].Dm == 0 ? "/Dm /H\n" : "/Dm /V\n");
3133 fschmid 1616
                                        break;
1617
                                case 2:
1618
                                        PutDoc("/S /Box\n");
4264 craig 1619
                                        PutDoc(Options.PresentVals[PgNr].M == 0 ? "/M /I\n" : "/M /O\n");
3133 fschmid 1620
                                        break;
1621
                                case 3:
1622
                                        PutDoc("/S /Dissolve\n");
1623
                                        break;
1624
                                case 4:
1625
                                        PutDoc("/S /Glitter\n");
1626
                                        PutDoc("/Di ");
4264 craig 1627
                                        switch (Options.PresentVals[PgNr].Di)
3133 fschmid 1628
                                        {
1629
                                                case 0:
1630
                                                        PutDoc("0");
1631
                                                        break;
1632
                                                case 1:
1633
                                                        PutDoc("270");
1634
                                                        break;
1635
                                                case 4:
1636
                                                        PutDoc("315");
1637
                                                        break;
1638
                                                default:
1639
                                                        PutDoc("0");
1640
                                                        break;
1641
                                        }
1642
                                        PutDoc("\n");
1643
                                        break;
1644
                                case 5:
1645
                                        PutDoc("/S /Split\n");
4264 craig 1646
                                        PutDoc(Options.PresentVals[PgNr].Dm == 0 ? "/Dm /H\n" : "/Dm /V\n");
1647
                                        PutDoc(Options.PresentVals[PgNr].M == 0 ? "/M /I\n" : "/M /O\n");
3133 fschmid 1648
                                        break;
1649
                                case 6:
1650
                                        PutDoc("/S /Wipe\n");
1651
                                        PutDoc("/Di ");
4264 craig 1652
                                        switch (Options.PresentVals[PgNr].Di)
3133 fschmid 1653
                                        {
1654
                                                case 0:
1655
                                                        PutDoc("0");
1656
                                                        break;
1657
                                                case 1:
1658
                                                        PutDoc("270");
1659
                                                        break;
1660
                                                case 2:
1661
                                                        PutDoc("90");
1662
                                                        break;
1663
                                                case 3:
1664
                                                        PutDoc("180");
1665
                                                        break;
1666
                                                default:
1667
                                                        PutDoc("0");
1668
                                                        break;
1669
                                        }
1670
                                        PutDoc("\n");
1671
                                        break;
1672
                        }
1673
                        PutDoc(">>\n");
1674
                }
1675
        }
1676
        PutDoc(">>\nendobj\n");
1677
        PageTree.Count++;
1678
        PageTree.Kids.append(ObjCounter);
1679
        ObjCounter++;
1680
}
1681
 
4241 craig 1682
void PDFlib::PDF_ProcessPage(const Page* pag, uint PNr, bool clip)
3133 fschmid 1683
{
1684
        QString tmp;
1685
        ActPageP = pag;
1686
        PageItem* ite;
1687
        QPtrList<PageItem> PItems;
1688
        int Lnr = 0;
1689
        struct Layer ll;
1690
        ll.isPrintable = false;
1691
        ll.LNr = 0;
4264 craig 1692
        if (Options.UseLPI)
3133 fschmid 1693
                PutPage("/"+HTName+" gs\n");
4264 craig 1694
        if ( (Options.MirrorH) && (!pag->MPageNam.isEmpty()) )
3200 cbradney 1695
                PutPage("-1 0 0 1 "+FToStr(ActPageP->width())+" 0 cm\n");
4264 craig 1696
        if ( (Options.MirrorV) && (!pag->MPageNam.isEmpty()) )
3200 cbradney 1697
                PutPage("1 0 0 -1 0 "+FToStr(ActPageP->height())+" cm\n");
3133 fschmid 1698
        if (clip)
1699
        {
1700
                PutPage(FToStr(pag->Margins.Left) + " " + FToStr(pag->Margins.Bottom) + " m\n");
3200 cbradney 1701
                PutPage(FToStr(ActPageP->width() - pag->Margins.Right) + " " + FToStr(pag->Margins.Bottom) + " l\n");
1702
                PutPage(FToStr(ActPageP->width() - pag->Margins.Right) + " " + FToStr(ActPageP->height() - pag->Margins.Top) + " l\n");
1703
                PutPage(FToStr(pag->Margins.Left) + " " + FToStr(ActPageP->height() - pag->Margins.Top) + " l h W n\n");
3133 fschmid 1704
        }
1705
        else
3200 cbradney 1706
                PutPage("0 0 "+FToStr(ActPageP->width())+" "+FToStr(ActPageP->height())+" re W n\n");
4546 subik 1707
 
3133 fschmid 1708
        if (!pag->MPageNam.isEmpty())
1709
        {
4264 craig 1710
                Page* mPage = doc.MasterPages.at(doc.MasterNames[doc.Pages->at(PNr)->MPageNam]);
1711
                if (doc.MasterItems.count() != 0)
3133 fschmid 1712
                {
4264 craig 1713
                        if (!Options.MirrorH)
3133 fschmid 1714
                                PutPage("1 0 0 1 0 0 cm\n");
4264 craig 1715
                        for (uint lam = 0; lam < doc.Layers.count(); ++lam)
3133 fschmid 1716
                        {
4264 craig 1717
                                Level2Layer(&doc, &ll, Lnr);
3133 fschmid 1718
                                Lnr++;
1719
                                if (ll.isPrintable)
1720
                                {
4264 craig 1721
                                        if ((Options.Version == 15) && (Options.useLayers))
3133 fschmid 1722
                                                PutPage("/OC /"+OCGEntries[ll.Name