|
|
/****************************************************************************/ // odint.cpp
//
// Order Decoder internal functions.
//
// Copyright (c) 1997-2000 Microsoft Corp.
// Portions copyright (c) 1992-1997 Microsoft, PictureTel
/****************************************************************************/
#include <adcg.h>
extern "C" { #define TRC_GROUP TRC_GROUP_CORE
#define TRC_FILE "aodint"
#include <atrcapi.h>
} #define TSC_HR_FILEID TSC_HR_ODINT_CPP
#include "od.h"
#include "cc.h"
#include "bbar.h"
// WinCE does not define BS_HATCHED for their wingdi.h
#ifdef OS_WINCE
#define BS_HATCHED 2
#endif
#define OD_DECODE_CHECK_READ( p, type, pEnd, hr ) \
CHECK_READ_N_BYTES(p, pEnd, sizeof(type), hr, \ ( TB, _T("Read past data end")))
#define OD_DECODE_CHECK_READ_MULT( p, type, mult, pEnd, hr ) \
CHECK_READ_N_BYTES(p, pEnd, (mult) * sizeof(type), hr, \ ( TB, _T("Read past data end")))
#define OD_DECODE_CHECK_VARIABLE_DATALEN( have, required ) \
if( have < required ) { \ TRC_ABORT((TB,_T("Slowpath decode varaible data len ") \ _T("[required=%u got=%u]"), required, have )); \ hr = E_TSC_CORE_LENGTH; \ DC_QUIT; \ }
/****************************************************************************/ // ODDecodeOpaqueRect
//
// Fast-path decode function for OpaqueRect (most common order [57%] in
// WinBench99).
/****************************************************************************/ HRESULT DCINTERNAL COD::ODDecodeOpaqueRect( BYTE ControlFlags, BYTE FAR * FAR *ppFieldDecode, DCUINT dataLen, UINT32 FieldFlags) { HRESULT hr = S_OK; PUH_ORDER pUHHdr = (PUH_ORDER)_OD.lastOpaqueRect; OPAQUERECT_ORDER FAR *pOR = (OPAQUERECT_ORDER FAR *) (_OD.lastOpaqueRect + UH_ORDER_HEADER_SIZE); BYTE FAR *pFieldDecode = *ppFieldDecode; BYTE FAR *pEnd = pFieldDecode + dataLen;
DC_BEGIN_FN("ODDecodeOpaqueRect");
if (ControlFlags & TS_DELTA_COORDINATES) { // All coord fields are 1-byte signed deltas from the last values.
if (FieldFlags & 0x01) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pOR->nLeftRect += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x02) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pOR->nTopRect += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x04) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pOR->nWidth += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x08) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pOR->nHeight += *((char FAR *)pFieldDecode); pFieldDecode++; } } else { // All coord fields are 2-byte values.sign-extended from the output.
if (FieldFlags & 0x01) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pOR->nLeftRect = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x02) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pOR->nTopRect = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x04) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pOR->nWidth = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x08) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pOR->nHeight = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } }
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!(ControlFlags & TS_BOUNDS)) { pUHHdr->dstRect.left = (int)pOR->nLeftRect; pUHHdr->dstRect.top = (int)pOR->nTopRect; pUHHdr->dstRect.right = (int)(pOR->nLeftRect + pOR->nWidth - 1); pUHHdr->dstRect.bottom = (int)(pOR->nTopRect + pOR->nHeight - 1); _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pUHHdr->dstRect.left, pUHHdr->dstRect.top, pUHHdr->dstRect.right, pUHHdr->dstRect.bottom); }
// Copy non-coordinate fields if present.
if (FieldFlags & 0x10) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pOR->Color.u.rgb.red = *pFieldDecode++; } if (FieldFlags & 0x20) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pOR->Color.u.rgb.green = *pFieldDecode++; } if (FieldFlags & 0x40) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pOR->Color.u.rgb.blue = *pFieldDecode++; }
// Return the incremented pointer to the main routine.
*ppFieldDecode = pFieldDecode;
#ifdef DC_HICOLOR
TRC_NRM((TB,_T("ORDER: OpaqueRect x(%d) y(%d) w(%d) h(%d) c(%#06lx)"), (int)pOR->nLeftRect, (int)pOR->nTopRect, (int)pOR->nWidth, (int)pOR->nHeight, *((PDCUINT32)&pOR->Color) )); #else
TRC_NRM((TB,_T("ORDER: OpaqueRect x(%d) y(%d) w(%d) h(%d) c(%#02x)"), (int)pOR->nLeftRect, (int)pOR->nTopRect, (int)pOR->nWidth, (int)pOR->nHeight, (int)pOR->Color.u.index)); #endif
// Create a solid brush of the required color. Hard-coded to use
// palette brushes for now because we don't support anything more.
_pUh->UHUseSolidPaletteBrush(pOR->Color);
// Do the blt.
TIMERSTART; PatBlt(_pUh->_UH.hdcDraw, (int)pOR->nLeftRect, (int)pOR->nTopRect, (int)pOR->nWidth, (int)pOR->nHeight, PATCOPY); TIMERSTOP; UPDATECOUNTER(FC_OPAQUERECT_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODDecodeMemBlt
//
// Fast-path decode function for MemBlt (3rd most common order in WinBench99).
/****************************************************************************/ HRESULT DCINTERNAL COD::ODDecodeMemBlt( BYTE ControlFlags, BYTE FAR * FAR *ppFieldDecode, DCUINT dataLen, UINT32 FieldFlags) { HRESULT hr = S_OK; PUH_ORDER pUHHdr = (PUH_ORDER)_OD.lastMembltR2; MEMBLT_R2_ORDER FAR *pMB = (MEMBLT_R2_ORDER FAR *) (_OD.lastMembltR2 + UH_ORDER_HEADER_SIZE); BYTE FAR *pFieldDecode = *ppFieldDecode; BYTE FAR *pEnd = pFieldDecode + dataLen;
DC_BEGIN_FN("ODDecodeMemBlt");
// CacheID is a fixed 2-byte field.
if (FieldFlags & 0x0001) { OD_DECODE_CHECK_READ( pFieldDecode, UINT16, pEnd, hr ); pMB->Common.cacheId = *((UINT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; }
if (ControlFlags & TS_DELTA_COORDINATES) { // All coord fields are 1-byte signed deltas from the last values.
if (FieldFlags & 0x0002) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pMB->Common.nLeftRect += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0004) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pMB->Common.nTopRect += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0008) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pMB->Common.nWidth += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0010) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pMB->Common.nHeight += *((char FAR *)pFieldDecode); pFieldDecode++; }
// bRop is just 1 byte.
if (FieldFlags & 0x0020) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pMB->Common.bRop = *pFieldDecode++; }
if (FieldFlags & 0x0040) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pMB->Common.nXSrc += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0080) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pMB->Common.nYSrc += *((char FAR *)pFieldDecode); pFieldDecode++; } } else { // All coord fields are 2-byte values.sign-extended from the output.
if (FieldFlags & 0x0002) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pMB->Common.nLeftRect = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0004) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pMB->Common.nTopRect = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0008) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pMB->Common.nWidth = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0010) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pMB->Common.nHeight = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; }
// bRop is just 1 byte.
if (FieldFlags & 0x0020) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pMB->Common.bRop = *pFieldDecode++; }
if (FieldFlags & 0x0040) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pMB->Common.nXSrc = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0080) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pMB->Common.nYSrc = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } }
// CacheIndex is always a 2-byte field.
if (FieldFlags & 0x0100) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pMB->Common.cacheIndex = *((UINT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; }
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!(ControlFlags & TS_BOUNDS)) { pUHHdr->dstRect.left = (int)pMB->Common.nLeftRect; pUHHdr->dstRect.top = (int)pMB->Common.nTopRect; pUHHdr->dstRect.right = (int)(pMB->Common.nLeftRect + pMB->Common.nWidth - 1); pUHHdr->dstRect.bottom = (int)(pMB->Common.nTopRect + pMB->Common.nHeight - 1); _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pUHHdr->dstRect.left, pUHHdr->dstRect.top, pUHHdr->dstRect.right, pUHHdr->dstRect.bottom); }
// Return the incremented pointer to the main routine.
*ppFieldDecode = pFieldDecode;
TRC_NRM((TB, _T("ORDER: MemBlt")));
hr = _pUh->UHDrawMemBltOrder(_pUh->_UH.hdcDraw, &pMB->Common); DC_QUIT_ON_FAIL(hr);
#ifdef DC_DEBUG
if (_pUh->_UH.hdcDraw == _pUh->_UH.hdcShadowBitmap || _pUh->_UH.hdcDraw == _pUh->_UH.hdcOutputWindow) { // Draw hatching over the memblt data if the option is enabled.
if (_pUh->_UH.hatchMemBltOrderData) { unsigned cacheId; unsigned cacheEntry;
cacheId = DCLO8(pMB->Common.cacheId); cacheEntry = pMB->Common.cacheIndex;
if (cacheId < _pUh->_UH.NumBitmapCaches && cacheEntry != BITMAPCACHE_WAITING_LIST_INDEX) { if (_pUh->_UH.MonitorEntries[0] != NULL) { _pUh->UH_HatchRect((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect, (int)(pMB->Common.nLeftRect + pMB->Common.nWidth), (int)(pMB->Common.nTopRect + pMB->Common.nHeight), (_pUh->_UH.MonitorEntries[cacheId][cacheEntry].UsageCount == 1) ? UH_RGB_MAGENTA : UH_RGB_BLUE, UH_BRUSHTYPE_FDIAGONAL); } else { _pUh->UH_HatchRect((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect, (int)(pMB->Common.nLeftRect + pMB->Common.nWidth), (int)(pMB->Common.nTopRect + pMB->Common.nHeight), UH_RGB_MAGENTA, UH_BRUSHTYPE_FDIAGONAL); } } } // Label the memblt if the option is enabled.
if (_pUh->_UH.labelMemBltOrders) { unsigned cacheId; unsigned cacheEntry;
cacheId = DCLO8(pMB->Common.cacheId); cacheEntry = pMB->Common.cacheIndex;
if (cacheId < _pUh->_UH.NumBitmapCaches && cacheEntry != BITMAPCACHE_WAITING_LIST_INDEX) { _pUh->UHLabelMemBltOrder((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect, pMB->Common.cacheId, pMB->Common.cacheIndex); } } } #endif /* DC_DEBUG */
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODDecodeLineTo
//
// Fast-path decode function for LineTo (5th most common order in WinBench99).
/****************************************************************************/ HRESULT DCINTERNAL COD::ODDecodeLineTo( BYTE ControlFlags, BYTE FAR * FAR *ppFieldDecode, DCUINT dataLen, UINT32 FieldFlags) { HRESULT hr = S_OK; PUH_ORDER pUHHdr = (PUH_ORDER)_OD.lastLineTo; LINETO_ORDER FAR *pLT = (LINETO_ORDER FAR *) (_OD.lastLineTo + UH_ORDER_HEADER_SIZE); BYTE FAR *pFieldDecode = *ppFieldDecode; BYTE FAR *pEnd = pFieldDecode + dataLen;
DC_BEGIN_FN("ODDecodeLineTo");
// BackMode is always a 2-byte field.
if (FieldFlags & 0x0001) { OD_DECODE_CHECK_READ( pFieldDecode, UINT16, pEnd, hr ); pLT->BackMode = *((UINT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; }
if (ControlFlags & TS_DELTA_COORDINATES) { // All coord fields are 1-byte signed deltas from the last values.
if (FieldFlags & 0x0002) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pLT->nXStart += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0004) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pLT->nYStart += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0008) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pLT->nXEnd += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0010) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pLT->nYEnd += *((char FAR *)pFieldDecode); pFieldDecode++; } } else { // All coord fields are 2-byte values.sign-extended from the output.
if (FieldFlags & 0x0002) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pLT->nXStart = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0004) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pLT->nYStart = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0008) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pLT->nXEnd = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0010) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pLT->nYEnd = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } }
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!(ControlFlags & TS_BOUNDS)) { if (pLT->nXStart < pLT->nXEnd) { pUHHdr->dstRect.left = (int)pLT->nXStart; pUHHdr->dstRect.right = (int)pLT->nXEnd; } else { pUHHdr->dstRect.right = (int)pLT->nXStart; pUHHdr->dstRect.left = (int)pLT->nXEnd; }
if (pLT->nYStart < pLT->nYEnd) { pUHHdr->dstRect.top = (int)pLT->nYStart; pUHHdr->dstRect.bottom = (int)pLT->nYEnd; } else { pUHHdr->dstRect.bottom = (int)pLT->nYStart; pUHHdr->dstRect.top = (int)pLT->nYEnd; }
_pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pUHHdr->dstRect.left, pUHHdr->dstRect.top, pUHHdr->dstRect.right, pUHHdr->dstRect.bottom); }
// Copy non-coordinate fields if present.
if (FieldFlags & 0x0020) { OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 3, pEnd, hr ); pLT->BackColor.u.rgb.red = *pFieldDecode++; pLT->BackColor.u.rgb.green = *pFieldDecode++; pLT->BackColor.u.rgb.blue = *pFieldDecode++; } if (FieldFlags & 0x0040) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pLT->ROP2 = *pFieldDecode++; } if (FieldFlags & 0x0080) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pLT->PenStyle = *pFieldDecode++; } if (FieldFlags & 0x0100) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pLT->PenWidth = *pFieldDecode++; } if (FieldFlags & 0x0200) { OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 3, pEnd, hr ); pLT->PenColor.u.rgb.red = *pFieldDecode++; pLT->PenColor.u.rgb.green = *pFieldDecode++; pLT->PenColor.u.rgb.blue = *pFieldDecode++; }
// Return the incremented pointer to the main routine.
*ppFieldDecode = pFieldDecode;
TRC_NRM((TB,_T("ORDER: LineTo BC %08lX BM %04X rop2 %04X pen ") _T("%04X %04X %08lX x1 %d y1 %d x2 %d y2 %d"), pLT->BackColor, pLT->BackMode, pLT->ROP2, pLT->PenStyle, pLT->PenWidth, pLT->PenColor, pLT->nXStart, pLT->nYStart, pLT->nXEnd, pLT->nYEnd));
UHUseBkColor(pLT->BackColor, UH_COLOR_PALETTE, _pUh); UHUseBkMode((int)pLT->BackMode, _pUh); UHUseROP2((int)pLT->ROP2, _pUh); _pUh->UHUsePen((unsigned)pLT->PenStyle, (unsigned)pLT->PenWidth, pLT->PenColor, UH_COLOR_PALETTE);
TIMERSTART;
#ifdef OS_WINCE
{ POINT pts[2];
pts[0].x = pLT->nXStart; pts[0].y = pLT->nYStart; pts[1].x = pLT->nXEnd; pts[1].y = pLT->nYEnd; Polyline(_pUh->_UH.hdcDraw, pts, 2); } #else
MoveToEx(_pUh->_UH.hdcDraw, (int)pLT->nXStart, (int)pLT->nYStart, NULL); LineTo(_pUh->_UH.hdcDraw, (int)pLT->nXEnd, (int)pLT->nYEnd); #endif // OS_WINCE
TIMERSTOP; UPDATECOUNTER(FC_LINETO_TYPE);
#ifdef DC_ROTTER
#pragma message("ROTTER keystroke return code compiled in")
/****************************************************************/ /* For use with ROund Trip TimER application */ /* */ /* ROTTER runs on the server and initiates a series of drawing */ /* commands to the screen, ending with a specific unusual line */ /* drawing command (from (1,1) and (51,51) with MERGEPENNOT ROP)*/ /* */ /* It then waits until it receives a 't' or 'T' keystroke after */ /* which it calculates the elapsed time between the start of */ /* the drawing and the receipt of the keystroke. This is the */ /* round trip time. */ /* */ /* The following code checks to see whether ROTTER has finished */ /* drawing, by testing all LineTo commands to see if any are 50 */ /* across by 50 down with MERGEPENNOT ROP. We are not able to */ /* simply test that the line's start and endpoints are at (1,1) */ /* and (51,51) because the coordinates that are received by */ /* Ducati depend on the position of ROTTER's window on the */ /* terminal. */ /* */ /* When the special case is detected we post a "T", by */ /* synthesizing a press of the T key and injecting it into the */ /* IH input handler window, which causes IH to send a key-down */ /* key-up sequence for the T key to the server. */ /****************************************************************/ if ((R2_MERGEPENNOT == (pLineTo->ROP2)) && (50 == ((pLineTo->nXEnd) - (pLineTo->nXStart))) && (50 == ((pLineTo->nYEnd) - (pLineTo->nYStart)))) { TRC_ALT((TB,_T("MERGEPENNOT ROP2 detected. Sending 'T'"))); PostMessage(IH_GetInputHandlerWindow(), WM_KEYDOWN, 0x00000054, 0x00140001); PostMessage(IH_GetInputHandlerWindow(), WM_KEYUP, 0x00000054, 0xC0140001); } #endif /* DC_ROTTER */
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODDecodePatBlt
//
// Fast-path decode function for PatBlt.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODDecodePatBlt( BYTE ControlFlags, BYTE FAR * FAR *ppFieldDecode, DCUINT dataLen, UINT32 FieldFlags) { HRESULT hr = S_OK; UINT32 WindowsROP; PUH_ORDER pUHHdr = (PUH_ORDER)_OD.lastPatblt; PATBLT_ORDER FAR *pPB = (PATBLT_ORDER FAR *) (_OD.lastPatblt + UH_ORDER_HEADER_SIZE); BYTE FAR *pFieldDecode = *ppFieldDecode; BYTE FAR *pEnd = pFieldDecode + dataLen;
DC_BEGIN_FN("ODDecodePatBlt");
if (ControlFlags & TS_DELTA_COORDINATES) { // All coord fields are 1-byte signed deltas from the last values.
if (FieldFlags & 0x0001) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pPB->nLeftRect += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0002) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pPB->nTopRect += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0004) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pPB->nWidth += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0008) { OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr ); pPB->nHeight += *((char FAR *)pFieldDecode); pFieldDecode++; } } else { // All coord fields are 2-byte values.sign-extended from the output.
if (FieldFlags & 0x0001) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pPB->nLeftRect = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0002) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pPB->nTopRect = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0004) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pPB->nWidth = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0008) { OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr ); pPB->nHeight = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } }
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!(ControlFlags & TS_BOUNDS)) { pUHHdr->dstRect.left = (int)pPB->nLeftRect; pUHHdr->dstRect.top = (int)pPB->nTopRect; pUHHdr->dstRect.right = (int)(pPB->nLeftRect + pPB->nWidth - 1); pUHHdr->dstRect.bottom = (int)(pPB->nTopRect + pPB->nHeight - 1); _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pUHHdr->dstRect.left, pUHHdr->dstRect.top, pUHHdr->dstRect.right, pUHHdr->dstRect.bottom); }
// Copy non-coordinate fields if present.
if (FieldFlags & 0x0010) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pPB->bRop = *pFieldDecode++; } if (FieldFlags & 0x0020) { OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 3, pEnd, hr ); pPB->BackColor.u.rgb.red = *pFieldDecode++; pPB->BackColor.u.rgb.green = *pFieldDecode++; pPB->BackColor.u.rgb.blue = *pFieldDecode++; } if (FieldFlags & 0x0040) { OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 3, pEnd, hr ); pPB->ForeColor.u.rgb.red = *pFieldDecode++; pPB->ForeColor.u.rgb.green = *pFieldDecode++; pPB->ForeColor.u.rgb.blue = *pFieldDecode++; } if (FieldFlags & 0x0080) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pPB->BrushOrgX = *pFieldDecode++; } if (FieldFlags & 0x0100) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pPB->BrushOrgY = *pFieldDecode++; } if (FieldFlags & 0x0200) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pPB->BrushStyle = *pFieldDecode++; } if (FieldFlags & 0x0400) { OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr ); pPB->BrushHatch = *pFieldDecode++; } if (FieldFlags & 0x0800) { OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 7, pEnd, hr ); memcpy(&pPB->BrushExtra, pFieldDecode, 7); pFieldDecode += 7; }
// Return the incremented pointer to the main routine.
*ppFieldDecode = pFieldDecode;
TRC_NRM((TB, _T("ORDER: PatBlt Brush %02X %02X BC %02x FC %02x ") _T("X %d Y %d w %d h %d rop %08lX"), (int)pPB->BrushStyle, (int)pPB->BrushHatch, (int)pPB->BackColor.u.index, (int)pPB->ForeColor.u.index, (int)pPB->nLeftRect, (int)pPB->nTopRect, (int)pPB->nWidth, (int)pPB->nHeight, _pUh->UHConvertToWindowsROP((unsigned)pPB->bRop)));
// Explicitly use palette entries; we don't support more than that now.
UHUseBkColor(pPB->BackColor, UH_COLOR_PALETTE, _pUh); UHUseTextColor(pPB->ForeColor, UH_COLOR_PALETTE, _pUh); UHUseBrushOrg((int)pPB->BrushOrgX, (int)pPB->BrushOrgY,_pUh); hr = _pUh->UHUseBrush((unsigned)pPB->BrushStyle, (unsigned)pPB->BrushHatch, pPB->ForeColor, UH_COLOR_PALETTE, pPB->BrushExtra); DC_QUIT_ON_FAIL(hr);
WindowsROP = _pUh->UHConvertToWindowsROP((unsigned)pPB->bRop);
TIMERSTART; PatBlt(_pUh->_UH.hdcDraw, (int)pPB->nLeftRect, (int)pPB->nTopRect, (int)pPB->nWidth, (int)pPB->nHeight, WindowsROP); TIMERSTOP; UPDATECOUNTER(FC_PATBLT_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleMultiPatBlt
//
// Handler for MultiPatBlt orders.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleMultiPatBlt(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; unsigned i; UINT32 WindowsROP; RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1]; MULTI_PATBLT_ORDER FAR *pPB = (MULTI_PATBLT_ORDER FAR *)pOrder->orderData;
DC_BEGIN_FN("ODHandleMultiPatBlt");
// If there are no rects, we have nothing to draw. The server in error, or
// a bad server, can send 0 rects. In this case we should simply defend our
// selves
if (0 == pPB->nDeltaEntries) { TRC_ERR((TB,_T("Multipatblt with no rects; uiVarDataLen=%u"), uiVarDataLen)); hr = S_OK; DC_QUIT; }
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = (int)pPB->nLeftRect; pOrder->dstRect.top = (int)pPB->nTopRect; pOrder->dstRect.right = (int)(pPB->nLeftRect + pPB->nWidth - 1); pOrder->dstRect.bottom = (int)(pPB->nTopRect + pPB->nHeight - 1); _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
TRC_NRM((TB, _T("ORDER: PatBlt Brush %02X %02X BC %02x FC %02x ") _T("X %d Y %d w %d h %d rop %08lX"), (int)pPB->BrushStyle, (int)pPB->BrushHatch, (int)pPB->BackColor.u.index, (int)pPB->ForeColor.u.index, (int)pPB->nLeftRect, (int)pPB->nTopRect, (int)pPB->nWidth, (int)pPB->nHeight, _pUh->UHConvertToWindowsROP((unsigned)pPB->bRop)));
// Explicitly use palette entries; we don't support more than that now.
UHUseBkColor(pPB->BackColor, UH_COLOR_PALETTE, _pUh); UHUseTextColor(pPB->ForeColor, UH_COLOR_PALETTE, _pUh);
UHUseBrushOrg((int)pPB->BrushOrgX, (int)pPB->BrushOrgY, _pUh); hr = _pUh->UHUseBrush((unsigned)pPB->BrushStyle, (unsigned)pPB->BrushHatch, pPB->ForeColor, UH_COLOR_PALETTE, pPB->BrushExtra); DC_QUIT_ON_FAIL(hr);
hr = ODDecodeMultipleRects(Rects, pPB->nDeltaEntries, &pPB->codedDeltaList, uiVarDataLen); DC_QUIT_ON_FAIL(hr); WindowsROP = _pUh->UHConvertToWindowsROP((unsigned)pPB->bRop);
TIMERSTART; for (i = 0; i < pPB->nDeltaEntries; i++ ) PatBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top, (int)(Rects[i].right - Rects[i].left), (int)(Rects[i].bottom - Rects[i].top), WindowsROP); TIMERSTOP; UPDATECOUNTER(FC_PATBLT_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleDstBlts
//
// Order handler for both DstBlt and MultiDstBlt.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleDstBlts(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1]; UINT32 WindowsROP; unsigned i; LPDSTBLT_ORDER pDB = (LPDSTBLT_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandleDstBlts");
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = (int)pDB->nLeftRect; pOrder->dstRect.top = (int)pDB->nTopRect; pOrder->dstRect.right = (int)(pDB->nLeftRect + pDB->nWidth - 1); pOrder->dstRect.bottom = (int)(pDB->nTopRect + pDB->nHeight - 1); _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
WindowsROP = _pUh->UHConvertToWindowsROP(pDB->bRop);
if (pDB->type == TS_ENC_DSTBLT_ORDER) { TRC_NRM((TB, _T("ORDER: DstBlt X %d Y %d w %d h %d rop %08lX"), (int)pDB->nLeftRect, (int)pDB->nTopRect, (int)pDB->nWidth, (int)pDB->nHeight, WindowsROP)); TRC_NRM((TB, _T("Single")));
TRC_ASSERT((0==uiVarDataLen), (TB,_T("Recieved varaible length data in fixed length order"))); TIMERSTART; PatBlt(_pUh->_UH.hdcDraw, (int)pDB->nLeftRect, (int)pDB->nTopRect, (int)pDB->nWidth, (int)pDB->nHeight, WindowsROP); TIMERSTOP; UPDATECOUNTER(FC_DSTBLT_TYPE); } else { LPMULTI_DSTBLT_ORDER pMDB = (LPMULTI_DSTBLT_ORDER)pDB; TRC_NRM((TB, _T("ORDER: MultiDstBlt X %d Y %d w %d h %d rop %08lX ") _T("nDeltas %d"), (int)pMDB->nLeftRect, (int)pMDB->nTopRect, (int)pMDB->nWidth, (int)pMDB->nHeight, WindowsROP, pMDB->nDeltaEntries));
if (0 == pMDB->nDeltaEntries) { TRC_ERR((TB,_T("MultiDstBlt with no rects; uiVarDataLen=%u"), uiVarDataLen)); hr = S_OK; DC_QUIT; } hr = ODDecodeMultipleRects(Rects, pMDB->nDeltaEntries, &pMDB->codedDeltaList, uiVarDataLen); DC_QUIT_ON_FAIL(hr); TIMERSTART; for (i = 0; i < pMDB->nDeltaEntries; i++) PatBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top, (int)(Rects[i].right - Rects[i].left), (int)(Rects[i].bottom - Rects[i].top), WindowsROP); TIMERSTOP; UPDATECOUNTER(FC_DSTBLT_TYPE); }
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleScrBlts
//
// Order handler for ScrBlt and MultiScrBlt.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleScrBlts(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1]; UINT32 WindowsROP; unsigned i; LPSCRBLT_ORDER pSB = (LPSCRBLT_ORDER)pOrder->orderData; #ifdef DISABLE_SHADOW_IN_FULLSCREEN
RECT rectTemp, rectIntersect; int nX, nY; int nWidth; #endif
DC_BEGIN_FN("ODHandleScrBlts");
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = (int)pSB->nLeftRect; pOrder->dstRect.top = (int)pSB->nTopRect; pOrder->dstRect.right = (int)(pSB->nLeftRect + pSB->nWidth - 1); pOrder->dstRect.bottom = (int)(pSB->nTopRect + pSB->nHeight - 1); _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
WindowsROP = _pUh->UHConvertToWindowsROP((unsigned)pSB->bRop);
if (pSB->type == TS_ENC_SCRBLT_ORDER) { TRC_NRM((TB, _T("ORDER: ScrBlt dx %d dy %d w %d h %d sx %d sy %d rop %08lX"), (int)pSB->nLeftRect, (int)pSB->nTopRect, (int)pSB->nWidth, (int)pSB->nHeight, (int)pSB->nXSrc, (int)pSB->nYSrc, WindowsROP));
TIMERSTART; // If we turned off screenblt support due to shadowing a
// large session from WinCE, the server will not currently
// register that and will still send us ScrBlts. We won't
// have a shadow bitmap in this scenario, but we can deal
// with this by invalidating the affected output area.
if (_pCc->_ccCombinedCapabilities.orderCapabilitySet. orderSupport[TS_NEG_SCRBLT_INDEX]) { TRC_DBG((TB, _T("Real ScrBlt"))); #ifdef DISABLE_SHADOW_IN_FULLSCREEN
if (!_pUh->_UH.DontUseShadowBitmap && _pUh->_UH.hdcShadowBitmap ) { #else
if (_pUh->_UH.hdcShadowBitmap) { #endif
if (!BitBlt(_pUh->_UH.hdcDraw, (int)pSB->nLeftRect, (int)pSB->nTopRect, (int)pSB->nWidth, (int)pSB->nHeight, _pUh->_UH.hdcShadowBitmap, (int)pSB->nXSrc, (int)pSB->nYSrc, WindowsROP)) { TRC_ERR((TB, _T("BitBlt failed"))); } } else {
#ifdef OS_WINCE
if (!ODHandleAlwaysOnTopRects(pSB)) { #endif
if (!BitBlt(_pUh->_UH.hdcDraw, (int)pSB->nLeftRect, (int)pSB->nTopRect, (int)pSB->nWidth, (int)pSB->nHeight, _pUh->_UH.hdcOutputWindow, (int)pSB->nXSrc, (int)pSB->nYSrc, WindowsROP)) { TRC_ERR((TB, _T("BitBlt failed"))); } #ifdef OS_WINCE
} #endif
#ifdef DISABLE_SHADOW_IN_FULLSCREEN
if ((_pUh->_UH.fIsBBarVisible) && (_pUh->_UH.hdcDraw == _pUh->_UH.hdcOutputWindow)) { rectTemp.left = (int)(pSB->nXSrc); rectTemp.top = (int)(pSB->nYSrc); rectTemp.right = (int)(pSB->nXSrc + pSB->nWidth); rectTemp.bottom = (int)(pSB->nYSrc + pSB->nHeight);
if (IntersectRect(&rectIntersect, &rectTemp, &(_pUh->_UH.rectBBar))) { nX = pSB->nLeftRect - pSB->nXSrc; nY = pSB->nTopRect - pSB->nYSrc; rectIntersect.left += nX; rectIntersect.right += nX; rectIntersect.top += nY; rectIntersect.bottom += nY;
// In fullscreen, when moving a window quickly inside and outside the bbar
// part of window intersected by bbar is not drawn correctly
// here we invalidate larger rectangle to solve this problem
nWidth = rectIntersect.right - rectIntersect.left; rectIntersect.left -= nWidth; rectIntersect.right += nWidth; rectIntersect.bottom += _pUh->_UH.rectBBar.bottom * 2;
InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &rectIntersect, FALSE); } } #endif // DISABLE_SHADOW_IN_FULLSCREEN
} } else { // Alternative processing for when we get a ScrBlt
// without having advertised support for it.
TRC_DBG((TB, _T("Simulated ScrBlt"))); Rects[0].left = (int)(pSB->nLeftRect); Rects[0].top = (int)(pSB->nTopRect); Rects[0].right = (int)(pSB->nLeftRect + pSB->nWidth); Rects[0].bottom = (int)(pSB->nTopRect + pSB->nHeight); InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &Rects[0], FALSE); } TIMERSTOP; UPDATECOUNTER(FC_SCRBLT_TYPE); } else { int deltaX, deltaY; LPMULTI_SCRBLT_ORDER pMSB = (LPMULTI_SCRBLT_ORDER)pSB;
TRC_NRM((TB, _T("ORDER: MultiScrBlt dx %d dy %d w %d h %d sx %d sy %d ") _T("rop %08lX nDeltas=%d"), (int)pMSB->nLeftRect, (int)pMSB->nTopRect, (int)pMSB->nWidth, (int)pMSB->nHeight, (int)pMSB->nXSrc, (int)pMSB->nYSrc, WindowsROP, (int)pMSB->nDeltaEntries));
TRC_ASSERT((pMSB->codedDeltaList.len <= (ORD_MAX_CLIP_RECTS_CODEDDELTAS_LEN + ORD_MAX_CLIP_RECTS_ZERO_FLAGS_BYTES)), (TB,_T("Received MultiScrBlt with too-large internal length")));
if (0 == pMSB->nDeltaEntries) { TRC_ERR((TB,_T("MultiScrBlt with no rects; uiVarDataLen=%u"), uiVarDataLen)); hr = S_OK; DC_QUIT; } hr = ODDecodeMultipleRects(Rects, pMSB->nDeltaEntries, &pMSB->codedDeltaList, uiVarDataLen); DC_QUIT_ON_FAIL(hr);
// Do a ScrBlt for each of the clip rects as a subrect of the
// original ScrBlt rect.
TIMERSTART; if (_pCc->_ccCombinedCapabilities.orderCapabilitySet. orderSupport[TS_NEG_MULTISCRBLT_INDEX]) { TRC_DBG((TB, _T("Real MultiScrBlt"))); for (i = 0; i < pMSB->nDeltaEntries; i++ ) { // Clip rects in Rects[] are specified within the dest
// rect (pSB->nLeftRect, nTopRect, nRightRect,
// nBottomRect) so we need to calc the offset from the
// source point (pSB->nXSrc, nYSrc) by calculating
// the delta from the dest rect top-left to the clip rect
// top-left, then adding the delta to the source point.
deltaX = (int)(Rects[i].left - pSB->nLeftRect); deltaY = (int)(Rects[i].top - pSB->nTopRect);
// Do the ScrBlt. Note that rects are in exclusive coords.
#ifdef DISABLE_SHADOW_IN_FULLSCREEN
if (!_pUh->_UH.DontUseShadowBitmap && _pUh->_UH.hdcShadowBitmap) { #else
if (_pUh->_UH.hdcShadowBitmap) { #endif
if (!BitBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top, (int)(Rects[i].right - Rects[i].left), (int)(Rects[i].bottom - Rects[i].top), _pUh->_UH.hdcShadowBitmap, (int)pMSB->nXSrc + deltaX, (int)pMSB->nYSrc + deltaY, WindowsROP)) { TRC_ERR((TB, _T("BitBlt failed"))); } } else { #ifdef OS_WINCE
if (!ODHandleAlwaysOnTopRects(pSB)) { #endif
if (!BitBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top, (int)(Rects[i].right - Rects[i].left), (int)(Rects[i].bottom - Rects[i].top), _pUh->_UH.hdcOutputWindow, (int)pMSB->nXSrc + deltaX, (int)pMSB->nYSrc + deltaY, WindowsROP)) { TRC_ERR((TB, _T("BitBlt failed"))); } #ifdef OS_WINCE
} #endif
#ifdef DISABLE_SHADOW_IN_FULLSCREEN
if ((_pUh->_UH.fIsBBarVisible) && (_pUh->_UH.hdcDraw == _pUh->_UH.hdcOutputWindow)) { rectTemp.left = (int)(pSB->nXSrc + deltaX); rectTemp.top = (int)(pSB->nYSrc + deltaY); rectTemp.right = (int)(pSB->nXSrc + deltaX + Rects[i].right - Rects[i].left); rectTemp.bottom = (int)(pSB->nYSrc + deltaY + Rects[i].bottom - Rects[i].top);
if (IntersectRect(&rectIntersect, &rectTemp, &(_pUh->_UH.rectBBar))) { nX = pMSB->nLeftRect - pMSB->nXSrc; nY = pMSB->nTopRect - pMSB->nYSrc; rectIntersect.left += nX; rectIntersect.right += nX; rectIntersect.top += nY; rectIntersect.bottom += nY;
// In fullscreen, when moving a window quickly inside and outside the bbar
// part of window intersected by bbar is not drawn correctly
// here we invalidate larger rectangle to solve this problem
nWidth = rectIntersect.right - rectIntersect.left; rectIntersect.left -= nWidth; rectIntersect.right += nWidth; rectIntersect.bottom += _pUh->_UH.rectBBar.bottom * 2;
InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &rectIntersect, FALSE); } } #endif //DISABLE_SHADOW_IN_FULLSCREEN
} } } else { // Alternative processing for when we get a MultiScrBlt
// without having advertised support for it.
TRC_DBG((TB, _T("Simulated MultiScrBlt"))); Rects[0].left = (int)(pMSB->nLeftRect); Rects[0].top = (int)(pMSB->nTopRect); Rects[0].right = (int)(pMSB->nLeftRect + pMSB->nWidth); Rects[0].bottom = (int)(pMSB->nTopRect + pMSB->nHeight); InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &Rects[0], FALSE); } TIMERSTOP; UPDATECOUNTER(FC_SCRBLT_TYPE); }
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleMultiOpaqueRect
//
// Order handler for MultiOpaqueRect.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleMultiOpaqueRect(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr; RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1]; unsigned i; LPMULTI_OPAQUERECT_ORDER pOR = (LPMULTI_OPAQUERECT_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandleMultiOpaqueRect");
if (0 == pOR->nDeltaEntries) { TRC_ERR((TB,_T("MultiOpaqueRect with no rects; uiVarDataLen=%u"), uiVarDataLen)); hr = S_OK; DC_QUIT; }
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = (int)pOR->nLeftRect; pOrder->dstRect.top = (int)pOR->nTopRect; pOrder->dstRect.right = (int)(pOR->nLeftRect + pOR->nWidth - 1); pOrder->dstRect.bottom = (int)(pOR->nTopRect + pOR->nHeight - 1); _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
TRC_NRM((TB, _T("ORDER: OpaqueRect x(%d) y(%d) w(%d) h(%d) c(%#02x)"), (int)pOR->nLeftRect, (int)pOR->nTopRect, (int)pOR->nWidth, (int)pOR->nHeight, (int)pOR->Color.u.index));
_pUh->UHUseSolidPaletteBrush(pOR->Color);
hr = ODDecodeMultipleRects(Rects, pOR->nDeltaEntries, &pOR->codedDeltaList, uiVarDataLen); DC_QUIT_ON_FAIL(hr);
TIMERSTART; for (i = 0; i < pOR ->nDeltaEntries; i++) PatBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top, (int)(Rects[i].right - Rects[i].left), (int)(Rects[i].bottom - Rects[i].top), PATCOPY); TIMERSTOP; UPDATECOUNTER(FC_OPAQUERECT_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
#ifdef DRAW_NINEGRID
/****************************************************************************/ // ODHandleDrawNineGrid
//
// Order handler for DrawNineGrid.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleDrawNineGrid(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; LPDRAWNINEGRID_ORDER pDNG = (LPDRAWNINEGRID_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandleDrawNineGrid");
TRC_ASSERT((bBoundsSet != 0), (TB, _T("Bounds is not set for DrawNineGrid"))); TRC_ASSERT((0==uiVarDataLen), (TB, _T("Varaible length data in fixed length packet")));
hr = _pUh->UHIsValidNineGridCacheIndex(pDNG->bitmapId); DC_QUIT_ON_FAIL(hr);
// The bounds is for the destination bounding rect, not clip region
// needs to be set
_pUh->UH_ResetClipRegion(); TRC_NRM((TB, _T("ORDER: DrawNineGrid x(%d) y(%d) w(%d) h(%d) id(%d)"), (int)pOrder->dstRect.left, (int)pOrder->dstRect.top, (int)pOrder->dstRect.right, (int)pOrder->dstRect.bottom, (int)pDNG->bitmapId));
TIMERSTART; hr = _pUh->UH_DrawNineGrid(pOrder, pDNG->bitmapId, (RECT *)&(pDNG->srcLeft)); TIMERSTOP; DC_QUIT_ON_FAIL(hr); //UPDATECOUNTER(FC_OPAQUERECT_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleMultiOpaqueRect
//
// Order handler for MultiOpaqueRect.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleMultiDrawNineGrid(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1]; unsigned i; LPMULTI_DRAWNINEGRID_ORDER pDNG = (LPMULTI_DRAWNINEGRID_ORDER)pOrder->orderData; DC_BEGIN_FN("ODHandleMultiDrawNineGrid");
TRC_ASSERT((bBoundsSet != 0), (TB, _T("Bounds is not set for MultiDrawNineGrid")));
if (0 == pDNG->nDeltaEntries) { TRC_ERR((TB,_T("MultiDrawNineGrid with no rects; uiVarDataLen=%u"), uiVarDataLen)); hr = S_OK; DC_QUIT; } hr = _pUh->UHIsValidNineGridCacheIndex(pDNG->bitmapId); DC_QUIT_ON_FAIL(hr); // Need to setup the clip region
hr = ODDecodeMultipleRects(Rects, pDNG->nDeltaEntries, &pDNG->codedDeltaList, uiVarDataLen); DC_QUIT_ON_FAIL(hr);
#if defined (OS_WINCE)
_UH.validClipDC = NULL; #endif
SelectClipRgn(_pUh->_UH.hdcDraw, NULL); SetRectRgn(_pUh->_UH.hDrawNineGridClipRegion, 0, 0, 0, 0); for (i = 0; i < pDNG->nDeltaEntries; i++) { UH_ORDER OrderRect; OrderRect.dstRect.left = Rects[i].left; OrderRect.dstRect.top = Rects[i].top; OrderRect.dstRect.right = Rects[i].right -1; OrderRect.dstRect.bottom = Rects[i].bottom -1;
_pUh->UHAddUpdateRegion(&OrderRect, _pUh->_UH.hDrawNineGridClipRegion); }
#if defined (OS_WINCE)
_UH.validClipDC = NULL; #endif
SelectClipRgn(_pUh->_UH.hdcDraw, _pUh->_UH.hDrawNineGridClipRegion); TRC_NRM((TB, _T("ORDER: MultiDrawNineGrid x(%d) y(%d) w(%d) h(%d) id(%d)"), (int)pOrder->dstRect.left, (int)pOrder->dstRect.top, (int)pOrder->dstRect.right, (int)pOrder->dstRect.bottom, (int)pDNG->bitmapId)); TIMERSTART; hr = _pUh->UH_DrawNineGrid(pOrder, pDNG->bitmapId, (RECT *)&(pDNG->srcLeft)); TIMERSTOP; //UPDATECOUNTER(FC_OPAQUERECT_TYPE);
DC_QUIT_ON_FAIL(hr);
#if defined (OS_WINCE)
_UH.validClipDC = NULL; #endif
SelectClipRgn(_pUh->_UH.hdcDraw, NULL);
DC_EXIT_POINT: DC_END_FN(); return hr; } #endif
/****************************************************************************/ // ODHandleMem3Blt
//
// Order handler for Mem3Blt.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleMem3Blt(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; LPMEM3BLT_R2_ORDER pMB = (LPMEM3BLT_R2_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandleMem3Blt");
TRC_ASSERT((0==uiVarDataLen), (TB, _T("Varaible length data in fixed length packet")));
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = (int)pMB->Common.nLeftRect; pOrder->dstRect.top = (int)pMB->Common.nTopRect; pOrder->dstRect.right = (int)(pMB->Common.nLeftRect + pMB->Common.nWidth - 1); pOrder->dstRect.bottom = (int)(pMB->Common.nTopRect + pMB->Common.nHeight - 1); _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
TRC_NRM((TB, _T("ORDER: Mem3Blt")));
UHUseBkColor(pMB->BackColor, UH_COLOR_PALETTE, _pUh); UHUseTextColor(pMB->ForeColor, UH_COLOR_PALETTE, _pUh); UHUseBrushOrg((int)pMB->BrushOrgX, (int)pMB->BrushOrgY, _pUh); hr = _pUh->UHUseBrush((int)pMB->BrushStyle, (int)pMB->BrushHatch, pMB->ForeColor, UH_COLOR_PALETTE, pMB->BrushExtra); DC_QUIT_ON_FAIL(hr);
hr = _pUh->UHDrawMemBltOrder(_pUh->_UH.hdcDraw, &pMB->Common); DC_QUIT_ON_FAIL(hr);
#ifdef DC_DEBUG
// Draw hatching over the memblt data if the option is enabled.
if (_pUh->_UH.hdcDraw == _pUh->_UH.hdcShadowBitmap || _pUh->_UH.hdcDraw == _pUh->_UH.hdcOutputWindow) { if (_pUh->_UH.hatchMemBltOrderData) { unsigned cacheId; unsigned cacheEntry;
cacheId = DCLO8(pMB->Common.cacheId); cacheEntry = pMB->Common.cacheIndex;
if (cacheEntry != BITMAPCACHE_WAITING_LIST_INDEX && SUCCEEDED(_pUh->UHIsValidBitmapCacheIndex(cacheId, cacheEntry))) { if (_pUh->_UH.MonitorEntries[0] != NULL) _pUh->UH_HatchRect((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect, (int)(pMB->Common.nLeftRect + pMB->Common.nWidth), (int)(pMB->Common.nTopRect + pMB->Common.nHeight), (_pUh->_UH.MonitorEntries[cacheId][cacheEntry].UsageCount == 1) ? UH_RGB_MAGENTA : UH_RGB_GREEN, UH_BRUSHTYPE_FDIAGONAL); else _pUh->UH_HatchRect((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect, (int)(pMB->Common.nLeftRect + pMB->Common.nWidth), (int)(pMB->Common.nTopRect + pMB->Common.nHeight), UH_RGB_MAGENTA, UH_BRUSHTYPE_FDIAGONAL); } }
// Label the memblt if the option is enabled.
if (_pUh->_UH.labelMemBltOrders) { unsigned cacheId; unsigned cacheEntry;
cacheId = DCLO8(pMB->Common.cacheId); cacheEntry = pMB->Common.cacheIndex;
if (cacheEntry != BITMAPCACHE_WAITING_LIST_INDEX && SUCCEEDED(_pUh->UHIsValidBitmapCacheIndex(cacheId, cacheEntry))) { _pUh->UHLabelMemBltOrder((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect, pMB->Common.cacheId, pMB->Common.cacheIndex); } } }
#endif /* DC_DEBUG */
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleSaveBitmap
//
// Order handler for SaveBitmap.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleSaveBitmap(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; int xSaveBitmap; int ySaveBitmap; int xScreenBitmap; int yScreenBitmap; int cxTile; int cyTile; int ScreenLeft, ScreenTop, ScreenRight, ScreenBottom; LPSAVEBITMAP_ORDER pSB = (LPSAVEBITMAP_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandleSaveBitmap");
TRC_ASSERT((0==uiVarDataLen), (TB, _T("Varaible length data in fixed length packet")));
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = (int)pSB->nLeftRect; pOrder->dstRect.top = (int)pSB->nTopRect; pOrder->dstRect.right = (int)pSB->nRightRect; pOrder->dstRect.bottom = (int)pSB->nBottomRect; _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
TRC_NRM((TB, _T("ORDER: SaveBitmap op %d rect %d %d %d %d"), (int)pSB->Operation, (int)pSB->nLeftRect, (int)pSB->nTopRect, (int)pSB->nRightRect, (int)pSB->nBottomRect));
if (_pUh->_UH.hSaveScreenBitmap != NULL) { // Check that we have selected a DC to draw to.
TRC_ASSERT((NULL != _pUh->_UH.hdcDraw), (TB,_T("No drawing hdc!")));
// Calculate the (x,y) offset into the Save Desktop Bitmap from the
// start position as encoded in the order. (The server knows the
// dimensions of our bitmap and is reponsible for telling us where to
// store/retrieve rectangles in the bitmap.)
// See T.128 8.16.17 for a justification of this algorithm.
ySaveBitmap = (int)((pSB->SavedBitmapPosition / (UH_SAVE_BITMAP_WIDTH * (UINT32)UH_SAVE_BITMAP_Y_GRANULARITY)) * UH_SAVE_BITMAP_Y_GRANULARITY);
xSaveBitmap = (int)((pSB->SavedBitmapPosition - (ySaveBitmap * (UINT32)UH_SAVE_BITMAP_WIDTH)) / UH_SAVE_BITMAP_Y_GRANULARITY);
TRC_DBG((TB, _T("start pos %lu = (%d,%d)"), pSB->SavedBitmapPosition, xSaveBitmap, ySaveBitmap));
// Split the bitmap rectangle into tiles that fit neatly into the
// save bitmap. Each tile's dimensions are a multiple of the
// xGranularity and yGranularity. Tiling is used so that a screen
// bitmap rectangle can be saved even if it is taller than the
// save bitmap. e.g.:
// Screen Bitmap Save Bitmap
// 111111 1111112222
// 222222 -> 2233333344
// 333333 4444------
// 444444
// The protocol uses inclusive co-ordinates, whereas Windows
// has an exclusive co-ordinate system. Therefore, doctor
// these co-ords to make sure the lower-right edges are included.
ScreenLeft = (int)pSB->nLeftRect; ScreenTop = (int)pSB->nTopRect; ScreenRight = (int)pSB->nRightRect + 1; ScreenBottom = (int)pSB->nBottomRect + 1;
// Start tiling in the top left corner of the Screen Bitmap rectangle.
xScreenBitmap = ScreenLeft; yScreenBitmap = ScreenTop;
// The height of the tile is the vertical granularity (or less - if
// the Screen Bitmap rect is thinner than the granularity).
cyTile = DC_MIN(ScreenBottom - yScreenBitmap, UH_SAVE_BITMAP_Y_GRANULARITY);
// Repeat while there are more tiles in the Screen Bitmap rect to
// process.
while (yScreenBitmap < ScreenBottom) { // The width of the tile is the minimum of:
// - the width of the remaining rectangle in the current strip of
// the Screen Bitmap rectangle
// - the width of the remaining empty space in the Save Bitmap
cxTile = DC_MIN(UH_SAVE_BITMAP_WIDTH - xSaveBitmap, ScreenRight - xScreenBitmap);
TRC_DBG((TB, _T("screen(%d,%d) save(%d,%d) cx(%d) cy(%d)"), xScreenBitmap, yScreenBitmap, xSaveBitmap, ySaveBitmap, cxTile, cyTile));
// Copy this tile.
if (pSB->Operation == SV_SAVEBITS) { TRC_NRM((TB, _T("Save a desktop bitmap"))); if (!BitBlt(_pUh->_UH.hdcSaveScreenBitmap, xSaveBitmap, ySaveBitmap, cxTile, cyTile, _pUh->_UH.hdcDraw, xScreenBitmap, yScreenBitmap, SRCCOPY)) { TRC_SYSTEM_ERROR("BitBlt"); TRC_ERR((TB, _T("Screen(%u,%u) Tile(%u,%u) Save(%u,%u)"), xScreenBitmap, yScreenBitmap, cxTile, cyTile, xSaveBitmap, ySaveBitmap)); }
} else { TRC_NRM((TB, _T("Restore a desktop bitmap"))); if (!BitBlt(_pUh->_UH.hdcDraw, xScreenBitmap, yScreenBitmap, cxTile, cyTile, _pUh->_UH.hdcSaveScreenBitmap, xSaveBitmap, ySaveBitmap, SRCCOPY)) { TRC_SYSTEM_ERROR("BitBlt"); TRC_ERR((TB, _T("Screen(%u,%u) Tile(%u,%u) Save(%u,%u)"), xScreenBitmap, yScreenBitmap, cxTile, cyTile, xSaveBitmap, ySaveBitmap)); }
}
// Move to the next tile in the Screen Bitmap rectangle.
xScreenBitmap += cxTile; if (xScreenBitmap >= ScreenRight) { xScreenBitmap = ScreenLeft; yScreenBitmap += cyTile; cyTile = DC_MIN(ScreenBottom - yScreenBitmap, UH_SAVE_BITMAP_Y_GRANULARITY); }
// Move to the next free space in the Save Bitmap.
xSaveBitmap += UHROUNDUP(cxTile, UH_SAVE_BITMAP_X_GRANULARITY); if (xSaveBitmap >= UH_SAVE_BITMAP_WIDTH) { // Move to the next horizontal strip.
TRC_DBG((TB,_T("Next strip"))); xSaveBitmap = 0; ySaveBitmap += UHROUNDUP(cyTile, UH_SAVE_BITMAP_Y_GRANULARITY); }
if (ySaveBitmap >= UH_SAVE_BITMAP_HEIGHT) { // Assert that we haven't been sent too much stuff. Quietly
// stop saving data in the retail build.
TRC_ABORT((TB, _T("Server out of bounds!"))); break; } }
#ifdef DC_DEBUG
// Draw hatching over the SSB data if the option is enabled.
if (_pUh->_UH.hatchSSBOrderData) _pUh->UH_HatchRect((int)pSB->nLeftRect, (int)pSB->nTopRect, (int)pSB->nRightRect, (int)pSB->nBottomRect, UH_RGB_CYAN, UH_BRUSHTYPE_FDIAGONAL); #endif
} else { // This should never happen. We only advertise SSB support
// if UH has successfully created this bitmap.
// Fail to process the order in the retail build - the
// server is probably being evil.
TRC_ABORT((TB, _T("SSB bitmap null!"))); }
return hr; DC_END_FN(); }
/****************************************************************************/ // ODHandlePolyLine
//
// Order handler for PolyLine.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandlePolyLine(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; POINT Points[ORD_MAX_POLYLINE_ENCODED_POINTS + 1]; RECT BoundRect; DCCOLOR ZeroColor; PPOLYLINE_ORDER pPL = (PPOLYLINE_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandlePolyLine");
TRC_NRM((TB, _T("ORDER: PolyLine xs=%d ys=%d rop2=%04X brc=0x%X ") _T("penc=%08lX #entr=%d"), pPL->XStart, pPL->YStart, pPL->ROP2, pPL->BrushCacheEntry, pPL->PenColor, pPL->NumDeltaEntries));
ZeroColor.u.rgb.red = 0; ZeroColor.u.rgb.green = 0; ZeroColor.u.rgb.blue = 0; UHUseBkColor(ZeroColor, UH_COLOR_PALETTE, _pUh); UHUseBkMode(TRANSPARENT, _pUh); UHUseROP2((int)pPL->ROP2, _pUh); _pUh->UHUsePen(PS_SOLID, 1, pPL->PenColor, UH_COLOR_PALETTE);
Points[0].x = (int)pPL->XStart; Points[0].y = (int)pPL->YStart;
BoundRect.left = BoundRect.right = Points[0].x; BoundRect.top = BoundRect.bottom = Points[0].y;
hr = ODDecodePathPoints(Points, &BoundRect, pPL->CodedDeltaList.Deltas, (unsigned)pPL->NumDeltaEntries, ORD_MAX_POLYLINE_ENCODED_POINTS, pPL->CodedDeltaList.len, ORD_MAX_POLYLINE_CODEDDELTAS_LEN + ORD_MAX_POLYLINE_ZERO_FLAGS_BYTES, uiVarDataLen, !bBoundsSet); DC_QUIT_ON_FAIL(hr);
// If we didn't get a rect across the net, use the one we calculated.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = BoundRect.left; pOrder->dstRect.top = BoundRect.top; pOrder->dstRect.right = BoundRect.right; pOrder->dstRect.bottom = BoundRect.bottom; _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
TIMERSTART; Polyline(_pUh->_UH.hdcDraw, Points, (UINT16)pPL->NumDeltaEntries + 1); TIMERSTOP; UPDATECOUNTER(FC_POLYLINE_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandlePolygonSC
//
// Order handler for Polygon with solic color brush.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandlePolygonSC(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; POINT Points[ORD_MAX_POLYGON_ENCODED_POINTS + 1]; RECT BoundRect; DCCOLOR ZeroColor; POLYGON_SC_ORDER FAR *pPG = (POLYGON_SC_ORDER FAR *)pOrder->orderData;
DC_BEGIN_FN("ODHandlePolygonSC");
TRC_NRM((TB, _T("ORDER: PolyGonSC xs=%d ys=%d rop2=%04X fill=%d ") _T("brushc=%08lX #entr=%d"), pPG->XStart, pPG->YStart, pPG->ROP2, pPG->FillMode, pPG->BrushColor, pPG->NumDeltaEntries));
ZeroColor.u.rgb.red = 0; ZeroColor.u.rgb.green = 0; ZeroColor.u.rgb.blue = 0; UHUseBkColor(ZeroColor, UH_COLOR_PALETTE, _pUh); UHUseBkMode(TRANSPARENT, _pUh); UHUseROP2((int)pPG->ROP2, _pUh); _pUh->UHUsePen(PS_NULL, 1, ZeroColor, UH_COLOR_PALETTE); _pUh->UHUseSolidPaletteBrush(pPG->BrushColor); UHUseFillMode(pPG->FillMode,_pUh);
Points[0].x = (int)pPG->XStart; Points[0].y = (int)pPG->YStart;
BoundRect.left = BoundRect.right = Points[0].x; BoundRect.top = BoundRect.bottom = Points[0].y;
hr = ODDecodePathPoints(Points, &BoundRect, pPG->CodedDeltaList.Deltas, (unsigned)pPG->NumDeltaEntries, ORD_MAX_POLYGON_ENCODED_POINTS, pPG->CodedDeltaList.len, ORD_MAX_POLYGON_CODEDDELTAS_LEN + ORD_MAX_POLYGON_ZERO_FLAGS_BYTES, uiVarDataLen, !bBoundsSet); DC_QUIT_ON_FAIL(hr);
// If we didn't get a rect across the net, use the one we calculated.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = BoundRect.left; pOrder->dstRect.top = BoundRect.top; pOrder->dstRect.right = BoundRect.right; pOrder->dstRect.bottom = BoundRect.bottom; _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
TIMERSTART; Polygon(_pUh->_UH.hdcDraw, Points, (UINT16)pPG->NumDeltaEntries + 1); TIMERSTOP; UPDATECOUNTER(FC_POLYGONSC_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandlePolygonCB
//
// Order handler for Polygon with complex brush.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandlePolygonCB(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; POINT Points[ORD_MAX_POLYGON_ENCODED_POINTS + 1]; RECT BoundRect; DCCOLOR ZeroColor; POLYGON_CB_ORDER FAR *pPG = (POLYGON_CB_ORDER FAR *)pOrder->orderData;
DC_BEGIN_FN("ODHandlePolygonCB");
TRC_NRM((TB, _T("ORDER: PolyGonCB xs=%d ys=%d rop2=%04X fill=%d ") _T("#entr=%d"), pPG->XStart, pPG->YStart, pPG->ROP2, pPG->FillMode, pPG->NumDeltaEntries));
ZeroColor.u.rgb.red = 0; ZeroColor.u.rgb.green = 0; ZeroColor.u.rgb.blue = 0; UHUseBkColor(pPG->BackColor, UH_COLOR_PALETTE, _pUh);
// If the brush is a hatched brush, we need to check the high bit (bit 7)
// of ROP2 to see if the background mode should be transparent or opaque:
// 1 means transparent mode, 0 means opaque mode
if (pPG->BrushStyle == BS_HATCHED) { if (!(pPG->ROP2 & 0x80)) { UHUseBkMode(OPAQUE, _pUh); } else { UHUseBkMode(TRANSPARENT, _pUh); } }
// Set the ROP2 for the forground mix mode
UHUseROP2(((int)pPG->ROP2) & 0x1F, _pUh);
UHUseTextColor(pPG->ForeColor, UH_COLOR_PALETTE, _pUh); _pUh->UHUsePen(PS_NULL, 1, ZeroColor, UH_COLOR_PALETTE); UHUseBrushOrg((int)pPG->BrushOrgX, (int)pPG->BrushOrgY, _pUh); hr = _pUh->UHUseBrush((unsigned)pPG->BrushStyle, (unsigned)pPG->BrushHatch, pPG->ForeColor, UH_COLOR_PALETTE, pPG->BrushExtra); DC_QUIT_ON_FAIL(hr); UHUseFillMode(pPG->FillMode, _pUh);
Points[0].x = (int)pPG->XStart; Points[0].y = (int)pPG->YStart;
BoundRect.left = BoundRect.right = Points[0].x; BoundRect.top = BoundRect.bottom = Points[0].y;
hr = ODDecodePathPoints(Points, &BoundRect, pPG->CodedDeltaList.Deltas, (unsigned)pPG->NumDeltaEntries, ORD_MAX_POLYGON_ENCODED_POINTS, pPG->CodedDeltaList.len, ORD_MAX_POLYGON_CODEDDELTAS_LEN + ORD_MAX_POLYGON_ZERO_FLAGS_BYTES, uiVarDataLen, !bBoundsSet); DC_QUIT_ON_FAIL(hr);
// If we didn't get a rect across the net, use the one we calculated.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = BoundRect.left; pOrder->dstRect.top = BoundRect.top; pOrder->dstRect.right = BoundRect.right; pOrder->dstRect.bottom = BoundRect.bottom; _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
TIMERSTART; Polygon(_pUh->_UH.hdcDraw, Points, (UINT16)pPG->NumDeltaEntries + 1); TIMERSTOP; UPDATECOUNTER(FC_POLYGONCB_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleEllipseSC
//
// Order handler for Ellipse with solid color brush.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleEllipseSC(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; unsigned FudgeFactor; DCCOLOR ZeroColor; PELLIPSE_SC_ORDER pEL = (PELLIPSE_SC_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandleEllipseSC");
TRC_ASSERT((0==uiVarDataLen), (TB, _T("Varaible length data in fixed length packet")));
TRC_NRM((TB, _T("ORDER: Ellipse SC xs=%d ys=%d xe=%d ye=%d rop2=%04X ") _T("fillmode=%d penc=%08lX"), pEL->LeftRect, pEL->TopRect, pEL->RightRect, pEL->BottomRect, pEL->ROP2, pEL->FillMode, pEL->Color));
ZeroColor.u.rgb.red = 0; ZeroColor.u.rgb.green = 0; ZeroColor.u.rgb.blue = 0; UHUseBkColor(ZeroColor, UH_COLOR_PALETTE, _pUh); UHUseBkMode(TRANSPARENT, _pUh); UHUseROP2((int)pEL->ROP2, _pUh);
if (pEL->FillMode) { _pUh->UHUsePen(PS_NULL, 1, ZeroColor, UH_COLOR_PALETTE); _pUh->UHUseSolidPaletteBrush(pEL->Color); UHUseFillMode(pEL->FillMode, _pUh);
// Because of the way the null pen works, we need to fudge the bottom
// and right coords a bit.
FudgeFactor = 1; } else { UINT32 extra[2] = { 0, 0 };
_pUh->UHUsePen(PS_SOLID, 1, pEL->Color, UH_COLOR_PALETTE); hr = _pUh->UHUseBrush(BS_NULL, 0, ZeroColor, UH_COLOR_PALETTE, (BYTE FAR *)extra); DC_QUIT_ON_FAIL(hr); FudgeFactor = 0; }
// If we didn't get a rect across the net, use the one we calculated.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = (int)pEL->LeftRect; pOrder->dstRect.top = (int)pEL->TopRect; pOrder->dstRect.right = (int)pEL->RightRect; pOrder->dstRect.bottom = (int)pEL->BottomRect; _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
TIMERSTART; // We add 1 to bottom and right here since the server sends an
// inclusive rect to us but GDI is exclusive.
Ellipse(_pUh->_UH.hdcDraw, (int)pEL->LeftRect, (int)pEL->TopRect, (int)pEL->RightRect + 1 + FudgeFactor, (int)pEL->BottomRect + 1 + FudgeFactor); TIMERSTOP; UPDATECOUNTER(FC_ELLIPSESC_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleEllipseCB
//
// Order handler for Ellipse with complex brush.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleEllipseCB(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; DCCOLOR ZeroColor; PELLIPSE_CB_ORDER pEL = (PELLIPSE_CB_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandleEllipseCB");
TRC_ASSERT((0==uiVarDataLen), (TB, _T("Varaible length data in fixed length packet")));
TRC_NRM((TB, _T("ORDER: Ellipse CB xs=%d ys=%d xe=%d ye=%d rop2=%04X ") _T("fillmode=%d"), pEL->LeftRect, pEL->TopRect, pEL->RightRect, pEL->BottomRect, pEL->ROP2, pEL->FillMode));
TRC_DBG((TB, _T("ORDER: Ellipse Brush %02X %02X BC %02x FC %02x ") _T("(%02x %02x %02x %02x %02x %02x %02x) rop %08lX"), (int)pEL->BrushStyle, (int)pEL->BrushHatch, (int)pEL->BackColor.u.index, (int)pEL->ForeColor.u.index, (int)pEL->BrushExtra[0], (int)pEL->BrushExtra[1], (int)pEL->BrushExtra[2], (int)pEL->BrushExtra[3], (int)pEL->BrushExtra[4], (int)pEL->BrushExtra[5], (int)pEL->BrushExtra[6], (int)pEL->ROP2));
ZeroColor.u.rgb.red = 0; ZeroColor.u.rgb.green = 0; ZeroColor.u.rgb.blue = 0; _pUh->UHUsePen(PS_NULL, 1, ZeroColor, UH_COLOR_PALETTE); UHUseBkColor(pEL->BackColor, UH_COLOR_PALETTE, _pUh);
// If the brush is a hatched brush, we need to check the high bit (bit 7)
// of ROP2 to see if the background mode should be transparent or opaque:
// 1 means transparent mode, 0 means opaque mode
if (pEL->BrushStyle == BS_HATCHED) { if (!(pEL->ROP2 & 0x80)) { UHUseBkMode(OPAQUE, _pUh); } else { UHUseBkMode(TRANSPARENT, _pUh); } }
// Set the ROP2 for the forground mix mode
UHUseROP2((((int)pEL->ROP2) & 0x1F), _pUh);
UHUseTextColor(pEL->ForeColor, UH_COLOR_PALETTE, _pUh); UHUseBrushOrg((int)pEL->BrushOrgX, (int)pEL->BrushOrgY, _pUh); hr = _pUh->UHUseBrush((unsigned)pEL->BrushStyle, (unsigned)pEL->BrushHatch, pEL->ForeColor, UH_COLOR_PALETTE, pEL->BrushExtra); DC_QUIT_ON_FAIL(hr);
UHUseFillMode(pEL->FillMode, _pUh);
// If we didn't get a rect across the net, use the one we calculated.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { pOrder->dstRect.left = (int)pEL->LeftRect; pOrder->dstRect.top = (int)pEL->TopRect; pOrder->dstRect.right = (int)pEL->RightRect; pOrder->dstRect.bottom = (int)pEL->BottomRect; _pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
TIMERSTART; // We add 1 to bottom and right here since the server sends an
// inclusive rect to us but GDI is exclusive. Also, to offset
// a null-pen bias at the bottom and right by adding another 1.
Ellipse(_pUh->_UH.hdcDraw, (int)pEL->LeftRect, (int)pEL->TopRect, (int)pEL->RightRect + 2, (int)pEL->BottomRect + 2); TIMERSTOP; UPDATECOUNTER(FC_ELLIPSECB_TYPE);
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODDecodeFastIndex
//
// Fast-path order decoder for FastIndex orders.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODDecodeFastIndex( BYTE ControlFlags, BYTE FAR * FAR *ppFieldDecode, DCUINT dataLen, UINT32 FieldFlags) { HRESULT hr = S_OK; unsigned OpEncodeFlags = 0; PUH_ORDER pOrder = (PUH_ORDER)_OD.lastFastIndex; LPINDEX_ORDER pGI = (LPINDEX_ORDER)(_OD.lastFastIndex + UH_ORDER_HEADER_SIZE); FAST_INDEX_ORDER FAR *pFI = (FAST_INDEX_ORDER FAR *) (_OD.lastFastIndex + UH_ORDER_HEADER_SIZE); BYTE FAR *pFieldDecode = *ppFieldDecode; BYTE FAR *pEnd = pFieldDecode + dataLen;
DC_BEGIN_FN("ODDecodeFastIndex");
// Copy initial non-coordinate fields if present.
if (FieldFlags & 0x0001) { OD_DECODE_CHECK_READ(pFieldDecode, BYTE, pEnd, hr); pFI->cacheId = *pFieldDecode++; } if (FieldFlags & 0x0002) { OD_DECODE_CHECK_READ(pFieldDecode, UINT16, pEnd, hr); pFI->fDrawing = *((UINT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0004) { OD_DECODE_CHECK_READ_MULT(pFieldDecode, BYTE, 3, pEnd, hr); pFI->BackColor.u.rgb.red = *pFieldDecode++; pFI->BackColor.u.rgb.green = *pFieldDecode++; pFI->BackColor.u.rgb.blue = *pFieldDecode++; } if (FieldFlags & 0x0008) { OD_DECODE_CHECK_READ_MULT(pFieldDecode, BYTE, 3, pEnd, hr); pFI->ForeColor.u.rgb.red = *pFieldDecode++; pFI->ForeColor.u.rgb.green = *pFieldDecode++; pFI->ForeColor.u.rgb.blue = *pFieldDecode++; }
if (ControlFlags & TS_DELTA_COORDINATES) { // All coord fields are 1-byte signed deltas from the last values.
if (FieldFlags & 0x0010) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->BkLeft += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0020) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->BkTop += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0040) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->BkRight += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0080) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->BkBottom += *((char FAR *)pFieldDecode); pFieldDecode++; }
if (FieldFlags & 0x0100) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->OpLeft += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0200) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->OpTop += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0400) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->OpRight += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x0800) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->OpBottom += *((char FAR *)pFieldDecode); pFieldDecode++; }
if (FieldFlags & 0x1000) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->x += *((char FAR *)pFieldDecode); pFieldDecode++; } if (FieldFlags & 0x2000) { OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr); pFI->y += *((char FAR *)pFieldDecode); pFieldDecode++; } } else { // All coord fields are 2-byte values.sign-extended from the output.
if (FieldFlags & 0x0010) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->BkLeft = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0020) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->BkTop = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0040) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->BkRight = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0080) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->BkBottom = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; }
if (FieldFlags & 0x0100) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->OpLeft = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0200) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->OpTop = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0400) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->OpRight = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x0800) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->OpBottom = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; }
if (FieldFlags & 0x1000) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->x = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } if (FieldFlags & 0x2000) { OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr); pFI->y = *((INT16 UNALIGNED FAR *)pFieldDecode); pFieldDecode += 2; } }
if (FieldFlags & 0x4000) { // First byte is the number of following bytes.
OD_DECODE_CHECK_READ(pFieldDecode, BYTE, pEnd, hr); pFI->variableBytes.len = *pFieldDecode++;
// The structure is defined with 255 elements
if (255 < pFI->variableBytes.len) { TRC_ABORT(( TB, _T("VARIBLE_INDEXBYTES len too great; len %u"), pFI->variableBytes.len )); hr = E_TSC_CORE_LENGTH; DC_QUIT; }
OD_DECODE_CHECK_READ_MULT(pFieldDecode, BYTE, pFI->variableBytes.len, pEnd, hr); memcpy(pFI->variableBytes.arecs, pFieldDecode, pFI->variableBytes.len); pFieldDecode += pFI->variableBytes.len; }
// Return the incremented pointer to the main routine.
*ppFieldDecode = pFieldDecode;
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!(ControlFlags & TS_BOUNDS)) { if (pFI->OpTop < pFI->OpBottom) { pOrder->dstRect.right = (int)pFI->OpRight; pOrder->dstRect.left = (int)pFI->OpLeft; pOrder->dstRect.top = (int)pFI->OpTop; pOrder->dstRect.bottom = (int)pFI->OpBottom; } else { // Since we encode OpRect fields, we have to
// decode it to get the correct bound rect.
if (pFI->OpTop == 0xF) { // Opaque rect is same as bk rect
pOrder->dstRect.left = (int)pFI->BkLeft; pOrder->dstRect.top = (int)pFI->BkTop; pOrder->dstRect.right = (int)pFI->BkRight; pOrder->dstRect.bottom = (int)pFI->BkBottom; } else if (pFI->OpTop == 0xD) { // Opaque rect is same as bk rect except
// OpRight stored in OpTop field
pOrder->dstRect.left = (int)pFI->BkLeft; pOrder->dstRect.top = (int)pFI->BkTop; pOrder->dstRect.right = (int)pFI->OpRight; pOrder->dstRect.bottom = (int)pFI->BkBottom; } else { // We take the Bk rect as bound rect
pOrder->dstRect.right = (int)pFI->BkRight; pOrder->dstRect.left = (int)pFI->BkLeft; pOrder->dstRect.top = (int)pFI->BkTop; pOrder->dstRect.bottom = (int)pFI->BkBottom; } }
_pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
// pGI and pFI are different views of the same order memory.
// We translate to the regular glyph index order format for display
// handling, then translate back.
pGI->cacheId = (BYTE)(pFI->cacheId & 0xF); // Mask out high bits for future use.
pGI->flAccel = (BYTE)(pFI->fDrawing >> 8); pGI->ulCharInc = (BYTE)(pFI->fDrawing & 0xFF); pGI->fOpRedundant = 0;
// For Fast Index order, we need to decode for x, y and
// opaque rect.
if (pFI->OpBottom == INT16_MIN) { OpEncodeFlags = (unsigned)pFI->OpTop; if (OpEncodeFlags == 0xF) { // Opaque rect is redundant
pGI->OpLeft = pFI->BkLeft; pGI->OpTop = pFI->BkTop; pGI->OpRight = pFI->BkRight; pGI->OpBottom = pFI->BkBottom; } else if (OpEncodeFlags == 0xD) { // Opaque rect is redundant except OpRight
// which is stored in OpTop
pGI->OpLeft = pFI->BkLeft; pGI->OpTop = pFI->BkTop; pGI->OpRight = pFI->OpRight; pGI->OpBottom = pFI->BkBottom; } }
if (pFI->x == INT16_MIN) pGI->x = pFI->BkLeft; if (pFI->y == INT16_MIN) pGI->y = pFI->BkTop;
TRC_NRM((TB, _T("ORDER: Glyph index cacheId %u flAccel %u ") _T("ulCharInc %u fOpRedundant %u"), pGI->cacheId, (unsigned)pGI->flAccel, (unsigned)pGI->ulCharInc, (unsigned)pGI->fOpRedundant)); TRC_NRM((TB, _T(" bc %08lX fc %08lX Bk(%ld,%ld)-(%ld,%ld) ") _T("Op(%ld,%ld)-(%ld,%ld)"), pGI->BackColor, pGI->ForeColor, pGI->BkLeft, pGI->BkTop, pGI->BkRight, pGI->BkBottom, pGI->OpLeft, pGI->OpTop, pGI->OpRight, pGI->OpBottom)); TRC_NRM((TB, _T(" BrushOrg x %ld y %ld BrushStyle %lu x %ld y %ld"), pGI->BrushOrgX, pGI->BrushOrgY, pGI->BrushStyle, pGI->x, pGI->y));
TIMERSTART; hr = _pUh->UHDrawGlyphOrder(pGI, &pFI->variableBytes); TIMERSTOP; UPDATECOUNTER(FC_FAST_INDEX_TYPE); DC_QUIT_ON_FAIL(hr);
// Now we need to put bits back
if (OpEncodeFlags) { if (OpEncodeFlags == 0xF) { pGI->OpLeft = 0; pGI->OpTop = OpEncodeFlags; pGI->OpRight = 0; pGI->OpBottom = INT16_MIN; } else if (OpEncodeFlags == 0xD) { pGI->OpLeft = 0; pGI->OpTop = OpEncodeFlags; pGI->OpRight = pGI->OpRight; pGI->OpBottom = INT16_MIN; } }
if (pFI->x == pFI->BkLeft) pGI->x = INT16_MIN; if (pFI->y == pFI->BkTop) pGI->y = INT16_MIN;
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleFastGlyph
//
// Order handler for FastGlyph orders.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleFastGlyph(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; unsigned OpEncodeFlags = 0; VARIABLE_INDEXBYTES VariableBytes; LPINDEX_ORDER pGI = (LPINDEX_ORDER)pOrder->orderData; LPFAST_GLYPH_ORDER pFG = (LPFAST_GLYPH_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandleFastGlyph");
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { if (pFG->OpTop < pFG->OpBottom) { pOrder->dstRect.right = (int)pFG->OpRight; pOrder->dstRect.left = (int)pFG->OpLeft; pOrder->dstRect.top = (int)pFG->OpTop; pOrder->dstRect.bottom = (int)pFG->OpBottom; } else { // Since we encode OpRect fields, we have to
// decode it to get the correct bound rect.
if (pFG->OpTop == 0xF) { // Opaque rect is same as bk rect
pOrder->dstRect.left = (int)pFG->BkLeft; pOrder->dstRect.top = (int)pFG->BkTop; pOrder->dstRect.right = (int)pFG->BkRight; pOrder->dstRect.bottom = (int)pFG->BkBottom; } else if (pFG->OpTop == 0xD) { // Opaque rect is same as bk rect except
// OpRight stored in OpTop field
pOrder->dstRect.left = (int)pFG->BkLeft; pOrder->dstRect.top = (int)pFG->BkTop; pOrder->dstRect.right = (int)pFG->OpRight; pOrder->dstRect.bottom = (int)pFG->BkBottom; } else { // We take the Bk rect as bound rect
pOrder->dstRect.right = (int)pFG->BkRight; pOrder->dstRect.left = (int)pFG->BkLeft; pOrder->dstRect.top = (int)pFG->BkTop; pOrder->dstRect.bottom = (int)pFG->BkBottom; } }
_pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
// pGI and pFG are different views of the same order memory.
// We translate to the regular glyph index order format for display
// handling, then translate back.
pGI->cacheId = (BYTE)(pFG->cacheId & 0xF); // Mask out high bits for future use.
OD_DECODE_CHECK_VARIABLE_DATALEN(uiVarDataLen, pFG->variableBytes.len);
// The structure is defined with 255 elements
if (255 < pFG->variableBytes.len) { TRC_ABORT(( TB, _T("VARIBLE_INDEXBYTES len too great; len %u"), pFG->variableBytes.len )); hr = E_TSC_CORE_LENGTH; DC_QUIT; }
if (pFG->variableBytes.len < 1) { TRC_ERR((TB,_T("No variable bytes"))); DC_QUIT; }
if (pFG->variableBytes.len > 1) { // SECURITY - the cacheId is verify in call to UHProcessCacheGlyphOrderRev2
hr = _pUh->UHProcessCacheGlyphOrderRev2(pGI->cacheId, 1, pFG->variableBytes.glyphData, (unsigned)pFG->variableBytes.len); DC_QUIT_ON_FAIL(hr); }
pGI->flAccel = (BYTE)(pFG->fDrawing >> 8); pGI->ulCharInc = (BYTE)(pFG->fDrawing & 0xff); pGI->fOpRedundant = 0;
// For Fast Index order, we need to decode for x, y and
// opaque rect.
if (pFG->OpBottom == INT16_MIN) { OpEncodeFlags = (unsigned)pFG->OpTop; if (OpEncodeFlags == 0xF) { // Opaque rect is redundant
pGI->OpLeft = pFG->BkLeft; pGI->OpTop = pFG->BkTop; pGI->OpRight = pFG->BkRight; pGI->OpBottom = pFG->BkBottom; } else if (OpEncodeFlags == 0xD) { // Opaque rect is redundant except OpRight
// which is stored in OpTop
pGI->OpLeft = pFG->BkLeft; pGI->OpTop = pFG->BkTop; pGI->OpRight = pFG->OpRight; pGI->OpBottom = pFG->BkBottom; } }
if (pFG->x == INT16_MIN) pGI->x = pFG->BkLeft; if (pFG->y == INT16_MIN) pGI->y = pFG->BkTop;
// Setup index order for the glyph
VariableBytes.len = 2; VariableBytes.arecs[0].byte = (BYTE)pFG->variableBytes.glyphData[0]; VariableBytes.arecs[1].byte = 0;
TIMERSTART; hr = _pUh->UHDrawGlyphOrder(pGI, &VariableBytes); TIMERSTOP; UPDATECOUNTER(FC_FAST_INDEX_TYPE); DC_QUIT_ON_FAIL(hr);
// Now we need to put bits back
if (OpEncodeFlags) { if (OpEncodeFlags == 0xF) { pGI->OpLeft = 0; pGI->OpTop = OpEncodeFlags; pGI->OpRight = 0; pGI->OpBottom = INT16_MIN; } else if (OpEncodeFlags == 0xD) { pGI->OpLeft = 0; pGI->OpTop = OpEncodeFlags; pGI->OpRight = pGI->OpRight; pGI->OpBottom = INT16_MIN; } }
if (pFG->x == pFG->BkLeft) pGI->x = INT16_MIN; if (pFG->y == pFG->BkTop) pGI->y = INT16_MIN;
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODHandleGlyphIndex
//
// Order handler for GlyphIndex orders.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODHandleGlyphIndex(PUH_ORDER pOrder, UINT16 uiVarDataLen, BOOL bBoundsSet) { HRESULT hr = S_OK; LPINDEX_ORDER pGI = (LPINDEX_ORDER)pOrder->orderData;
DC_BEGIN_FN("ODHandleGlyphIndex");
// If we've not already set the bounds (the order didn't contain
// any), set the bounds to the blt rect and reset the clip region.
// This rect might be needed later to add to the clip region for
// updating the shadow buffer to the screen.
if (!bBoundsSet) { if (pGI->OpTop < pGI->OpBottom) { pOrder->dstRect.right = (int)pGI->OpRight; pOrder->dstRect.left = (int)pGI->OpLeft; pOrder->dstRect.top = (int)pGI->OpTop; pOrder->dstRect.bottom = (int)pGI->OpBottom; } else { pOrder->dstRect.right = (int)pGI->BkRight; pOrder->dstRect.left = (int)pGI->BkLeft; pOrder->dstRect.top = (int)pGI->BkTop; pOrder->dstRect.bottom = (int)pGI->BkBottom; }
_pUh->UH_ResetClipRegion(); } else { _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top, pOrder->dstRect.right, pOrder->dstRect.bottom); }
// Handle the opaque rectangle if given.
if (pGI->fOpRedundant) { pGI->OpTop = pGI->BkTop; pGI->OpRight = pGI->BkRight; pGI->OpBottom = pGI->BkBottom; pGI->OpLeft = pGI->BkLeft; }
TRC_NRM((TB, _T("ORDER: Glyph index cacheId %u flAccel %u ") _T("ulCharInc %u fOpRedundant %u"), pGI->cacheId, (unsigned)pGI->flAccel, (unsigned)pGI->ulCharInc, (unsigned)pGI->fOpRedundant)); TRC_NRM((TB, _T(" bc %08lX fc %08lX Bk(%ld,%ld)-(%ld,%ld) ") _T("Op(%ld,%ld)-(%ld,%ld)"), pGI->BackColor, pGI->ForeColor, pGI->BkLeft, pGI->BkTop, pGI->BkRight, pGI->BkBottom, pGI->OpLeft, pGI->OpTop, pGI->OpRight, pGI->OpBottom)); TRC_NRM((TB, _T(" BrushOrg x %ld y %ld BrushStyle %lu x %ld y %ld"), pGI->BrushOrgX, pGI->BrushOrgY, pGI->BrushStyle, pGI->x, pGI->y));
OD_DECODE_CHECK_VARIABLE_DATALEN(uiVarDataLen, pGI->variableBytes.len);
// The structure is defined with 255 elements
if (255 < pGI->variableBytes.len) { TRC_ABORT((TB, _T("Variable bytes length too great; %u"), pGI->variableBytes.len)); hr = E_TSC_CORE_LENGTH; DC_QUIT; }
TIMERSTART; hr = _pUh->UHDrawGlyphOrder(pGI, &pGI->variableBytes); TIMERSTOP; UPDATECOUNTER(FC_INDEX_TYPE); DC_QUIT_ON_FAIL(hr);
// Restore the correct last order data.
if (pGI->fOpRedundant) { pGI->OpTop = 0; pGI->OpRight = 0; pGI->OpBottom = 0; pGI->OpLeft = 0; }
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODDecodeMultipleRects
//
// Translates wire protocol multiple clipping rects to unpacked form.
/****************************************************************************/
#define DECODE_DELTA() \
if (bDeltaZero) { \ Delta = 0; \ } \ else { \ OD_DECODE_CHECK_READ(pCurDecode, char, pDataEnd, hr); \ \ /* Sign-extend the low 7 bits of first byte into int. */ \ Delta = (int)((char)((*pCurDecode & 0x7F) | \ ((*pCurDecode & 0x40) << 1))); \ \ /* Get 2nd byte if present. */ \ if (*pCurDecode++ & ORD_CLIP_RECTS_LONG_DELTA) { \ OD_DECODE_CHECK_READ(pCurDecode, BYTE, pDataEnd, hr); \ Delta = (Delta << 8) | (*pCurDecode++); \ } \ } \
HRESULT COD::ODDecodeMultipleRects( RECT *Rects, UINT32 nDeltaEntries, CLIP_RECT_VARIABLE_CODEDDELTALIST FAR *codedDeltaList, UINT16 uiVarDataLen) { int Delta; BYTE *ZeroFlags; BOOL bDeltaZero; unsigned i; unsigned char *pCurDecode; BYTE *pDataEnd; HRESULT hr = S_OK;
DC_BEGIN_FN("ODDecodeMultipleRects");
TRC_ASSERT((nDeltaEntries > 0), (TB,_T("No rects passed in"))); OD_DECODE_CHECK_VARIABLE_DATALEN(uiVarDataLen, codedDeltaList->len);
// SECURITY: Because the OD_Decode already wrote this varible data into
// the lastOrderBuffer, we should be sure that we didn't get too much
// data at this point
if (codedDeltaList->len > ORD_MAX_CLIP_RECTS_CODEDDELTAS_LEN + ORD_MAX_CLIP_RECTS_ZERO_FLAGS_BYTES) { TRC_ABORT((TB, _T("codedDeltaList length too great; [got %u, max %u]"), codedDeltaList->len, ORD_MAX_CLIP_RECTS_CODEDDELTAS_LEN + ORD_MAX_CLIP_RECTS_ZERO_FLAGS_BYTES)); hr = E_TSC_CORE_LENGTH; DC_QUIT; }
if (nDeltaEntries > ORD_MAX_ENCODED_CLIP_RECTS) { TRC_ABORT((TB, _T("number deltas too great; [got %u, max %u]"), nDeltaEntries, ORD_MAX_ENCODED_CLIP_RECTS)); hr = E_TSC_CORE_LENGTH; DC_QUIT; }
pDataEnd = ((BYTE*)codedDeltaList->Deltas) + codedDeltaList->len;
// Get pointers to the zero flags placed before the encoded deltas, and
// the encoded deltas. Note the zero flags take 2 bits per encode
// point, 2 points per rectangle, rounded up to the nearest byte.
ZeroFlags = codedDeltaList->Deltas; pCurDecode = codedDeltaList->Deltas + ((nDeltaEntries + 1) / 2);
// All access to ZeroFlags are checked with this
CHECK_READ_N_BYTES(ZeroFlags, pDataEnd, (BYTE*)pCurDecode-(BYTE*)ZeroFlags, hr, (TB, _T("Read past end of data")));
// The first points are encoded as a delta from (0,0).
bDeltaZero = ZeroFlags[0] & ORD_CLIP_RECTS_XLDELTA_ZERO; DECODE_DELTA(); TRC_DBG((TB, _T("Start x left %d"), Delta)); Rects[0].left = Delta;
bDeltaZero = ZeroFlags[0] & ORD_CLIP_RECTS_YTDELTA_ZERO; DECODE_DELTA(); TRC_DBG((TB, _T("Start y top %d"), Delta)); Rects[0].top = Delta;
bDeltaZero = ZeroFlags[0] & ORD_CLIP_RECTS_XRDELTA_ZERO; DECODE_DELTA(); TRC_DBG((TB, _T("Start x right %d"), Delta)); Rects[0].right = Rects[0].left + Delta;
bDeltaZero = ZeroFlags[0] & ORD_CLIP_RECTS_YBDELTA_ZERO; DECODE_DELTA(); TRC_DBG((TB, _T("Start y %d"), Delta)); Rects[0].bottom = Rects[0].top + Delta;
TRC_NRM((TB, _T("Rectangle #0 l,t %d,%d - r,b %d,%d"), (int)Rects[0].left, (int)Rects[0].top, (int)Rects[0].right, (int)Rects[0].bottom));
// Decode the encoded point deltas into regular POINTs to draw.
for (i = 1; i < nDeltaEntries; i++) { // Decode the top left corner.
bDeltaZero = ZeroFlags[i / 2] & (ORD_CLIP_RECTS_XLDELTA_ZERO >> (4 * (i & 0x01))); DECODE_DELTA(); TRC_DBG((TB, _T("Delta x left %d"), Delta)); Rects[i].left = Rects[i - 1].left + Delta;
bDeltaZero = ZeroFlags[i / 2] & (ORD_CLIP_RECTS_YTDELTA_ZERO >> (4 * (i & 0x01))); DECODE_DELTA(); TRC_DBG((TB, _T("Delta y top %d"), Delta)); Rects[i].top = Rects[i - 1].top + Delta;
// and now the bottom right - note this is relative to the current
// top left rather than to the previous bottom right
bDeltaZero = ZeroFlags[i / 2] & (ORD_CLIP_RECTS_XRDELTA_ZERO >> (4 * (i & 0x01))); DECODE_DELTA(); TRC_DBG((TB, _T("Delta x right %d"), Delta)); Rects[i].right = Rects[i].left + Delta;
bDeltaZero = ZeroFlags[i / 2] & (ORD_CLIP_RECTS_YBDELTA_ZERO >> (4 * (i & 0x01))); DECODE_DELTA(); TRC_DBG((TB, _T("Delta y bottom %d"), Delta)); Rects[i].bottom = Rects[i].top + Delta;
TRC_NRM((TB, _T("Drawing rectangle #%d l,t %d,%d - r,b %d,%d"), i, (int)Rects[i].left, (int)Rects[i].top, (int)Rects[i].right, (int)Rects[i].bottom)); }
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODDecodePathPoints
//
// Decode encoded polygon and ellipse path points.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODDecodePathPoints( POINT *Points, RECT *BoundRect, BYTE FAR *pData, unsigned NumDeltaEntries, unsigned MaxNumDeltaEntries, unsigned dataLen, unsigned MaxDataLen, UINT16 uiVarDataLen, BOOL fUnClipped) { HRESULT hr = S_OK; int Delta; BOOL bDeltaZero; unsigned i; BYTE FAR * ZeroFlags; BYTE FAR * pCurDecode; BYTE FAR * pEnd;
DC_BEGIN_FN("ODDecodePathPoints");
OD_DECODE_CHECK_VARIABLE_DATALEN(uiVarDataLen, (UINT16)dataLen);
if (NumDeltaEntries > MaxNumDeltaEntries) { TRC_ABORT((TB, _T("NumDeltaEntries too great; [got %u max %u]"), NumDeltaEntries, MaxNumDeltaEntries)); hr = E_TSC_CORE_LENGTH; DC_QUIT; }
if (dataLen > MaxDataLen) { TRC_ABORT((TB,_T("Received PolyLine with too-large internal length; ") _T("[got %u max %u]"), dataLen, MaxDataLen)); hr = E_TSC_CORE_LENGTH; DC_QUIT; }
// Get pointers to the zero flags placed before the encoded
// deltas, and the encoded deltas. Note the zero flags take 2
// bits per encode point, rounded up to the nearest byte.
ZeroFlags = pData; pCurDecode = pData + ((NumDeltaEntries + 3) / 4); pEnd = ZeroFlags + dataLen;
CHECK_READ_N_BYTES(ZeroFlags, pEnd, (BYTE*)pCurDecode-(BYTE*)ZeroFlags, hr, (TB, _T("Read past end of data")));
// Decode the encoded point deltas into regular POINTs to draw.
for (i = 0; i < NumDeltaEntries; i++) { // Determine if the X delta is zero by checking the 0 flag.
bDeltaZero = ZeroFlags[i / 4] & (ORD_POLYLINE_XDELTA_ZERO >> (2 * (i & 0x03))); if (bDeltaZero) { Delta = 0; } else { OD_DECODE_CHECK_READ(pCurDecode, char, pEnd, hr); // Sign-extend the low 7 bits of first X byte into int.
Delta = (int)((char)((*pCurDecode & 0x7F) | ((*pCurDecode & 0x40) << 1)));
// Get 2nd X byte if present.
if (*pCurDecode++ & ORD_POLYLINE_LONG_DELTA) { OD_DECODE_CHECK_READ(pCurDecode, BYTE, pEnd, hr); Delta = (Delta << 8) | (*pCurDecode++); } } Points[i + 1].x = Points[i].x + Delta;
// Determine if the Y delta is zero by checking the 0 flag.
bDeltaZero = ZeroFlags[i / 4] & (ORD_POLYLINE_YDELTA_ZERO >> (2 * (i & 0x03))); if (bDeltaZero) { Delta = 0; } else { OD_DECODE_CHECK_READ(pCurDecode, char, pEnd, hr); // Sign-extend the low 7 bits of first Y byte into int.
Delta = (int)((char)((*pCurDecode & 0x7F) | ((*pCurDecode & 0x40) << 1)));
// Get 2nd Y byte if present.
if (*pCurDecode++ & ORD_POLYLINE_LONG_DELTA) { OD_DECODE_CHECK_READ(pCurDecode, BYTE, pEnd, hr); Delta = (Delta << 8) | (*pCurDecode++); } } Points[i + 1].y = Points[i].y + Delta;
if (fUnClipped) { // Update the calculated bounding rect.
if (Points[i + 1].x < BoundRect->left) BoundRect->left = Points[i + 1].x; else if (Points[i + 1].x > BoundRect->right) BoundRect->right = Points[i + 1].x;
if (Points[i + 1].y < BoundRect->top) BoundRect->top = Points[i + 1].y; else if (Points[i + 1].y > BoundRect->bottom) BoundRect->bottom = Points[i + 1].y; } }
DC_EXIT_POINT: DC_END_FN(); return hr; }
/****************************************************************************/ // ODDecodeFieldSingle
//
// Copies a single field entry from src to dest with field size
// conversion as necessary.
/****************************************************************************/ HRESULT DCINTERNAL COD::ODDecodeFieldSingle( PPDCUINT8 ppSrc, PDCVOID pDst, unsigned srcFieldLength, unsigned dstFieldLength, BOOL signedValue) { HRESULT hr = S_OK; DC_BEGIN_FN("ODDecodeFieldSingle");
if (dstFieldLength < srcFieldLength) { TRC_ABORT((TB, _T("Src size greater than dest"))); hr = E_TSC_CORE_LENGTH; DC_QUIT; }
// If the source and destination field lengths are the same, we can
// just do a copy (no type conversion required).
if (srcFieldLength == dstFieldLength) { memcpy(pDst, *ppSrc, dstFieldLength); } else { // 3 types left to consider:
// 8 bit -> 16 bit
// 8 bit -> 32 bit
// 16 bit -> 32 bit
//
// We also have to get the signed / unsigned attributes correct. If
// we try to promote a signed value using unsigned pointers, we
// will get the wrong result.
//
// e.g. Consider converting the value -1 from a INT16 to INT32
// using unsigned pointers.
//
// -1 -> DCUINT16 == 65535
// -> DCUINT32 == 65535
// -> DCINT32 == 65535
// Most common among non-coord entries: 1-byte source.
if (srcFieldLength == 1) { // Most common: 4-byte destination.
if (dstFieldLength == 4) { // Most common: unsigned
if (!signedValue) *((UINT32 FAR *)pDst) = *((BYTE FAR *)*ppSrc); else *((INT32 FAR *)pDst) = *((char FAR *)*ppSrc); } else if (dstFieldLength == 2) { if (!signedValue) *((UINT16 FAR *)pDst) = *((UINT16 UNALIGNED FAR *)*ppSrc); else *((INT16 FAR *)pDst) = *((short UNALIGNED FAR *)*ppSrc); } else { TRC_ABORT((TB,_T("src size 1->dst %u"), dstFieldLength)); hr = E_TSC_CORE_LENGTH; DC_QUIT; } } // Only thing left should be 2-byte to 4-byte.
else if (srcFieldLength == 2 && dstFieldLength == 4) { if (!signedValue) *((UINT32 FAR *)pDst) = *((UINT16 UNALIGNED FAR *)*ppSrc); else *((INT32 FAR *)pDst) = *((short UNALIGNED FAR *)*ppSrc); } else { TRC_ABORT((TB,_T("src=%u, dst=%u - unexpected"), srcFieldLength, dstFieldLength)); hr = E_TSC_CORE_LENGTH; DC_QUIT; } }
*ppSrc += srcFieldLength;
DC_EXIT_POINT: DC_END_FN(); return hr; }
#ifdef OS_WINCE
BOOL DCINTERNAL COD::ODHandleAlwaysOnTopRects(LPMULTI_SCRBLT_ORDER pSB) { DC_BEGIN_FN("ODHandleAlwaysOnTopRects");
BOOL bIntersect = FALSE; RECT rectSrc, rectIntersect, rectInvalid;
SetRect(&rectSrc, (int)pSB->nXSrc, (int)pSB->nYSrc, (int)(pSB->nXSrc + pSB->nWidth), (int)(pSB->nYSrc + pSB->nHeight));
for (DWORD j=0; j<_pUh->_UH.ulNumAOTRects; j++) { if (IntersectRect(&rectIntersect, &rectSrc, &(_pUh->_UH.rcaAOT[j]))) { bIntersect = TRUE; break; } }
if (!bIntersect) { GetUpdateRect(_pOp->OP_GetOutputWindowHandle(), &rectInvalid, FALSE); bIntersect = (IntersectRect(&rectIntersect, &rectSrc, &rectInvalid)); }
if (bIntersect) { SetRect(&rectInvalid, pSB->nLeftRect, pSB->nTopRect, pSB->nLeftRect+pSB->nWidth, pSB->nTopRect+pSB->nHeight); InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &rectInvalid, FALSE); } DC_END_FN(); return bIntersect; } #endif
|