Subversion Repositories Scribus

Rev

Rev 14819 | Rev 16508 | 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
                        }
221
                }
222
                else if ( ValueFormat1 && ( !ValueFormat2 ) )
223
                {
224
                        for ( int psIdx ( 0 ); psIdx < PairSetCount; ++ psIdx )
225
                        {
226
                                unsigned int FirstGlyph ( coverages[subtableOffset][psIdx] );
227
                                quint16 PairSetOffset ( toUint16 ( subtableOffset +10 + ( 2 * psIdx ) ) +  subtableOffset );
228
                                quint16 PairValueCount ( toUint16 ( PairSetOffset ) );
229
                                quint16 PairValueRecord ( PairSetOffset + 2 );
230
                                for ( int pvIdx ( 0 );pvIdx < PairValueCount; ++pvIdx )
231
                                {
232
                                        quint16 recordBase ( PairValueRecord + ( ( 2 + 2 ) * pvIdx ) );
233
                                        quint16 SecondGlyph ( toUint16 ( recordBase ) );
234
                                        qint16 Value1 ( toInt16 ( recordBase + 2 ) );
235
                                        pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
236
 
237
                                }
238
 
239
                        }
240
                }
241
                else
242
                {
243
                        qDebug() <<"ValueFormat1 is null or both ValueFormat1 and ValueFormat2 are null";
244
                }
245
 
246
        }
247
        else if ( PosFormat == 2 )
248
        {
249
                quint16 ValueFormat1 ( toUint16 ( subtableOffset +4 ) );
250
                quint16 ValueFormat2 ( toUint16 ( subtableOffset +6 ) );
251
                quint16 ClassDef1 ( toUint16 ( subtableOffset +8 )  + subtableOffset );
252
                quint16 ClassDef2 ( toUint16 ( subtableOffset +10 ) + subtableOffset );
253
                quint16 Class1Count ( toUint16 ( subtableOffset +12 ) );
254
                quint16 Class2Count ( toUint16 ( subtableOffset +14 ) );
255
                quint16 Class1Record ( subtableOffset +16 );
256
 
257
                // first extract classses
258
                ClassDefTable Class1Data ( getClass ( ClassDef1 , subtableOffset ) );
259
                ClassDefTable Class2Data ( getClass ( ClassDef2 , subtableOffset ) );
260
 
261
                if ( ValueFormat1 && ValueFormat2 )
262
                {
263
                        for ( quint16 C1 ( 0 );C1 < Class1Count; ++C1 )
264
                        {
265
                                QList<quint16> Class1 ( Class1Data[C1] );
266
                                quint16 Class2Record ( Class1Record + ( C1 * ( 2 * 2 * Class2Count ) ) );
267
                                for ( quint16 C2 ( 0 );C2 < Class2Count; ++C2 )
268
                                {
269
                                        qint16 Value1 ( toInt16 ( Class2Record + ( C2 * ( 2 * 2 ) ) ) );
270
                                        QList<quint16> Class2 ( Class2Data[C2] );
271
                                        // keep it barbarian :D
272
                                        foreach ( quint16 FirstGlyph, Class1 )
273
                                        {
274
                                                foreach ( quint16 SecondGlyph, Class2 )
275
                                                {
276
                                                        if ( Value1 )
277
                                                                pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
278
                                                }
279
                                        }
280
                                }
281
                        }
282
                }
283
                else if ( ValueFormat1 && ( !ValueFormat2 ) )
284
                {
285
                        for ( quint16 C1 ( 0 );C1 < Class1Count; ++C1 )
286
                        {
287
                                QString cdbg ( QString::number ( C1 ).rightJustified ( 5,QChar ( 32 ) ) );
288
                                QList<quint16> Class1 ( Class1Data[C1] );
289
                                quint16 Class2Record ( Class1Record + ( C1 * ( 2 * Class2Count ) ) );
290
                                for ( quint16 C2 ( 0 );C2 < Class2Count; ++C2 )
291
                                {
292
                                        qint16 Value1 ( toInt16 ( Class2Record + ( C2 * 2 ) ) );
293
                                        QList<quint16> Class2 ( Class2Data[C2] );
294
 
295
                                        foreach ( quint16 FirstGlyph, Class1 )
296
                                        {
297
                                                foreach ( quint16 SecondGlyph, Class2 )
298
                                                {
299
                                                        if ( Value1 )
300
                                                                pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
301
                                                }
302
                                        }
303
                                }
304
                        }
305
                }
306
                else
307
                {
308
                        qDebug() <<"ValueFormat1 is null or both ValueFormat1 and ValueFormat2 are null";
309
                }
310
 
311
        }
312
        else
313
                qDebug() <<"unknown PosFormat"<<PosFormat;
314
}
315
 
