source: trunk/src/gdi32/fontres.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 18.6 KB
Line 
1/* $Id: fontres.cpp,v 1.1 2004-01-11 11:42:13 sandervl Exp $ */
2
3
4/*
5 * GDI32 font apis
6 *
7 * Copyright 2003 Sander van Leeuwen (sandervl@innotek.de)
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13/*****************************************************************************
14 * Includes *
15 *****************************************************************************/
16
17#include <odin.h>
18#include <odinwrap.h>
19#include <os2sel.h>
20
21#include <os2win.h>
22#include <stdlib.h>
23#include <stdarg.h>
24#include <ctype.h>
25#include <string.h>
26#include <dbglog.h>
27#include <unicode.h>
28#include <heapstring.h>
29#include <neexe.h>
30#include <objhandle.h>
31#include <font.h>
32#include <vmutex.h>
33#include "ft2supp.h"
34
35#include "oslibgpi.h"
36
37#define DBG_LOCALLOG DBG_fontres
38#include "dbglocal.h"
39
40#define TESTFONT_RESNAME "TESTFONT"
41
42//just picking a reasonable maximum; don't want to mess with linked lists
43#define MAX_PUBLICFONTS 32
44
45typedef struct {
46 char szFaceName[32];
47 char szFontResName[260];
48 char szFileName[260];
49 char *pFontData;
50 DWORD dwFontSize;
51} SCALABLEFONTS;
52
53
54static SCALABLEFONTS *publicfonts = NULL;
55static VMutex fntmutex;
56
57#define FntLock() fntmutex.enter()
58#define FntUnlock() fntmutex.leave()
59
60
61//******************************************************************************
62// Remember the font filename for GetFontData if this is a font previously
63// registered with AddFontResource
64//******************************************************************************
65BOOL RegisterFont(HFONT hFont, LPSTR lfFaceName)
66{
67 if(!publicfonts) {
68 return FALSE;
69 }
70
71 FntLock();
72 int i;
73 for(i=0;i<MAX_PUBLICFONTS;i++) {
74 if(strcmp(publicfonts[i].szFaceName, lfFaceName) == 0) {
75#ifdef DEBUG
76 dprintf(("Remember font file %s for font %x", publicfonts[i].szFileName, hFont));
77 if(GetFileAttributesA(publicfonts[i].szFileName) == -1) {
78 dprintf(("ERROR: font file does not exist anymore!!!!!!"));
79 }
80#endif
81 ObjSetHandleGDI32Data(hFont, HNDL_FONT, (DWORD)&publicfonts[i]);
82 break;
83 }
84 }
85 FntUnlock();
86 if(i == MAX_PUBLICFONTS) {
87 return FALSE;
88 }
89 return TRUE;
90}
91//******************************************************************************
92//******************************************************************************
93static LPVOID ReadEntireFile(LPSTR lpszFileName, DWORD *lpdwSize = NULL)
94{
95 HFILE hFile = INVALID_HANDLE_VALUE;
96
97 DWORD dwSize, dwBytesRead, ret;
98 LPVOID lpFileData = NULL;
99
100 hFile = CreateFileA(lpszFileName,
101 GENERIC_READ,
102 FILE_SHARE_READ | FILE_SHARE_WRITE,
103 NULL,
104 OPEN_EXISTING,
105 0,
106 NULL);
107
108 if(hFile == INVALID_HANDLE_VALUE) {
109 DebugInt3();
110 goto failure;
111 }
112 //determine filesize
113 dwSize = SetFilePointer(hFile, 0, NULL, FILE_END);
114 SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
115
116 //allocate memory to hold the entire file
117 lpFileData = (char *)malloc(dwSize);
118 if(lpFileData == NULL) {
119 DebugInt3();
120 goto failure;
121 }
122 //and read it
123 ret = ReadFile(hFile, lpFileData, dwSize, &dwBytesRead, NULL);
124 if(ret == FALSE || dwBytesRead != dwSize) {
125 DebugInt3();
126 goto failure;
127 }
128 if(lpdwSize) *lpdwSize = dwSize;
129
130 CloseHandle(hFile);
131 return lpFileData;
132
133failure:
134 if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
135 if(lpFileData) free(lpFileData);
136 return NULL;
137}
138//******************************************************************************
139//******************************************************************************
140DWORD WIN32API GetFontData(HDC hdc, DWORD dwTable,
141 DWORD dwOffset,
142 LPVOID lpvBuffer,
143 DWORD cbData)
144{
145 HFONT hFont;
146 SCALABLEFONTS *font;
147
148 dprintf(("GDI32: GetFontData, partially implemented"));
149
150 hFont = GetCurrentObject(hdc, OBJ_FONT);
151 if(hFont == 0) {
152 SetLastError(ERROR_INVALID_PARAMETER);
153 return GDI_ERROR;
154 }
155 font = (SCALABLEFONTS *)ObjQueryHandleGDI32Data(hFont, HNDL_FONT);
156 if(font == NULL) {
157 return FT2Module.Ft2GetFontData(hdc, dwTable, dwOffset, lpvBuffer, cbData);
158 }
159
160 if(font->pFontData == NULL)
161 {
162 font->pFontData = (char *)ReadEntireFile(font->szFileName, &font->dwFontSize);
163 if(!font->pFontData) return GDI_ERROR;
164 }
165
166 cbData = min(cbData, font->dwFontSize);
167 if(dwTable == 0 && dwOffset == 0) {
168 if(lpvBuffer == NULL) return font->dwFontSize;
169
170 memcpy(lpvBuffer, font->pFontData, cbData);
171 return cbData;
172 }
173
174 //todo: parse TTF structure (haven't seen anybody rely on that yet)
175
176 return(GDI_ERROR);
177}
178//******************************************************************************
179//TODO: supposed to support more than only .fon files
180//******************************************************************************
181int WIN32API AddFontResourceA(LPCSTR szFont)
182{
183 DWORD ret, alignment, nrFonts, fontOrdinal, i;
184 PIMAGE_DOS_HEADER pDosHdr = NULL;
185 PIMAGE_OS2_HEADER pNEHdr;
186 struct resource_typeinfo_s *pResInfo;
187 struct resource_nameinfo_s *pNameInfo;
188 LPFONTDIR16 pFontDir = NULL;
189 char *pFontNameId;
190 char *pResNameTable;
191 char *pFontPath, *newname = NULL, *extension;
192 char szFamily[32], szFace[32];
193
194 dprintf(("GDI32: AddFontResourceA %s", szFont));
195
196 if(GetFileAttributesA(szFont) == -1) {
197 dprintf(("WARNING: Font res file doesn't exists"));
198 SetLastError(ERROR_INVALID_PARAMETER);
199 return FALSE;
200 }
201
202 //Support for raw .ttf files as well
203 newname = strupr(strdup(szFont));
204 extension = strrchr(newname, '.');
205 if (!strcmp(extension, ".TTF"))
206 {
207 //get font family and face names
208 OSLibGpiQueryFontName(newname, szFamily, szFace, sizeof(szFamily));
209 }
210 else
211 {
212 pDosHdr = (PIMAGE_DOS_HEADER)ReadEntireFile((LPSTR)szFont);
213 if(!pDosHdr) return FALSE;
214
215 pNEHdr = (PIMAGE_OS2_HEADER) ((char *)pDosHdr + pDosHdr->e_lfanew);
216 if(pDosHdr->e_magic != IMAGE_DOS_SIGNATURE ||
217 pNEHdr->ne_magic != IMAGE_OS2_SIGNATURE) {
218 dprintf(("Unknown file format"));
219 goto failure;
220 }
221
222 pResInfo = (struct resource_typeinfo_s *)((char *)pNEHdr + pNEHdr->ne_rsrctab);
223 alignment = *(WORD *)pResInfo;
224 pResInfo = (struct resource_typeinfo_s *)((char *)pResInfo+sizeof(WORD));
225
226 //first resource is a font directory
227 if(pResInfo->type_id != NE_RSCTYPE_FONTDIR && pResInfo->count != 1) {
228 dprintf(("Unknown file format"));
229 goto failure;
230 }
231 pNameInfo = (struct resource_nameinfo_s *)(pResInfo+1);
232 pFontDir = (LPFONTDIR16)((char *)pDosHdr + (pNameInfo->offset << alignment));
233 //first word = length followed by the string (not terminated)
234 pFontNameId = (char *)pResInfo - sizeof(WORD) + pNameInfo->id;
235
236 nrFonts = *(WORD *)pFontDir;
237 fontOrdinal = *((WORD *)pFontDir+1);
238 pFontDir = (LPFONTDIR16)((char *)pFontDir + 2*sizeof(WORD));
239
240 pResNameTable = (char *)pNEHdr + pNEHdr->ne_restab;
241
242 //second resource is the absolute path of the TTF file
243 pResInfo = (struct resource_typeinfo_s *)(pNameInfo+1);
244 if(pResInfo->type_id != 0x80CC && pResInfo->count != 1) {
245 dprintf(("Unknown file format"));
246 goto failure;
247 }
248 pNameInfo = (struct resource_nameinfo_s *)(pResInfo+1);
249 pFontPath = ((char *)pDosHdr + (pNameInfo->offset << alignment));
250
251 free(newname);
252
253 //GPI makes assumptions about the file based on the extention (d'oh)
254 newname = strdup(pFontPath);
255 extension = strrchr(newname, '.');
256
257 strcpy(extension, ".TTF");
258 CopyFileA(pFontPath, newname, FALSE);
259 }
260
261 //Load the TrueType font
262 ret = OSLibGpiLoadFonts(newname);
263 if(ret == FALSE) {
264 dprintf(("OSLibGpiLoadFonts %s failed!!", pFontPath));
265 goto failure;
266 }
267
268 //add to the list of known public fonts that we added before
269 if(publicfonts == NULL) {
270 publicfonts = (SCALABLEFONTS*)malloc(MAX_PUBLICFONTS*sizeof(SCALABLEFONTS));
271 if(publicfonts == NULL) {
272 DebugInt3();
273 goto failure;
274 }
275 memset(publicfonts, 0, MAX_PUBLICFONTS*sizeof(SCALABLEFONTS));
276 }
277 FntLock();
278 for(i=0;i<MAX_PUBLICFONTS;i++) {
279 if(publicfonts[i].szFaceName[0] == 0) {
280 break;
281 }
282 }
283 if(i == MAX_PUBLICFONTS) {
284 FntUnlock();
285 DebugInt3();
286 goto failure;
287 }
288 strncpy(publicfonts[i].szFileName, newname, sizeof(publicfonts[i].szFileName));
289 if (pFontDir)
290 strncpy(publicfonts[i].szFaceName, pFontDir->szDeviceName, sizeof(publicfonts[i].szFaceName));
291 else
292 strncpy(publicfonts[i].szFaceName, szFace, sizeof(publicfonts[i].szFaceName));
293 strncpy(publicfonts[i].szFontResName, szFont, sizeof(publicfonts[i].szFontResName));
294 publicfonts[i].pFontData = NULL;
295 FntUnlock();
296
297 free(newname);
298 free(pDosHdr);
299 return 1;
300
301failure:
302 if(pDosHdr) free(pDosHdr);
303 if(newname) free(newname);
304 return 0;
305}
306//******************************************************************************
307//******************************************************************************
308int WIN32API AddFontResourceW(LPCWSTR szFont)
309{
310 char *astring = UnicodeToAsciiString((LPWSTR)szFont);
311 int ret;
312
313 dprintf(("GDI32: AddFontResourceW"));
314 ret = AddFontResourceA(astring);
315 FreeAsciiString(astring);
316 return ret;
317}
318//******************************************************************************
319//******************************************************************************
320BOOL WIN32API RemoveFontResourceA(LPCSTR lpszFont)
321{
322 BOOL ret;
323
324 dprintf(("GDI32: RemoveFontResourceA %s", lpszFont));
325
326 if(!publicfonts) {
327 dprintf(("WARNING: font not found in our list!!"));
328 return FALSE;
329 }
330 FntLock();
331 int i;
332 for(i=0;i<MAX_PUBLICFONTS;i++) {
333 if(strcmp(publicfonts[i].szFontResName, lpszFont) == 0)
334 {
335 ret = OSLibGpiUnloadFonts(publicfonts[i].szFileName);
336 DeleteFileA(publicfonts[i].szFileName);
337
338 if(publicfonts[i].pFontData) free(publicfonts[i].pFontData);
339 publicfonts[i].pFontData = 0;
340 publicfonts[i].szFileName[0] = 0;
341 publicfonts[i].szFaceName[0] = 0;
342 break;
343 }
344 }
345 FntUnlock();
346 if(i == MAX_PUBLICFONTS) {
347 dprintf(("WARNING: font not found in our list!!"));
348// no need to trap on a warning DebugInt3();
349 return FALSE;
350 }
351 return ret;
352}
353//******************************************************************************
354//******************************************************************************
355BOOL WIN32API RemoveFontResourceW(LPCWSTR szFont)
356{
357 char *astring = UnicodeToAsciiString((LPWSTR)szFont);
358 BOOL ret;
359
360 dprintf(("GDI32: RemoveFontResourceW"));
361 ret = RemoveFontResourceA(astring);
362 FreeAsciiString(astring);
363 return ret;
364}
365/*****************************************************************************
366 * Name : BOOL CreateScalableFontResourceA
367 * Purpose : The CreateScalableFontResourceA function creates a font resource
368 * file for a scalable font.
369 * Parameters: DWORD fdwHidden flag for read-only embedded font
370 * LPCSTR lpszFontRes address of filename for font resource
371 * LPCSTR lpszFontFile address of filename for scalable font
372 * LPCSTR lpszCurrentPath address of path to font file
373 * Variables :
374 * Result : TRUE / FALSE
375 * Remark :
376 * Status : UNTESTED STUB
377 *
378 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
379 *****************************************************************************/
380
381BOOL WIN32API CreateScalableFontResourceA(DWORD fdwHidden,
382 LPCSTR lpszFontRes,
383 LPCSTR lpszFontFile,
384 LPCSTR lpszCurrentPath)
385{
386 HRSRC hRsrc;
387 HINSTANCE hGdi32;
388 HGLOBAL handle;
389 DWORD dwSize;
390 LPVOID lpData, lpCopy = NULL;
391 HANDLE hFile = 0;
392 DWORD ret, dwBytesWritten, alignment, nrFonts, fontOrdinal, len;
393 PIMAGE_DOS_HEADER pDosHdr;
394 PIMAGE_OS2_HEADER pNEHdr;
395 struct resource_typeinfo_s *pResInfo;
396 struct resource_nameinfo_s *pNameInfo;
397 LPFONTDIR16 pFontDir;
398 char *pFontNameId;
399 char *pResNameTable;
400 char *pFontPath, *newname, *extension;
401 char szFamily[32], szFace[32];
402
403 dprintf(("GDI32: CreateScalableFontResourceA %x %s %s %s partly implemented", fdwHidden, lpszFontRes, lpszFontFile, lpszCurrentPath));
404
405 if(lpszCurrentPath != NULL) {
406 //figure out which possibilities exist
407 DebugInt3();
408 return FALSE;
409 }
410
411 //This function is supposed to create a font resource file (.fot; NE dll with
412 //references to the TTF file (absolute path))
413
414 if(GetFileAttributesA(lpszFontRes) != -1) {
415 dprintf(("WARNING: Font res file already exists"));
416 SetLastError(ERROR_INVALID_PARAMETER);
417 return FALSE;
418 }
419
420 //fetch our font resource file example
421 hGdi32 = GetModuleHandleA("GDI32");
422 hRsrc = FindResourceA( hGdi32, TESTFONT_RESNAME, RT_RCDATAA );
423 if(!hRsrc) {
424 dprintf(("WARNING: Test font file resource not found!!"));
425 DebugInt3();
426 return FALSE;
427 }
428 handle = LoadResource(hGdi32, hRsrc);
429 dwSize = SizeofResource(hGdi32, hRsrc);
430 lpData = LockResource(handle);
431 if(!dwSize || !handle || !lpData) {
432 dprintf(("WARNING: Test font file resource not loaded/locked!!"));
433 DebugInt3();
434 return FALSE;
435 }
436 lpCopy = malloc(dwSize);
437 if(lpCopy == NULL) {
438 DebugInt3();
439 return FALSE;
440 }
441 memcpy(lpCopy, lpData, dwSize);
442
443 pDosHdr = (PIMAGE_DOS_HEADER)lpCopy;
444 pNEHdr = (PIMAGE_OS2_HEADER) ((char *)pDosHdr + pDosHdr->e_lfanew);
445 if(pDosHdr->e_magic != IMAGE_DOS_SIGNATURE ||
446 pNEHdr->ne_magic != IMAGE_OS2_SIGNATURE) {
447 dprintf(("Unknown file format"));
448 goto failure;
449 }
450
451 pResInfo = (struct resource_typeinfo_s *)((char *)pNEHdr + pNEHdr->ne_rsrctab);
452 alignment = *(WORD *)pResInfo;
453 pResInfo = (struct resource_typeinfo_s *)((char *)pResInfo+sizeof(WORD));
454
455 //first resource is a font directory
456 if(pResInfo->type_id != NE_RSCTYPE_FONTDIR && pResInfo->count != 1) {
457 dprintf(("Unknown file format"));
458 goto failure;
459 }
460 pNameInfo = (struct resource_nameinfo_s *)(pResInfo+1);
461 pFontDir = (LPFONTDIR16)((char *)pDosHdr + (pNameInfo->offset << alignment));
462 //first word = length followed by the string (not terminated)
463 pFontNameId = (char *)pResInfo - sizeof(WORD) + pNameInfo->id;
464
465 //GPI makes assumptions about the file based on the extention (d'oh)
466 newname = strdup(lpszFontFile);
467 extension = strrchr(newname, '.');
468
469 strcpy(extension, ".TTF");
470 CopyFileA(lpszFontFile, newname, FALSE);
471
472 //get font family and face names
473 OSLibGpiQueryFontName(newname, szFamily, szFace, sizeof(szFamily));
474
475 DeleteFileA(newname);
476 free(newname);
477
478 nrFonts = *(WORD *)pFontDir;
479 fontOrdinal = *((WORD *)pFontDir+1);
480 pFontDir = (LPFONTDIR16)((char *)pFontDir + 2*sizeof(WORD));
481
482 //copy family and face names to fontdir structure
483 len = strlen(szFamily);
484 strcpy(pFontDir->szDeviceName, szFamily);
485 strcpy(pFontDir->szDeviceName + len + 1, szFace);
486
487 dprintf(("Family %s, Face %s", szFamily, szFace));
488
489 pResNameTable = (char *)pNEHdr + pNEHdr->ne_restab;
490
491 //second resource is the absolute path of the TTF file
492 pResInfo = (struct resource_typeinfo_s *)(pNameInfo+1);
493 if(pResInfo->type_id != 0x80CC && pResInfo->count != 1) {
494 dprintf(("Unknown file format"));
495 goto failure;
496 }
497 pNameInfo = (struct resource_nameinfo_s *)(pResInfo+1);
498 pFontPath = ((char *)pDosHdr + (pNameInfo->offset << alignment));
499 //overwrite absolute font path
500 strcpy(pFontPath, lpszFontFile);
501 pNameInfo->length = strlen(lpszFontFile)+1;
502
503 hFile = CreateFileA(lpszFontRes,
504 GENERIC_READ | GENERIC_WRITE,
505 FILE_SHARE_READ | FILE_SHARE_WRITE,
506 NULL,
507 CREATE_NEW,
508 0,
509 NULL);
510
511 if(hFile == INVALID_HANDLE_VALUE) {
512 DebugInt3();
513 goto failure;
514 }
515 ret = WriteFile(hFile, lpCopy, dwSize, &dwBytesWritten, NULL);
516 if(ret == FALSE || dwBytesWritten != dwSize) {
517 DebugInt3();
518 goto failure;
519 }
520 CloseHandle(hFile);
521
522 if(lpCopy) free(lpCopy);
523
524 SetLastError(ERROR_SUCCESS);
525 return TRUE;
526
527failure:
528 if(hFile != INVALID_HANDLE_VALUE) {
529 CloseHandle(hFile);
530 DeleteFileA(lpszFontRes);
531 }
532 if(lpCopy) free(lpCopy);
533 SetLastError(ERROR_INVALID_PARAMETER); //not correct
534 return FALSE;
535}
536
537
538/*****************************************************************************
539 * Name : BOOL CreateScalableFontResourceW
540 * Purpose : The CreateScalableFontResourceW function creates a font resource
541 * file for a scalable font.
542 * Parameters: DWORD fdwHidden flag for read-only embedded font
543 * LPCSTR lpszFontRes address of filename for font resource
544 * LPCSTR lpszFontFile address of filename for scalable font
545 * LPCSTR lpszCurrentPath address of path to font file
546 * Variables :
547 * Result : TRUE / FALSE
548 * Remark :
549 * Status : UNTESTED STUB
550 *
551 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
552 *****************************************************************************/
553
554BOOL WIN32API CreateScalableFontResourceW(DWORD fdwHidden,
555 LPCWSTR lpszFontRes,
556 LPCWSTR lpszFontFile,
557 LPCWSTR lpszCurrentPath)
558{
559 LPSTR lpszFontFileA = NULL, lpszFontResA = NULL, lpszCurrentPathA = NULL;
560
561 dprintf(("GDI32: CreateScalableFontResourceW %x %ls %ls %ls not implemented", fdwHidden, lpszFontRes, lpszFontFile, lpszCurrentPath));
562
563 STACK_strdupWtoA(lpszFontFile, lpszFontFileA);
564 STACK_strdupWtoA(lpszFontRes, lpszFontResA);
565 STACK_strdupWtoA(lpszCurrentPath, lpszCurrentPathA);
566 return CreateScalableFontResourceA(fdwHidden, lpszFontResA, lpszFontFileA, lpszCurrentPathA);
567}
568//******************************************************************************
569//******************************************************************************
Note: See TracBrowser for help on using the repository browser.