/******************************Module*Header*******************************\ * Module Name: screen.c * * This file contains the virtual driver that is used for user-mode GDI+ * painting on the desktop screen. * * Copyright (c) 1998-1999 Microsoft Corporation * * Created: 29-Apr-1998 * Author: J. Andrew Goossen [andrewgo] * \**************************************************************************/ // @@@ Re-visit headers: #define NO_DDRAWINT_NO_COM // @@@ Temporary: #include #include #include #include #include #include #include #include #include VOID vFreeMem(VOID*); VOID* pAllocMem(ULONG, ULONG); #define RIP(x) OutputDebugString(x) #define WARNING(x) OutputDebugString(x) #define ASSERTGDI(x, y) if (!(x)) OutputDebugString(y) #define PALLOCMEM(size, tag) pAllocMem(size, tag); #define VFREEMEM(p) vFreeMem(p); ULONG DbgPrint( PCH Format, ... ); typedef struct _GPDEV { HDEV hdev; HWND hwnd; // @@@ Hwnd this HDEV was created from HSURF hsurfScreen; // Handle to the screen surface SIZEL sizlScreen; // Size of the screen ULONG iBitmapFormat; // The color depth ULONG flRed; // The RGB color masks ULONG flGreen; ULONG flBlue; HPALETTE hpalDefault; // The GDI palette handle PALETTEENTRY* pPal; // The palette table if palette managed LPDIRECTDRAW lpDD; // DirectDraw object LPDIRECTDRAWSURFACE lpDDPrimary; // DirectDraw primary surface LPDIRECTDRAWSURFACE lpDDBuffer; // DirectDraw buffer surface LPDIRECTDRAWCLIPPER lpDDClipper; // Primary surface DirectDraw clipper SURFOBJ* psoBuffer; // GDI surface wrapped around buffer } GDEV; /******************************Public*Structure****************************\ * GDIINFO ggdiGdiPlusDefault * * This contains the default GDIINFO fields that are passed back to GDI * during DrvEnablePDEV. * * NOTE: This structure defaults to values for an 8bpp palette device. * Some fields are overwritten for different colour depths. \**************************************************************************/ GDIINFO ggdiGdiPlusDefault = { GDI_DRIVER_VERSION, DT_RASDISPLAY, // ulTechnology 320, // ulHorzSize 240, // ulVertSize 0, // ulHorzRes (filled in later) 0, // ulVertRes (filled in later) 0, // cBitsPixel (filled in later) 0, // cPlanes (filled in later) 20, // ulNumColors (palette managed) 0, // flRaster (DDI reserved field) 0, // ulLogPixelsX (filled in later) 0, // ulLogPixelsY (filled in later) TC_RA_ABLE, // flTextCaps -- If we had wanted console windows // to scroll by repainting the entire window, // instead of doing a screen-to-screen blt, we // would have set TC_SCROLLBLT (yes, the flag is // bass-ackwards). 8, // ulDACRed (possibly overwritten later) 8, // ulDACGreen (possibly overwritten later) 8, // ulDACBlue (possibly overwritten later) 0x0024, // ulAspectX 0x0024, // ulAspectY 0x0033, // ulAspectXY (one-to-one aspect ratio) 1, // xStyleStep 1, // yStyleSte; 3, // denStyleStep -- Styles have a one-to-one aspect // ratio, and every 'dot' is 3 pixels long { 0, 0 }, // ptlPhysOffset { 0, 0 }, // szlPhysSize 256, // ulNumPalReg // These fields are for halftone initialization. The actual values are // a bit magic, but seem to work well on our display. { // ciDevice { 6700, 3300, 0 }, // Red { 2100, 7100, 0 }, // Green { 1400, 800, 0 }, // Blue { 1750, 3950, 0 }, // Cyan { 4050, 2050, 0 }, // Magenta { 4400, 5200, 0 }, // Yellow { 3127, 3290, 0 }, // AlignmentWhite 20000, // RedGamma 20000, // GreenGamma 20000, // BlueGamma 0, 0, 0, 0, 0, 0 // No dye correction for raster displays }, 0, // ulDevicePelsDPI (for printers only) PRIMARY_ORDER_CBA, // ulPrimaryOrder HT_PATSIZE_4x4_M, // ulHTPatternSize HT_FORMAT_8BPP, // ulHTOutputFormat HT_FLAG_ADDITIVE_PRIMS, // flHTFlags 0, // ulVRefresh 0, // ulPanningHorzRes 0, // ulPanningVertRes 0, // ulBltAlignment }; /******************************Public*Structure****************************\ * DEVINFO gdevinfoGdiPlusDefault * * This contains the default DEVINFO fields that are passed back to GDI * during DrvEnablePDEV. * * NOTE: This structure defaults to values for an 8bpp palette device. * Some fields are overwritten for different colour depths. \**************************************************************************/ #define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\ CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\ VARIABLE_PITCH | FF_DONTCARE,L"System"} #define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\ CLIP_STROKE_PRECIS,PROOF_QUALITY,\ VARIABLE_PITCH | FF_DONTCARE,L"MS Sans Serif"} #define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\ CLIP_STROKE_PRECIS,PROOF_QUALITY,\ FIXED_PITCH | FF_DONTCARE, L"Courier"} DEVINFO gdevinfoGdiPlusDefault = { (GCAPS_OPAQUERECT | GCAPS_PALMANAGED | GCAPS_MONO_DITHER | GCAPS_COLOR_DITHER), // flGraphicsFlags SYSTM_LOGFONT, // lfDefaultFont HELVE_LOGFONT, // lfAnsiVarFont COURI_LOGFONT, // lfAnsiFixFont 0, // cFonts BMF_8BPP, // iDitherFormat 8, // cxDither 8, // cyDither 0 // hpalDefault (filled in later) }; /******************************Public*Routine******************************\ * VOID vGpsUninitializeDirectDraw * \**************************************************************************/ VOID vGpsUninitializeDirectDraw( GDEV* pgdev) { HSURF hsurf; if (pgdev->psoBuffer != NULL) { hsurf = pgdev->psoBuffer->hsurf; EngUnlockSurface(pgdev->psoBuffer); EngDeleteSurface(hsurf); } if (pgdev->lpDDClipper != NULL) { pgdev->lpDDClipper->lpVtbl->Release(pgdev->lpDDClipper); pgdev->lpDDClipper = NULL; } if (pgdev->lpDDBuffer != NULL) { pgdev->lpDDBuffer->lpVtbl->Release(pgdev->lpDDBuffer); pgdev->lpDDBuffer = NULL; } if (pgdev->lpDDPrimary != NULL) { pgdev->lpDDPrimary->lpVtbl->Release(pgdev->lpDDPrimary); pgdev->lpDDPrimary = NULL; } if (pgdev->lpDD != NULL) { pgdev->lpDD->lpVtbl->Release(pgdev->lpDD); pgdev->lpDD = NULL; } } /******************************Public*Routine******************************\ * BOOL bGpsInitializeDirectDraw * \**************************************************************************/ BOOL bGpsInitializeDirectDraw( GDEV* pgdev, HWND hwnd, ULONG* pScreenWidth, ULONG* pScreenHeight, ULONG* pBitsPerPlane, ULONG* pRedMask, ULONG* pGreenMask, ULONG* pBlueMask) { LPDIRECTDRAW lpDD; DDSURFACEDESC DDMode; DDSURFACEDESC ddsd; LPDIRECTDRAWSURFACE lpDDPrimary; LPDIRECTDRAWSURFACE lpDDBuffer; LPDIRECTDRAWCLIPPER lpDDClipper; SURFOBJ* psoBuffer; SIZEL sizl; ULONG iFormat; HSURF hsurf; DDMode.dwSize = sizeof(DDMode); if (DirectDrawCreate(NULL, &lpDD, NULL) == DD_OK) { if ((lpDD->lpVtbl->SetCooperativeLevel(lpDD, hwnd, DDSCL_NORMAL) == DD_OK) && (lpDD->lpVtbl->GetDisplayMode(lpDD, &DDMode) == DD_OK)) { *pScreenWidth = DDMode.dwWidth; *pScreenHeight = DDMode.dwHeight; *pBitsPerPlane = DDMode.ddpfPixelFormat.dwRGBBitCount; *pRedMask = DDMode.ddpfPixelFormat.dwRBitMask; *pGreenMask = DDMode.ddpfPixelFormat.dwGBitMask; *pBlueMask = DDMode.ddpfPixelFormat.dwBBitMask; // Create a primary surface: RtlZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if (lpDD->lpVtbl->CreateSurface(lpDD, &ddsd, &lpDDPrimary, NULL) == DD_OK) { if (lpDD->lpVtbl->CreateClipper(lpDD, 0, &lpDDClipper, NULL) == DD_OK) { if ((lpDDClipper->lpVtbl->SetHWnd(lpDDClipper, 0, hwnd) == DD_OK) && (lpDDPrimary->lpVtbl->SetClipper(lpDDPrimary, lpDDClipper) == DD_OK)) { // Create a temporary DirectDraw surface that's used // as a staging area. // // @@@ This darn well better be temporary! RtlZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; ddsd.dwWidth = DDMode.dwWidth; ddsd.dwHeight = DDMode.dwHeight; if (lpDD->lpVtbl->CreateSurface(lpDD, &ddsd, &lpDDBuffer, NULL) == DD_OK) { if (lpDDBuffer->lpVtbl->Lock(lpDDBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL) == DD_OK) { // Create a GDI surface to wrap around the temporary // buffer: sizl.cx = ddsd.dwWidth; sizl.cy = ddsd.dwHeight; switch (DDMode.ddpfPixelFormat.dwRGBBitCount) { case 4: iFormat = BMF_4BPP; break; case 8: iFormat = BMF_8BPP; break; case 16: iFormat = BMF_16BPP; break; case 24: iFormat = BMF_24BPP; break; case 32: iFormat = BMF_32BPP; break; default: RIP("Unexpected dwRGBBitCount"); } // !!! @@@ Why did I have to specify BMF_TOPDOWN? hsurf = (HSURF) EngCreateBitmap(sizl, ddsd.lPitch, iFormat, BMF_TOPDOWN, ddsd.lpSurface); lpDDBuffer->lpVtbl->Unlock(lpDDBuffer, ddsd.lpSurface); if (hsurf != NULL) { psoBuffer = EngLockSurface(hsurf); pgdev->hwnd = hwnd; pgdev->lpDD = lpDD; pgdev->lpDDPrimary = lpDDPrimary; pgdev->lpDDBuffer = lpDDBuffer; pgdev->psoBuffer = psoBuffer; return(TRUE); } } lpDDBuffer->lpVtbl->Release(lpDDBuffer); } } lpDDClipper->lpVtbl->Release(lpDDClipper); } lpDDPrimary->lpVtbl->Release(lpDDPrimary); } } lpDD->lpVtbl->Release(lpDD); } WARNING("Failed bGpsInitializeDirectDraw"); return(FALSE); } /******************************Public*Routine******************************\ * BOOL bGpsInitializeModeFields * * Fill in the GDIINFO and DEVINFO structures required by the engine. * \**************************************************************************/ BOOL bGpsInitializeModeFields( GDEV* pgdev, ULONG* pScreenWidth, ULONG* pScreenHeight, ULONG* pBitsPerPlane, ULONG* pRedMask, ULONG* pGreenMask, ULONG* pBlueMask, GDIINFO* pgdi, DEVINFO* pdi) { ULONG BitsPerPlane; ULONG RedMask; ULONG GreenMask; ULONG BlueMask; ULONG ScreenWidth; ULONG ScreenHeight; RedMask = *pRedMask; GreenMask = *pGreenMask; BlueMask = *pBlueMask; BitsPerPlane = *pBitsPerPlane; ScreenWidth = *pScreenWidth; ScreenHeight = *pScreenHeight; pgdev->sizlScreen.cx = ScreenWidth; pgdev->sizlScreen.cy = ScreenHeight; // Fill in the GDIINFO data structure with the default 8bpp values: *pgdi = ggdiGdiPlusDefault; // Now overwrite the defaults with the relevant information returned // from the kernel driver: pgdi->ulHorzRes = ScreenWidth; pgdi->ulVertRes = ScreenHeight; pgdi->ulPanningHorzRes = ScreenWidth; pgdi->ulPanningVertRes = ScreenHeight; pgdi->cBitsPixel = BitsPerPlane; pgdi->cPlanes = 1; pgdi->ulLogPixelsX = 120; // @@@ pgdi->ulLogPixelsY = 120; // Fill in the devinfo structure with the default 8bpp values: *pdi = gdevinfoGdiPlusDefault; if (BitsPerPlane == 8) { pgdev->iBitmapFormat = BMF_8BPP; pgdi->ulDACRed = 0; pgdi->ulDACGreen = 0; pgdi->ulDACBlue = 0; } else if ((BitsPerPlane == 16) || (BitsPerPlane == 15)) { pgdev->iBitmapFormat = BMF_16BPP; pgdev->flRed = RedMask; pgdev->flGreen = GreenMask; pgdev->flBlue = BlueMask; pgdi->ulNumColors = (ULONG) -1; pgdi->ulNumPalReg = 0; pgdi->ulHTOutputFormat = HT_FORMAT_16BPP; pdi->iDitherFormat = BMF_16BPP; pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER); } else if (BitsPerPlane == 24) { pgdev->iBitmapFormat = BMF_24BPP; pgdev->flRed = RedMask; pgdev->flGreen = GreenMask; pgdev->flBlue = BlueMask; pgdi->ulNumColors = (ULONG) -1; pgdi->ulNumPalReg = 0; pgdi->ulHTOutputFormat = HT_FORMAT_24BPP; pdi->iDitherFormat = BMF_24BPP; pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER); } else { ASSERTGDI(BitsPerPlane == 32, "This driver supports only 8, 16, 24 and 32bpp"); pgdev->iBitmapFormat = BMF_32BPP; pgdev->flRed = RedMask; pgdev->flGreen = GreenMask; pgdev->flBlue = BlueMask; pgdi->ulNumColors = (ULONG) -1; pgdi->ulNumPalReg = 0; pgdi->ulHTOutputFormat = HT_FORMAT_32BPP; pdi->iDitherFormat = BMF_32BPP; pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER); } return(TRUE); } /******************************Public*Routine******************************\ * BOOL bGpsInitializePalette * * Initializes default palette for PDEV. * \**************************************************************************/ BOOL bGpsInitializePalette( GDEV* pgdev, DEVINFO* pdi) { PALETTEENTRY* ppal; PALETTEENTRY* ppalTmp; ULONG ulLoop; BYTE jRed; BYTE jGre; BYTE jBlu; HPALETTE hpal; if (pgdev->iBitmapFormat == BMF_8BPP) { // Allocate our palette: ppal = EngAllocMem(FL_ZERO_MEMORY, sizeof(PALETTEENTRY) * 256, 'zzzG'); if (ppal == NULL) goto ReturnFalse; pgdev->pPal = ppal; // Create handle for palette. hpal = EngCreatePalette(PAL_INDEXED, 256, (ULONG*) ppal, 0, 0, 0); } else { ASSERTGDI((pgdev->iBitmapFormat == BMF_16BPP) || (pgdev->iBitmapFormat == BMF_24BPP) || (pgdev->iBitmapFormat == BMF_32BPP), "This case handles only 16, 24 or 32bpp"); hpal = EngCreatePalette(PAL_BITFIELDS, 0, NULL, pgdev->flRed, pgdev->flGreen, pgdev->flBlue); } pgdev->hpalDefault = hpal; pdi->hpalDefault = hpal; if (hpal == 0) goto ReturnFalse; return(TRUE); ReturnFalse: WARNING("Failed bInitializePalette"); return(FALSE); } /******************************Public*Routine******************************\ * VOID vGpsUninitializePalette * * Frees resources allocated by bInitializePalette. * * Note: In an error case, this may be called before bInitializePalette. * \**************************************************************************/ VOID vGpsUninitializePalette(GDEV* gpdev) { // Delete the default palette if we created one: if (gpdev->hpalDefault != 0) EngDeletePalette(gpdev->hpalDefault); if (gpdev->pPal != (PALETTEENTRY*) NULL) EngFreeMem(gpdev->pPal); } /******************************Public*Routine******************************\ * GpsDisablePDEV * \**************************************************************************/ VOID GpsDisablePDEV( DHPDEV dhpdev) { GDEV* pgdev; pgdev = (GDEV*) dhpdev; vGpsUninitializePalette(pgdev); vGpsUninitializeDirectDraw(pgdev); VFREEMEM(pgdev); } /******************************Public*Routine******************************\ * DHPDEV GpsEnablePDEV * \**************************************************************************/ DHPDEV GpsEnablePDEV( DEVMODEW* pdm, PWSTR pwszLogAddr, ULONG cPat, HSURF* phsurfPatterns, ULONG cjCaps, ULONG* pdevcaps, ULONG cjDevInfo, DEVINFO* pdi, HDEV hdev, PWSTR pwszDeviceName, HANDLE hDriver) { GDEV* pgdev; HWND hwnd; ULONG BitsPerPlane; ULONG RedMask; ULONG GreenMask; ULONG BlueMask; ULONG ScreenWidth; ULONG ScreenHeight; pgdev = PALLOCMEM(sizeof(GDEV), 'zzzG'); if (pgdev == NULL) { goto ReturnFailure0; } hwnd = (HWND) pdm; if (!bGpsInitializeDirectDraw(pgdev, hwnd, &ScreenWidth, &ScreenHeight, &BitsPerPlane, &RedMask, &GreenMask, &BlueMask)) { goto ReturnFailure0; } if (!bGpsInitializeModeFields(pgdev, &ScreenWidth, &ScreenHeight, &BitsPerPlane, &RedMask, &GreenMask, &BlueMask, (GDIINFO*) pdevcaps, pdi)) { goto ReturnFailure0; } if (!bGpsInitializePalette(pgdev, pdi)) { goto ReturnFailure1; } return((DHPDEV) pgdev); ReturnFailure1: GpsDisablePDEV((DHPDEV) pgdev); ReturnFailure0: return(0); } /******************************Public*Routine******************************\ * VOID GpsCompletePDEV * \**************************************************************************/ VOID GpsCompletePDEV( DHPDEV dhpdev, HDEV hdev) { ((GDEV*) dhpdev)->hdev = hdev; } /******************************Public*Routine******************************\ * VOID GpsDisableSurface * \**************************************************************************/ VOID GpsDisableSurface( DHPDEV dhpdev) { GDEV* pgdev; pgdev = (GDEV*) dhpdev; EngDeleteSurface(pgdev->hsurfScreen); } /******************************Public*Routine******************************\ * HSURF GpsEnableSurface * \**************************************************************************/ HSURF GpsEnableSurface( DHPDEV dhpdev) { HSURF hsurf; GDEV* pgdev; pgdev = (GDEV*) dhpdev; hsurf = EngCreateDeviceSurface(NULL, pgdev->sizlScreen, pgdev->iBitmapFormat); if (hsurf == 0) { goto ReturnFailure; } // Associate surface with a physical device now if (!EngAssociateSurface(hsurf, pgdev->hdev, HOOK_BITBLT | HOOK_COPYBITS | HOOK_STROKEPATH | HOOK_TEXTOUT)) { goto ReturnFailure; } pgdev->hsurfScreen = hsurf; // Remember it for clean-up return(hsurf); ReturnFailure: GpsDisableSurface((DHPDEV) pgdev); return(0); } /******************************Public*Routine******************************\ * VOID vGpsWindowOffset * * Hack function to account for the window offset. * \**************************************************************************/ VOID vGpsWindowOffset( GDEV* pgdev, RECTL* prcl, RECT* prc) { RECT rcWindow; GetWindowRect(pgdev->hwnd, &rcWindow); prc->left = rcWindow.left + prcl->left; prc->right = rcWindow.left + prcl->right; prc->top = rcWindow.top + prcl->top; prc->bottom = rcWindow.top + prcl->bottom; } /******************************Public*Routine******************************\ * BOOL GpsCopyBits * \**************************************************************************/ BOOL GpsCopyBits( SURFOBJ *psoDst, SURFOBJ *psoSrc, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclDst, POINTL *pptlSrc) { GDEV* pgdev; RECTL rclSrc; HRESULT hr; RECT rcWindow; RECT rcSrc; rclSrc.left = pptlSrc->x; rclSrc.top = pptlSrc->y; rclSrc.right = pptlSrc->x + (prclDst->right - prclDst->left); rclSrc.bottom = pptlSrc->y + (prclDst->bottom - prclDst->top); if (psoSrc->dhpdev == NULL) { // DIB-to-screen: pgdev = (GDEV*) psoDst->dhpdev; vGpsWindowOffset(pgdev, prclDst, &rcWindow); if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL)) { // Read in a copy of the destination bits in order to handle // complex clipping because we're going to write everything // back out: Repeat1: hr = pgdev->lpDDBuffer->lpVtbl->Blt(pgdev->lpDDBuffer, (RECT*) prclDst, pgdev->lpDDPrimary, &rcWindow, DDBLT_WAIT, NULL); if (hr == DDERR_SURFACELOST) { DbgPrint("Lost!\n"); pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary); goto Repeat1; } } EngCopyBits(pgdev->psoBuffer, psoSrc, pco, pxlo, prclDst, pptlSrc); Repeat2: hr = pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary, &rcWindow, pgdev->lpDDBuffer, (RECT*) prclDst, DDBLT_WAIT, NULL); if (hr == DDERR_SURFACELOST) { DbgPrint("Lost2\n"); pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary); goto Repeat2; } } else if (psoDst->dhpdev == NULL) { // Screen-to-DIB: pgdev = (GDEV*) psoSrc->dhpdev; vGpsWindowOffset(pgdev, &rclSrc, &rcWindow); pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDBuffer, (RECT*) &rclSrc, pgdev->lpDDPrimary, &rcWindow, DDBLT_WAIT, NULL); EngCopyBits(psoDst, pgdev->psoBuffer, pco, pxlo, prclDst, pptlSrc); } else { // Screen-to-screen: pgdev = (GDEV*) psoDst->dhpdev; vGpsWindowOffset(pgdev, prclDst, &rcWindow); vGpsWindowOffset(pgdev, &rclSrc, &rcSrc); pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary, &rcWindow, pgdev->lpDDPrimary, &rcSrc, DDBLT_WAIT, NULL); } return(TRUE); } /******************************Public*Routine******************************\ * BOOL GpsBitBlt * * An 's' is appended to this function name so that we don't conflict * with 'GpsBitBlt' exported from gdiplus.dll. * \**************************************************************************/ BOOL GpsBitBlt( SURFOBJ* psoDst, SURFOBJ* psoSrc, SURFOBJ* psoMsk, CLIPOBJ* pco, XLATEOBJ* pxlo, RECTL* prclDst, POINTL* pptlSrc, POINTL* pptlMsk, BRUSHOBJ* pbo, POINTL* pptlBrush, ROP4 rop4) { GDEV* pgdev; HRESULT hr; RECT rcWindow; if (psoSrc == NULL) { // Patblt to screen: pgdev = (GDEV*) psoDst->dhpdev; vGpsWindowOffset(pgdev, prclDst, &rcWindow); if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL)) { // Read in a copy of the destination bits in order to handle // complex clipping because we're going to write everything // back out: Repeat1: hr = pgdev->lpDDBuffer->lpVtbl->Blt(pgdev->lpDDBuffer, (RECT*) prclDst, pgdev->lpDDPrimary, &rcWindow, DDBLT_WAIT, NULL); if (hr == DDERR_SURFACELOST) { DbgPrint("Lost!\n"); pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary); goto Repeat1; } } EngBitBlt(pgdev->psoBuffer, psoSrc, psoMsk, pco, pxlo, prclDst, pptlSrc, pptlMsk, pbo, pptlBrush, rop4); Repeat2: hr = pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary, &rcWindow, pgdev->lpDDBuffer, (RECT*) prclDst, DDBLT_WAIT, NULL); if (hr == DDERR_SURFACELOST) { DbgPrint("Lost2\n"); pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary); goto Repeat2; } return(TRUE); } else { return(EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, prclDst, pptlSrc, pptlMsk, pbo, pptlBrush, rop4)); } } /******************************Public*Routine******************************\ * BOOL GpsStrokePath * \**************************************************************************/ BOOL GpsStrokePath( SURFOBJ* pso, PATHOBJ* ppo, CLIPOBJ* pco, XFORMOBJ* pxlo, BRUSHOBJ* pbo, POINTL* pptlBrush, LINEATTRS* pla, MIX mix) { GDEV* pgdev; HRESULT hr; RECT rcWindow; Repeat1: pgdev = (GDEV*) pso->dhpdev; vGpsWindowOffset(pgdev, &pco->rclBounds, &rcWindow); hr = pgdev->lpDDBuffer->lpVtbl->Blt(pgdev->lpDDBuffer, (RECT*) &pco->rclBounds, pgdev->lpDDPrimary, &rcWindow, DDBLT_WAIT, NULL); if (hr == DDERR_SURFACELOST) { DbgPrint("Lost!\n"); pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary); goto Repeat1; } EngStrokePath(pgdev->psoBuffer, ppo, pco, pxlo, pbo, pptlBrush, pla, mix); hr = pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary, &rcWindow, pgdev->lpDDBuffer, (RECT*) &pco->rclBounds, DDBLT_WAIT, NULL); return(TRUE); } /******************************Public*Routine******************************\ * BOOL GpsTextOut * \**************************************************************************/ BOOL GpsTextOut( SURFOBJ* pso, STROBJ* pstro, FONTOBJ* pfo, CLIPOBJ* pco, RECTL* prclExtra, RECTL* prclOpaque, BRUSHOBJ* pboFore, BRUSHOBJ* pboOpaque, POINTL* pptlOrg, MIX mix) { GDEV* pgdev; HRESULT hr; RECT rcWindow; RECTL* prclDraw; Repeat1: pgdev = (GDEV*) pso->dhpdev; prclDraw = (prclOpaque != NULL) ? prclOpaque : &pstro->rclBkGround; vGpsWindowOffset(pgdev, prclDraw, &rcWindow); hr = pgdev->lpDDBuffer->lpVtbl->Blt(pgdev->lpDDBuffer, (RECT*) prclDraw, pgdev->lpDDPrimary, &rcWindow, DDBLT_WAIT, NULL); if (hr == DDERR_SURFACELOST) { DbgPrint("Lost!\n"); pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary); goto Repeat1; } EngTextOut(pgdev->psoBuffer, pstro, pfo, pco, prclExtra, prclOpaque, pboFore, pboOpaque, pptlOrg, mix); hr = pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary, &rcWindow, pgdev->lpDDBuffer, (RECT*) prclDraw, DDBLT_WAIT, NULL); return(TRUE); } /******************************Public*Structure****************************\ * DFVFN gadrvfnGdiPlus[] * \**************************************************************************/ DRVFN gadrvfnGdiPlus[] = { { INDEX_DrvEnablePDEV, (PFN) GpsEnablePDEV }, { INDEX_DrvCompletePDEV, (PFN) GpsCompletePDEV }, { INDEX_DrvDisablePDEV, (PFN) GpsDisablePDEV }, { INDEX_DrvEnableSurface, (PFN) GpsEnableSurface }, { INDEX_DrvDisableSurface, (PFN) GpsDisableSurface }, { INDEX_DrvCopyBits, (PFN) GpsCopyBits }, { INDEX_DrvBitBlt, (PFN) GpsBitBlt }, { INDEX_DrvStrokePath, (PFN) GpsStrokePath }, { INDEX_DrvTextOut, (PFN) GpsTextOut }, }; ULONG gcdrvfnGdiPlus = sizeof(gadrvfnGdiPlus) / sizeof(DRVFN); /******************************Public*Routine******************************\ * BOOL GpsEnableDriver * \**************************************************************************/ BOOL GpsEnableDriver( ULONG iEngineVersion, ULONG cj, DRVENABLEDATA* pded) { pded->pdrvfn = gadrvfnGdiPlus; pded->c = gcdrvfnGdiPlus; pded->iDriverVersion = DDI_DRIVER_VERSION; return(TRUE); }