316
KernFeature::ClassDefTable KernFeature::getClass ( quint16 classDefOffset, quint16 coverageId )
317
{
318
        ClassDefTable ret;
319
        ret[0] = coverages[coverageId];
320
        quint16 ClassFormat ( toUint16 ( classDefOffset ) );
321
        if ( ClassFormat == 1 )
322
        {
323
                quint16 StartGlyph ( toUint16 ( classDefOffset +2 ) );
324
                quint16 GlyphCount ( toUint16 ( classDefOffset +4 ) );
325
                quint16 ClassValueArray ( classDefOffset + 6 );
326
 
327
                for ( quint16 CV ( 0 );CV < GlyphCount; ++CV )
328
                {
329
                        ret[0].removeAll ( StartGlyph + CV );
330
                        ret[ toUint16 ( ClassValueArray + ( CV * 2 ) ) ] << StartGlyph + CV;
331
                }
332
        }
333
        else if ( ClassFormat == 2 )
334
        {
335
                quint16 ClassRangeCount ( toUint16 ( classDefOffset + 2 ) );
336
                quint16 ClassRangeRecord ( classDefOffset + 4 );
337
                for ( int CRR ( 0 ); CRR < ClassRangeCount; ++CRR )
338
                {
339
                        quint16 Start ( toUint16 ( ClassRangeRecord + ( CRR * 6 ) ) );
340
                        quint16 End ( toUint16 ( ClassRangeRecord + ( CRR * 6 ) + 2 ) );
341
                        quint16 Class ( toUint16 ( ClassRangeRecord + ( CRR * 6 ) + 4 ) );
342
 
343
                        for ( quint16 gl ( Start ); gl <= End; ++gl )
344
                        {
345
                                ret[0].removeAll ( gl );
346
                                ret[Class] << gl;
347
                        }
348
                }
349
        }
350
        else
351
                qDebug() <<"Unknown Class Table type";
352
 
353
        return ret;
354
}
355
 
356
quint16 KernFeature::toUint16 ( quint16 index )
357
{
358
        if ( ( index + 2 ) > GPOSTableRaw.count() )
359
        {
360
                qDebug() << "HORROR!" << index << GPOSTableRaw.count() << FontName ;
361
                // Rather no kerning at all than random kerning
362
//              m_valid = false;
363
                return 0;
364
        }
365
        // FIXME I just do not know how it has to be done *properly*
366
        quint16 c1 ( GPOSTableRaw.at ( index ) );
367
        quint16 c2 ( GPOSTableRaw.at ( index + 1 ) );
368
        c1 &= 0xFF;
369
        c2 &= 0xFF;
370
        quint16 ret ( ( c1 << 8 ) | c2 );
371
        return ret;
372
}
373
 
374
qint16 KernFeature::toInt16 ( quint16 index )
375
{
376
        if ( ( index + 2 ) > GPOSTableRaw.count() )
377
        {
378
                return 0;
379
        }
380
        // FIXME I just do not know how it has to be done *properly*
381
        quint16 c1 ( GPOSTableRaw.at ( index ) );
382
        quint16 c2 ( GPOSTableRaw.at ( index + 1 ) );
383
        c1 &= 0xFF;
384
        c2 &= 0xFF;
385
        qint16 ret ( ( c1 << 8 ) | c2 );
386
        return ret;
387
}
388
 
389
 
390
namespace
391
{
392
        uint word ( QByteArray const & bb, uint pos )
393
        {
394
                const unsigned char * pp = reinterpret_cast<const unsigned char*> ( bb.data() ) + pos;
395
                return pp[0] << 24 | pp[1] << 16 | pp[2] << 8 | pp[3];
396
        }
397
        uint word16 ( QByteArray const & bb, uint pos )
398
        {
399
                const unsigned char * pp = reinterpret_cast<const unsigned char*> ( bb.data() ) + pos;
400
                return pp[0] << 8 | pp[1];
401
        }
402
        QString tag ( QByteArray const & bb, uint pos )
403
        {
404
                char buf[5] = "1234";
405
                buf[0] = bb.data() [pos];
406
                buf[1] = bb.data() [pos+1];
407
                buf[2] = bb.data() [pos+2];
408
                buf[3] = bb.data() [pos+3];
409
                return buf;
410
        }
411
        bool copy ( QByteArray & dst, uint to, QByteArray & src, uint from, uint len )
412
        {
413
                if ( !dst.data() )
414
                        return false;
415
                if ( !src.data() )
416
                        return false;
417
                if ( to + len > static_cast<uint> ( dst.size() ) )
418
                        return false;
419
                if ( from + len > static_cast<uint> ( src.size() ) )
420
                        return false;
421
 
422
                memcpy ( dst.data() + to, src.data() + from, len );
423
                return true;
424
        }
5979 avox 425
} //namespace
426
 
