Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
5979 avox 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
*/
7
 
10223 cbradney 8
#include <QFile>
9
#include <QString>
10
#include <QObject>
13531 pierre 11
#include <QDebug>
12
// #include <QTime>
5979 avox 13
 
14
#include <sys/types.h>
15
 
16
#include "fonts/scface_ttf.h"
17
#include "fonts/scfontmetrics.h"
18
#include "util.h"
19
#include "scconfig.h"
20
 
13531 pierre 21
KernFeature::KernFeature ( FT_Face face )
22
                :m_valid ( true )
23
{
24
        FontName = QString ( face->family_name ) + " " + QString ( face->style_name )   ;
25
//      qDebug() <<"KF"<<FontName;
26
//      QTime t;
27
//      t.start();
28
        FT_ULong length = 0;
29
        if ( !FT_Load_Sfnt_Table ( face, TTAG_GPOS , 0, NULL, &length ) )
30
        {
31
//              qDebug() <<"\t"<<"GPOS table len"<<length;
32
                if ( length > 32 )
33
                {
34
                        GPOSTableRaw.resize ( length );
35
                        FT_Load_Sfnt_Table ( face, TTAG_GPOS, 0, reinterpret_cast<FT_Byte*> ( GPOSTableRaw.data() ), &length );
5979 avox 36
 
13531 pierre 37
                        makeCoverage();
38
                }
39
                else
40
                        m_valid = false;
5979 avox 41
 
13531 pierre 42
                GPOSTableRaw.clear();
43
                coverages.clear();
44
        }
45
        else
46
                m_valid = false;
47
 
48
        if ( !m_valid )
49
                pairs.clear();
50
//      qDebug() <<"\t"<<m_valid;
51
//      qDebug() <<"\t"<<t.elapsed();
52
}
53
 
54
KernFeature::KernFeature ( const KernFeature & kf )
5979 avox 55
{
13531 pierre 56
        m_valid = kf.m_valid;
57
        if ( m_valid )
58
                pairs = kf.pairs;
59
 
5979 avox 60
}
13531 pierre 61
 
62
 
63
KernFeature::~ KernFeature()
5979 avox 64
{
65
}
13531 pierre 66
 
67
double KernFeature::getPairValue ( unsigned int glyph1, unsigned int glyph2 ) const
5979 avox 68
{
13531 pierre 69
        if ( m_valid )
70
        {
71
                if ( pairs.contains ( glyph1 ) )
72
                {
73
                        if ( pairs[glyph1].contains ( glyph2 ) )
74
                        {
75
                                return pairs[glyph1][glyph2];
76
                        }
77
                }
78
        }
79
        return 0.0;
5979 avox 80
}
13531 pierre 81
 
