diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index de40d9f44d9..33e196ce89b 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -364,6 +364,12 @@ typedef struct { GdiFont *font; } CHILD_FONT; +struct font_fileinfo { + FILETIME writetime; + LARGE_INTEGER size; + WCHAR path[1]; +}; + struct tagGdiFont { struct list entry; struct list unused_entry; @@ -400,6 +406,7 @@ struct tagGdiFont { const VOID *vert_feature; DWORD cache_num; DWORD instance_id; + struct font_fileinfo *fileinfo; }; typedef struct { @@ -4505,6 +4512,7 @@ static void free_font(GdiFont *font) HeapFree(GetProcessHeap(), 0, child); } + HeapFree(GetProcessHeap(), 0, font->fileinfo); free_font_handle(font->instance_id); if (font->ft_face) pFT_Done_Face(font->ft_face); if (font->mapping) unmap_font_file( font->mapping ); @@ -5161,6 +5169,29 @@ static const VOID * get_GSUB_vert_feature(const GdiFont *font) return feature; } +static void fill_fileinfo_from_face( GdiFont *font, Face *face ) +{ + WIN32_FILE_ATTRIBUTE_DATA info; + int len; + + if (!face->file) + { + font->fileinfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*font->fileinfo)); + return; + } + + len = strlenW(face->file); + font->fileinfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*font->fileinfo) + len * sizeof(WCHAR)); + if (GetFileAttributesExW(face->file, GetFileExInfoStandard, &info)) + { + font->fileinfo->writetime = info.ftLastWriteTime; + font->fileinfo->size.QuadPart = (LONGLONG)info.nFileSizeHigh << 32 | info.nFileSizeLow; + strcpyW(font->fileinfo->path, face->file); + } + else + memset(&font->fileinfo, 0, sizeof(*font->fileinfo) + len * sizeof(WCHAR)); +} + /************************************************************* * freetype_SelectFont */ @@ -5555,6 +5586,7 @@ found_face: goto done; } + fill_fileinfo_from_face( ret, face ); ret->ntmFlags = face->ntmFlags; pick_charmap( ret->ft_face, ret->charset ); @@ -8238,7 +8270,7 @@ static BOOL freetype_GetFontRealizationInfo( PHYSDEV dev, void *ptr ) return dev->funcs->pGetFontRealizationInfo( dev, ptr ); } - FIXME("(%p, %p): stub!\n", physdev->font, info); + TRACE("(%p, %p)\n", physdev->font, info); info->flags = 1; if(FT_IS_SCALABLE(physdev->font->ft_face)) @@ -8255,6 +8287,33 @@ static BOOL freetype_GetFontRealizationInfo( PHYSDEV dev, void *ptr ) return TRUE; } +/************************************************************************* + * GetFontFileInfo (GDI32.@) + */ +BOOL WINAPI GetFontFileInfo( DWORD instance_id, DWORD unknown, struct font_fileinfo *info, DWORD size, DWORD *needed ) +{ + struct font_handle_entry *entry = handle_entry( instance_id ); + const GdiFont *font; + + if (!entry) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + font = entry->obj; + *needed = sizeof(*info) + strlenW(font->fileinfo->path) * sizeof(WCHAR); + if (*needed > size) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + /* path is included too */ + memcpy(info, font->fileinfo, *needed); + return TRUE; +} + /************************************************************************* * Kerning support for TrueType fonts */ @@ -8644,6 +8703,8 @@ static const struct gdi_dc_funcs freetype_funcs = #else /* HAVE_FREETYPE */ +struct font_fileinfo; + /*************************************************************************/ BOOL WineEngInit(void) @@ -8687,4 +8748,13 @@ BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes) return TRUE; } +/************************************************************************* + * GetFontFileInfo (GDI32.@) + */ +BOOL WINAPI GetFontFileInfo( DWORD instance_id, DWORD unknown, struct font_fileinfo *info, DWORD size, DWORD *needed) +{ + *needed = 0; + return FALSE; +} + #endif /* HAVE_FREETYPE */ diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec index 8bba68676a6..7d837f692a8 100644 --- a/dlls/gdi32/gdi32.spec +++ b/dlls/gdi32/gdi32.spec @@ -279,6 +279,7 @@ @ stdcall GetEnhMetaFileW(wstr) # @ stub GetFontAssocStatus @ stdcall GetFontData(long long long ptr long) +@ stdcall GetFontFileInfo(long long ptr long ptr) @ stdcall GetFontLanguageInfo(long) @ stdcall GetFontRealizationInfo(long ptr) @ stub GetFontResourceInfo diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index dff0eb620b6..c7dd6e19ab8 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -4177,14 +4177,14 @@ static void test_RealizationInfo(void) ok((info[0] & 0xf) == 1, "info[0] = %x for the system font\n", info[0]); ok(info[3] == 0xcccccccc, "structure longer than 3 dwords\n"); - if (!is_truetype_font_installed("Arial")) + if (!is_truetype_font_installed("Tahoma")) { skip("skipping GdiRealizationInfo with truetype font\n"); goto end; } memset(&lf, 0, sizeof(lf)); - strcpy(lf.lfFaceName, "Arial"); + strcpy(lf.lfFaceName, "Tahoma"); lf.lfHeight = 20; lf.lfWeight = FW_NORMAL; hfont = CreateFontIndirectA(&lf); @@ -4238,12 +4238,19 @@ static void test_RealizationInfo(void) ok(info2[6] == 0xcccccccc, "structure longer than 6 dwords\n"); /* Test GetFontFileInfo() */ - if (pGetFontFileInfo) { + /* invalid font id */ + SetLastError(0xdeadbeef); + r = pGetFontFileInfo(0xabababab, 0, &file_info, sizeof(file_info), &needed); + ok(r == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "ret %d gle %d\n", r, GetLastError()); + + needed = 0; r = pGetFontFileInfo(fri->instance_id, 0, &file_info, sizeof(file_info), &needed); ok(r != 0 || GetLastError() == ERROR_NOACCESS, "ret %d gle %d\n", r, GetLastError()); if (r) { + ok(needed > 0 && needed < sizeof(file_info), "got needed size %u\n", needed); + h = CreateFileW(file_info.path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); ok(h != INVALID_HANDLE_VALUE, "Unable to open file %d\n", GetLastError()); @@ -4256,8 +4263,14 @@ static void test_RealizationInfo(void) ReadFile(h, file, sizeof(file), &read, NULL); CloseHandle(h); have_file = TRUE; + + /* shorter buffer */ + SetLastError(0xdeadbeef); + r = pGetFontFileInfo(fri->instance_id, 0, &file_info, needed - 1, &needed); + ok(r == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "ret %d gle %d\n", r, GetLastError()); } + if (pGetFontFileData) { /* Get bytes 2 - 16 using GetFontFileData */ r = pGetFontFileData(fri->instance_id, 0, 2, data, sizeof(data)); ok(r != 0, "ret 0 gle %d\n", GetLastError());