13531 pierre 427
ScFace_ttf::ScFace_ttf ( QString fam, QString sty, QString alt, QString scname, QString psname, QString path, int face )
428
                : FtFace ( fam, sty, alt, scname, psname, path, face )
429
{
430
        formatCode = ScFace::SFNT;
431
        kernFeature = 0;
432
}
5979 avox 433
 
13531 pierre 434
ScFace_ttf::~ ScFace_ttf()
435
{
436
        if ( kernFeature )
437
                delete kernFeature;
438
}
439
 
440
 
441
void ScFace_ttf::load() const
442
{
443
        if ( !kernFeature )
444
                kernFeature = new KernFeature ( ftFace() );
445
        FtFace::load();
446
}
447
 
448
void ScFace_ttf::unload() const
449
{
450
        if ( kernFeature )
451
                delete kernFeature;
452
        kernFeature = 0;
453
        FtFace::unload();
454
}
455
 
456
 
457
void ScFace_ttf::RawData ( QByteArray & bb ) const
458
{
459
        if ( formatCode == ScFace::TTCF )
460
        {
5979 avox 461
                QByteArray coll;
13531 pierre 462
                FtFace::RawData ( coll );
5979 avox 463
                // access table for faceIndex
13531 pierre 464
                if ( faceIndex >= static_cast<int> ( word ( coll, 8 ) ) )
5979 avox 465
                {
13531 pierre 466
                        bb.resize ( 0 );
5979 avox 467
                        return;
468
                }
469
                static const uint OFFSET_TABLE_LEN = 12;
470
                static const uint   TDIR_ENTRY_LEN = 16;
13531 pierre 471
                uint faceOffset = word ( coll, 12 + 4 * faceIndex );
472
                uint nTables    = word16 ( coll, faceOffset + 4 );
473
                sDebug ( QObject::tr ( "extracting face %1 from font %2 (offset=%3, nTables=%4)" ).arg ( faceIndex ).arg ( fontFile ).arg ( faceOffset ).arg ( nTables ) );
5979 avox 474
                uint headerLength = OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * nTables;
475
                uint tableLengths = 0;
476
                // sum table lengths incl padding
13531 pierre 477
                for ( uint i=0; i < nTables; ++i )
5979 avox 478
                {
13531 pierre 479
                        tableLengths += word ( coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12 );
480
                        tableLengths = ( tableLengths+3 ) & ~3;
5979 avox 481
                }
13531 pierre 482
                bb.resize ( headerLength + tableLengths );
483
                if ( ! bb.data() )
5979 avox 484
                        return;
485
                // write header
13531 pierre 486
                sDebug ( QObject::tr ( "memcpy header: %1 %2 %3" ).arg ( 0 ).arg ( faceOffset ).arg ( headerLength ) );
487
                if ( !copy ( bb, 0, coll, faceOffset, headerLength ) )
5979 avox 488
                        return;
489
 
490
                uint pos = headerLength;
13531 pierre 491
                for ( uint i=0; i < nTables; ++i )
5979 avox 492
                {
13531 pierre 493
                        uint tableSize  = word ( coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12 );
494
                        uint tableStart = word ( coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8 );
495
                        sDebug ( QObject::tr ( "table '%1'" ).arg ( tag ( coll, tableStart ) ) );
496
                        sDebug ( QObject::tr ( "memcpy table: %1 %2 %3" ).arg ( pos ).arg ( tableStart ).arg ( tableSize ) );
497
                        if ( !copy ( bb, pos, coll, tableStart, tableSize ) ) break;
5979 avox 498
                        // write new offset to table entry
13531 pierre 499
                        sDebug ( QObject::tr ( "memcpy offset: %1 %2 %3" ).arg ( OFFSET_TABLE_LEN + TDIR_ENTRY_LEN*i + 8 ).arg ( pos ).arg ( 4 ) );
500
                        memcpy ( bb.data() + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8, &pos, 4 );
5979 avox 501
                        pos += tableSize;
502
                        // pad
13531 pierre 503
                        while ( ( pos & 3 ) != 0 )
504
                                bb.data() [pos++] = '\0';
5979 avox 505
                }
506
        }
13531 pierre 507
        else if ( formatCode == ScFace::TYPE42 )
508
        {
509
                FtFace::RawData ( bb );
5979 avox 510
        }
13531 pierre 511
        else
512
        {
513
                FtFace::RawData ( bb );
514
        }
5979 avox 515
}
516
 
