diff --git a/dlls/gdi/freetype.c b/dlls/gdi/freetype.c index a29fb29fe7f..cd61e513187 100644 --- a/dlls/gdi/freetype.c +++ b/dlls/gdi/freetype.c @@ -1723,6 +1723,33 @@ BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count, return TRUE; } +/************************************************************* + * WineEngGetTextExtentPointI + * + */ +BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count, + LPSIZE size) +{ + UINT idx; + GLYPHMETRICS gm; + TEXTMETRICW tm; + + TRACE("%p, %p, %d, %p\n", font, indices, count, size); + + size->cx = 0; + WineEngGetTextMetrics(font, &tm); + size->cy = tm.tmHeight; + + for(idx = 0; idx < count; idx++) { + WineEngGetGlyphOutline(font, indices[idx], + GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, + NULL); + size->cx += font->gm[indices[idx]].adv; + } + TRACE("return %ld,%ld\n", size->cx, size->cy); + return TRUE; +} + /************************************************************* * WineEngGetFontData * @@ -1824,6 +1851,13 @@ BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count, return FALSE; } +BOOL WineEngGetTextExtentPointI(GdiFont font, LPWORD indices, INT count, + LPSIZE size) +{ + ERR("called but we don't have FreeType\n"); + return FALSE; +} + DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf, DWORD cbData) { diff --git a/dlls/gdi/gdi32.spec b/dlls/gdi/gdi32.spec index 256db66e3d2..5c632a0ac13 100644 --- a/dlls/gdi/gdi32.spec +++ b/dlls/gdi/gdi32.spec @@ -273,10 +273,11 @@ debug_channels (bitblt bitmap clipping dc ddraw driver enhmetafile font gdi @ stdcall GetTextColor(long) GetTextColor @ stdcall GetTextExtentExPointA(long str long long ptr ptr ptr) GetTextExtentExPointA @ stdcall GetTextExtentExPointW(long wstr long long ptr ptr ptr) GetTextExtentExPointW -@ stdcall GetTextExtentPoint32A(long ptr long ptr) GetTextExtentPoint32A -@ stdcall GetTextExtentPoint32W(long ptr long ptr) GetTextExtentPoint32W -@ stdcall GetTextExtentPointA(long ptr long ptr) GetTextExtentPointA -@ stdcall GetTextExtentPointW(long ptr long ptr) GetTextExtentPointW +@ stdcall GetTextExtentPoint32A(long str long ptr) GetTextExtentPoint32A +@ stdcall GetTextExtentPoint32W(long wstr long ptr) GetTextExtentPoint32W +@ stdcall GetTextExtentPointA(long str long ptr) GetTextExtentPointA +@ stdcall GetTextExtentPointI(long ptr long ptr) GetTextExtentPointI +@ stdcall GetTextExtentPointW(long wstr long ptr) GetTextExtentPointW @ stdcall GetTextFaceA(long long ptr) GetTextFaceA @ stdcall GetTextFaceW(long long ptr) GetTextFaceW @ stdcall GetTextMetricsA(long ptr) GetTextMetricsA diff --git a/dlls/x11drv/xrender.c b/dlls/x11drv/xrender.c index 417012426a7..327ad89f168 100644 --- a/dlls/x11drv/xrender.c +++ b/dlls/x11drv/xrender.c @@ -365,7 +365,7 @@ void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev) return; } -static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, WCHAR glyph) +static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph) { int buflen; char *buf; @@ -373,7 +373,7 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, WCHAR glyph) GLYPHMETRICS gm; XGlyphInfo gi; gsCacheEntry *entry = physDev->xrender->cacheEntry; - UINT ggo_format; + UINT ggo_format = GGO_GLYPH_INDEX; BOOL aa; if(entry->nrealized <= glyph) { @@ -387,10 +387,10 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, WCHAR glyph) if(entry->font_format->depth == 8) { aa = TRUE; - ggo_format = WINE_GGO_GRAY16_BITMAP; + ggo_format |= WINE_GGO_GRAY16_BITMAP; } else { aa = FALSE; - ggo_format = GGO_BITMAP; + ggo_format |= GGO_BITMAP; } buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL, @@ -490,11 +490,20 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag XGCValues xgcval; LOGFONTW lf; int render_op = PictOpOver; + WORD *glyphs; HDC hdc = physDev->hdc; DC *dc = physDev->dc; TRACE("%04x, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags, lprect, debugstr_wn(wstr, count), count, lpDx); + + if(flags & ETO_GLYPH_INDEX) + glyphs = (LPWORD)wstr; + else { + glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR)); + GetGlyphIndicesW(hdc, wstr, count, glyphs, 0); + } + if(lprect) TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right, lprect->bottom); @@ -517,7 +526,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag if(flags & (ETO_CLIPPED | ETO_OPAQUE)) { if(!lprect) { if(flags & ETO_CLIPPED) return FALSE; - GetTextExtentPointW(hdc, wstr, count, &sz); + GetTextExtentPointI(hdc, glyphs, count, &sz); done_extents = TRUE; rc.left = x; rc.top = y; @@ -567,7 +576,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag width += lpDx[idx]; } else { if(!done_extents) { - GetTextExtentPointW(hdc, wstr, count, &sz); + GetTextExtentPointI(hdc, glyphs, count, &sz); done_extents = TRUE; } width = sz.cx; @@ -746,9 +755,9 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag render_op = PictOpOutReverse; /* This gives us 'black' text */ for(idx = 0; idx < count; idx++) { - if(wstr[idx] >= physDev->xrender->cacheEntry->nrealized || - physDev->xrender->cacheEntry->realized[wstr[idx]] == FALSE) { - UploadGlyph(physDev, wstr[idx]); + if(glyphs[idx] >= physDev->xrender->cacheEntry->nrealized || + physDev->xrender->cacheEntry->realized[glyphs[idx]] == FALSE) { + UploadGlyph(physDev, glyphs[idx]); } } @@ -761,8 +770,8 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag physDev->xrender->pict, physDev->xrender->cacheEntry->font_format, physDev->xrender->cacheEntry->glyphset, - 0, 0, dc->DCOrgX + x, dc->DCOrgY + y, (unsigned short *)wstr, - count); + 0, 0, dc->DCOrgX + x, dc->DCOrgY + y, + glyphs, count); else { INT offset = 0, xoff = 0, yoff = 0; @@ -774,7 +783,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag physDev->xrender->cacheEntry->glyphset, 0, 0, dc->DCOrgX + x + xoff, dc->DCOrgY + y + yoff, - (unsigned short *)wstr + idx, 1); + glyphs + idx, 1); offset += INTERNAL_XWSTODS(dc, lpDx[idx]); xoff = offset * cosEsc; yoff = offset * -sinEsc; @@ -791,6 +800,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag RestoreVisRgn16( hdc ); X11DRV_UnlockDIBSection( physDev, TRUE ); + if(glyphs != wstr) HeapFree(GetProcessHeap(), 0, glyphs); return TRUE; } diff --git a/include/font.h b/include/font.h index 8cfbdb47688..19c6de6fe4f 100644 --- a/include/font.h +++ b/include/font.h @@ -99,6 +99,7 @@ extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format, const MAT2*); extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW); extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE); +extern BOOL WineEngGetTextExtentPointI(GdiFont, const WORD *, INT, LPSIZE); extern BOOL WineEngGetTextMetrics(GdiFont, LPTEXTMETRICW); extern BOOL WineEngInit(void); diff --git a/include/gdi.h b/include/gdi.h index 69820617eca..d68a59e1e48 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -493,6 +493,58 @@ static inline INT WINE_UNUSED INTERNAL_YWSTODS(DC *dc, INT height) } + /* Device -> World size conversion */ + +/* Performs a device to world transformation on the specified width (which + * is in floating point format). + */ +static inline void INTERNAL_XDSTOWS_FLOAT(DC *dc, FLOAT *width) +{ + /* Perform the transformation */ + *width = *width * dc->xformVport2World.eM11; +} + +/* Performs a device to world transformation on the specified width (which + * is in integer format). + */ +static inline INT INTERNAL_XDSTOWS(DC *dc, INT width) +{ + FLOAT floatWidth; + + /* Perform operation with floating point */ + floatWidth = (FLOAT)width; + INTERNAL_XDSTOWS_FLOAT(dc, &floatWidth); + + /* Round to integers */ + return GDI_ROUND(floatWidth); +} + + +/* Performs a device to world transformation on the specified size (which + * is in floating point format). + */ +static inline void INTERNAL_YDSTOWS_FLOAT(DC *dc, FLOAT *height) +{ + /* Perform the transformation */ + *height = *height * dc->xformVport2World.eM22; +} + +/* Performs a device to world transformation on the specified size (which + * is in integer format). + */ +static inline INT INTERNAL_YDSTOWS(DC *dc, INT height) +{ + FLOAT floatHeight; + + /* Perform operation with floating point */ + floatHeight = (FLOAT)height; + INTERNAL_YDSTOWS_FLOAT(dc, &floatHeight); + + /* Round to integers */ + return GDI_ROUND(floatHeight); +} + + /* Device <-> logical size conversion */ #define XDSTOLS(dc,x) \ diff --git a/include/wingdi.h b/include/wingdi.h index 47eb2a98c8a..0918af7fd31 100644 --- a/include/wingdi.h +++ b/include/wingdi.h @@ -1343,7 +1343,7 @@ typedef struct tagGCP_RESULTSW UINT *lpOrder; INT *lpDx; INT *lpCaretPos; - LPWSTR lpClass; + LPSTR lpClass; LPWSTR lpGlyphs; UINT nGlyphs; UINT nMaxFit; @@ -3270,13 +3270,15 @@ BOOL WINAPI GetTextExtentExPointA(HDC,LPCSTR,INT,INT, LPINT,LPINT,LPSIZE); BOOL WINAPI GetTextExtentExPointW(HDC,LPCWSTR,INT,INT, LPINT,LPINT,LPSIZE); +#define GetTextExtentExPoint WINELIB_NAME_AW(GetTextExtentExPoint) BOOL WINAPI GetTextExtentPointA(HDC,LPCSTR,INT,LPSIZE); BOOL WINAPI GetTextExtentPointW(HDC,LPCWSTR,INT,LPSIZE); #define GetTextExtentPoint WINELIB_NAME_AW(GetTextExtentPoint) BOOL WINAPI GetTextExtentPoint32A(HDC,LPCSTR,INT,LPSIZE); BOOL WINAPI GetTextExtentPoint32W(HDC,LPCWSTR,INT,LPSIZE); #define GetTextExtentPoint32 WINELIB_NAME_AW(GetTextExtentPoint32) -#define GetTextExtentExPoint WINELIB_NAME_AW(GetTextExtentExPoint) +BOOL WINAPI GetTextExtentExPointI(HDC,const WORD*,INT,INT,LPINT,LPINT,LPSIZE); +BOOL WINAPI GetTextExtentPointI(HDC,const WORD*,INT,LPSIZE); INT WINAPI GetTextFaceA(HDC,INT,LPSTR); INT WINAPI GetTextFaceW(HDC,INT,LPWSTR); #define GetTextFace WINELIB_NAME_AW(GetTextFace) diff --git a/objects/font.c b/objects/font.c index 656717bbc38..99264d41169 100644 --- a/objects/font.c +++ b/objects/font.c @@ -1084,8 +1084,11 @@ BOOL WINAPI GetTextExtentPoint32W( DC * dc = DC_GetDCPtr( hdc ); if (!dc) return FALSE; - if(dc->gdiFont) + if(dc->gdiFont) { ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size); + size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx)); + size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy)); + } else if(dc->funcs->pGetTextExtentPoint) ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size ); @@ -1096,6 +1099,42 @@ BOOL WINAPI GetTextExtentPoint32W( return ret; } +/*********************************************************************** + * GetTextExtentPointI [GDI32.@] + * + * Computes width and height of the array of glyph indices. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI GetTextExtentPointI( + HDC hdc, /* [in] Handle of device context */ + const WORD *indices, /* [in] Address of glyph index array */ + INT count, /* [in] Number of glyphs in array */ + LPSIZE size) /* [out] Address of structure for string size */ +{ + BOOL ret = FALSE; + DC * dc = DC_GetDCPtr( hdc ); + if (!dc) return FALSE; + + if(dc->gdiFont) { + ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size); + size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx)); + size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy)); + } + else if(dc->funcs->pGetTextExtentPoint) { + FIXME("calling GetTextExtentPoint\n"); + ret = dc->funcs->pGetTextExtentPoint( dc, (LPCWSTR)indices, count, size ); + } + + GDI_ReleaseObj( hdc ); + + TRACE("(%08x %p %d %p): returning %ld x %ld\n", + hdc, indices, count, size, size->cx, size->cy ); + return ret; +} + /*********************************************************************** * GetTextExtentPointA (GDI32.@)