Subversion Repositories Scribus

Rev

Rev 6213 | Rev 6222 | 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
#include <qpainter.h>
8
#include <qcolor.h>
9
#include <qwmatrix.h>
10
#include <qpixmap.h>
11
#include <qstringlist.h>
12
#include <qmap.h>
13
#include <qregexp.h>
14
 
15
#include "scribusdoc.h"
16
#include "scfonts.h"
17
#include "style.h"
18
#include "scfontmetrics.h"
19
#include "scpainter.h"
20
#include "fpoint.h"
21
#include "fpointarray.h"
22
#include "page.h"
23
#include "util.h"
24
 
25
// this code contains a set of font related functions
26
// that don't really fit within ScFonts.
27
 
28
static FPoint firstP;
29
static bool FirstM;
30
static QMap<FT_ULong, QString> adobeGlyphNames;
31
static const char* table[] = {
32
//#include "glyphnames.txt.q"
33
                                        NULL};
34
 
35
// private functions
36
static void readAdobeGlyphNames();
37
static QString adobeGlyphName(FT_ULong charcode);
38
static int traceMoveto( FT_Vector *to, FPointArray *composite );
39
static int traceLineto( FT_Vector *to, FPointArray *composite );
40
static int traceQuadraticBezier( FT_Vector *control, FT_Vector *to, FPointArray *composite );
41
static int traceCubicBezier( FT_Vector *p, FT_Vector *q, FT_Vector *to, FPointArray *composite );
42
 
43
FT_Outline_Funcs OutlineMethods =
44
    {
45
        (FT_Outline_MoveTo_Func) traceMoveto,
46
        (FT_Outline_LineTo_Func) traceLineto,
47
        (FT_Outline_ConicTo_Func) traceQuadraticBezier,
48
        (FT_Outline_CubicTo_Func) traceCubicBezier,
49
        0,
50
 
51
    };
52
 
53
 
54
const double FTSCALE = 64.0;
55
 
56
 
57
int setBestEncoding(FT_Face face)
58
{
59
        FT_ULong  charcode;
60
        FT_UInt   gindex;
61
        bool foundEncoding = false;
62
        int countUniCode = 0;
63
        int chmapUniCode = -1;
64
        int chmapCustom = -1;
65
        int retVal = 0;
66
        //FT_CharMap defaultEncoding = face->charmap;
67
//      int defaultchmap=face->charmap ? FT_Get_Charmap_Index(face->charmap) : 0;
68
// Since the above function is only available in FreeType 2.1.10 its replaced by
69
// the following line, assuming that the default charmap has the index 0
70
        int defaultchmap = 0;
71
        for(int u = 0; u < face->num_charmaps; u++)
72
        {
73
                if (face->charmaps[u]->encoding == FT_ENCODING_UNICODE )
74
                {
75
                        FT_Set_Charmap(face, face->charmaps[u]);
76
                        chmapUniCode = u;
77
                        gindex = 0;
78
                        charcode = FT_Get_First_Char( face, &gindex );
79
                        while ( gindex != 0 )
80
                        {
81
                                countUniCode++;
82
                                charcode = FT_Get_Next_Char( face, charcode, &gindex );
83
                        }
84
                }
85
                if (face->charmaps[u]->encoding == FT_ENCODING_ADOBE_CUSTOM)
86
                {
87
                        chmapCustom = u;
88
                        foundEncoding = true;
89
                        retVal = 1;
90
                        break;
91
                }
92
                else if (face->charmaps[u]->encoding == FT_ENCODING_MS_SYMBOL)
93
                {
94
                        chmapCustom = u;
95
                        foundEncoding = true;
96
                        retVal = 2;
97
                        break;
98
                }
99
        }
100
        int mapToSet=defaultchmap;
101
        if (chmapUniCode>0 && countUniCode >= face->num_glyphs-1)
102
        {
103
                mapToSet=chmapUniCode;
104
                //FT_Set_Charmap(face, face->charmaps[chmapUniCode]);
105
                retVal = 0;
106
        }
107
        else
108
        if (foundEncoding)
109
        {
110
                mapToSet=chmapCustom;
111
                //FT_Set_Charmap(face, face->charmaps[chmapCustom]);
112
        }
113
        else
114
        {
115
                mapToSet=defaultchmap;
116
                //FT_Set_Charmap(face, defaultEncoding);
117
                retVal = 0;
118
        }
119
 
120
        //Fixes #2199, missing glyphs from 1.2.1->1.2.2
121
        //If the currently wanted character map is not already Unicode...
122
        //if (FT_Get_Charmap_Index(face->charmap)!=chmapUniCode)
123
        if (mapToSet!=chmapUniCode)
124
        {
125
                //Change map so we can count the chars in it
126
                FT_Set_Charmap(face, face->charmaps[mapToSet]);
127
                //Count the characters in the current map
128
                gindex = 0;
129
                int countCurrMap=0;
130
                charcode = FT_Get_First_Char( face, &gindex );
131
                while ( gindex != 0 )
132
                {
133
                        countCurrMap++;
134
                        charcode = FT_Get_Next_Char( face, charcode, &gindex );
135
                }
136
                //If the last Unicode map we found before has more characters,
137
                //then set it to be the current map.
138
                if (countUniCode>countCurrMap)
139
                {
140
                        mapToSet=chmapUniCode;
141
                        //FT_Set_Charmap(face, face->charmaps[chmapUniCode]);
142
                        retVal = 0;
143
                }
144
        }
145
//      if (face->charmap == NULL || mapToSet!=FT_Get_Charmap_Index(face->charmap))
146
                FT_Set_Charmap(face, face->charmaps[mapToSet]);
147
        return retVal;
148
}
149
 
