source: trunk/src/gdi32/fontres.cpp@ 21304

Last change on this file since 21304 was 21304, checked in by ydario, 16 years ago

Gdi32 updates.

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