82
void KernFeature::makeCoverage()
5979 avox 83
{
13531 pierre 84
        if ( GPOSTableRaw.isEmpty() )
85
                return;
86
 
87
        quint16 FeatureList_Offset= toUint16 ( 6 );
88
        quint16 LookupList_Offset = toUint16 ( 8 );
89
 
90
        // Find the offsets of the kern feature tables
91
        quint16 FeatureCount = toUint16 ( FeatureList_Offset );;
92
        QList<quint16> FeatureKern_Offset;
93
        for ( quint16 FeatureRecord ( 0 ); FeatureRecord < FeatureCount; ++ FeatureRecord )
94
        {
95
                int rawIdx ( FeatureList_Offset + 2 + ( 6 * FeatureRecord ) );
96
                quint32 tag ( FT_MAKE_TAG ( GPOSTableRaw.at ( rawIdx ),
97
                                            GPOSTableRaw.at ( rawIdx + 1 ),
98
                                            GPOSTableRaw.at ( rawIdx + 2 ),
99
                                            GPOSTableRaw.at ( rawIdx + 3 ) ) );
100
                if ( tag == TTAG_kern )
101
                {
102
                        FeatureKern_Offset << ( toUint16 ( rawIdx + 4 ) + FeatureList_Offset );
103
 
104
                }
105
        }
106
 
107
        // Extract indices of lookups for feture kern
108
        QList<quint16> LookupListIndex;
109
        foreach ( quint16 kern, FeatureKern_Offset )
110
        {
111
                quint16 LookupCount ( toUint16 ( kern + 2 ) );
112
                for ( int llio ( 0 ) ; llio < LookupCount; ++llio )
113
                {
114
                        quint16 Idx ( toUint16 ( kern + 4 + ( llio * 2 ) ) );
115
                        if ( !LookupListIndex.contains ( Idx ) )
116
                        {
117
                                LookupListIndex <<Idx ;
118
                        }
119
                }
120
        }
121
 
122
 
123
        // Extract offsets of lookup tables for feature kern
124
        QList<quint16> LookupTables;
125
        QList<quint16> PairAdjustmentSubTables;
126
        for ( int i ( 0 ); i < LookupListIndex.count(); ++i )
127
        {
128
                int rawIdx ( LookupList_Offset + 2 + ( LookupListIndex[i] * 2 ) );
129
                quint16 Lookup ( toUint16 ( rawIdx )  + LookupList_Offset );
130
                quint16 SubTableCount ( toUint16 ( Lookup + 4 ) );
131
                for ( int stIdx ( 0 ); stIdx < SubTableCount; ++ stIdx )
132
                {
133
                        quint16 SubTable ( toUint16 ( Lookup + 6 + ( 2 * stIdx ) ) + Lookup );
134
 
135
//                      quint16 PosFormat ( toUint16 ( SubTable ) );
136
                        quint16 Coverage_Offset ( toUint16 ( SubTable + 2 ) + SubTable );
137
                        quint16 CoverageFormat ( toUint16 ( Coverage_Offset ) );
138
 
139
                        if ( 1 == CoverageFormat ) // glyph indices based
140
                        {
141
                                quint16 GlyphCount ( toUint16 ( Coverage_Offset + 2 ) );
142
                                quint16 GlyphID ( Coverage_Offset + 4 );
143
 
144
                                for ( unsigned int gl ( 0 ); gl < GlyphCount; ++gl )
145
                                {
146
                                        coverages[SubTable] << toUint16 ( GlyphID + ( gl * 2 ) );
147
                                }
148
                        }
149
                        else if ( 2 == CoverageFormat ) // Coverage Format2 => ranges based
150
                        {
151
                                quint16 RangeCount ( toUint16 ( Coverage_Offset + 2 ) );
152
 
153
//                              int gl_base ( 0 );
154
                                for ( int r ( 0 ); r < RangeCount; ++r )
155
                                {
156
                                        quint16 rBase ( Coverage_Offset + 4 + ( r * 6 ) );
157
                                        quint16 Start ( toUint16 ( rBase ) );
158
                                        quint16 End ( toUint16 ( rBase + 2 ) );
159
//                                      quint16 StartCoverageIndex ( toUint16 ( rBase + 4 ) );
16456 jghali 160
                                        // #9842 : for some font such as Gabriola Regular
161
                                        // the range maybe be specified in reverse order
162
                                        if (Start <= End)
163
                                        {
164
                                                for ( unsigned int gl ( Start ); gl <= End; ++gl )
165
                                                        coverages[SubTable]  << gl;
166
                                        }
167
                                        else
168
                                        {
169
                                                for ( unsigned int gl ( Start ); gl >= End; --gl )
170
                                                        coverages[SubTable]  << gl;
171
                                        }
13531 pierre 172
                                }
173
                        }
174
                        else
14819 fschmid 175
                        {
13531 pierre 176
                                qDebug() <<"Unknow Coverage Format:"<<CoverageFormat;
14819 fschmid 177
                                continue;
178
                        }
13531 pierre 179
 
180
                        makePairs ( SubTable );
181
                }
182
 
183
        }
184
 
185
 
5979 avox 186
}
13531 pierre 187
 
188
 
