gdiplus: Implement in-memory font storage.
This commit is contained in:
parent
130e38e047
commit
8794f8f708
|
@ -930,17 +930,158 @@ GpStatus WINGDIPAPI GdipPrivateAddFontFile(GpFontCollection* fontCollection,
|
||||||
return NotImplemented;
|
return NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copied from msi/font.c */
|
||||||
|
|
||||||
|
typedef struct _tagTT_OFFSET_TABLE {
|
||||||
|
USHORT uMajorVersion;
|
||||||
|
USHORT uMinorVersion;
|
||||||
|
USHORT uNumOfTables;
|
||||||
|
USHORT uSearchRange;
|
||||||
|
USHORT uEntrySelector;
|
||||||
|
USHORT uRangeShift;
|
||||||
|
} TT_OFFSET_TABLE;
|
||||||
|
|
||||||
|
typedef struct _tagTT_TABLE_DIRECTORY {
|
||||||
|
char szTag[4]; /* table name */
|
||||||
|
ULONG uCheckSum; /* Check sum */
|
||||||
|
ULONG uOffset; /* Offset from beginning of file */
|
||||||
|
ULONG uLength; /* length of the table in bytes */
|
||||||
|
} TT_TABLE_DIRECTORY;
|
||||||
|
|
||||||
|
typedef struct _tagTT_NAME_TABLE_HEADER {
|
||||||
|
USHORT uFSelector; /* format selector. Always 0 */
|
||||||
|
USHORT uNRCount; /* Name Records count */
|
||||||
|
USHORT uStorageOffset; /* Offset for strings storage,
|
||||||
|
* from start of the table */
|
||||||
|
} TT_NAME_TABLE_HEADER;
|
||||||
|
|
||||||
|
#define NAME_ID_FULL_FONT_NAME 4
|
||||||
|
#define NAME_ID_VERSION 5
|
||||||
|
|
||||||
|
typedef struct _tagTT_NAME_RECORD {
|
||||||
|
USHORT uPlatformID;
|
||||||
|
USHORT uEncodingID;
|
||||||
|
USHORT uLanguageID;
|
||||||
|
USHORT uNameID;
|
||||||
|
USHORT uStringLength;
|
||||||
|
USHORT uStringOffset; /* from start of storage area */
|
||||||
|
} TT_NAME_RECORD;
|
||||||
|
|
||||||
|
#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
|
||||||
|
#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Code based off of code located here
|
||||||
|
* http://www.codeproject.com/gdi/fontnamefromfile.asp
|
||||||
|
*/
|
||||||
|
WCHAR *load_ttf_name_id( const char *mem, DWORD_PTR size, DWORD id, WCHAR *ret, DWORD len )
|
||||||
|
{
|
||||||
|
const TT_TABLE_DIRECTORY *tblDir;
|
||||||
|
TT_OFFSET_TABLE ttOffsetTable;
|
||||||
|
TT_NAME_TABLE_HEADER ttNTHeader;
|
||||||
|
TT_NAME_RECORD ttRecord;
|
||||||
|
DWORD ofs, pos;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sizeof(TT_OFFSET_TABLE) > size)
|
||||||
|
return NULL;
|
||||||
|
ttOffsetTable = *(TT_OFFSET_TABLE*)mem;
|
||||||
|
ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
|
||||||
|
ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
|
||||||
|
ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);
|
||||||
|
|
||||||
|
if (ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pos = sizeof(ttOffsetTable);
|
||||||
|
for (i = 0; i < ttOffsetTable.uNumOfTables; i++)
|
||||||
|
{
|
||||||
|
tblDir = (const TT_TABLE_DIRECTORY*)&mem[pos];
|
||||||
|
pos += sizeof(*tblDir);
|
||||||
|
if (memcmp(tblDir->szTag,"name",4)==0)
|
||||||
|
{
|
||||||
|
ofs = SWAPLONG(tblDir->uOffset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= ttOffsetTable.uNumOfTables)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pos = ofs + sizeof(ttNTHeader);
|
||||||
|
if (pos > size)
|
||||||
|
return NULL;
|
||||||
|
ttNTHeader = *(TT_NAME_TABLE_HEADER*)&mem[ofs];
|
||||||
|
ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
|
||||||
|
ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
|
||||||
|
for(i=0; i<ttNTHeader.uNRCount; i++)
|
||||||
|
{
|
||||||
|
ttRecord = *(TT_NAME_RECORD*)&mem[pos];
|
||||||
|
pos += sizeof(ttRecord);
|
||||||
|
if (pos > size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
|
||||||
|
if (ttRecord.uNameID == id)
|
||||||
|
{
|
||||||
|
const char *buf;
|
||||||
|
|
||||||
|
ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
|
||||||
|
ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
|
||||||
|
if (ofs + ttRecord.uStringOffset + ttNTHeader.uStorageOffset + ttRecord.uStringLength > size)
|
||||||
|
return NULL;
|
||||||
|
buf = mem + ofs + ttRecord.uStringOffset + ttNTHeader.uStorageOffset;
|
||||||
|
len = MultiByteToWideChar(CP_ACP, 0, buf, ttRecord.uStringLength, ret, len-1);
|
||||||
|
ret[len] = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, DWORD type, LPARAM lParam);
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* GdipPrivateAddMemoryFont [GDIPLUS.@]
|
* GdipPrivateAddMemoryFont [GDIPLUS.@]
|
||||||
*/
|
*/
|
||||||
GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
|
GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
|
||||||
GDIPCONST void* memory, INT length)
|
GDIPCONST void* memory, INT length)
|
||||||
{
|
{
|
||||||
FIXME("%p, %p, %d\n", fontCollection, memory, length);
|
WCHAR buf[32], *name;
|
||||||
|
DWORD count = 0;
|
||||||
|
HANDLE font;
|
||||||
|
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));
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
HDC hdc;
|
||||||
|
LOGFONTW lfw;
|
||||||
|
|
||||||
|
hdc = GetDC(0);
|
||||||
|
|
||||||
|
lfw.lfCharSet = DEFAULT_CHARSET;
|
||||||
|
lstrcpyW(lfw.lfFaceName, name);
|
||||||
|
lfw.lfPitchAndFamily = 0;
|
||||||
|
|
||||||
|
if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)fontCollection, 0))
|
||||||
|
{
|
||||||
|
ReleaseDC(0, hdc);
|
||||||
|
return OutOfMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseDC(0, hdc);
|
||||||
|
}
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue