https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d57f7becc3f320408008649fa21c86926d9d16b6

commit d57f7becc3f320408008649fa21c86926d9d16b6
Author:     James Tabor <[email protected]>
AuthorDate: Fri Mar 8 22:21:41 2019 -0600
Commit:     James Tabor <[email protected]>
CommitDate: Fri Mar 8 22:21:41 2019 -0600

    [Win32SS] Add TextOut to GDI Batch
    
    Add fix ups to PolyPatBlt and freetype.
    TextOut supports 580 characters w/o Dx and Dx at a max of 193 characters
    with Dx*1, both if offset is 0.
    
    Noticed a lot of over drawing with start menu from ComCtl32 SB_SETTEXT
    going through User32 DrawText/Worker ExtTextOutW. Explain why it might
    be slowing down.
    
    If issues arise, commenting out lines in win32ss/include/gdi32p.h can
    help.
    
    Example:
    else if (Cmd == GdiBCTextOut) cjSize = 0;//sizeof(GDIBSTEXTOUT); <----
    this one most of all.
     else if (Cmd == GdiBCExtTextOut) cjSize = 0;//sizeof(GDIBSEXTTEXTOUT);
    
    Test results:
    https://reactos.org/testman/compare.php?ids=66260,66262
---
 win32ss/gdi/gdi32/include/gdi32p.h   |   4 +-
 win32ss/gdi/gdi32/objects/painting.c |  11 ++-
 win32ss/gdi/gdi32/objects/text.c     |  97 ++++++++++++++++++++++
 win32ss/gdi/ntgdi/freetype.c         |   2 +-
 win32ss/gdi/ntgdi/gdibatch.c         | 155 +++++++++++++++++++++++++++++++----
 win32ss/include/ntgdityp.h           |  10 ++-
 6 files changed, 255 insertions(+), 24 deletions(-)

diff --git a/win32ss/gdi/gdi32/include/gdi32p.h 
b/win32ss/gdi/gdi32/include/gdi32p.h
index 67d3a68dbf..f0b4cb46d9 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 efc987e6cb..8fc0d645c3 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 1242020639..9ff4fde9df 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 197304d469..7005057a07 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 3c7d6c2ad0..13d6ad9088 100644
--- a/win32ss/gdi/ntgdi/gdibatch.c
+++ b/win32ss/gdi/ntgdi/gdibatch.c
@@ -5,6 +5,8 @@
 #include <debug.h>
 
 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 4bf8aa92fa..99eed15cc9 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

Reply via email to