You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2994 lines
112 KiB
2994 lines
112 KiB
/****************************************************************************/
|
|
// 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
|
|
|