2 * PROJECT: ReactOS win32 subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: GDI font driver for bitmap fonts
5 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
19 if ((ULONG_PTR
)p
< (ULONG_PTR
)pStart
||
20 (ULONG_PTR
)p
+ cjSize
>= (ULONG_PTR
)pEnd
||
21 (ULONG_PTR
)p
& (cjAlign
-1))
32 PFONTINFO16 pFontInfo
)
39 pface
->pFontInfo
= pFontInfo
;
40 pface
->ulVersion
= GETVAL(pFontInfo
->dfVersion
);
41 pface
->cGlyphs
= pFontInfo
->dfLastChar
- pFontInfo
->dfFirstChar
+ 1;
43 /* Convert chars to unicode */
44 ansi
[0] = pFontInfo
->dfFirstChar
;
45 ansi
[1] = pFontInfo
->dfLastChar
;
46 ansi
[2] = pFontInfo
->dfFirstChar
+ pFontInfo
->dfDefaultChar
;
47 ansi
[3] = pFontInfo
->dfFirstChar
+ pFontInfo
->dfBreakChar
;
48 EngMultiByteToUnicodeN(unicode
, 4 * sizeof(WCHAR
), &written
, ansi
, 4);
49 pface
->wcFirstChar
= unicode
[0];
50 pface
->wcLastChar
= unicode
[1];
51 pface
->wcDefaultChar
= unicode
[2];
52 pface
->wcBreakChar
= unicode
[3];
54 /* Copy some values */
55 pface
->wPixHeight
= GETVAL(pFontInfo
->dfPixHeight
);
56 pface
->wPixWidth
= GETVAL(pFontInfo
->dfPixWidth
);
57 pface
->wWidthBytes
= GETVAL(pFontInfo
->dfWidthBytes
);
58 pface
->wAscent
= GETVAL(pFontInfo
->dfAscent
);
59 pface
->wDescent
= pface
->wPixHeight
- pface
->wAscent
;
61 /* Some version specific members */
62 if (pface
->ulVersion
>= 0x300)
64 dfFlags
= GETVAL(pFontInfo
->dfFlags
);
65 pface
->wA
= GETVAL(pFontInfo
->dfAspace
);
66 pface
->wB
= GETVAL(pFontInfo
->dfBspace
);
67 pface
->wC
= GETVAL(pFontInfo
->dfCspace
);
68 pface
->pCharTable
= pface
->pFontInfo
->dfCharTable
;
69 pface
->cjEntrySize
= sizeof(GLYPHENTRY30
);
77 pface
->pCharTable
= &pface
->pFontInfo
->dfReserved
+ 1;
78 pface
->cjEntrySize
= sizeof(GLYPHENTRY20
);
81 pface
->flInfo
= FM_INFO_MASK
;
83 /* If dfWidth is non-null, we have a fixed width font */
84 if (dfFlags
& DFF_FIXED
|| pface
->wPixWidth
)
85 pface
->flInfo
|= FM_INFO_CONSTANT_WIDTH
;
87 /* Initialize color depth flags */
88 if (dfFlags
& DFF_1COLOR
)
89 pface
->flInfo
|= FM_INFO_1BPP
;
90 else if (dfFlags
& DFF_16COLOR
)
91 pface
->flInfo
|= FM_INFO_4BPP
;
92 else if (dfFlags
& DFF_256COLOR
)
93 pface
->flInfo
|= FM_INFO_8BPP
;
94 else if (dfFlags
& DFF_RGBCOLOR
)
95 pface
->flInfo
|= FM_INFO_24BPP
;
97 // TODO: walk through all glyphs and veryfy them and calculate max values
99 // FIXME: After this point, the whole font data should be verified!
121 PIMAGE_DOS_HEADER pDosHeader
= pvView
;
122 PIMAGE_OS2_HEADER pOs2Header
;
123 PNE_RESTABLE pResTable
;
125 PFONTINFO16 pFontInfo
;
127 PBMFD_FILE pfile
= NULL
;
129 ULONG i
, cjOffset
, cjLength
;
130 ULONG type_id
, count
;
132 /* Initial margins for valid pointers */
134 pEnd
= pStart
+ cjView
;
136 /* Check for image dos header */
137 if (GETVAL(pDosHeader
->e_magic
) != IMAGE_DOS_MAGIC
)
142 /* Get pointer to OS2 header and veryfy it is valid */
143 pOs2Header
= (PVOID
)((PCHAR
)pDosHeader
+ GETVAL(pDosHeader
->e_lfanew
));
144 pStart
+= sizeof(IMAGE_DOS_HEADER
);
145 if (!IsValidPtr(pOs2Header
, sizeof(IMAGE_OS2_HEADER
), pStart
, pEnd
, 4))
147 DbgPrint("e_lfanew is invalid: 0x%lx\n", pDosHeader
->e_lfanew
);
151 /* Get pointer to resource table and verify it is valid */
152 pResTable
= (PVOID
)((PCHAR
)pOs2Header
+ GETVAL(pOs2Header
->ne_rsrctab
));
153 pStart
= (PCHAR
)pOs2Header
;
154 if (!IsValidPtr(pResTable
, sizeof(NE_RESTABLE
), pStart
, pEnd
, 1))
156 DbgPrint("pTInfo is invalid: 0x%p\n", pResTable
);
160 wShift
= GETVAL(pResTable
->size_shift
);
161 pTInfo
= pResTable
->typeinfo
;
162 type_id
= GETVAL(pTInfo
->type_id
);
164 /* Loop the resource table to find a font resource */
167 /* Get number of nameinfo entries */
168 count
= GETVAL(pTInfo
->count
);
170 /* Look for a font resource */
171 if (type_id
== NE_RSCTYPE_FONT
&& count
> 0)
173 DbgPrint("Found NE_RSCTYPE_FONT\n");
175 /* Allocate an info structure for this font and all faces */
176 cjLength
= sizeof(BMFD_FILE
) + (count
-1) * sizeof(BMFD_FACE
);
177 pfile
= EngAllocMem(0, cjLength
, TAG_FONTINFO
);
180 DbgPrint("Not enough memory: %ld\n", cjLength
);
184 pfile
->cNumFaces
= count
;
186 /* Fill all face info structures */
187 for (i
= 0; i
< count
; i
++)
189 cjOffset
= GETVAL(pTInfo
->nameinfo
[i
].offset
) << wShift
;
190 cjLength
= GETVAL(pTInfo
->nameinfo
[i
].length
) << wShift
;
191 pFontInfo
= (PVOID
)((PCHAR
)pDosHeader
+ cjOffset
);
193 if (!IsValidPtr(pFontInfo
, cjLength
, pStart
, pEnd
, 1))
195 DbgPrint("pFontInfo is invalid: 0x%p\n", pFontInfo
);
200 /* Validate FONTINFO and fill face info */
201 if (!FillFaceInfo(&pfile
->aface
[i
], pFontInfo
))
203 DbgPrint("pFontInfo is invalid: 0x%p\n", pFontInfo
);
209 /* Break out of the loop */
213 /* Following pointers must be bigger than this */
214 pStart
= (PCHAR
)pTInfo
;
216 /* Goto next entry in resource table */
217 pTInfo
= (PVOID
)&pTInfo
->nameinfo
[count
];
219 /* Verify that the new pTInfo pointer is valid */
220 if (!IsValidPtr(pTInfo
, sizeof(NE_TYPEINFO
), pStart
, pEnd
, 1))
222 DbgPrint("pTInfo is invalid: 0x%p\n", pTInfo
);
226 type_id
= GETVAL(pTInfo
->type_id
);
232 /** Public Interface **********************************************************/
243 ULONG ulFastCheckSum
)
245 PBMFD_FILE pfile
= NULL
;
249 DbgPrint("BmfdLoadFontFile()\n");
252 /* Check parameters */
255 DbgPrint("Only 1 File is allowed, got %ld!\n", cFiles
);
259 /* Map the font file */
260 if (!EngMapFontFileFD(*piFile
, (PULONG
*)&pvView
, &cjView
))
262 DbgPrint("Could not map font file!\n", cFiles
);
266 DbgPrint("mapped font file to %p, site if %ld\n", pvView
, cjView
);
268 /* Try to parse a .fon file */
269 pfile
= ParseFonFile(pvView
, cjView
);
273 /* Could be a .fnt file */
274 pfile
= ParseFntFile(pvView
, cjView
);
277 /* Check whether we succeeded finding a font */
280 DbgPrint("No font data found\n");
283 EngUnmapFontFileFD(*piFile
);
289 pfile
->iFile
= *piFile
;
290 pfile
->pvView
= pvView
;
292 /* Success, return the pointer to font info structure */
293 return (ULONG_PTR
)pfile
;
301 PBMFD_FILE pfile
= (PBMFD_FILE
)iFile
;
303 DbgPrint("BmfdUnloadFontFile()\n");
305 /* Unmap the font file */
306 EngUnmapFontFileFD(pfile
->iFile
);
308 /* Free the memory that was allocated for the font */
323 PBMFD_FILE pfile
= (PBMFD_FILE
)iFile
;
325 DbgPrint("BmfdQueryFontFile()\n");
330 case QFF_DESCRIPTION
:
332 /* We copy the face name of the 1st face */
333 PCHAR pDesc
= pfile
->aface
[0].pszFaceName
;
337 EngMultiByteToUnicodeN((LPWSTR
)pulBuf
,
341 strnlen(pDesc
, LF_FACESIZE
));
345 cOutSize
= (strnlen(pDesc
, LF_FACESIZE
) + 1) * sizeof(WCHAR
);
351 /* return the number of faces in the file */
352 return pfile
->cNumFaces
;
365 DbgPrint("BmfdQueryFontCaps()\n");
367 /* We need room for 2 ULONGs */
373 /* We only support 1 bpp */
375 pulCaps
[1] = QC_1BIT
;
390 PBMFD_FILE pfile
= (PBMFD_FILE
)iFile
;
392 ULONG i
, j
, cjSize
, cGlyphs
, cRuns
;
393 CHAR ch
, chFirst
, ach
[256];
395 PFD_GLYPHSET pGlyphSet
;
399 DbgPrint("DrvQueryFontTree(iMode=%ld)\n", iMode
);
402 /* Check parameters, we only support QFT_GLYPHSET */
403 if (!iFace
|| iFace
> pfile
->cNumFaces
|| iMode
!= QFT_GLYPHSET
)
405 DbgPrint("iFace = %ld, cNumFaces = %ld\n", iFace
, pfile
->cNumFaces
);
409 /* Get a pointer to the face data */
410 pface
= &pfile
->aface
[iFace
- 1];
412 /* Get the number of characters in the face */
413 cGlyphs
= pface
->cGlyphs
;
415 chFirst
= pface
->pFontInfo
->dfFirstChar
;
417 /* Build array of supported chars */
418 for (i
= 0; i
< cGlyphs
; i
++)
420 ach
[i
] = chFirst
+ i
;
423 /* Convert the chars to unicode */
424 EngMultiByteToUnicodeN(awc
, sizeof(awc
), NULL
, ach
, cGlyphs
);
426 /* Sort both arrays in wchar order */
427 for (i
= 0; i
< cGlyphs
- 1; i
++)
430 for (j
= i
+ 1; j
< cGlyphs
; j
++)
444 /* Find number of WCRUNs */
446 for (i
= 1; i
< cGlyphs
; i
++)
448 if (awc
[i
] != awc
[i
- 1] + 1)
454 /* Calculate FD_GLYPHSET size */
455 cjSize
= sizeof(FD_GLYPHSET
)
456 + (cRuns
- 1) * sizeof(WCRUN
)
457 + cGlyphs
* sizeof(HGLYPH
);
459 /* Allocate the FD_GLYPHSET structure */
460 pGlyphSet
= EngAllocMem(0, cjSize
, TAG_GLYPHSET
);
466 /* Initialize FD_GLYPHSET */
467 pGlyphSet
->cjThis
= cjSize
;
468 pGlyphSet
->flAccel
= 0;
469 pGlyphSet
->cGlyphsSupported
= cGlyphs
;
470 pGlyphSet
->cRuns
= cRuns
;
472 /* Initialize 1st WCRUN */
473 pwcrun
= pGlyphSet
->awcrun
;
474 phglyphs
= (PHGLYPH
)&pGlyphSet
->awcrun
[cRuns
];
475 pwcrun
[0].wcLow
= awc
[0];
476 pwcrun
[0].cGlyphs
= 1;
477 pwcrun
[0].phg
= phglyphs
;
480 /* Walk through all supported chars */
481 for (i
= 1, j
= 0; i
< cGlyphs
; i
++)
483 /* Use offset to glyph entry as hglyph */
484 phglyphs
[i
] = (ach
[i
] - chFirst
) * pface
->cjEntrySize
;
486 /* Check whether we can append the wchar to a run */
487 if (awc
[i
] == awc
[i
- 1] + 1)
489 /* Append to current WCRUN */
494 /* Add a new WCRUN */
496 pwcrun
[j
].wcLow
= awc
[i
];
497 pwcrun
[j
].cGlyphs
= 1;
498 pwcrun
[j
].phg
= &phglyphs
[i
];
502 /* Set *pid to the allocated structure for use in BmfdFree */
503 *pid
= (ULONG_PTR
)pGlyphSet
;
516 PBMFD_FILE pfile
= (PBMFD_FILE
)iFile
;
518 PFONTINFO16 pFontInfo
;
520 PBMFD_IFIMETRICS pifiX
;
523 DbgPrint("BmfdQueryFont()\n");
526 /* Validate parameters */
527 if (iFace
> pfile
->cNumFaces
|| !pid
)
532 pface
= &pfile
->aface
[iFace
- 1];
533 pFontInfo
= pface
->pFontInfo
;
535 /* Allocate the structure */
536 pifiX
= EngAllocMem(FL_ZERO_MEMORY
, sizeof(BMFD_IFIMETRICS
), TAG_IFIMETRICS
);
542 /* Return a pointer to free it later */
543 *pid
= (ULONG_PTR
)pifiX
;
545 /* Fill IFIMETRICS */
547 pifi
->cjThis
= sizeof(BMFD_IFIMETRICS
);
548 pifi
->cjIfiExtra
= 0;
549 pifi
->dpwszFamilyName
= FIELD_OFFSET(BMFD_IFIMETRICS
, wszFamilyName
);
550 pifi
->dpwszStyleName
= FIELD_OFFSET(BMFD_IFIMETRICS
, wszFamilyName
);
551 pifi
->dpwszFaceName
= FIELD_OFFSET(BMFD_IFIMETRICS
, wszFaceName
);
552 pifi
->dpwszUniqueName
= FIELD_OFFSET(BMFD_IFIMETRICS
, wszFaceName
);
555 pifi
->lItalicAngle
= 0;
557 pifi
->dpCharSets
= 0;
558 pifi
->jWinCharSet
= pFontInfo
->dfCharSet
;
559 pifi
->jWinPitchAndFamily
= pFontInfo
->dfPitchAndFamily
;
560 pifi
->usWinWeight
= GETVAL(pFontInfo
->dfWeight
);
561 pifi
->flInfo
= pface
->flInfo
;
562 pifi
->fsSelection
= 0;
564 pifi
->fwdUnitsPerEm
= GETVAL(pFontInfo
->dfPixHeight
);
565 pifi
->fwdLowestPPEm
= 0;
566 pifi
->fwdWinAscender
= GETVAL(pFontInfo
->dfAscent
);
567 pifi
->fwdWinDescender
= pifi
->fwdUnitsPerEm
- pifi
->fwdWinAscender
;
568 pifi
->fwdMacAscender
= pifi
->fwdWinAscender
;
569 pifi
->fwdMacDescender
= - pifi
->fwdWinDescender
;
570 pifi
->fwdMacLineGap
= 0;
571 pifi
->fwdTypoAscender
= pifi
->fwdWinAscender
;
572 pifi
->fwdTypoDescender
= - pifi
->fwdWinDescender
;
573 pifi
->fwdTypoLineGap
= 0;
574 pifi
->fwdAveCharWidth
= GETVAL(pFontInfo
->dfAvgWidth
);
575 pifi
->fwdMaxCharInc
= GETVAL(pFontInfo
->dfMaxWidth
);
576 pifi
->fwdCapHeight
= pifi
->fwdUnitsPerEm
/ 2;
577 pifi
->fwdXHeight
= pifi
->fwdUnitsPerEm
/ 4;
578 pifi
->fwdSubscriptXSize
= 0;
579 pifi
->fwdSubscriptYSize
= 0;
580 pifi
->fwdSubscriptXOffset
= 0;
581 pifi
->fwdSubscriptYOffset
= 0;
582 pifi
->fwdSuperscriptXSize
= 0;
583 pifi
->fwdSuperscriptYSize
= 0;
584 pifi
->fwdSuperscriptXOffset
= 0;
585 pifi
->fwdSuperscriptYOffset
= 0;
586 pifi
->fwdUnderscoreSize
= 01;
587 pifi
->fwdUnderscorePosition
= -1;
588 pifi
->fwdStrikeoutSize
= 1;
589 pifi
->fwdStrikeoutPosition
= pifi
->fwdXHeight
+ 1;
590 pifi
->chFirstChar
= pFontInfo
->dfFirstChar
;
591 pifi
->chLastChar
= pFontInfo
->dfLastChar
;
592 pifi
->chDefaultChar
= pFontInfo
->dfFirstChar
+ pFontInfo
->dfDefaultChar
;
593 pifi
->chBreakChar
= pFontInfo
->dfFirstChar
+ pFontInfo
->dfBreakChar
;
594 pifi
->wcFirstChar
= pface
->wcFirstChar
;
595 pifi
->wcLastChar
= pface
->wcLastChar
;
596 pifi
->wcDefaultChar
= pface
->wcDefaultChar
;
597 pifi
->wcBreakChar
= pface
->wcBreakChar
;
598 pifi
->ptlBaseline
.x
= 1;
599 pifi
->ptlBaseline
.y
= 0;
600 pifi
->ptlAspect
.x
= pFontInfo
->dfVertRes
; // CHECKME
601 pifi
->ptlAspect
.y
= pFontInfo
->dfHorizRes
;
602 pifi
->ptlCaret
.x
= 0;
603 pifi
->ptlCaret
.y
= 1;
604 pifi
->rclFontBox
.left
= 0;
605 pifi
->rclFontBox
.right
= pifi
->fwdAveCharWidth
;
606 pifi
->rclFontBox
.top
= pifi
->fwdWinAscender
;
607 pifi
->rclFontBox
.bottom
= - pifi
->fwdWinDescender
;
608 *(DWORD
*)&pifi
->achVendId
= 0x30303030; // FIXME
609 pifi
->cKerningPairs
= 0;
610 pifi
->ulPanoseCulture
= FM_PANOSE_CULTURE_LATIN
;
611 pifi
->panose
= panose
;
614 pifiX
->ajCharSet
[0] = pifi
->jWinCharSet
;
615 pifiX
->ajCharSet
[1] = DEFAULT_CHARSET
;
617 if (pface
->flInfo
& FM_INFO_CONSTANT_WIDTH
)
618 pifi
->jWinPitchAndFamily
|= FIXED_PITCH
;
621 EngMultiByteToUnicodeN(pifiX
->wszFaceName
,
622 LF_FACESIZE
* sizeof(WCHAR
),
625 strnlen(pDesc
, LF_FACESIZE
));
627 wcscpy(pifiX
->wszFaceName
, L
"Courier-X");
628 wcscpy(pifiX
->wszFamilyName
, L
"Courier-X");
630 /* Initialize font weight style flags and string */
631 if (pifi
->usWinWeight
== FW_REGULAR
)
633 // pifi->fsSelection |= FM_SEL_REGULAR;
635 else if (pifi
->usWinWeight
> FW_SEMIBOLD
)
637 pifi
->fsSelection
|= FM_SEL_BOLD
;
638 wcscat(pifiX
->wszStyleName
, L
"Bold ");
640 else if (pifi
->usWinWeight
<= FW_LIGHT
)
642 wcscat(pifiX
->wszStyleName
, L
"Light ");
645 if (pFontInfo
->dfItalic
)
647 pifi
->fsSelection
|= FM_SEL_ITALIC
;
648 wcscat(pifiX
->wszStyleName
, L
"Italic ");
651 if (pFontInfo
->dfUnderline
)
653 pifi
->fsSelection
|= FM_SEL_UNDERSCORE
;
654 wcscat(pifiX
->wszStyleName
, L
"Underscore ");
657 if (pFontInfo
->dfStrikeOut
)
659 pifi
->fsSelection
|= FM_SEL_STRIKEOUT
;
660 wcscat(pifiX
->wszStyleName
, L
"Strikeout ");
673 DbgPrint("BmfdFree()\n");
676 EngFreeMem((PVOID
)id
);
686 /* Free the font realization info */
687 EngFreeMem(pfo
->pvProducer
);
688 pfo
->pvProducer
= NULL
;