Subversion Repositories Scribus

Rev

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