Hello,

Pour mon projet actuel, je devais pouvoir charger une police à partir d'un fichier .TTF défini par l'utilisateur et s'en servir ensuite pour écrire du texte à l'écran avec DirectX.
Pas de problème :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
AddFontResource(myFontFile);
Ok, et maintenant comment je fais pour utiliser cette police ? Il me faut son nom (qui n'a parfoi rien avoir avec le nom du fichier)...

Google m'a indiqué un article bien sympatique : click !.
Mais la fonction décrite utilise MFC... C'est pas terrible.
J'ai donc dû la ré-écrire en utilisant uniquement la STL.
J'ai eu quelques soucis pour convertir les données :
  • bizarrement j'ai pas eu besoin de faire la conversion Big Endian -> Little Endian...
  • j'ai du me créer des fonctions perso pour lire correctement le fichier. Est-ce que j'ai ré-inventé la roue ? Parceque dans la version du lien, la fonction CFile::Read se chargeai de tout faire. Mais fsream::read ne retourne que des caractères...


Enfin bref, voilà le résultat. C'est pas forcément super clean, mais ça fonctionne bien :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#include <sstream>
#include <fstream>
#include <ios>
 
using namespace std;
 
//This is TTF file header
typedef struct _tagTT_OFFSET_TABLE
{
    unsigned short uMajorVersion;
    unsigned short uMinorVersion;
    unsigned short uNumOfTables;
    unsigned short uSearchRange;
    unsigned short uEntrySelector;
    unsigned short uRangeShift;
}TT_OFFSET_TABLE;
 
//Tables in TTF file and there placement and name (tag)
typedef struct _tagTT_TABLE_DIRECTORY
{
    char* szTag; //table name
    unsigned long uCheckSum; //Check sum
    unsigned long uOffset; //Offset from beginning of file
    unsigned long uLength; //length of the table in bytes
 
}TT_TABLE_DIRECTORY;
 
//Header of names table
typedef struct _tagTT_NAME_TABLE_HEADER
{
    unsigned short uFSelector; //format selector. Always 0
    unsigned short uNRCount; //Name Records count
    unsigned short uStorageOffset; //Offset for strings storage, from start of the table
 
}TT_NAME_TABLE_HEADER;
 
//Record in names table
typedef struct _tagTT_NAME_RECORD
{
    unsigned short uPlatformID;
    unsigned short uEncodingID;
    unsigned short uLanguageID;
    unsigned short uNameID;
    unsigned short uStringLength;
    unsigned short uStringOffset; //from start of storage area
 
}TT_NAME_RECORD;
 
string IntToHex( int i )
{
	if (i < 0) i = 256+i;
	char* c = new char[256];
	itoa(i, c, 16);
	string s = c;
	delete c;
 
	if (s.size() == 1)
		s = "0" + s;
	else if (s.size() == 0)
		s = "00";
 
	return s;
}
 
int HexToInt( const char* c )
{
	int i;
	i = strtol(c, NULL, 16);
 
	return i;
}
 
unsigned long HexToULong( const char* c )
{
	unsigned long u;
	stringstream iss;
	iss << c;
	iss >> std::hex >> u;
 
	return u;
}
 
void GetErrors(fstream* f)
{
	if (f->eof())
		prinft("#Error : end of file");
	if (f->bad())
		prinft("#Error : bad");
	else if (f->fail())
		prinft("#Error : fail");
}
 
unsigned short GetUSHORT(fstream* f, int* pos)
{
	if (f->good() && *pos != -1)
	{
		f->seekg(*pos);
		char* tmp = new char[256];
		f->read(tmp, sizeof(unsigned short));
		string s = "";
		int i1 = tmp[0]; int i2 = tmp[1];
		s += IntToHex(i1);
		s += IntToHex(i2);
		unsigned short u = HexToInt(s.c_str());
 
		*pos += sizeof(unsigned short);
 
		delete tmp;
 
		return u;
	}
	else
	{
		GetErrors(f);
		*pos = -1;
		return 0;
	}
}
 
unsigned long GetULONG(fstream* f, int* pos)
{
	if (f->good() && *pos != -1)
	{
		f->seekg(*pos);
		char* tmp = new char[256];
		f->read(tmp, sizeof(unsigned long));
		string s = "";
		int i1 = tmp[0]; int i2 = tmp[1];  int i3 = tmp[2];  int i4 = tmp[3];
		s += IntToHex(i1);
		s += IntToHex(i2);
		s += IntToHex(i3);
		s += IntToHex(i4);
		unsigned long u = HexToULong(s.c_str());
 
		*pos += sizeof(unsigned long);
 
		delete tmp;
 
		return u;
	}
	else
	{
		GetErrors(f);
		*pos = -1;
		return 0;
	}
}
 
string GetFontName(string lpszFilePath)
{
	fstream f(lpszFilePath.c_str(), ios::in | ios::binary);
	string csRetVal = "";
 
	//lpszFilePath is the path to our font file
	if (f.is_open())
	{
		//define and read file header
		TT_OFFSET_TABLE ttOffsetTable;
		int pos = ios::beg;
 
		ttOffsetTable.uMajorVersion = GetUSHORT(&f, &pos);
		ttOffsetTable.uMinorVersion = GetUSHORT(&f, &pos);
		ttOffsetTable.uNumOfTables = GetUSHORT(&f, &pos);
		ttOffsetTable.uSearchRange = GetUSHORT(&f, &pos);
		ttOffsetTable.uEntrySelector = GetUSHORT(&f, &pos);
		ttOffsetTable.uRangeShift = GetUSHORT(&f, &pos);
 
		if (pos == -1)
			return csRetVal;
 
		//check is this is a true type font and the version is 1.0
		if(ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0)
			return csRetVal;
 
		TT_TABLE_DIRECTORY tblDir;
		bool bFound = false;
		string csTemp;
 
		for (int i=0; i< ttOffsetTable.uNumOfTables; i++)
		{
   			tblDir.szTag = new char[4];
   			f.read(tblDir.szTag, sizeof(char[4]));
   			pos += sizeof(char[4]);
   			tblDir.uCheckSum = GetULONG(&f, &pos);
   			tblDir.uOffset = GetULONG(&f, &pos);
   			tblDir.uLength = GetULONG(&f, &pos);
 
   			if (pos == -1)
   				return csRetVal;
 
			//table's tag cannot exceed 4 characters
			csTemp = tblDir.szTag;
			csTemp.erase(4);
 
			delete tblDir.szTag;
 
			if (csTemp == "name")
			{
				//we found our table
				bFound = true;
				break;
			}
		}
 
		if (bFound)
		{
			//move to offset we got from Offsets Table
			pos = tblDir.uOffset;
			TT_NAME_TABLE_HEADER ttNTHeader;
			ttNTHeader.uFSelector = GetUSHORT(&f, &pos);
			ttNTHeader.uNRCount = GetUSHORT(&f, &pos);
			ttNTHeader.uStorageOffset = GetUSHORT(&f, &pos);
 
			if (pos == -1)
   				return csRetVal;
 
			TT_NAME_RECORD ttRecord;
			bFound = true;
			for (int i=0; i<ttNTHeader.uNRCount; i++)
			{
				ttRecord.uPlatformID = GetUSHORT(&f, &pos);
				ttRecord.uEncodingID = GetUSHORT(&f, &pos);
				ttRecord.uLanguageID = GetUSHORT(&f, &pos);
				ttRecord.uNameID = GetUSHORT(&f, &pos);
				ttRecord.uStringLength = GetUSHORT(&f, &pos);
				ttRecord.uStringOffset = GetUSHORT(&f, &pos);
 
				if (pos == -1)
   					return csRetVal;
 
				//1 says that this is font name. 0 for example determines copyright info
				if (ttRecord.uNameID == 1)
				{
					//save file position, so we can return to continue with search
					int nPos = f.tellg();
					f.seekg(tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset);
 
					char* lpszNameBuf = new char[ttRecord.uStringLength + 1];
					f.read(lpszNameBuf, ttRecord.uStringLength);
					csTemp = lpszNameBuf;
 
					//yes, still need to check if the font name is not empty
					//if it is, continue the search
					if (csTemp.length() > 0)
					{
						csRetVal = csTemp.erase(ttRecord.uStringLength);
						break;
					}
				}
			}
		}
	}
 
	return csRetVal;
}