diff --git a/win32ss/gdi/gdi32/include/gdi32p.h b/win32ss/gdi/gdi32/include/gdi32p.h index 67d3a68dbff..f0b4cb46d93 100644 --- a/win32ss/gdi/gdi32/include/gdi32p.h +++ b/win32ss/gdi/gdi32/include/gdi32p.h @@ -390,8 +390,8 @@ GdiAllocBatchCommand( /* Get the size of the entry */ if (Cmd == GdiBCPatBlt) cjSize = sizeof(GDIBSPATBLT); else if (Cmd == GdiBCPolyPatBlt) cjSize = sizeof(GDIBSPPATBLT); - else if (Cmd == GdiBCTextOut) cjSize = 0; - else if (Cmd == GdiBCExtTextOut) cjSize = 0; + else if (Cmd == GdiBCTextOut) cjSize = sizeof(GDIBSTEXTOUT); + else if (Cmd == GdiBCExtTextOut) cjSize = sizeof(GDIBSEXTTEXTOUT); else if (Cmd == GdiBCSetBrushOrg) cjSize = sizeof(GDIBSSETBRHORG); else if (Cmd == GdiBCExtSelClipRgn) cjSize = 0; else if (Cmd == GdiBCSelObj) cjSize = sizeof(GDIBSOBJECT); diff --git a/win32ss/gdi/gdi32/objects/painting.c b/win32ss/gdi/gdi32/objects/painting.c index efc987e6cba..8fc0d645c3b 100644 --- a/win32ss/gdi/gdi32/objects/painting.c +++ b/win32ss/gdi/gdi32/objects/painting.c @@ -548,7 +548,8 @@ PolyPatBlt( pgO = GdiAllocBatchCommand(hdc, GdiBCPolyPatBlt); if (pgO) { - USHORT cjSize = sizeof(GDIBSPPATBLT) + (nCount-1) * sizeof(PATRECT); + USHORT cjSize = 0; + if (nCount > 1) cjSize = (nCount-1) * sizeof(PATRECT); if ((pTeb->GdiTebBatch.Offset + cjSize) <= GDIBATCHBUFSIZE) { @@ -563,10 +564,14 @@ PolyPatBlt( pgO->ulBackgroundClr = pdcattr->ulBackgroundClr; pgO->ulBrushClr = pdcattr->ulBrushClr; RtlCopyMemory(pgO->pRect, pPoly, nCount * sizeof(PATRECT)); - // Recompute offset, remember one is already accounted for in the structure. - pTeb->GdiTebBatch.Offset += (nCount-1) * sizeof(PATRECT); + // Recompute offset and return size, remember one is already accounted for in the structure. + pTeb->GdiTebBatch.Offset += cjSize; + ((PGDIBATCHHDR)pgO)->Size += cjSize; return TRUE; } + // Reset offset and count then fall through + pTeb->GdiTebBatch.Offset -= sizeof(GDIBSPPATBLT); + pTeb->GdiBatchCount--; } } return NtGdiPolyPatBlt(hdc, dwRop, pPoly, nCount, dwMode); diff --git a/win32ss/gdi/gdi32/objects/text.c b/win32ss/gdi/gdi32/objects/text.c index 1242020639e..9ff4fde9dff 100644 --- a/win32ss/gdi/gdi32/objects/text.c +++ b/win32ss/gdi/gdi32/objects/text.c @@ -488,6 +488,8 @@ ExtTextOutW( _In_ UINT cwc, _In_reads_opt_(cwc) const INT *lpDx) { + PDC_ATTR pdcattr; + HANDLE_METADC(BOOL, ExtTextOut, FALSE, @@ -506,6 +508,101 @@ ExtTextOutW( return LpkExtTextOut(hdc, x, y, fuOptions, lprc, lpString, cwc , lpDx, 0); } + /* Get the DC attribute */ + pdcattr = GdiGetDcAttr(hdc); + if ( pdcattr && + !(pdcattr->ulDirty_ & DC_DIBSECTION) && + !(pdcattr->lTextAlign & TA_UPDATECP)) + { + if ( lprc && !cwc ) + { + if ( fuOptions & ETO_OPAQUE ) + { + PGDIBSEXTTEXTOUT pgO; + + pgO = GdiAllocBatchCommand(hdc, GdiBCExtTextOut); + if (pgO) + { + pgO->Count = cwc; + pgO->Rect = *lprc; + pgO->Options = fuOptions; + /* Snapshot attribute */ + pgO->ulBackgroundClr = pdcattr->ulBackgroundClr; + pgO->ptlViewportOrg = pdcattr->ptlViewportOrg; + return TRUE; + } + } + else // Do nothing, old explorer pops this off. + { + DPRINT1("GdiBCExtTextOut nothing\n"); + return TRUE; + } + } // Max 580 wchars, if offset 0 + else if ( cwc <= ((GDIBATCHBUFSIZE - sizeof(GDIBSTEXTOUT)) / sizeof(WCHAR)) ) + { + PGDIBSTEXTOUT pgO; + PTEB pTeb = NtCurrentTeb(); + + pgO = GdiAllocBatchCommand(hdc, GdiBCTextOut); + if (pgO) + { + USHORT cjSize = 0; + ULONG DxSize = 0; + + if (cwc > 2) cjSize = (cwc * sizeof(WCHAR)) - sizeof(pgO->String); + + /* Calculate buffer size for string and Dx values */ + if (lpDx) + { + /* If ETO_PDY is specified, we have pairs of INTs */ + DxSize = (cwc * sizeof(INT)) * (fuOptions & ETO_PDY ? 2 : 1); + cjSize += DxSize; + // The structure buffer holds 4 bytes. Store Dx data then string. + // Result one wchar -> Buf[ Dx ]Str[wC], [4][2][X] one extra unused wchar + // to assure alignment of 4. + } + + if ((pTeb->GdiTebBatch.Offset + cjSize ) <= GDIBATCHBUFSIZE) + { + pgO->cbCount = cwc; + pgO->x = x; + pgO->y = y; + pgO->Options = fuOptions; + pgO->iCS_CP = 0; + + if (lprc) pgO->Rect = *lprc; + else + { + pgO->Options |= GDIBS_NORECT; // Tell the other side lprc is nill. + } + + /* Snapshot attributes */ + pgO->crForegroundClr = pdcattr->crForegroundClr; + pgO->crBackgroundClr = pdcattr->crBackgroundClr; + pgO->ulForegroundClr = pdcattr->ulForegroundClr; + pgO->ulBackgroundClr = pdcattr->ulBackgroundClr; + pgO->lBkMode = pdcattr->lBkMode == OPAQUE ? OPAQUE : TRANSPARENT; + pgO->hlfntNew = pdcattr->hlfntNew; + pgO->flTextAlign = pdcattr->flTextAlign; + pgO->ptlViewportOrg = pdcattr->ptlViewportOrg; + + pgO->Size = DxSize; // of lpDx then string after. + /* Put the Dx before the String to assure alignment of 4 */ + if (lpDx) RtlCopyMemory( &pgO->Buffer, lpDx, DxSize); + + if (cwc) RtlCopyMemory( &pgO->String[DxSize/sizeof(WCHAR)], lpString, cwc * sizeof(WCHAR)); + + // Recompute offset and return size + pTeb->GdiTebBatch.Offset += cjSize; + ((PGDIBATCHHDR)pgO)->Size += cjSize; + return TRUE; + } + // Reset offset and count then fall through + pTeb->GdiTebBatch.Offset -= sizeof(GDIBSTEXTOUT); + pTeb->GdiBatchCount--; + } + } + } return NtGdiExtTextOutW(hdc, x, y, diff --git a/win32ss/gdi/ntgdi/freetype.c b/win32ss/gdi/ntgdi/freetype.c index 197304d469d..7005057a077 100644 --- a/win32ss/gdi/ntgdi/freetype.c +++ b/win32ss/gdi/ntgdi/freetype.c @@ -5814,7 +5814,7 @@ IntExtTextOutW( if ((fuOptions & ETO_OPAQUE) && (dc->pdcattr->ulDirty_ & DIRTY_BACKGROUND)) DC_vUpdateBackgroundBrush(dc) ; - if(dc->pdcattr->ulDirty_ & DIRTY_TEXT) + if (dc->pdcattr->ulDirty_ & DIRTY_TEXT) DC_vUpdateTextBrush(dc) ; thickness = 1; diff --git a/win32ss/gdi/ntgdi/gdibatch.c b/win32ss/gdi/ntgdi/gdibatch.c index 3c7d6c2ad00..13d6ad90880 100644 --- a/win32ss/gdi/ntgdi/gdibatch.c +++ b/win32ss/gdi/ntgdi/gdibatch.c @@ -5,6 +5,8 @@ #include BOOL FASTCALL IntPatBlt( PDC,INT,INT,INT,INT,DWORD,PEBRUSHOBJ); +BOOL APIENTRY IntExtTextOutW(IN PDC,IN INT,IN INT,IN UINT,IN OPTIONAL PRECTL,IN LPCWSTR,IN INT,IN OPTIONAL LPINT,IN DWORD); + // // Gdi Batch Flush support functions. @@ -40,7 +42,7 @@ DoDeviceSync( SURFOBJ *Surface, PRECTL Rect, FLONG fl) VOID FASTCALL -SynchonizeDriver(FLONG Flags) +SynchronizeDriver(FLONG Flags) { SURFOBJ *SurfObj; //PPDEVOBJ Device; @@ -130,7 +132,7 @@ GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr) dc->pdcattr->ulForegroundClr = pgDPB->ulForegroundClr; dc->pdcattr->ulBackgroundClr = pgDPB->ulBackgroundClr; dc->pdcattr->ulBrushClr = pgDPB->ulBrushClr; - // Process dirty attributes if any + // Process dirty attributes if any. if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); if (dc->pdcattr->ulDirty_ & DIRTY_TEXT) @@ -157,7 +159,7 @@ GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr) EBRUSHOBJ eboFill; PBRUSH pbrush; PPATRECT pRects; - INT cRects, i; + INT i; DWORD dwRop, flags; COLORREF crColor, crBkColor, crBrushClr; ULONG ulForegroundClr, ulBackgroundClr, ulBrushClr; @@ -200,10 +202,9 @@ GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr) DC_vUpdateBackgroundBrush(dc); DPRINT1("GdiBCPolyPatBlt Testing\n"); - pRects = pgDPB->pRect; - cRects = pgDPB->Count; + pRects = &pgDPB->pRect[0]; - for (i = 0; i < cRects; i++) + for (i = 0; i < pgDPB->Count; i++) { pbrush = BRUSH_ShareLockBrush(pRects->hBrush); @@ -238,21 +239,141 @@ GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr) dc->pdcattr->ulBrushClr = ulBrushClr; dc->pdcattr->ulDirty_ |= flags; break; - } + } + case GdiBCTextOut: + { + PGDIBSTEXTOUT pgO; + COLORREF crColor = -1, crBkColor; + ULONG ulForegroundClr, ulBackgroundClr; + DWORD flags = 0, saveflags; + FLONG flTextAlign = -1; + HANDLE hlfntNew; + PRECTL lprc; + USHORT jBkMode; + LONG lBkMode; + if (!dc) break; + pgO = (PGDIBSTEXTOUT) pHdr; + + // Save current attributes, flags and Set the attribute snapshots + saveflags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_TEXT|DIRTY_FILL|DC_BRUSH_DIRTY|DIRTY_CHARSET); + + // In this instance check for differences and set the appropriate dirty flags. + if ( dc->pdcattr->crForegroundClr != pgO->crForegroundClr) + { + crColor = dc->pdcattr->crForegroundClr; + dc->pdcattr->crForegroundClr = pgO->crForegroundClr; + ulForegroundClr = dc->pdcattr->ulForegroundClr; + dc->pdcattr->ulForegroundClr = pgO->ulForegroundClr; + flags |= (DIRTY_FILL|DIRTY_LINE|DIRTY_TEXT); + } + if (dc->pdcattr->crBackgroundClr != pgO->crBackgroundClr) + { + crBkColor = dc->pdcattr->ulBackgroundClr; + dc->pdcattr->crBackgroundClr = pgO->crBackgroundClr; + ulBackgroundClr = dc->pdcattr->ulBackgroundClr; + dc->pdcattr->ulBackgroundClr = pgO->ulBackgroundClr; + flags |= (DIRTY_FILL|DIRTY_LINE|DIRTY_TEXT|DIRTY_BACKGROUND); + } + if (dc->pdcattr->flTextAlign != pgO->flTextAlign) + { + flTextAlign = dc->pdcattr->flTextAlign; + dc->pdcattr->flTextAlign = pgO->flTextAlign; + } + if (dc->pdcattr->hlfntNew != pgO->hlfntNew) + { + hlfntNew = dc->pdcattr->hlfntNew; + dc->pdcattr->hlfntNew = pgO->hlfntNew; + dc->pdcattr->ulDirty_ &= ~SLOW_WIDTHS; + flags |= DIRTY_CHARSET; + } + + dc->pdcattr->ulDirty_ |= flags; + + jBkMode = dc->pdcattr->jBkMode; + dc->pdcattr->jBkMode = pgO->lBkMode; + lBkMode = dc->pdcattr->lBkMode; + dc->pdcattr->lBkMode = pgO->lBkMode; + + lprc = (pgO->Options & GDIBS_NORECT) ? NULL : &pgO->Rect; + pgO->Options &= ~GDIBS_NORECT; + + IntExtTextOutW( dc, + pgO->x, + pgO->y, + pgO->Options, + lprc, + (LPCWSTR)&pgO->String[pgO->Size/sizeof(WCHAR)], + pgO->cbCount, + pgO->Size ? (LPINT)&pgO->Buffer : NULL, + pgO->iCS_CP ); + + // Restore attributes and flags + dc->pdcattr->jBkMode = jBkMode; + dc->pdcattr->lBkMode = lBkMode; + + if (flags & DIRTY_TEXT && crColor != -1) + { + dc->pdcattr->crForegroundClr = crColor; + dc->pdcattr->ulForegroundClr = ulForegroundClr; + } + if (flags & DIRTY_BACKGROUND) + { + dc->pdcattr->crBackgroundClr = crBkColor; + dc->pdcattr->ulBackgroundClr = ulBackgroundClr; + } + if (flTextAlign != -1) + { + dc->pdcattr->flTextAlign = flTextAlign; + } + + if (flags & DIRTY_CHARSET) + { + dc->pdcattr->hlfntNew = hlfntNew; + dc->pdcattr->ulDirty_ &= ~SLOW_WIDTHS; + } + dc->pdcattr->ulDirty_ |= saveflags | flags; break; + } case GdiBCExtTextOut: { - //GreExtTextOutW( hDC, - // XStart, - // YStart, - // fuOptions, - // &SafeRect, - // SafeString, - // Count, - // SafeDx, - // dwCodePage ); + PGDIBSEXTTEXTOUT pgO; + COLORREF crBkColor; + ULONG ulBackgroundClr; + DWORD flags = 0, saveflags; + if (!dc) break; + pgO = (PGDIBSEXTTEXTOUT) pHdr; + + saveflags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_FILL|DC_BRUSH_DIRTY|DIRTY_CHARSET); + + if (dc->pdcattr->crBackgroundClr != pgO->ulBackgroundClr) + { + crBkColor = dc->pdcattr->crBackgroundClr; + ulBackgroundClr = dc->pdcattr->ulBackgroundClr; + dc->pdcattr->crBackgroundClr = pgO->ulBackgroundClr; + dc->pdcattr->ulBackgroundClr = pgO->ulBackgroundClr; + flags |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL); + } + + dc->pdcattr->ulDirty_ |= flags; + + IntExtTextOutW( dc, + 0, + 0, + pgO->Options, + &pgO->Rect, + NULL, + pgO->Count, + NULL, + 0 ); + + if (flags & DIRTY_BACKGROUND) + { + dc->pdcattr->crBackgroundClr = crBkColor; + dc->pdcattr->ulBackgroundClr = ulBackgroundClr; + } + dc->pdcattr->ulDirty_ |= saveflags | flags; break; } @@ -308,7 +429,7 @@ APIENTRY NtGdiFlush( VOID) { - SynchonizeDriver(GCAPS2_SYNCFLUSH); + SynchronizeDriver(GCAPS2_SYNCFLUSH); return STATUS_SUCCESS; } diff --git a/win32ss/include/ntgdityp.h b/win32ss/include/ntgdityp.h index 4bf8aa92fae..99eed15cc92 100644 --- a/win32ss/include/ntgdityp.h +++ b/win32ss/include/ntgdityp.h @@ -495,12 +495,17 @@ typedef struct _GDIBSPPATBLT PATRECT pRect[1]; // POLYPATBLT } GDIBSPPATBLT, *PGDIBSPPATBLT; +// +// Both ExtSelectClipRgn and TextOut pass a nill RECT. +// +#define GDIBS_NORECT 0x80000000 + typedef struct _GDIBSTEXTOUT { GDIBATCHHDR gbHdr; COLORREF crForegroundClr; COLORREF crBackgroundClr; - LONG lmBkMode; + LONG lBkMode; ULONG ulForegroundClr; ULONG ulBackgroundClr; int x; @@ -513,7 +518,10 @@ typedef struct _GDIBSTEXTOUT HANDLE hlfntNew; FLONG flTextAlign; POINTL ptlViewportOrg; + union { WCHAR String[2]; + ULONG Buffer[1]; + }; } GDIBSTEXTOUT, *PGDIBSTEXTOUT; typedef struct _GDIBSEXTTEXTOUT