mirror of
https://github.com/reactos/wine.git
synced 2024-11-28 06:00:45 +00:00
Lay down the infrastructure for gdi font rendering.
Partial implementation of GetGylphOutline and GetOutlineTextMetrics for gdi fonts.
This commit is contained in:
parent
37a4639ee1
commit
814654ef9f
@ -407,7 +407,8 @@ else
|
|||||||
freetype/tttables.h \
|
freetype/tttables.h \
|
||||||
freetype/ftnames.h \
|
freetype/ftnames.h \
|
||||||
freetype/ftsnames.h \
|
freetype/ftsnames.h \
|
||||||
freetype/ttnameid.h)
|
freetype/ttnameid.h \
|
||||||
|
freetype/ftoutln.h)
|
||||||
CPPFLAGS="$ac_save_CPPFLAGS"
|
CPPFLAGS="$ac_save_CPPFLAGS"
|
||||||
wine_cv_msg_freetype=no
|
wine_cv_msg_freetype=no
|
||||||
fi
|
fi
|
||||||
|
@ -6,10 +6,13 @@ MODULE = gdi32
|
|||||||
SOVERSION = 1.0
|
SOVERSION = 1.0
|
||||||
ALTNAMES = gdi dispdib wing
|
ALTNAMES = gdi dispdib wing
|
||||||
IMPORTS = kernel32 ntdll
|
IMPORTS = kernel32 ntdll
|
||||||
|
EXTRALIBS = @FREETYPELIBS@
|
||||||
|
EXTRAINCL = @FREETYPEINCL@
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
bidi16.c \
|
bidi16.c \
|
||||||
driver.c \
|
driver.c \
|
||||||
|
freetype.c \
|
||||||
gdi_main.c \
|
gdi_main.c \
|
||||||
printdrv.c \
|
printdrv.c \
|
||||||
thunk.c \
|
thunk.c \
|
||||||
|
835
dlls/gdi/freetype.c
Normal file
835
dlls/gdi/freetype.c
Normal file
@ -0,0 +1,835 @@
|
|||||||
|
/*
|
||||||
|
* FreeType font engine interface
|
||||||
|
*
|
||||||
|
* Copyright 2001 Huw D M Davies for CodeWeavers.
|
||||||
|
*
|
||||||
|
* This file contains the WineEng* functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winerror.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
#include "gdi.h"
|
||||||
|
#include "font.h"
|
||||||
|
#include "debugtools.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
DEFAULT_DEBUG_CHANNEL(font);
|
||||||
|
|
||||||
|
#ifdef HAVE_FREETYPE
|
||||||
|
|
||||||
|
#ifdef HAVE_FREETYPE_FREETYPE_H
|
||||||
|
#include <freetype/freetype.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FREETYPE_FTGLYPH_H
|
||||||
|
#include <freetype/ftglyph.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FREETYPE_TTTABLES_H
|
||||||
|
#include <freetype/tttables.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FREETYPE_FTNAMES_H
|
||||||
|
#include <freetype/ftnames.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FREETYPE_FTSNAMES_H
|
||||||
|
#include <freetype/ftsnames.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FREETYPE_TTNAMEID_H
|
||||||
|
#include <freetype/ttnameid.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FREETYPE_FTOUTLN_H
|
||||||
|
#include <freetype/ftoutln.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static FT_Library library = 0;
|
||||||
|
|
||||||
|
typedef struct tagFace {
|
||||||
|
WCHAR *StyleName;
|
||||||
|
char *file;
|
||||||
|
BOOL Italic;
|
||||||
|
BOOL Bold;
|
||||||
|
struct tagFace *next;
|
||||||
|
} Face;
|
||||||
|
|
||||||
|
typedef struct tagFamily {
|
||||||
|
WCHAR *FamilyName;
|
||||||
|
Face *FirstFace;
|
||||||
|
struct tagFamily *next;
|
||||||
|
} Family;
|
||||||
|
|
||||||
|
struct tagGdiFont {
|
||||||
|
DWORD ref;
|
||||||
|
FT_Face ft_face;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Family *FontList = NULL;
|
||||||
|
|
||||||
|
static BOOL AddFontFileToList(char *file)
|
||||||
|
{
|
||||||
|
FT_Face ft_face;
|
||||||
|
WCHAR *FamilyW, *StyleW;
|
||||||
|
DWORD len;
|
||||||
|
Family *family = FontList;
|
||||||
|
Family **insert = &FontList;
|
||||||
|
Face **insertface;
|
||||||
|
|
||||||
|
TRACE("Loading font file %s\n", debugstr_a(file));
|
||||||
|
if(FT_New_Face(library, file, 0, &ft_face)) {
|
||||||
|
ERR("Unable to load font file %s\n", debugstr_a(file));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!FT_IS_SFNT(ft_face)) { /* for now we'll skip everything but TT/OT */
|
||||||
|
FT_Done_Face(ft_face);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0);
|
||||||
|
FamilyW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, FamilyW, len);
|
||||||
|
|
||||||
|
while(family) {
|
||||||
|
if(!strcmpW(family->FamilyName, FamilyW))
|
||||||
|
break;
|
||||||
|
insert = &family->next;
|
||||||
|
family = family->next;
|
||||||
|
}
|
||||||
|
if(!family) {
|
||||||
|
family = *insert = HeapAlloc(GetProcessHeap(), 0, sizeof(*family));
|
||||||
|
family->FamilyName = FamilyW;
|
||||||
|
family->FirstFace = NULL;
|
||||||
|
family->next = NULL;
|
||||||
|
} else {
|
||||||
|
HeapFree(GetProcessHeap(), 0, FamilyW);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0);
|
||||||
|
StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
|
||||||
|
|
||||||
|
|
||||||
|
for(insertface = &family->FirstFace; *insertface;
|
||||||
|
insertface = &(*insertface)->next) {
|
||||||
|
if(!strcmpW((*insertface)->StyleName, StyleW)) {
|
||||||
|
ERR("Already loaded font %s %s\n", debugstr_w(family->FamilyName),
|
||||||
|
debugstr_w(StyleW));
|
||||||
|
HeapFree(GetProcessHeap(), 0, StyleW);
|
||||||
|
FT_Done_Face(ft_face);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*insertface = HeapAlloc(GetProcessHeap(), 0, sizeof(**insertface));
|
||||||
|
(*insertface)->StyleName = StyleW;
|
||||||
|
(*insertface)->file = HeapAlloc(GetProcessHeap(),0,strlen(file)+1);
|
||||||
|
strcpy((*insertface)->file, file);
|
||||||
|
(*insertface)->next = NULL;
|
||||||
|
(*insertface)->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
|
||||||
|
(*insertface)->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0;
|
||||||
|
FT_Done_Face(ft_face);
|
||||||
|
|
||||||
|
TRACE("Added font %s %s\n", debugstr_w(family->FamilyName),
|
||||||
|
debugstr_w(StyleW));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DumpFontList(void)
|
||||||
|
{
|
||||||
|
Family *family;
|
||||||
|
Face *face;
|
||||||
|
|
||||||
|
for(family = FontList; family; family = family->next) {
|
||||||
|
TRACE("Family: %s\n", debugstr_w(family->FamilyName));
|
||||||
|
for(face = family->FirstFace; face; face = face->next) {
|
||||||
|
TRACE("\t%s\n", debugstr_w(face->StyleName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL ReadFontDir(char *dirname)
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *dent;
|
||||||
|
char path[MAX_PATH];
|
||||||
|
|
||||||
|
dir = opendir(dirname);
|
||||||
|
if(!dir) {
|
||||||
|
ERR("Can't open directory %s\n", debugstr_a(dirname));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
while((dent = readdir(dir)) != NULL) {
|
||||||
|
if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
|
||||||
|
continue;
|
||||||
|
sprintf(path, "%s/%s", dirname, dent->d_name);
|
||||||
|
AddFontFileToList(path);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngInit
|
||||||
|
*
|
||||||
|
* Initialize FreeType library and create a list of available faces
|
||||||
|
*/
|
||||||
|
BOOL WineEngInit(void)
|
||||||
|
{
|
||||||
|
HKEY hkey;
|
||||||
|
DWORD valuelen, datalen, i = 0, type, dlen, vlen;
|
||||||
|
LPSTR value;
|
||||||
|
LPVOID data;
|
||||||
|
|
||||||
|
if(FT_Init_FreeType(&library) != 0) {
|
||||||
|
ERR("Can't init FreeType library\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
|
||||||
|
"Software\\Wine\\Wine\\Config\\FontDirs",
|
||||||
|
&hkey) != ERROR_SUCCESS) {
|
||||||
|
TRACE("Can't open FontDirs key in config file\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &valuelen,
|
||||||
|
&datalen, NULL, NULL);
|
||||||
|
|
||||||
|
valuelen++; /* returned value doesn't include room for '\0' */
|
||||||
|
value = HeapAlloc(GetProcessHeap(), 0, valuelen);
|
||||||
|
data = HeapAlloc(GetProcessHeap(), 0, datalen);
|
||||||
|
|
||||||
|
dlen = datalen;
|
||||||
|
vlen = valuelen;
|
||||||
|
while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
|
||||||
|
&dlen) == ERROR_SUCCESS) {
|
||||||
|
TRACE("Got %s=%s\n", value, (LPSTR)data);
|
||||||
|
ReadFontDir((LPSTR)data);
|
||||||
|
/* reset dlen and vlen */
|
||||||
|
dlen = datalen;
|
||||||
|
vlen = valuelen;
|
||||||
|
}
|
||||||
|
HeapFree(GetProcessHeap(), 0, data);
|
||||||
|
HeapFree(GetProcessHeap(), 0, value);
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
DumpFontList();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FT_Face OpenFontFile(char *file, LONG height)
|
||||||
|
{
|
||||||
|
FT_Error err;
|
||||||
|
TT_OS2 *pOS2;
|
||||||
|
FT_Face ft_face;
|
||||||
|
LONG ppem;
|
||||||
|
|
||||||
|
err = FT_New_Face(library, file, 0, &ft_face);
|
||||||
|
if(err) {
|
||||||
|
ERR("FT_New_Face rets %d\n", err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pOS2 = FT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
|
||||||
|
|
||||||
|
if(height == 0) height = 16;
|
||||||
|
|
||||||
|
/* Calc. height of EM square:
|
||||||
|
*
|
||||||
|
* For +ve lfHeight we have
|
||||||
|
* lfHeight = (winAscent + winDescent) * ppem / units_per_em
|
||||||
|
* Re-arranging gives:
|
||||||
|
* ppem = units_per_em * lfheight / (winAscent + winDescent)
|
||||||
|
*
|
||||||
|
* For -ve lfHeight we have
|
||||||
|
* |lfHeight| = ppem
|
||||||
|
* [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
|
||||||
|
* with il = winAscent + winDescent - units_per_em]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(height > 0)
|
||||||
|
ppem = ft_face->units_per_EM * height /
|
||||||
|
(pOS2->usWinAscent + pOS2->usWinDescent);
|
||||||
|
else
|
||||||
|
ppem = -height;
|
||||||
|
|
||||||
|
FT_Set_Pixel_Sizes(ft_face, 0, ppem);
|
||||||
|
return ft_face;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngCreateFontInstance
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
GdiFont WineEngCreateFontInstance(HFONT hfont)
|
||||||
|
{
|
||||||
|
GdiFont ret;
|
||||||
|
Face *face;
|
||||||
|
Family *family = NULL;
|
||||||
|
WCHAR FaceName[LF_FACESIZE];
|
||||||
|
BOOL bd, it;
|
||||||
|
FONTOBJ *font = GDI_GetObjPtr(hfont, FONT_MAGIC);
|
||||||
|
LOGFONTW *plf = &font->logfont;
|
||||||
|
|
||||||
|
TRACE("%s, h=%ld, it=%d, weight=%ld\n", debugstr_w(plf->lfFaceName),
|
||||||
|
plf->lfHeight, plf->lfItalic, plf->lfWeight);
|
||||||
|
|
||||||
|
ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
|
||||||
|
ret->ref = 1;
|
||||||
|
|
||||||
|
strcpyW(FaceName, plf->lfFaceName);
|
||||||
|
|
||||||
|
if(FaceName[0] != '\0') {
|
||||||
|
for(family = FontList; family; family = family->next) {
|
||||||
|
if(!strcmpiW(family->FamilyName, FaceName))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!family) {
|
||||||
|
family = FontList;
|
||||||
|
FIXME("just using first face for now\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
it = plf->lfItalic ? 1 : 0;
|
||||||
|
bd = plf->lfWeight > 550 ? 1 : 0;
|
||||||
|
|
||||||
|
for(face = family->FirstFace; face; face = face->next) {
|
||||||
|
if(!(face->Italic ^ it) && !(face->Bold ^ bd))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!face) face = family->FirstFace;
|
||||||
|
|
||||||
|
TRACE("Choosen %s %s\n", debugstr_w(family->FamilyName),
|
||||||
|
debugstr_w(face->StyleName));
|
||||||
|
|
||||||
|
ret->ft_face = OpenFontFile(face->file, plf->lfHeight);
|
||||||
|
|
||||||
|
GDI_ReleaseObj(hfont);
|
||||||
|
TRACE("returning %p\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngAddRefFont
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
DWORD WineEngAddRefFont(GdiFont font)
|
||||||
|
{
|
||||||
|
return ++font->ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngDecRefFont
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
DWORD WineEngDecRefFont(GdiFont font)
|
||||||
|
{
|
||||||
|
DWORD ret = --font->ref;
|
||||||
|
|
||||||
|
if(ret == 0) {
|
||||||
|
FT_Done_Face(font->ft_face);
|
||||||
|
HeapFree(GetProcessHeap(), 0, font);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
|
||||||
|
LPNEWTEXTMETRICEXW pntm, LPDWORD ptype)
|
||||||
|
{
|
||||||
|
OUTLINETEXTMETRICW *potm;
|
||||||
|
UINT size;
|
||||||
|
GdiFont font = HeapAlloc(GetProcessHeap(),0,sizeof(*font));
|
||||||
|
|
||||||
|
font->ref = 1;
|
||||||
|
font->ft_face = OpenFontFile(face->file, 100);
|
||||||
|
|
||||||
|
memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
|
||||||
|
|
||||||
|
size = WineEngGetOutlineTextMetrics(font, 0, NULL);
|
||||||
|
potm = HeapAlloc(GetProcessHeap(), 0, size);
|
||||||
|
WineEngGetOutlineTextMetrics(font, size, potm);
|
||||||
|
|
||||||
|
#define TM potm->otmTextMetrics
|
||||||
|
|
||||||
|
pntm->ntmTm.tmHeight = pelf->elfLogFont.lfHeight = TM.tmHeight;
|
||||||
|
pntm->ntmTm.tmAscent = TM.tmAscent;
|
||||||
|
pntm->ntmTm.tmDescent = TM.tmDescent;
|
||||||
|
pntm->ntmTm.tmInternalLeading = TM.tmInternalLeading;
|
||||||
|
pntm->ntmTm.tmExternalLeading = TM.tmExternalLeading;
|
||||||
|
pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWeight = TM.tmAveCharWidth;
|
||||||
|
pntm->ntmTm.tmMaxCharWidth = TM.tmMaxCharWidth;
|
||||||
|
pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = TM.tmWeight;
|
||||||
|
pntm->ntmTm.tmOverhang = TM.tmOverhang;
|
||||||
|
pntm->ntmTm.tmDigitizedAspectX = TM.tmDigitizedAspectX;
|
||||||
|
pntm->ntmTm.tmDigitizedAspectY = TM.tmDigitizedAspectY;
|
||||||
|
pntm->ntmTm.tmFirstChar = TM.tmFirstChar;
|
||||||
|
pntm->ntmTm.tmLastChar = TM.tmLastChar;
|
||||||
|
pntm->ntmTm.tmDefaultChar = TM.tmDefaultChar;
|
||||||
|
pntm->ntmTm.tmBreakChar = TM.tmBreakChar;
|
||||||
|
pntm->ntmTm.tmItalic = pelf->elfLogFont.lfItalic = TM.tmItalic;
|
||||||
|
pntm->ntmTm.tmUnderlined = pelf->elfLogFont.lfUnderline = TM.tmUnderlined;
|
||||||
|
pntm->ntmTm.tmStruckOut = pelf->elfLogFont.lfStrikeOut = TM.tmStruckOut;
|
||||||
|
pntm->ntmTm.tmPitchAndFamily = TM.tmPitchAndFamily;
|
||||||
|
pelf->elfLogFont.lfPitchAndFamily = (TM.tmPitchAndFamily & 0xf1) + 1;
|
||||||
|
pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = TM.tmCharSet;
|
||||||
|
|
||||||
|
pntm->ntmTm.ntmFlags = TM.tmItalic ? NTM_ITALIC : 0;
|
||||||
|
if(TM.tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD;
|
||||||
|
if(pntm->ntmTm.ntmFlags == 0) pntm->ntmTm.ntmFlags = NTM_REGULAR;
|
||||||
|
|
||||||
|
pntm->ntmTm.ntmSizeEM = potm->otmEMSquare;
|
||||||
|
pntm->ntmTm.ntmCellHeight = 0;
|
||||||
|
pntm->ntmTm.ntmAvgWidth = 0;
|
||||||
|
|
||||||
|
*ptype = TM.tmPitchAndFamily & TMPF_TRUETYPE ? TRUETYPE_FONTTYPE : 0;
|
||||||
|
if(!(TM.tmPitchAndFamily & TMPF_VECTOR))
|
||||||
|
*ptype |= RASTER_FONTTYPE;
|
||||||
|
|
||||||
|
#undef TM
|
||||||
|
memset(&pntm->ntmFontSig, 0, sizeof(FONTSIGNATURE));
|
||||||
|
|
||||||
|
strncpyW(pelf->elfLogFont.lfFaceName,
|
||||||
|
(WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFamilyName),
|
||||||
|
LF_FACESIZE);
|
||||||
|
strncpyW(pelf->elfFullName,
|
||||||
|
(WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFullName),
|
||||||
|
LF_FULLFACESIZE);
|
||||||
|
strncpyW(pelf->elfStyle,
|
||||||
|
(WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName),
|
||||||
|
LF_FACESIZE);
|
||||||
|
pelf->elfScript[0] = '\0'; /* FIXME */
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, potm);
|
||||||
|
WineEngDecRefFont(font);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngEnumFonts
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc,
|
||||||
|
LPARAM lparam)
|
||||||
|
{
|
||||||
|
Family *family;
|
||||||
|
Face *face;
|
||||||
|
ENUMLOGFONTEXW elf;
|
||||||
|
NEWTEXTMETRICEXW ntm;
|
||||||
|
DWORD type, ret = 1;
|
||||||
|
|
||||||
|
TRACE("facename = %s\n", debugstr_w(plf->lfFaceName));
|
||||||
|
if(plf->lfFaceName[0]) {
|
||||||
|
for(family = FontList; family; family = family->next) {
|
||||||
|
if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
|
||||||
|
for(face = family->FirstFace; face; face = face->next) {
|
||||||
|
GetEnumStructs(face, &elf, &ntm, &type);
|
||||||
|
TRACE("enuming '%s'\n",
|
||||||
|
debugstr_w(elf.elfLogFont.lfFaceName));
|
||||||
|
ret = proc(&elf, &ntm, type, lparam);
|
||||||
|
if(!ret) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(family = FontList; family; family = family->next) {
|
||||||
|
GetEnumStructs(family->FirstFace, &elf, &ntm, &type);
|
||||||
|
TRACE("enuming '%s'\n", debugstr_w(elf.elfLogFont.lfFaceName));
|
||||||
|
ret = proc(&elf, &ntm, type, lparam);
|
||||||
|
if(!ret) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngGetGlyphOutline
|
||||||
|
*
|
||||||
|
* Behaves in exactly the same way as the win32 api GetGlyphOutline
|
||||||
|
* except that the first parameter is the HWINEENGFONT of the font in
|
||||||
|
* question rather than an HDC.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
|
||||||
|
LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
|
||||||
|
const MAT2* lpmat)
|
||||||
|
{
|
||||||
|
FT_Face ft_face = font->ft_face;
|
||||||
|
FT_UInt glyph_index;
|
||||||
|
DWORD width, height, pitch, needed;
|
||||||
|
FT_Bitmap ft_bitmap;
|
||||||
|
|
||||||
|
TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm,
|
||||||
|
buflen, buf, lpmat);
|
||||||
|
|
||||||
|
if(format & GGO_GLYPH_INDEX)
|
||||||
|
glyph_index = glyph;
|
||||||
|
else
|
||||||
|
glyph_index = FT_Get_Char_Index(ft_face, glyph);
|
||||||
|
|
||||||
|
FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_DEFAULT);
|
||||||
|
|
||||||
|
lpgm->gmBlackBoxX = ft_face->glyph->metrics.width >> 6;
|
||||||
|
lpgm->gmBlackBoxY = ft_face->glyph->metrics.height >> 6;
|
||||||
|
lpgm->gmptGlyphOrigin.x = ft_face->glyph->metrics.horiBearingX >> 6;
|
||||||
|
lpgm->gmptGlyphOrigin.y = ft_face->glyph->metrics.horiBearingY >> 6;
|
||||||
|
lpgm->gmCellIncX = ft_face->glyph->metrics.horiAdvance >> 6;
|
||||||
|
lpgm->gmCellIncY = 0;
|
||||||
|
|
||||||
|
if(format == GGO_METRICS)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if(ft_face->glyph->format != ft_glyph_format_outline) {
|
||||||
|
FIXME("loaded a bitmap\n");
|
||||||
|
return GDI_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(format == GGO_BITMAP) {
|
||||||
|
width = lpgm->gmBlackBoxX;
|
||||||
|
height = lpgm->gmBlackBoxY;
|
||||||
|
pitch = (width + 31) / 32 * 4;
|
||||||
|
needed = pitch * height;
|
||||||
|
|
||||||
|
if(!buf || !buflen) return needed;
|
||||||
|
ft_bitmap.width = width;
|
||||||
|
ft_bitmap.rows = height;
|
||||||
|
ft_bitmap.pitch = pitch;
|
||||||
|
ft_bitmap.pixel_mode = ft_pixel_mode_mono;
|
||||||
|
ft_bitmap.buffer = buf;
|
||||||
|
|
||||||
|
FT_Outline_Translate(&ft_face->glyph->outline,
|
||||||
|
- ft_face->glyph->metrics.horiBearingX,
|
||||||
|
- (ft_face->glyph->metrics.horiBearingY -
|
||||||
|
ft_face->glyph->metrics.height) );
|
||||||
|
|
||||||
|
FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
|
||||||
|
} else {
|
||||||
|
FIXME("Unsupported format %d\n", format);
|
||||||
|
return GDI_ERROR;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngGetTextMetrics
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
|
||||||
|
{
|
||||||
|
FT_Face ft_face = font->ft_face;
|
||||||
|
TT_OS2 *pOS2;
|
||||||
|
TT_HoriHeader *pHori;
|
||||||
|
FT_Fixed x_scale, y_scale;
|
||||||
|
|
||||||
|
x_scale = ft_face->size->metrics.x_scale;
|
||||||
|
y_scale = ft_face->size->metrics.y_scale;
|
||||||
|
|
||||||
|
pOS2 = FT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
|
||||||
|
if(!pOS2) {
|
||||||
|
FIXME("Can't find OS/2 table - not TT font?\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pHori = FT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
|
||||||
|
if(!pHori) {
|
||||||
|
FIXME("Can't find HHEA table - not TT font?\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("OS/2 winA = %d winD = %d typoA = %d typoD = %d typoLG = %d FT_Face a = %d, d = %d, h = %d: HORZ a = %d, d = %d lg = %d maxY = %ld minY = %ld\n",
|
||||||
|
pOS2->usWinAscent, pOS2->usWinDescent,
|
||||||
|
pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
|
||||||
|
ft_face->ascender, ft_face->descender, ft_face->height,
|
||||||
|
pHori->Ascender, pHori->Descender, pHori->Line_Gap,
|
||||||
|
ft_face->bbox.yMax, ft_face->bbox.yMin);
|
||||||
|
|
||||||
|
ptm->tmAscent = (FT_MulFix(pOS2->usWinAscent, y_scale) + 32) >> 6;
|
||||||
|
ptm->tmDescent = (FT_MulFix(pOS2->usWinDescent, y_scale) + 32) >> 6;
|
||||||
|
ptm->tmHeight = ptm->tmAscent + ptm->tmDescent;
|
||||||
|
ptm->tmInternalLeading = (FT_MulFix(pOS2->usWinAscent + pOS2->usWinDescent
|
||||||
|
- ft_face->units_per_EM, y_scale) + 32) >> 6;
|
||||||
|
|
||||||
|
/* MSDN says:
|
||||||
|
el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
|
||||||
|
*/
|
||||||
|
ptm->tmExternalLeading = max(0, (FT_MulFix(pHori->Line_Gap -
|
||||||
|
((pOS2->usWinAscent + pOS2->usWinDescent) -
|
||||||
|
(pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
|
||||||
|
|
||||||
|
ptm->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
|
||||||
|
ptm->tmMaxCharWidth = (FT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
|
||||||
|
ptm->tmWeight = pOS2->usWeightClass;
|
||||||
|
ptm->tmOverhang = 0;
|
||||||
|
ptm->tmDigitizedAspectX = 300;
|
||||||
|
ptm->tmDigitizedAspectY = 300;
|
||||||
|
ptm->tmFirstChar = pOS2->usFirstCharIndex;
|
||||||
|
ptm->tmLastChar = pOS2->usLastCharIndex;
|
||||||
|
ptm->tmDefaultChar = pOS2->usDefaultChar;
|
||||||
|
ptm->tmBreakChar = pOS2->usBreakChar;
|
||||||
|
ptm->tmItalic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
|
||||||
|
ptm->tmUnderlined = 0; /* entry in OS2 table */
|
||||||
|
ptm->tmStruckOut = 0; /* entry in OS2 table */
|
||||||
|
|
||||||
|
/* Yes this is correct; braindead api */
|
||||||
|
ptm->tmPitchAndFamily = FT_IS_FIXED_WIDTH(ft_face) ? 0 : TMPF_FIXED_PITCH;
|
||||||
|
if(FT_IS_SCALABLE(ft_face))
|
||||||
|
ptm->tmPitchAndFamily |= TMPF_VECTOR;
|
||||||
|
if(FT_IS_SFNT(ft_face))
|
||||||
|
ptm->tmPitchAndFamily |= TMPF_TRUETYPE;
|
||||||
|
|
||||||
|
ptm->tmCharSet = ANSI_CHARSET;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngGetOutlineTextMetrics
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
|
||||||
|
OUTLINETEXTMETRICW *potm)
|
||||||
|
{
|
||||||
|
FT_Face ft_face = font->ft_face;
|
||||||
|
UINT needed, lenfam, lensty, ret;
|
||||||
|
TT_OS2 *pOS2;
|
||||||
|
TT_HoriHeader *pHori;
|
||||||
|
FT_Fixed x_scale, y_scale;
|
||||||
|
WCHAR *family_nameW, *style_nameW;
|
||||||
|
WCHAR spaceW[] = {' ', '\0'};
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
needed = sizeof(*potm);
|
||||||
|
|
||||||
|
lenfam = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0)
|
||||||
|
* sizeof(WCHAR);
|
||||||
|
family_nameW = HeapAlloc(GetProcessHeap(), 0, lenfam);
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1,
|
||||||
|
family_nameW, lenfam);
|
||||||
|
|
||||||
|
lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
|
||||||
|
* sizeof(WCHAR);
|
||||||
|
style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
|
||||||
|
style_nameW, lensty);
|
||||||
|
|
||||||
|
/* These names should be read from the TT name table */
|
||||||
|
|
||||||
|
/* length of otmpFamilyName */
|
||||||
|
needed += lenfam;
|
||||||
|
|
||||||
|
/* length of otmpFaceName */
|
||||||
|
if(!strcasecmp(ft_face->style_name, "regular")) {
|
||||||
|
needed += lenfam; /* just the family name */
|
||||||
|
} else {
|
||||||
|
needed += lenfam + lensty; /* family + " " + style */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* length of otmpStyleName */
|
||||||
|
needed += lensty;
|
||||||
|
|
||||||
|
/* length of otmpFullName */
|
||||||
|
needed += lenfam + lensty;
|
||||||
|
|
||||||
|
if(needed > cbSize) {
|
||||||
|
ret = needed;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_scale = ft_face->size->metrics.x_scale;
|
||||||
|
y_scale = ft_face->size->metrics.y_scale;
|
||||||
|
|
||||||
|
pOS2 = FT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
|
||||||
|
if(!pOS2) {
|
||||||
|
FIXME("Can't find OS/2 table - not TT font?\n");
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
pHori = FT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
|
||||||
|
if(!pHori) {
|
||||||
|
FIXME("Can't find HHEA table - not TT font?\n");
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
potm->otmSize = needed;
|
||||||
|
|
||||||
|
WineEngGetTextMetrics(font, &potm->otmTextMetrics);
|
||||||
|
|
||||||
|
potm->otmFiller = 0;
|
||||||
|
memcpy(&potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
|
||||||
|
potm->otmfsSelection = pOS2->fsSelection;
|
||||||
|
potm->otmfsType = pOS2->fsType;
|
||||||
|
potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
|
||||||
|
potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
|
||||||
|
potm->otmItalicAngle = 0; /* POST table */
|
||||||
|
potm->otmEMSquare = ft_face->units_per_EM;
|
||||||
|
potm->otmAscent = pOS2->sTypoAscender;
|
||||||
|
potm->otmDescent = pOS2->sTypoDescender;
|
||||||
|
potm->otmLineGap = pOS2->sTypoLineGap;
|
||||||
|
potm->otmsCapEmHeight = pOS2->sCapHeight;
|
||||||
|
potm->otmsXHeight = pOS2->sxHeight;
|
||||||
|
potm->otmrcFontBox.left = ft_face->bbox.xMin;
|
||||||
|
potm->otmrcFontBox.right = ft_face->bbox.xMax;
|
||||||
|
potm->otmrcFontBox.top = ft_face->bbox.yMin;
|
||||||
|
potm->otmrcFontBox.bottom = ft_face->bbox.yMax;
|
||||||
|
potm->otmMacAscent = 0; /* where do these come from ? */
|
||||||
|
potm->otmMacDescent = 0;
|
||||||
|
potm->otmMacLineGap = 0;
|
||||||
|
potm->otmusMinimumPPEM = 0; /* TT Header */
|
||||||
|
potm->otmptSubscriptSize.x = pOS2->ySubscriptXSize;
|
||||||
|
potm->otmptSubscriptSize.y = pOS2->ySubscriptYSize;
|
||||||
|
potm->otmptSubscriptOffset.x = pOS2->ySubscriptXOffset;
|
||||||
|
potm->otmptSubscriptOffset.y = pOS2->ySubscriptYOffset;
|
||||||
|
potm->otmptSuperscriptSize.x = pOS2->ySuperscriptXSize;
|
||||||
|
potm->otmptSuperscriptSize.y = pOS2->ySuperscriptYSize;
|
||||||
|
potm->otmptSuperscriptOffset.x = pOS2->ySuperscriptXOffset;
|
||||||
|
potm->otmptSuperscriptOffset.y = pOS2->ySuperscriptYOffset;
|
||||||
|
potm->otmsStrikeoutSize = pOS2->yStrikeoutSize;
|
||||||
|
potm->otmsStrikeoutPosition = pOS2->yStrikeoutPosition;
|
||||||
|
potm->otmsUnderscoreSize = 0; /* POST Header */
|
||||||
|
potm->otmsUnderscorePosition = 0; /* POST Header */
|
||||||
|
|
||||||
|
/* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
|
||||||
|
cp = (char*)potm + sizeof(*potm);
|
||||||
|
potm->otmpFamilyName = (LPSTR)(cp - (char*)potm);
|
||||||
|
strcpyW((WCHAR*)cp, family_nameW);
|
||||||
|
cp += lenfam;
|
||||||
|
potm->otmpStyleName = (LPSTR)(cp - (char*)potm);
|
||||||
|
strcpyW((WCHAR*)cp, style_nameW);
|
||||||
|
cp += lensty;
|
||||||
|
potm->otmpFaceName = (LPSTR)(cp - (char*)potm);
|
||||||
|
strcpyW((WCHAR*)cp, family_nameW);
|
||||||
|
if(strcasecmp(ft_face->style_name, "regular")) {
|
||||||
|
strcatW((WCHAR*)cp, spaceW);
|
||||||
|
strcatW((WCHAR*)cp, style_nameW);
|
||||||
|
cp += lenfam + lensty;
|
||||||
|
} else
|
||||||
|
cp += lenfam;
|
||||||
|
potm->otmpFullName = (LPSTR)(cp - (char*)potm);
|
||||||
|
strcpyW((WCHAR*)cp, family_nameW);
|
||||||
|
strcatW((WCHAR*)cp, spaceW);
|
||||||
|
strcatW((WCHAR*)cp, style_nameW);
|
||||||
|
ret = needed;
|
||||||
|
|
||||||
|
end:
|
||||||
|
HeapFree(GetProcessHeap(), 0, style_nameW);
|
||||||
|
HeapFree(GetProcessHeap(), 0, family_nameW);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngGetCharWidth
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
|
||||||
|
LPINT buffer)
|
||||||
|
{
|
||||||
|
UINT c;
|
||||||
|
GLYPHMETRICS gm;
|
||||||
|
TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
|
||||||
|
|
||||||
|
for(c = firstChar; c <= lastChar; c++) {
|
||||||
|
WineEngGetGlyphOutline(font, c, GGO_METRICS, &gm, 0, NULL, NULL);
|
||||||
|
buffer[c - firstChar] = gm.gmCellIncX;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* WineEngGetTextExtentPoint
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
|
||||||
|
LPSIZE size)
|
||||||
|
{
|
||||||
|
UINT idx;
|
||||||
|
GLYPHMETRICS gm;
|
||||||
|
TEXTMETRICW tm;
|
||||||
|
|
||||||
|
TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count,
|
||||||
|
size);
|
||||||
|
|
||||||
|
size->cx = 0;
|
||||||
|
WineEngGetTextMetrics(font, &tm);
|
||||||
|
size->cy = tm.tmHeight;
|
||||||
|
|
||||||
|
for(idx = 0; idx < count; idx++) {
|
||||||
|
WineEngGetGlyphOutline(font, wstr[idx], GGO_METRICS, &gm, 0, NULL,
|
||||||
|
NULL);
|
||||||
|
size->cx += gm.gmCellIncX;
|
||||||
|
}
|
||||||
|
TRACE("return %ld,%ld\n", size->cx, size->cy);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_FREETYPE */
|
||||||
|
|
||||||
|
BOOL WineEngInit(void)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
GdiFont WineEngCreateFontInstance(HFONT hfont)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
DWORD WineEngAddRefFont(GdiFont font)
|
||||||
|
{
|
||||||
|
ERR("called but we don't have FreeType\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DWORD WineEngDecRefFont(GdiFont font)
|
||||||
|
{
|
||||||
|
ERR("called but we don't have FreeType\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc, LPARAM lparam)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
|
||||||
|
LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
|
||||||
|
const MAT2* lpmat)
|
||||||
|
{
|
||||||
|
ERR("called but we don't have FreeType\n");
|
||||||
|
return GDI_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
|
||||||
|
{
|
||||||
|
ERR("called but we don't have FreeType\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
|
||||||
|
OUTLINETEXTMETRICW *potm)
|
||||||
|
{
|
||||||
|
ERR("called but we don't have FreeType\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
|
||||||
|
LPINT buffer)
|
||||||
|
{
|
||||||
|
ERR("called but we don't have FreeType\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
|
||||||
|
LPSIZE size)
|
||||||
|
{
|
||||||
|
ERR("called but we don't have FreeType\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_FREETYPE */
|
||||||
|
|
@ -37,14 +37,9 @@ static HBRUSH TTYDRV_DC_BRUSH_SelectObject(DC *dc, HBRUSH hbrush)
|
|||||||
*/
|
*/
|
||||||
static HFONT TTYDRV_DC_FONT_SelectObject(DC* dc, HFONT hfont)
|
static HFONT TTYDRV_DC_FONT_SelectObject(DC* dc, HFONT hfont)
|
||||||
{
|
{
|
||||||
HFONT hPreviousFont;
|
|
||||||
|
|
||||||
TRACE("(%p, 0x%04x)\n", dc, hfont);
|
TRACE("(%p, 0x%04x)\n", dc, hfont);
|
||||||
|
|
||||||
hPreviousFont = dc->hFont;
|
return TRUE; /* Use device font */
|
||||||
dc->hFont = hfont;
|
|
||||||
|
|
||||||
return hPreviousFont;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -130,7 +130,6 @@ static VOID ScaleFont(const AFM *afm, LONG lfHeight, PSFONT *font,
|
|||||||
HFONT PSDRV_FONT_SelectObject( DC * dc, HFONT hfont )
|
HFONT PSDRV_FONT_SelectObject( DC * dc, HFONT hfont )
|
||||||
{
|
{
|
||||||
LOGFONTW lf;
|
LOGFONTW lf;
|
||||||
HFONT16 prevfont = dc->hFont;
|
|
||||||
PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
|
PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
|
||||||
BOOL bd = FALSE, it = FALSE;
|
BOOL bd = FALSE, it = FALSE;
|
||||||
AFMLISTENTRY *afmle;
|
AFMLISTENTRY *afmle;
|
||||||
@ -143,8 +142,6 @@ HFONT PSDRV_FONT_SelectObject( DC * dc, HFONT hfont )
|
|||||||
debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
|
debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
|
||||||
lf.lfWeight);
|
lf.lfWeight);
|
||||||
|
|
||||||
dc->hFont = hfont;
|
|
||||||
|
|
||||||
if(lf.lfItalic)
|
if(lf.lfItalic)
|
||||||
it = TRUE;
|
it = TRUE;
|
||||||
if(lf.lfWeight > 550)
|
if(lf.lfWeight > 550)
|
||||||
@ -258,7 +255,7 @@ HFONT PSDRV_FONT_SelectObject( DC * dc, HFONT hfont )
|
|||||||
physDev->font.tm.tmDigitizedAspectX = physDev->logPixelsY;
|
physDev->font.tm.tmDigitizedAspectX = physDev->logPixelsY;
|
||||||
physDev->font.tm.tmDigitizedAspectY = physDev->logPixelsX;
|
physDev->font.tm.tmDigitizedAspectY = physDev->logPixelsX;
|
||||||
|
|
||||||
return prevfont;
|
return TRUE; /* We'll use a device font for now */
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -178,7 +178,6 @@ static HFONT EMFDRV_FONT_SelectObject( DC * dc, HFONT hFont )
|
|||||||
{
|
{
|
||||||
EMRSELECTOBJECT emr;
|
EMRSELECTOBJECT emr;
|
||||||
DWORD index;
|
DWORD index;
|
||||||
HFONT hOldFont;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* If the object is a stock font object, do not need to create it.
|
/* If the object is a stock font object, do not need to create it.
|
||||||
@ -195,17 +194,15 @@ static HFONT EMFDRV_FONT_SelectObject( DC * dc, HFONT hFont )
|
|||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(index = EMFDRV_CreateFontIndirect(dc, hFont ))) return 0;
|
if (!(index = EMFDRV_CreateFontIndirect(dc, hFont ))) return GDI_ERROR;
|
||||||
found:
|
found:
|
||||||
emr.emr.iType = EMR_SELECTOBJECT;
|
emr.emr.iType = EMR_SELECTOBJECT;
|
||||||
emr.emr.nSize = sizeof(emr);
|
emr.emr.nSize = sizeof(emr);
|
||||||
emr.ihObject = index;
|
emr.ihObject = index;
|
||||||
if(!EMFDRV_WriteRecord( dc, &emr.emr ))
|
if(!EMFDRV_WriteRecord( dc, &emr.emr ))
|
||||||
return FALSE;
|
return GDI_ERROR;
|
||||||
|
|
||||||
hOldFont = dc->hFont;
|
return FALSE;
|
||||||
dc->hFont = hFont;
|
|
||||||
return hOldFont;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,13 +178,12 @@ static BOOL MFDRV_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
|
|||||||
*/
|
*/
|
||||||
static HFONT MFDRV_FONT_SelectObject( DC * dc, HFONT hfont )
|
static HFONT MFDRV_FONT_SelectObject( DC * dc, HFONT hfont )
|
||||||
{
|
{
|
||||||
HFONT16 prevHandle = dc->hFont;
|
|
||||||
LOGFONT16 lf16;
|
LOGFONT16 lf16;
|
||||||
|
|
||||||
if (!GetObject16( hfont, sizeof(lf16), &lf16 )) return 0;
|
if (!GetObject16( hfont, sizeof(lf16), &lf16 )) return GDI_ERROR;
|
||||||
if (MFDRV_CreateFontIndirect(dc, hfont, &lf16))
|
if (MFDRV_CreateFontIndirect(dc, hfont, &lf16))
|
||||||
return prevHandle;
|
return FALSE;
|
||||||
return 0;
|
return GDI_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
@ -75,12 +75,10 @@ BOOL WIN16DRV_GetTextMetrics( DC *dc, TEXTMETRICW *metrics )
|
|||||||
HFONT WIN16DRV_FONT_SelectObject( DC * dc, HFONT hfont)
|
HFONT WIN16DRV_FONT_SelectObject( DC * dc, HFONT hfont)
|
||||||
{
|
{
|
||||||
WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
|
WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
|
||||||
HPEN prevHandle = dc->hFont;
|
|
||||||
int nSize;
|
int nSize;
|
||||||
|
|
||||||
if (!GetObject16( hfont, sizeof(physDev->lf), &physDev->lf )) return 0;
|
if (!GetObject16( hfont, sizeof(physDev->lf), &physDev->lf ))
|
||||||
|
return GDI_ERROR;
|
||||||
dc->hFont = hfont;
|
|
||||||
|
|
||||||
TRACE("WIN16DRV_FONT_SelectObject %s h=%d\n",
|
TRACE("WIN16DRV_FONT_SelectObject %s h=%d\n",
|
||||||
debugstr_a(physDev->lf.lfFaceName), physDev->lf.lfHeight);
|
debugstr_a(physDev->lf.lfFaceName), physDev->lf.lfHeight);
|
||||||
@ -146,11 +144,11 @@ HFONT WIN16DRV_FONT_SelectObject( DC * dc, HFONT hfont)
|
|||||||
physDev->tm.tmMaxCharWidth,
|
physDev->tm.tmMaxCharWidth,
|
||||||
physDev->tm.tmWeight);
|
physDev->tm.tmWeight);
|
||||||
|
|
||||||
return prevHandle;
|
return TRUE; /* We'll use a device font */
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* GetCharWidth32A (GDI32.@)
|
* WIN16DRV_GetCharWidth
|
||||||
*/
|
*/
|
||||||
BOOL WIN16DRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
|
BOOL WIN16DRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
|
||||||
LPINT buffer )
|
LPINT buffer )
|
||||||
|
@ -3146,12 +3146,14 @@ LPIFONTINFO16 XFONT_GetFontInfo( X_PHYSFONT pFont )
|
|||||||
*/
|
*/
|
||||||
HFONT X11DRV_FONT_SelectObject( DC* dc, HFONT hfont )
|
HFONT X11DRV_FONT_SelectObject( DC* dc, HFONT hfont )
|
||||||
{
|
{
|
||||||
HFONT hPrevFont = 0;
|
|
||||||
LOGFONTW logfont;
|
LOGFONTW logfont;
|
||||||
LOGFONT16 lf;
|
LOGFONT16 lf;
|
||||||
X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
|
X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
|
||||||
|
|
||||||
if (!GetObjectW( hfont, sizeof(logfont), &logfont )) return 0;
|
if (!GetObjectW( hfont, sizeof(logfont), &logfont )) return GDI_ERROR;
|
||||||
|
|
||||||
|
/* If we want to use a gdi font, we should check for XRender extension
|
||||||
|
and return FALSE here */
|
||||||
|
|
||||||
EnterCriticalSection( &crtsc_fonts_X11 );
|
EnterCriticalSection( &crtsc_fonts_X11 );
|
||||||
|
|
||||||
@ -3215,12 +3217,9 @@ HFONT X11DRV_FONT_SelectObject( DC* dc, HFONT hfont )
|
|||||||
logfont.lfCharSet = charsetMatched;
|
logfont.lfCharSet = charsetMatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
hPrevFont = dc->hFont;
|
|
||||||
dc->hFont = hfont;
|
|
||||||
|
|
||||||
LeaveCriticalSection( &crtsc_fonts_X11 );
|
LeaveCriticalSection( &crtsc_fonts_X11 );
|
||||||
|
|
||||||
return hPrevFont;
|
return TRUE; /* Use a device font */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,6 +229,9 @@
|
|||||||
/* Define if you have the <freetype/ftnames.h> header file. */
|
/* Define if you have the <freetype/ftnames.h> header file. */
|
||||||
#undef HAVE_FREETYPE_FTNAMES_H
|
#undef HAVE_FREETYPE_FTNAMES_H
|
||||||
|
|
||||||
|
/* Define if you have the <freetype/ftoutln.h> header file. */
|
||||||
|
#undef HAVE_FREETYPE_FTOUTLN_H
|
||||||
|
|
||||||
/* Define if you have the <freetype/ftsnames.h> header file. */
|
/* Define if you have the <freetype/ftsnames.h> header file. */
|
||||||
#undef HAVE_FREETYPE_FTSNAMES_H
|
#undef HAVE_FREETYPE_FTSNAMES_H
|
||||||
|
|
||||||
|
@ -70,7 +70,18 @@ extern void FONT_TextMetric16ToW(const TEXTMETRIC16 *ptm16, LPTEXTMETRICW ptm32
|
|||||||
extern void FONT_TextMetricAToW(const TEXTMETRICA *ptm32A, LPTEXTMETRICW ptm32W );
|
extern void FONT_TextMetricAToW(const TEXTMETRICA *ptm32A, LPTEXTMETRICW ptm32W );
|
||||||
extern void FONT_NewTextMetricEx16ToW(const NEWTEXTMETRICEX16*, LPNEWTEXTMETRICEXW);
|
extern void FONT_NewTextMetricEx16ToW(const NEWTEXTMETRICEX16*, LPNEWTEXTMETRICEXW);
|
||||||
extern void FONT_EnumLogFontEx16ToW(const ENUMLOGFONTEX16*, LPENUMLOGFONTEXW);
|
extern void FONT_EnumLogFontEx16ToW(const ENUMLOGFONTEX16*, LPENUMLOGFONTEXW);
|
||||||
extern BOOL ENGINE_InitFonts(void);
|
|
||||||
|
|
||||||
|
extern DWORD WineEngAddRefFont(GdiFont);
|
||||||
|
extern GdiFont WineEngCreateFontInstance(HFONT);
|
||||||
|
extern DWORD WineEngDecRefFont(GdiFont);
|
||||||
|
extern DWORD WineEngEnumFonts(LPLOGFONTW, DEVICEFONTENUMPROC, LPARAM);
|
||||||
|
extern BOOL WineEngGetCharWidth(GdiFont, UINT, UINT, LPINT);
|
||||||
|
extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format,
|
||||||
|
LPGLYPHMETRICS, DWORD buflen, LPVOID buf,
|
||||||
|
const MAT2*);
|
||||||
|
extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW);
|
||||||
|
extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE);
|
||||||
|
extern BOOL WineEngGetTextMetrics(GdiFont, LPTEXTMETRICW);
|
||||||
|
extern BOOL WineEngInit(void);
|
||||||
|
|
||||||
#endif /* __WINE_FONT_H */
|
#endif /* __WINE_FONT_H */
|
||||||
|
@ -50,6 +50,8 @@ typedef struct tagGDIOBJHDR
|
|||||||
|
|
||||||
typedef BOOL16 CALLBACK (*DCHOOKPROC)(HDC16,WORD,DWORD,LPARAM);
|
typedef BOOL16 CALLBACK (*DCHOOKPROC)(HDC16,WORD,DWORD,LPARAM);
|
||||||
|
|
||||||
|
typedef struct tagGdiFont *GdiFont;
|
||||||
|
|
||||||
typedef struct tagDC
|
typedef struct tagDC
|
||||||
{
|
{
|
||||||
GDIOBJHDR header;
|
GDIOBJHDR header;
|
||||||
@ -81,6 +83,7 @@ typedef struct tagDC
|
|||||||
HANDLE16 hDevice;
|
HANDLE16 hDevice;
|
||||||
HPALETTE16 hPalette;
|
HPALETTE16 hPalette;
|
||||||
|
|
||||||
|
GdiFont gdiFont;
|
||||||
GdiPath path;
|
GdiPath path;
|
||||||
|
|
||||||
WORD ROPmode;
|
WORD ROPmode;
|
||||||
|
@ -57,6 +57,7 @@ DC *DC_AllocDC( const DC_FUNCTIONS *funcs )
|
|||||||
dc->hBitmap = 0;
|
dc->hBitmap = 0;
|
||||||
dc->hDevice = 0;
|
dc->hDevice = 0;
|
||||||
dc->hPalette = GetStockObject( DEFAULT_PALETTE );
|
dc->hPalette = GetStockObject( DEFAULT_PALETTE );
|
||||||
|
dc->gdiFont = 0;
|
||||||
dc->ROPmode = R2_COPYPEN;
|
dc->ROPmode = R2_COPYPEN;
|
||||||
dc->polyFillMode = ALTERNATE;
|
dc->polyFillMode = ALTERNATE;
|
||||||
dc->stretchBltMode = BLACKONWHITE;
|
dc->stretchBltMode = BLACKONWHITE;
|
||||||
@ -311,6 +312,13 @@ HDC16 WINAPI GetDCState16( HDC16 hdc )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
newdc->hClipRgn = 0;
|
newdc->hClipRgn = 0;
|
||||||
|
|
||||||
|
if(dc->gdiFont) {
|
||||||
|
WineEngAddRefFont(dc->gdiFont);
|
||||||
|
newdc->gdiFont = dc->gdiFont;
|
||||||
|
} else
|
||||||
|
newdc->gdiFont = 0;
|
||||||
|
|
||||||
GDI_ReleaseObj( handle );
|
GDI_ReleaseObj( handle );
|
||||||
GDI_ReleaseObj( hdc );
|
GDI_ReleaseObj( hdc );
|
||||||
return handle;
|
return handle;
|
||||||
@ -767,6 +775,7 @@ BOOL WINAPI DeleteDC( HDC hdc )
|
|||||||
if (dc->hGCClipRgn) DeleteObject( dc->hGCClipRgn );
|
if (dc->hGCClipRgn) DeleteObject( dc->hGCClipRgn );
|
||||||
if (dc->pAbortProc) THUNK_Free( (FARPROC)dc->pAbortProc );
|
if (dc->pAbortProc) THUNK_Free( (FARPROC)dc->pAbortProc );
|
||||||
if (dc->hookThunk) THUNK_Free( (FARPROC)dc->hookThunk );
|
if (dc->hookThunk) THUNK_Free( (FARPROC)dc->hookThunk );
|
||||||
|
if (dc->gdiFont) WineEngDecRefFont( dc->gdiFont );
|
||||||
PATH_DestroyGdiPath(&dc->path);
|
PATH_DestroyGdiPath(&dc->path);
|
||||||
|
|
||||||
GDI_FreeObject( hdc, dc );
|
GDI_FreeObject( hdc, dc );
|
||||||
|
306
objects/font.c
306
objects/font.c
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
@ -724,25 +725,28 @@ static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
|
|||||||
LPARAM lParam, DWORD dwUnicode)
|
LPARAM lParam, DWORD dwUnicode)
|
||||||
{
|
{
|
||||||
BOOL (*enum_func)(HDC,LPLOGFONTW,DEVICEFONTENUMPROC,LPARAM);
|
BOOL (*enum_func)(HDC,LPLOGFONTW,DEVICEFONTENUMPROC,LPARAM);
|
||||||
INT ret = 0;
|
INT ret = 1;
|
||||||
DC *dc = DC_GetDCPtr( hDC );
|
DC *dc = DC_GetDCPtr( hDC );
|
||||||
|
fontEnum32 fe32;
|
||||||
|
BOOL enum_gdi_fonts;
|
||||||
|
|
||||||
if (!dc) return 0;
|
if (!dc) return 0;
|
||||||
|
|
||||||
|
fe32.lpLogFontParam = plf;
|
||||||
|
fe32.lpEnumFunc = efproc;
|
||||||
|
fe32.lpData = lParam;
|
||||||
|
fe32.dwFlags = dwUnicode;
|
||||||
|
|
||||||
enum_func = dc->funcs->pEnumDeviceFonts;
|
enum_func = dc->funcs->pEnumDeviceFonts;
|
||||||
GDI_ReleaseObj( hDC );
|
GDI_ReleaseObj( hDC );
|
||||||
|
enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
|
||||||
|
|
||||||
if (enum_func)
|
if (!enum_func && !enum_gdi_fonts) return 0;
|
||||||
{
|
|
||||||
fontEnum32 fe32;
|
if (enum_gdi_fonts)
|
||||||
|
ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
|
||||||
fe32.lpLogFontParam = plf;
|
if (ret && enum_func)
|
||||||
fe32.lpEnumFunc = efproc;
|
|
||||||
fe32.lpData = lParam;
|
|
||||||
|
|
||||||
fe32.dwFlags = dwUnicode;
|
|
||||||
|
|
||||||
ret = enum_func( hDC, plf, FONT_EnumInstance, (LPARAM)&fe32 );
|
ret = enum_func( hDC, plf, FONT_EnumInstance, (LPARAM)&fe32 );
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1029,25 +1033,15 @@ BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
|
|||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */
|
UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */
|
||||||
DC * dc = DC_GetDCPtr( hdc );
|
UINT wlen = MultiByteToWideChar(codepage,0,str,count,NULL,0);
|
||||||
|
LPWSTR p = HeapAlloc( GetProcessHeap(), 0, wlen * sizeof(WCHAR) );
|
||||||
|
|
||||||
if (!dc) return FALSE;
|
if (p) {
|
||||||
|
wlen = MultiByteToWideChar(codepage,0,str,count,p,wlen);
|
||||||
if (dc->funcs->pGetTextExtentPoint)
|
ret = GetTextExtentPoint32W( hdc, p, wlen, size );
|
||||||
{
|
HeapFree( GetProcessHeap(), 0, p );
|
||||||
/* str may not be 0 terminated so we can't use HEAP_strdupWtoA.
|
|
||||||
* So we use MultiByteToWideChar.
|
|
||||||
*/
|
|
||||||
UINT wlen = MultiByteToWideChar(codepage,0,str,count,NULL,0);
|
|
||||||
LPWSTR p = HeapAlloc( GetProcessHeap(), 0, wlen * sizeof(WCHAR) );
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
wlen = MultiByteToWideChar(codepage,0,str,count,p,wlen);
|
|
||||||
ret = dc->funcs->pGetTextExtentPoint( dc, p, wlen, size );
|
|
||||||
HeapFree( GetProcessHeap(), 0, p );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
GDI_ReleaseObj( hdc );
|
|
||||||
TRACE("(%08x %s %d %p): returning %ld x %ld\n",
|
TRACE("(%08x %s %d %p): returning %ld x %ld\n",
|
||||||
hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
|
hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
|
||||||
return ret;
|
return ret;
|
||||||
@ -1071,12 +1065,15 @@ BOOL WINAPI GetTextExtentPoint32W(
|
|||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
DC * dc = DC_GetDCPtr( hdc );
|
DC * dc = DC_GetDCPtr( hdc );
|
||||||
if (dc)
|
if (!dc) return FALSE;
|
||||||
{
|
|
||||||
if(dc->funcs->pGetTextExtentPoint)
|
if(dc->gdiFont)
|
||||||
ret = dc->funcs->pGetTextExtentPoint( dc, str, count, size );
|
ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
|
||||||
GDI_ReleaseObj( hdc );
|
else if(dc->funcs->pGetTextExtentPoint)
|
||||||
}
|
ret = dc->funcs->pGetTextExtentPoint( dc, str, count, size );
|
||||||
|
|
||||||
|
GDI_ReleaseObj( hdc );
|
||||||
|
|
||||||
TRACE("(%08x %s %d %p): returning %ld x %ld\n",
|
TRACE("(%08x %s %d %p): returning %ld x %ld\n",
|
||||||
hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
|
hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
|
||||||
return ret;
|
return ret;
|
||||||
@ -1160,15 +1157,11 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
|
|||||||
int index, nFit, extent;
|
int index, nFit, extent;
|
||||||
SIZE tSize;
|
SIZE tSize;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
DC * dc = DC_GetDCPtr( hdc );
|
|
||||||
if (!dc) return FALSE;
|
|
||||||
|
|
||||||
if (!dc->funcs->pGetTextExtentPoint) goto done;
|
|
||||||
|
|
||||||
size->cx = size->cy = nFit = extent = 0;
|
size->cx = size->cy = nFit = extent = 0;
|
||||||
for(index = 0; index < count; index++)
|
for(index = 0; index < count; index++)
|
||||||
{
|
{
|
||||||
if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) goto done;
|
if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
|
||||||
/* GetTextExtentPoint includes intercharacter spacing. */
|
/* GetTextExtentPoint includes intercharacter spacing. */
|
||||||
/* FIXME - justification needs doing yet. Remember that the base
|
/* FIXME - justification needs doing yet. Remember that the base
|
||||||
* data will not be in logical coordinates.
|
* data will not be in logical coordinates.
|
||||||
@ -1191,7 +1184,6 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
|
|||||||
hdc,debugstr_wn(str,count),maxExt,nFit, size->cx,size->cy);
|
hdc,debugstr_wn(str,count),maxExt,nFit, size->cx,size->cy);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
GDI_ReleaseObj( hdc );
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1229,7 +1221,12 @@ BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
|
|||||||
DC * dc = DC_GetDCPtr( hdc );
|
DC * dc = DC_GetDCPtr( hdc );
|
||||||
if (!dc) return FALSE;
|
if (!dc) return FALSE;
|
||||||
|
|
||||||
if (dc->funcs->pGetTextMetrics && dc->funcs->pGetTextMetrics( dc, metrics ))
|
if (dc->gdiFont)
|
||||||
|
ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
|
||||||
|
else if (dc->funcs->pGetTextMetrics)
|
||||||
|
ret = dc->funcs->pGetTextMetrics( dc, metrics );
|
||||||
|
|
||||||
|
if (ret)
|
||||||
{
|
{
|
||||||
/* device layer returns values in device units
|
/* device layer returns values in device units
|
||||||
* therefore we have to convert them to logical */
|
* therefore we have to convert them to logical */
|
||||||
@ -1311,63 +1308,131 @@ UINT WINAPI GetOutlineTextMetricsA(
|
|||||||
UINT cbData, /* [in] Size of metric data array */
|
UINT cbData, /* [in] Size of metric data array */
|
||||||
LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
|
LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
|
||||||
{
|
{
|
||||||
|
char buf[512], *ptr;
|
||||||
|
UINT ret, needed;
|
||||||
|
OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
|
||||||
|
INT left, len;
|
||||||
|
|
||||||
|
if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) {
|
||||||
|
if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
|
||||||
|
return 0;
|
||||||
|
lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
|
||||||
|
GetOutlineTextMetricsW(hdc, ret, lpOTMW);
|
||||||
|
}
|
||||||
|
|
||||||
|
needed = sizeof(OUTLINETEXTMETRICA);
|
||||||
|
if(lpOTMW->otmpFamilyName)
|
||||||
|
needed += WideCharToMultiByte(CP_ACP, 0,
|
||||||
|
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
|
||||||
|
NULL, 0, NULL, NULL);
|
||||||
|
if(lpOTMW->otmpFaceName)
|
||||||
|
needed += WideCharToMultiByte(CP_ACP, 0,
|
||||||
|
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
|
||||||
|
NULL, 0, NULL, NULL);
|
||||||
|
if(lpOTMW->otmpStyleName)
|
||||||
|
needed += WideCharToMultiByte(CP_ACP, 0,
|
||||||
|
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
|
||||||
|
NULL, 0, NULL, NULL);
|
||||||
|
if(lpOTMW->otmpFullName)
|
||||||
|
needed += WideCharToMultiByte(CP_ACP, 0,
|
||||||
|
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
|
||||||
|
NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
|
if(!lpOTM) {
|
||||||
|
ret = needed;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(needed > cbData) {
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
UINT rtn = FALSE;
|
lpOTM->otmSize = needed;
|
||||||
LPTEXTMETRICA lptxtMetr;
|
FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (lpOTM == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
lpOTM = (LPOUTLINETEXTMETRICA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OUTLINETEXTMETRICA));
|
|
||||||
rtn = sizeof(OUTLINETEXTMETRICA);
|
|
||||||
cbData = rtn;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
cbData = sizeof(*lpOTM);
|
|
||||||
rtn = cbData;
|
|
||||||
};
|
|
||||||
|
|
||||||
lpOTM->otmSize = cbData;
|
|
||||||
|
|
||||||
lptxtMetr =HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TEXTMETRICA));
|
|
||||||
|
|
||||||
if (!GetTextMetricsA(hdc,lptxtMetr))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
memcpy(&(lpOTM->otmTextMetrics),lptxtMetr,sizeof(TEXTMETRICA));
|
|
||||||
};
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(),HEAP_ZERO_MEMORY,lptxtMetr);
|
|
||||||
|
|
||||||
lpOTM->otmFiller = 0;
|
lpOTM->otmFiller = 0;
|
||||||
|
lpOTM->otmPanoseNumber = lpOTMW->otmPanoseNumber;
|
||||||
|
lpOTM->otmfsSelection = lpOTMW->otmfsSelection;
|
||||||
|
lpOTM->otmfsType = lpOTMW->otmfsType;
|
||||||
|
lpOTM->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
|
||||||
|
lpOTM->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
|
||||||
|
lpOTM->otmItalicAngle = lpOTMW->otmItalicAngle;
|
||||||
|
lpOTM->otmEMSquare = lpOTMW->otmEMSquare;
|
||||||
|
lpOTM->otmAscent = lpOTMW->otmAscent;
|
||||||
|
lpOTM->otmDescent = lpOTMW->otmDescent;
|
||||||
|
lpOTM->otmLineGap = lpOTMW->otmLineGap;
|
||||||
|
lpOTM->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
|
||||||
|
lpOTM->otmsXHeight = lpOTMW->otmsXHeight;
|
||||||
|
lpOTM->otmrcFontBox = lpOTMW->otmrcFontBox;
|
||||||
|
lpOTM->otmMacAscent = lpOTMW->otmMacAscent;
|
||||||
|
lpOTM->otmMacDescent = lpOTMW->otmMacDescent;
|
||||||
|
lpOTM->otmMacLineGap = lpOTMW->otmMacLineGap;
|
||||||
|
lpOTM->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
|
||||||
|
lpOTM->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
|
||||||
|
lpOTM->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
|
||||||
|
lpOTM->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
|
||||||
|
lpOTM->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
|
||||||
|
lpOTM->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
|
||||||
|
lpOTM->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
|
||||||
|
lpOTM->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
|
||||||
|
lpOTM->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
|
||||||
|
|
||||||
lpOTM->otmPanoseNumber.bFamilyType = 0;
|
|
||||||
lpOTM->otmPanoseNumber.bSerifStyle = 0;
|
|
||||||
lpOTM->otmPanoseNumber.bWeight = 0;
|
|
||||||
lpOTM->otmPanoseNumber.bProportion = 0;
|
|
||||||
lpOTM->otmPanoseNumber.bContrast = 0;
|
|
||||||
lpOTM->otmPanoseNumber.bStrokeVariation = 0;
|
|
||||||
lpOTM->otmPanoseNumber.bArmStyle = 0;
|
|
||||||
lpOTM->otmPanoseNumber.bLetterform = 0;
|
|
||||||
lpOTM->otmPanoseNumber.bMidline = 0;
|
|
||||||
lpOTM->otmPanoseNumber.bXHeight = 0;
|
|
||||||
|
|
||||||
lpOTM->otmfsSelection = 0;
|
ptr = (char*)(lpOTM + 1);
|
||||||
lpOTM->otmfsType = 0;
|
left = needed - sizeof(*lpOTM);
|
||||||
|
|
||||||
/*
|
if(lpOTMW->otmpFamilyName) {
|
||||||
Further fill of the structure not implemented,
|
lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM);
|
||||||
Needs real values for the structure members
|
len = WideCharToMultiByte(CP_ACP, 0,
|
||||||
*/
|
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
|
||||||
|
ptr, left, NULL, NULL);
|
||||||
|
left -= len;
|
||||||
|
ptr += len;
|
||||||
|
} else
|
||||||
|
lpOTM->otmpFamilyName = 0;
|
||||||
|
|
||||||
|
if(lpOTMW->otmpFaceName) {
|
||||||
|
lpOTM->otmpFaceName = (LPSTR)(ptr - (char*)lpOTM);
|
||||||
|
len = WideCharToMultiByte(CP_ACP, 0,
|
||||||
|
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
|
||||||
|
ptr, left, NULL, NULL);
|
||||||
|
left -= len;
|
||||||
|
ptr += len;
|
||||||
|
} else
|
||||||
|
lpOTM->otmpFaceName = 0;
|
||||||
|
|
||||||
|
if(lpOTMW->otmpStyleName) {
|
||||||
|
lpOTM->otmpStyleName = (LPSTR)(ptr - (char*)lpOTM);
|
||||||
|
len = WideCharToMultiByte(CP_ACP, 0,
|
||||||
|
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
|
||||||
|
ptr, left, NULL, NULL);
|
||||||
|
left -= len;
|
||||||
|
ptr += len;
|
||||||
|
} else
|
||||||
|
lpOTM->otmpStyleName = 0;
|
||||||
|
|
||||||
|
if(lpOTMW->otmpFullName) {
|
||||||
|
lpOTM->otmpFullName = (LPSTR)(ptr - (char*)lpOTM);
|
||||||
|
len = WideCharToMultiByte(CP_ACP, 0,
|
||||||
|
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
|
||||||
|
ptr, left, NULL, NULL);
|
||||||
|
left -= len;
|
||||||
|
} else
|
||||||
|
lpOTM->otmpFullName = 0;
|
||||||
|
|
||||||
return rtn;
|
assert(left == 0);
|
||||||
|
|
||||||
|
ret = needed;
|
||||||
|
|
||||||
|
end:
|
||||||
|
if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
|
||||||
|
HeapFree(GetProcessHeap(), 0, lpOTMW);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* GetOutlineTextMetricsW [GDI32.@]
|
* GetOutlineTextMetricsW [GDI32.@]
|
||||||
*/
|
*/
|
||||||
@ -1376,10 +1441,38 @@ UINT WINAPI GetOutlineTextMetricsW(
|
|||||||
UINT cbData, /* [in] Size of metric data array */
|
UINT cbData, /* [in] Size of metric data array */
|
||||||
LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
|
LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
|
||||||
{
|
{
|
||||||
FIXME("(%d,%d,%p): stub\n", hdc, cbData, lpOTM);
|
DC *dc = DC_GetDCPtr( hdc );
|
||||||
return 0;
|
UINT ret;
|
||||||
|
|
||||||
|
TRACE("(%d,%d,%p)\n", hdc, cbData, lpOTM);
|
||||||
|
if(!dc) return 0;
|
||||||
|
|
||||||
|
if(dc->gdiFont)
|
||||||
|
ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, lpOTM);
|
||||||
|
|
||||||
|
else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
|
||||||
|
but really this should just be a return 0. */
|
||||||
|
|
||||||
|
ret = sizeof(*lpOTM);
|
||||||
|
if (lpOTM) {
|
||||||
|
if(cbData < ret)
|
||||||
|
ret = 0;
|
||||||
|
else {
|
||||||
|
memset(lpOTM, 0, ret);
|
||||||
|
lpOTM->otmSize = sizeof(*lpOTM);
|
||||||
|
GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
|
||||||
|
/*
|
||||||
|
Further fill of the structure not implemented,
|
||||||
|
Needs real values for the structure members
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GDI_ReleaseObj(hdc);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* GetCharWidth (GDI.350)
|
* GetCharWidth (GDI.350)
|
||||||
*/
|
*/
|
||||||
@ -1428,7 +1521,12 @@ BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
|
|||||||
DC * dc = DC_GetDCPtr( hdc );
|
DC * dc = DC_GetDCPtr( hdc );
|
||||||
if (!dc) return FALSE;
|
if (!dc) return FALSE;
|
||||||
|
|
||||||
if (dc->funcs->pGetCharWidth && dc->funcs->pGetCharWidth( dc, firstChar, lastChar, buffer))
|
if (dc->gdiFont)
|
||||||
|
ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
|
||||||
|
else if (dc->funcs->pGetCharWidth)
|
||||||
|
ret = dc->funcs->pGetCharWidth( dc, firstChar, lastChar, buffer);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
{
|
{
|
||||||
/* convert device units to logical */
|
/* convert device units to logical */
|
||||||
|
|
||||||
@ -1589,9 +1687,8 @@ DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
|
|||||||
LPGLYPHMETRICS lpgm, DWORD cbBuffer,
|
LPGLYPHMETRICS lpgm, DWORD cbBuffer,
|
||||||
LPVOID lpBuffer, const MAT2 *lpmat2 )
|
LPVOID lpBuffer, const MAT2 *lpmat2 )
|
||||||
{
|
{
|
||||||
FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
|
return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
|
||||||
hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
|
lpmat2);
|
||||||
return (DWORD)-1; /* failure */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@ -1601,9 +1698,22 @@ DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
|
|||||||
LPGLYPHMETRICS lpgm, DWORD cbBuffer,
|
LPGLYPHMETRICS lpgm, DWORD cbBuffer,
|
||||||
LPVOID lpBuffer, const MAT2 *lpmat2 )
|
LPVOID lpBuffer, const MAT2 *lpmat2 )
|
||||||
{
|
{
|
||||||
FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
|
DC *dc = DC_GetDCPtr(hdc);
|
||||||
|
DWORD ret;
|
||||||
|
|
||||||
|
TRACE("(%04x, '%c', %04x, %p, %ld, %p, %p)\n",
|
||||||
hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
|
hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
|
||||||
return (DWORD)-1; /* failure */
|
|
||||||
|
if(!dc) return GDI_ERROR;
|
||||||
|
|
||||||
|
if(dc->gdiFont)
|
||||||
|
ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
|
||||||
|
cbBuffer, lpBuffer, lpmat2);
|
||||||
|
else
|
||||||
|
ret = GDI_ERROR;
|
||||||
|
|
||||||
|
GDI_ReleaseObj(hdc);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -244,6 +244,9 @@ BOOL GDI_Init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hkey) RegCloseKey( hkey );
|
if (hkey) RegCloseKey( hkey );
|
||||||
|
|
||||||
|
WineEngInit();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,7 +735,46 @@ HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
/***********************************************************************
|
||||||
|
* FONT_SelectObject
|
||||||
|
*
|
||||||
|
* If the driver supports vector fonts we create a gdi font first and
|
||||||
|
* then call the driver to give it a chance to supply its own device
|
||||||
|
* font. If the driver wants to do this it returns TRUE and we can
|
||||||
|
* delete the gdi font, if the driver wants to use the gdi font it
|
||||||
|
* should return FALSE, to signal an error return GDI_ERROR. For
|
||||||
|
* drivers that don't support vector fonts they must supply their own
|
||||||
|
* font.
|
||||||
|
*/
|
||||||
|
static HGDIOBJ FONT_SelectObject(DC *dc, HGDIOBJ hFont)
|
||||||
|
{
|
||||||
|
HGDIOBJ ret = FALSE;
|
||||||
|
|
||||||
|
if(dc->gdiFont) {
|
||||||
|
WineEngDecRefFont(dc->gdiFont);
|
||||||
|
dc->gdiFont = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
|
||||||
|
dc->gdiFont = WineEngCreateFontInstance(hFont);
|
||||||
|
|
||||||
|
if(dc->funcs->pSelectObject)
|
||||||
|
ret = dc->funcs->pSelectObject(dc, hFont);
|
||||||
|
|
||||||
|
if(ret && dc->gdiFont) {
|
||||||
|
WineEngDecRefFont(dc->gdiFont);
|
||||||
|
dc->gdiFont = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret == GDI_ERROR)
|
||||||
|
ret = FALSE; /* SelectObject returns FALSE on error */
|
||||||
|
else {
|
||||||
|
ret = dc->hFont;
|
||||||
|
dc->hFont = hFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* SelectObject (GDI.45)
|
* SelectObject (GDI.45)
|
||||||
@ -752,7 +794,12 @@ HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
|
|||||||
DC * dc = DC_GetDCUpdate( hdc );
|
DC * dc = DC_GetDCUpdate( hdc );
|
||||||
if (!dc) return 0;
|
if (!dc) return 0;
|
||||||
TRACE("hdc=%04x %04x\n", hdc, handle );
|
TRACE("hdc=%04x %04x\n", hdc, handle );
|
||||||
if (dc->funcs->pSelectObject)
|
|
||||||
|
/* Fonts get a rather different treatment so we'll handle them
|
||||||
|
separately */
|
||||||
|
if(GetObjectType(handle) == OBJ_FONT)
|
||||||
|
ret = FONT_SelectObject(dc, handle);
|
||||||
|
else if (dc->funcs->pSelectObject)
|
||||||
ret = dc->funcs->pSelectObject( dc, handle );
|
ret = dc->funcs->pSelectObject( dc, handle );
|
||||||
GDI_ReleaseObj( hdc );
|
GDI_ReleaseObj( hdc );
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user