2
* KFontInst - KDE Font Installer
4
* Copyright 2003-2007 Craig Drummond <craig@kde.org>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; see the file COPYING. If not, write to
20
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
* Boston, MA 02110-1301, USA.
25
// This class contains code inspired/copied/nicked from mkfontscale. Specifically
26
// the getName(), lookupName(), and the getFoundry() routines...
28
// mkfontscale's (C) notice is:
30
Copyright (c) 2002 by Juliusz Chroboczek
32
Permission is hereby granted, free of charge, to any person obtaining a copy
33
of this software and associated documentation files (the "Software"), to deal
34
in the Software without restriction, including without limitation the rights
35
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36
copies of the Software, and to permit persons to whom the Software is
37
furnished to do so, subject to the following conditions:
39
The above copyright notice and this permission notice shall be included in
40
all copies or substantial portions of the Software.
42
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
51
#include "FontEngine.h"
54
#include <KDE/KGlobal>
61
#include <sys/types.h>
65
#include FT_SFNT_NAMES_H
66
#include FT_TRUETYPE_IDS_H
67
#include FT_TRUETYPE_TABLES_H
68
#include FT_TYPE1_TABLES_H
69
#include <QtCore/QBuffer>
70
#include <QtCore/QTextStream>
75
static unsigned long ftStreamRead(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count)
77
QByteArray *in((QByteArray *)stream->descriptor.pointer);
79
if((offset+count)<=(unsigned long)in->size())
81
memcpy(buffer, &(in->data()[offset]), count);
88
static FT_Error openFtFace(FT_Library library, QByteArray &in, FT_Long index, FT_Face *face)
94
if(NULL==(stream=(FT_Stream)calloc(1, sizeof(*stream))))
95
return FT_Err_Out_Of_Memory;
97
stream->descriptor.pointer = ∈
98
stream->pathname.pointer = NULL;
99
stream->size = in.size();
102
stream->read = ftStreamRead;
103
args.flags = FT_OPEN_STREAM;
104
args.stream = stream;
106
error = FT_Open_Face(library, &args, index, face);
108
if (FT_Err_Ok!=error)
111
(*face)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
116
// TTF : 00 01 00 00 00 5
121
// Type1: %!PS-AdobeFont-1. 17
122
// : ?? ?? ?? ?? ?? ?? %!PS-AdobeFont-1. 23
123
// : %!FontType1-1. 14
124
// : ?? ?? ?? ?? ?? ?? %!FontType1-1. 20
127
// AFM : StartFontMetrics 16
128
// BDF : STARTFONT 20 10
130
static const int constHeaderLen=69;
132
CFontEngine::EType CFontEngine::getType(const char *fileName)
134
EType type(TYPE_UNKNOWN);
135
int fd=::open(fileName, O_RDONLY);
139
unsigned char header[constHeaderLen];
141
if(constHeaderLen==::read(fd, header, constHeaderLen))
142
type=getType(fileName, header);
149
CFontEngine::EType CFontEngine::getType(const char *fileName, Strigi::InputStream *in)
153
static const int constHeaderLen=69;
155
int n=in->read(h, constHeaderLen, constHeaderLen);
159
return getType(fileName, n==constHeaderLen ? (const unsigned char *)h : NULL);
162
CFontEngine::EType CFontEngine::getType(const char *fileName, const unsigned char *header)
166
if( (0x00==header[0] && 0x01==header[1] && 0x00==header[2] && 0x00==header[3] && 0x00==header[4]) ||
167
('F'==header[0] && 'F'==header[1] && 'I'==header[2] && 'L'==header[3]) ||
168
('F'==header[65] && 'F'==header[66] && 'I'==header[67] && 'L'==header[68]))
171
if('t'==header[0] && 't'==header[1] && 'c'==header[2] && 'f'==header[3])
174
if('O'==header[0] && 'T'==header[1] && 'T'==header[2] && 'O'==header[3])
177
if(0x01==header[0] && 'f'==header[1] && 'c'==header[2] && 'p'==header[3])
180
if(0==memcmp(header, "STARTFONT", 9) && 0x20==header[9])
183
if(0==memcmp(header, "%!PS-AdobeFont-1.", 17) ||
184
0==memcmp(&header[6], "%!PS-AdobeFont-1.", 17) ||
185
0==memcmp(header, "%!FontType1-1.", 14) ||
186
0==memcmp(&header[6], "%!FontType1-1.", 14) ||
187
('L'==header[0] && 'W'==header[1] && 'F'==header[2] && 'N'==header[3]) ||
188
('L'==header[65] && 'W'==header[66] && 'F'==header[67] && 'N'==header[68]))
191
if(0==memcmp(header, "StartFontMetrics", 16))
195
// Right mime 'magic' failed, try by extension...
196
if(Misc::checkExt(fileName, "ttf"))
199
if(Misc::checkExt(fileName, "ttc"))
202
if(Misc::checkExt(fileName, "otf"))
205
if(Misc::checkExt(fileName, "pfa") || Misc::checkExt(fileName, "pfb"))
209
// NOTE: Do not accept .gz extension - strigi will decompress for us.
210
if(Misc::checkExt(fileName, "pcf"))
213
if(Misc::checkExt(fileName, "bdf"))
216
if(Misc::checkExt(fileName, "afm"))
222
QString & CFontEngine::fixFoundry(QString &foundry)
224
// Try to make foundry similar to that of AFMs...
225
if(foundry==QString::fromLatin1("ibm"))
226
foundry=QString::fromLatin1("IBM");
227
else if(foundry==QString::fromLatin1("urw"))
228
foundry=QString::fromLatin1("URW");
229
else if(foundry==QString::fromLatin1("itc"))
230
foundry=QString::fromLatin1("ITC");
231
else if(foundry==QString::fromLatin1("nec"))
232
foundry=QString::fromLatin1("NEC");
233
else if(foundry==QString::fromLatin1("b&h"))
234
foundry=QString::fromLatin1("B&H");
237
QChar *ch(foundry.data());
238
int len(foundry.length());
246
isSpace=ch->isSpace();
254
bool CFontEngine::openFont(EType type, QByteArray &in, const char *fileName, int face)
260
itsWeight=FC_WEIGHT_MEDIUM;
261
itsWidth=FC_WIDTH_NORMAL;
262
itsSpacing=FC_PROPORTIONAL;
263
itsItalic=FC_SLANT_ROMAN;
264
itsFamily=itsFoundry=itsVersion=QString();
266
if(in.size()<=0 && fileName && TYPE_UNKNOWN==type)
267
type=getType(fileName); // Read file header to obtain type...
272
ok=openFontFt(in, fileName, face, TYPE_TYPE1==type);
274
#ifndef HAVE_FcFreeTypeQueryFace
291
void CFontEngine::closeFont()
295
FT_Done_Face(itsFt.face);
300
static int strToWeight(const QString &str)
303
return FC_WEIGHT_MEDIUM;
304
else if(str.contains("Bold", Qt::CaseInsensitive))
305
return FC_WEIGHT_BOLD;
306
else if(str.contains("Heavy", Qt::CaseInsensitive))
307
return FC_WEIGHT_HEAVY;
308
else if(str.contains("Black", Qt::CaseInsensitive))
309
return FC_WEIGHT_BLACK;
310
else if(str.contains("ExtraBold", Qt::CaseInsensitive))
311
return FC_WEIGHT_EXTRABOLD;
312
else if(str.contains("UltraBold", Qt::CaseInsensitive))
313
return FC_WEIGHT_ULTRABOLD;
314
else if(str.contains("ExtraLight", Qt::CaseInsensitive))
315
return FC_WEIGHT_EXTRALIGHT;
316
else if(str.contains("UltraLight", Qt::CaseInsensitive))
317
return FC_WEIGHT_ULTRALIGHT;
318
else if(str.contains("Light", Qt::CaseInsensitive))
319
return FC_WEIGHT_LIGHT;
320
else if(str.contains("Medium", Qt::CaseInsensitive) ||
321
str.contains("Normal", Qt::CaseInsensitive) ||
322
str.contains("Roman", Qt::CaseInsensitive))
323
return FC_WEIGHT_MEDIUM;
324
else if(str.contains("Regular", Qt::CaseInsensitive))
325
return FC_WEIGHT_REGULAR;
326
else if(str.contains("SemiBold", Qt::CaseInsensitive))
327
return FC_WEIGHT_SEMIBOLD;
328
else if(str.contains("DemiBold", Qt::CaseInsensitive))
329
return FC_WEIGHT_DEMIBOLD;
330
else if(str.contains("Thin", Qt::CaseInsensitive))
331
return FC_WEIGHT_THIN;
332
else if(str.contains("Book", Qt::CaseInsensitive))
333
return FC_WEIGHT_NORMAL;
334
else if(str.contains("Demi", Qt::CaseInsensitive))
335
return FC_WEIGHT_NORMAL;
337
return FC_WEIGHT_MEDIUM;
340
static int strToWidth(const QString &str)
343
return KFI_FC_WIDTH_NORMAL;
344
else if(str.contains("UltraCondensed", Qt::CaseInsensitive))
345
return KFI_FC_WIDTH_ULTRACONDENSED;
346
else if(str.contains("ExtraCondensed", Qt::CaseInsensitive))
347
return KFI_FC_WIDTH_EXTRACONDENSED;
348
else if(str.contains("SemiCondensed", Qt::CaseInsensitive))
349
return KFI_FC_WIDTH_SEMICONDENSED;
350
else if(str.contains("Condensed", Qt::CaseInsensitive))
351
return KFI_FC_WIDTH_CONDENSED;
352
else if(str.contains("SemiExpanded", Qt::CaseInsensitive))
353
return KFI_FC_WIDTH_SEMIEXPANDED;
354
else if(str.contains("UltraExpanded", Qt::CaseInsensitive))
355
return KFI_FC_WIDTH_ULTRAEXPANDED;
356
else if(str.contains("ExtraExpanded", Qt::CaseInsensitive))
357
return KFI_FC_WIDTH_EXTRAEXPANDED;
358
else if(str.contains("Expanded", Qt::CaseInsensitive))
359
return KFI_FC_WIDTH_EXPANDED;
361
return KFI_FC_WIDTH_NORMAL;
364
static int checkItalic(int it, const QString &full)
366
return (FC_SLANT_ITALIC==it && (-1!=full.indexOf("Oblique") || -1!=full.indexOf("Slanted")))
371
static const char * getFoundry(const char *notice)
375
const char *noticeStr,
379
static const Map map[]=
383
{ "Bitstream", "Bitstream"},
384
{ "Monotype", "Monotype"},
385
{ "Linotype", "Linotype"},
386
{ "LINOTYPE-HELL", "Linotype"},
389
{ "International Typeface Corporation", "ITC"},
390
{ "Tiro Typeworks", "Tiro"},
391
{ "XFree86", "XFree86"},
392
{ "Microsoft", "Microsoft"},
395
{ "HanYang System", "Hanyang"},
402
for(entry=map; NULL!=entry->foundry; entry++)
403
if(strstr(notice, entry->noticeStr)!=NULL)
404
return entry->foundry;
409
#ifndef HAVE_FcFreeTypeQueryFace
410
static bool lookupName(FT_Face face, int nid, int pid, int eid, FT_SfntName *nameReturn)
412
int n = FT_Get_Sfnt_Name_Count(face);
420
if(0==FT_Get_Sfnt_Name(face, i, &name) && name.name_id == nid && name.platform_id == pid &&
421
(eid < 0 || name.encoding_id == eid))
423
switch(name.platform_id)
425
case TT_PLATFORM_APPLE_UNICODE:
426
case TT_PLATFORM_MACINTOSH:
427
if(name.language_id != TT_MAC_LANGID_ENGLISH)
430
case TT_PLATFORM_MICROSOFT:
431
if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES &&
432
name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM)
439
if(name.string_len > 0)
450
static QByteArray getName(FT_Face face, int nid)
455
if(lookupName(face, nid, TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) ||
456
lookupName(face, nid, TT_PLATFORM_APPLE_UNICODE, -1, &name))
457
for(unsigned int i=0; i < name.string_len / 2; i++)
458
str+=0 == name.string[2*i] ? name.string[(2*i)+1] : '_';
459
else if(lookupName(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, &name)) // Pretend that Apple Roman is ISO 8859-1
460
for(unsigned int i=0; i < name.string_len; i++)
466
static const char * getFoundry(const FT_Face face, TT_OS2 *os2)
470
const char *vendorId,
474
static const int constVendLen=4;
476
// These are taken from ttmkfdir
477
static const Map map[]=
484
{ "ATEC", "Alltype"},
486
{ "BITS", "Bitstream"},
488
{ "DYNA", "DynaLab"},
493
{ "IMPR", "Impress"},
494
{ "LARA", "Larabie"},
495
{ "LEAF", "Interleaf"},
496
{ "LETR", "letraset"},
497
{ "LINO", "Linotype"},
498
{ "MACR", "Macromedia"},
499
{ "MONO", "Monotype"},
500
{ "MS", "Microsoft"},
503
{ "PARA", "ParaType"},
511
static char vendor[constVendLen+1];
515
if(NULL!=os2 && 0xFFFF!=os2->version)
518
char vend[constVendLen+1];
520
strncpy(vendor, (const char *)(os2->achVendID), constVendLen);
521
vendor[constVendLen]='\0';
523
for(int i=0; i<constVendLen; ++i)
524
vend[i]=toupper(vendor[i]);
526
for(entry=map; NULL!=entry->vendorId; entry++)
528
unsigned int len=strlen(entry->vendorId);
530
if(0==memcmp(entry->vendorId, vend, len))
534
for(int i=len; i<constVendLen && ok; i++)
535
if(vend[i]!=' ' && entry->vendorId[i]!='\0')
539
return entry->foundry;
544
const char *foundry=NULL;
547
foundry=getFoundry(getName(face, TT_NAME_ID_TRADEMARK));
550
foundry=getFoundry(getName(face, TT_NAME_ID_MANUFACTURER));
552
if(!foundry && vendor[0] && !isspace(vendor[0]) && '-'!=vendor[0]) // Some fonts have a totally blank vendor field
556
// Remove any dashes...
557
for(int i=constVendLen-1; i>0; i--)
561
// Strip any trailing whitepace
562
for(i=constVendLen-1; i>0; i--)
563
if(isspace(vendor[i]))
575
bool CFontEngine::openFontFt(QByteArray &in, const char *fileName, int face, bool type1)
577
bool status=in.size()<=0
578
? FT_New_Face(itsFt.library, fileName, face, &itsFt.face) ? false : true
579
: openFtFace(itsFt.library, in, face, &itsFt.face) ? false : true;
586
PS_FontInfoRec t1info;
589
FT_Get_PS_Font_Info(itsFt.face, &t1info);
591
#ifdef HAVE_FcFreeTypeQueryFace
592
FcPattern *pat=FcFreeTypeQueryFace(itsFt.face, (FcChar8*) fileName, face, NULL);
594
itsWeight=FC_WEIGHT_REGULAR;
595
itsWidth=KFI_FC_WIDTH_NORMAL;
596
itsSpacing=FC_PROPORTIONAL;
600
itsFamily=FC::getFcString(pat, FC_FAMILY, face);
601
FcPatternGetInteger(pat, FC_WEIGHT, face, &itsWeight);
602
#ifndef KFI_FC_NO_WIDTHS
603
FcPatternGetInteger(pat, FC_WIDTH, face, &itsWidth);
605
FcPatternGetInteger(pat, FC_SLANT, face, &itsItalic);
606
FcPatternGetInteger(pat, FC_SPACING, face, &itsSpacing);
607
itsFoundry=FC::getFcString(pat, FC_FOUNDRY, face);
610
itsVersion=t1info.version;
615
FcPatternGetInteger(pat, FC_FONTVERSION, face, &version);
617
itsVersion.setNum(decodeFixed(version));
620
FcPatternDestroy(pat);
621
fixFoundry(itsFoundry);
630
TTF_WIDTH_ULTRA_CONDENSED = 1,
631
TTF_WIDTH_EXTRA_CONDENSED = 2,
632
TTF_WIDTH_CONDENSED = 3,
633
TTF_WIDTH_SEMI_CONDENSED = 4,
634
TTF_WIDTH_NORMAL = 5,
635
TTF_WIDTH_SEMI_EXPANDED = 6,
636
TTF_WIDTH_EXPANDED = 7,
637
TTF_WIDTH_EXTRA_EXPANDED = 8,
638
TTF_WIDTH_ULTRA_EXPANDED = 9
645
fullName=t1info.full_name;
646
itsFamily=t1info.family_name;
650
fullName=getName(itsFt.face, TT_NAME_ID_FULL_NAME);
651
itsFamily=getName(itsFt.face, TT_NAME_ID_FONT_FAMILY);
654
if(itsFamily.isEmpty())
655
if(fullName.isEmpty())
656
itsFamily=fullName=FT_Get_Postscript_Name(itsFt.face);
660
if(fullName.isEmpty())
663
if(fullName.isEmpty())
664
status=false; // Hmm... couldn't find any of the names!
670
itsWeight=strToWeight(t1info.weight);
671
itsItalic=t1info.italic_angle <= -4 || t1info.italic_angle >= 4 ? FC_SLANT_ITALIC : FC_SLANT_ROMAN;
672
itsWidth=strToWidth(fullName);
673
itsItalic=checkItalic(itsItalic, fullName);
674
itsSpacing=t1info.is_fixed_pitch ? FC_MONO : FC_PROPORTIONAL;
675
itsFoundry=KFI::getFoundry(t1info.notice);
676
itsVersion=t1info.version;
680
#define WEIGHT_UNKNOWN 0xFFFF
681
#define WIDTH_UNKNOWN 0xFFFF
683
TT_Postscript *post=(TT_Postscript *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_post);
684
TT_OS2 *os2=(TT_OS2 *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_os2);
685
TT_Header *head=(TT_Header *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_head);
686
bool gotItalic=false;
688
itsWidth=WIDTH_UNKNOWN;
689
itsWeight=WEIGHT_UNKNOWN;
691
if(NULL!=os2 && 0xFFFF!=os2->version)
693
if (os2->usWeightClass == 0)
695
else if (os2->usWeightClass < 150)
696
itsWeight=FC_WEIGHT_THIN;
697
else if (os2->usWeightClass < 250)
698
itsWeight=FC_WEIGHT_EXTRALIGHT;
699
else if (os2->usWeightClass < 350)
700
itsWeight=FC_WEIGHT_LIGHT;
701
else if (os2->usWeightClass < 450)
702
itsWeight=FC_WEIGHT_REGULAR;
703
else if (os2->usWeightClass < 550)
704
itsWeight=FC_WEIGHT_MEDIUM;
705
else if (os2->usWeightClass < 650)
706
itsWeight=FC_WEIGHT_SEMIBOLD;
707
else if (os2->usWeightClass < 750)
708
itsWeight=FC_WEIGHT_BOLD;
709
else if (os2->usWeightClass < 850)
710
itsWeight=FC_WEIGHT_EXTRABOLD;
711
else if (os2->usWeightClass < 950)
712
itsWeight=FC_WEIGHT_BLACK;
714
switch(os2->usWidthClass)
716
case TTF_WIDTH_ULTRA_CONDENSED:
717
itsWidth=FC_WIDTH_ULTRACONDENSED;
719
case TTF_WIDTH_EXTRA_CONDENSED:
720
itsWidth=FC_WIDTH_EXTRACONDENSED;
722
case TTF_WIDTH_CONDENSED:
723
itsWidth=FC_WIDTH_CONDENSED;
725
case TTF_WIDTH_SEMI_CONDENSED:
726
itsWidth=FC_WIDTH_SEMICONDENSED;
728
case TTF_WIDTH_NORMAL:
729
itsWidth=FC_WIDTH_NORMAL;
731
case TTF_WIDTH_SEMI_EXPANDED:
732
itsWidth=FC_WIDTH_SEMIEXPANDED;
734
case TTF_WIDTH_EXPANDED:
735
itsWidth=FC_WIDTH_EXPANDED;
737
case TTF_WIDTH_EXTRA_EXPANDED:
738
itsWidth=FC_WIDTH_EXTRAEXPANDED;
740
case TTF_WIDTH_ULTRA_EXPANDED:
741
itsWidth=FC_WIDTH_ULTRAEXPANDED;
745
itsItalic=os2->fsSelection&(1 << 0) ? FC_SLANT_ITALIC : FC_SLANT_ROMAN;
749
if(WEIGHT_UNKNOWN==itsWeight)
750
itsWeight=itsFt.face->style_flags&FT_STYLE_FLAG_BOLD
754
if(WIDTH_UNKNOWN==itsWidth)
755
itsWidth=FC_WIDTH_NORMAL;
757
if(!gotItalic && head!=NULL)
760
itsItalic=head->Mac_Style & 2 ? FC_SLANT_ITALIC : FC_SLANT_ROMAN;
765
double version=decodeFixed(head->Font_Revision);
768
itsVersion.setNum(version);
771
if(!gotItalic && NULL!=post)
774
itsItalic=0.0f==decodeFixed(post->italicAngle) ? FC_SLANT_ROMAN : FC_SLANT_ITALIC;
777
itsItalic=checkItalic(itsItalic, fullName);
779
if(NULL!=post && post->isFixedPitch)
781
TT_HoriHeader *hhea=NULL;
783
if(NULL!=(hhea=(TT_HoriHeader *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_hhea)) &&
784
hhea->min_Left_Side_Bearing >= 0 && hhea->xMax_Extent <= hhea->advance_Width_Max)
785
itsSpacing=FC_CHARCELL;
790
itsSpacing=FC_PROPORTIONAL;
792
itsFoundry=KFI::getFoundry(itsFt.face, os2);
803
bool CFontEngine::openFontAfm(QByteArray &in)
805
bool inMetrics=false;
807
QTextStream ds(&in, QIODevice::ReadOnly);
811
QString line(ds.readLine());
812
line=line.simplified();
816
if(0==line.indexOf("FullName "))
819
itsWidth=strToWidth(full);
821
else if(0==line.indexOf("FamilyName "))
822
itsFamily=line.mid(11);
823
else if(0==line.indexOf("Weight "))
824
itsWeight=strToWeight(line.mid(7));
825
else if(0==line.indexOf("ItalicAngle "))
826
itsItalic=0.0f==line.mid(12).toFloat() ? FC_SLANT_ROMAN : FC_SLANT_ITALIC;
827
else if(0==line.indexOf("IsFixedPitch "))
828
itsSpacing= ( line.mid(13).contains("false", Qt::CaseInsensitive)
829
? FC_PROPORTIONAL : FC_MONO );
830
else if(0==line.indexOf("Notice "))
831
itsFoundry=KFI::getFoundry(line.mid(7).toLatin1());
832
else if(0==line.indexOf("Version "))
833
itsVersion=line.mid(8);
834
else if(0==line.indexOf("StartCharMetrics"))
838
if(0==line.indexOf("StartFontMetrics"))
842
if(itsFamily.isEmpty() && !full.isEmpty())
845
checkItalic(itsItalic, full);
847
return !full.isEmpty() && !itsFamily.isEmpty();
850
#ifndef HAVE_FcFreeTypeQueryFace
851
static int charToItalic(char c)
857
return FC_SLANT_ITALIC;
860
return FC_SLANT_OBLIQUE;
864
return FC_SLANT_ROMAN;
868
static int charToSpacing(char c)
881
return FC_PROPORTIONAL;
885
void CFontEngine::parseXlfdBmp(const QString &xlfd)
910
// -foundry-family-weight-slant-width-?-pixelSize-pointSize-resX-resY-spacing-avWidth-csReg-csEnc
911
for(entry=XLFD_FOUNDRY; -1!=(pos=xlfd.indexOf('-', pos+1)) && entry<XLFD_END; ++entry)
918
itsFoundry=xlfd.mid(oldPos, pos-oldPos);
921
itsFamily=xlfd.mid(oldPos, pos-oldPos);
924
itsWeight=strToWeight(xlfd.mid(oldPos, pos-oldPos).toLocal8Bit());
928
itsItalic=charToItalic(xlfd[pos-1].toLatin1());
931
itsWidth=strToWidth(xlfd.mid(oldPos, pos-oldPos));
934
case XLFD_PIXEL_SIZE:
935
case XLFD_POINT_SIZE:
941
itsSpacing=charToSpacing(xlfd[pos-1].toLatin1());
952
bool CFontEngine::openFontBdf(QByteArray &in)
954
QTextStream ds(&in, QIODevice::ReadOnly);
956
ds.readLine(); // Skip 1st line.
959
QString line(ds.readLine());
961
if(0==line.indexOf("FONT ", Qt::CaseInsensitive))
963
parseXlfdBmp(line.mid(5));
971
static unsigned int readLsb32(QBuffer &in)
973
unsigned char num[4];
975
return 4==in.read((char *)num, 4)
976
? (num[0])+(num[1]<<8)+(num[2]<<16)+(num[3]<<24)
980
static unsigned int read32(QBuffer &in, bool msb)
984
unsigned char num[4];
986
return 4==in.read((char *)num, 4)
987
? (num[0]<<24)+(num[1]<<16)+(num[2]<<8)+(num[3])
991
return readLsb32(in);
994
static const unsigned int constBitmapMaxProps=1024;
996
bool CFontEngine::openFontPcf(QByteArray &in)
998
bool foundXlfd=false;
999
const unsigned int contPcfVersion=(('p'<<24)|('c'<<16)|('f'<<8)|1);
1003
buf.open(QIODevice::ReadOnly);
1005
if(contPcfVersion==readLsb32(buf))
1007
const unsigned int constPropertiesType=1;
1009
unsigned int numTables=readLsb32(buf),
1016
for(table=0; table<numTables && !buf.atEnd() && !foundXlfd; ++table)
1018
type=readLsb32(buf);
1019
format=readLsb32(buf);
1020
size=readLsb32(buf);
1021
offset=readLsb32(buf);
1022
if(constPropertiesType==type)
1024
if(buf.seek(offset))
1026
const unsigned int constFormatMask=0xffffff00;
1028
format=readLsb32(buf);
1029
if(0==(format&constFormatMask))
1031
const unsigned int constByteMask=0x4;
1033
bool msb=format&constByteMask;
1034
unsigned int numProps=read32(buf, msb);
1036
if(numProps>0 && numProps<constBitmapMaxProps)
1038
unsigned int strSize,
1046
} *props=new struct TProp [numProps];
1051
unsigned short prop;
1053
for(prop=0; prop<numProps; ++prop)
1055
props[prop].name=read32(buf, msb);
1057
props[prop].isString=tmp ? true : false;
1058
props[prop].value=read32(buf, msb);
1061
skip=4-((numProps*9)%4);
1063
buf.seek(buf.pos()+skip);
1065
strSize=read32(buf, msb);
1069
QByteArray str=buf.read(strSize);
1071
if(str.size()==(int)strSize)
1073
// Finally we have the data............
1074
const int constMaxStrLen=1024;
1076
char tmp[constMaxStrLen];
1078
for(prop=0; prop<numProps && !foundXlfd; ++prop)
1079
if(kasciistricmp(&(str.data()[props[prop].name]), "FONT")==0)
1081
if(props[prop].isString && strlen(&(str.data()[props[prop].value])))
1084
strncpy(tmp, &(str.data()[props[prop].value]), constMaxStrLen);
1085
tmp[constMaxStrLen-1]='\0';
1097
break; // Forget the other tables...
1106
CFontEngine::TFtData::TFtData()
1109
if(FT_Init_FreeType(&library))
1111
std::cerr << "ERROR: FreeType2 failed to initialise\n";
1116
CFontEngine::TFtData::~TFtData()
1118
FT_Done_FreeType(library);