mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
- 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:
parent
e6ad1bc2c0
commit
a7b989769f
1 changed files with 203 additions and 131 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue