Subversion Repositories Scribus

Rev

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