189
void KernFeature::makePairs ( quint16 subtableOffset )
190
{
191
        /*
192
        Lookup Type 2:
193
        Pair Adjustment Positioning Subtable
194
        */
195
 
196
        quint16 PosFormat ( toUint16 ( subtableOffset ) );
197
 
198
        if ( PosFormat == 1 )
199
        {
200
                quint16 ValueFormat1 ( toUint16 ( subtableOffset +4 ) );
201
                quint16 ValueFormat2 ( toUint16 ( subtableOffset +6 ) );
202
                quint16 PairSetCount ( toUint16 ( subtableOffset +8 ) );
203
                if ( ValueFormat1 && ValueFormat2 )
204
                {
205
                        for ( int psIdx ( 0 ); psIdx < PairSetCount; ++ psIdx )
206
                        {
207
                                unsigned int FirstGlyph ( coverages[subtableOffset][psIdx] );
208
                                quint16 PairSetOffset ( toUint16 ( subtableOffset +10 + ( 2 * psIdx ) ) +  subtableOffset );
209
                                quint16 PairValueCount ( toUint16 ( PairSetOffset ) );
210
                                quint16 PairValueRecord ( PairSetOffset + 2 );
211
                                for ( int pvIdx ( 0 );pvIdx < PairValueCount; ++pvIdx )
212
                                {
213
                                        quint16 recordBase ( PairValueRecord + ( ( 2 + 2 + 2 ) * pvIdx ) );
214
                                        quint16 SecondGlyph ( toUint16 ( recordBase ) );
215
                                        qint16 Value1 ( toInt16 ( recordBase + 2 ) );
216
                                        pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
217
                                }
218
                        }
219
                }
220
                else if ( ValueFormat1 && ( !ValueFormat2 ) )
221
                {
222
                        for ( int psIdx ( 0 ); psIdx < PairSetCount; ++ psIdx )
223
                        {
224
                                unsigned int FirstGlyph ( coverages[subtableOffset][psIdx] );
225
                                quint16 PairSetOffset ( toUint16 ( subtableOffset +10 + ( 2 * psIdx ) ) +  subtableOffset );
226
                                quint16 PairValueCount ( toUint16 ( PairSetOffset ) );
227
                                quint16 PairValueRecord ( PairSetOffset + 2 );
228
                                for ( int pvIdx ( 0 );pvIdx < PairValueCount; ++pvIdx )
229
                                {
230
                                        quint16 recordBase ( PairValueRecord + ( ( 2 + 2 ) * pvIdx ) );
231
                                        quint16 SecondGlyph ( toUint16 ( recordBase ) );
232
                                        qint16 Value1 ( toInt16 ( recordBase + 2 ) );
233
                                        pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
234
                                }
235
                        }
236
                }
237
                else
238
                {
239
                        qDebug() <<"ValueFormat1 is null or both ValueFormat1 and ValueFormat2 are null";
240
                }
241
 
242
        }
243
        else if ( PosFormat == 2 )
244
        {
245
                quint16 ValueFormat1 ( toUint16 ( subtableOffset +4 ) );
246
                quint16 ValueFormat2 ( toUint16 ( subtableOffset +6 ) );
247
                quint16 ClassDef1 ( toUint16 ( subtableOffset +8 )  + subtableOffset );
248
                quint16 ClassDef2 ( toUint16 ( subtableOffset +10 ) + subtableOffset );
249
                quint16 Class1Count ( toUint16 ( subtableOffset +12 ) );
250
                quint16 Class2Count ( toUint16 ( subtableOffset +14 ) );
251
                quint16 Class1Record ( subtableOffset +16 );
252
 
253
                // first extract classses
254
                ClassDefTable Class1Data ( getClass ( ClassDef1 , subtableOffset ) );
255
                ClassDefTable Class2Data ( getClass ( ClassDef2 , subtableOffset ) );
256
 
257
                if ( ValueFormat1 && ValueFormat2 )
258
                {
259
                        for ( quint16 C1 ( 0 );C1 < Class1Count; ++C1 )
260
                        {
261
                                QList<quint16> Class1 ( Class1Data[C1] );
262
                                quint16 Class2Record ( Class1Record + ( C1 * ( 2 * 2 * Class2Count ) ) );
263
                                for ( quint16 C2 ( 0 );C2 < Class2Count; ++C2 )
264
                                {
265
                                        qint16 Value1 ( toInt16 ( Class2Record + ( C2 * ( 2 * 2 ) ) ) );
266
                                        QList<quint16> Class2 ( Class2Data[C2] );
267
                                        // keep it barbarian :D
268
                                        foreach ( quint16 FirstGlyph, Class1 )
269
                                        {
270
                                                foreach ( quint16 SecondGlyph, Class2 )
271
                                                {
272
                                                        if ( Value1 )
273
                                                                pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
274
                                                }
275
                                        }
276
                                }
277
                        }
278
                }
279
                else if ( ValueFormat1 && ( !ValueFormat2 ) )
280
                {
281
                        for ( quint16 C1 ( 0 );C1 < Class1Count; ++C1 )
282
                        {
283
                                QString cdbg ( QString::number ( C1 ).rightJustified ( 5,QChar ( 32 ) ) );
284
                                QList<quint16> Class1 ( Class1Data[C1] );
285
                                quint16 Class2Record ( Class1Record + ( C1 * ( 2 * Class2Count ) ) );
286
                                for ( quint16 C2 ( 0 );C2 < Class2Count; ++C2 )
287
                                {
288
                                        qint16 Value1 ( toInt16 ( Class2Record + ( C2 * 2 ) ) );
289
                                        QList<quint16> Class2 ( Class2Data[C2] );
290
 
291
                                        foreach ( quint16 FirstGlyph, Class1 )
292
                                        {
293
                                                foreach ( quint16 SecondGlyph, Class2 )
294
                                                {
295
                                                        if ( Value1 )
296
                                                                pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
297
                                                }
298
                                        }
299
                                }
300
                        }
301
                }
302
                else
303
                {
304
                        qDebug() <<"ValueFormat1 is null or both ValueFormat1 and ValueFormat2 are null";
305
                }
306
 
307
        }
308
        else
309
                qDebug() <<"unknown PosFormat"<<PosFormat;
310
}
311
 
