Commit 89366f74 authored by Fabian Maurer's avatar Fabian Maurer Committed by Alexandre Julliard

gdiplus: In GdipPrivateAddMemoryFont allow loading fonts with long names.

parent ff18f812
...@@ -1393,33 +1393,36 @@ static int match_name_table_language( const tt_name_record *name, LANGID lang ) ...@@ -1393,33 +1393,36 @@ static int match_name_table_language( const tt_name_record *name, LANGID lang )
return 0; return 0;
} }
static WCHAR *copy_name_table_string( const tt_name_record *name, const BYTE *data, WCHAR *ret, DWORD len ) static WCHAR *copy_name_table_string( const tt_name_record *name, const BYTE *data )
{ {
WORD name_len = GET_BE_WORD(name->length); WORD name_len = GET_BE_WORD(name->length);
WORD codepage; WORD codepage;
WCHAR *ret;
int len;
switch (GET_BE_WORD(name->platform_id)) switch (GET_BE_WORD(name->platform_id))
{ {
case TT_PLATFORM_APPLE_UNICODE: case TT_PLATFORM_APPLE_UNICODE:
case TT_PLATFORM_MICROSOFT: case TT_PLATFORM_MICROSOFT:
if (name_len >= len*sizeof(WCHAR)) ret = heap_alloc((name_len / 2 + 1) * sizeof(WCHAR));
return NULL;
for (len = 0; len < name_len / 2; len++) for (len = 0; len < name_len / 2; len++)
ret[len] = (data[len * 2] << 8) | data[len * 2 + 1]; ret[len] = (data[len * 2] << 8) | data[len * 2 + 1];
ret[len] = 0; ret[len] = 0;
return ret; return ret;
case TT_PLATFORM_MACINTOSH: case TT_PLATFORM_MACINTOSH:
codepage = get_mac_code_page( name ); codepage = get_mac_code_page( name );
len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, ret, len-1 ); len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, NULL, 0 ) + 1;
if (!len) if (!len)
return NULL; return NULL;
ret = heap_alloc(len * sizeof(WCHAR));
len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, ret, len - 1 );
ret[len] = 0; ret[len] = 0;
return ret; return ret;
} }
return NULL; return NULL;
} }
static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id, WCHAR *ret, DWORD len ) static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id )
{ {
LANGID lang = GetSystemDefaultLangID(); LANGID lang = GetSystemDefaultLangID();
const tt_header *header; const tt_header *header;
...@@ -1480,8 +1483,9 @@ static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id, WCHAR ...@@ -1480,8 +1483,9 @@ static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id, WCHAR
if (best_lang) if (best_lang)
{ {
WCHAR *ret;
name_record = (const tt_name_record*)(name_table + 1) + best_index; name_record = (const tt_name_record*)(name_table + 1) + best_index;
ret = copy_name_table_string( name_record, mem+ofs+GET_BE_WORD(name_record->offset), ret, len ); ret = copy_name_table_string( name_record, mem+ofs+GET_BE_WORD(name_record->offset) );
TRACE( "name %u found platform %u lang %04x %s\n", GET_BE_WORD(name_record->name_id), TRACE( "name %u found platform %u lang %04x %s\n", GET_BE_WORD(name_record->name_id),
GET_BE_WORD(name_record->platform_id), GET_BE_WORD(name_record->language_id), debugstr_w( ret )); GET_BE_WORD(name_record->platform_id), GET_BE_WORD(name_record->language_id), debugstr_w( ret ));
return ret; return ret;
...@@ -1497,43 +1501,45 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, D ...@@ -1497,43 +1501,45 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, D
GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection, GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
GDIPCONST void* memory, INT length) GDIPCONST void* memory, INT length)
{ {
WCHAR buf[32], *name; WCHAR *name;
DWORD count = 0; DWORD count = 0;
HANDLE font; HANDLE font;
GpStatus ret = Ok;
TRACE("%p, %p, %d\n", fontCollection, memory, length); TRACE("%p, %p, %d\n", fontCollection, memory, length);
if (!fontCollection || !memory || !length) if (!fontCollection || !memory || !length)
return InvalidParameter; return InvalidParameter;
name = load_ttf_name_id(memory, length, NAME_ID_FULL_FONT_NAME, buf, sizeof(buf)/sizeof(*buf)); name = load_ttf_name_id(memory, length, NAME_ID_FULL_FONT_NAME);
if (!name) if (!name)
return OutOfMemory; return OutOfMemory;
font = AddFontMemResourceEx((void*)memory, length, NULL, &count); font = AddFontMemResourceEx((void*)memory, length, NULL, &count);
TRACE("%s: %p/%u\n", debugstr_w(name), font, count); TRACE("%s: %p/%u\n", debugstr_w(name), font, count);
if (!font || !count) if (!font || !count)
return InvalidParameter; ret = InvalidParameter;
else
if (count)
{ {
HDC hdc; HDC hdc;
LOGFONTW lfw; LOGFONTW lfw;
hdc = CreateCompatibleDC(0); hdc = CreateCompatibleDC(0);
/* Truncate name if necessary, GDI32 can't deal with long names */
if(lstrlenW(name) > LF_FACESIZE - 1)
name[LF_FACESIZE - 1] = 0;
lfw.lfCharSet = DEFAULT_CHARSET; lfw.lfCharSet = DEFAULT_CHARSET;
lstrcpyW(lfw.lfFaceName, name); lstrcpyW(lfw.lfFaceName, name);
lfw.lfPitchAndFamily = 0; lfw.lfPitchAndFamily = 0;
if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)fontCollection, 0)) if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)fontCollection, 0))
{ ret = OutOfMemory;
DeleteDC(hdc);
return OutOfMemory;
}
DeleteDC(hdc); DeleteDC(hdc);
} }
return Ok; heap_free(name);
return ret;
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -14,3 +14,8 @@ C_SRCS = \ ...@@ -14,3 +14,8 @@ C_SRCS = \
pen.c \ pen.c \
region.c \ region.c \
stringformat.c stringformat.c
RC_SRCS = resource.rc
FONT_SRCS = \
wine_longname.sfd
...@@ -43,6 +43,78 @@ static void set_rect_empty(RectF *rc) ...@@ -43,6 +43,78 @@ static void set_rect_empty(RectF *rc)
rc->Height = 0.0; rc->Height = 0.0;
} }
static void create_testfontfile(const WCHAR *filename, int resource, WCHAR pathW[MAX_PATH])
{
DWORD written;
HANDLE file;
HRSRC res;
void *ptr;
GetTempPathW(MAX_PATH, pathW);
lstrcatW(pathW, filename);
file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW), GetLastError());
res = FindResourceA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(resource), (LPCSTR)RT_RCDATA);
ok(res != 0, "couldn't find resource\n");
ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res));
WriteFile(file, ptr, SizeofResource(GetModuleHandleA(NULL), res), &written, NULL);
ok(written == SizeofResource(GetModuleHandleA(NULL), res), "couldn't write resource\n");
CloseHandle(file);
}
#define DELETE_FONTFILE(filename) _delete_testfontfile(filename, __LINE__)
static void _delete_testfontfile(const WCHAR *filename, int line)
{
BOOL ret = DeleteFileW(filename);
ok_(__FILE__,line)(ret, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename), GetLastError());
}
static void test_long_name(void)
{
WCHAR path[MAX_PATH];
static const WCHAR path_longname[] = {'w','i','n','e','_','l','o','n','g','n','a','m','e','.','t','t','f',0};
GpStatus stat;
GpFontCollection *fonts;
INT num_families;
GpFontFamily *family;
WCHAR family_name[LF_FACESIZE];
GpFont *font;
stat = GdipNewPrivateFontCollection(&fonts);
ok(stat == Ok, "GdipNewPrivateFontCollection failed: %d\n", stat);
create_testfontfile(path_longname, 1, path);
stat = GdipPrivateAddFontFile(fonts, path);
ok(stat == Ok, "GdipPrivateAddFontFile failed: %d\n", stat);
stat = GdipGetFontCollectionFamilyCount(fonts, &num_families);
ok(stat == Ok, "GdipGetFontCollectionFamilyCount failed: %d\n", stat);
ok(num_families == 1, "expected num_families to be 1, got %d\n", num_families);
stat = GdipGetFontCollectionFamilyList(fonts, num_families, &family, &num_families);
ok(stat == Ok, "GdipGetFontCollectionFamilyList failed: %d\n", stat);
stat = GdipGetFamilyName(family, family_name, LANG_NEUTRAL);
ok(stat == Ok, "GdipGetFamilyName failed: %d\n", stat);
stat = GdipCreateFont(family, 256.0, FontStyleRegular, UnitPixel, &font);
ok(stat == Ok, "GdipCreateFont failed: %d\n", stat);
/* Cleanup */
stat = GdipDeleteFont(font);
ok(stat == Ok, "GdipDeleteFont failed: %d\n", stat);
stat = GdipDeletePrivateFontCollection(&fonts);
ok(stat == Ok, "GdipDeletePrivateFontCollection failed: %d\n", stat);
DELETE_FONTFILE(path);
}
static void test_createfont(void) static void test_createfont(void)
{ {
GpFontFamily* fontfamily = NULL, *fontfamily2; GpFontFamily* fontfamily = NULL, *fontfamily2;
...@@ -1183,6 +1255,7 @@ START_TEST(font) ...@@ -1183,6 +1255,7 @@ START_TEST(font)
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
test_long_name();
test_font_transform(); test_font_transform();
test_font_substitution(); test_font_substitution();
test_font_metrics(); test_font_metrics();
......
/*
* Resources for gdiplus test suite.
*
* Copyright 2017 Fabian Maurer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* @makedep: wine_longname.ttf */
1 RCDATA wine_longname.ttf
SplineFontDB: 3.0
FontName: wine_1_this_is_a_very_long_name_that_might_be_too_long_for_gdi32
FullName: wine_2_this_is_a_very_long_name_that_might_be_too_long_for_gdi32
FamilyName: wine_3_this_is_a_very_long_name_that_might_be_too_long_for_gdi32
Weight: Regular
Copyright: Copyright (c) 2017, Fabian Maurer
UComments: "2017-11-17: Created with FontForge (http://fontforge.org)"
Version: 001.000
ItalicAngle: 0
UnderlinePosition: -102.4
UnderlineWidth: 51.2
Ascent: 819
Descent: 205
InvalidEm: 0
LayerCount: 2
Layer: 0 0 "Back" 1
Layer: 1 0 "Fore" 0
XUID: [1021 48 28337276 3092883]
OS2Version: 0
OS2_WeightWidthSlopeOnly: 0
OS2_UseTypoMetrics: 1
CreationTime: 1510948643
ModificationTime: 1510949092
OS2TypoAscent: 0
OS2TypoAOffset: 1
OS2TypoDescent: 0
OS2TypoDOffset: 1
OS2TypoLinegap: 0
OS2WinAscent: 0
OS2WinAOffset: 1
OS2WinDescent: 0
OS2WinDOffset: 1
HheadAscent: 0
HheadAOffset: 1
HheadDescent: 0
HheadDOffset: 1
OS2Vendor: 'PfEd'
MarkAttachClasses: 1
DEI: 91125
Encoding: ISO8859-1
UnicodeInterp: none
NameList: AGL For New Fonts
DisplaySize: -48
AntiAlias: 1
FitToEm: 0
WinInfo: 64 16 4
BeginPrivate: 0
EndPrivate
BeginChars: 256 1
StartChar: at
Encoding: 64 64 0
Width: 1024
VWidth: 0
Flags: HW
LayerCount: 2
Fore
SplineSet
259 332 m 29
468 664 l 29
514 332 l 29
259 332 l 29
EndSplineSet
EndChar
EndChars
EndSplineFont
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment