Subversion Repositories Scribus

Rev

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