- Unified indenting style in NtGdiExtTextOut and implemented support for right and centered text alignment.

- Don't render glyphs in TextIntGetTextExtentPoint.

svn path=/trunk/; revision=8297
This commit is contained in:
Filip Navara 2004-02-22 08:35:21 +00:00
parent e6ad1bc2c0
commit a7b989769f

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: text.c,v 1.76 2004/02/21 21:15:22 navaraf Exp $ */ /* $Id: text.c,v 1.77 2004/02/22 08:35:21 navaraf Exp $ */
#undef WIN32_LEAN_AND_MEAN #undef WIN32_LEAN_AND_MEAN
@ -560,8 +560,15 @@ NtGdiEnumFonts(HDC hDC,
} }
BOOL STDCALL BOOL STDCALL
NtGdiExtTextOut(HDC hDC, int XStart, int YStart, UINT fuOptions, NtGdiExtTextOut(
CONST RECT *lprc, LPCWSTR String, UINT Count, CONST INT *lpDx) HDC hDC,
INT XStart,
INT YStart,
UINT fuOptions,
CONST RECT *lprc,
LPCWSTR String,
UINT Count,
CONST INT *lpDx)
{ {
/* /*
* FIXME: * FIXME:
@ -604,9 +611,6 @@ NtGdiExtTextOut(HDC hDC, int XStart, int YStart, UINT fuOptions,
XStart += dc->w.DCOrgX; XStart += dc->w.DCOrgX;
YStart += dc->w.DCOrgY; YStart += dc->w.DCOrgY;
TextLeft = XStart;
TextTop = YStart;
BackgroundLeft = XStart;
TextObj = TEXTOBJ_LockText(dc->w.hFont); TextObj = TEXTOBJ_LockText(dc->w.hFont);
@ -719,143 +723,221 @@ NtGdiExtTextOut(HDC hDC, int XStart, int YStart, UINT fuOptions,
} }
} }
// Determine the yoff from the dc's w.textAlign /*
if (dc->w.textAlign & TA_BASELINE) { * Process the vertical alignment and determine the yoff.
yoff = 0; */
}
else
if (dc->w.textAlign & TA_BOTTOM) {
yoff = -face->size->metrics.descender / 64;
}
else { // TA_TOP
yoff = face->size->metrics.ascender / 64;
}
use_kerning = FT_HAS_KERNING(face); if (dc->w.textAlign & TA_BASELINE)
previous = 0; yoff = 0;
else if (dc->w.textAlign & TA_BOTTOM)
yoff = -face->size->metrics.descender / 64;
else /* TA_TOP */
yoff = face->size->metrics.ascender / 64;
for(i=0; i<Count; i++) use_kerning = FT_HAS_KERNING(face);
{ previous = 0;
ExAcquireFastMutex(&FreeTypeLock);
glyph_index = FT_Get_Char_Index(face, *String);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
ExReleaseFastMutex(&FreeTypeLock);
if(error) {
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
goto fail;
}
glyph = face->glyph;
// retrieve kerning distance and move pen position /*
if (use_kerning && previous && glyph_index) * Process the horizontal alignment and modify XStart accordingly.
{ */
FT_Vector delta;
ExAcquireFastMutex(&FreeTypeLock);
FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
ExReleaseFastMutex(&FreeTypeLock);
TextLeft += delta.x >> 6;
}
if (glyph->format == ft_glyph_format_outline) if (dc->w.textAlign & (TA_RIGHT | TA_CENTER))
{ {
ExAcquireFastMutex(&FreeTypeLock); UINT TextWidth;
error = FT_Render_Glyph(glyph, RenderMode); LPCWSTR TempText = String;
ExReleaseFastMutex(&FreeTypeLock);
if(error) {
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
DPRINT1("WARNING: Failed to render glyph!\n");
goto fail;
}
pitch = glyph->bitmap.pitch;
} else {
pitch = glyph->bitmap.width;
}
if (fuOptions & ETO_OPAQUE) /*
* Calculate width of the text.
*/
for (i = 0; i < Count; i++)
{ {
DestRect.left = BackgroundLeft; ExAcquireFastMutex(&FreeTypeLock);
DestRect.right = TextLeft + (glyph->advance.x + 32) / 64; glyph_index = FT_Get_Char_Index(face, *TempText);
DestRect.top = TextTop + yoff - (face->size->metrics.ascender + 32) / 64; error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
DestRect.bottom = TextTop + yoff + (- face->size->metrics.descender + 32) / 64; ExReleaseFastMutex(&FreeTypeLock);
IntEngBitBlt(SurfObj,
NULL, if (error)
NULL, {
dc->CombinedClip, DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
NULL, }
&DestRect,
&SourcePoint, glyph = face->glyph;
&SourcePoint,
BrushBg, /* retrieve kerning distance */
&BrushOrigin, if (use_kerning && previous && glyph_index)
PATCOPY); {
BackgroundLeft = DestRect.right; FT_Vector delta;
ExAcquireFastMutex(&FreeTypeLock);
FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
ExReleaseFastMutex(&FreeTypeLock);
TextWidth += delta.x >> 6;
}
TextWidth += glyph->advance.x >> 6;
previous = glyph_index;
TempText++;
} }
DestRect.left = TextLeft; previous = 0;
DestRect.right = TextLeft + glyph->bitmap.width;
DestRect.top = TextTop + yoff - glyph->bitmap_top; if (dc->w.textAlign & TA_RIGHT)
DestRect.bottom = DestRect.top + glyph->bitmap.rows; {
XStart -= TextWidth;
}
else
{
XStart -= TextWidth >> 1;
}
}
TextLeft = XStart;
TextTop = YStart;
BackgroundLeft = XStart;
/*
* The main rendering loop.
*/
for (i = 0; i < Count; i++)
{
ExAcquireFastMutex(&FreeTypeLock);
glyph_index = FT_Get_Char_Index(face, *String);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
ExReleaseFastMutex(&FreeTypeLock);
if (error)
{
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
goto fail;
}
glyph = face->glyph;
/* retrieve kerning distance and move pen position */
if (use_kerning && previous && glyph_index)
{
FT_Vector delta;
ExAcquireFastMutex(&FreeTypeLock);
FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
ExReleaseFastMutex(&FreeTypeLock);
TextLeft += delta.x >> 6;
}
if (glyph->format == ft_glyph_format_outline)
{
ExAcquireFastMutex(&FreeTypeLock);
error = FT_Render_Glyph(glyph, RenderMode);
ExReleaseFastMutex(&FreeTypeLock);
if (error)
{
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
DPRINT1("WARNING: Failed to render glyph!\n");
goto fail;
}
pitch = glyph->bitmap.pitch;
} else {
pitch = glyph->bitmap.width;
}
if (fuOptions & ETO_OPAQUE)
{
DestRect.left = BackgroundLeft;
DestRect.right = TextLeft + (glyph->advance.x + 32) / 64;
DestRect.top = TextTop + yoff - (face->size->metrics.ascender + 32) / 64;
DestRect.bottom = TextTop + yoff + (- face->size->metrics.descender + 32) / 64;
IntEngBitBlt(
SurfObj,
NULL,
NULL,
dc->CombinedClip,
NULL,
&DestRect,
&SourcePoint,
&SourcePoint,
BrushBg,
&BrushOrigin,
PATCOPY);
BackgroundLeft = DestRect.right;
}
DestRect.left = TextLeft;
DestRect.right = TextLeft + glyph->bitmap.width;
DestRect.top = TextTop + yoff - glyph->bitmap_top;
DestRect.bottom = DestRect.top + glyph->bitmap.rows;
bitSize.cx = glyph->bitmap.width; bitSize.cx = glyph->bitmap.width;
bitSize.cy = glyph->bitmap.rows; bitSize.cy = glyph->bitmap.rows;
MaskRect.right = glyph->bitmap.width; MaskRect.right = glyph->bitmap.width;
MaskRect.bottom = glyph->bitmap.rows; MaskRect.bottom = glyph->bitmap.rows;
// We should create the bitmap out of the loop at the biggest possible glyph size /*
// Then use memset with 0 to clear it and sourcerect to limit the work of the transbitblt * We should create the bitmap out of the loop at the biggest possible
HSourceGlyph = EngCreateBitmap(bitSize, pitch, (glyph->bitmap.pixel_mode == ft_pixel_mode_grays) ? BMF_8BPP : BMF_1BPP, 0, glyph->bitmap.buffer); * glyph size. Then use memset with 0 to clear it and sourcerect to
SourceGlyphSurf = (PSURFOBJ)AccessUserObject((ULONG) HSourceGlyph); * limit the work of the transbitblt.
*/
HSourceGlyph = EngCreateBitmap(bitSize, pitch, (glyph->bitmap.pixel_mode == ft_pixel_mode_grays) ? BMF_8BPP : BMF_1BPP, 0, glyph->bitmap.buffer);
SourceGlyphSurf = (PSURFOBJ)AccessUserObject((ULONG) HSourceGlyph);
// Use the font data as a mask to paint onto the DCs surface using a brush /*
IntEngMaskBlt ( * Use the font data as a mask to paint onto the DCs surface using a
SurfObj, * brush.
SourceGlyphSurf, */
dc->CombinedClip,
XlateObj,
XlateObj2,
&DestRect,
&SourcePoint,
(PPOINTL)&MaskRect,
BrushFg,
&BrushOrigin);
EngDeleteSurface(HSourceGlyph); IntEngMaskBlt(
SurfObj,
SourceGlyphSurf,
dc->CombinedClip,
XlateObj,
XlateObj2,
&DestRect,
&SourcePoint,
(PPOINTL)&MaskRect,
BrushFg,
&BrushOrigin);
TextLeft += (glyph->advance.x + 32) / 64; EngDeleteSurface(HSourceGlyph);
previous = glyph_index;
String++; TextLeft += (glyph->advance.x + 32) / 64;
} previous = glyph_index;
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2); String++;
TEXTOBJ_UnlockText(dc->w.hFont); }
if (NULL != hBrushBg)
{ EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
TEXTOBJ_UnlockText(dc->w.hFont);
if (hBrushBg != NULL)
{
BRUSHOBJ_UnlockBrush(hBrushBg); BRUSHOBJ_UnlockBrush(hBrushBg);
NtGdiDeleteObject(hBrushBg); NtGdiDeleteObject(hBrushBg);
} }
BRUSHOBJ_UnlockBrush(hBrushFg); BRUSHOBJ_UnlockBrush(hBrushFg);
NtGdiDeleteObject(hBrushFg); NtGdiDeleteObject(hBrushFg);
DC_UnlockDc(hDC); DC_UnlockDc(hDC);
return TRUE;
return TRUE;
fail: fail:
TEXTOBJ_UnlockText( dc->w.hFont ); TEXTOBJ_UnlockText(dc->w.hFont);
if (NULL != hBrushBg) if (hBrushBg != NULL)
{ {
BRUSHOBJ_UnlockBrush(hBrushBg); BRUSHOBJ_UnlockBrush(hBrushBg);
NtGdiDeleteObject(hBrushBg); NtGdiDeleteObject(hBrushBg);
} }
if (NULL != hBrushFg) if (hBrushFg != NULL)
{ {
BRUSHOBJ_UnlockBrush(hBrushFg); BRUSHOBJ_UnlockBrush(hBrushFg);
NtGdiDeleteObject(hBrushFg); NtGdiDeleteObject(hBrushFg);
} }
DC_UnlockDc( hDC ); DC_UnlockDc(hDC);
return FALSE;
return FALSE;
} }
BOOL BOOL
@ -1167,16 +1249,6 @@ TextIntGetTextExtentPoint(HDC hDC,
} }
TotalWidth += glyph->advance.x >> 6; TotalWidth += glyph->advance.x >> 6;
if (glyph->format == ft_glyph_format_outline)
{
ExAcquireFastMutex(&FreeTypeLock);
error = FT_Render_Glyph(glyph, FT_RENDER_MODE_MONO);
ExReleaseFastMutex(&FreeTypeLock);
if (error)
{
DPRINT1("WARNING: Failed to render glyph!\n");
}
}
if (TotalWidth <= MaxExtent && NULL != Fit) if (TotalWidth <= MaxExtent && NULL != Fit)
{ {