--- a/dlls/gdi32/freetype.c.1.1.12.orig 2009-01-02 20:45:05.000000000 -0600 +++ b/dlls/gdi32/freetype.c 2009-01-03 12:43:54.000000000 -0600 @@ -208,6 +208,17 @@ MAKE_FUNCPTR(FcPatternDestroy); MAKE_FUNCPTR(FcPatternGetBool); MAKE_FUNCPTR(FcPatternGetString); +MAKE_FUNCPTR(FcPatternGetDouble); +MAKE_FUNCPTR(FcPatternBuild); +MAKE_FUNCPTR(FcFontMatch); +MAKE_FUNCPTR(FcConfigSubstitute); +MAKE_FUNCPTR(FcDefaultSubstitute); +MAKE_FUNCPTR(FcPatternGetInteger); +MAKE_FUNCPTR(FcPatternGetCharSet); +MAKE_FUNCPTR(FcCharSetCopy); +MAKE_FUNCPTR(FcCharSetCount); +MAKE_FUNCPTR(FcCharSetDestroy); +MAKE_FUNCPTR(FcPatternGetMatrix); #endif #undef MAKE_FUNCPTR @@ -318,6 +329,16 @@ GdiFont *font; } CHILD_FONT; + +#ifdef SONAME_LIBFONTCONFIG +typedef struct { + FT_Int load_flags; + WCHAR * fc_family; + int fc_pixel_size, fake_italic; + char * filename; +} FC_DATA; +#endif + struct tagGdiFont { struct list entry; GM **gm; @@ -328,6 +349,11 @@ KERNINGPAIR *kern_pairs; struct list child_fonts; +#ifdef SONAME_LIBFONTCONFIG + BOOL use_fc_data; + FC_DATA fc_data; +#endif + /* the following members can be accessed without locking, they are never modified after creation */ FT_Face ft_face; struct font_mapping *mapping; @@ -482,6 +508,12 @@ static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph); +#ifdef SONAME_LIBFONTCONFIG +BOOL GetFCData(LOGFONTW *lf, FC_DATA *fc_data); +BOOL use_fontconfig(void); +static BOOL use_fc; +#endif + /**************************************** * Notes on .fon files * @@ -1787,7 +1819,6 @@ static void load_fontconfig_fonts(void) { #ifdef SONAME_LIBFONTCONFIG - void *fc_handle = NULL; FcConfig *config; FcPattern *pat; FcObjectSet *os; @@ -1796,26 +1827,6 @@ char *file; const char *ext; - fc_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0); - if(!fc_handle) { - TRACE("Wine cannot find the fontconfig library (%s).\n", - SONAME_LIBFONTCONFIG); - return; - } -#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(fc_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;} -LOAD_FUNCPTR(FcConfigGetCurrent); -LOAD_FUNCPTR(FcFontList); -LOAD_FUNCPTR(FcFontSetDestroy); -LOAD_FUNCPTR(FcInit); -LOAD_FUNCPTR(FcObjectSetAdd); -LOAD_FUNCPTR(FcObjectSetCreate); -LOAD_FUNCPTR(FcObjectSetDestroy); -LOAD_FUNCPTR(FcPatternCreate); -LOAD_FUNCPTR(FcPatternDestroy); -LOAD_FUNCPTR(FcPatternGetBool); -LOAD_FUNCPTR(FcPatternGetString); -#undef LOAD_FUNCPTR - if(!pFcInit()) return; config = pFcConfigGetCurrent(); @@ -1851,7 +1862,6 @@ pFcFontSetDestroy(fontset); pFcObjectSetDestroy(os); pFcPatternDestroy(pat); - sym_not_found: #endif return; } @@ -2354,6 +2364,36 @@ RegDeleteValueA(hkey, name); } +BOOL use_fontconfig(void) +{ + DWORD len, type, value; + HKEY hkey = 0; + + if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL) != ERROR_SUCCESS) + { + TRACE ("Not using fontconfig data for rendering fonts"); + return FALSE; + } + + len = sizeof(DWORD); + if (RegQueryValueExA(hkey, "UseFontconfig", 0, &type, (BYTE *)&value, &len) == ERROR_SUCCESS) + { + if (value > 0) + { + TRACE ("Using fontconfig data for rendering fonts"); + RegCloseKey(hkey); + return TRUE; + } + } + + /* FIXME */ + /*value = 0; + if (RegSetValueExW(hkey, "UseFontconfig", 0, REG_DWORD, (CONST BYTE *)&value, sizeof(DWORD)) == ERROR_SUCCESS) printf ("******* SUCCESS ******"); + else printf ("******* UNABLE TO SET VALUE ******");*/ + RegCloseKey(hkey); + return FALSE; +} + static void update_font_info(void) { char buf[40], cpbuf[40]; @@ -2544,6 +2584,62 @@ return FALSE; } + +static BOOL init_fontconfig(void) +{ + + + void *fc_handle = NULL; + + fc_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0); + if(!fc_handle) { + TRACE("Wine cannot find the fontconfig library (%s).\n", + SONAME_LIBFONTCONFIG); + return FALSE; + } +#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(fc_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;} +LOAD_FUNCPTR(FcConfigGetCurrent); +LOAD_FUNCPTR(FcFontList); +LOAD_FUNCPTR(FcFontSetDestroy); +LOAD_FUNCPTR(FcInit); +LOAD_FUNCPTR(FcObjectSetAdd); +LOAD_FUNCPTR(FcObjectSetCreate); +LOAD_FUNCPTR(FcObjectSetDestroy); +LOAD_FUNCPTR(FcPatternCreate); +LOAD_FUNCPTR(FcPatternDestroy); +LOAD_FUNCPTR(FcPatternGetBool); +LOAD_FUNCPTR(FcPatternGetDouble); +LOAD_FUNCPTR(FcPatternGetString); +LOAD_FUNCPTR(FcPatternGetInteger); + +LOAD_FUNCPTR(FcPatternBuild); +LOAD_FUNCPTR(FcFontMatch); +LOAD_FUNCPTR(FcConfigSubstitute); +LOAD_FUNCPTR(FcDefaultSubstitute); +LOAD_FUNCPTR(FcPatternGetCharSet); +LOAD_FUNCPTR(FcCharSetCopy); +LOAD_FUNCPTR(FcPatternGetMatrix); +LOAD_FUNCPTR(FcCharSetCount); +LOAD_FUNCPTR(FcCharSetDestroy); + +#undef LOAD_FUNCPTR + + + use_fc = use_fontconfig(); + return TRUE; + +sym_not_found: + WINE_MESSAGE( + "Wine cannot find certain functions that it needs inside the Fontconfig\n" + "font library. \n" +); + use_fc = use_fontconfig(); + wine_dlclose(fc_handle, NULL, 0); + fc_handle = NULL; + return FALSE; +} + + /************************************************************* * WineEngInit * @@ -2567,6 +2663,7 @@ update_font_info(); if(!init_freetype()) return FALSE; + if(!init_fontconfig()) return FALSE; if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) { ERR("Failed to create font mutex\n"); @@ -2840,6 +2937,7 @@ if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0) WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", width, height, err); } + return ft_face; } @@ -3312,6 +3410,11 @@ FMAT2 dcmat; FontSubst *psub = NULL; +#ifdef SONAME_LIBFONTCONFIG + FC_DATA fc_data; + BOOL use_fc_data = FALSE; +#endif + if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL; lf.lfWidth = abs(lf.lfWidth); @@ -3396,6 +3499,18 @@ } } +#ifdef SONAME_LIBFONTCONFIG + if (use_fc){ + use_fc_data = GetFCData(&ret->font_desc.lf, &fc_data); + if (use_fc_data){ + TRACE("Using fontconfig for hinting / replacements: %s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n", + debugstr_w(fc_data.fc_family), fc_data.fc_pixel_size, lf.lfItalic, + lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation, + lf.lfEscapement); + } + } +#endif + family = NULL; if(lf.lfFaceName[0] != '\0') { SYSTEM_LINKS *font_link; @@ -3601,6 +3716,14 @@ else ret->charset = get_nearest_charset(face, &ret->codepage); +#ifdef SONAME_LIBFONTCONFIG + if (use_fc && use_fc_data) + { + face->file = fc_data.filename; + ret->fake_italic = (fc_data.fake_italic > 0); + } +#endif + TRACE("Chosen: %s %s (%s/%p:%ld)\n", debugstr_w(family->FamilyName), debugstr_w(face->StyleName), face->file, face->font_data_ptr, face->face_index); @@ -3632,7 +3755,16 @@ ret->scale_y = 1.0; TRACE("font scale y: %f\n", ret->scale_y); +#ifdef SONAME_LIBFONTCONFIG + if (use_fc && use_fc_data) + { + ret->ft_face = OpenFontFace(ret, face, width, fc_data.fc_pixel_size); + ret->use_fc_data = use_fc_data; + } + else ret->ft_face = OpenFontFace(ret, face, width, height); +#else ret->ft_face = OpenFontFace(ret, face, width, height); +#endif if (!ret->ft_face) { @@ -3673,6 +3805,10 @@ TRACE("caching: gdiFont=%p hfont=%p\n", ret, hfont); +#ifdef SONAME_LIBFONTCONFIG + ret->fc_data = fc_data; +#endif + add_to_cache(ret); LeaveCriticalSection( &freetype_cs ); return ret; @@ -4346,6 +4482,171 @@ } /************************************************************* + * GetFCData + * Load fontconfig data for hinting and replacements + */ +BOOL GetFCData(LOGFONTW *lf, FC_DATA * fc_data) +{ +#ifdef SONAME_LIBFONTCONFIG + FT_Int load_flags = 0, fcweight, fcslant; + FcPattern *pat, *matched; + FcResult *result = 0; + FcBool hinting, autohint; + FcMatrix *font_matrix; + WCHAR * family_name = NULL; + char *file; + int hintstyle; + double fcheight; + const char *df = "Tahoma"; + const char *df2 = "Arial"; + char *fn; + int len; + + /***** Gather information from the requested font ****/ + + fn=strndup(debugstr_w(lf->lfFaceName)+2, strlen(debugstr_w(lf->lfFaceName))-3) ; + + /* FIXME - Hardcoded - should be configurable with fontconfig, but haven't + figured out how to accomlish this yet */ + if (strcmp(fn, "System") == 0) return FALSE; //strcpy(fn, df); + if (strcmp(fn, "MS Shell Dlg") == 0) strcpy(fn, df); + if (strcmp(fn, "MS Sans Serif") == 0) strcpy(fn, df); + if (strcmp(fn, "Helvetica") == 0) strcpy(fn, df2); + if (strcmp(fn, "Helv") == 0) strcpy(fn, df2); + + //TRACE("Requested Family: %s, ", fn); + switch (lf->lfWeight) { + case 700: + case 600: + fcweight = FC_WEIGHT_BOLD; + //TRACE("Requested Weight: BOLD, "); + break; + case 400: + default: + fcweight = FC_WEIGHT_NORMAL; + //TRACE("Requested Weight: NORMAL, "); + break; + } + switch (lf->lfItalic) { + case TRUE: + fcslant = FC_SLANT_ITALIC; + //TRACE("Requested Style: ITALIC, "); + break; + case FALSE: + default: + fcslant = FC_SLANT_ROMAN; + //TRACE("Requested Style: NORMAL, "); + break; + } + fcheight = abs(lf->lfHeight); + //TRACE("Requested PPEM: %d, ", lf->lfHeight); + + /***** Create fontconfig pattern and get data from the match ****/ + + pat = pFcPatternBuild (NULL, + FC_FAMILY, FcTypeString, fn, + FC_PIXEL_SIZE, FcTypeDouble, fcheight, + FC_WEIGHT, FcTypeInteger, fcweight, + FC_SLANT, FcTypeInteger, fcslant, + NULL); + pFcConfigSubstitute(0, pat, FcMatchPattern); + pFcDefaultSubstitute(pat); + matched = pFcFontMatch (0, pat, result); + + pFcPatternGetString(matched, FC_FAMILY, 0, &fn); + pFcPatternGetDouble(matched, FC_PIXEL_SIZE, 0, &fcheight); + + fc_data->fc_pixel_size = -(int)fcheight; + //TRACE("Matched PPEM: %d, ", fc_data->fc_pixel_size); + + len = MultiByteToWideChar(CP_ACP, 0, fn, -1, NULL, 0); + family_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, fn, -1, family_name, len); + fc_data->fc_family = family_name; + //TRACE("Matched Family Name: %s", debugstr_w(fc_data->fc_family)); + + /***** Create load flags for freetype, based on matched data ****/ + /* TODO: Fully implement other FC features like matrix, charset, embolden, etc.) */ + + /* FIXME: A hack that detects ANY matrix value and assumes it is fake_italic */ + fc_data->fake_italic = 0; + switch (pFcPatternGetMatrix (matched, FC_MATRIX, 0, &font_matrix)) { + case FcResultNoMatch: + break; + case FcResultMatch: + fc_data->fake_italic = 1; + break; + default: + goto bail1; + } + + if (pFcPatternGetString (matched, FC_FILE, 0, &file) == FcResultMatch) + { + fc_data->filename = file; + //TRACE("Matched Filename: %s, ", file); + } + + if (pFcPatternGetBool (matched, FC_HINTING, 0, &hinting) != FcResultMatch) + { + //TRACE("Matched Hinting: OFF, "); + } else { + //TRACE("Matched Hinting: ON, "); + } + + if (pFcPatternGetInteger (matched, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) + hintstyle = FC_HINT_FULL; + + if (!hinting) hintstyle = FC_HINT_NONE; + + switch (hintstyle) { + case FC_HINT_NONE: + load_flags = load_flags | FT_LOAD_NO_HINTING; + //TRACE("Matched Hintstyle: NONE, "); + break; + case FC_HINT_SLIGHT: + load_flags = load_flags | FT_LOAD_TARGET_LIGHT; + //TRACE("Matched Hintstyle: SLIGHT, "); + break; + case FC_HINT_MEDIUM: + default: + //TRACE("Matched Hintstyle: MEDIUM, "); + break; + case FC_HINT_FULL: + //TRACE("Matched Hintstyle: FULL, "); + break; + } + + autohint = FcTrue; + /* force autohinting if requested */ + switch (pFcPatternGetBool (matched, FC_AUTOHINT, 0, &autohint)) { + case FcResultNoMatch: + autohint = FcFalse; + break; + case FcResultMatch: + break; + default: + goto bail1; + } + + if (autohint){ + load_flags |= FT_LOAD_FORCE_AUTOHINT; + //TRACE( "Using autohint, " ); + } else { + //TRACE( "Using native hinter, " ); + } + + pFcPatternDestroy (pat); + pFcPatternDestroy (matched); + + fc_data->load_flags = load_flags; + + return TRUE; +bail1: +#endif + return FALSE; +} + +/************************************************************* * WineEngGetGlyphOutline * * Behaves in exactly the same way as the win32 api GetGlyphOutline @@ -4509,7 +4810,19 @@ load_flags |= FT_LOAD_NO_BITMAP; } +#ifdef SONAME_LIBFONTCONFIG + if (use_fc && font->use_fc_data) + { + load_flags = load_flags | font->fc_data.load_flags; + err = pFT_Load_Glyph(font->ft_face, glyph_index, load_flags); + } else { + err = pFT_Load_Glyph(ft_face, glyph_index, load_flags); + } +#else err = pFT_Load_Glyph(ft_face, glyph_index, load_flags); +#endif + + if(err) { WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);