Subversion Repositories Scribus

Rev

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