13531 pierre 517
bool ScFace_ttf::EmbedFont ( QString &str ) const
5979 avox 518
{
13531 pierre 519
        if ( formatCode == ScFace::TYPE42 )
520
        {
5979 avox 521
                //easy:
522
                QByteArray bb;
13531 pierre 523
                FtFace::RawData ( bb );
5979 avox 524
                str += bb;
525
                return true;
526
        }
527
        QString tmp4;
528
        QString tmp2 = "";
529
        QString tmp3 = "";
530
        int counter = 0;
531
        char *buf[50];
532
        FT_ULong  charcode;
533
        FT_UInt   gindex;
534
        FT_Face face = ftFace();
13531 pierre 535
        if ( !face )
536
        {
5979 avox 537
                return false;
538
        }
539
        const FT_Stream fts = face->stream;
13531 pierre 540
        if ( ftIOFunc ( fts, 0L, NULL, 0 ) )
541
        {
542
                return ( false );
5979 avox 543
        }
544
        str+="%!PS-TrueTypeFont\n";
545
        str+="11 dict begin\n";
546
        str+="/FontName /" + psName + " def\n";
547
        str+="/Encoding /ISOLatin1Encoding where {pop ISOLatin1Encoding} {StandardEncoding} ifelse def\n";
548
        str+="/PaintType 0 def\n/FontMatrix [1 0 0 1 0 0] def\n";
549
        str+="/FontBBox ["+FontBBox+"] def\n";
550
        str+="/FontType 42 def\n";
551
        str+="/FontInfo 8 dict dup begin\n";
552
        str+="/FamilyName (" + psName + ") def\n";
553
        str+="end readonly def\n";
554
        unsigned char *tmp = new unsigned char[65535];
555
        int length;
556
        char linebuf[80];
557
        str += "/sfnts [";
558
        int poso=0;
13531 pierre 559
        do
560
        {
5979 avox 561
                int posi=0;
562
                length= fts->size - fts->pos;
13531 pierre 563
                if ( length > 65534 )
564
                {
5979 avox 565
                        length = 65534;
566
                }
13531 pierre 567
                if ( !ftIOFunc ( fts, 0L, tmp, length ) )
5979 avox 568
                {
569
                        str+="\n<\n";
13531 pierre 570
                        for ( int j = 0; j < length; j++ )
5979 avox 571
                        {
572
                                unsigned char u=tmp[posi];
13531 pierre 573
                                linebuf[poso]= ( ( u >> 4 ) & 15 ) + '0';
574
                                if ( u>0x9f ) linebuf[poso]+='a'-':';
5979 avox 575
                                ++poso;
576
                                u&=15; linebuf[poso]=u + '0';
13531 pierre 577
                                if ( u>0x9 ) linebuf[poso]+='a'-':';
5979 avox 578
                                ++posi;
579
                                ++poso;
13531 pierre 580
                                if ( poso > 70 )
5979 avox 581
                                {
582
                                        linebuf[poso++]='\n';
583
                                        linebuf[poso++]=0;
584
                                        str += linebuf;
585
                                        poso = 0;
586
                                }
587
                        }
588
                        linebuf[poso++]=0;
589
                        str += linebuf;
590
                        poso = 0;
591
                        str += "00\n>";
592
                }
13531 pierre 593
                else
594
                {
595
                        sDebug ( QObject::tr ( "Font %1 is broken (read stream), no embedding" ).arg ( fontFile ) );
5979 avox 596
                        str += "\n] def\n";
13531 pierre 597
                        status = qMax ( status,ScFace::BROKENGLYPHS );
5979 avox 598
                        return false;
599
                }
13531 pierre 600
        }
601
        while ( length==65534 );
602
 
5979 avox 603
        str += "\n] def\n";
9556 avox 604
        delete[] tmp;
5979 avox 605
        gindex = 0;
13531 pierre 606
        charcode = FT_Get_First_Char ( face, &gindex );
607
        while ( gindex != 0 )
5979 avox 608
        {
13531 pierre 609
                FT_Get_Glyph_Name ( face, gindex, buf, 50 );
610
                tmp2 += "/"+QString ( reinterpret_cast<char*> ( buf ) ) +" "+tmp3.setNum ( gindex ) +" def\n";
611
                charcode = FT_Get_Next_Char ( face, charcode, &gindex );
5979 avox 612
                counter++;
613
        }
13531 pierre 614
        tmp4.setNum ( counter );
5979 avox 615
        str += "/CharStrings " + tmp4 + " dict dup begin\n"+tmp2;
616
        str += "end readonly def\n";
617
        str += "FontName currentdict end definefont pop\n";
13531 pierre 618
        return ( true );
5979 avox 619
}
620
 
13531 pierre 621
qreal ScFace_ttf::glyphKerning ( uint gl1, uint gl2, qreal sz ) const
622
{
623
        if ( kernFeature->isValid() )
624
        {
625
                return kernFeature->getPairValue ( gl1,gl2 ) / m_uniEM * sz;
626
 
627
        }
628
        else
629
                return FtFace::glyphKerning ( gl1, gl2, sz );
630
}
631
 
632