gdiplus: In GdipPrivateAddMemoryFont allow loading fonts with long names.
Signed-off-by: Fabian Maurer <dark.shadow4@web.de> Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ff18f81278
commit
89366f740f
|
@ -1393,33 +1393,36 @@ static int match_name_table_language( const tt_name_record *name, LANGID lang )
|
|||
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 codepage;
|
||||
WCHAR *ret;
|
||||
int len;
|
||||
|
||||
switch (GET_BE_WORD(name->platform_id))
|
||||
{
|
||||
case TT_PLATFORM_APPLE_UNICODE:
|
||||
case TT_PLATFORM_MICROSOFT:
|
||||
if (name_len >= len*sizeof(WCHAR))
|
||||
return NULL;
|
||||
ret = heap_alloc((name_len / 2 + 1) * sizeof(WCHAR));
|
||||
for (len = 0; len < name_len / 2; len++)
|
||||
ret[len] = (data[len * 2] << 8) | data[len * 2 + 1];
|
||||
ret[len] = 0;
|
||||
return ret;
|
||||
case TT_PLATFORM_MACINTOSH:
|
||||
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)
|
||||
return NULL;
|
||||
ret = heap_alloc(len * sizeof(WCHAR));
|
||||
len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, ret, len - 1 );
|
||||
ret[len] = 0;
|
||||
return ret;
|
||||
}
|
||||
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();
|
||||
const tt_header *header;
|
||||
|
@ -1480,8 +1483,9 @@ static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id, WCHAR
|
|||
|
||||
if (best_lang)
|
||||
{
|
||||
WCHAR *ret;
|
||||
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),
|
||||
GET_BE_WORD(name_record->platform_id), GET_BE_WORD(name_record->language_id), debugstr_w( ret ));
|
||||
return ret;
|
||||
|
@ -1497,43 +1501,45 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, D
|
|||
GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
|
||||
GDIPCONST void* memory, INT length)
|
||||
{
|
||||
WCHAR buf[32], *name;
|
||||
WCHAR *name;
|
||||
DWORD count = 0;
|
||||
HANDLE font;
|
||||
GpStatus ret = Ok;
|
||||
TRACE("%p, %p, %d\n", fontCollection, memory, length);
|
||||
|
||||
if (!fontCollection || !memory || !length)
|
||||
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)
|
||||
return OutOfMemory;
|
||||
|
||||
font = AddFontMemResourceEx((void*)memory, length, NULL, &count);
|
||||
TRACE("%s: %p/%u\n", debugstr_w(name), font, count);
|
||||
if (!font || !count)
|
||||
return InvalidParameter;
|
||||
|
||||
if (count)
|
||||
ret = InvalidParameter;
|
||||
else
|
||||
{
|
||||
HDC hdc;
|
||||
LOGFONTW lfw;
|
||||
|
||||
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;
|
||||
lstrcpyW(lfw.lfFaceName, name);
|
||||
lfw.lfPitchAndFamily = 0;
|
||||
|
||||
if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)fontCollection, 0))
|
||||
{
|
||||
DeleteDC(hdc);
|
||||
return OutOfMemory;
|
||||
}
|
||||
ret = OutOfMemory;
|
||||
|
||||
DeleteDC(hdc);
|
||||
}
|
||||
return Ok;
|
||||
heap_free(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
@ -14,3 +14,8 @@ C_SRCS = \
|
|||
pen.c \
|
||||
region.c \
|
||||
stringformat.c
|
||||
|
||||
RC_SRCS = resource.rc
|
||||
|
||||
FONT_SRCS = \
|
||||
wine_longname.sfd
|
||||
|
|
|
@ -43,6 +43,78 @@ static void set_rect_empty(RectF *rc)
|
|||
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)
|
||||
{
|
||||
GpFontFamily* fontfamily = NULL, *fontfamily2;
|
||||
|
@ -1183,6 +1255,7 @@ START_TEST(font)
|
|||
|
||||
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
|
||||
|
||||
test_long_name();
|
||||
test_font_transform();
|
||||
test_font_substitution();
|
||||
test_font_metrics();
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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
|
|
@ -0,0 +1,66 @@
|
|||
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
|
Binary file not shown.
Loading…
Reference in New Issue