Subversion Repositories Scribus

Rev

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