Subversion Repositories Scribus

Rev

Rev 17377 | Rev 17401 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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