Subversion Repositories Scribus

Rev

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

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