Subversion Repositories Scribus

Rev

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