From 6e2e1c2fa552e6bbbde78906e80744aeaa889ce6 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Thu, 25 Dec 2003 00:28:09 +0000 Subject: [PATCH] implemented font smoothing svn path=/trunk/; revision=7222 --- reactos/include/base.h | 2 +- reactos/subsys/win32k/eng/bitblt.c | 320 ++++++++++++++++++++++++++- reactos/subsys/win32k/include/eng.h | 11 + reactos/subsys/win32k/objects/text.c | 58 +++-- 4 files changed, 370 insertions(+), 21 deletions(-) diff --git a/reactos/include/base.h b/reactos/include/base.h index 97fffb2738c..a74d72639db 100644 --- a/reactos/include/base.h +++ b/reactos/include/base.h @@ -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)) diff --git a/reactos/subsys/win32k/eng/bitblt.c b/reactos/subsys/win32k/eng/bitblt.c index 3a73981a827..1bddb24bdf6 100644 --- a/reactos/subsys/win32k/eng/bitblt.c +++ b/reactos/subsys/win32k/eng/bitblt.c @@ -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 */ diff --git a/reactos/subsys/win32k/include/eng.h b/reactos/subsys/win32k/include/eng.h index 9a94dd2b2bb..cafed3f9bff 100644 --- a/reactos/subsys/win32k/include/eng.h +++ b/reactos/subsys/win32k/include/eng.h @@ -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 */ diff --git a/reactos/subsys/win32k/objects/text.c b/reactos/subsys/win32k/objects/text.c index 5edabeb4ef4..c50d39eeb25 100644 --- a/reactos/subsys/win32k/objects/text.c +++ b/reactos/subsys/win32k/objects/text.c @@ -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; iformat == 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) {