implemented font smoothing

svn path=/trunk/; revision=7222
This commit is contained in:
Thomas Bluemel 2003-12-25 00:28:09 +00:00
parent 4a0ecf56be
commit 6e2e1c2fa5
4 changed files with 370 additions and 21 deletions

View file

@ -355,7 +355,7 @@ typedef enum _SID_NAME_USE {
#define GetBValue(rgb) ((BYTE) ((rgb) >> 16))
#define GetGValue(rgb) ((BYTE) (((WORD) (rgb)) >> 8))
#define GetRValue(rgb) ((BYTE) (rgb))
#define RGB(r, g ,b) ((DWORD) (((BYTE) (r) | ((WORD) (g) << 8)) | (((DWORD) (BYTE) (b)) << 16)))
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
#define HANDLE_WM_NOTIFY(hwnd, wParam, lParam, fn) (fn)((hwnd), (int)(wParam), (NMHDR FAR*)(lParam))

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: bitblt.c,v 1.32 2003/12/09 14:28:48 fireball Exp $
/* $Id: bitblt.c,v 1.33 2003/12/25 00:28:09 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -109,7 +109,7 @@ BltMask(SURFOBJ* Dest,
LONG i, j, dx, dy, c8;
BYTE *tMask, *lMask;
static BYTE maskbit[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
dx = DestRect->right - DestRect->left;
dy = DestRect->bottom - DestRect->top;
@ -797,4 +797,320 @@ IntEngStretchBlt(SURFOBJ *DestObj,
return ret;
}
/**** REACTOS FONT RENDERING CODE *********************************************/
/* renders the alpha mask bitmap */
static BOOLEAN STDCALL
AlphaBltMask(SURFOBJ* Dest,
SURFGDI* DestGDI,
SURFOBJ* Source,
SURFGDI* SourceGDI,
SURFOBJ* Mask,
XLATEOBJ* ColorTranslation,
XLATEOBJ* SrcColorTranslation,
RECTL* DestRect,
POINTL* SourcePoint,
POINTL* MaskPoint,
BRUSHOBJ* Brush,
POINTL* BrushPoint)
{
LONG i, j, dx, dy;
int r[2], g[2], b[2];
ULONG Background, BrushColor;
BYTE *tMask, *lMask;
dx = DestRect->right - DestRect->left;
dy = DestRect->bottom - DestRect->top;
if (Mask != NULL)
{
BrushColor = XLATEOBJ_iXlate(ColorTranslation, Brush->iSolidColor);
r[0] = (int)GetRValue(BrushColor);
g[0] = (int)GetGValue(BrushColor);
b[0] = (int)GetBValue(BrushColor);
tMask = Mask->pvBits + SourcePoint->y * Mask->lDelta;
for (j = 0; j < dy; j++)
{
lMask = tMask;
for (i = 0; i < dx; i++)
{
if (*lMask > 0)
{
if(*lMask == 0xff)
{
DestGDI->DIB_PutPixel(Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
}
else
{
Background = DIB_GetSource(Dest, DestGDI, DestRect->left + i, DestRect->top + j, SrcColorTranslation);
r[1] = (((int)GetRValue(Background) - r[0]) * (255 - (int)*lMask)) /255 + r[0];
g[1] = (((int)GetGValue(Background) - g[0]) * (255 - (int)*lMask)) /255 + g[0];
b[1] = (((int)GetBValue(Background) - b[0]) * (255 - (int)*lMask)) /255 + b[0];
Background = XLATEOBJ_iXlate(ColorTranslation, RGB((UCHAR)r[1], (UCHAR)g[1], (UCHAR)b[1]));
DestGDI->DIB_PutPixel(Dest, DestRect->left + i, DestRect->top + j, Background);
}
}
lMask++;
}
tMask += Mask->lDelta;
}
return TRUE;
}
else
{
return FALSE;
}
}
BOOL STDCALL
EngMaskBitBlt(SURFOBJ *DestObj,
SURFOBJ *Mask,
CLIPOBJ *ClipRegion,
XLATEOBJ *DestColorTranslation,
XLATEOBJ *SourceColorTranslation,
RECTL *DestRect,
POINTL *SourcePoint,
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin)
{
BYTE clippingType;
RECTL CombinedRect;
RECT_ENUM RectEnum;
BOOL EnumMore;
SURFGDI* OutputGDI;
SURFGDI* InputGDI;
POINTL InputPoint;
RECTL InputRect;
RECTL OutputRect;
POINTL Translate;
INTENG_ENTER_LEAVE EnterLeaveSource;
INTENG_ENTER_LEAVE EnterLeaveDest;
SURFOBJ* InputObj;
SURFOBJ* OutputObj;
BOOLEAN Ret;
RECTL ClipRect;
unsigned i;
POINTL Pt;
ULONG Direction;
if (NULL != SourcePoint)
{
InputRect.left = SourcePoint->x;
InputRect.right = SourcePoint->x + (DestRect->right - DestRect->left);
InputRect.top = SourcePoint->y;
InputRect.bottom = SourcePoint->y + (DestRect->bottom - DestRect->top);
}
else
{
InputRect.left = 0;
InputRect.right = DestRect->right - DestRect->left;
InputRect.top = 0;
InputRect.bottom = DestRect->bottom - DestRect->top;
}
if (! IntEngEnter(&EnterLeaveSource, NULL, &InputRect, TRUE, &Translate, &InputObj))
{
return FALSE;
}
if (NULL != SourcePoint)
{
InputPoint.x = SourcePoint->x + Translate.x;
InputPoint.y = SourcePoint->y + Translate.y;
}
else
{
InputPoint.x = 0;
InputPoint.y = 0;
}
if (NULL != InputObj)
{
InputGDI = (SURFGDI*) AccessInternalObjectFromUserObject(InputObj);
}
else
{
InputGDI = NULL;
}
OutputRect = *DestRect;
if (NULL != ClipRegion)
{
if (OutputRect.left < ClipRegion->rclBounds.left)
{
InputRect.left += ClipRegion->rclBounds.left - OutputRect.left;
InputPoint.x += ClipRegion->rclBounds.left - OutputRect.left;
OutputRect.left = ClipRegion->rclBounds.left;
}
if (ClipRegion->rclBounds.right < OutputRect.right)
{
InputRect.right -= OutputRect.right - ClipRegion->rclBounds.right;
OutputRect.right = ClipRegion->rclBounds.right;
}
if (OutputRect.top < ClipRegion->rclBounds.top)
{
InputRect.top += ClipRegion->rclBounds.top - OutputRect.top;
InputPoint.y += ClipRegion->rclBounds.top - OutputRect.top;
OutputRect.top = ClipRegion->rclBounds.top;
}
if (ClipRegion->rclBounds.bottom < OutputRect.bottom)
{
InputRect.bottom -= OutputRect.bottom - ClipRegion->rclBounds.bottom;
OutputRect.bottom = ClipRegion->rclBounds.bottom;
}
}
/* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
nothing to do */
if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top)
{
IntEngLeave(&EnterLeaveSource);
return TRUE;
}
if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj))
{
IntEngLeave(&EnterLeaveSource);
return FALSE;
}
OutputRect.left = DestRect->left + Translate.x;
OutputRect.right = DestRect->right + Translate.x;
OutputRect.top = DestRect->top + Translate.y;
OutputRect.bottom = DestRect->bottom + Translate.y;
if (NULL != OutputObj)
{
OutputGDI = (SURFGDI*)AccessInternalObjectFromUserObject(OutputObj);
}
// Determine clipping type
if (ClipRegion == (CLIPOBJ *) NULL)
{
clippingType = DC_TRIVIAL;
} else {
clippingType = ClipRegion->iDComplexity;
}
switch(clippingType)
{
case DC_TRIVIAL:
Ret = AlphaBltMask(OutputObj, OutputGDI, InputObj, InputGDI, Mask, DestColorTranslation, SourceColorTranslation,
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin);
break;
case DC_RECT:
// Clip the blt to the clip rectangle
ClipRect.left = ClipRegion->rclBounds.left + Translate.x;
ClipRect.right = ClipRegion->rclBounds.right + Translate.x;
ClipRect.top = ClipRegion->rclBounds.top + Translate.y;
ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y;
EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
Ret = AlphaBltMask(OutputObj, OutputGDI, InputObj, InputGDI, Mask, DestColorTranslation, SourceColorTranslation,
&CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin);
break;
case DC_COMPLEX:
Ret = TRUE;
if (OutputObj == InputObj)
{
if (OutputRect.top < InputPoint.y)
{
Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN;
}
else
{
Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP;
}
}
else
{
Direction = CD_ANY;
}
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, ENUM_RECT_LIMIT);
do
{
EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
for (i = 0; i < RectEnum.c; i++)
{
ClipRect.left = RectEnum.arcl[i].left + Translate.x;
ClipRect.right = RectEnum.arcl[i].right + Translate.x;
ClipRect.top = RectEnum.arcl[i].top + Translate.y;
ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
Ret = AlphaBltMask(OutputObj, OutputGDI, InputObj, InputGDI, Mask, DestColorTranslation, SourceColorTranslation,
&CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin) &&
Ret;
}
}
while(EnumMore);
break;
}
IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource);
return Ret;
}
BOOL STDCALL
IntEngMaskBlt(SURFOBJ *DestObj,
SURFOBJ *Mask,
CLIPOBJ *ClipRegion,
XLATEOBJ *DestColorTranslation,
XLATEOBJ *SourceColorTranslation,
RECTL *DestRect,
POINTL *SourcePoint,
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin)
{
BOOLEAN ret;
SURFGDI *DestGDI;
RECTL OutputRect;
POINTL InputPoint;
if (NULL != SourcePoint)
{
InputPoint = *SourcePoint;
}
/* Clip against the bounds of the clipping region so we won't try to write
* outside the surface */
if (NULL != ClipRegion)
{
if (! EngIntersectRect(&OutputRect, DestRect, &ClipRegion->rclBounds))
{
return TRUE;
}
InputPoint.x += OutputRect.left - DestRect->left;
InputPoint.y += OutputRect.top - DestRect->top;
}
else
{
OutputRect = *DestRect;
}
/* No success yet */
ret = FALSE;
DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj);
MouseSafetyOnDrawStart(DestObj, DestGDI, OutputRect.left, OutputRect.top,
OutputRect.right, OutputRect.bottom);
ret = EngMaskBitBlt(DestObj, Mask, ClipRegion, DestColorTranslation, SourceColorTranslation,
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin);
MouseSafetyOnDrawEnd(DestObj, DestGDI);
return ret;
}
/* EOF */

