Subversion Repositories Scribus

Rev

Rev 16577 | Rev 16629 | 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
        {
16577 craig 521
                tmpFile  = QDir::toNativeSeparators(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
        {
16336 jghali 1081
                ScFace& face(AllFonts[it.key()]);
1082
                ScFace::FontFormat fformat = face.format();
1083
                if ((!face.hasNames()) || (Options.SubsetList.contains(it.key())))
3133 fschmid 1084
                {
16336 jghali 1085
                        if (face.hasNames())
3133 fschmid 1086
                        {
8469 fschmid 1087
                                UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
1088
                                uint SubFonts = 0;
8559 subik 1089
                                int glyphCount = 0;
15071 fschmid 1090
                                double minx = 999999.9;
1091
                                double miny = 999999.9;
1092
                                double maxx = -999999.9;
1093
                                double maxy = -999999.9;
9803 fschmid 1094
                                QList<uint> glyphWidths;
8469 fschmid 1095
                                QStringList charProcs;
1096
                                QString encoding = "<< /Type /Encoding\n/Differences [ 0\n";
1097
                                QString fon("");
1098
                                QMap<uint, uint> glyphMapping;
1099
                                QMap<uint,std::pair<QChar,QString> > gl;
16336 jghali 1100
                                face.glyphNames(gl);
10469 cbradney 1101
                                QMap<uint,FPointArray>& RealGlyphs(it.value());
8469 fschmid 1102
                                QMap<uint,FPointArray>::Iterator ig;
1103
                                for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
3133 fschmid 1104
                                {
8469 fschmid 1105
                                        FPoint np, np1, np2;
1106
                                        bool nPath = true;
1107
                                        fon = "";
10469 cbradney 1108
                                        if (ig.value().size() > 3)
3133 fschmid 1109
                                        {
10469 cbradney 1110
                                                FPointArray gly = ig.value();
13951 fschmid 1111
                                                QTransform mat;
8469 fschmid 1112
                                                mat.scale(100.0, -100.0);
1113
                                                gly.map(mat);
1114
                                                gly.translate(0, 1000);
1115
                                                for (uint poi = 0; poi < gly.size()-3; poi += 4)
3133 fschmid 1116
                                                {
8469 fschmid 1117
                                                        if (gly.point(poi).x() > 900000)
1118
                                                        {
1119
                                                                fon += "h\n";
1120
                                                                nPath = true;
1121
                                                                continue;
1122
                                                        }
1123
                                                        if (nPath)
1124
                                                        {
1125
                                                                np = gly.point(poi);
1126
                                                                fon += FToStr(np.x())+" "+FToStr(np.y())+" m\n";
1127
                                                                nPath = false;
1128
                                                        }
1129
                                                        np = gly.point(poi+1);
1130
                                                        np1 = gly.point(poi+3);
1131
                                                        np2 = gly.point(poi+2);
1132
                                                        fon += FToStr(np.x()) + " " + FToStr(np.y()) + " " + FToStr(np1.x()) + " " + FToStr(np1.y()) + " " + FToStr(np2.x()) + " " + FToStr(np2.y()) + " c\n";
3133 fschmid 1133
                                                }
8469 fschmid 1134
                                                fon += "h f*\n";
1135
                                                np = getMinClipF(&gly);
1136
                                                np1 = getMaxClipF(&gly);
1137
                                        }
1138
                                        else
1139
                                        {
1140
                                                fon = "h";
1141
                                                np = FPoint(0, 0);
1142
                                                np1 = FPoint(0, 0);
1143
                                        }
1144
                                        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 1145
                                        minx = qMin(minx, np.x());
1146
                                        miny = qMin(miny, np.y());
1147
                                        maxx = qMax(maxx, np1.x());
1148
                                        maxy = qMax(maxy, np1.y());
8469 fschmid 1149
                                        glyphWidths.append(qRound(np1.x()));
12080 avox 1150
                                        uint charProcObject = newObject();
1151
                                        charProcs.append("/"+gl[ig.key()].second+" "+QString::number(charProcObject)+" 0 R\n");
8469 fschmid 1152
                                        encoding += "/"+gl[ig.key()].second+" ";
1153
                                        glyphMapping.insert(ig.key(), glyphCount + SubFonts * 256);
12080 avox 1154
                                        StartObj(charProcObject);
11317 jghali 1155
                                        if (Options.Compress)
8469 fschmid 1156
                                                fon = CompressStr(&fon);
1157
                                        PutDoc("<< /Length "+QString::number(fon.length()+1));
11317 jghali 1158
                                        if (Options.Compress)
8469 fschmid 1159
                                                PutDoc("\n/Filter /FlateDecode");
12080 avox 1160
                                        PutDoc("\n>>\nstream\n"+EncStream(fon, charProcObject)+"\nendstream\nendobj\n");
8469 fschmid 1161
                                        glyphCount++;
13522 jghali 1162
                                        int glyphsLeft = RealGlyphs.count() - SubFonts * 256;
1163
                                        if ((glyphCount > 255) || (glyphCount == glyphsLeft))
8469 fschmid 1164
                                        {
12080 avox 1165
                                                uint fontWidths = newObject();
1166
                                                StartObj(fontWidths);
8469 fschmid 1167
                                                PutDoc("[ ");
8559 subik 1168
                                                for (int ww = 0; ww < glyphWidths.count(); ++ww)
3133 fschmid 1169
                                                {
8469 fschmid 1170
                                                        PutDoc(QString::number(qRound(glyphWidths[ww]))+" ");
3133 fschmid 1171
                                                }
8469 fschmid 1172
                                                PutDoc("]\nendobj\n");
12080 avox 1173
                                                uint fontCharProcs = newObject();
1174
                                                StartObj(fontCharProcs);
8469 fschmid 1175
                                                PutDoc("<<\n");
8559 subik 1176
                                                for (int ww = 0; ww < charProcs.count(); ++ww)
8469 fschmid 1177
                                                {
1178
                                                        PutDoc(charProcs[ww]);
1179
                                                }
1180
                                                PutDoc(">>\nendobj\n");
12080 avox 1181
                                                uint fontEncoding = newObject();
1182
                                                StartObj(fontEncoding);
8469 fschmid 1183
                                                PutDoc(encoding);
1184
                                                PutDoc("]\n");
1185
                                                PutDoc(">>\nendobj\n");
12080 avox 1186
                                                uint font3Object = newObject();
1187
                                                StartObj(font3Object);
8469 fschmid 1188
                                                PutDoc("<<\n/Type /Font\n/Subtype /Type3\n");
1189
                                                PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(SubFonts)+"\n");
1190
                                                PutDoc("/FirstChar 0\n");
1191
                                                PutDoc("/LastChar "+QString::number(glyphCount-1)+"\n");
12080 avox 1192
                                                PutDoc("/Widths "+QString::number(fontWidths)+" 0 R\n");
1193
                                                PutDoc("/CharProcs "+QString::number(fontCharProcs)+" 0 R\n");
8469 fschmid 1194
                                                PutDoc("/FontBBox ["+QString::number(qRound(minx))+" "+QString::number(qRound(miny))+" "+QString::number(qRound(maxx))+ " "+QString::number(qRound(maxy))+"]\n");
1195
                                                PutDoc("/FontMatrix [0.001 0 0 0.001 0 0]\n");
12080 avox 1196
                                                PutDoc("/Encoding "+QString::number(fontEncoding)+" 0 R\n");
8469 fschmid 1197
                                                PutDoc(">>\nendobj\n");
12080 avox 1198
                                                Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(SubFonts)] = font3Object;
8469 fschmid 1199
                                                charProcs.clear();
1200
                                                glyphWidths.clear();
1201
//                                              glyphMapping.clear();
1202
                                                glyphCount = 0;
13522 jghali 1203
                                                ++SubFonts;
15071 fschmid 1204
                                                minx = 999999.9;
1205
                                                miny = 999999.9;
1206
                                                maxx = -999999.9;
1207
                                                maxy = -999999.9;
8469 fschmid 1208
                                                encoding = "<< /Type /Encoding\n/Differences [ 0\n";
3133 fschmid 1209
                                        }
1210
                                }
8469 fschmid 1211
                                Type3Fonts.insert("/Fo"+QString::number(a), glyphMapping);
1212
                        }
1213
                        else
1214
                        {
1215
                                QString fon("");
10469 cbradney 1216
                                QMap<uint,FPointArray>& RealGlyphs(it.value());
8469 fschmid 1217
                                QMap<uint,FPointArray>::Iterator ig;
1218
                                for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
5606 fschmid 1219
                                {
8469 fschmid 1220
                                        FPoint np, np1, np2;
1221
                                        bool nPath = true;
1222
                                        fon = "";
10469 cbradney 1223
                                        if (ig.value().size() > 3)
8469 fschmid 1224
                                        {
10469 cbradney 1225
                                                FPointArray gly = ig.value();
13951 fschmid 1226
                                                QTransform mat;
8469 fschmid 1227
                                                mat.scale(0.1, 0.1);
1228
                                                gly.map(mat);
1229
                                                for (uint poi = 0; poi < gly.size()-3; poi += 4)
1230
                                                {
1231
                                                        if (gly.point(poi).x() > 900000)
1232
                                                        {
1233
                                                                fon += "h\n";
1234
                                                                nPath = true;
1235
                                                                continue;
1236
                                                        }
1237
                                                        if (nPath)
1238
                                                        {
1239
                                                                np = gly.point(poi);
1240
                                                                fon += FToStr(np.x())+" "+FToStr(-np.y())+" m\n";
1241
                                                                nPath = false;
1242
                                                        }
1243
                                                        np = gly.point(poi+1);
1244
                                                        np1 = gly.point(poi+3);
1245
                                                        np2 = gly.point(poi+2);
1246
                                                        fon += FToStr(np.x()) + " " + FToStr(-np.y()) + " " +
1247
                                                                FToStr(np1.x()) + " " + FToStr(-np1.y()) + " " +
1248
                                                                FToStr(np2.x()) + " " + FToStr(-np2.y()) + " c\n";
1249
                                                }
1250
                                                fon += "h f*\n";
1251
                                                np = getMinClipF(&gly);
1252
                                                np1 = getMaxClipF(&gly);
1253
                                        }
1254
                                        else
1255
                                        {
1256
                                                fon = "h";
1257
                                                np = FPoint(0, 0);
1258
                                                np1 = FPoint(0, 0);
1259
                                        }
12080 avox 1260
                                        uint fontGlyphXForm = newObject();
1261
                                        StartObj(fontGlyphXForm);
8469 fschmid 1262
                                        PutDoc("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1\n");
1263
                                        PutDoc("/BBox [ "+FToStr(np.x())+" "+FToStr(-np.y())+" "+FToStr(np1.x())+ " "+FToStr(-np1.y())+" ]\n");
1264
                                        PutDoc("/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
1265
                                        PutDoc(">>\n");
11317 jghali 1266
                                        if (Options.Compress)
8469 fschmid 1267
                                                fon = CompressStr(&fon);
1268
                                        PutDoc("/Length "+QString::number(fon.length()+1));
11317 jghali 1269
                                        if (Options.Compress)
8469 fschmid 1270
                                                PutDoc("\n/Filter /FlateDecode");
12080 avox 1271
                                        PutDoc(" >>\nstream\n"+EncStream(fon, fontGlyphXForm)+"\nendstream\nendobj\n");
1272
                                        Seite.XObjects[AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+QString::number(ig.key())] = fontGlyphXForm;
5606 fschmid 1273
                                }
3133 fschmid 1274
                        }
1275
                }
1276
                else
1277
                {
4229 craig 1278
                        UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
12080 avox 1279
                        uint embeddedFontObject = 0;
5980 avox 1280
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1281
                        {
3829 cbradney 1282
                                QString fon("");
12080 avox 1283
                                embeddedFontObject = newObject();
1284
                                StartObj(embeddedFontObject);
3133 fschmid 1285
                                QByteArray bb;
5980 avox 1286
                                AllFonts[it.key()].RawData(bb);
8559 subik 1287
                                int posi;
3133 fschmid 1288
                                for (posi = 6; posi < bb.size(); ++posi)
1289
                                {
1290
                                        if ((bb[posi] == static_cast<char>(0x80)) && (static_cast<int>(bb[posi+1]) == 2))
1291
                                                break;
1292
                                        fon += QChar(bb[posi]);
1293
                                }
1294
                                int len1 = fon.length();
8559 subik 1295
                                int ulen;
3133 fschmid 1296
                                ulen = bb[posi+2] & 0xff;
1297
                                ulen |= (bb[posi+3] << 8) & 0xff00;
1298
                                ulen |= (bb[posi+4] << 16) & 0xff0000;
1299
                                ulen |= (bb[posi+5] << 24) & 0xff000000;
1300
                                if (ulen > bb.size())
1301
                                        ulen = bb.size()-7;
1302
                                posi += 6;
8559 subik 1303
                                for (int j = 0; j < ulen; ++j)
3133 fschmid 1304
                                        fon += QChar(bb[posi++]);
1305
                                posi += 6;
1306
                                int len2 = fon.length()-len1;
8559 subik 1307
                                for (int j = posi; j < bb.size(); ++j)
3133 fschmid 1308
                                {
1309
                                        if ((bb[j] == static_cast<char>(0x80)) && (static_cast<int>(bb[j+1]) == 3))
1310
                                                break;
1311
                                        if (bb[j] == '\r')
1312
                                                fon += "\n";
1313
                                        else
1314
                                                fon += QChar(bb[j]);
1315
                                }
1316
                                int len3 = fon.length()-len2-len1;
11317 jghali 1317
                                if (Options.Compress)
3133 fschmid 1318
                                        fon = CompressStr(&fon);
4229 craig 1319
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
1320
                                PutDoc("/Length1 "+QString::number(len1)+"\n");
1321
                                PutDoc("/Length2 "+QString::number(len2)+"\n");
1322
                                PutDoc("/Length3 "+QString::number(len3)+"\n");
11317 jghali 1323
                                if (Options.Compress)
3133 fschmid 1324
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1325
                                PutDoc(">>\nstream\n"+EncStream(fon,embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1326
                        }
5980 avox 1327
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1328
                        {
3829 cbradney 1329
                                QString fon("");
1330
                                QString fon2("");
1331
                                QString tm("");
3133 fschmid 1332
                                uint value;
1333
                                bool ok = true;
12080 avox 1334
                                embeddedFontObject = newObject();
1335
                                StartObj(embeddedFontObject);
5980 avox 1336
                                AllFonts[it.key()].EmbedFont(fon);
10469 cbradney 1337
                                int len1 = fon.indexOf("eexec")+5;
3133 fschmid 1338
                                fon2 = fon.left(len1)+"\n";
10469 cbradney 1339
                                int len2 = fon.indexOf("0000000000000000000000000");
3133 fschmid 1340
                                if (len2 == -1)
1341
                                        len2 = fon.length()+1;
1342
                                int count = 0;
1343
                                for (int xx = len1; xx < len2-1; ++xx)
1344
                                {
1345
                                        tm = fon.at(xx);
1346
                                        if ((tm == QChar(13)) || (tm == QChar(10)))
1347
                                                continue;
1348
                                        xx++;
1349
                                        count++;
1350
                                        tm += fon.at(xx);
1351
                                        value = tm.toUInt(&ok, 16);
1352
                                        fon2 += QChar(value);
1353
                                }
1354
                                fon2 += fon.mid(len2);
11317 jghali 1355
                                if (Options.Compress)
3133 fschmid 1356
                                        fon2 = CompressStr(&fon2);
4229 craig 1357
                                PutDoc("<<\n/Length "+QString::number(fon2.length()+1)+"\n");
1358
                                PutDoc("/Length1 "+QString::number(len1+1)+"\n");
1359
                                PutDoc("/Length2 "+QString::number(count)+"\n");
1360
                                PutDoc(static_cast<int>(fon.length()-len2) == -1 ? QString("/Length3 0\n") : "/Length3 "+QString::number(fon.length()-len2)+"\n");
11317 jghali 1361
                                if (Options.Compress)
3133 fschmid 1362
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1363
                                PutDoc(">>\nstream\n"+EncStream(fon2, embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1364
                        }
5980 avox 1365
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1366
                        {
3829 cbradney 1367
                                QString fon("");
12080 avox 1368
                                embeddedFontObject = newObject();
1369
                                StartObj(embeddedFontObject);
3133 fschmid 1370
                                QByteArray bb;
5980 avox 1371
                                AllFonts[it.key()].RawData(bb);
3133 fschmid 1372
                                //AV: += and append() dont't work because they stop at '\0' :-(
8559 subik 1373
                                for (int i=0; i < bb.size(); i++)
3133 fschmid 1374
                                        fon += QChar(bb[i]);
1375
                                int len = fon.length();
11317 jghali 1376
                                if (Options.Compress)
3133 fschmid 1377
                                        fon = CompressStr(&fon);
13085 jghali 1378
                                //qDebug() << QString("sfnt data: size=%1 before=%2 compressed=%3").arg(bb.size()).arg(len).arg(fon.length());
4229 craig 1379
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
1380
                                PutDoc("/Length1 "+QString::number(len)+"\n");
11317 jghali 1381
                                if (Options.Compress)
3133 fschmid 1382
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1383
                                PutDoc(">>\nstream\n"+EncStream(fon, embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1384
                        }
12080 avox 1385
                        uint fontDescriptor = newObject();
1386
                        StartObj(fontDescriptor);
5387 avox 1387
                        // TODO: think about QByteArray ScFace::getFontDescriptor() -- AV
3133 fschmid 1388
                        PutDoc("<<\n/Type /FontDescriptor\n");
5980 avox 1389
                        PutDoc("/FontName /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
15364 jghali 1390
                        PutDoc("/FontBBox [ "+AllFonts[it.key()].fontBBoxAsString()+" ]\n");
3133 fschmid 1391
                        PutDoc("/Flags ");
5980 avox 1392
                        //FIXME: isItalic() should be queried from ScFace, not from Qt -- AV
3544 avox 1393
                        //QFontInfo fo = QFontInfo(it.data());
3133 fschmid 1394
                        int pfl = 0;
5980 avox 1395
                        if (AllFonts[it.key()].isFixedPitch())
3133 fschmid 1396
                                pfl = pfl ^ 1;
3544 avox 1397
                        //if (fo.italic())
15364 jghali 1398
                        if (AllFonts[it.key()].italicAngleAsString() != "0")
3133 fschmid 1399
                                pfl = pfl ^ 64;
1400
//                      pfl = pfl ^ 4;
1401
                        pfl = pfl ^ 32;
4229 craig 1402
                        PutDoc(QString::number(pfl)+"\n");
6213 fschmid 1403
                        PutDoc("/Ascent "+AllFonts[it.key()].ascentAsString()+"\n");
1404
                        PutDoc("/Descent "+AllFonts[it.key()].descentAsString()+"\n");
1405
                        PutDoc("/CapHeight "+AllFonts[it.key()].capHeightAsString()+"\n");
15364 jghali 1406
                        PutDoc("/ItalicAngle "+AllFonts[it.key()].italicAngleAsString()+"\n");
6213 fschmid 1407
//                      PutDoc("/Ascent "+QString::number(static_cast<int>(AllFonts[it.key()].ascent()))+"\n");
1408
//                      PutDoc("/Descent "+QString::number(static_cast<int>(AllFonts[it.key()].descent()))+"\n");
1409
//                      PutDoc("/CapHeight "+QString::number(static_cast<int>(AllFonts[it.key()].capHeight()))+"\n");
1410
//                      PutDoc("/ItalicAngle "+AllFonts[it.key()].italicAngle()+"\n");
1411
//                      PutDoc("/StemV "+ AllFonts[it.key()].stemV() + "\n");
1412
                        PutDoc("/StemV 1\n");
5980 avox 1413
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
12080 avox 1414
                                PutDoc("/FontFile2 "+QString::number(embeddedFontObject)+" 0 R\n");
5980 avox 1415
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
12080 avox 1416
                                PutDoc("/FontFile "+QString::number(embeddedFontObject)+" 0 R\n");
5980 avox 1417
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
12080 avox 1418
                                PutDoc("/FontFile "+QString::number(embeddedFontObject)+" 0 R\n");
3133 fschmid 1419
                        PutDoc(">>\nendobj\n");
4546 subik 1420
/*                      if (!FT_Has_PS_Glyph_Names(AllFonts[it.key()])
3133 fschmid 1421
                        {
1422
                                StartObj(ObjCounter);
1423
                                int chCount = 31;
1424
                                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 ");
1425
                                for (int ww = 31; ww < 256; ++ww)
1426
                                {
4229 craig 1427
                                        PutDoc(QString::number(static_cast<int>(AllFonts[it.key()]->CharWidth[itg.key()]*
3133 fschmid 1428
                                                        1000))+" ");
1429
                                        if (itg == gl.end())
1430
                                                break;
1431
                                        ++itg;
1432
                                        chCount++;
1433
                                }
1434
                                PutDoc("]\nendobj\n");
1435
                                ObjCounter++;
1436
                                // put widths object
1437
                                // encoding dictionary w/ base encoding w/o differences
1438
                                StartObj(ObjCounter);
1439
                                PutDoc("<<\n/Type /Font\n/Subtype ");
5980 avox 1440
                                PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
4229 craig 1441
                                PutDoc("/Name /Fo"+QString::number(a)+"\n");
5980 avox 1442
                                PutDoc("/BaseFont /"+AllFonts[it.key()]->psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "" )+"\n");
3133 fschmid 1443
                                //cf. widths:
1444
                                PutDoc("/FirstChar 0\n");
4229 craig 1445
                                PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
1446
                                PutDoc("/Widths "+QString::number(ObjCounter-1)+" 0 R\n");
1447
                                PutDoc("/FontDescriptor "+QString::number(ObjCounter-2)+" 0 R\n");
3133 fschmid 1448
                                PutDoc(">>\nendobj\n");
4229 craig 1449
                                Seite.FObjects["Fo"+QString::number(a)] = ObjCounter;
3133 fschmid 1450
                                ObjCounter++;
1451
                        }
1452
                        else */
1453
//                      {
6301 avox 1454
                                QMap<uint,std::pair<QChar,QString> > gl;
1455
                                AllFonts[it.key()].glyphNames(gl);
1456
                                int nglyphs = 0;
1457
                                QMap<uint,std::pair<QChar,QString> >::Iterator gli;
8092 fschmid 1458
                                for (gli = gl.begin(); gli != gl.end(); ++gli)
1459
                                {
7328 fschmid 1460
                                        if (gli.key() > static_cast<uint>(nglyphs))
6301 avox 1461
                                                nglyphs = gli.key();
1462
                                }
1463
                                ++nglyphs;
13085 jghali 1464
//                              qDebug() << QString("pdflib: nglyphs %1 max %2").arg(nglyphs).arg(AllFonts[it.key()].maxGlyph());
12080 avox 1465
                                uint FontDes = fontDescriptor;
14043 jghali 1466
                                if (Options.Version == PDFOptions::PDFVersion_X4 && (fformat == ScFace::SFNT || fformat == ScFace::TTCF))
3133 fschmid 1467
                                {
12080 avox 1468
                                        uint fontWidths2 = newObject();
1469
                                        StartObj(fontWidths2);
8147 fschmid 1470
                                        QStringList toUnicodeMaps;
9803 fschmid 1471
                                        QList<int> toUnicodeMapsCount;
8136 fschmid 1472
                                        QString toUnicodeMap = "";
1473
                                        int toUnicodeMapCounter = 0;
14043 jghali 1474
 
1475
                                        PutDoc("[ ");
1476
                                        QList<uint> keys = gl.uniqueKeys();
1477
                                        QList<uint>::iterator git;
1478
                                        for (git = keys.begin(); git != keys.end(); ++git)
3133 fschmid 1479
                                        {
14043 jghali 1480
                                                PutDoc(QString::number(*git)+" ["+QString::number(static_cast<int>(AllFonts[it.key()].glyphWidth(*git)* 1000))+"] " );
1481
                                                QString tmp, tmp2;
1482
                                                tmp.sprintf("%02X", *git);
1483
                                                tmp2.sprintf("%04X", gl.value(*git).first.unicode());
1484
                                                toUnicodeMap += QString("<%1> <%2>\n").arg(tmp).arg((tmp2));
1485
                                                toUnicodeMapCounter++;
1486
                                                if (toUnicodeMapCounter == 100)
6213 fschmid 1487
                                                {
14043 jghali 1488
                                                        toUnicodeMaps.append(toUnicodeMap);
1489
                                                        toUnicodeMapsCount.append(toUnicodeMapCounter);
1490
                                                        toUnicodeMap = "";
1491
                                                        toUnicodeMapCounter = 0;
6213 fschmid 1492
                                                }
3133 fschmid 1493
                                        }
14043 jghali 1494
                                        PutDoc("]\nendobj\n");
8147 fschmid 1495
                                        if (toUnicodeMapCounter != 0)
1496
                                        {
1497
                                                toUnicodeMaps.append(toUnicodeMap);
1498
                                                toUnicodeMapsCount.append(toUnicodeMapCounter);
1499
                                        }
8136 fschmid 1500
                                        QString toUnicodeMapStream = "";
1501
                                        toUnicodeMapStream += "/CIDInit /ProcSet findresource begin\n";
1502
                                        toUnicodeMapStream += "12 dict begin\n";
1503
                                        toUnicodeMapStream += "begincmap\n";
1504
                                        toUnicodeMapStream += "/CIDSystemInfo <<\n";
1505
                                        toUnicodeMapStream += "/Registry (Adobe)\n";
1506
                                        toUnicodeMapStream += "/Ordering (UCS)\n";
1507
                                        toUnicodeMapStream += "/Supplement 0\n";
1508
                                        toUnicodeMapStream += ">> def\n";
1509
                                        toUnicodeMapStream += "/CMapName /Adobe-Identity-UCS def\n";
1510
                                        toUnicodeMapStream += "/CMapType 2 def\n";
1511
                                        toUnicodeMapStream += "1 begincodespacerange\n";
8147 fschmid 1512
                                        toUnicodeMapStream += "<0000> <FFFF>\n";
8136 fschmid 1513
                                        toUnicodeMapStream += "endcodespacerange\n";
8559 subik 1514
                                        for (int uniC = 0; uniC < toUnicodeMaps.count(); uniC++)
8147 fschmid 1515
                                        {
1516
                                                toUnicodeMapStream += QString("%1 beginbfchar\n").arg(toUnicodeMapsCount[uniC]);
1517
                                                toUnicodeMapStream += toUnicodeMaps[uniC];
1518
                                                toUnicodeMapStream += "endbfchar\n";
1519
                                        }
8136 fschmid 1520
                                        toUnicodeMapStream += "endcmap\n";
1521
                                        toUnicodeMapStream += "CMapName currentdict /CMap defineresource pop\n";
1522
                                        toUnicodeMapStream += "end\n";
1523
                                        toUnicodeMapStream += "end\n";
12906 jghali 1524
                                        uint fontToUnicode2 = WritePDFStream(toUnicodeMapStream);
12080 avox 1525
                                        uint fontObject2 = newObject();
1526
                                        StartObj(fontObject2);
14043 jghali 1527
                                        PutDoc("<<\n/Type /Font\n/Subtype /Type0\n");
1528
                                        PutDoc("/Name /Fo"+QString::number(a)+"\n");
1529
                                        PutDoc("/BaseFont /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1530
                                        PutDoc("/Encoding /Identity-H\n");
1531
                                        PutDoc("/ToUnicode "+QString::number(fontToUnicode2)+" 0 R\n");
1532
                                        PutDoc("/DescendantFonts [");
1533
                                        PutDoc("<</Type /Font");
1534
                                        PutDoc("/Subtype /CIDFontType2");
1535
                                        PutDoc("/BaseFont /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ));
1536
                                        PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R");
1537
                                        PutDoc("/CIDSystemInfo <</Ordering(Identity)/Registry(Adobe)/Supplement 0>>");
1538
                                        PutDoc("/DW 1000");
1539
                                        PutDoc("/W "+QString::number(fontWidths2)+" 0 R");
1540
                                        PutDoc("/CIDToGIDMap /Identity");
1541
                                        PutDoc(">>"); // close CIDFont dictionary
1542
                                        PutDoc("]\n"); // close DescendantFonts array
1543
                                        PutDoc(">>\nendobj\n");
1544
                                        Seite.FObjects["Fo"+QString::number(a)] = fontObject2;
1545
                                }
1546
                                else
1547
                                {
1548
                                        uint Fcc = nglyphs / 224;
1549
                                        if ((nglyphs % 224) != 0)
1550
                                                Fcc += 1;
1551
                                        for (uint Fc = 0; Fc < Fcc; ++Fc)
1552
                                        {
1553
                                                uint fontWidths2 = newObject();
1554
                                                StartObj(fontWidths2);
1555
                                                int chCount = 32;
1556
                                                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 ");
1557
                                                for (int ww = 32; ww < 256; ++ww)
1558
                                                {
1559
                                                        uint glyph = 224 * Fc + ww - 32;
1560
                                                        if (gl.contains(glyph))
1561
                                                                PutDoc(QString::number(static_cast<int>(AllFonts[it.key()].glyphWidth(glyph)* 1000))+" ");
1562
                                                        else
1563
                                                                PutDoc("0 ");
1564
                                                        chCount++;
1565
                                                        if (signed(glyph) == nglyphs-1)
1566
                                                                break;
1567
                                                }
1568
                                                PutDoc("]\nendobj\n");
1569
                                                uint fontEncoding2 = newObject();
1570
                                                StartObj(fontEncoding2);
1571
                                                QStringList toUnicodeMaps;
1572
                                                QList<int> toUnicodeMapsCount;
1573
                                                QString toUnicodeMap = "";
1574
                                                int toUnicodeMapCounter = 0;
1575
                                                PutDoc("<< /Type /Encoding\n");
1576
                                                PutDoc("/Differences [ \n");
1577
                                                int crc = 0;
1578
                                                bool startOfSeq = true;
1579
                                                for (int ww2 = 32; ww2 < 256; ++ww2)
1580
                                                {
1581
                                                        uint glyph = 224 * Fc + ww2 - 32;
1582
                                                        QMap<uint,std::pair<QChar,QString> >::Iterator glIt = gl.find(glyph);
1583
                                                        if (glIt != gl.end() && !glIt.value().second.isEmpty())
1584
                                                        {
1585
                                                                if (startOfSeq)
1586
                                                                {
1587
                                                                        PutDoc(QString::number(ww2)+" ");
1588
                                                                        startOfSeq = false;
1589
                                                                }
1590
                                                                PutDoc("/"+glIt.value().second+" ");
1591
                                                                QString tmp, tmp2;
1592
                                                                tmp.sprintf("%02X", ww2);
1593
                                                                tmp2.sprintf("%04X", glIt.value().first.unicode());
1594
                                                                toUnicodeMap += QString("<%1> <%2>\n").arg(tmp).arg((tmp2));
1595
                                                                toUnicodeMapCounter++;
1596
                                                                if (toUnicodeMapCounter == 100)
1597
                                                                {
1598
                                                                        toUnicodeMaps.append(toUnicodeMap);
1599
                                                                        toUnicodeMapsCount.append(toUnicodeMapCounter);
1600
                                                                        toUnicodeMap = "";
1601
                                                                        toUnicodeMapCounter = 0;
1602
                                                                }
1603
                                                                crc++;
1604
                                                        }
1605
                                                        else
1606
                                                        {
1607
                                                                startOfSeq = true;
1608
                                                        }
1609
                                                        if (signed(glyph) == nglyphs-1)
1610
                                                                break;
1611
                                                        if (crc > 8)
1612
                                                        {
1613
                                                                PutDoc("\n");
1614
                                                                crc = 0;
1615
                                                        }
1616
                                                }
1617
                                                if (toUnicodeMapCounter != 0)
1618
                                                {
1619
                                                        toUnicodeMaps.append(toUnicodeMap);
1620
                                                        toUnicodeMapsCount.append(toUnicodeMapCounter);
1621
                                                }
1622
                                                PutDoc("]\n");
1623
                                                PutDoc(">>\nendobj\n");
1624
                                                QString toUnicodeMapStream = "";
1625
                                                toUnicodeMapStream += "/CIDInit /ProcSet findresource begin\n";
1626
                                                toUnicodeMapStream += "12 dict begin\n";
1627
                                                toUnicodeMapStream += "begincmap\n";
1628
                                                toUnicodeMapStream += "/CIDSystemInfo <<\n";
1629
                                                toUnicodeMapStream += "/Registry (Adobe)\n";
1630
                                                toUnicodeMapStream += "/Ordering (UCS)\n";
1631
                                                toUnicodeMapStream += "/Supplement 0\n";
1632
                                                toUnicodeMapStream += ">> def\n";
1633
                                                toUnicodeMapStream += "/CMapName /Adobe-Identity-UCS def\n";
1634
                                                toUnicodeMapStream += "/CMapType 2 def\n";
1635
                                                toUnicodeMapStream += "1 begincodespacerange\n";
1636
                                                toUnicodeMapStream += "<0000> <FFFF>\n";
1637
                                                toUnicodeMapStream += "endcodespacerange\n";
1638
                                                for (int uniC = 0; uniC < toUnicodeMaps.count(); uniC++)
1639
                                                {
1640
                                                        toUnicodeMapStream += QString("%1 beginbfchar\n").arg(toUnicodeMapsCount[uniC]);
1641
                                                        toUnicodeMapStream += toUnicodeMaps[uniC];
1642
                                                        toUnicodeMapStream += "endbfchar\n";
1643
                                                }
1644
                                                toUnicodeMapStream += "endcmap\n";
1645
                                                toUnicodeMapStream += "CMapName currentdict /CMap defineresource pop\n";
1646
                                                toUnicodeMapStream += "end\n";
1647
                                                toUnicodeMapStream += "end\n";
1648
                                                uint fontToUnicode2 = WritePDFStream(toUnicodeMapStream);
1649
                                                uint fontObject2 = newObject();
1650
                                                StartObj(fontObject2);
1651
                                                PutDoc("<<\n/Type /Font\n/Subtype ");
1652
                                                PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
1653
                                                PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(Fc)+"\n");
1654
                                                PutDoc("/BaseFont /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1655
                                                PutDoc("/FirstChar 0\n");
1656
                                                PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
1657
                                                PutDoc("/Widths "+QString::number(fontWidths2)+" 0 R\n");
1658
                                                PutDoc("/Encoding "+QString::number(fontEncoding2)+" 0 R\n");
1659
                                                PutDoc("/ToUnicode "+QString::number(fontToUnicode2)+" 0 R\n");
1660
                                                PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
1661
                                                PutDoc(">>\nendobj\n");
1662
                                                Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(Fc)] = fontObject2;
1663
                                        } // for(Fc)
1664
                                        uint fontWidthsForm = newObject();
1665
                                        StartObj(fontWidthsForm);
1666
                                        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 ");
1667
                                        for (int ww = 32; ww < 256; ++ww)
1668
                                        {
1669
                                                uint glyph = AllFonts[it.key()].char2CMap(QChar(ww));
1670
                                                if (gl.contains(glyph))
1671
                                                        PutDoc(QString::number(static_cast<int>(AllFonts[it.key()].glyphWidth(glyph)* 1000))+" ");
1672
                                                else
1673
                                                        PutDoc("0 ");
1674
                                        }
1675
                                        PutDoc("]\nendobj\n");
1676
                                        uint fontObjectForm = newObject();
1677
                                        StartObj(fontObjectForm);
3133 fschmid 1678
                                        PutDoc("<<\n/Type /Font\n/Subtype ");
5980 avox 1679
                                        PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
14043 jghali 1680
        //                              if (fformat == ScFace::SFNT || fformat == ScFace::TTCF)
1681
        //                              {
1682
        //                                      PutDoc("/TrueType\n");
1683
                                                PutDoc("/Name /Fo"+QString::number(a)+"Form"+"\n");
1684
                                                Seite.FObjects["Fo"+QString::number(a)+"Form"] = fontObjectForm;
1685
                                                UsedFontsF.insert(it.key(), "/Fo"+QString::number(a)+"Form");
1686
        /*                              }
1687
                                        else
1688
                                        {
1689
                                                PutDoc("/Type1\n");
1690
                                                PutDoc("/Name /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1691
                                                Seite.FObjects[AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )] = ObjCounter;
1692
                                                UsedFontsF.insert(it.key(), "/"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ));
1693
                                        } */
5980 avox 1694
                                        PutDoc("/BaseFont /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
14043 jghali 1695
                                        PutDoc("/Encoding << \n");
1696
                                        PutDoc("/Differences [ \n");
1697
                                        PutDoc("24 /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde\n");
1698
                                        PutDoc("39 /quotesingle 96 /grave 128 /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction /guilsinglleft /guilsinglright\n");
1699
                                        PutDoc("/minus /perthousand /quotedblbase /quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron\n");
1700
                                        PutDoc("/Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron 164 /currency 166 /brokenbar 168 /dieresis /copyright /ordfeminine 172 /logicalnot\n");
1701
                                        PutDoc("/.notdef /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu 183 /periodcentered /cedilla /onesuperior /ordmasculine\n");
1702
                                        PutDoc("188 /onequarter /onehalf /threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex\n");
1703
                                        PutDoc("/Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n");
1704
                                        PutDoc("/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n");
1705
                                        PutDoc("/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis\n");
1706
                                        PutDoc("/divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis\n");
1707
                                        PutDoc("] >>\n");
3133 fschmid 1708
                                        PutDoc("/FirstChar 0\n");
14043 jghali 1709
                                        PutDoc("/LastChar 255\n");
1710
                                        PutDoc("/Widths "+QString::number(fontWidthsForm)+" 0 R\n");
4229 craig 1711
                                        PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
3133 fschmid 1712
                                        PutDoc(">>\nendobj\n");
14043 jghali 1713
        //                      } // FT_Has_PS_Glyph_Names
8101 fschmid 1714
                                }
14043 jghali 1715
 
3133 fschmid 1716
                }
1717
                a++;
1718
        }
4264 craig 1719
        if (Options.UseLPI)
3133 fschmid 1720
        {
12080 avox 1721
                uint halftones = newObject();
1722
                StartObj(halftones);
3133 fschmid 1723
                PutDoc("<<\n/Type /Halftone\n/HalftoneType 5\n");
4264 craig 1724
                QMap<QString,LPIData>::const_iterator itlp;
1725
                for (itlp = Options.LPISettings.constBegin(); itlp != Options.LPISettings.constEnd(); ++itlp)
3133 fschmid 1726
                {
1727
                        PutDoc("/"+itlp.key()+"\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency ");
10469 cbradney 1728
                        PutDoc(QString::number(itlp.value().Frequency)+"\n/Angle "+QString::number(itlp.value().Angle)+"\n/SpotFunction ");
3829 cbradney 1729
                        QString func ("");
10469 cbradney 1730
                        switch (itlp.value().SpotFunc)
3133 fschmid 1731
                        {
1732
                                case 0:
1733
                                        func = "/SimpleDot";
1734
                                        break;
1735
                                case 1:
1736
                                        func = "/Line";
1737
                                        break;
1738
                                case 2:
1739
                                        func = "/Round";
1740
                                        break;
1741
                                case 3:
1742
                                        func = "/Ellipse";
1743
                                        break;
1744
                                default:
1745
                                        func = "/SimpleDot";
1746
                                        break;
1747
                        }
1748
                        PutDoc(func+"\n>>\n");
1749
                }
1750
                PutDoc("/Default\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency 50\n/Angle 45\n/SpotFunction /Round\n>>\n");
1751
                PutDoc(">>\nendobj\n");
4229 craig 1752
                HTName = ResNam+QString::number(ResCount);
12080 avox 1753
                Transpar[HTName] = writeGState("/HT "+QString::number(halftones)+" 0 R\n");
3133 fschmid 1754
                ResCount++;
1755
        }
14043 jghali 1756
        if ((doc.HasCMS) && (Options.UseProfiles) && (Options.Version != PDFOptions::PDFVersion_X1a ))
3133 fschmid 1757
        {
12080 avox 1758
                uint iccProfileObject = newObject();
1759
                StartObj(iccProfileObject);
7144 jghali 1760
                QByteArray dataP;
3133 fschmid 1761
                struct ICCD dataD;
7144 jghali 1762
                loadRawBytes(ScCore->InputProfiles[Options.SolidProf], dataP);
3133 fschmid 1763
                PutDoc("<<\n");
11317 jghali 1764
                if (Options.Compress)
3133 fschmid 1765
                {
11317 jghali 1766
                        QByteArray compData = CompressArray(dataP);
1767
                        if (compData.size() > 0)
1768
                        {
1769
                                PutDoc("/Filter /FlateDecode\n");
1770
                                dataP = compData;
1771
                        }
3133 fschmid 1772
                }
7144 jghali 1773
                PutDoc("/Length "+QString::number(dataP.size()+1)+"\n");
4264 craig 1774
                PutDoc("/N "+QString::number(Options.SComp)+"\n");
7144 jghali 1775
                PutDoc(">>\nstream\n");
12080 avox 1776
                EncodeArrayToStream(dataP, iccProfileObject);
7144 jghali 1777
                PutDoc("\nendstream\nendobj\n");
12080 avox 1778
                uint iccColorspace = newObject();
1779
                StartObj(iccColorspace);
4229 craig 1780
                dataD.ResName = ResNam+QString::number(ResCount);
12080 avox 1781
                dataD.ICCArray = "[ /ICCBased "+QString::number(iccProfileObject)+" 0 R ]";
1782
                dataD.ResNum = iccColorspace;
12732 fschmid 1783
                dataD.components = Options.SComp;
4264 craig 1784
                ICCProfiles[Options.SolidProf] = dataD;
12080 avox 1785
                PutDoc("[ /ICCBased "+QString::number(iccProfileObject)+" 0 R ]\n");
3133 fschmid 1786
                PutDoc("endobj\n");
1787
                ResCount++;
1788
        }
4264 craig 1789
        if (((Options.isGrayscale == false) && (Options.UseRGB == false)) && (Options.UseSpotColors))
3133 fschmid 1790
        {
4264 craig 1791
                doc.getUsedColors(colorsToUse);
3133 fschmid 1792
                ColorList::Iterator itf;
1793
                for (itf = colorsToUse.begin(); itf != colorsToUse.end(); ++itf)
1794
                {
1795
                        if ((colorsToUse[itf.key()].isSpotColor()) || (colorsToUse[itf.key()].isRegistrationColor()))
1796
                        {
9619 jghali 1797
                                CMYKColor cmykValues;
3133 fschmid 1798
                                int cc, cm, cy, ck;
1799
                                struct SpotC spotD;
9619 jghali 1800
                                ScColorEngine::getCMYKValues(colorsToUse[itf.key()], &doc, cmykValues);
1801
                                cmykValues.getValues(cc, cm, cy, ck);
3133 fschmid 1802
                                QString colorDesc = "{\ndup "+FToStr(static_cast<double>(cc) / 255)+"\nmul exc