From f2c4bc3f8be0d0defc21c1396f2688c22ac859ec Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 21 Dec 2003 18:38:37 +0000 Subject: [PATCH] Bug fixes. svn path=/trunk/; revision=7161 --- reactos/include/win32k/coord.h | 9 + reactos/lib/user32/controls/edit.c | 2 +- reactos/lib/user32/windows/nonclient.c | 2 + reactos/subsys/win32k/objects/cliprgn.c | 44 +++- reactos/subsys/win32k/objects/coord.c | 61 +++-- reactos/subsys/win32k/objects/text.c | 281 +++++++++++++++++++++++- 6 files changed, 350 insertions(+), 49 deletions(-) diff --git a/reactos/include/win32k/coord.h b/reactos/include/win32k/coord.h index 649bfb3db2f..7bbf868c5db 100644 --- a/reactos/include/win32k/coord.h +++ b/reactos/include/win32k/coord.h @@ -10,6 +10,15 @@ NtGdiCombineTransform ( CONST LPXFORM xform1, CONST LPXFORM xform2 ); + +VOID +FASTCALL +IntDPtoLP ( PDC dc, LPPOINT Points, INT Count ); + +VOID +FASTCALL +CoordDPtoLP ( PDC Dc, LPPOINT Point ); + BOOL STDCALL NtGdiDPtoLP ( diff --git a/reactos/lib/user32/controls/edit.c b/reactos/lib/user32/controls/edit.c index 1673af2dd61..d7ef6df4173 100644 --- a/reactos/lib/user32/controls/edit.c +++ b/reactos/lib/user32/controls/edit.c @@ -293,7 +293,7 @@ const struct builtin_class_descr EDIT_builtin_class = { #ifdef __REACTOS__ L"Edit", /* name */ - /*TODO: Fix ExtTextOut so that we can have the CS_PARENTDC style*/ + /* FIXME: Add CS_PARENTDC when the handling of WM_ERASEBKGND will be fixed! */ CS_GLOBALCLASS | CS_DBLCLKS, /* style */ (WNDPROC)EditWndProcW, /* procW */ (WNDPROC)EditWndProcA, /* procA */ diff --git a/reactos/lib/user32/windows/nonclient.c b/reactos/lib/user32/windows/nonclient.c index 61b5423babe..74d8e2c2371 100644 --- a/reactos/lib/user32/windows/nonclient.c +++ b/reactos/lib/user32/windows/nonclient.c @@ -1095,6 +1095,8 @@ DrawCaption(HWND hWnd, HDC hDC, LPCRECT lprc, UINT uFlags) r.top ++; r.left += 2; + r.bottom = r.top + Height; + if ((uFlags & DC_TEXT) && (GetWindowTextW( hWnd, buffer, sizeof(buffer)/sizeof(buffer[0]) ))) { if (!(uFlags & DC_SMALLCAP) && ((uFlags & DC_ICON) || (uFlags & DC_INBUTTON))) diff --git a/reactos/subsys/win32k/objects/cliprgn.c b/reactos/subsys/win32k/objects/cliprgn.c index 1750bb21660..7be727cc1da 100644 --- a/reactos/subsys/win32k/objects/cliprgn.c +++ b/reactos/subsys/win32k/objects/cliprgn.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: cliprgn.c,v 1.28 2003/12/15 20:47:57 navaraf Exp $ */ +/* $Id: cliprgn.c,v 1.29 2003/12/21 18:38:37 navaraf Exp $ */ #undef WIN32_LEAN_AND_MEAN #include @@ -163,14 +163,13 @@ IntGdiGetClipBox(HDC hDC, LPRECT rc) { int retval; - DC *dc; + PDC dc; if (!(dc = DC_LockDc(hDC))) return ERROR; retval = UnsafeIntGetRgnBox(dc->w.hGCClipRgn, rc); - + IntDPtoLP(dc, (LPPOINT)rc, 2); DC_UnlockDc( hDC ); - NtGdiDPtoLP(hDC, (LPPOINT)rc, 2); return(retval); } @@ -206,7 +205,42 @@ int STDCALL NtGdiIntersectClipRect(HDC hDC, int RightRect, int BottomRect) { - UNIMPLEMENTED; + INT Result; + RECT Rect; + HRGN NewRgn; + PDC dc = DC_LockDc(hDC); + + if (!dc) + return ERROR; + + Rect.left = LeftRect; + Rect.top = TopRect; + Rect.right = RightRect; + Rect.bottom = BottomRect; + + IntLPtoDP(dc, (LPPOINT)&Rect, 2); + + NewRgn = UnsafeIntCreateRectRgnIndirect(&Rect); + if (!NewRgn) + { + Result = ERROR; + } + else if (!dc->w.hClipRgn) + { + dc->w.hClipRgn = NewRgn; + Result = SIMPLEREGION; + } + else + { + Result = NtGdiCombineRgn(dc->w.hClipRgn, dc->w.hClipRgn, NewRgn, RGN_AND); + NtGdiDeleteObject(NewRgn); + } + if (Result != ERROR) + CLIPPING_UpdateGCRegion(dc); + + DC_UnlockDc(hDC); + + return Result; } int STDCALL NtGdiOffsetClipRgn(HDC hDC, diff --git a/reactos/subsys/win32k/objects/coord.c b/reactos/subsys/win32k/objects/coord.c index e69c62d98d3..4bf071a9145 100644 --- a/reactos/subsys/win32k/objects/coord.c +++ b/reactos/subsys/win32k/objects/coord.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: coord.c,v 1.19 2003/09/09 09:39:21 gvg Exp $ +/* $Id: coord.c,v 1.20 2003/12/21 18:38:37 navaraf Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -69,7 +69,7 @@ BOOL STDCALL NtGdiCombineTransform(LPXFORM UnsafeXFormResult, return TRUE; } -VOID STATIC FASTCALL +VOID FASTCALL CoordDPtoLP(PDC Dc, LPPOINT Point) { FLOAT x, y; @@ -81,6 +81,18 @@ FLOAT x, y; y * Dc->w.xformVport2World.eM22 + Dc->w.xformVport2World.eDy; } +VOID +FASTCALL +IntDPtoLP ( PDC dc, LPPOINT Points, INT Count ) +{ + INT i; + + ASSERT ( Points ); + + for ( i = 0; i < Count; i++ ) + CoordDPtoLP ( dc, &Points[i] ); +} + /*! * Converts points from device coordinates into logical coordinates. Conversion depends on the mapping mode, * world transfrom, viewport origin settings for the given device context. @@ -94,38 +106,25 @@ NtGdiDPtoLP(HDC hDC, LPPOINT UnsafePoints, int Count) { - PDC dc; - INT i; - LPPOINT Points = (LPPOINT) ExAllocatePool( PagedPool, Count*sizeof(POINT)); - BOOL ret = FALSE; // default to failure + PDC dc; + LPPOINT Points = (LPPOINT)ExAllocatePool(PagedPool, Count * sizeof(POINT)); + BOOL ret = FALSE; // default to failure - ASSERT(Points); - if ( !Points ) - return ret; + if (!Points) + return FALSE; - MmCopyFromCaller( Points, UnsafePoints, Count*sizeof(POINT) ); + dc = DC_LockDc(hDC); + if (dc) + { + ret = TRUE; + MmCopyFromCaller(Points, UnsafePoints, Count * sizeof(POINT)); + IntDPtoLP(dc, Points, Count); + MmCopyToCaller(UnsafePoints, Points, Count * sizeof(POINT)); + DC_UnlockDc(hDC); + } + ExFreePool(Points); - dc = DC_LockDc (hDC); - if ( dc ) - { - ret = TRUE; - if ( dc->w.vport2WorldValid ) - { - for (i = 0; i < Count; i++) - { - CoordDPtoLP ( dc, &Points[i] ); - } - } - - DC_UnlockDc( hDC ); - - MmCopyToCaller( UnsafePoints, Points, Count*sizeof(POINT) ); - - } - - ExFreePool ( Points ); - - return(TRUE); + return ret; } int diff --git a/reactos/subsys/win32k/objects/text.c b/reactos/subsys/win32k/objects/text.c index a5ff2c1d2ce..57b10f06207 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.61 2003/12/13 10:34:13 weiden Exp $ */ +/* $Id: text.c,v 1.62 2003/12/21 18:38:37 navaraf Exp $ */ #undef WIN32_LEAN_AND_MEAN @@ -467,19 +467,276 @@ NtGdiEnumFonts(HDC hDC, UNIMPLEMENTED; } -BOOL -STDCALL -NtGdiExtTextOut(HDC hdc, - int X, - int Y, - UINT fuOptions, - CONST RECT *lprc, - LPCWSTR lpString, - UINT cbCount, - CONST INT *lpDx) +BOOL STDCALL +NtGdiExtTextOut(HDC hDC, int XStart, int YStart, UINT fuOptions, + CONST RECT *lprc, LPCWSTR String, UINT Count, CONST INT *lpDx) { /* FIXME: Implement */ - return NtGdiTextOut(hdc, X, Y, lpString, cbCount); +// return NtGdiTextOut(hdc, X, Y, lpString, cbCount); + // Fixme: Call EngTextOut, which does the real work (calling DrvTextOut where appropriate) + + DC *dc; + SURFOBJ *SurfObj; + int error, glyph_index, n, i; + FT_Face face; + FT_GlyphSlot glyph; + ULONG TextLeft, TextTop, pitch, previous, BackgroundLeft; + FT_Bool use_kerning; + RECTL DestRect, MaskRect; + POINTL SourcePoint, BrushOrigin; + HBRUSH hBrushFg = NULL; + PBRUSHOBJ BrushFg = NULL; + HBRUSH hBrushBg = NULL; + PBRUSHOBJ BrushBg = NULL; + HBITMAP HSourceGlyph; + PSURFOBJ SourceGlyphSurf; + SIZEL bitSize; + FT_CharMap found = 0, charmap; + INT yoff; + PFONTOBJ FontObj; + PFONTGDI FontGDI; + PTEXTOBJ TextObj; + PPALGDI PalDestGDI; + PXLATEOBJ XlateObj; + ULONG Mode; + + dc = DC_LockDc(hDC); + if( !dc ) + return FALSE; + SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface); + + XStart += dc->w.DCOrgX; + YStart += dc->w.DCOrgY; + TextLeft = XStart; + TextTop = YStart; + BackgroundLeft = XStart; + + TextObj = TEXTOBJ_LockText(dc->w.hFont); + + if (! NT_SUCCESS(GetFontObjectsFromTextObj(TextObj, NULL, &FontObj, &FontGDI))) + { + goto fail; + } + face = FontGDI->face; + + if (face->charmap == NULL) + { + DPRINT("WARNING: No charmap selected!\n"); + DPRINT("This font face has %d charmaps\n", face->num_charmaps); + + for (n = 0; n < face->num_charmaps; n++) + { + charmap = face->charmaps[n]; + DPRINT("found charmap encoding: %u\n", charmap->encoding); + if (charmap->encoding != 0) + { + found = charmap; + break; + } + } + if (!found) DPRINT1("WARNING: Could not find desired charmap!\n"); + error = FT_Set_Charmap(face, found); + if (error) DPRINT1("WARNING: Could not set the charmap!\n"); + } + + error = FT_Set_Pixel_Sizes(face, + /* FIXME should set character height if neg */ + (TextObj->logfont.lfHeight < 0 ? + - TextObj->logfont.lfHeight : + TextObj->logfont.lfHeight), + TextObj->logfont.lfWidth); + if(error) { + DPRINT1("Error in setting pixel sizes: %u\n", error); + goto fail; + } + + // Create the brushes + PalDestGDI = PALETTE_LockPalette(dc->w.hPalette); + Mode = PalDestGDI->Mode; + PALETTE_UnlockPalette(dc->w.hPalette); + XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL); + hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor)); + BrushFg = BRUSHOBJ_LockBrush(hBrushFg); + if (OPAQUE == dc->w.backgroundMode) + { + hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor)); + if(hBrushBg) + { + BrushBg = BRUSHOBJ_LockBrush(hBrushBg); + } + else + { + EngDeleteXlate(XlateObj); + goto fail; + } + } + EngDeleteXlate(XlateObj); + + SourcePoint.x = 0; + SourcePoint.y = 0; + MaskRect.left = 0; + MaskRect.top = 0; + BrushOrigin.x = 0; + BrushOrigin.y = 0; + + // Determine the yoff from the dc's w.textAlign + if (dc->w.textAlign & TA_BASELINE) { + 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); + previous = 0; + + for(i=0; iglyph; + + // retrieve kerning distance and move pen position + if (use_kerning && previous && glyph_index) + { + FT_Vector delta; + FT_Get_Kerning(face, previous, glyph_index, 0, &delta); + TextLeft += delta.x >> 6; + } + + if (glyph->format == ft_glyph_format_outline) + { + error = FT_Render_Glyph(glyph, ft_render_mode_mono); + if(error) { + DPRINT1("WARNING: Failed to render glyph!\n"); + goto fail; + } + pitch = glyph->bitmap.pitch; + } else { + pitch = glyph->bitmap.width; + } + + if (OPAQUE == dc->w.backgroundMode) + { + 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; + if (fuOptions & ETO_CLIPPED) + { + if (DestRect.left > lprc->right || DestRect.right < lprc->left || + DestRect.top > lprc->bottom || DestRect.bottom < lprc->top) + { + DestRect.right = DestRect.left; + } + else + { + DestRect.left = max(DestRect.left, lprc->left); + DestRect.right = min(DestRect.right, lprc->right); + DestRect.top = max(DestRect.top, lprc->top); + DestRect.bottom = min(DestRect.bottom, lprc->bottom); + } + } + 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; + + if (fuOptions & ETO_CLIPPED) + { + if (DestRect.left > lprc->right || DestRect.right < lprc->left || + DestRect.top > lprc->bottom || DestRect.bottom < lprc->top) + { + break; + } + else + { + DestRect.left = max(DestRect.left, lprc->left); + DestRect.right = min(DestRect.right, lprc->right); + DestRect.top = max(DestRect.top, lprc->top); + DestRect.bottom = min(DestRect.bottom, lprc->bottom); + } + } + + bitSize.cx = glyph->bitmap.width; + 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); + SourceGlyphSurf = (PSURFOBJ)AccessUserObject((ULONG) HSourceGlyph); + + // Use the font data as a mask to paint onto the DCs surface using a brush + IntEngBitBlt ( + SurfObj, + NULL, + SourceGlyphSurf, + dc->CombinedClip, + NULL, + &DestRect, + &SourcePoint, + (PPOINTL)&MaskRect, + BrushFg, + &BrushOrigin, + 0xAACC ); + + EngDeleteSurface(HSourceGlyph); + + TextLeft += (glyph->advance.x + 32) / 64; + previous = glyph_index; + + String++; + } + TEXTOBJ_UnlockText(dc->w.hFont); + if (NULL != hBrushBg) + { + BRUSHOBJ_UnlockBrush(hBrushBg); + NtGdiDeleteObject(hBrushBg); + } + BRUSHOBJ_UnlockBrush(hBrushFg); + NtGdiDeleteObject(hBrushFg); + DC_UnlockDc(hDC); + return TRUE; + +fail: + TEXTOBJ_UnlockText( dc->w.hFont ); + if (NULL != hBrushBg) + { + BRUSHOBJ_UnlockBrush(hBrushBg); + NtGdiDeleteObject(hBrushBg); + } + if (NULL != hBrushFg) + { + BRUSHOBJ_UnlockBrush(hBrushFg); + NtGdiDeleteObject(hBrushFg); + } + DC_UnlockDc( hDC ); + return FALSE; } BOOL