Lay down the infrastructure for gdi font rendering.

Partial implementation of GetGylphOutline and GetOutlineTextMetrics
for gdi fonts.
This commit is contained in:
Huw D M Davies 2001-09-12 20:21:06 +00:00 committed by Alexandre Julliard
parent 37a4639ee1
commit 814654ef9f
16 changed files with 1284 additions and 276 deletions

287
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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
View 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 */

View File

@ -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;
} }
/*********************************************************************** /***********************************************************************

View File

@ -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 */
} }
/*********************************************************************** /***********************************************************************

View File

@ -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;
} }

View File

@ -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;
} }
/****************************************************************** /******************************************************************

View File

@ -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 )

View File

@ -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 */
} }

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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 );

View File

@ -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;
enum_func = dc->funcs->pEnumDeviceFonts;
GDI_ReleaseObj( hDC );
if (enum_func)
{
fontEnum32 fe32;
fe32.lpLogFontParam = plf; fe32.lpLogFontParam = plf;
fe32.lpEnumFunc = efproc; fe32.lpEnumFunc = efproc;
fe32.lpData = lParam; fe32.lpData = lParam;
fe32.dwFlags = dwUnicode; 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 ); 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 );
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); UINT wlen = MultiByteToWideChar(codepage,0,str,count,NULL,0);
LPWSTR p = HeapAlloc( GetProcessHeap(), 0, wlen * sizeof(WCHAR) ); LPWSTR p = HeapAlloc( GetProcessHeap(), 0, wlen * sizeof(WCHAR) );
if (p)
{ if (p) {
wlen = MultiByteToWideChar(codepage,0,str,count,p,wlen); 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 ); 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 = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
else if(dc->funcs->pGetTextExtentPoint)
ret = dc->funcs->pGetTextExtentPoint( dc, str, count, size ); ret = dc->funcs->pGetTextExtentPoint( dc, str, count, size );
GDI_ReleaseObj( hdc ); 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) {
UINT rtn = FALSE; if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
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))
{
return 0; return 0;
} else lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
{ GetOutlineTextMetricsW(hdc, ret, lpOTMW);
memcpy(&(lpOTM->otmTextMetrics),lptxtMetr,sizeof(TEXTMETRICA));
};
HeapFree(GetProcessHeap(),HEAP_ZERO_MEMORY,lptxtMetr);
lpOTM->otmFiller = 0;
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;
/*
Further fill of the structure not implemented,
Needs real values for the structure members
*/
return rtn;
} }
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;
ptr = (char*)(lpOTM + 1);
left = needed - sizeof(*lpOTM);
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;
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.@] * GetOutlineTextMetricsW [GDI32.@]
*/ */
@ -1376,9 +1441,37 @@ 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;
} }
/*********************************************************************** /***********************************************************************

View File

@ -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 );