diff --git a/reactos/subsys/win32k/dib/dib4bpp.c b/reactos/subsys/win32k/dib/dib4bpp.c index e1667191bb0..f321516fa84 100644 --- a/reactos/subsys/win32k/dib/dib4bpp.c +++ b/reactos/subsys/win32k/dib/dib4bpp.c @@ -92,6 +92,31 @@ BOOLEAN DIB_To_4BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, } break; + case 8: + SourceBits_8BPP = SourceSurf->pvBits + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x; + + for (j=DestRect->top; jbottom; j++) + { + SourceLine_8BPP = SourceBits_8BPP; + DestLine = DestBits; + sx = SourcePoint->x; + f1 = sx & 1; + f2 = DestRect->left & 1; + + for (i=DestRect->left; iright; i++) + { + *DestLine = (*DestLine & notmask[i&1]) | + ((XLATEOBJ_iXlate(ColorTranslation, *SourceLine_8BPP)) << ((4 * (1-(sx & 1))))); + if(f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; } + SourceLine_8BPP++; + sx++; + } + + SourceBits_8BPP += SourceSurf->lDelta; + DestBits += DestSurf->lDelta; + } + break; + case 24: SourceBits_24BPP = SourceSurf->pvBits + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x * 3; diff --git a/reactos/subsys/win32k/eng/bitblt.c b/reactos/subsys/win32k/eng/bitblt.c index 3e80deffed2..399e706cd2e 100644 --- a/reactos/subsys/win32k/eng/bitblt.c +++ b/reactos/subsys/win32k/eng/bitblt.c @@ -49,13 +49,13 @@ BOOL EngBitBlt(SURFOBJ *Dest, SURFOBJ *Source, BOOL EnumMore; PSURFGDI DestGDI, SourceGDI; HSURF hTemp; - PSURFOBJ TempSurf; + PSURFOBJ TempSurf = NULL; BOOLEAN canCopyBits; POINTL TempPoint; RECTL TempRect; SIZEL TempSize; - SourceGDI = AccessInternalObjectFromUserObject(Source); + if(Source != NULL) SourceGDI = AccessInternalObjectFromUserObject(Source); // If we don't have to do anything special, we can punt to DrvCopyBits // if it exists @@ -75,23 +75,26 @@ BOOL EngBitBlt(SURFOBJ *Dest, SURFOBJ *Source, if (DestGDI->BitBlt!=NULL) { - // The destination is device managed, therefore get the source into a format compatible surface - TempPoint.x = 0; - TempPoint.y = 0; - TempRect.top = 0; - TempRect.left = 0; - TempRect.bottom = DestRect->bottom - DestRect->top; - TempRect.right = DestRect->right - DestRect->left; - TempSize.cx = TempRect.right; - TempSize.cy = TempRect.bottom; + if (Source!=NULL) + { + // Get the source into a format compatible surface + TempPoint.x = 0; + TempPoint.y = 0; + TempRect.top = 0; + TempRect.left = 0; + TempRect.bottom = DestRect->bottom - DestRect->top; + TempRect.right = DestRect->right - DestRect->left; + TempSize.cx = TempRect.right; + TempSize.cy = TempRect.bottom; - hTemp = EngCreateBitmap(TempSize, - DIB_GetDIBWidthBytes(DestRect->right - DestRect->left, BitsPerFormat(Dest->iBitmapFormat)), - Dest->iBitmapFormat, 0, NULL); - TempSurf = AccessUserObject(hTemp); + hTemp = EngCreateBitmap(TempSize, + DIB_GetDIBWidthBytes(DestRect->right - DestRect->left, BitsPerFormat(Dest->iBitmapFormat)), + Dest->iBitmapFormat, 0, NULL); + TempSurf = AccessUserObject(hTemp); - // FIXME: Skip creating a TempSurf if we have the same BPP and palette - EngBitBlt(TempSurf, Source, NULL, NULL, ColorTranslation, &TempRect, SourcePoint, NULL, NULL, NULL, 0); + // FIXME: Skip creating a TempSurf if we have the same BPP and palette + EngBitBlt(TempSurf, Source, NULL, NULL, ColorTranslation, &TempRect, SourcePoint, NULL, NULL, NULL, 0); + } return DestGDI->BitBlt(Dest, TempSurf, Mask, ClipRegion, NULL, DestRect, &TempPoint, diff --git a/reactos/subsys/win32k/eng/lineto.c b/reactos/subsys/win32k/eng/lineto.c index 326c662fbce..6e6b58454f0 100644 --- a/reactos/subsys/win32k/eng/lineto.c +++ b/reactos/subsys/win32k/eng/lineto.c @@ -22,6 +22,7 @@ BOOL EngLineTo(SURFOBJ *Surface, CLIPOBJ *Clip, BRUSHOBJ *Brush, if(Surface->iType!=STYPE_BITMAP) { // Call the driver's DrvLineTo +DbgPrint("calling surfgdi's lineto\n"); return SurfGDI->LineTo(Surface, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); } diff --git a/reactos/subsys/win32k/eng/objects.h b/reactos/subsys/win32k/eng/objects.h index 461a60d0ca1..331c77f083a 100644 --- a/reactos/subsys/win32k/eng/objects.h +++ b/reactos/subsys/win32k/eng/objects.h @@ -8,6 +8,8 @@ * 21/8/1999: Created */ +#include + typedef struct _BRUSHGDI { } BRUSHGDI; @@ -32,8 +34,10 @@ typedef struct _FLOATGDI { } FLOATGDI; typedef struct _FONTGDI { - -} FONTGDI; + LPCWSTR Filename; + FT_Face face; + TEXTMETRIC TextMetric; +} FONTGDI, *PFONTGDI; typedef struct _PALGDI { ULONG Mode; // PAL_INDEXED, PAL_BITFIELDS, PAL_RGB, PAL_BGR @@ -56,6 +60,8 @@ typedef BOOL (*PFN_BitBlt)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PCLIPOBJ, PXLATEOBJ, PRECTL, PPOINTL, PPOINTL, PBRUSHOBJ, PPOINTL, ROP4); +typedef BOOL (*PFN_TransparentBlt)(PSURFOBJ, PSURFOBJ, PCLIPOBJ, PXLATEOBJ, PRECTL, PRECTL, ULONG, ULONG); + typedef BOOL (*PFN_StretchBlt)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PCLIPOBJ, PXLATEOBJ, PCOLORADJUSTMENT, PPOINTL, PRECTL, PRECTL, PPOINT, ULONG); @@ -94,6 +100,7 @@ typedef struct _SURFGDI { INT BitsPerPixel; PFN_BitBlt BitBlt; + PFN_TransparentBlt TransparentBlt; PFN_StretchBlt StretchBlt; PFN_TextOut TextOut; PFN_Paint Paint; diff --git a/reactos/subsys/win32k/eng/palette.c b/reactos/subsys/win32k/eng/palette.c index 2acfe5d241a..3904fc2791f 100644 --- a/reactos/subsys/win32k/eng/palette.c +++ b/reactos/subsys/win32k/eng/palette.c @@ -56,7 +56,7 @@ BOOL EngDeletePalette(IN HPALETTE Palette) PALGDI *PalGDI; PalGDI = AccessInternalObject(Palette); - PalObj = AccessInternalObject(Palette); + PalObj = AccessUserObject(Palette); EngFreeMem(PalGDI); EngFreeMem(PalObj); diff --git a/reactos/subsys/win32k/eng/surface.c b/reactos/subsys/win32k/eng/surface.c index 14b7248b651..1fdf07ad8b6 100644 --- a/reactos/subsys/win32k/eng/surface.c +++ b/reactos/subsys/win32k/eng/surface.c @@ -60,6 +60,7 @@ VOID InitializeHooks(SURFGDI *SurfGDI) SurfGDI->CopyBits = NULL; SurfGDI->CreateDeviceBitmap = NULL; SurfGDI->SetPalette = NULL; + SurfGDI->TransparentBlt = NULL; } HBITMAP EngCreateDeviceBitmap(DHSURF dhsurf, SIZEL Size, ULONG Format) @@ -90,6 +91,7 @@ HBITMAP EngCreateBitmap(IN SIZEL Size, NewBitmap = (PVOID)CreateGDIHandle(SurfGDI, SurfObj); InitializeHooks(SurfGDI); + SurfGDI->BitsPerPixel = BitsPerFormat(Format); SurfObj->lDelta = Width; SurfObj->cjBits = SurfObj->lDelta * Size.cy; @@ -174,6 +176,7 @@ BOOL EngAssociateSurface(HSURF Surface, HDEV Dev, ULONG Hooks) // Hook up specified functions if(Hooks & HOOK_BITBLT) SurfGDI->BitBlt = Dc->DriverFunctions.BitBlt; + if(Hooks & HOOK_TRANSPARENTBLT) SurfGDI->TransparentBlt = Dc->DriverFunctions.TransparentBlt; if(Hooks & HOOK_STRETCHBLT) SurfGDI->StretchBlt = Dc->DriverFunctions.StretchBlt; if(Hooks & HOOK_TEXTOUT) SurfGDI->TextOut = Dc->DriverFunctions.TextOut; if(Hooks & HOOK_PAINT) SurfGDI->Paint = Dc->DriverFunctions.Paint; diff --git a/reactos/subsys/win32k/eng/transblt.c b/reactos/subsys/win32k/eng/transblt.c new file mode 100644 index 00000000000..926bbcb6fd5 --- /dev/null +++ b/reactos/subsys/win32k/eng/transblt.c @@ -0,0 +1,69 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI TransparentBlt Function + * FILE: subsys/win32k/eng/transblt.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 4/6/2001: Created + */ + +#include +#include +#include +#include "brush.h" +#include "enum.h" +#include "objects.h" + +BOOL EngTransparentBlt(PSURFOBJ Dest, PSURFOBJ Source, + PCLIPOBJ Clip, PXLATEOBJ ColorTranslation, + PRECTL DestRect, PRECTL SourceRect, + ULONG TransparentColor, ULONG Reserved) +{ + PSURFGDI DestGDI = AccessInternalObjectFromUserObject(Dest); + HSURF hTemp; + PSURFOBJ TempSurf; + POINTL TempPoint, SourcePoint; + RECTL TempRect; + SIZEL TempSize; + LONG dx, dy, sx, sy; + + dx = abs(DestRect->right - DestRect->left); + dy = abs(DestRect->bottom - DestRect->top); + + sx = abs(SourceRect->right - SourceRect->left); + sy = abs(SourceRect->bottom - SourceRect->top); + + if(sxTransparentBlt != NULL) + { + // The destination is device managed, therefore get the source into a format compatible surface + TempPoint.x = 0; + TempPoint.y = 0; + TempRect.top = 0; + TempRect.left = 0; + TempRect.bottom = dy; + TempRect.right = dx; + TempSize.cx = TempRect.right; + TempSize.cy = TempRect.bottom; + + hTemp = EngCreateBitmap(TempSize, + DIB_GetDIBWidthBytes(dx, BitsPerFormat(Dest->iBitmapFormat)), Dest->iBitmapFormat, 0, NULL); + TempSurf = AccessUserObject(hTemp); + + SourcePoint.x = SourceRect->left; + SourcePoint.y = SourceRect->top; + + // FIXME: Skip creating a TempSurf if we have the same BPP and palette + EngBitBlt(TempSurf, Source, NULL, NULL, ColorTranslation, &TempRect, &SourcePoint, NULL, NULL, NULL, 0); + + return DestGDI->TransparentBlt(Dest, TempSurf, Clip, NULL, DestRect, SourceRect, + TransparentColor, Reserved); + } + + // Simulate a transparent blt + + return TRUE; +} diff --git a/reactos/subsys/win32k/eng/xlate.c b/reactos/subsys/win32k/eng/xlate.c index a97a1bb2328..436926a8e4d 100644 --- a/reactos/subsys/win32k/eng/xlate.c +++ b/reactos/subsys/win32k/eng/xlate.c @@ -8,6 +8,8 @@ * 8/20/1999: Created */ +// TODO: Cache XLATEOBJs that are created by EngCreateXlate by checking if the given palettes match a cached list + #include #include #include @@ -46,8 +48,8 @@ ULONG ClosestColorMatch(ULONG SourceColor, ULONG *DestColors, { PVIDEO_CLUTDATA cSourceColor; PVIDEO_CLUTDATA cDestColors; - ULONG bestMatch = 256, idx = 0, i; - ULONG rt; + LONG idx = 0, i, rt; + ULONG cxRed, cxGreen, cxBlue, BestMatch = 65535; // Simple cache -- only one value because we don't want to waste time // if the colors aren't very sequential @@ -58,19 +60,20 @@ ULONG ClosestColorMatch(ULONG SourceColor, ULONG *DestColors, } cSourceColor = &SourceColor; - for (i=0; iRed - cDestColors->Red) + - abs(cSourceColor->Green - cDestColors->Green) + - abs(cSourceColor->Blue - cDestColors->Blue) ) / 3; + cxRed = abs(cSourceColor->Red - cDestColors->Red) ^ 2; + cxGreen = abs(cSourceColor->Green - cDestColors->Green) ^ 2; + cxBlue = abs(cSourceColor->Blue - cDestColors->Blue) ^ 2; - if(rt<=bestMatch) + rt = /* sqrt */ (cxRed + cxGreen + cxBlue); + + if(rt<=BestMatch) { idx = i; - bestMatch = rt; + BestMatch = rt; } } @@ -132,8 +135,17 @@ XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType, if( (SourcePalType == PAL_INDEXED) || (SourcePalType == PAL_RGB) ) { XlateObj->flXlate |= XO_TABLE; - if (SourcePalType == PAL_INDEXED) IndexedColors = SourcePalGDI->NumColors; - if (DestPalType == PAL_INDEXED) IndexedColors = DestPalGDI->NumColors; + if ((SourcePalType == PAL_INDEXED) && (DestPalType == PAL_INDEXED)) + { + if(SourcePalGDI->NumColors > DestPalGDI->NumColors) + { + IndexedColors = SourcePalGDI->NumColors; + } else + IndexedColors = DestPalGDI->NumColors; + } + else if (SourcePalType == PAL_INDEXED) { IndexedColors = SourcePalGDI->NumColors; } + else if (DestPalType == PAL_INDEXED) { IndexedColors = DestPalGDI->NumColors; } + XlateGDI->translationTable = EngAllocMem(FL_ZERO_MEMORY, sizeof(ULONG)*IndexedColors, NULL); } diff --git a/reactos/subsys/win32k/main/dllmain.c b/reactos/subsys/win32k/main/dllmain.c index c3879415cef..c4162d2043a 100644 --- a/reactos/subsys/win32k/main/dllmain.c +++ b/reactos/subsys/win32k/main/dllmain.c @@ -1,4 +1,4 @@ -/* $Id: dllmain.c,v 1.18 2001/03/31 15:35:08 jfilby Exp $ +/* $Id: dllmain.c,v 1.19 2001/05/02 12:33:42 jfilby Exp $ * * Entry Point for win32k.sys */ @@ -52,6 +52,8 @@ BOOLEAN STDCALL W32kInitialize (VOID) { + DbgPrint("W32kInitialize\n"); + // FIXME: Retrieve name from registry EngLoadImage(L"\\SystemRoot\\system32\\drivers\\vidport.sys"); diff --git a/reactos/subsys/win32k/makefile b/reactos/subsys/win32k/makefile index cd601c51606..e4832d9682a 100644 --- a/reactos/subsys/win32k/makefile +++ b/reactos/subsys/win32k/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.29 2001/03/31 16:09:17 jfilby Exp $ +# $Id: makefile,v 1.30 2001/05/02 12:33:42 jfilby Exp $ # # WIN32K.SYS build spec # @@ -7,7 +7,7 @@ PATH_TO_TOP = ../.. TARGET=win32k # from atheos appserver makefile -COPTS = -pipe -O3 -I./freetype2-beta8/include -c -Wall +COPTS = -pipe -O3 -I./freetype/include -c -Wall CFLAGS = -I. @@ -15,7 +15,7 @@ CFLAGS = -I. ENG_OBJECTS= eng/debug.o eng/mem.o eng/brush.o eng/bitblt.o eng/clip.o eng/copybits.o \ eng/device.o eng/handle.o eng/lineto.o eng/paint.o eng/palette.o \ - eng/surface.o eng/xlate.o + eng/surface.o eng/xlate.o eng/transblt.o MAIN_OBJECTS = main/dllmain.o MISC_OBJECTS = misc/driver.o misc/math.o LDR_OBJECTS = ldr/loader.o @@ -27,7 +27,11 @@ OBJECTS_OBJECTS = objects/bitmaps.o objects/brush.o objects/cliprgn.o \ objects/region.o objects/text.o objects/wingl.o \ objects/bezier.o objects/objconv.o objects/dib.o objects/palette.o DIB_OBJECTS = dib/dib4bpp.o dib/dib24bpp.o -FREETYPE_OBJECTS = freetype/grfont.o +FREETYPE_OBJECTS = freetype/grfont.o freetype/ctype.o \ + freetype/ftsystem.o freetype/ftdebug.o freetype/ftinit.o freetype/ftbase.o \ + freetype/ftglyph.o freetype/ftmm.o freetype/autohint.o freetype/cff.o \ + freetype/type1cid.o freetype/psnames.o freetype/raster1.o freetype/sfnt.o \ + freetype/smooth.o freetype/truetype.o freetype/winfnt.o freetype/type1z.o RESOURCE_OBJECT = $(TARGET).coff STUBS_OBJECTS = stubs/stubs.o diff --git a/reactos/subsys/win32k/misc/driver.c b/reactos/subsys/win32k/misc/driver.c index a65d6e2c58e..b2a2348fe6a 100644 --- a/reactos/subsys/win32k/misc/driver.c +++ b/reactos/subsys/win32k/misc/driver.c @@ -1,4 +1,4 @@ -/* $Id: driver.c,v 1.17 2001/04/15 22:08:23 narnaoud Exp $ +/* $Id: driver.c,v 1.18 2001/05/02 12:33:42 jfilby Exp $ * * GDI Driver support routines * (mostly swiped from Wine) @@ -107,6 +107,7 @@ BOOL DRIVER_BuildDDIFunctions(PDRVENABLEDATA DED, DF->StrokeAndFillPath = (PGD_STROKEANDFILLPATH)DED->pdrvfn[i].pfn; if(DED->pdrvfn[i].iFunc == INDEX_DrvPaint) DF->Paint = (PGD_PAINT)DED->pdrvfn[i].pfn; if(DED->pdrvfn[i].iFunc == INDEX_DrvBitBlt) DF->BitBlt = (PGD_BITBLT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvTransparentBlt) DF->TransparentBlt = (PGD_TRANSPARENTBLT)DED->pdrvfn[i].pfn; if(DED->pdrvfn[i].iFunc == INDEX_DrvCopyBits) DF->CopyBits = (PGD_COPYBITS)DED->pdrvfn[i].pfn; if(DED->pdrvfn[i].iFunc == INDEX_DrvStretchBlt) DF->StretchBlt = (PGD_STRETCHBLT)DED->pdrvfn[i].pfn; if(DED->pdrvfn[i].iFunc == INDEX_DrvSetPalette) DF->SetPalette = (PGD_SETPALETTE)DED->pdrvfn[i].pfn; diff --git a/reactos/subsys/win32k/objects/brush.c b/reactos/subsys/win32k/objects/brush.c index b9a2cfe3732..239b1e72b36 100644 --- a/reactos/subsys/win32k/objects/brush.c +++ b/reactos/subsys/win32k/objects/brush.c @@ -1,4 +1,4 @@ -/* $Id: brush.c,v 1.11 2001/03/31 15:35:08 jfilby Exp $ +/* $Id: brush.c,v 1.12 2001/05/02 12:33:42 jfilby Exp $ */ @@ -9,28 +9,29 @@ #include //#include -// #define NDEBUG +#define NDEBUG #include HBRUSH STDCALL W32kCreateBrushIndirect(CONST LOGBRUSH *lb) { PBRUSHOBJ brushPtr; HBRUSH hBrush; - + brushPtr = BRUSHOBJ_AllocBrush(); hBrush = BRUSHOBJ_PtrToHandle (brushPtr); + if (hBrush == NULL) { return 0; } - + + brushPtr->iSolidColor = lb->lbColor; brushPtr->logbrush.lbStyle = lb->lbStyle; brushPtr->logbrush.lbColor = lb->lbColor; brushPtr->logbrush.lbHatch = lb->lbHatch; BRUSHOBJ_UnlockBrush (hBrush); - DPRINT("%08x\n", hBrush); - + return hBrush; } diff --git a/reactos/subsys/win32k/objects/color.c b/reactos/subsys/win32k/objects/color.c index fc0574afe89..c56ca8b4273 100644 --- a/reactos/subsys/win32k/objects/color.c +++ b/reactos/subsys/win32k/objects/color.c @@ -119,6 +119,7 @@ HPALETTE STDCALL W32kCreateHalftonePalette(HDC hDC) HPALETTE STDCALL W32kCreatePalette(CONST PLOGPALETTE palette) { PPALOBJ PalObj; + HPALETTE NewPalette = EngCreatePalette(PAL_INDEXED, palette->palNumEntries, palette->palPalEntry, 0, 0, 0); ULONG size; diff --git a/reactos/subsys/win32k/objects/dc.c b/reactos/subsys/win32k/objects/dc.c index 2768ab51521..a4ff7fb49ae 100644 --- a/reactos/subsys/win32k/objects/dc.c +++ b/reactos/subsys/win32k/objects/dc.c @@ -1,4 +1,4 @@ -/* $Id: dc.c,v 1.19 2001/03/31 15:35:08 jfilby Exp $ +/* $Id: dc.c,v 1.20 2001/05/02 12:33:42 jfilby Exp $ * * DC.C - Device context functions * @@ -16,6 +16,7 @@ #include #include #include +#include #include "../eng/objects.h" // #define NDEBUG @@ -166,6 +167,8 @@ HDC STDCALL W32kCreateCompatableDC(HDC hDC) NewDC->w.hBitmap = hBitmap; NewDC->w.hFirstBitmap = hBitmap; NewDC->w.hPalette = OrigDC->w.hPalette; + NewDC->w.textColor = OrigDC->w.textColor; + NewDC->w.textAlign = OrigDC->w.textAlign; DC_UnlockDC(NewDC); DC_UnlockDC(OrigDC); @@ -173,6 +176,8 @@ HDC STDCALL W32kCreateCompatableDC(HDC hDC) return DC_PtrToHandle(NewDC); } +#include + HDC STDCALL W32kCreateDC(LPCWSTR Driver, LPCWSTR Device, LPCWSTR Output, @@ -192,7 +197,7 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver, } DPRINT("NAME: %S\n", Driver); // FIXME: Should not crash if NULL - + /* Allocate a DC object */ if ((NewDC = DC_AllocDC(Driver)) == NULL) { @@ -291,6 +296,9 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver, DC_InitDC(NewDC); hNewDC = DC_PtrToHandle(NewDC); + W32kSetTextColor(hNewDC, RGB(0xff, 0xff, 0xff)); + W32kSetTextAlign(hNewDC, TA_BASELINE); + // If we've created a DC for the DISPLAY, save the reference for later CreateCompatibleDC(NULL... usage if(wcscmp(Driver, "DISPLAY")) // FIXME: this works.. but shouldn't we compare to L"DISPLAY" ? (which doesn't work..) { diff --git a/reactos/subsys/win32k/objects/text.c b/reactos/subsys/win32k/objects/text.c index e7ff7ea8b47..419a7b43c4c 100644 --- a/reactos/subsys/win32k/objects/text.c +++ b/reactos/subsys/win32k/objects/text.c @@ -6,22 +6,38 @@ #include #include #include -// #include +#include + +#include "../eng/objects.h" // #define NDEBUG #include -// FT_Library library; +FT_Library library; + +typedef struct _FONTTABLE { + HFONT hFont; + LPCWSTR FaceName; +} FONTTABLE, *PFONTTABLE; + +FONTTABLE FontTable[256]; +INT FontsLoaded = 0; BOOL InitFontSupport() { -/* ULONG error; + ULONG error; error = FT_Init_FreeType(&library); if(error) { return FALSE; - } else return TRUE; */ + } + + W32kAddFontResource(L"\\SystemRoot\\media\\fonts\\helb____.ttf"); + W32kAddFontResource(L"\\SystemRoot\\media\\fonts\\timr____.ttf"); + + DbgPrint("All fonts loaded\n"); + return TRUE; } @@ -29,7 +45,103 @@ int STDCALL W32kAddFontResource(LPCWSTR Filename) { - UNIMPLEMENTED; + HFONT NewFont; + PFONTOBJ FontObj; + PFONTGDI FontGDI; + UNICODE_STRING uFileName; + NTSTATUS Status; + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + FILE_STANDARD_INFORMATION FileStdInfo; + PVOID buffer; + ULONG size; + INT error; + FT_Face face; + ANSI_STRING StringA; + UNICODE_STRING StringU; + + FontObj = EngAllocMem(FL_ZERO_MEMORY, sizeof(XLATEOBJ), NULL); + FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(XLATEGDI), NULL); + NewFont = CreateGDIHandle(FontGDI, FontObj); + + RtlCreateUnicodeString(&uFileName, Filename); + + // Open the Module + InitializeObjectAttributes(&ObjectAttributes, &uFileName, 0, NULL, NULL); + + Status = NtOpenFile(&FileHandle, FILE_ALL_ACCESS, &ObjectAttributes, NULL, 0, 0); + + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not open module file: %wZ\n", Filename); + return 0; + } + + // Get the size of the file + Status = NtQueryInformationFile(FileHandle, NULL, &FileStdInfo, sizeof(FileStdInfo), FileStandardInformation); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not get file size\n"); + return 0; + } + + // Allocate nonpageable memory for driver + size = FileStdInfo.EndOfFile.u.LowPart; + buffer = ExAllocatePool(NonPagedPool, size); + + if (buffer == NULL) + { + DbgPrint("could not allocate memory for module"); + return 0; + } + + // Load driver into memory chunk + Status = NtReadFile(FileHandle, 0, 0, 0, 0, buffer, FileStdInfo.EndOfFile.u.LowPart, 0, 0); + if (!NT_SUCCESS(Status)) + { + DbgPrint("could not read module file into memory"); + ExFreePool(buffer); + return 0; + } + + NtClose(FileHandle); + + error = FT_New_Memory_Face(library, buffer, size, 0, &face); + if (error == FT_Err_Unknown_File_Format) + { + DbgPrint("Unknown font file format\n"); + return 0; + } + else if (error) + { + DbgPrint("Error reading font file (error code: %u)\n", error); // 48 + return 0; + } + + // FontGDI->Filename = Filename; perform strcpy + FontGDI->face = face; + + // FIXME: Complete text metrics + FontGDI->TextMetric.tmAscent = face->size->metrics.ascender; // units above baseline + FontGDI->TextMetric.tmDescent = face->size->metrics.descender; // units below baseline + FontGDI->TextMetric.tmHeight = FontGDI->TextMetric.tmAscent + FontGDI->TextMetric.tmDescent; + + DbgPrint("Family name: %s\n", face->family_name); + DbgPrint("Style name: %s\n", face->style_name); + DbgPrint("Num glyphs: %u\n", face->num_glyphs); + + // Add this font resource to the font table + FontTable[FontsLoaded].hFont = NewFont; + FontTable[FontsLoaded].FaceName = ExAllocatePool(NonPagedPool, (StringU.Length + 1) * 2); + + RtlInitAnsiString(&StringA, (LPSTR)face->family_name); + RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE); + wcscpy(FontTable[FontsLoaded].FaceName, StringU.Buffer); + RtlFreeUnicodeString(&StringU); + + FontsLoaded++; + + return 1; } HFONT @@ -49,14 +161,53 @@ W32kCreateFont(int Height, DWORD PitchAndFamily, LPCWSTR Face) { - UNIMPLEMENTED; + LOGFONT logfont; + + logfont.lfHeight = Height; + logfont.lfWidth = Width; + logfont.lfEscapement = Escapement; + logfont.lfOrientation = Orientation; + logfont.lfWeight = Weight; + logfont.lfItalic = Italic; + logfont.lfUnderline = Underline; + logfont.lfStrikeOut = StrikeOut; + logfont.lfCharSet = CharSet; + logfont.lfOutPrecision = OutputPrecision; + logfont.lfClipPrecision = ClipPrecision; + logfont.lfQuality = Quality; + logfont.lfPitchAndFamily = PitchAndFamily; + + if(Face) + memcpy(logfont.lfFaceName, Face, sizeof(logfont.lfFaceName)); + else + logfont.lfFaceName[0] = '\0'; + + return W32kCreateFontIndirect(&logfont); } HFONT STDCALL W32kCreateFontIndirect(CONST LPLOGFONT lf) { - DbgPrint("WARNING: W32kCreateFontIndirect is current unimplemented\n"); + HFONT hFont = 0; + PTEXTOBJ fontPtr; + + if (lf) + { + if(fontPtr = TEXTOBJ_AllocText()) + { + memcpy(&fontPtr->logfont, lf, sizeof(LOGFONT)); + + if (lf->lfEscapement != lf->lfOrientation) { + /* this should really depend on whether GM_ADVANCED is set */ + fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement; + } + hFont = TEXTOBJ_PtrToHandle(fontPtr); + TEXTOBJ_UnlockText(hFont); + } + } + + return hFont; } BOOL @@ -268,7 +419,42 @@ W32kGetTextExtentPoint(HDC hDC, int Count, LPSIZE Size) { - UNIMPLEMENTED; + PDC dc = AccessUserObject(hDC); + PFONTGDI FontGDI; + FT_Face face; + FT_GlyphSlot glyph; + INT error, pitch, glyph_index, i; + ULONG TotalWidth = 0, MaxHeight = 0, CurrentChar = 0, SpaceBetweenChars = 5; + + FontGDI = AccessInternalObject(dc->w.hFont); + + for(i=0; iglyph; + + if (glyph->format == ft_glyph_format_outline) + { + error = FT_Render_Glyph(glyph, ft_render_mode_mono); + if(error) DbgPrint("WARNING: Failed to render glyph!\n"); + pitch = glyph->bitmap.pitch; + } else { + pitch = glyph->bitmap.width; + } + + TotalWidth += pitch-1; + if((glyph->bitmap.rows-1) > MaxHeight) MaxHeight = glyph->bitmap.rows-1; + + CurrentChar++; + + if(CurrentChar < Size) TotalWidth += SpaceBetweenChars; + String++; + } + + Size->cx = TotalWidth; + Size->cy = MaxHeight; } BOOL @@ -295,7 +481,13 @@ STDCALL W32kGetTextMetrics(HDC hDC, LPTEXTMETRIC tm) { - UNIMPLEMENTED; + PDC dc = AccessUserObject(hDC); + PFONTGDI FontGDI; + + FontGDI = AccessInternalObject(dc->w.hFont); + memcpy(tm, &FontGDI->TextMetric, sizeof(TEXTMETRIC)); + + return TRUE; } BOOL @@ -357,6 +549,7 @@ W32kSetTextColor(HDC hDC, oldColor = dc->w.textColor; dc->w.textColor = color; + DC_UnlockDC(hDC); return oldColor; @@ -379,104 +572,55 @@ W32kTextOut(HDC hDC, LPCWSTR String, int Count) { - UNIMPLEMENTED; // Fixme: Call EngTextOut, which does the real work (calling DrvTextOut where appropriate) -/* + DC *dc = DC_HandleToPtr(hDC); SURFOBJ *SurfObj = AccessUserObject(dc->Surface); - UNICODE_STRING FileName; - int error, glyph_index, n, load_flags = FT_LOAD_RENDER, i, j; + int error, glyph_index, n, load_flags = FT_LOAD_RENDER, i, j, sx, sy, scc; FT_Face face; FT_GlyphSlot glyph; - NTSTATUS Status; - HANDLE FileHandle; - OBJECT_ATTRIBUTES ObjectAttributes; - FILE_STANDARD_INFORMATION FileStdInfo; - PVOID buffer; - ULONG size, TextLeft = XStart, TextTop = YStart, SpaceBetweenChars = 5, StringLength; - FT_Vector origin; - FT_Bitmap bit, bit2, bit3; - POINTL SourcePoint; - RECTL DestRect; + ULONG TextLeft = XStart, TextTop = YStart, SpaceBetweenChars = 2, pitch, previous; + FT_Bool use_kerning; + RECTL DestRect, MaskRect; + POINTL SourcePoint, BrushOrigin; + HBRUSH hBrush; + PBRUSHOBJ Brush; HBITMAP HSourceGlyph; PSURFOBJ SourceGlyphSurf; SIZEL bitSize; - FT_CharMap found = 0; - FT_CharMap charmap; - PCHAR bitbuf; + FT_CharMap found = 0, charmap; + INT yoff; + HFONT hFont = 0; + PFONTOBJ FontObj; + PFONTGDI FontGDI; + PTEXTOBJ TextObj; + PPALGDI PalDestGDI; + PXLATEOBJ XlateObj; - // For now we're just going to use an internal font -// grWriteCellString(SurfObj, XStart, YStart, AString->Buffer, 0xffffff); + TextObj = TEXTOBJ_HandleToPtr(dc->w.hFont); - // Prepare the Unicode FileName - RtlCreateUnicodeString(&FileName, L"\\SystemRoot\\fonts\\arial.ttf"); - - // Open the Module - InitializeObjectAttributes(&ObjectAttributes, &FileName, 0, NULL, NULL); - - Status = NtOpenFile(&FileHandle, FILE_ALL_ACCESS, &ObjectAttributes, NULL, 0, 0); - - if (!NT_SUCCESS(Status)) + for(i=0; ilogfont.lfFaceName) == 0) + hFont = FontTable[i].hFont; } - // Get the size of the file - Status = NtQueryInformationFile(FileHandle, NULL, &FileStdInfo, sizeof(FileStdInfo), FileStandardInformation); - if (!NT_SUCCESS(Status)) + if(hFont == 0) { - DbgPrint("Could not get file size\n"); - return 0; + DbgPrint("Specified font %s is not loaded\n", TextObj->logfont.lfFaceName); + return FALSE; } - // Allocate nonpageable memory for driver - size = FileStdInfo.EndOfFile.u.LowPart; - buffer = ExAllocatePool(NonPagedPool, size); - - if (buffer == NULL) - { - DbgPrint("could not allocate memory for module"); - return 0; - } - - // Load driver into memory chunk - Status = NtReadFile(FileHandle, 0, 0, 0, 0, buffer, FileStdInfo.EndOfFile.u.LowPart, 0, 0); - if (!NT_SUCCESS(Status)) - { - DbgPrint("could not read module file into memory"); - ExFreePool(buffer); - - return 0; - } - - NtClose(FileHandle); - - error = FT_New_Memory_Face(library, - buffer, // first byte in memory - size, // size in bytes - 0, // face_index - &face ); - if ( error == FT_Err_Unknown_File_Format ) - { - DbgPrint("Unknown font file format\n"); - } - else if ( error ) - { - DbgPrint("Error reading font file\n"); - } - - DbgPrint("Family name: %s\n", face->family_name); - DbgPrint("Style name: %s\n", face->style_name); - DbgPrint("Num glyphs: %u\n", face->num_glyphs); - DbgPrint("Height: %d\n", face->height); + FontObj = AccessUserObject(hFont); + FontGDI = AccessInternalObject(hFont); + face = FontGDI->face; if (face->charmap == NULL) { DbgPrint("WARNING: No charmap selected!\n"); DbgPrint("This font face has %d charmaps\n", face->num_charmaps); - for ( n = 0; n < face->num_charmaps; n++ ) + for (n = 0; n < face->num_charmaps; n++) { charmap = face->charmaps[n]; DbgPrint("found charmap encoding: %u\n", charmap->encoding); @@ -486,70 +630,97 @@ W32kTextOut(HDC hDC, break; } } + if (!found) DbgPrint("WARNING: Could not find desired charmap!\n"); + error = FT_Set_Charmap(face, found); + if (error) DbgPrint("WARNING: Could not set the charmap!\n"); } - if (!found) DbgPrint("WARNING: Could not find desired charmap!\n"); - - error = FT_Set_Charmap(face, found); - if (error) DbgPrint("WARNING: Could not set the charmap!\n"); - error = FT_Set_Char_Size( - face, // handle to face object - 16*64, // char_width in 1/64th of points - 16*64, // char_height in 1/64th of points - 300, // horizontal device resolution - 300 ); // vertical device resolution + error = FT_Set_Pixel_Sizes(face, TextObj->logfont.lfHeight, TextObj->logfont.lfWidth); + if(error) { + DbgPrint("Error in setting pixel sizes: %u\n", error); + return FALSE; + } - StringLength = wcslen(String); - DbgPrint("StringLength: %u\n", StringLength); + // Create the brush + PalDestGDI = AccessInternalObject(dc->w.hPalette); + XlateObj = EngCreateXlate(PalDestGDI->Mode, PAL_RGB, dc->w.hPalette, NULL); + hBrush = W32kCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor)); + Brush = BRUSHOBJ_HandleToPtr(hBrush); + EngDeleteXlate(XlateObj); - for(i=0; iw.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; - if ( glyph->format == ft_glyph_format_outline ) + // retrieve kerning distance and move pen position + if (use_kerning && previous && glyph_index) { - DbgPrint("Outline Format Font\n"); - error = FT_Render_Glyph( glyph, ft_render_mode_normal ); - if(error) DbgPrint("WARNING: Failed to render glyph!\n"); - } else { - DbgPrint("Bitmap Format Font\n"); - bit3.rows = glyph->bitmap.rows; - bit3.width = glyph->bitmap.width; - bit3.pitch = glyph->bitmap.pitch; - bit3.buffer = glyph->bitmap.buffer; + FT_Vector delta; + FT_Get_Kerning(face, previous, glyph_index, 0, &delta); + TextLeft += delta.x >> 6; } - SourcePoint.x = 0; - SourcePoint.y = 0; - DestRect.left = TextLeft; - DestRect.top = TextTop; - DestRect.right = TextLeft + glyph->bitmap.width-1; - DestRect.bottom = TextTop + glyph->bitmap.rows-1; - bitSize.cx = glyph->bitmap.width-1; - bitSize.cy = glyph->bitmap.rows-1; + if (glyph->format == ft_glyph_format_outline) + { + error = FT_Render_Glyph(glyph, ft_render_mode_mono); + if(error) { + DbgPrint("WARNING: Failed to render glyph!\n"); + return FALSE; + } + pitch = glyph->bitmap.pitch; + } else { + pitch = glyph->bitmap.width; + } - HSourceGlyph = EngCreateBitmap(bitSize, glyph->bitmap.pitch, BMF_8BPP, 0, glyph->bitmap.buffer); + DestRect.left = TextLeft; + DestRect.top = TextTop + yoff - glyph->bitmap_top; + DestRect.right = TextLeft + glyph->bitmap.width; + DestRect.bottom = DestRect.top + glyph->bitmap.rows; + bitSize.cx = pitch-1; + bitSize.cy = glyph->bitmap.rows-1; + 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 = AccessUserObject(HSourceGlyph); - EngBitBlt(SurfObj, SourceGlyphSurf, - NULL, NULL, NULL, &DestRect, &SourcePoint, NULL, NULL, NULL, NULL); + // Use the font data as a mask to paint onto the DCs surface using a brush + EngBitBlt(SurfObj, NULL, SourceGlyphSurf, NULL, NULL, &DestRect, &SourcePoint, &MaskRect, Brush, &BrushOrigin, 0xAACC); + + EngDeleteSurface(HSourceGlyph); + + TextLeft += glyph->advance.x >> 6; + previous = glyph_index; - TextLeft += glyph->bitmap.width + SpaceBetweenChars; String++; } - -DbgPrint("BREAK\n"); for (;;) ; -*/ -/* RtlFreeAnsiString(AString); - RtlFreeUnicodeString(UString); */ } UINT