Author: tkreuzer Date: Sun Aug 14 08:52:14 2011 New Revision: 53219
URL: http://svn.reactos.org/svn/reactos?rev=53219&view=rev Log: [GDI FONT DRIVER] Revert unwanted changes
Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/CMakeLists.txt branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/enable.c branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/font.c branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/ftfd.h branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/glyph.c branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/rosglue.c
Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/drivers/... ============================================================================== --- branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/CMakeLists.txt [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/CMakeLists.txt [iso-8859-1] Sun Aug 14 08:52:14 2011 @@ -5,10 +5,11 @@
add_library(ftfd SHARED enable.c + copybits.c font.c glyph.c + tttables.c rosglue.c - sprintf.c ${CMAKE_CURRENT_BINARY_DIR}/ftfd.def)
set_entrypoint(ftfd FtfdEnableDriver@12)
Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/enable.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/drivers/... ============================================================================== --- branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/enable.c [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/enable.c [iso-8859-1] Sun Aug 14 08:52:14 2011 @@ -1,7 +1,7 @@ /* * PROJECT: ReactOS win32 subsystem * LICENSE: GPL - See COPYING in the top level directory - * PURPOSE: GDI font driver for bitmap fonts + * PURPOSE: GDI font driver based on freetype * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) */
@@ -9,22 +9,28 @@
static DRVFN gadrvfn[] = { - {INDEX_DrvEnablePDEV, (PFN)FtfdEnablePDEV}, - {INDEX_DrvCompletePDEV, (PFN)FtfdCompletePDEV}, - {INDEX_DrvDisablePDEV, (PFN)FtfdDisablePDEV}, - {INDEX_DrvLoadFontFile, (PFN)FtfdLoadFontFile}, - {INDEX_DrvUnloadFontFile, (PFN)FtfdUnloadFontFile}, - {INDEX_DrvQueryFontFile, (PFN)FtfdQueryFontFile}, - {INDEX_DrvQueryFontCaps, (PFN)FtfdQueryFontCaps}, - {INDEX_DrvQueryFontTree, (PFN)FtfdQueryFontTree}, - {INDEX_DrvQueryFont, (PFN)FtfdQueryFont}, - {INDEX_DrvFree, (PFN)FtfdFree}, - {INDEX_DrvQueryGlyphAttrs, (PFN)FtfdQueryGlyphAttrs}, - {INDEX_DrvQueryFontData, (PFN)FtfdQueryFontData}, + {INDEX_DrvEnablePDEV, (PFN)FtfdEnablePDEV}, + {INDEX_DrvCompletePDEV, (PFN)FtfdCompletePDEV}, + {INDEX_DrvDisablePDEV, (PFN)FtfdDisablePDEV}, + {INDEX_DrvLoadFontFile, (PFN)FtfdLoadFontFile}, + {INDEX_DrvUnloadFontFile, (PFN)FtfdUnloadFontFile}, + {INDEX_DrvQueryFontFile, (PFN)FtfdQueryFontFile}, + {INDEX_DrvQueryFontCaps, (PFN)FtfdQueryFontCaps}, + {INDEX_DrvQueryFontTree, (PFN)FtfdQueryFontTree}, + {INDEX_DrvQueryFont, (PFN)FtfdQueryFont}, + {INDEX_DrvDestroyFont, (PFN)FtfdDestroyFont}, +// {INDEX_DrvFree, (PFN)FtfdFree}, + {INDEX_DrvQueryGlyphAttrs, (PFN)FtfdQueryGlyphAttrs}, + {INDEX_DrvQueryFontData, (PFN)FtfdQueryFontData}, + {INDEX_DrvQueryAdvanceWidths, (PFN)FtfdQueryAdvanceWidths}, + {INDEX_DrvQueryTrueTypeOutline, (PFN)FtfdQueryTrueTypeOutline}, + {INDEX_DrvQueryTrueTypeTable, (PFN)FtfdQueryTrueTypeTable}, + {INDEX_DrvEscape, (PFN)FtfdEscape}, + {INDEX_DrvFontManagement, (PFN)FtfdFontManagement}, + {INDEX_DrvGetTrueTypeFile, (PFN)FtfdGetTrueTypeFile}, };
FT_Library gftlibrary; -
BOOL APIENTRY @@ -33,9 +39,12 @@ ULONG cj, PDRVENABLEDATA pded) { - FT_Error fterror; + FT_Error fterror;
- DbgPrint("FtfdEnableDriver()\n"); + TRACE("FtfdEnableDriver()\n"); + +//__debugbreak(); +
/* Check parameter */ if (cj < sizeof(DRVENABLEDATA)) @@ -47,7 +56,7 @@ fterror = FT_Init_FreeType(&gftlibrary); if (fterror) { - DbgPrint("an error occurred during library initialization: %ld.\n", fterror); + WARN("Failed to initialize freetype library: %ld.\n", fterror); return FALSE; }
@@ -76,9 +85,7 @@ IN LPWSTR pwszDeviceName, IN HANDLE hDriver) { - DbgPrint("FtfdEnablePDEV(hdev=%p)\n", hdev); - __debugbreak(); - + TRACE("FtfdEnablePDEV(hdev=%p)\n", hdev);
/* Return a dummy DHPDEV */ return (PVOID)1; @@ -91,7 +98,7 @@ IN DHPDEV dhpdev, IN HDEV hdev) { - DbgPrint("FtfdCompletePDEV()\n"); + TRACE("FtfdCompletePDEV()\n"); /* Nothing to do */ }
@@ -101,6 +108,22 @@ FtfdDisablePDEV( IN DHPDEV dhpdev) { - DbgPrint("FtfdDisablePDEV()\n"); + TRACE("FtfdDisablePDEV()\n"); /* Nothing to do */ } + +ULONG +APIENTRY +FtfdEscape( + SURFOBJ *pso, + ULONG iEsc, + ULONG cjIn, + PVOID pvIn, + ULONG cjOut, + PVOID pvOut) +{ + TRACE("FtfdEscape\n"); + __debugbreak(); + return 0; +} +
Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/font.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/drivers/... ============================================================================== --- branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/font.c [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/font.c [iso-8859-1] Sun Aug 14 08:52:14 2011 @@ -1,26 +1,512 @@ /* * PROJECT: ReactOS win32 subsystem * LICENSE: GPL - See COPYING in the top level directory - * PURPOSE: GDI font driver for bitmap fonts + * PURPOSE: GDI font driver based on freetype * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) */
#include "ftfd.h"
+static +FWORD +CalculateAveCharWidth( + FT_Face ftface) +{ + ULONG cGlyphs = 0, ulAccumCharWidth = 0; + WCHAR wc; + FT_UInt index; + FT_Error fterror; + + /* Loop all glyphs from 'a' to 'z' */ + for (wc = L'a'; wc <= L'z'; wc++) + { + /* Load the glyph into the glyph slot */ + fterror = FT_Load_Char(ftface, wc, FT_LOAD_NO_SCALE|FT_LOAD_NO_BITMAP); + if (fterror) break; + + /* Calculate accumulative char width */ + ulAccumCharWidth += ftface->glyph->metrics.width; + cGlyphs++; + } + + /* Check if an error occured */ + if (wc <= L'z') + { + TRACE("using all glyphs\n"); + + /* Start over */ + ulAccumCharWidth = 0; + cGlyphs = 0; + + /* Loop all glyphs in the font */ + for (index = 0; index <= (UINT)ftface->num_glyphs; index++) + { + /* Load the glyph into the glyph slot */ + fterror = FT_Load_Glyph(ftface, index, FT_LOAD_NO_SCALE|FT_LOAD_NO_BITMAP); + if (fterror) continue; + + /* Calculate accumulative char width */ + ulAccumCharWidth += ftface->glyph->metrics.width; // FIXME: weighted + cGlyphs++; + } + } + + /* Return the average glyph width */ + return (FWORD)(ulAccumCharWidth / cGlyphs); +} + +BOOL +NTAPI +FtfdInitIfiMetrics( + PFTFD_FACE pface) +{ + PFTFD_IFIMETRICS pifiex; + PIFIMETRICS pifi; + FT_Face ftface; + FT_Error fterror; + PS_FontInfoRec fontinfo; + ULONG i; + + TRACE("FtfdInitIfiMetrics()\n"); + + /* Get the freetype face pointer */ + ftface = pface->ftface; + + /* Init header */ + pifiex = &pface->ifiex; + pifi = &pface->ifiex.ifi; + pifi->cjThis = sizeof(FTFD_IFIMETRICS); + pifi->cjIfiExtra = 0; + + /* Set relative offsets */ + pifi->dpwszFamilyName = FIELD_OFFSET(FTFD_IFIMETRICS, awcFamilyName); + pifi->dpwszStyleName = FIELD_OFFSET(FTFD_IFIMETRICS, awcStyleName); + pifi->dpwszFaceName = FIELD_OFFSET(FTFD_IFIMETRICS, awcFaceName); + pifi->dpwszUniqueName = FIELD_OFFSET(FTFD_IFIMETRICS, awcUniqueName); + pifi->dpCharSets = FIELD_OFFSET(FTFD_IFIMETRICS, ajCharSet); + pifi->dpFontSim = 0; + + /* Initialize charsets */ + pifi->jWinCharSet = ANSI_CHARSET; + pifiex->ajCharSet[0] = pifi->jWinCharSet; + for (i = 1; i < 16; i++) + { + pifiex->ajCharSet[i] = DEFAULT_CHARSET; + } + + pifi->lEmbedId = 0; + pifi->lCharBias = 0; + + /* Feature flags */ + pifi->flInfo = FM_INFO_RETURNS_BITMAPS | FM_INFO_1BPP | FM_INFO_4BPP; + if (pface->ulFontFormat == FMT_TYPE1) + pifi->flInfo |= FM_INFO_TECH_TYPE1; + if (pface->ulFontFormat == FMT_CFF) + pifi->flInfo |= FM_INFO_TECH_TYPE1 | FM_INFO_TECH_CFF; + if (pface->ulFontFormat == FMT_TRUETYPE) + pifi->flInfo |= FM_INFO_TECH_TRUETYPE; + else + pifi->flInfo |= FM_INFO_TECH_OUTLINE_NOT_TRUETYPE; + if (pface->cRuns > 1) + pifi->flInfo |= FM_INFO_NOT_CONTIGUOUS; + if (pface->ulFontFormat != FMT_FNT) + pifi->flInfo |= /*FM_INFO_RETURNS_OUTLINES |*/ FM_INFO_ARB_XFORMS; + pifi->flInfo |= FM_INFO_RIGHT_HANDED; // FIXME: how to determine? + + /* Font resolution */ + pifi->fwdUnitsPerEm = ftface->units_per_EM; + pifi->fwdLowestPPEm = 3; + + /* Font metrics */ + pifi->fwdMacAscender = ftface->ascender; + pifi->fwdMacDescender = ftface->descender; + pifi->fwdMacLineGap = 0; + pifi->fwdMaxCharInc = ftface->max_advance_width; + pifi->fwdUnderscoreSize = ftface->underline_thickness; + pifi->fwdUnderscorePosition = ftface->underline_position; + + pifi->ptlBaseline.x = 1; // FIXME + pifi->ptlBaseline.y = 0; // FIXME + pifi->ptlAspect.x = 1; + pifi->ptlAspect.y = 1; + pifi->ptlCaret.x = 0; // FIXME + pifi->ptlCaret.y = 1; // FIXME + + /* Set the biggest characters bounding box */ + pifi->rclFontBox.left = ftface->bbox.xMin; + pifi->rclFontBox.right = ftface->bbox.xMax; + pifi->rclFontBox.top = ftface->bbox.yMax; + pifi->rclFontBox.bottom = ftface->bbox.yMin; + + pifi->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN; + + /* Try to get OS/2 TrueType or OpenType metrics */ + if (!FtfdGetWinMetrics(pface, pifi)) + { + /* No success, use fallback */ + + /* Font style flags */ + pifi->fsType = 0; + pifi->fsSelection = FM_SEL_REGULAR; + pifi->usWinWeight = FW_REGULAR; + if (ftface->style_flags & FT_STYLE_FLAG_BOLD) + { + pifi->fsSelection &= ~FM_SEL_REGULAR; + pifi->fsSelection |= FM_SEL_BOLD; + pifi->usWinWeight = FW_BOLD; + } + if (ftface->style_flags & FT_STYLE_FLAG_ITALIC) + { + pifi->fsSelection &= ~FM_SEL_REGULAR; + pifi->fsSelection |= FM_SEL_ITALIC; + } + + /* Metrics */ + pifi->fwdWinAscender = (ftface->ascender * 213) / 170; + pifi->fwdWinDescender = -(ftface->descender * 213) / 170; + pifi->fwdTypoAscender = ftface->ascender; + pifi->fwdTypoDescender = ftface->descender; + pifi->fwdTypoLineGap = pifi->fwdUnitsPerEm / 10; + pifi->fwdCapHeight = pifi->fwdUnitsPerEm / 2; + pifi->fwdXHeight = pifi->fwdUnitsPerEm / 4; + pifi->fwdSubscriptXSize = 0; + pifi->fwdSubscriptYSize = 0; + pifi->fwdSubscriptXOffset = 0; + pifi->fwdSubscriptYOffset = 0; + pifi->fwdSuperscriptXSize = 0; + pifi->fwdSuperscriptYSize = 0; + pifi->fwdSuperscriptXOffset = 0; + pifi->fwdSuperscriptYOffset = 0; + pifi->fwdStrikeoutSize = pifi->fwdUnderscoreSize; + pifi->fwdStrikeoutPosition = pifi->fwdMacAscender / 3; + pifi->fwdAveCharWidth = CalculateAveCharWidth(ftface); + + /* Special characters */ + pifi->wcDefaultChar = 0x001F; + pifi->wcBreakChar = 0x0020; + + pifi->panose.bFamilyType = PAN_FAMILY_TEXT_DISPLAY; + pifi->panose.bSerifStyle = PAN_ANY; + pifi->panose.bWeight = PAN_ANY; + pifi->panose.bProportion = PAN_ANY; + pifi->panose.bContrast = PAN_ANY; + pifi->panose.bStrokeVariation = PAN_ANY; + pifi->panose.bArmStyle = PAN_ANY; + pifi->panose.bLetterform = PAN_ANY; + pifi->panose.bMidline = PAN_ANY; + pifi->panose.bXHeight = PAN_ANY; + + *(DWORD*)&pifi->achVendId = 'nknU'; + } + + /* Copy unicode values to ansi values */ + pifi->chDefaultChar = (CHAR)pifi->wcDefaultChar; + pifi->chBreakChar = (CHAR)pifi->wcBreakChar; + pifi->chFirstChar = (CHAR)pifi->wcFirstChar; + if (pifi->wcFirstChar > 0xff) pifi->chFirstChar = 0xff; + pifi->chLastChar = (CHAR)pifi->wcLastChar; + if (pifi->wcLastChar > 0xff) pifi->chLastChar = 0xff; + + /* Try to get type1 info from freetype */ + fterror = FT_Get_PS_Font_Info(pface->ftface, &fontinfo); + if (fterror == 0) + { + /* Set italic angle */ + pifi->lItalicAngle = fontinfo.italic_angle; + } + else + { + /* Set fallback values */ + pifi->lItalicAngle = 0; + } + + /* Get the win family */ + if (pifi->panose.bFamilyType == PAN_FAMILY_SCRIPT) + pifi->jWinPitchAndFamily = FF_SCRIPT; + else if (pifi->panose.bFamilyType == PAN_FAMILY_DECORATIVE) + pifi->jWinPitchAndFamily = FF_DECORATIVE; + else if (pifi->panose.bProportion == PAN_PROP_MODERN) + pifi->jWinPitchAndFamily = FF_MODERN; + else if (pifi->panose.bSerifStyle <= PAN_SERIF_ROUNDED) + pifi->jWinPitchAndFamily = FF_SWISS; + else + pifi->jWinPitchAndFamily = FF_ROMAN; + + /* Set pitch */ + pifi->jWinPitchAndFamily |= FT_IS_FIXED_WIDTH(ftface) ? FIXED_PITCH : + VARIABLE_PITCH; + + /* Convert the special characters from unicode to ansi */ + EngUnicodeToMultiByteN(&pifi->chFirstChar, 4, NULL, &pifi->wcFirstChar, 8); + + /* This one seems to be hardcoded to 0xff */ + pifi->chLastChar = 0xff; + + /* Convert names to unicode */ + EngMultiByteToUnicodeN(pifiex->awcFamilyName, + sizeof(pifiex->awcFamilyName), + NULL, + ftface->family_name, + strnlen(ftface->family_name, MAX_PATH)); + + EngMultiByteToUnicodeN(pifiex->awcStyleName, + sizeof(pifiex->awcStyleName), + NULL, + ftface->style_name, + strnlen(ftface->style_name, MAX_PATH)); + + EngMultiByteToUnicodeN(pifiex->awcFaceName, + sizeof(pifiex->awcFaceName), + NULL, + ftface->family_name, + strnlen(ftface->family_name, MAX_PATH)); + + /* Create a unique name */ + wcscpy(pifiex->awcUniqueName, L"1.000;????;"); + wcsncat(pifiex->awcUniqueName, pifiex->awcFamilyName, LF_FACESIZE); + pifiex->awcUniqueName[0] = L'0' + HIWORD(pface->ulFontRevision) % 10; + pifiex->awcUniqueName[2] = L'0' + (LOWORD(pface->ulFontRevision) / 100) % 10; + pifiex->awcUniqueName[3] = L'0' + (LOWORD(pface->ulFontRevision) / 10) % 10; + pifiex->awcUniqueName[4] = L'0' + LOWORD(pface->ulFontRevision) % 10; + EngMultiByteToUnicodeN(pifiex->awcUniqueName+6, 8, NULL, pifi->achVendId, 4); + + //__debugbreak(); + return TRUE; +} + PVOID -HackFixup( - PVOID pvView, - ULONG cjView) -{ - CHAR *pc; - - pc = EngAllocMem(0, cjView, 'tmp '); - memcpy(pc, pvView, cjView); - - *pc = 0; - - return pc; -} +APIENTRY +FtfdInitGlyphSet( + PFTFD_FACE pface) +{ + FT_Face ftface = pface->ftface; + FD_GLYPHSET *pGlyphSet; + FT_UInt index; + ULONG i, cRuns, cjSize; + HGLYPH * phglyphs; + WCHAR wcCurrent, wcPrev; + PWCHAR pwcReverseTable; + + TRACE("FtfdInitGlyphSet()\n"); + + /* Allocate an array of WCHARs */ + cjSize = pface->cGlyphs * sizeof(WCHAR); + pwcReverseTable = EngAllocMem(0, cjSize, 'dftF'); + if (!pwcReverseTable) + { + WARN("EngAllocMem() failed.\n"); + return NULL; + } + + /* Calculate FD_GLYPHSET size (incl. HGLYPH array!) */ + cjSize = FIELD_OFFSET(FD_GLYPHSET, awcrun) + + pface->cRuns * sizeof(WCRUN) + + pface->cMappings * sizeof(HGLYPH); + + /* Allocate the FD_GLYPHSET structure plus an array of HGLYPHs */ + pGlyphSet = EngAllocMem(0, cjSize, TAG_GLYPHSET); + if (!pGlyphSet) + { + WARN("EngAllocMem() failed.\n"); + return NULL; + } + + /* Get a pointer to the HGLYPH array */ + phglyphs = (PHGLYPH)&pGlyphSet->awcrun[pface->cRuns]; + + /* Initialize FD_GLYPHSET */ + pGlyphSet->cjThis = cjSize; + pGlyphSet->flAccel = GS_16BIT_HANDLES; + pGlyphSet->cGlyphsSupported = pface->cMappings; + pGlyphSet->cRuns = pface->cRuns; + + /* Loop through all character mappings */ + wcPrev = wcCurrent = (WCHAR)FT_Get_First_Char(ftface, &index); + for (i = 0, cRuns = 0; i < pface->cMappings && index; i++) + { + /* Create an entry in the reverse lookup table */ + ASSERT(index < pface->cGlyphs); + pwcReverseTable[index] = wcCurrent; + + /* Use index as glyph handle */ + phglyphs[i] = (HGLYPH)index; + + /* Check whether we can append the wchar to a run */ + if (wcCurrent == wcPrev + 1) + { + /* Append to current WCRUN */ + pGlyphSet->awcrun[cRuns - 1].cGlyphs++; + } + else + { + /* Add a new WCRUN */ + cRuns++; + pGlyphSet->awcrun[cRuns - 1].wcLow = wcCurrent - pface->wcCharBias; + pGlyphSet->awcrun[cRuns - 1].cGlyphs = 1; + pGlyphSet->awcrun[cRuns - 1].phg = &phglyphs[i]; + } + + /* Get the next charcode and index */ + wcPrev = wcCurrent; + wcCurrent = (WCHAR)FT_Get_Next_Char(ftface, wcCurrent, &index); + } + + TRACE("Done with font tree, %d runs\n", pGlyphSet->cRuns); + pface->pGlyphSet = pGlyphSet; + pface->pwcReverseTable = pwcReverseTable; + return pGlyphSet; +} + + +static +ULONG +FtfdGetFontFormat(FT_Face ftface) +{ + const char *pstrFormat; + + /* FreeType only provides a string :-/ */ + pstrFormat = FT_Get_X11_Font_Format(ftface); + if (strcmp(pstrFormat, "TrueType") == 0) return FMT_TRUETYPE; + if (strcmp(pstrFormat, "Type 1") == 0) return FMT_TYPE1; + if (strcmp(pstrFormat, "CFF") == 0) return FMT_CFF; + if (strcmp(pstrFormat, "Windows FNT") == 0) return FMT_FNT; + if (strcmp(pstrFormat, "BDF") == 0) return FMT_BDF; + if (strcmp(pstrFormat, "PCF") == 0) return FMT_PCF; + if (strcmp(pstrFormat, "Type 42") == 0) return FMT_TYPE42; + if (strcmp(pstrFormat, "CID Type 1") == 0) return FMT_CIDTYPE1; + if (strcmp(pstrFormat, "PFR") == 0) return FMT_PFR; + return FMT_UNKNOWN; +} + +static +ULONG +FtfdGetFileFormat( + PFTFD_FILE pfile) +{ + ULONG ulFontFormat = pfile->apface[0]->ulFontFormat; + + if (ulFontFormat == FMT_CFF) return FILEFMT_OTF; + if (ulFontFormat == FMT_FNT) return FILEFMT_FNT; + if (ulFontFormat == FMT_TRUETYPE) + { + if (*(DWORD*)pfile->pvView == 'OTTO') return FILEFMT_OTF; + return FILEFMT_TTF; + } + + __debugbreak(); + return 0; +} + +PFTFD_FACE +NTAPI +FtfdCreateFace( + PFTFD_FILE pfile, + ULONG iFace, + FT_Face ftface) +{ + PFTFD_FACE pface; + FT_Error fterror; + ULONG ulEncoding, ulAccumCharWidth = 0; + WCHAR wcCurrent, wcPrev; + FT_UInt index; + + /* Try to load a unicode charmap */ + ulEncoding = FT_ENCODING_UNICODE; + fterror = FT_Select_Charmap(ftface, ulEncoding); + if (fterror) + { + /* Check if we have any charmaps at all */ + if (ftface->num_charmaps == 0) + { + WARN("There are no charmaps available!\n"); + return NULL; + } + + /* Load first charmap instead */ + ulEncoding = ftface->charmaps[0]->encoding; + fterror = FT_Select_Charmap(ftface, ulEncoding); + if (fterror) + { + WARN("Could not load a charmap\n"); + return NULL; + } + + TRACE("Loaded charmap with encoding %.4s\n", &ulEncoding); + } + + pface = EngAllocMem(FL_ZERO_MEMORY, sizeof(FTFD_FACE), 'dftF'); + if (!pface) + { + WARN("Couldn't allcate a face\n"); + return NULL; + } + + /* Set basic fields */ + pface->pfile = pfile; + pface->iFace = iFace; + pface->ftface = ftface; + pface->cGlyphs = ftface->num_glyphs; + pface->ulEncoding = ulEncoding; + + /* Set char bias, FIXME: use lCharBias? other encodings? */ + pface->wcCharBias = ulEncoding == FT_ENCODING_MS_SYMBOL ? 0xf000 : 0; + + /* Get the font format */ + pface->ulFontFormat = FtfdGetFontFormat(ftface); + + /* Start with 0 runs and 0 mappings */ + pface->cMappings = 0; + pface->cRuns = 0; + + /* Loop through all character mappings */ + wcPrev = wcCurrent = (WCHAR)FT_Get_First_Char(ftface, &index); + pface->ifiex.ifi.wcFirstChar = wcCurrent - pface->wcCharBias;; + while (index) + { + /* Count the mapping */ + pface->cMappings++; + + /* If character is not subsequent, count a new run */ + if (wcCurrent != wcPrev + 1) pface->cRuns++; + wcPrev = wcCurrent; + + /* Get the next charcode and index */ + wcCurrent = (WCHAR)FT_Get_Next_Char(ftface, wcCurrent, &index); + } + + /* Save the last character */ + pface->ifiex.ifi.wcLastChar = wcPrev - pface->wcCharBias;; + + /* Initialize IFIMETRICS */ + FtfdInitIfiMetrics(pface); + + /* Initialize glyphset */ + FtfdInitGlyphSet(pface); + + /* Initialize kerning pairs */ + FtfdInitKerningPairs(pface); + + return pface; +} + +static +VOID +FtfdDestroyFace( + PFTFD_FACE pface) +{ + /* Cleanup the freetype face */ + FT_Done_Face(pface->ftface); + + /* Free the glyphset structure */ + EngFreeMem(pface->pGlyphSet); + + /* Free the kerning pairs structure */ + if (pface->pKerningPairs) EngFreeMem(pface->pKerningPairs); + + /* Finally free the face structure */ + EngFreeMem(pface); +} +
/** Public Interface **********************************************************/
@@ -36,121 +522,142 @@ ULONG ulFastCheckSum) { PVOID pvView; - ULONG cjView, i; + ULONG cjView, cjSize, cNumFaces, i; FT_Error fterror; FT_Face ftface; - PFTFD_FILE pfile; - ULONG cjSize, cNumFaces; - - DbgPrint("FtfdLoadFontFile()\n"); + PFTFD_FILE pfile = NULL; + + TRACE("FtfdLoadFontFile()\n"); +//__debugbreak(); +//return 0;
/* Check parameters */ if (cFiles != 1) { - DbgPrint("Only 1 File is allowed, got %ld!\n", cFiles); + WARN("Only 1 File is allowed, got %ld!\n", cFiles); return HFF_INVALID; }
/* Map the font file */ if (!EngMapFontFileFD(*piFile, (PULONG*)&pvView, &cjView)) { - DbgPrint("Could not map font file!\n"); + WARN("Could not map font file!\n"); return HFF_INVALID; }
- // HACK!!! - pvView = HackFixup(pvView, cjView); - + /* Load the first face */ fterror = FT_New_Memory_Face(gftlibrary, pvView, cjView, 0, &ftface); if (fterror) { - DbgPrint("No faces found in file\n"); - - /* Unmap the file */ - EngUnmapFontFileFD(*piFile); - /* Failure! */ - return HFF_INVALID; + WARN("No faces found in file\n"); + goto error; }
/* Get number of faces from the first face */ cNumFaces = ftface->num_faces;
- cjSize = sizeof(FTFD_FILE) + cNumFaces * sizeof(FT_Face); + /* Allocate the file structure */ + cjSize = sizeof(FTFD_FILE) + cNumFaces * sizeof(PVOID); pfile = EngAllocMem(0, cjSize, 'dftF'); if (!pfile) { - DbgPrint("EngAllocMem() failed.\n"); - - /* Unmap the file */ - EngUnmapFontFileFD(*piFile); - /* Failure! */ - return HFF_INVALID; - } - + WARN("EngAllocMem() failed.\n"); + goto error; + } + + /* Initialize the file structure */ pfile->cNumFaces = cNumFaces; pfile->iFile = *piFile; - pfile->pvView = pvView; - pfile->cjView = cjView; - - for (i = 0; i < pfile->cNumFaces; i++) - { - pfile->aftface[i] = ftface; - FT_Select_Charmap(ftface, FT_ENCODING_UNICODE); - } - - DbgPrint("Success! Returning %ld faces\n", cNumFaces); - + pfile->pvView = *ppvView; + pfile->cjView = *pcjView; + pfile->ulFastCheckSum = ulFastCheckSum; + + /* Create a face */ + pfile->apface[0] = FtfdCreateFace(pfile, 1, ftface); + if (!pfile->apface[0]) + { + WARN("FtfdCreateFace() failed.\n"); + goto error; + } + + /* Get the file format */ + pfile->ulFileFormat = FtfdGetFileFormat(pfile); + + /* Check for design vector */ + if (pdv) + { + /* Check if the font format supports it */ + if (pfile->apface[0]->ulFontFormat != FMT_TYPE1) + { + WARN("Design vector is not supported\n"); + goto error; + } + + /* Verify the design vector, just in case ... */ + if (pdv->dvReserved != STAMP_DESIGNVECTOR || + pdv->dvNumAxes > MM_MAX_NUMAXES) + { + WARN("Design vector is invalid\n"); + goto error; + } + + /* Copy design vector */ + pfile->dv = *pdv; + } + else + { + /* Mark as not present */ + pfile->dv.dvReserved = 0; + } + + /* Loop all additional faces in this file */ + for (i = 1; i < cNumFaces; i++) + { + /* Load the face */ + fterror = FT_New_Memory_Face(gftlibrary, *ppvView, *pcjView, i, &ftface); + if (fterror) + { + WARN("error\n"); + __debugbreak(); + goto error; + } + + /* Store the face in the file structure */ + pfile->apface[i] = FtfdCreateFace(pfile, i + 1, ftface); + } + + TRACE("Success! Returning %ld faces\n", cNumFaces); return (ULONG_PTR)pfile; -} - -BOOL -APIENTRY -FtfdUnloadFontFile( - IN ULONG_PTR iFile) -{ - PFTFD_FILE pfile = (PFTFD_FILE)iFile; - ULONG i; - - DbgPrint("FtfdUnloadFontFile()\n"); - - // HACK!!! - EngFreeMem(pfile->pvView); - - /* Cleanup faces */ - for (i = 0; i < pfile->cNumFaces; i++) - { - FT_Done_Face(pfile->aftface[i]); - } - - /* Unmap the font file */ - EngUnmapFontFileFD(pfile->iFile); - - /* Free the memory that was allocated for the font */ - EngFreeMem(pfile); - - return TRUE; -} - + +error: + if (pfile) EngFreeMem(pfile); + + /* Unmap the file */ + EngUnmapFontFileFD(*piFile); + + /* Failure! */ + return HFF_INVALID; +}
LONG APIENTRY FtfdQueryFontFile( - ULONG_PTR iFile, + ULONG_PTR diFile, ULONG ulMode, ULONG cjBuf, ULONG *pulBuf) { - PFTFD_FILE pfile = (PFTFD_FILE)iFile; - - DbgPrint("FtfdQueryFontFile(ulMode=%ld)\n", ulMode); -// __debugbreak(); + PFTFD_FILE pfile = (PFTFD_FILE)diFile; + + TRACE("FtfdQueryFontFile(ulMode=%ld)\n", ulMode);
switch (ulMode) { case QFF_DESCRIPTION: { + WARN("QFF_DESCRIPTION unimplemented\n"); return 0; }
@@ -162,171 +669,99 @@
return FD_ERROR; } -
PIFIMETRICS APIENTRY FtfdQueryFont( IN DHPDEV dhpdev, - IN ULONG_PTR iFile, + IN ULONG_PTR diFile, IN ULONG iFace, IN ULONG_PTR *pid) { - PFTFD_FILE pfile = (PFTFD_FILE)iFile; - PFTFD_IFIMETRICS pifiX; - PIFIMETRICS pifi; - FT_Face ftface; - FT_Error fterror; - ULONG i; - - DbgPrint("FtfdQueryFont()\n"); + PFTFD_FILE pfile = (PFTFD_FILE)diFile; + PFTFD_FACE pface = pfile->apface[iFace - 1]; + + TRACE("FtfdQueryFont()\n");
/* Validate parameters */ if (iFace > pfile->cNumFaces || !pid) { - DbgPrint("iFace > pfile->cNumFaces || !pid\n"); + WARN("iFace > pfile->cNumFaces || !pid\n"); return NULL; }
- fterror = FT_New_Memory_Face(gftlibrary, - pfile->pvView, - pfile->cjView, - iFace - 1, - &ftface); - if (fterror) - { - DbgPrint("FT_New_Memory_Face failed\n"); + /* Nothing to free */ + *pid = 0; + + /* Return pointer to the IFIMETRICS */ + return &pface->ifiex.ifi; +} + +PVOID +APIENTRY +FtfdQueryFontTree( + DHPDEV dhpdev, + ULONG_PTR diFile, + ULONG iFace, + ULONG iMode, + ULONG_PTR *pid) +{ + PFTFD_FILE pfile = (PFTFD_FILE)diFile; + PFTFD_FACE pface; + + TRACE("FtfdQueryFontTree(iMode=%ld)\n", iMode); + + /* Validate parameters */ + if (iFace > pfile->cNumFaces || !pid) + { + WARN("iFace > pfile->cNumFaces || !pid\n"); return NULL; }
- /* Allocate the ifi metrics structure */ - pifiX = EngAllocMem(FL_ZERO_MEMORY, sizeof(FTFD_IFIMETRICS), TAG_IFIMETRICS); - if (!pifiX) - { - DbgPrint("EngAllocMem() failed.\n"); - FT_Done_Face(ftface); - return NULL; - } - - /* Fill IFIMETRICS */ - pifi = &pifiX->ifim; - pifi->cjThis = sizeof(FTFD_IFIMETRICS); - pifi->cjIfiExtra = 0; - - /* Relative offsets */ - pifi->dpwszFamilyName = FIELD_OFFSET(FTFD_IFIMETRICS, wszFamilyName); - pifi->dpwszStyleName = FIELD_OFFSET(FTFD_IFIMETRICS, wszStyleName); - pifi->dpwszFaceName = FIELD_OFFSET(FTFD_IFIMETRICS, wszFaceName); - pifi->dpwszUniqueName = FIELD_OFFSET(FTFD_IFIMETRICS, wszFaceName); - pifi->dpCharSets = FIELD_OFFSET(FTFD_IFIMETRICS, ajCharSet); - pifi->dpFontSim = 0; - - /* Charsets */ - pifi->jWinCharSet = ANSI_CHARSET; - pifiX->ajCharSet[0] = pifi->jWinCharSet; - for (i = 1; i < 16; i++) - { - pifiX->ajCharSet[i] = DEFAULT_CHARSET; - } - - pifi->lEmbedId = 0; - pifi->lItalicAngle = 0; - pifi->lCharBias = 0; - pifi->jWinPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE; // FIXME - pifi->usWinWeight = FW_MEDIUM; // FIXME - pifi->flInfo = FM_INFO_TECH_TRUETYPE | FM_INFO_ARB_XFORMS | - FM_INFO_1BPP | FM_INFO_4BPP | - FM_INFO_RETURNS_OUTLINES | - FM_INFO_RETURNS_BITMAPS | - FM_INFO_RIGHT_HANDED; - pifi->fsSelection = 0; - pifi->fsType = 0; - - /* Font resolution */ - pifi->fwdUnitsPerEm = ftface->units_per_EM; - pifi->fwdLowestPPEm = 8; // FIXME - - /* Font metrics */ - pifi->fwdWinAscender = ftface->ascender; - pifi->fwdWinDescender = - ftface->descender; - pifi->fwdMacAscender = pifi->fwdWinAscender; - pifi->fwdMacDescender = - pifi->fwdWinDescender; - pifi->fwdMacLineGap = 0; - pifi->fwdTypoAscender = pifi->fwdWinAscender; - pifi->fwdTypoDescender = 0; // FIXME!!! - pifi->fwdWinDescender; - pifi->fwdTypoLineGap = 0; - pifi->fwdAveCharWidth = 1085; // FIXME - pifi->fwdMaxCharInc = ftface->max_advance_width; - pifi->fwdCapHeight = pifi->fwdUnitsPerEm / 2; - pifi->fwdXHeight = pifi->fwdUnitsPerEm / 4; - pifi->fwdSubscriptXSize = 0; - pifi->fwdSubscriptYSize = 0; - pifi->fwdSubscriptXOffset = 0; - pifi->fwdSubscriptYOffset = 0; - pifi->fwdSuperscriptXSize = 0; - pifi->fwdSuperscriptYSize = 0; - pifi->fwdSuperscriptXOffset = 0; - pifi->fwdSuperscriptYOffset = 0; - pifi->fwdUnderscoreSize = 1; - pifi->fwdUnderscorePosition = -1; - pifi->fwdStrikeoutSize = 1; - pifi->fwdStrikeoutPosition = pifi->fwdXHeight + 1; - - pifi->ptlBaseline.x = 1; - pifi->ptlBaseline.y = 0; - pifi->ptlAspect.x = 1; - pifi->ptlAspect.y = 1; - pifi->ptlCaret.x = 0; - pifi->ptlCaret.y = 1; - - /* Set the biggest characters bounding box */ - pifi->rclFontBox.left = ftface->bbox.xMin; - pifi->rclFontBox.right = ftface->bbox.xMax; - pifi->rclFontBox.top = ftface->bbox.yMax; - pifi->rclFontBox.bottom = ftface->bbox.yMin; - - /* Special characters */ - pifi->chFirstChar = 0x1c; // FIXME - pifi->chLastChar = 0x79; - pifi->chDefaultChar = 0x1d; - pifi->chBreakChar = 0x1e; - pifi->wcFirstChar = 0x1e; - pifi->wcLastChar = 0x79; - pifi->wcDefaultChar = 0x1d; - pifi->wcBreakChar = 0x1e; - - - *(DWORD*)&pifi->achVendId = 0x30303030; // FIXME - pifi->cKerningPairs = 0; - pifi->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN; -// pifi->panose = panose; - - EngMultiByteToUnicodeN(pifiX->wszFamilyName, - LF_FACESIZE, - NULL, - ftface->family_name, - strnlen(ftface->family_name, MAX_PATH)); - - EngMultiByteToUnicodeN(pifiX->wszStyleName, - LF_FACESIZE, - NULL, - ftface->style_name, - strnlen(ftface->style_name, MAX_PATH)); - - EngMultiByteToUnicodeN(pifiX->wszFaceName, - LF_FACESIZE, - NULL, - ftface->family_name, - strnlen(ftface->family_name, MAX_PATH)); - - FT_Done_Face(ftface); - - DbgPrint("Finished with the ifi: %p\n", pifiX); - __debugbreak(); - - return pifi; -} - + /* Get pointer to the requested face */ + pface = pfile->apface[iFace - 1]; + + switch (iMode) + { + case QFT_GLYPHSET: + *pid = 0; + return pface->pGlyphSet; + + case QFT_KERNPAIRS: + *pid = 0; + return pface->pKerningPairs; + + default: + WARN("Invalid iMode: %ld\n", iMode); + } + + return NULL; +} + +BOOL +APIENTRY +FtfdUnloadFontFile( + IN ULONG_PTR diFile) +{ + PFTFD_FILE pfile = (PFTFD_FILE)diFile; + ULONG i; + + TRACE("FtfdUnloadFontFile()\n"); + + /* Cleanup faces */ + for (i = 0; i < pfile->cNumFaces; i++) + { + FtfdDestroyFace(pfile->apface[i]); + } + + /* Unmap the font file */ + EngUnmapFontFileFD(pfile->iFile); + + /* Free the memory that was allocated for the file */ + EngFreeMem(pfile); + + return TRUE; +}
LONG APIENTRY @@ -334,7 +769,7 @@ ULONG culCaps, ULONG *pulCaps) { - DbgPrint("FtfdQueryFontCaps()\n"); + TRACE("FtfdQueryFontCaps()\n");
/* We need room for 2 ULONGs */ if (culCaps < 2) @@ -342,150 +777,24 @@ return FD_ERROR; }
- /* We only support 1 bpp */ + /* We only support bitmaps for now */ pulCaps[0] = 2; - pulCaps[1] = QC_1BIT; + pulCaps[1] = QC_1BIT | QC_4BIT;
return 2; }
-PVOID -APIENTRY -FtfdQueryFontTree( - DHPDEV dhpdev, - ULONG_PTR iFile, - ULONG iFace, - ULONG iMode, - ULONG_PTR *pid) -{ - PFTFD_FILE pfile = (PFTFD_FILE)iFile; - FT_Face ftface; - FT_Error fterror; - FTFD_CHARPAIR *pcp; - FD_GLYPHSET *pGlyphSet; - FT_ULong charcode; - ULONG i, j, cGlyphs, cRuns, cjSize; - WCRUN *pwcrun; - HGLYPH * phglyphs; - - DbgPrint("FtfdQueryFontTree()\n"); - - fterror = FT_New_Memory_Face(gftlibrary, - pfile->pvView, - pfile->cjView, - iFace - 1, - &ftface); - if (fterror) - { - DbgPrint("FT_New_Memory_Face() failed.\n"); - return NULL; - } - - /* Get inital value for cGlyphs from ftface */ - cGlyphs = ftface->num_glyphs + 1; - - /* Allocate a buffer for the char codes and glyph indexes */ - pcp = EngAllocMem(0, cGlyphs * sizeof(FTFD_CHARPAIR), 'pcp '); - if (!pcp) - { - DbgPrint("EngAllocMem() failed.\n"); - return NULL; - } - - /* Gather char codes and indexes and count WCRUNs */ - pcp[0].code = FT_Get_First_Char(ftface, &pcp[0].index); - charcode = pcp[0].code; - for (i = 1, cRuns = 1; charcode && i < cGlyphs; i++) - { - charcode = FT_Get_Next_Char(ftface, charcode, &pcp[i].index); - DbgPrint("charcode=0x%lx, index=0x%lx\n", charcode, pcp[i].index); - pcp[i].code = charcode; - if (charcode != pcp[i - 1].code + 1) - { - cRuns++; - } - } - - /* Update cGlyphs to real value */ - cGlyphs = i - 1; - - /* Calculate FD_GLYPHSET size */ - cjSize = sizeof(FD_GLYPHSET) - + (cRuns - 1) * sizeof(WCRUN) - + cGlyphs * sizeof(HGLYPH); - - /* Allocate the FD_GLYPHSET structure */ - pGlyphSet = EngAllocMem(0, cjSize, TAG_GLYPHSET); - if (!pGlyphSet) - { - DbgPrint("EngAllocMem() failed.\n"); - return NULL; - } - - /* Initialize FD_GLYPHSET */ - pGlyphSet->cjThis = cjSize; - pGlyphSet->flAccel = 0; - pGlyphSet->cGlyphsSupported = cGlyphs; - pGlyphSet->cRuns = cRuns; - - /* Initialize 1st WCRUN */ - pwcrun = pGlyphSet->awcrun; - phglyphs = (PHGLYPH)&pGlyphSet->awcrun[cRuns]; - pwcrun[0].wcLow = pcp[0].code; - pwcrun[0].cGlyphs = 1; - pwcrun[0].phg = &phglyphs[0]; - phglyphs[0] = pcp[0].index; - -DbgPrint("pcp[0].index = 0x%lx\n", pcp[0].index); - - /* Walk through all supported chars */ - for (i = 1, j = 0; i < cGlyphs; i++) - { - /* Use glyph index as HGLYPH */ - phglyphs[i] = pcp[i].index; - - /* Check whether we can append the wchar to a run */ - if (pcp[i].code == pcp[i - 1].code + 1) - { - /* Append to current WCRUN */ - pwcrun[j].cGlyphs++; - } - else - { - /* Add a new WCRUN */ - DbgPrint("adding new run\n"); - j++; - pwcrun[j].wcLow = pcp[i].code; - pwcrun[j].cGlyphs = 1; - pwcrun[j].phg = &phglyphs[i]; - } - } - - /* Free the temporary buffer */ - EngFreeMem(pcp); - - /* Set *pid to the allocated structure for use in FtfdFree */ - *pid = (ULONG_PTR)pGlyphSet; - -DbgPrint("pGlyphSet=%p\n", pGlyphSet); -__debugbreak(); - - return pGlyphSet; -} - +#if 0 // not needed atm VOID APIENTRY FtfdFree( PVOID pv, ULONG_PTR id) { - DbgPrint("FtfdFree()\n"); - if (id) - { - EngFreeMem((PVOID)id); - } -} - - - + TRACE("FtfdFree()\n"); + EngFreeMem(pv); +} +#endif + +
Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/ftfd.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/drivers/... ============================================================================== --- branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/ftfd.h [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/ftfd.h [iso-8859-1] Sun Aug 14 08:52:14 2011 @@ -11,41 +11,151 @@ #include <winddi.h>
#include <ft2build.h> -#include FT_FREETYPE_H +#include FT_FREETYPE_H +#include FT_ADVANCES_H +#include FT_XFREE86_H +#include FT_TYPE1_TABLES_H +#include FT_MULTIPLE_MASTERS_H +#include FT_TRIGONOMETRY_H +
extern FT_Library gftlibrary;
#define TAG_GLYPHSET 'GlSt' #define TAG_IFIMETRICS 'Ifim'
+#if 1// DBG +#define ASSERT(x) \ + if(!(x)) \ + { \ + DbgPrint("Assertion '%s' failed at %s:%i\n", #x, __FILE__, __LINE__); \ + __debugbreak(); \ + } +#define TRACE DbgPrint +#define WARN DbgPrint +#define FATAL DbgPrint +#else +#define ASSERT(x) +#define TRACE(...) +#define WARN(...) +#define FATAL(...) +#endif + +/* Helper for FLOATOBJ */ +#ifdef _M_IX86 +#define FLOATOBJ_bIsNull(pf) (((pf)->ul1 == 0) && ((pf)->ul2 == 0)) +#else +#define FLOATOBJ_bIsNull(pf) (*(pf) == 0) +#endif + /** Driver specific types *****************************************************/
+typedef enum +{ + FMT_UNKNOWN, + FMT_TRUETYPE, + FMT_TYPE1, + FMT_CFF, + FMT_FNT, + FMT_BDF, + FMT_PCF, + FMT_TYPE42, + FMT_CIDTYPE1, + FMT_PFR +} FONT_FORMAT; + +typedef enum +{ + FILEFMT_TTF, /* TrueType font file */ + FILEFMT_OTF, /* OpenType font file */ + FILEFMT_FNT, /* Windows .fnt file */ +} FILE_FORMAT; + +//"Bold Italic Underline Strikeout" +#define MAX_STYLESIZE 35 typedef struct { - FT_UInt index; - FT_ULong code; -} FTFD_CHARPAIR; + IFIMETRICS ifi; + BYTE ajCharSet[16]; + FONTSIM fontsim; + WCHAR awcFamilyName[LF_FACESIZE]; + WCHAR awcFaceName[LF_FACESIZE]; + WCHAR awcStyleName[MAX_STYLESIZE]; + WCHAR awcUniqueName[LF_FACESIZE + 11]; +} FTFD_IFIMETRICS, *PFTFD_IFIMETRICS;
typedef struct +{ + struct _FTFD_FILE *pfile; + FT_Face ftface; + ULONG iFace; + ULONG ulFontFormat; + ULONG cGlyphs; + ULONG cMappings; + ULONG cRuns; + ULONG ulFontRevision; + ULONG ulEncoding; + WCHAR wcCharBias; + PWCHAR pwcReverseTable; + FD_GLYPHSET *pGlyphSet; + FD_KERNINGPAIR *pKerningPairs; + FTFD_IFIMETRICS ifiex; +} FTFD_FACE, *PFTFD_FACE; + +typedef struct _FTFD_FILE { PVOID pvView; ULONG cjView; ULONG_PTR iFile; ULONG cNumFaces; - FT_Face aftface[1]; + ULONG ulFastCheckSum; + ULONG ulFileFormat; + DESIGNVECTOR dv; + PFTFD_FACE apface[1]; } FTFD_FILE, *PFTFD_FILE;
-//"Bold Italic Underline Strikeout" -#define MAX_STYLESIZE 35 +typedef struct _FTFD_DEVICEMETRICS +{ + union + { + POINTL aptl[8]; + struct + { + POINTL ptlUnderline1; + POINTL ptlStrikeout; + POINTL ptlULThickness; + POINTL ptlSOThickness; + POINTL aptfxBBox[4]; + }; + }; + FIX fxMaxAscender; + FIX fxMaxDescender; +} FTFD_DEVICEMETRICS; + +typedef struct _POINTEF +{ + FLOATOBJ x; + FLOATOBJ y; +} POINTEF, *PPOINTEF; + typedef struct { - IFIMETRICS ifim; - BYTE ajCharSet[16]; - FONTSIM fontsim; - WCHAR wszFamilyName[LF_FACESIZE]; - WCHAR wszFaceName[LF_FACESIZE]; - WCHAR wszStyleName[MAX_STYLESIZE]; -} FTFD_IFIMETRICS, *PFTFD_IFIMETRICS; + FONTOBJ *pfo; + PFTFD_FILE pfile; + PFTFD_FACE pface; + ULONG iFace; + FT_Face ftface; + FD_XFORM fdxQuantized; + FTFD_DEVICEMETRICS metrics; + RECTL rcfxBBox; + SIZEL sizlMax; + POINTEF ptefBase; + POINTEF ptefSide; + SIZEL sizlScale; + HGLYPH hgSelected; + UCHAR jBpp; +} FTFD_FONT, *PFTFD_FONT; +
/** Function prototypes *******************************************************/
@@ -127,6 +237,11 @@
VOID APIENTRY +FtfdDestroyFont( + FONTOBJ *pfo); + +VOID +APIENTRY FtfdFree( PVOID pv, ULONG_PTR id); @@ -148,3 +263,91 @@ PVOID pv, ULONG cjSize);
+BOOL +APIENTRY +FtfdQueryAdvanceWidths( + DHPDEV dhpdev, + FONTOBJ *pfo, + ULONG iMode, + HGLYPH *phg, + PVOID pvWidths, + ULONG cGlyphs); + +LONG +APIENTRY +FtfdQueryTrueTypeOutline( + DHPDEV dhpdev, + FONTOBJ *pfo, + HGLYPH hglyph, + BOOL bMetricsOnly, + GLYPHDATA *pgldt, + ULONG cjBuf, + TTPOLYGONHEADER *ppoly); + +LONG +APIENTRY +FtfdQueryTrueTypeTable( + ULONG_PTR iFile, + ULONG ulFont, + ULONG ulTag, + PTRDIFF dpStart, + ULONG cjBuf, + BYTE *pjBuf, + PBYTE *ppjTable, + ULONG *pcjTable); + +ULONG +APIENTRY +FtfdEscape( + SURFOBJ *pso, + ULONG iEsc, + ULONG cjIn, + PVOID pvIn, + ULONG cjOut, + PVOID pvOut); + +ULONG +APIENTRY +FtfdFontManagement( + SURFOBJ *pso, + FONTOBJ *pfo, + ULONG iMode, + ULONG cjIn, + PVOID pvIn, + ULONG cjOut, + PVOID pvOut); + +PVOID +APIENTRY +FtfdGetTrueTypeFile( + ULONG_PTR iFile, + ULONG *pcj); + +/* Private interface */ + +PVOID +NTAPI +FtfdFindTrueTypeTable( + PVOID pvView, + ULONG cjView, + ULONG iFace, + ULONG ulTag, + PULONG pulLength); + +BOOL +NTAPI +FtfdGetWinMetrics( + PFTFD_FACE pface, + PIFIMETRICS pifi); + +VOID +NTAPI +FtfdInitKerningPairs( + PFTFD_FACE pface); + +VOID +NTAPI +FtfdCopyBits( + BYTE jBppDst, + GLYPHBITS *pgb, + FT_Bitmap *ftbitmap);
Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/glyph.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/drivers/... ============================================================================== --- branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/glyph.c [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/glyph.c [iso-8859-1] Sun Aug 14 08:52:14 2011 @@ -1,23 +1,548 @@ /* * PROJECT: ReactOS win32 subsystem * LICENSE: GPL - See COPYING in the top level directory - * PURPOSE: GDI font driver for bitmap fonts + * PURPOSE: GDI font driver based on freetype * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) */
#include "ftfd.h"
+/** Private Interface *********************************************************/ + +#define FLOATL_1 0x3f800000 + +#define BITMAP_SIZE(cx, cy, bpp) \ + (((((((cx) * (bpp)) + 7) >> 3) * (cy)) + 3) & ~3) + +#define GLYPHBITS_SIZE(cx, cy, bpp) \ + (FIELD_OFFSET(GLYPHBITS, aj) + BITMAP_SIZE(cx, cy, bpp)) + +static +FLOATOBJ +FtfdNormalizeBaseVector( + POINTEF *pptef) +{ + FLOATOBJ efTmp, efLength; + FT_Vector ftvector; + LONG lLength; + + /* Optimization for scaling transformations */ + if (FLOATOBJ_bIsNull(&pptef->y)) + { + efLength = pptef->x; + FLOATOBJ_SetLong(&pptef->x, 1); + return efLength; + } + + if (FLOATOBJ_bIsNull(&pptef->x)) + { + efLength = pptef->y; + FLOATOBJ_SetLong(&pptef->y, -1); + return efLength; + } + + /* Convert the point into a 8.24 fixpoint vector */ + efTmp = pptef->x; + FLOATOBJ_MulLong(&efTmp, 0x01000000); + ftvector.x = FLOATOBJ_GetLong(&efTmp); + efTmp = pptef->y; + FLOATOBJ_MulLong(&efTmp, 0x01000000); + ftvector.y = FLOATOBJ_GetLong(&efTmp); + + /* Get the length of the fixpoint vector */ + lLength = FT_Vector_Length(&ftvector); + + /* Convert the fixpoint back into a FLOATOBJ */ + FLOATOBJ_SetLong(&efLength, lLength); + FLOATOBJ_DivLong(&efLength, 0x01000000); + + /* Now divide the vector by the length */ + FLOATOBJ_Div(&pptef->x, &efLength); + FLOATOBJ_Div(&pptef->y, &efLength); + + /* y axis is inverted! */ + FLOATOBJ_Neg(&pptef->y); + + /* Return the former length of the vector */ + return efLength; +} + +PFTFD_FONT +NTAPI +FtfdCreateFontInstance( + FONTOBJ *pfo) +{ + PFTFD_FILE pfile = (PFTFD_FILE)pfo->iFile; + PFTFD_FACE pface = pfile->apface[pfo->iFace - 1]; + PFTFD_FONT pfont; + XFORMOBJ* pxo; + FLOATOBJ_XFORM fxform; + FT_Error fterror; + FT_Face ftface; + FT_Matrix ftmatrix; + ULONG iComplexity; + FTFD_DEVICEMETRICS *pmetrics; + FLOATOBJ efTemp, efScaleX, efScaleY; + + /* Allocate a font structure */ + pfont = EngAllocMem(0, sizeof(FTFD_FONT), 0); + if (!pfont) + { + return NULL; + } + + /* Set basic fields */ + pfont->pfo = pfo; + pfont->pfile = pfile; + pfont->iFace = pfo->iFace; + pfont->pface = pface; + pfont->hgSelected = -1; + + + /* Create a freetype face */ + fterror = FT_New_Memory_Face(gftlibrary, + pfile->pvView, + pfile->cjView, + pfo->iFace - 1, + &ftface); + if (fterror) + { + /* Failure! */ + WARN("Error creating face\n"); + EngFreeMem(pfont); + return NULL; + } + + pfont->ftface = ftface; + + /* Set requested number of bits per pixel */ + pfont->jBpp = pfo->flFontType & FO_GRAY16 ? 4 : 1; + + /* Get the XFORMOBJ from the font */ + pxo = FONTOBJ_pxoGetXform(pfo); + if (!pxo) + { + WARN("Error there is no XFORMOBJ!\n"); + EngFreeMem(pfont); + return NULL; + } + + /* Get a FLOATOBJ_XFORM matrix */ + iComplexity = XFORMOBJ_iGetFloatObjXform(pxo, &fxform); + ASSERT(iComplexity != DDI_ERROR); + + // FIXME: quantize to 16.16 fixpoint + pfont->fdxQuantized.eXX = FLOATOBJ_GetFloat(&fxform.eM11); + pfont->fdxQuantized.eXY = FLOATOBJ_GetFloat(&fxform.eM12); + pfont->fdxQuantized.eYX = FLOATOBJ_GetFloat(&fxform.eM21); + pfont->fdxQuantized.eYY = FLOATOBJ_GetFloat(&fxform.eM22); + + /* Get the base vectors (unnormalized) */ + pfont->ptefBase.x = fxform.eM11; + pfont->ptefBase.y = fxform.eM21; + pfont->ptefSide.x = fxform.eM12; + pfont->ptefSide.y = fxform.eM22; + + /* Normalize the base vectors and get their length */ + efScaleX = FtfdNormalizeBaseVector(&pfont->ptefBase); + efScaleY = FtfdNormalizeBaseVector(&pfont->ptefSide); + + /* Calculate maximum ascender and descender */ + efTemp = efScaleY; + FLOATOBJ_MulLong(&efTemp, pface->ifiex.ifi.fwdWinAscender << 4); + pfont->metrics.fxMaxAscender = FLOATOBJ_GetLong(&efTemp); + efTemp = efScaleY; + FLOATOBJ_MulLong(&efTemp, pface->ifiex.ifi.fwdWinDescender << 4); + pfont->metrics.fxMaxDescender = FLOATOBJ_GetLong(&efTemp); + + /* The coordinate transformation given by Windows transforms from font + * space to device space. Since we use FT_Set_Char_Size, which allows + * higher precision than FT_Set_Pixel_Sizes, we need to convert into + * points. So we multiply our scaling coefficients with 72 divided by + * the device resolution. We also need a 26.6 fixpoint value, so we + * multiply with 64. */ + FLOATOBJ_MulLong(&efScaleX, 64 * pface->ifiex.ifi.fwdUnitsPerEm * 72); + FLOATOBJ_DivLong(&efScaleX, pfo->sizLogResPpi.cx); + pfont->sizlScale.cx = FLOATOBJ_GetLong(&efScaleX); + FLOATOBJ_MulLong(&efScaleY, 64 * pface->ifiex.ifi.fwdUnitsPerEm * 72); + FLOATOBJ_DivLong(&efScaleY, pfo->sizLogResPpi.cy); + pfont->sizlScale.cy = FLOATOBJ_GetLong(&efScaleY); + + /* Set the x and y character size for the font */ + fterror = FT_Set_Char_Size(ftface, + pfont->sizlScale.cx, + pfont->sizlScale.cy, + pfo->sizLogResPpi.cx, + pfo->sizLogResPpi.cy); + if (fterror) + { + /* Failure! */ + WARN("Error setting face size\n"); + EngFreeMem(pfont); + return NULL; + } + + /* Check if there is rotation / skewing (cannot use iComplexity!?) */ + if (!FLOATOBJ_bIsNull(&fxform.eM12) || !FLOATOBJ_bIsNull(&fxform.eM21)) + { + //__debugbreak(); + + /* Create a transformation matrix that is applied after the character + * scaling. We simply use the normalized base vectors and convert them + * to 16.16 fixpoint format */ + + efTemp = pfont->ptefBase.x; + FLOATOBJ_MulLong(&efTemp, 0x00010000); + ftmatrix.xx = FLOATOBJ_GetLong(&efTemp); + + efTemp = pfont->ptefSide.x; + FLOATOBJ_MulLong(&efTemp, 0x00010000); + ftmatrix.xy = FLOATOBJ_GetLong(&efTemp); + + efTemp = pfont->ptefBase.y; + FLOATOBJ_MulLong(&efTemp, 0x00010000); + ftmatrix.yx = FLOATOBJ_GetLong(&efTemp); + + efTemp = pfont->ptefSide.y; + FLOATOBJ_MulLong(&efTemp, 0x00010000); + ftmatrix.yy = FLOATOBJ_GetLong(&efTemp); + + /* Set the transformation matrix */ + FT_Set_Transform(ftface, &ftmatrix, 0); + } + + /* Check if there is a design vector */ + if (pfile->dv.dvReserved == STAMP_DESIGNVECTOR) + { + /* Set the coordinates */ + fterror = FT_Set_MM_Design_Coordinates(ftface, + pfile->dv.dvNumAxes, + pfile->dv.dvValues); + if (fterror) + { + /* Failure! */ + WARN("Failed to set design vector\n"); + EngFreeMem(pfont); + return NULL; + } + } + + /* Prepare required coordinates in font space */ + pmetrics = &pfont->metrics; + pmetrics->ptlUnderline1.x = 0; + pmetrics->ptlUnderline1.y = -pface->ifiex.ifi.fwdUnderscorePosition; + pmetrics->ptlStrikeout.x = 0; + pmetrics->ptlStrikeout.y = -pface->ifiex.ifi.fwdStrikeoutPosition;; + pmetrics->ptlULThickness.x = 0; + pmetrics->ptlULThickness.y = pface->ifiex.ifi.fwdUnderscoreSize; + pmetrics->ptlSOThickness.x = 0; + pmetrics->ptlSOThickness.y = pface->ifiex.ifi.fwdStrikeoutSize; + pmetrics->aptfxBBox[0].x = ftface->bbox.xMin << 4; + pmetrics->aptfxBBox[0].y = ftface->bbox.yMin << 4; + pmetrics->aptfxBBox[1].x = ftface->bbox.xMax << 4; + pmetrics->aptfxBBox[1].y = ftface->bbox.yMin << 4; + pmetrics->aptfxBBox[2].x = ftface->bbox.xMax << 4; + pmetrics->aptfxBBox[2].y = ftface->bbox.yMax << 4; + pmetrics->aptfxBBox[3].x = ftface->bbox.xMin << 4; + pmetrics->aptfxBBox[3].y = ftface->bbox.yMax << 4; + + /* Transform all coordinates into device space */ + if (!XFORMOBJ_bApplyXform(pxo, XF_LTOL, 8, pmetrics->aptl, pmetrics->aptl)) + { + WARN("Failed apply coordinate transformation.\n"); + EngFreeMem(pfont); + return NULL; + } + + /* Extract the bounding box in FIX device coordinates */ + pfont->rcfxBBox.left = min(pmetrics->aptfxBBox[0].x, pmetrics->aptfxBBox[1].x); + pfont->rcfxBBox.left = min(pfont->rcfxBBox.left, pmetrics->aptfxBBox[2].x); + pfont->rcfxBBox.left = min(pfont->rcfxBBox.left, pmetrics->aptfxBBox[3].x); + pfont->rcfxBBox.right = max(pmetrics->aptfxBBox[0].x, pmetrics->aptfxBBox[1].x); + pfont->rcfxBBox.right = max(pfont->rcfxBBox.right, pmetrics->aptfxBBox[2].x); + pfont->rcfxBBox.right = max(pfont->rcfxBBox.right, pmetrics->aptfxBBox[3].x); + pfont->rcfxBBox.top = min(pmetrics->aptfxBBox[0].y, pmetrics->aptfxBBox[1].y); + pfont->rcfxBBox.top = min(pfont->rcfxBBox.top, pmetrics->aptfxBBox[2].y); + pfont->rcfxBBox.top = min(pfont->rcfxBBox.top, pmetrics->aptfxBBox[3].y); + pfont->rcfxBBox.bottom = max(pmetrics->aptfxBBox[0].y, pmetrics->aptfxBBox[1].y); + pfont->rcfxBBox.bottom = max(pfont->rcfxBBox.bottom, pmetrics->aptfxBBox[2].y); + pfont->rcfxBBox.bottom = max(pfont->rcfxBBox.bottom, pmetrics->aptfxBBox[3].y); + + /* Round the bounding box margings to pixels */ + pfont->rcfxBBox.left = pfont->rcfxBBox.left & ~0xf; + pfont->rcfxBBox.top = pfont->rcfxBBox.top & ~0xf; + pfont->rcfxBBox.right = (pfont->rcfxBBox.right + 0xf) & ~0xf; + pfont->rcfxBBox.bottom = (pfont->rcfxBBox.bottom + 0xf) & ~0xf; + + /* Calculate maximum extents in pixels */ + pfont->sizlMax.cx = (pfont->rcfxBBox.right - pfont->rcfxBBox.left) >> 4; + pfont->sizlMax.cy = (pfont->rcfxBBox.bottom - pfont->rcfxBBox.top) >> 4; + + /* Fixup some minimum values */ + if (pmetrics->ptlULThickness.y <= 0) pmetrics->ptlULThickness.y = 1; + if (pmetrics->ptlSOThickness.y <= 0) pmetrics->ptlSOThickness.y = 1; + + TRACE("Created font of size %ld (%ld)\n", + pfont->sizlScale.cy, (pfont->sizlScale.cy+32)/64); + //__debugbreak(); + + /* Set the pvProducer member of the fontobj */ + pfo->pvProducer = pfont; + return pfont; +} + +static +PFTFD_FONT +FtfdGetFontInstance( + FONTOBJ *pfo) +{ + PFTFD_FONT pfont = pfo->pvProducer; + + /* Create a font instance if neccessary */ + if (!pfont) pfont = FtfdCreateFontInstance(pfo); + + /* Return the font instance */ + return pfont; +} + +ULONG +NTAPI +FtfdQueryMaxExtents( + FONTOBJ *pfo, + PFD_DEVICEMETRICS pfddm, + ULONG cjSize) +{ + PFTFD_FONT pfont = FtfdGetFontInstance(pfo); + PFTFD_FACE pface = pfont->pface; + FT_Face ftface = pfont->ftface; + + TRACE("FtfdQueryMaxExtents\n"); + + if (pfddm) + { + /* Verify parameter */ + if (cjSize < sizeof(FD_DEVICEMETRICS)) + { + /* Not enough space, fail */ + WARN("cjSize = %ld\n", cjSize); + return FD_ERROR; + } + + /* Accelerator flags (ignored atm) */ + pfddm->flRealizedType = 0; + + /* Set fixed width advance */ + if (FT_IS_FIXED_WIDTH(ftface)) + pfddm->lD = ftface->max_advance_width; + else + pfddm->lD = 0; + + /* Copy some values from the font structure */ + pfddm->fxMaxAscender = pfont->metrics.fxMaxAscender; + pfddm->fxMaxDescender = pfont->metrics.fxMaxDescender; + pfddm->ptlUnderline1 = pfont->metrics.ptlUnderline1; + pfddm->ptlStrikeout = pfont->metrics.ptlStrikeout; + pfddm->ptlULThickness = pfont->metrics.ptlULThickness; + pfddm->ptlSOThickness = pfont->metrics.ptlSOThickness; + pfddm->cxMax = pfont->sizlMax.cx; + pfddm->cyMax = pfont->sizlMax.cy; + + /* Convert the base vectors from FLOATOBJ to FLOATL */ + pfddm->pteBase.x = FLOATOBJ_GetFloat(&pfont->ptefBase.x); + pfddm->pteBase.y = FLOATOBJ_GetFloat(&pfont->ptefBase.y); + pfddm->pteSide.x = FLOATOBJ_GetFloat(&pfont->ptefSide.x); + pfddm->pteSide.y = FLOATOBJ_GetFloat(&pfont->ptefSide.y); + + /* cjGlyphMax is the full size of the GLYPHBITS structure */ + pfddm->cjGlyphMax = GLYPHBITS_SIZE(pfddm->cxMax, + pfddm->cyMax, + pfont->jBpp); + + /* Copy the quantized matrix from the font structure */ + pfddm->fdxQuantized = pfont->fdxQuantized; + + pfddm->lNonLinearExtLeading = 0x80000000; + pfddm->lNonLinearIntLeading = 0x80000000; // FIXME + pfddm->lNonLinearMaxCharWidth = 0x80000000; + pfddm->lNonLinearAvgCharWidth = 0x80000000; + + pfddm->lMinA = 0; + pfddm->lMinC = 0; + pfddm->lMinD = 0; + } + + TRACE("pfddm->fxMaxAscender=%ld, yScale=%ld, height=%ld\n", + pfddm->fxMaxAscender, pfont->sizlScale.cy, + (pfont->sizlScale.cy+32)/64); +//__debugbreak(); + + /* Return the size of the structure */ + return sizeof(FD_DEVICEMETRICS); +} + +static +BOOL +FtfdLoadGlyph( + PFTFD_FONT pfont, + HGLYPH hg, + ULONG iFormat) // 0 = bitmap, 1 = outline +{ + FT_Error fterror; + + /* Check if the glyph needs to be updated */ + if (pfont->hgSelected != hg) + { + /* Load the glyph into the freetype face slot */ + fterror = FT_Load_Glyph(pfont->ftface, hg, 0); + if (fterror) + { + WARN("Couldn't load glyph 0x%lx\n", hg); + pfont->hgSelected = -1; + return FALSE; + } + + /* Update the selected glyph */ + pfont->hgSelected = hg; + } + + return TRUE; +} + +static +VOID +FtfdQueryGlyphData( + FONTOBJ *pfo, + HGLYPH hg, + GLYPHDATA *pgd, + PVOID pvGlyphData) +{ + PFTFD_FONT pfont = pfo->pvProducer; + FT_GlyphSlot ftglyph = pfont->ftface->glyph; + SIZEL sizlBitmap; + + pgd->gdf.pgb = pvGlyphData; + pgd->hg = hg; + + if (1 /* layout horizontal */) + { + // FIXME: ftglyph->metrics doesn't handle non-orthogonal transformations + // http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_... + pgd->fxA = ftglyph->metrics.horiBearingX; + pgd->fxAB = pgd->fxA + ftglyph->metrics.width / 4; + } + else + { + pgd->fxA = ftglyph->metrics.vertBearingX; + pgd->fxAB = pgd->fxA + ftglyph->metrics.height; + } + + /* D is the glyph advance width */ + pgd->fxD = ftglyph->advance.x / 4; // FIXME: should be projected on the x-axis + + /* Get the bitnmap size */ + sizlBitmap.cx = ftglyph->bitmap.width; + sizlBitmap.cy = ftglyph->bitmap.rows; + + /* Make the bitmap at least 1x1 pixel large */ + if (sizlBitmap.cx == 0) sizlBitmap.cx++; + if (sizlBitmap.cy == 0) sizlBitmap.cy++; + + /* Don't let the bitmap be larger than the maximum */ + sizlBitmap.cx = min(sizlBitmap.cx, pfont->sizlMax.cx); + sizlBitmap.cy = min(sizlBitmap.cy, pfont->sizlMax.cy); + + /* This is the box in which the bitmap fits */ + pgd->rclInk.left = ftglyph->bitmap_left; + pgd->rclInk.top = -ftglyph->bitmap_top; + pgd->rclInk.right = pgd->rclInk.left + sizlBitmap.cx; + pgd->rclInk.bottom = pgd->rclInk.top + sizlBitmap.cy; + + /* FIX representation of bitmap top and bottom */ + pgd->fxInkBottom = (-pgd->rclInk.bottom) << 4; + pgd->fxInkTop = pgd->rclInk.top << 4; + + // FIXME: + pgd->ptqD.x.LowPart = pgd->fxD; + pgd->ptqD.x.HighPart = 0; + pgd->ptqD.y.LowPart = 0; + pgd->ptqD.y.HighPart = 0; + +//__debugbreak(); +} + +VOID +FtfdQueryGlyphBits( + FONTOBJ *pfo, + HGLYPH hg, + GLYPHBITS *pgb, + ULONG cjSize) +{ + PFTFD_FONT pfont = pfo->pvProducer; + FT_GlyphSlot ftglyph = pfont->ftface->glyph; + ULONG cjBitmapSize; + + pgb->ptlOrigin.x = ftglyph->bitmap_left; + pgb->ptlOrigin.y = - ftglyph->bitmap_top; + pgb->sizlBitmap.cx = ftglyph->bitmap.width; + pgb->sizlBitmap.cy = ftglyph->bitmap.rows; + + /* Make the bitmap at least 1x1 pixel large */ + if (pgb->sizlBitmap.cx == 0) pgb->sizlBitmap.cx++; + if (pgb->sizlBitmap.cy == 0) pgb->sizlBitmap.cy++; + + /* Don't let the bitmap be larger than the maximum */ + pgb->sizlBitmap.cx = min(pgb->sizlBitmap.cx, pfont->sizlMax.cx); + pgb->sizlBitmap.cy = min(pgb->sizlBitmap.cy, pfont->sizlMax.cy); + + cjBitmapSize = BITMAP_SIZE(pgb->sizlBitmap.cx, + pgb->sizlBitmap.cy, + pfont->jBpp); + if (cjBitmapSize + FIELD_OFFSET(GLYPHBITS, aj) > cjSize) + { + WARN("Buffer too small, got %ld, need %ld\n", + cjSize, cjBitmapSize + FIELD_OFFSET(GLYPHBITS, aj)); + __debugbreak(); + return; + } + + /* Copy the bitmap */ + FtfdCopyBits(pfont->jBpp, pgb, &ftglyph->bitmap); + + //TRACE("QueryGlyphBits hg=%lx, (%ld,%ld) cjSize=%ld, need %ld\n", + // hg, pgb->sizlBitmap.cx, pgb->sizlBitmap.cy, cjSize, + // GLYPHBITS_SIZE(pgb->sizlBitmap.cx, pgb->sizlBitmap.cy, pfont->jBpp)); +} + +VOID +FtfdQueryGlyphOutline( + FONTOBJ *pfo, + HGLYPH hg, + PATHOBJ *ppo, + ULONG cjSize) +{ + WARN("FtfdQueryGlyphOutline is unimplemented\n"); + __debugbreak(); +} + +BOOL +FtRenderGlyphBitmap( + PFTFD_FONT pfont) +{ + FT_Error fterror; + FT_Render_Mode mode; + + mode = pfont->jBpp == 1 ? FT_RENDER_MODE_MONO : FT_RENDER_MODE_NORMAL; + fterror = FT_Render_Glyph(pfont->ftface->glyph, mode); + if (fterror) + { + WARN("Cound't render glyph\n"); + return FALSE; + } + + return TRUE; +}
/** Public Interface **********************************************************/ - -PFD_GLYPHATTR -APIENTRY -FtfdQueryGlyphAttrs( - FONTOBJ *pfo, - ULONG iMode) -{ - return NULL; -}
LONG APIENTRY @@ -30,5 +555,226 @@ PVOID pv, ULONG cjSize) { + PFTFD_FONT pfont = FtfdGetFontInstance(pfo); + ULONG cx, cy; + + //TRACE("FtfdQueryFontData, iMode=%ld, hg=%lx, pgd=%p, pv=%p, cjSize=%ld\n", + // iMode, hg, pgd, pv, cjSize); + + switch (iMode) + { + case QFD_GLYPHANDBITMAP: + /* Load the requested glyph */ + if (!FtfdLoadGlyph(pfont, hg, 0)) return FD_ERROR; + + /* Render the glyph bitmap */ + if (!FtRenderGlyphBitmap(pfont)) return FD_ERROR; + + if (pgd) FtfdQueryGlyphData(pfo, hg, pgd, pv); + + + if (pv) + { + FtfdQueryGlyphBits(pfo, hg, pv, cjSize); + } + + /* Return the size for a bitmap at least 1x1 pixels */ + cx = pfont->ftface->glyph->bitmap.width; + cy = pfont->ftface->glyph->bitmap.rows; + return GLYPHBITS_SIZE(cx > 0 ? cx : 1, + cy > 0 ? cy : 1, + pfont->jBpp); + + case QFD_GLYPHANDOUTLINE: + TRACE("QFD_GLYPHANDOUTLINE\n"); + + /* Load the requested glyph */ + if (!FtfdLoadGlyph(pfont, hg, 1)) return FD_ERROR; + + if (pgd) + { + FtfdQueryGlyphData(pfo, hg, pgd, pv); + } + + if (pv) + { + FtfdQueryGlyphOutline(pfo, hg, pv, cjSize); + } + break; + + case QFD_MAXEXTENTS: + return FtfdQueryMaxExtents(pfo, pv, cjSize); + + case QFD_TT_GRAY1_BITMAP: + TRACE("QFD_TT_GRAY1_BITMAP\n"); + break; + case QFD_TT_GRAY2_BITMAP: + TRACE("QFD_TT_GRAY2_BITMAP\n"); + break; + case QFD_TT_GRAY4_BITMAP: + TRACE("QFD_TT_GRAY4_BITMAP\n"); + break; + case QFD_TT_GRAY8_BITMAP: + TRACE("QFD_TT_GRAY8_BITMAP\n"); + break; + default: + WARN("Invalid iMode value: %lx\n", iMode); + EngSetLastError(ERROR_INVALID_PARAMETER); + return FD_ERROR; + } + + __debugbreak(); + + return FD_ERROR; } + +PFD_GLYPHATTR +APIENTRY +FtfdQueryGlyphAttrs( + FONTOBJ *pfo, + ULONG iMode) +{ + TRACE("FtfdQueryGlyphAttrs\n"); + + /* Verify parameters */ + if (!pfo || iMode != FO_ATTR_MODE_ROTATE) + { + WARN("Invalid parameters: %p, %ld\n", pfo, iMode); + return NULL; + } + + + + __debugbreak(); + return NULL; +} + +BOOL +APIENTRY +FtfdQueryAdvanceWidths( + DHPDEV dhpdev, + FONTOBJ *pfo, + ULONG iMode, + HGLYPH *phg, + PVOID pvWidths, + ULONG cGlyphs) +{ + PFTFD_FONT pfont = FtfdGetFontInstance(pfo); + PUSHORT pusWidths = pvWidths; + BOOL bResult = TRUE; + ULONG i, fl; + FT_Face ftface = pfont->ftface; + FT_Error fterror; + FT_Fixed advance; + + //TRACE("FtfdQueryAdvanceWidths\n"); + + /* The selected glyph will be changed */ + pfont->hgSelected = -1; + + /* Check if fast version is requested */ + if (0 && iMode == QAW_GETEASYWIDTHS) + { + fl = FT_ADVANCE_FLAG_FAST_ONLY; + + /* Check if the font layout is vertical */ + if (ftface->face_flags & FT_FACE_FLAG_VERTICAL) + { + fl |= FT_LOAD_VERTICAL_LAYOUT; + } + + /* Loop all requested glyphs */ + for (i = 0; i < cGlyphs; i++) + { + /* Query advance width */ + fterror = FT_Get_Advances(ftface, (FT_UInt)phg[i], 1, fl, &advance); + if (fterror || advance > 0xFFFF) + { + pusWidths[i] = 0xffff; + bResult = FALSE; + } + else + { + pusWidths[i] = (USHORT)(advance >> 2); + //TRACE("Got advance width: hg=%lx, adv=%lx->%ld\n", phg[i], advance, pt.x); + } + } + } + else + { + /* Loop all requested glyphs */ + for (i = 0; i < cGlyphs; i++) + { + /* Load the glyph */ + fterror = FT_Load_Glyph(ftface, (FT_UInt)phg[i], 0); + if (fterror) + { + pusWidths[i] = 0xffff; + bResult = FALSE; // FIXME: return FALSE or DDI_ERROR? + } + else + { + pusWidths[i] = (USHORT)ftface->glyph->advance.x >> 2; + } + } + } + + //__debugbreak(); + return bResult; +} + +LONG +APIENTRY +FtfdQueryTrueTypeOutline( + DHPDEV dhpdev, + FONTOBJ *pfo, + HGLYPH hg, + BOOL bMetricsOnly, + GLYPHDATA *pgldt, + ULONG cjBuf, + TTPOLYGONHEADER *ppoly) +{ + TRACE("FtfdQueryTrueTypeOutline\n"); + __debugbreak(); + return 0; +} + +ULONG +APIENTRY +FtfdFontManagement( + SURFOBJ *pso, + FONTOBJ *pfo, + ULONG iMode, + ULONG cjIn, + PVOID pvIn, + ULONG cjOut, + PVOID pvOut) +{ + TRACE("FtfdFontManagement\n"); + __debugbreak(); + return 0; +} + +VOID +APIENTRY +FtfdDestroyFont( + FONTOBJ *pfo) +{ + PFTFD_FONT pfont = pfo->pvProducer; + + TRACE("FtfdDestroyFont()\n"); + + /* Nothing to do? */ + if (!pfont) return; + + /* We don't need this anymore */ + pfo->pvProducer = NULL; + + /* Cleanup the freetype face for this font */ + FT_Done_Face(pfont->ftface); + + /* Free the font structure */ + EngFreeMem(pfont); +} +
Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/rosglue.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/drivers/... ============================================================================== --- branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/rosglue.c [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/rosglue.c [iso-8859-1] Sun Aug 14 08:52:14 2011 @@ -29,7 +29,7 @@ va_list args;
va_start(args, Format); - EngDebugPrint("ft2: ", (PCHAR)Format, args); + EngDebugPrint("ftfd: ", (PCHAR)Format, args); va_end(args); return 0; }