150
FPointArray traceGlyph(FT_Face face, FT_UInt glyphIndex, int chs, double *x, double *y, bool *err)
151
{
152
        bool error = false;
153
        //AV: not threadsave, but tracechar is only used in ReadMetrics() and fontSample()
154
        static FPointArray pts;
155
        FPointArray pts2;
156
        pts.resize(0);
157
        pts2.resize(0);
158
        firstP = FPoint(0,0);
159
        FirstM = true;
160
        error = FT_Set_Char_Size( face, 0, chs*6400, 72, 72 );
161
        if (error)
162
        {
163
                *err = error;
164
                return pts2;
165
        }
166
        if (glyphIndex == 0)
167
        {
168
                *err = true;
169
                return pts2;
170
        }
171
        double uniEM = static_cast<double>(face->units_per_EM);
172
        error = FT_Load_Glyph( face, glyphIndex, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP );
173
        if (error)
174
        {
175
                *err = error;
176
                return pts2;
177
        }
178
        error = FT_Outline_Decompose(&face->glyph->outline, &OutlineMethods, reinterpret_cast<void*>(&pts));
179
        if (error)
180
        {
181
                *err = error;
182
                return pts2;
183
        }
184
        *x = face->glyph->metrics.horiBearingX / 6400.0;
185
        *y = face->glyph->metrics.horiBearingY / 6400.0;
186
        QWMatrix ma;
187
        ma.scale(0.01, -0.01);
188
        pts.map(ma);
189
        pts.translate(0, chs);
190
        pts2.putPoints(0, pts.size()-2, pts, 0);
191
 
192
        return pts2;
193
}
194
 
195
 
196
FPointArray traceChar(FT_Face face, uint chr, int chs, double *x, double *y, bool *err)
197
{
198
        bool error = false;
199
        FT_UInt glyphIndex;
6220 fschmid 200
        static FPointArray pts;
201
        FPointArray pts2;
202
        pts.resize(0);
203
        pts2.resize(0);
204
        firstP = FPoint(0,0);
205
        FirstM = true;
5979 avox 206
        error = FT_Set_Char_Size( face, 0, chs*64, 72, 72 );
207
        if (error)
208
        {
209
                *err = error;
210
                return FPointArray();
211
        }
212
        glyphIndex = FT_Get_Char_Index(face, chr);
6220 fschmid 213
        if (glyphIndex == 0)
214
        {
215
                *err = true;
216
                return FPointArray();
217
        }
218
        double uniEM = static_cast<double>(face->units_per_EM);
219
        error = FT_Load_Glyph( face, glyphIndex, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP );
220
        if (error)
221
        {
222
                *err = error;
223
                return pts2;
224
        }
225
        error = FT_Outline_Decompose(&face->glyph->outline, &OutlineMethods, reinterpret_cast<void*>(&pts));
226
        if (error)
227
        {
228
                *err = error;
229
                return pts2;
230
        }
231
        *x = face->glyph->metrics.horiBearingX / 64.0;
232
        *y = face->glyph->metrics.horiBearingY / 64.0;
233
        QWMatrix ma;
234
        ma.scale(1, -1);
235
        pts.map(ma);
236
        pts.translate(0, chs);
237
        pts2.putPoints(0, pts.size()-2, pts, 0);
238
        return pts2;
5979 avox 239
}
240
 
241
 
5989 jghali 242
QPixmap FontSample(const ScFace& fnt, int s, QString ts, QColor back, bool force)
5979 avox 243
{
244
        FT_Face face;
245
        FT_Library library;
246
        double x, y, ymax;
247
        bool error;
248
        int  pen_x;
249
        FPoint gp;
250
        error = FT_Init_FreeType( &library );
5989 jghali 251
        error = FT_New_Face( library, QFile::encodeName(fnt.fontFilePath()), fnt.faceIndex(), &face );
5979 avox 252
        int encode = setBestEncoding(face);
253
        double uniEM = static_cast<double>(face->units_per_EM);
254
        int h = qRound(face->height / uniEM) * s + 1;
255
        double a = static_cast<double>(face->descender) / uniEM * s + 1;
256
        int w = qRound((face->bbox.xMax - face->bbox.xMin) / uniEM) * s * (ts.length()+1);
257
        if (w < 1)
258
                w = s * (ts.length()+1);
259
        if (h < 1)
260
                h = s;
261
        QPixmap pm(w, h);
262
        pm.fill();
263
        pen_x = 0;
264
        ymax = 0.0;
265
        ScPainter *p = new ScPainter(&pm, pm.width(), pm.height());
266
        p->setFillMode(1);
267
        p->setLineWidth(0.0);
268
        p->setBrush(back);
269
        p->drawRect(0.0, 0.0, static_cast<double>(w), static_cast<double>(h));
270
        p->setBrush(Qt::black);
271
        FPointArray gly;
272
        uint dv;
273
        dv = ts[0].unicode();
274
        error = false;
275
        gly = traceChar(face, dv, s, &x, &y, &error);
276
        if (((encode != 0) || (error)) && (!force))
277
        {
278
                error = false;
279
                FT_ULong  charcode;
280
                FT_UInt gindex;
281
                gindex = 0;
282
                charcode = FT_Get_First_Char(face, &gindex );
283
                for (uint n = 0; n < ts.length(); ++n)
284
                {
285
                        gly = traceChar(face, charcode, s, &x, &y, &error);
286
                        if (error)
287
                                break;
288
                        if (gly.size() > 3)
289
                        {
290
                                gly.translate(static_cast<double>(pen_x) / FTSCALE, a);
291
                                gp = getMaxClipF(&gly);
292
                                ymax = QMAX(ymax, gp.y());
293
                                p->setupPolygon(&gly);
294
                                p->fillPath();
295
                        }
296
                        pen_x += face->glyph->advance.x;
297
                        charcode = FT_Get_Next_Char(face, charcode, &gindex );
298
                        if (gindex == 0)
299
                                break;
300
                }
301
        }
302
        else
303
        {
304
                for (uint n = 0; n < ts.length(); ++n)
305
                {
306
                        dv = ts[n].unicode();
307
                        error = false;
308
                        gly = traceChar(face, dv, s, &x, &y, &error);
309
                        if (gly.size() > 3)
310
                        {
311
                                gly.translate(static_cast<double>(pen_x) / FTSCALE, a);
312
                                gp = getMaxClipF(&gly);
313
                                ymax = QMAX(ymax, gp.y());
314
                                p->setupPolygon(&gly);
315
                                p->fillPath();
316
                        }
317
                        pen_x += face->glyph->advance.x;
318
                }
319
        }
320
        p->end();
321
        pm.resize(QMIN(qRound(gp.x()), w), QMIN(qRound(ymax), h));
322
        delete p;
323
        FT_Done_FreeType( library );
324
        return pm;
325
}
326
 