312
KernFeature::ClassDefTable KernFeature::getClass ( quint16 classDefOffset, quint16 coverageId )
313
{
314
        ClassDefTable ret;
315
        ret[0] = coverages[coverageId];
316
        quint16 ClassFormat ( toUint16 ( classDefOffset ) );
317
        if ( ClassFormat == 1 )
318
        {
319
                quint16 StartGlyph ( toUint16 ( classDefOffset +2 ) );
320
                quint16 GlyphCount ( toUint16 ( classDefOffset +4 ) );
321
                quint16 ClassValueArray ( classDefOffset + 6 );
322
 
323
                for ( quint16 CV ( 0 );CV < GlyphCount; ++CV )
324
                {
325
                        ret[0].removeAll ( StartGlyph + CV );
326
                        ret[ toUint16 ( ClassValueArray + ( CV * 2 ) ) ] << StartGlyph + CV;
327
                }
328
        }
329
        else if ( ClassFormat == 2 )
330
        {
331
                quint16 ClassRangeCount ( toUint16 ( classDefOffset + 2 ) );
332
                quint16 ClassRangeRecord ( classDefOffset + 4 );
333
                for ( int CRR ( 0 ); CRR < ClassRangeCount; ++CRR )
334
                {
335
                        quint16 Start ( toUint16 ( ClassRangeRecord + ( CRR * 6 ) ) );
336
                        quint16 End ( toUint16 ( ClassRangeRecord + ( CRR * 6 ) + 2 ) );
337
                        quint16 Class ( toUint16 ( ClassRangeRecord + ( CRR * 6 ) + 4 ) );
338
 
16508 jghali 339
                        for ( int gl ( Start ); gl <= (int) End; ++gl )
13531 pierre 340
                        {
16508 jghali 341
                                ret[0].removeAll ( (quint16) gl );
342
                                ret[Class] << (quint16) gl;
13531 pierre 343
                        }
344
                }
345
        }
346
        else
347
                qDebug() <<"Unknown Class Table type";
348
 
349
        return ret;
350
}
351
 
