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/ftnames.h \
|
||||
freetype/ftsnames.h \
|
||||
freetype/ttnameid.h)
|
||||
freetype/ttnameid.h \
|
||||
freetype/ftoutln.h)
|
||||
CPPFLAGS="$ac_save_CPPFLAGS"
|
||||
wine_cv_msg_freetype=no
|
||||
fi
|
||||
|
|
|
@ -6,10 +6,13 @@ MODULE = gdi32
|
|||
SOVERSION = 1.0
|
||||
ALTNAMES = gdi dispdib wing
|
||||
IMPORTS = kernel32 ntdll
|
||||
EXTRALIBS = @FREETYPELIBS@
|
||||
EXTRAINCL = @FREETYPEINCL@
|
||||
|
||||
C_SRCS = \
|
||||
bidi16.c \
|
||||
driver.c \
|
||||
freetype.c \
|
||||
gdi_main.c \
|
||||
printdrv.c \
|
||||
thunk.c \
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
HFONT hPreviousFont;
|
||||
|
||||
TRACE("(%p, 0x%04x)\n", dc, hfont);
|
||||
|
||||
hPreviousFont = dc->hFont;
|
||||
dc->hFont = hfont;
|
||||
|
||||
return hPreviousFont;
|
||||
return TRUE; /* Use device font */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -130,7 +130,6 @@ static VOID ScaleFont(const AFM *afm, LONG lfHeight, PSFONT *font,
|
|||
HFONT PSDRV_FONT_SelectObject( DC * dc, HFONT hfont )
|
||||
{
|
||||
LOGFONTW lf;
|
||||
HFONT16 prevfont = dc->hFont;
|
||||
PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
|
||||
BOOL bd = FALSE, it = FALSE;
|
||||
AFMLISTENTRY *afmle;
|
||||
|
@ -143,8 +142,6 @@ HFONT PSDRV_FONT_SelectObject( DC * dc, HFONT hfont )
|
|||
debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
|
||||
lf.lfWeight);
|
||||
|
||||
dc->hFont = hfont;
|
||||
|
||||
if(lf.lfItalic)
|
||||
it = TRUE;
|
||||
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.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;
|
||||
DWORD index;
|
||||
HFONT hOldFont;
|
||||
int i;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
if (!(index = EMFDRV_CreateFontIndirect(dc, hFont ))) return 0;
|
||||
if (!(index = EMFDRV_CreateFontIndirect(dc, hFont ))) return GDI_ERROR;
|
||||
found:
|
||||
emr.emr.iType = EMR_SELECTOBJECT;
|
||||
emr.emr.nSize = sizeof(emr);
|
||||
emr.ihObject = index;
|
||||
if(!EMFDRV_WriteRecord( dc, &emr.emr ))
|
||||
return FALSE;
|
||||
return GDI_ERROR;
|
||||
|
||||
hOldFont = dc->hFont;
|
||||
dc->hFont = hFont;
|
||||
return hOldFont;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -178,13 +178,12 @@ static BOOL MFDRV_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
|
|||
*/
|
||||
static HFONT MFDRV_FONT_SelectObject( DC * dc, HFONT hfont )
|
||||
{
|
||||
HFONT16 prevHandle = dc->hFont;
|
||||
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))
|
||||
return prevHandle;
|
||||
return 0;
|
||||
return FALSE;
|
||||
return GDI_ERROR;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
|
|
@ -75,12 +75,10 @@ BOOL WIN16DRV_GetTextMetrics( DC *dc, TEXTMETRICW *metrics )
|
|||
HFONT WIN16DRV_FONT_SelectObject( DC * dc, HFONT hfont)
|
||||
{
|
||||
WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
|
||||
HPEN prevHandle = dc->hFont;
|
||||
int nSize;
|
||||
|
||||
if (!GetObject16( hfont, sizeof(physDev->lf), &physDev->lf )) return 0;
|
||||
|
||||
dc->hFont = hfont;
|
||||
if (!GetObject16( hfont, sizeof(physDev->lf), &physDev->lf ))
|
||||
return GDI_ERROR;
|
||||
|
||||
TRACE("WIN16DRV_FONT_SelectObject %s h=%d\n",
|
||||
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.tmWeight);
|
||||
|
||||
return prevHandle;
|
||||
return TRUE; /* We'll use a device font */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetCharWidth32A (GDI32.@)
|
||||
* WIN16DRV_GetCharWidth
|
||||
*/
|
||||
BOOL WIN16DRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
|
||||
LPINT buffer )
|
||||
|
|
|
@ -3146,12 +3146,14 @@ LPIFONTINFO16 XFONT_GetFontInfo( X_PHYSFONT pFont )
|
|||
*/
|
||||
HFONT X11DRV_FONT_SelectObject( DC* dc, HFONT hfont )
|
||||
{
|
||||
HFONT hPrevFont = 0;
|
||||
LOGFONTW logfont;
|
||||
LOGFONT16 lf;
|
||||
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 );
|
||||
|
||||
|
@ -3215,12 +3217,9 @@ HFONT X11DRV_FONT_SelectObject( DC* dc, HFONT hfont )
|
|||
logfont.lfCharSet = charsetMatched;
|
||||
}
|
||||
|
||||
hPrevFont = dc->hFont;
|
||||
dc->hFont = hfont;
|
||||
|
||||
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. */
|
||||
#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. */
|
||||
#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_NewTextMetricEx16ToW(const NEWTEXTMETRICEX16*, LPNEWTEXTMETRICEXW);
|
||||
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 */
|
||||
|
|
|
@ -50,6 +50,8 @@ typedef struct tagGDIOBJHDR
|
|||
|
||||
typedef BOOL16 CALLBACK (*DCHOOKPROC)(HDC16,WORD,DWORD,LPARAM);
|
||||
|
||||
typedef struct tagGdiFont *GdiFont;
|
||||
|
||||
typedef struct tagDC
|
||||
{
|
||||
GDIOBJHDR header;
|
||||
|
@ -81,6 +83,7 @@ typedef struct tagDC
|
|||
HANDLE16 hDevice;
|
||||
HPALETTE16 hPalette;
|
||||
|
||||
GdiFont gdiFont;
|
||||
GdiPath path;
|
||||
|
||||
WORD ROPmode;
|
||||
|
|
|
@ -57,6 +57,7 @@ DC *DC_AllocDC( const DC_FUNCTIONS *funcs )
|
|||
dc->hBitmap = 0;
|
||||
dc->hDevice = 0;
|
||||
dc->hPalette = GetStockObject( DEFAULT_PALETTE );
|
||||
dc->gdiFont = 0;
|
||||
dc->ROPmode = R2_COPYPEN;
|
||||
dc->polyFillMode = ALTERNATE;
|
||||
dc->stretchBltMode = BLACKONWHITE;
|
||||
|
@ -311,6 +312,13 @@ HDC16 WINAPI GetDCState16( HDC16 hdc )
|
|||
}
|
||||
else
|
||||
newdc->hClipRgn = 0;
|
||||
|
||||
if(dc->gdiFont) {
|
||||
WineEngAddRefFont(dc->gdiFont);
|
||||
newdc->gdiFont = dc->gdiFont;
|
||||
} else
|
||||
newdc->gdiFont = 0;
|
||||
|
||||
GDI_ReleaseObj( handle );
|
||||
GDI_ReleaseObj( hdc );
|
||||
return handle;
|
||||
|
@ -767,6 +775,7 @@ BOOL WINAPI DeleteDC( HDC hdc )
|
|||
if (dc->hGCClipRgn) DeleteObject( dc->hGCClipRgn );
|
||||
if (dc->pAbortProc) THUNK_Free( (FARPROC)dc->pAbortProc );
|
||||
if (dc->hookThunk) THUNK_Free( (FARPROC)dc->hookThunk );
|
||||
if (dc->gdiFont) WineEngDecRefFont( dc->gdiFont );
|
||||
PATH_DestroyGdiPath(&dc->path);
|
||||
|
||||
GDI_FreeObject( hdc, dc );
|
||||
|
|
286
objects/font.c
286
objects/font.c
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "winerror.h"
|
||||
#include "winnls.h"
|
||||
#include "font.h"
|
||||
|
@ -724,25 +725,28 @@ static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
|
|||
LPARAM lParam, DWORD dwUnicode)
|
||||
{
|
||||
BOOL (*enum_func)(HDC,LPLOGFONTW,DEVICEFONTENUMPROC,LPARAM);
|
||||
INT ret = 0;
|
||||
INT ret = 1;
|
||||
DC *dc = DC_GetDCPtr( hDC );
|
||||
fontEnum32 fe32;
|
||||
BOOL enum_gdi_fonts;
|
||||
|
||||
if (!dc) return 0;
|
||||
enum_func = dc->funcs->pEnumDeviceFonts;
|
||||
GDI_ReleaseObj( hDC );
|
||||
|
||||
if (enum_func)
|
||||
{
|
||||
fontEnum32 fe32;
|
||||
|
||||
fe32.lpLogFontParam = plf;
|
||||
fe32.lpEnumFunc = efproc;
|
||||
fe32.lpData = lParam;
|
||||
|
||||
fe32.dwFlags = dwUnicode;
|
||||
|
||||
enum_func = dc->funcs->pEnumDeviceFonts;
|
||||
GDI_ReleaseObj( hDC );
|
||||
enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
|
||||
|
||||
if (!enum_func && !enum_gdi_fonts) return 0;
|
||||
|
||||
if (enum_gdi_fonts)
|
||||
ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
|
||||
if (ret && enum_func)
|
||||
ret = enum_func( hDC, plf, FONT_EnumInstance, (LPARAM)&fe32 );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1029,25 +1033,15 @@ BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
|
|||
{
|
||||
BOOL ret = FALSE;
|
||||
UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */
|
||||
DC * dc = DC_GetDCPtr( hdc );
|
||||
|
||||
if (!dc) return FALSE;
|
||||
|
||||
if (dc->funcs->pGetTextExtentPoint)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
|
||||
if (p) {
|
||||
wlen = MultiByteToWideChar(codepage,0,str,count,p,wlen);
|
||||
ret = dc->funcs->pGetTextExtentPoint( dc, p, wlen, size );
|
||||
ret = GetTextExtentPoint32W( hdc, p, wlen, size );
|
||||
HeapFree( GetProcessHeap(), 0, p );
|
||||
}
|
||||
}
|
||||
GDI_ReleaseObj( hdc );
|
||||
|
||||
TRACE("(%08x %s %d %p): returning %ld x %ld\n",
|
||||
hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
|
||||
return ret;
|
||||
|
@ -1071,12 +1065,15 @@ BOOL WINAPI GetTextExtentPoint32W(
|
|||
{
|
||||
BOOL ret = FALSE;
|
||||
DC * dc = DC_GetDCPtr( hdc );
|
||||
if (dc)
|
||||
{
|
||||
if(dc->funcs->pGetTextExtentPoint)
|
||||
if (!dc) return FALSE;
|
||||
|
||||
if(dc->gdiFont)
|
||||
ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
|
||||
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",
|
||||
hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
|
||||
return ret;
|
||||
|
@ -1160,15 +1157,11 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
|
|||
int index, nFit, extent;
|
||||
SIZE tSize;
|
||||
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;
|
||||
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. */
|
||||
/* FIXME - justification needs doing yet. Remember that the base
|
||||
* 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);
|
||||
|
||||
done:
|
||||
GDI_ReleaseObj( hdc );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1229,7 +1221,12 @@ BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
|
|||
DC * dc = DC_GetDCPtr( hdc );
|
||||
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
|
||||
* therefore we have to convert them to logical */
|
||||
|
@ -1311,63 +1308,131 @@ UINT WINAPI GetOutlineTextMetricsA(
|
|||
UINT cbData, /* [in] Size 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;
|
||||
|
||||
|
||||
UINT rtn = FALSE;
|
||||
LPTEXTMETRICA lptxtMetr;
|
||||
|
||||
|
||||
|
||||
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))
|
||||
{
|
||||
if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) {
|
||||
if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
|
||||
return 0;
|
||||
} else
|
||||
{
|
||||
memcpy(&(lpOTM->otmTextMetrics),lptxtMetr,sizeof(TEXTMETRICA));
|
||||
};
|
||||
lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
|
||||
GetOutlineTextMetricsW(hdc, ret, lpOTMW);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(),HEAP_ZERO_MEMORY,lptxtMetr);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
lpOTM->otmSize = needed;
|
||||
FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics );
|
||||
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;
|
||||
lpOTM->otmfsType = 0;
|
||||
ptr = (char*)(lpOTM + 1);
|
||||
left = needed - sizeof(*lpOTM);
|
||||
|
||||
/*
|
||||
Further fill of the structure not implemented,
|
||||
Needs real values for the structure members
|
||||
*/
|
||||
if(lpOTMW->otmpFamilyName) {
|
||||
lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM);
|
||||
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;
|
||||
|
||||
return rtn;
|
||||
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;
|
||||
|
||||
assert(left == 0);
|
||||
|
||||
ret = needed;
|
||||
|
||||
end:
|
||||
if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
|
||||
HeapFree(GetProcessHeap(), 0, lpOTMW);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetOutlineTextMetricsW [GDI32.@]
|
||||
*/
|
||||
|
@ -1376,10 +1441,38 @@ UINT WINAPI GetOutlineTextMetricsW(
|
|||
UINT cbData, /* [in] Size of metric data array */
|
||||
LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
|
||||
{
|
||||
FIXME("(%d,%d,%p): stub\n", hdc, cbData, lpOTM);
|
||||
return 0;
|
||||
DC *dc = DC_GetDCPtr( hdc );
|
||||
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)
|
||||
*/
|
||||
|
@ -1428,7 +1521,12 @@ BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
|
|||
DC * dc = DC_GetDCPtr( hdc );
|
||||
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 */
|
||||
|
||||
|
@ -1589,9 +1687,8 @@ DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
|
|||
LPGLYPHMETRICS lpgm, DWORD cbBuffer,
|
||||
LPVOID lpBuffer, const MAT2 *lpmat2 )
|
||||
{
|
||||
FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
|
||||
hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
|
||||
return (DWORD)-1; /* failure */
|
||||
return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
|
||||
lpmat2);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1601,9 +1698,22 @@ DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
|
|||
LPGLYPHMETRICS lpgm, DWORD cbBuffer,
|
||||
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 );
|
||||
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 );
|
||||
|
||||
WineEngInit();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -732,7 +735,46 @@ HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
|
|||
}
|
||||
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)
|
||||
|
@ -752,7 +794,12 @@ HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
|
|||
DC * dc = DC_GetDCUpdate( hdc );
|
||||
if (!dc) return 0;
|
||||
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 );
|
||||
GDI_ReleaseObj( hdc );
|
||||
|
||||
|
|
Loading…
Reference in New Issue