327
/** Same as FontSample() with \n strings support added.
328
09/26/2004 petr vanek
329
 
330
QPixmap fontSamples(ScFace * fnt, int s, QString ts, QColor back)
331
{
332
        QStringList lines = QStringList::split("\n", ts);
333
        QPixmap ret(640, 480);
334
        QPixmap sample;
335
        QPainter *painter = new QPainter(&ret);
336
        int y = 0;
337
        int x = 0;
338
        ret.fill(back);
339
        for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it )
340
        {
341
                sample = FontSample(fnt, s, *it, back);
342
                if (!sample.isNull())
343
                        painter->drawPixmap(0, y, sample, 0, 0);
344
                y = y + sample.height();
345
                if (x < sample.width())
346
                        x = sample.width();
347
        } // for
348
        delete(painter);
349
        QPixmap final(x, y);
350
        if ((x != 0) && (y != 0))
351
        {
352
                QPainter *fpainter = new QPainter(&final);
353
                fpainter->drawPixmap(0, 0, ret, 0, 0, x, y);
354
                delete(fpainter);
355
        }
356
        return final;
357
}
358
*/
359
 
6163 avox 360
bool GlyNames(FT_Face face, QMap<uint, std::pair<QChar, QString> >& GList)
5979 avox 361
{
362
        bool error;
363
        char buf[50];
364
        FT_ULong  charcode;
365
        FT_UInt gindex;
366
        setBestEncoding(face);
367
        gindex = 0;
368
        charcode = FT_Get_First_Char(face, &gindex );
369
        const bool hasPSNames = FT_HAS_GLYPH_NAMES(face);
370
        if (adobeGlyphNames.empty())
371
                readAdobeGlyphNames();
372
        while (gindex != 0)
373
        {
374
                bool notfound = true;
375
                if (hasPSNames)
376
                        notfound = FT_Get_Glyph_Name(face, gindex, &buf, 50);
377
 
378
                // just in case FT gives empty string or ".notdef"
379
                // no valid glyphname except ".notdef" starts with '.'          
380
                if (notfound || buf[0] == '\0' || buf[0] == '.')
6163 avox 381
                        GList.insert(gindex, std::make_pair(QChar(static_cast<uint>(charcode)),adobeGlyphName(charcode)));
5979 avox 382
                else
6163 avox 383
                        GList.insert(gindex, std::make_pair(QChar(static_cast<uint>(charcode)),QString(reinterpret_cast<char*>(buf))));
5979 avox 384
 
385
                charcode = FT_Get_Next_Char(face, charcode, &gindex );
386
        }
387
        return true;
388
}
6213 fschmid 389
 
390
bool GlyIndex(FT_Face face, QMap<uint, std::pair<uint, QString> >& GList)
5979 avox 391
{
392
        bool error;
393
        char buf[50];
394
        FT_ULong  charcode;
395
        FT_UInt   gindex;
396
        uint counter1 = 32;
397
        uint counter2 = 0;
398
        setBestEncoding(face);
399
        gindex = 0;
400
        charcode = FT_Get_First_Char(face, &gindex );
401
        const bool hasPSNames = FT_HAS_GLYPH_NAMES(face);
402
        if (adobeGlyphNames.empty())
403
                readAdobeGlyphNames();
404
        while (gindex != 0)
405
        {
406
                bool notfound = true;
407
                if (hasPSNames)
408
                        notfound = FT_Get_Glyph_Name(face, gindex, buf, 50);
409
 
410
                // just in case FT gives empty string or ".notdef"
411
                // no valid glyphname except ".notdef" starts with '.'          
412
                if (notfound || buf[0] == '\0' || buf[0] == '.')
6213 fschmid 413
                        GList.insert(charcode, std::make_pair(counter1 + counter2, adobeGlyphName(charcode)));
5979 avox 414
                else
6213 fschmid 415
                        GList.insert(charcode, std::make_pair(counter1 + counter2, QString(reinterpret_cast<char*>(buf))));
5979 avox 416
                charcode = FT_Get_Next_Char(face, charcode, &gindex );
417
                counter1++;
418
                if (counter1 > 255)
419
                {
420
                        counter1 = 32;
421
                        counter2 += 0x100;
422
                }
423
        }
424
        return true;
425
}
426
 
6213 fschmid 427
 
5979 avox 428
static int traceMoveto( FT_Vector *to, FPointArray *composite )
429
{
430
        double tox = ( to->x / FTSCALE );
431
        double toy = ( to->y / FTSCALE );
432
        if (!FirstM)
433
        {
434
                composite->addPoint(firstP);
435
                composite->addPoint(firstP);
436
                composite->setMarker();
437
        }
438
        else
439
                FirstM = false;
440
        composite->addPoint(tox, toy);
441
        composite->addPoint(tox, toy);
442
        firstP.setXY(tox, toy);
443
        return 0;
444
}
445
 
446
static int traceLineto( FT_Vector *to, FPointArray *composite )
447
{
448
        double tox = ( to->x / FTSCALE );
449
        double toy = ( to->y / FTSCALE );
450
        if ( !composite->hasLastQuadPoint(tox, toy, tox, toy, tox, toy, tox, toy))
451
                composite->addQuadPoint(tox, toy, tox, toy, tox, toy, tox, toy);
452
        return 0;
453
}
454
 
455
static int traceQuadraticBezier( FT_Vector *control, FT_Vector *to, FPointArray *composite )
456
{
457
        double x1 = ( control->x / FTSCALE );
458
        double y1 = ( control->y / FTSCALE );
459
        double x2 = ( to->x / FTSCALE );
460
        double y2 = ( to->y / FTSCALE );
461
        if ( !composite->hasLastQuadPoint(x2, y2, x1, y1, x2, y2, x2, y2))
462
                composite->addQuadPoint(x2, y2, x1, y1, x2, y2, x2, y2);
463
        return 0;
464
}
465
 
466
static int traceCubicBezier( FT_Vector *p, FT_Vector *q, FT_Vector *to, FPointArray *composite )
467
{
468
        double x1 = ( p->x / FTSCALE );
469
        double y1 = ( p->y / FTSCALE );
470
        double x2 = ( q->x / FTSCALE );
471
        double y2 = ( q->y / FTSCALE );
472
        double x3 = ( to->x / FTSCALE );
473
        double y3 = ( to->y / FTSCALE );
474
        if ( !composite->hasLastQuadPoint(x3, y3, x2, y2, x3, y3, x3, y3) )
475
        {
476
                composite->setPoint(composite->size()-1, FPoint(x1, y1));
477
                composite->addQuadPoint(x3, y3, x2, y2, x3, y3, x3, y3);
478
        }
479
        return 0;
480
}
481
 
482
/// init the Adobe Glyph List
483
void readAdobeGlyphNames() {
484
        adobeGlyphNames.clear();
485
        QRegExp pattern("(\\w*);([0-9A-Fa-f]{4})");
486
        for (uint i=0; table[i]; ++i) {
487
                if (pattern.search(table[i]) >= 0) {
488
                        FT_ULong unicode = pattern.cap(2).toULong(0, 16);
489
                        qDebug("%s", QString("reading glyph name %1 fo unicode %2(%3)").arg(pattern.cap(1)).arg(unicode).arg(pattern.cap(2)).ascii());
490
                        adobeGlyphNames.insert(unicode, pattern.cap(1));
491
                }
492
        }
493
}
494
 
495
 
496
/// if in AGL, use that name, else use "uni1234" or "u12345"
497
QString adobeGlyphName(FT_ULong charcode) {
498
        static const char HEX[] = "0123456789ABCDEF";
499
        QString result;
500
        if (adobeGlyphNames.contains(charcode))
501
                return adobeGlyphNames[charcode];
502
        else if (charcode < 0x10000) {
503
                result = QString("uni") + HEX[charcode>>12 & 0xF]
504
                                        + HEX[charcode>> 8 & 0xF]
505
                                        + HEX[charcode>> 4 & 0xF]
506
                                        + HEX[charcode     & 0xF];
507
        }
508
        else  {
509
                result = QString("u");
510
                for (int i= 28; i >= 0; i-=4) {
511
                        if (charcode & (0xF << i))
512
                                result += HEX[charcode >> i & 0xF];
513
                }
514
        }
515
        return result;
516
}
517
 
518
/*
519
double Cwidth(ScribusDoc *, ScFace* scFace, QString ch, int Size, QString ch2)
520
{
521
        double width;
522
        FT_Vector  delta;
523
        FT_Face      face;
524
        uint c1 = ch.at(0).unicode();
525
        uint c2 = ch2.at(0).unicode();
526
        double size10=Size/10.0;
527
        if (scFace->canRender(ch[0]))
528
        {
529
                width = scFace->charWidth(ch[0])*size10;
530
                face = scFace->ftFace();
531
                /\****
532
                        Ok, this looks like a regression between Freetype 2.1.9 -> 2.1.10.
533
                        Ignoring the value of FT_HAS_KERNING for now -- AV
534
                 ****\/
535
                if (true || FT_HAS_KERNING(face) )
536
                {
537
                        uint cl = FT_Get_Char_Index(face, c1);
538
                        uint cr = FT_Get_Char_Index(face, c2);
539
                        FT_Error error = FT_Get_Kerning(face, cl, cr, FT_KERNING_UNSCALED, &delta);
540
                        if (error) {
541
                                qDebug(QString("Error %2 when accessing kerning pair for font %1").arg(scFace->scName()).arg(error));
542
                        }
543
                        else {
544
                                double uniEM = static_cast<double>(face->units_per_EM);
545
                                width += delta.x / uniEM * size10;
546
                        }
547
                }
548
                else {
549
                        qDebug(QString("Font %1 has no kerning pairs (according to Freetype)").arg(scFace->scName()));
550
                }
551
                return width;
552
        }
553
        else
554
                return size10;
555
}
556
 
557
double RealCWidth(ScribusDoc *, ScFace* scFace, QString ch, int Size)
558
{
559
        double w, ww;
560
        uint c1 = ch.at(0).unicode();
561
        FT_Face      face;
562
        if (scFace->canRender(ch.at(0)))
563
        {
564
                face = scFace->ftFace();
565
                uint cl = FT_Get_Char_Index(face, c1);
566
                int error = FT_Load_Glyph(face, cl, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
567
                if (!error) {
568
                        double uniEM = static_cast<double>(face->units_per_EM);
569
                        w = (face->glyph->metrics.width + fabs((double)face->glyph->metrics.horiBearingX)) / uniEM * (Size / 10.0);
570
                        ww = face->glyph->metrics.horiAdvance / uniEM * (Size / 10.0);
571
                        return QMAX(ww, w);
572
                }
573
                else
574
                        sDebug(QString("internal error: missing glyph: %1 (char %2) error=%3").arg(c1).arg(ch).arg(error));
575
 
576
        }
577
        return static_cast<double>(Size / 10.0);
578
}
579
 
580
double RealCHeight(ScribusDoc *, ScFace* scFace, QString ch, int Size)
581
{
582
        double w;
583
        uint c1 = ch.at(0).unicode();
584
        FT_Face      face;
585
        if (scFace->canRender(ch.at(0)))
586
        {
587
                face = scFace->ftFace();
588
                uint cl = FT_Get_Char_Index(face, c1);
589
                int error = FT_Load_Glyph(face, cl, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
590
                if (!error) {
591
                        double uniEM = static_cast<double>(face->units_per_EM);
592
                        w = face->glyph->metrics.height / uniEM * (Size / 10.0);
593
                }
594
                else {
595
                        sDebug(QString("internal error: missing glyph: %1 (char %2) error=%3").arg(c1).arg(ch).arg(error));
596
                        w = Size / 10.0;
597
                }
598
                return w;
599
        }
600
        else
601
                return static_cast<double>(Size / 10.0);
602
}
603
 
604
double RealCAscent(ScribusDoc *, ScFace* scFace, QString ch, int Size)
605
{
606
        double w;
607
        uint c1 = ch.at(0).unicode();
608
        FT_Face      face;
609
        if (scFace->canRender(ch.at(0)))
610
        {
611
                face = scFace->ftFace();
612
                uint cl = FT_Get_Char_Index(face, c1);
613
                int error = FT_Load_Glyph(face, cl, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
614
                if (! error) {
615
                        double uniEM = static_cast<double>(face->units_per_EM);
616
                        w = face->glyph->metrics.horiBearingY / uniEM * (Size / 10.0);
617
                }
618
                else {
619
                        sDebug(QString("internal error: missing glyph: %1 (char %2) error=%3").arg(c1).arg(ch).arg(error));
620
                        w = Size / 10.0;
621
                }
622
                return w;
623
        }
624
        else
625
                return static_cast<double>(Size / 10.0);
626
}
627
 
628
double RealFHeight(ScribusDoc *, ScFace* scFace, int Size)
629
{
630
        FT_Face face = scFace->ftFace();
631
        double uniEM = static_cast<double>(face->units_per_EM);
632
        return face->height / uniEM * (Size / 10.0);
633
}
6125 cbradney 634
*/