352
quint16 KernFeature::toUint16 ( quint16 index )
353
{
354
        if ( ( index + 2 ) > GPOSTableRaw.count() )
355
        {
356
                qDebug() << "HORROR!" << index << GPOSTableRaw.count() << FontName ;
357
                // Rather no kerning at all than random kerning
358
//              m_valid = false;
359
                return 0;
360
        }
361
        // FIXME I just do not know how it has to be done *properly*
362
        quint16 c1 ( GPOSTableRaw.at ( index ) );
363
        quint16 c2 ( GPOSTableRaw.at ( index + 1 ) );
364
        c1 &= 0xFF;
365
        c2 &= 0xFF;
366
        quint16 ret ( ( c1 << 8 ) | c2 );
367
        return ret;
368
}
369
 
370
qint16 KernFeature::toInt16 ( quint16 index )
371
{
372
        if ( ( index + 2 ) > GPOSTableRaw.count() )
373
        {
374
                return 0;
375
        }
376
        // FIXME I just do not know how it has to be done *properly*
377
        quint16 c1 ( GPOSTableRaw.at ( index ) );
378
        quint16 c2 ( GPOSTableRaw.at ( index + 1 ) );
379
        c1 &= 0xFF;
380
        c2 &= 0xFF;
381
        qint16 ret ( ( c1 << 8 ) | c2 );
382
        return ret;
383
}
384
 
385
 
386
namespace
387
{
388
        uint word ( QByteArray const & bb, uint pos )
389
        {
390
                const unsigned char * pp = reinterpret_cast<const unsigned char*> ( bb.data() ) + pos;
391
                return pp[0] << 24 | pp[1] << 16 | pp[2] << 8 | pp[3];
392
        }
393
        uint word16 ( QByteArray const & bb, uint pos )
394
        {
395
                const unsigned char * pp = reinterpret_cast<const unsigned char*> ( bb.data() ) + pos;
396
                return pp[0] << 8 | pp[1];
397
        }
398
        QString tag ( QByteArray const & bb, uint pos )
399
        {
400
                char buf[5] = "1234";
401
                buf[0] = bb.data() [pos];
402
                buf[1] = bb.data() [pos+1];
403
                buf[2] = bb.data() [pos+2];
404
                buf[3] = bb.data() [pos+3];
405
                return buf;
406
        }
407
        bool copy ( QByteArray & dst, uint to, QByteArray & src, uint from, uint len )
408
        {
409
                if ( !dst.data() )
410
                        return false;
411
                if ( !src.data() )
412
                        return false;
413
                if ( to + len > static_cast<uint> ( dst.size() ) )
414
                        return false;
415
                if ( from + len > static_cast<uint> ( src.size() ) )
416
                        return false;
417
 
418
                memcpy ( dst.data() + to, src.data() + from, len );
419
                return true;
420
        }
5979 avox 421
} //namespace
422
 
13531 pierre 423
ScFace_ttf::ScFace_ttf ( QString fam, QString sty, QString alt, QString scname, QString psname, QString path, int face )
424
                : FtFace ( fam, sty, alt, scname, psname, path, face )
425
{
426
        formatCode = ScFace::SFNT;
427
        kernFeature = 0;
428
}
5979 avox 429
 
13531 pierre 430
ScFace_ttf::~ ScFace_ttf()
431
{
432
        if ( kernFeature )
433
                delete kernFeature;
434
}
435
 
436
 
437
void ScFace_ttf::load() const
438
{
439
        if ( !kernFeature )
440
                kernFeature = new KernFeature ( ftFace() );
441
        FtFace::load();
442
}
443
 
444
void ScFace_ttf::unload() const
445
{
446
        if ( kernFeature )
447
                delete kernFeature;
448
        kernFeature = 0;
449
        FtFace::unload();
450
}
451
 
452
 
