From f9047238134e1dbfd7eaedf81a6ee94788a4681d Mon Sep 17 00:00:00 2001 From: Dan Hipschman Date: Tue, 11 Jul 2006 17:58:35 -0700 Subject: [PATCH] gdi32: Implement GetTextExtentPoint in terms of GetTextExtentExPoint (not vice versa) for efficiency (required adding the Ex functionality to drivers). --- dlls/gdi/driver.c | 2 +- dlls/gdi/enhmfdrv/init.c | 2 +- dlls/gdi/font.c | 106 +++++++++++++++++------------- dlls/gdi/freetype.c | 27 +++++--- dlls/gdi/gdi_private.h | 4 +- dlls/gdi/mfdrv/init.c | 2 +- dlls/wineps.drv/builtin.c | 19 +++++- dlls/wineps.drv/psdrv.h | 4 +- dlls/wineps.drv/wineps.drv.spec | 2 +- dlls/winex11.drv/codepage.c | 32 +++++++-- dlls/winex11.drv/text.c | 18 +++-- dlls/winex11.drv/winex11.drv.spec | 2 +- dlls/winex11.drv/x11font.h | 3 +- 13 files changed, 149 insertions(+), 74 deletions(-) diff --git a/dlls/gdi/driver.c b/dlls/gdi/driver.c index 8d50e8c2ba9..76657a7d5c2 100644 --- a/dlls/gdi/driver.c +++ b/dlls/gdi/driver.c @@ -121,7 +121,7 @@ static struct graphics_driver *create_driver( HMODULE module ) GET_FUNC(GetPixel); GET_FUNC(GetPixelFormat); GET_FUNC(GetSystemPaletteEntries); - GET_FUNC(GetTextExtentPoint); + GET_FUNC(GetTextExtentExPoint); GET_FUNC(GetTextMetrics); GET_FUNC(IntersectClipRect); GET_FUNC(InvertRgn); diff --git a/dlls/gdi/enhmfdrv/init.c b/dlls/gdi/enhmfdrv/init.c index 82f0222fe7c..c3677b0d61f 100644 --- a/dlls/gdi/enhmfdrv/init.c +++ b/dlls/gdi/enhmfdrv/init.c @@ -80,7 +80,7 @@ static const DC_FUNCTIONS EMFDRV_Funcs = NULL, /* pGetPixel */ NULL, /* pGetPixelFormat */ NULL, /* pGetSystemPaletteEntries */ - NULL, /* pGetTextExtentPoint */ + NULL, /* pGetTextExtentExPoint */ NULL, /* pGetTextMetrics */ EMFDRV_IntersectClipRect, /* pIntersectClipRect */ EMFDRV_InvertRgn, /* pInvertRgn */ diff --git a/dlls/gdi/font.c b/dlls/gdi/font.c index 33a03f6c376..c4441915204 100644 --- a/dlls/gdi/font.c +++ b/dlls/gdi/font.c @@ -1053,27 +1053,7 @@ BOOL WINAPI GetTextExtentPoint32W( INT count, /* [in] Number of characters in string */ 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 = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size); - else if(dc->funcs->pGetTextExtentPoint) - ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size ); - - if (ret) - { - size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx)); - size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy)); - size->cx += count * dc->charExtra + dc->breakRem; - } - - GDI_ReleaseObj( hdc ); - - TRACE("(%p %s %d %p): returning %ld x %ld\n", - hdc, debugstr_wn (str, count), count, size, size->cx, size->cy ); - return ret; + return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size); } /*********************************************************************** @@ -1101,9 +1081,10 @@ BOOL WINAPI GetTextExtentPointI( size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy)); size->cx += count * dc->charExtra; } - else if(dc->funcs->pGetTextExtentPoint) { - FIXME("calling GetTextExtentPoint\n"); - ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size ); + else if(dc->funcs->pGetTextExtentExPoint) { + FIXME("calling GetTextExtentExPoint\n"); + ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices, + count, 0, NULL, NULL, size ); } GDI_ReleaseObj( hdc ); @@ -1205,36 +1186,69 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count, INT maxExt, LPINT lpnFit, LPINT alpDx, LPSIZE size ) { - int index, nFit, extent; - SIZE tSize; + INT nFit = 0; + LPINT dxs = NULL; + DC *dc; BOOL ret = FALSE; TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt); - size->cx = size->cy = nFit = extent = 0; - for(index = 0; index < count; index++) + dc = DC_GetDCPtr(hdc); + if (! dc) + return FALSE; + + /* If we need to calculate nFit, then we need the partial extents even if + the user hasn't provided us with an array. */ + if (lpnFit) { - if(!GetTextExtentPoint32W( hdc, str, index + 1, &tSize )) goto done; - /* GetTextExtentPoint includes intercharacter spacing. */ - /* FIXME - justification needs doing yet. Remember that the base - * data will not be in logical coordinates. - */ - extent = tSize.cx; - if( !lpnFit || extent <= maxExt ) - /* It is allowed to be equal. */ - { - nFit++; - if( alpDx ) alpDx[index] = extent; - } - if( tSize.cy > size->cy ) size->cy = tSize.cy; + dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]); + if (! dxs) + { + GDI_ReleaseObj(hdc); + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } } - size->cx = extent; - if(lpnFit) *lpnFit = nFit; - ret = TRUE; + else + dxs = alpDx; + + if (dc->gdiFont) + ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count, + 0, NULL, dxs, size); + else if (dc->funcs->pGetTextExtentExPoint) + ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count, + 0, NULL, dxs, size); + + /* Perform device size to world size transformations. */ + if (ret) + { + INT extra = dc->charExtra, breakRem = dc->breakRem; + + if (dxs) + { + INT i; + for (i = 0; i < count; ++i) + { + dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i])); + dxs[i] += (i+1) * extra + breakRem; + if (dxs[i] <= maxExt) + ++nFit; + } + } + size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx)); + size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy)); + size->cx += count * extra + breakRem; + } + + if (lpnFit) + *lpnFit = nFit; + + if (dxs && ! alpDx) + HeapFree(GetProcessHeap(), 0, dxs); + + GDI_ReleaseObj( hdc ); TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy); - -done: return ret; } diff --git a/dlls/gdi/freetype.c b/dlls/gdi/freetype.c index 9f52e602090..7fb62bd95e2 100644 --- a/dlls/gdi/freetype.c +++ b/dlls/gdi/freetype.c @@ -3849,20 +3849,21 @@ BOOL WineEngGetCharABCWidthsI(GdiFont font, UINT firstChar, UINT count, LPWORD p } /************************************************************* - * WineEngGetTextExtentPoint + * WineEngGetTextExtentExPoint * */ -BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count, - LPSIZE size) +BOOL WineEngGetTextExtentExPoint(GdiFont font, LPCWSTR wstr, INT count, + INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size) { INT idx; + INT nfit = 0, ext; GLYPHMETRICS gm; TEXTMETRICW tm; FT_UInt glyph_index; GdiFont linked_font; - TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count, - size); + TRACE("%p, %s, %d, %d, %p\n", font, debugstr_wn(wstr, count), count, + max_ext, size); size->cx = 0; WineEngGetTextMetrics(font, &tm); @@ -3873,8 +3874,18 @@ BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count, WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, NULL); size->cx += linked_font->gm[glyph_index].adv; + ext = size->cx; + if (! pnfit || ext <= max_ext) { + ++nfit; + if (dxs) + dxs[idx] = ext; + } } - TRACE("return %ld,%ld\n", size->cx, size->cy); + + if (pnfit) + *pnfit = nfit; + + TRACE("return %ld, %ld, %d\n", size->cx, size->cy, nfit); return TRUE; } @@ -4149,8 +4160,8 @@ BOOL WineEngGetCharABCWidthsI(GdiFont font, UINT firstChar, UINT count, LPWORD p return FALSE; } -BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count, - LPSIZE size) +BOOL WineEngGetTextExtentExPoint(GdiFont font, LPCWSTR wstr, INT count, + INT max_ext, LPINT nfit, LPINT dx, LPSIZE size) { ERR("called but we don't have FreeType\n"); return FALSE; diff --git a/dlls/gdi/gdi_private.h b/dlls/gdi/gdi_private.h index 610babb1d0a..a0de444d133 100644 --- a/dlls/gdi/gdi_private.h +++ b/dlls/gdi/gdi_private.h @@ -107,7 +107,7 @@ typedef struct tagDC_FUNCS COLORREF (*pGetPixel)(PHYSDEV,INT,INT); INT (*pGetPixelFormat)(PHYSDEV); UINT (*pGetSystemPaletteEntries)(PHYSDEV,UINT,UINT,LPPALETTEENTRY); - BOOL (*pGetTextExtentPoint)(PHYSDEV,LPCWSTR,INT,LPSIZE); + BOOL (*pGetTextExtentExPoint)(PHYSDEV,LPCWSTR,INT,INT,LPINT,LPINT,LPSIZE); BOOL (*pGetTextMetrics)(PHYSDEV,TEXTMETRICW*); INT (*pIntersectClipRect)(PHYSDEV,INT,INT,INT,INT); BOOL (*pInvertRgn)(PHYSDEV,HRGN); @@ -379,7 +379,7 @@ extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format, extern BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph); extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW); extern UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags); -extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE); +extern BOOL WineEngGetTextExtentExPoint(GdiFont, LPCWSTR, INT, INT, LPINT, LPINT, LPSIZE); extern BOOL WineEngGetTextExtentPointI(GdiFont, const WORD *, INT, LPSIZE); extern INT WineEngGetTextFace(GdiFont, INT, LPWSTR); extern BOOL WineEngGetTextMetrics(GdiFont, LPTEXTMETRICW); diff --git a/dlls/gdi/mfdrv/init.c b/dlls/gdi/mfdrv/init.c index bf964a7e467..c85501a65ad 100644 --- a/dlls/gdi/mfdrv/init.c +++ b/dlls/gdi/mfdrv/init.c @@ -80,7 +80,7 @@ static const DC_FUNCTIONS MFDRV_Funcs = NULL, /* pGetPixel */ NULL, /* pGetPixelFormat */ NULL, /* pGetSystemPaletteEntries */ - NULL, /* pGetTextExtentPoint */ + NULL, /* pGetTextExtentExPoint */ NULL, /* pGetTextMetrics */ MFDRV_IntersectClipRect, /* pIntersectClipRect */ MFDRV_InvertRgn, /* pInvertRgn */ diff --git a/dlls/wineps.drv/builtin.c b/dlls/wineps.drv/builtin.c index 7c4cd8cdb73..fe436dab55b 100644 --- a/dlls/wineps.drv/builtin.c +++ b/dlls/wineps.drv/builtin.c @@ -304,23 +304,38 @@ const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const AFM *afm) } /*********************************************************************** - * PSDRV_GetTextExtentPoint + * PSDRV_GetTextExtentExPoint */ -BOOL PSDRV_GetTextExtentPoint(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count, LPSIZE size) +BOOL PSDRV_GetTextExtentExPoint(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count, + INT maxExt, LPINT lpnFit, LPINT alpDx, LPSIZE size) { + int nfit = 0; int i; float width = 0.0; + float scale; assert(physDev->font.fontloc == Builtin); TRACE("%s %i\n", debugstr_wn(str, count), count); + scale = physDev->font.fontinfo.Builtin.scale; for (i = 0; i < count && str[i] != '\0'; ++i) + { + float scaled_width; width += PSDRV_UVMetrics(str[i], physDev->font.fontinfo.Builtin.afm)->WX; + scaled_width = width * scale; + if (alpDx) + alpDx[i] = scaled_width; + if (scaled_width <= maxExt) + ++nfit; + } size->cx = width * physDev->font.fontinfo.Builtin.scale; size->cy = physDev->font.fontinfo.Builtin.tm.tmHeight; + if (lpnFit) + *lpnFit = nfit; + TRACE("cx=%li cy=%li\n", size->cx, size->cy); return TRUE; diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h index 94dbb0b97d2..f60731daee3 100644 --- a/dlls/wineps.drv/psdrv.h +++ b/dlls/wineps.drv/psdrv.h @@ -480,8 +480,8 @@ extern BOOL PSDRV_ExtTextOut( PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags, const INT *lpDx ); extern BOOL PSDRV_GetCharWidth( PSDRV_PDEVICE *physDev, UINT firstChar, UINT lastChar, LPINT buffer ); -extern BOOL PSDRV_GetTextExtentPoint( PSDRV_PDEVICE *physDev, LPCWSTR str, INT count, - LPSIZE size ); +extern BOOL PSDRV_GetTextExtentExPoint( PSDRV_PDEVICE *physDev, LPCWSTR str, INT count, + INT maxExt, LPINT lpnFit, LPINT alpDx, LPSIZE size ); extern BOOL PSDRV_GetTextMetrics( PSDRV_PDEVICE *physDev, TEXTMETRICW *metrics ); extern BOOL PSDRV_LineTo( PSDRV_PDEVICE *physDev, INT x, INT y ); extern BOOL PSDRV_PatBlt( PSDRV_PDEVICE *physDev, INT x, INT y, INT width, INT height, DWORD diff --git a/dlls/wineps.drv/wineps.drv.spec b/dlls/wineps.drv/wineps.drv.spec index 79082d4fed9..1d3f20c7af3 100644 --- a/dlls/wineps.drv/wineps.drv.spec +++ b/dlls/wineps.drv/wineps.drv.spec @@ -14,7 +14,7 @@ @ cdecl ExtTextOut(ptr long long long ptr ptr long ptr) PSDRV_ExtTextOut @ cdecl GetCharWidth(ptr long long ptr) PSDRV_GetCharWidth @ cdecl GetDeviceCaps(ptr long) PSDRV_GetDeviceCaps -@ cdecl GetTextExtentPoint(ptr ptr long ptr) PSDRV_GetTextExtentPoint +@ cdecl GetTextExtentExPoint(ptr ptr long long ptr ptr ptr) PSDRV_GetTextExtentExPoint @ cdecl GetTextMetrics(ptr ptr) PSDRV_GetTextMetrics @ cdecl LineTo(ptr long long) PSDRV_LineTo @ cdecl PaintRgn(ptr long) PSDRV_PaintRgn diff --git a/dlls/winex11.drv/codepage.c b/dlls/winex11.drv/codepage.c index 86201dafc9b..697b6483f52 100644 --- a/dlls/winex11.drv/codepage.c +++ b/dlls/winex11.drv/codepage.c @@ -432,14 +432,32 @@ static void X11DRV_DrawText_normal( fontObject* pfo, Display* pdisp, Drawable d, static void X11DRV_TextExtents_normal( fontObject* pfo, XChar2b* pstr, int count, int* pdir, int* pascent, int* pdescent, - int* pwidth ) + int* pwidth, int max_extent, int* pfit, + int* partial_extents ) { XCharStruct info; + int ascent, descent, width; + int i, fit; + width = 0; + fit = 0; + *pascent = 0; + *pdescent = 0; wine_tsx11_lock(); - XTextExtents16( pfo->fs, pstr, count, pdir, pascent, pdescent, &info ); + for ( i = 0; i < count; i++ ) + { + XTextExtents16( pfo->fs, pstr, 1, pdir, &ascent, &descent, &info ); + if ( *pascent < ascent ) *pascent = ascent; + if ( *pdescent < descent ) *pdescent = descent; + width += info.width; + if ( partial_extents ) partial_extents[i] = width; + if ( width < max_extent ) fit++; + + pstr++; + } wine_tsx11_unlock(); - *pwidth = info.width; + *pwidth = width; + if ( pfit ) *pfit = fit; } static void X11DRV_GetTextMetricsW_normal( fontObject* pfo, LPTEXTMETRICW pTM ) @@ -594,11 +612,13 @@ void X11DRV_DrawText_dbcs_2fonts( fontObject* pfo, Display* pdisp, Drawable d, static void X11DRV_TextExtents_dbcs_2fonts( fontObject* pfo, XChar2b* pstr, int count, int* pdir, int* pascent, int* pdescent, - int* pwidth ) + int* pwidth, int max_extent, int* pfit, + int* partial_extents ) { XCharStruct info; int ascent, descent, width; int i; + int fit; int curfont; fontObject* pfos[X11FONT_REFOBJS_MAX+1]; @@ -607,6 +627,7 @@ void X11DRV_TextExtents_dbcs_2fonts( fontObject* pfo, XChar2b* pstr, int count, if ( pfos[0] == NULL ) pfos[0] = pfo; width = 0; + fit = 0; *pascent = 0; *pdescent = 0; wine_tsx11_lock(); @@ -617,11 +638,14 @@ void X11DRV_TextExtents_dbcs_2fonts( fontObject* pfo, XChar2b* pstr, int count, if ( *pascent < ascent ) *pascent = ascent; if ( *pdescent < descent ) *pdescent = descent; width += info.width; + if ( partial_extents ) partial_extents[i] = width; + if ( width <= max_extent ) fit++; pstr ++; } wine_tsx11_unlock(); *pwidth = width; + if ( pfit ) *pfit = fit; } static void X11DRV_GetTextMetricsW_cp932( fontObject* pfo, LPTEXTMETRICW pTM ) diff --git a/dlls/winex11.drv/text.c b/dlls/winex11.drv/text.c index 0ec9bbcc13d..8efd27a8a3d 100644 --- a/dlls/winex11.drv/text.c +++ b/dlls/winex11.drv/text.c @@ -201,10 +201,10 @@ END: /*********************************************************************** - * X11DRV_GetTextExtentPoint + * X11DRV_GetTextExtentExPoint */ -BOOL X11DRV_GetTextExtentPoint( X11DRV_PDEVICE *physDev, LPCWSTR str, INT count, - LPSIZE size ) +BOOL X11DRV_GetTextExtentExPoint( X11DRV_PDEVICE *physDev, LPCWSTR str, INT count, + INT maxExt, LPINT lpnFit, LPINT alpDx, LPSIZE size ) { fontObject* pfo = XFONT_GetFontObject( physDev->font ); @@ -216,23 +216,33 @@ BOOL X11DRV_GetTextExtentPoint( X11DRV_PDEVICE *physDev, LPCWSTR str, INT count, int dir, ascent, descent; int info_width; X11DRV_cptable[pfo->fi->cptable].pTextExtents( pfo, p, - count, &dir, &ascent, &descent, &info_width ); + count, &dir, &ascent, &descent, &info_width, + maxExt, lpnFit, alpDx ); size->cx = info_width; size->cy = pfo->fs->ascent + pfo->fs->descent; } else { INT i; + INT nfit = 0; float x = 0.0, y = 0.0; + float scaled_x = 0.0, pixsize = pfo->lpX11Trans->pixelsize; /* FIXME: Deal with *_char_or_byte2 != 0 situations */ for(i = 0; i < count; i++) { x += pfo->fs->per_char ? pfo->fs->per_char[p[i].byte2 - pfo->fs->min_char_or_byte2].attributes : pfo->fs->min_bounds.attributes; + scaled_x = x * pixsize / 1000.0; + if (alpDx) + alpDx[i] = scaled_x; + if (scaled_x <= maxExt) + ++nfit; } y = pfo->lpX11Trans->RAW_ASCENT + pfo->lpX11Trans->RAW_DESCENT; TRACE("x = %f y = %f\n", x, y); size->cx = x * pfo->lpX11Trans->pixelsize / 1000.0; size->cy = y * pfo->lpX11Trans->pixelsize / 1000.0; + if (lpnFit) + *lpnFit = nfit; } size->cx *= pfo->rescale; size->cy *= pfo->rescale; diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index 687aabd6a21..072295deefe 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -27,7 +27,7 @@ @ cdecl GetPixel(ptr long long) X11DRV_GetPixel @ cdecl GetPixelFormat(ptr) X11DRV_GetPixelFormat @ cdecl GetSystemPaletteEntries(ptr long long ptr) X11DRV_GetSystemPaletteEntries -@ cdecl GetTextExtentPoint(ptr ptr long ptr) X11DRV_GetTextExtentPoint +@ cdecl GetTextExtentExPoint(ptr ptr long long ptr ptr ptr) X11DRV_GetTextExtentExPoint @ cdecl GetTextMetrics(ptr ptr) X11DRV_GetTextMetrics @ cdecl LineTo(ptr long long) X11DRV_LineTo @ cdecl PaintRgn(ptr long) X11DRV_PaintRgn diff --git a/dlls/winex11.drv/x11font.h b/dlls/winex11.drv/x11font.h index c3c77e41d8c..27eb82e6779 100644 --- a/dlls/winex11.drv/x11font.h +++ b/dlls/winex11.drv/x11font.h @@ -240,7 +240,8 @@ typedef struct tagX11DRV_CP int x, int y, XTextItem16* pitems, int count ); void (*pTextExtents)( fontObject* pfo, XChar2b* pstr, int count, int* pdir, int* pascent, int* pdescent, - int* pwidth ); + int* pwidth, int max_extent, int *pfit, + int* partial_extents ); void (*pGetTextMetricsW)( fontObject* pfo, LPTEXTMETRICW pTM ); } X11DRV_CP;