View file

@ -3,5 +3,16 @@
BOOL STDCALL EngIntersectRect (PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2);
VOID FASTCALL EngDeleteXlate (XLATEOBJ *XlateObj);
BOOL STDCALL
IntEngMaskBlt(SURFOBJ *DestObj,
SURFOBJ *Mask,
CLIPOBJ *ClipRegion,
XLATEOBJ *DestColorTranslation,
XLATEOBJ *SourceColorTranslation,
RECTL *DestRect,
POINTL *SourcePoint,
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin);
#endif /* _WIN32K_ENG_H */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: text.c,v 1.65 2003/12/23 21:29:37 navaraf Exp $ */
/* $Id: text.c,v 1.66 2003/12/25 00:28:09 weiden Exp $ */
#undef WIN32_LEAN_AND_MEAN
@ -56,6 +56,25 @@ static LIST_ENTRY FontListHead;
static FAST_MUTEX FontListLock;
static INT FontsLoaded = 0; /* number of all fonts loaded (including private fonts */
FT_Render_Mode FASTCALL
IntGetFontRenderMode(LOGFONTW *logfont)
{
switch(logfont->lfQuality)
{
//case ANTIALIASED_QUALITY:
case DEFAULT_QUALITY:
return FT_RENDER_MODE_NORMAL;
case DRAFT_QUALITY:
return FT_RENDER_MODE_LIGHT;
//case NONANTIALIASED_QUALITY:
case PROOF_QUALITY:
return FT_RENDER_MODE_MONO;
//case CLEARTYPE_QUALITY:
// return FT_RENDER_MODE_LCD;
}
return FT_RENDER_MODE_MONO;
}
int FASTCALL
IntGdiAddFontResource(PUNICODE_STRING Filename, DWORD fl)
{
@ -616,7 +635,7 @@ NtGdiExtTextOut(HDC hDC, int XStart, int YStart, UINT fuOptions,
if (glyph->format == ft_glyph_format_outline)
{
error = FT_Render_Glyph(glyph, ft_render_mode_mono);
error = FT_Render_Glyph(glyph, IntGetFontRenderMode(&TextObj->logfont));
if(error) {
DPRINT1("WARNING: Failed to render glyph!\n");
goto fail;
@ -689,7 +708,6 @@ NtGdiExtTextOut(HDC hDC, int XStart, int YStart, UINT fuOptions,
// 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
HSourceGlyph = EngCreateBitmap(bitSize, pitch, BMF_1BPP, 0, glyph->bitmap.buffer);
SourceGlyphSurf = (PSURFOBJ)AccessUserObject((ULONG) HSourceGlyph);
@ -1038,7 +1056,7 @@ TextIntGetTextExtentPoint(PTEXTOBJ TextObj,
TotalWidth += glyph->advance.x >> 6;
if (glyph->format == ft_glyph_format_outline)
{
error = FT_Render_Glyph(glyph, ft_render_mode_mono);
error = FT_Render_Glyph(glyph, FT_RENDER_MODE_MONO);
if (error)
{
DPRINT1("WARNING: Failed to render glyph!\n");
@ -1477,7 +1495,7 @@ NtGdiTextOut(HDC hDC,
PFONTGDI FontGDI;
PTEXTOBJ TextObj;
PPALGDI PalDestGDI;
PXLATEOBJ XlateObj;
PXLATEOBJ XlateObj, XlateObj2;
ULONG Mode;
dc = DC_LockDc(hDC);
@ -1550,8 +1568,8 @@ NtGdiTextOut(HDC hDC,
goto fail;
}
}
EngDeleteXlate(XlateObj);
XlateObj2 = (PXLATEOBJ)IntEngCreateXlate(PAL_RGB, Mode, NULL, dc->w.hPalette);
SourcePoint.x = 0;
SourcePoint.y = 0;
MaskRect.left = 0;
@ -1577,8 +1595,10 @@ NtGdiTextOut(HDC hDC,
for(i=0; i<Count; i++)
{
glyph_index = FT_Get_Char_Index(face, *String);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER);
if(error) {
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
goto fail;
}
@ -1594,8 +1614,10 @@ NtGdiTextOut(HDC hDC,
if (glyph->format == ft_glyph_format_outline)
{
error = FT_Render_Glyph(glyph, ft_render_mode_mono);
error = FT_Render_Glyph(glyph, IntGetFontRenderMode(&TextObj->logfont));
if(error) {
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
DPRINT1("WARNING: Failed to render glyph!\n");
goto fail;
}
@ -1633,26 +1655,24 @@ NtGdiTextOut(HDC hDC,
bitSize.cy = glyph->bitmap.rows;
MaskRect.right = glyph->bitmap.width;
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
HSourceGlyph = EngCreateBitmap(bitSize, pitch, BMF_1BPP, 0, glyph->bitmap.buffer);
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);
DPRINT1("glyph->bitmap.palette_mode == 0x%x (0x%x)\n", glyph->bitmap.palette_mode, glyph->bitmap.num_grays);
// Use the font data as a mask to paint onto the DCs surface using a brush
IntEngBitBlt (
IntEngMaskBlt (
SurfObj,
NULL,
SourceGlyphSurf,
dc->CombinedClip,
NULL,
XlateObj,
XlateObj2,
&DestRect,
&SourcePoint,
(PPOINTL)&MaskRect,
BrushFg,
&BrushOrigin,
0xAACC );
&BrushOrigin);
EngDeleteSurface(HSourceGlyph);
@ -1661,6 +1681,8 @@ NtGdiTextOut(HDC hDC,
String++;
}
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
TEXTOBJ_UnlockText(dc->w.hFont);
if (NULL != hBrushBg)
{