453
void ScFace_ttf::RawData ( QByteArray & bb ) const
454
{
455
        if ( formatCode == ScFace::TTCF )
456
        {
5979 avox 457
                QByteArray coll;
13531 pierre 458
                FtFace::RawData ( coll );
5979 avox 459
                // access table for faceIndex
13531 pierre 460
                if ( faceIndex >= static_cast<int> ( word ( coll, 8 ) ) )
5979 avox 461
                {
13531 pierre 462
                        bb.resize ( 0 );
5979 avox 463
                        return;
464
                }
465
                static const uint OFFSET_TABLE_LEN = 12;
466
                static const uint   TDIR_ENTRY_LEN = 16;
13531 pierre 467
                uint faceOffset = word ( coll, 12 + 4 * faceIndex );
468
                uint nTables    = word16 ( coll, faceOffset + 4 );
469
                sDebug ( QObject::tr ( "extracting face %1 from font %2 (offset=%3, nTables=%4)" ).arg ( faceIndex ).arg ( fontFile ).arg ( faceOffset ).arg ( nTables ) );
5979 avox 470
                uint headerLength = OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * nTables;
471
                uint tableLengths = 0;
472
                // sum table lengths incl padding
13531 pierre 473
                for ( uint i=0; i < nTables; ++i )
5979 avox 474
                {
13531 pierre 475
                        tableLengths += word ( coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12 );
476
                        tableLengths = ( tableLengths+3 ) & ~3;
5979 avox 477
                }
13531 pierre 478
                bb.resize ( headerLength + tableLengths );
479
                if ( ! bb.data() )
5979 avox 480
                        return;
481
                // write header
13531 pierre 482
                sDebug ( QObject::tr ( "memcpy header: %1 %2 %3" ).arg ( 0 ).arg ( faceOffset ).arg ( headerLength ) );
483
                if ( !copy ( bb, 0, coll, faceOffset, headerLength ) )
5979 avox 484
                        return;
485
 
486
                uint pos = headerLength;
13531 pierre 487
                for ( uint i=0; i < nTables; ++i )
5979 avox 488
                {
13531 pierre 489
                        uint tableSize  = word ( coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12 );
490
                        uint tableStart = word ( coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8 );
491
                        sDebug ( QObject::tr ( "table '%1'" ).arg ( tag ( coll, tableStart ) ) );
492
                        sDebug ( QObject::tr ( "memcpy table: %1 %2 %3" ).arg ( pos ).arg ( tableStart ).arg ( tableSize ) );
493
                        if ( !copy ( bb, pos, coll, tableStart, tableSize ) ) break;
5979 avox 494
                        // write new offset to table entry
13531 pierre 495
                        sDebug ( QObject::tr ( "memcpy offset: %1 %2 %3" ).arg ( OFFSET_TABLE_LEN + TDIR_ENTRY_LEN*i + 8 ).arg ( pos ).arg ( 4 ) );
496
                        memcpy ( bb.data() + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8, &pos, 4 );
5979 avox 497
                        pos += tableSize;
498
                        // pad
13531 pierre 499
                        while ( ( pos & 3 ) != 0 )
500
                                bb.data() [pos++] = '\0';
5979 avox 501
                }
502
        }
13531 pierre 503
        else if ( formatCode == ScFace::TYPE42 )
504
        {
505
                FtFace::RawData ( bb );
5979 avox 506
        }
13531 pierre 507
        else
508
        {
509
                FtFace::RawData ( bb );
510
        }
5979 avox 511
}
512
 
13531 pierre 513
bool ScFace_ttf::EmbedFont ( QString &str ) const
5979 avox 514
{
13531 pierre 515
        if ( formatCode == ScFace::TYPE42 )
516
        {
5979 avox 517
                //easy:
518
                QByteArray bb;
13531 pierre 519
                FtFace::RawData ( bb );
5979 avox 520
                str += bb;
521
                return true;
522
        }
523
        QString tmp4;
524
        QString tmp2 = "";
525
        QString tmp3 = "";
526
        int counter = 0;
527
        char *buf[50];
528
        FT_ULong  charcode;
529
        FT_UInt   gindex;
530
        FT_Face face = ftFace();
13531 pierre 531
        if ( !face )
532
        {
5979 avox 533
                return false;
534
        }
535
        const FT_Stream fts = face->stream;
13531 pierre 536
        if ( ftIOFunc ( fts, 0L, NULL, 0 ) )
537
        {
538
                return ( false );
5979 avox 539
        }
540
        str+="%!PS-TrueTypeFont\n";
541
        str+="11 dict begin\n";
542
        str+="/FontName /" + psName + " def\n";
543
        str+="/Encoding /ISOLatin1Encoding where {pop ISOLatin1Encoding} {StandardEncoding} ifelse def\n";
544
        str+="/PaintType 0 def\n/FontMatrix [1 0 0 1 0 0] def\n";
545
        str+="/FontBBox ["+FontBBox+"] def\n";
546
        str+="/FontType 42 def\n";
547
        str+="/FontInfo 8 dict dup begin\n";
548
        str+="/FamilyName (" + psName + ") def\n";
549
        str+="end readonly def\n";
550
        unsigned char *tmp = new unsigned char[65535];
551
        int length;
552
        char linebuf[80];
553
        str += "/sfnts [";
554
        int poso=0;
13531 pierre 555
        do
556
        {
5979 avox 557
                int posi=0;
558
                length= fts->size - fts->pos;
13531 pierre 559
                if ( length > 65534 )
560
                {
5979 avox 561
                        length = 65534;
562
                }
13531 pierre 563
                if ( !ftIOFunc ( fts, 0L, tmp, length ) )
5979 avox 564
                {
565
                        str+="\n<\n";
13531 pierre 566
                        for ( int j = 0; j < length; j++ )
5979 avox 567
                        {
568
                                unsigned char u=tmp[posi];
13531 pierre 569
                                linebuf[poso]= ( ( u >> 4 ) & 15 ) + '0';
570
                                if ( u>0x9f ) linebuf[poso]+='a'-':';
5979 avox 571
                                ++poso;
572
                                u&=15; linebuf[poso]=u + '0';
13531 pierre 573
                                if ( u>0x9 ) linebuf[poso]+='a'-':';
5979 avox 574
                                ++posi;
575
                                ++poso;
13531 pierre 576
                                if ( poso > 70 )
5979 avox 577
                                {
578
                                        linebuf[poso++]='\n';
579
                                        linebuf[poso++]=0;
580
                                        str += linebuf;
581
                                        poso = 0;
582
                                }
583
                        }
584
                        linebuf[poso++]=0;
585
                        str += linebuf;
586
                        poso = 0;
587
                        str += "00\n>";
588
                }
13531 pierre 589
                else
590
                {
591
                        sDebug ( QObject::tr ( "Font %1 is broken (read stream), no embedding" ).arg ( fontFile ) );
5979 avox 592
                        str += "\n] def\n";
13531 pierre 593
                        status = qMax ( status,ScFace::BROKENGLYPHS );
5979 avox 594
                        return false;
595
                }
13531 pierre 596
        }
597
        while ( length==65534 );
598
 
5979 avox 599
        str += "\n] def\n";
9556 avox 600
        delete[] tmp;
5979 avox 601
        gindex = 0;
13531 pierre 602
        charcode = FT_Get_First_Char ( face, &gindex );
603
        while ( gindex != 0 )
5979 avox 604
        {
13531 pierre 605
                FT_Get_Glyph_Name ( face, gindex, buf, 50 );
606
                tmp2 += "/"+QString ( reinterpret_cast<char*> ( buf ) ) +" "+tmp3.setNum ( gindex ) +" def\n";
607
                charcode = FT_Get_Next_Char ( face, charcode, &gindex );
5979 avox 608
                counter++;
609
        }
13531 pierre 610
        tmp4.setNum ( counter );
5979 avox 611
        str += "/CharStrings " + tmp4 + " dict dup begin\n"+tmp2;
612
        str += "end readonly def\n";
613
        str += "FontName currentdict end definefont pop\n";
13531 pierre 614
        return ( true );
5979 avox 615
}
616
 
13531 pierre 617
qreal ScFace_ttf::glyphKerning ( uint gl1, uint gl2, qreal sz ) const
618
{
619
        if ( kernFeature->isValid() )
620
        {
621
                return kernFeature->getPairValue ( gl1,gl2 ) / m_uniEM * sz;
622
 
623
        }
624
        else
625
                return FtFace::glyphKerning ( gl1, gl2, sz );
626
}
627
 
628