Subversion Repositories Scribus

Rev

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