gdi32: Implement GetTextExtentPoint in terms of GetTextExtentExPoint

(not vice versa) for efficiency (required adding the Ex functionality
to drivers).
oldstable
Dan Hipschman 2006-07-11 17:58:35 -07:00 committed by Alexandre Julliard
parent fe3c9428c3
commit f904723813
13 changed files with 149 additions and 74 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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