Subversion Repositories Scribus

Rev

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