|
|
#include "precomp.h"
//
// OE2.CPP
// Order Encoding Second Level
//
// Copyright(c) Microsoft 1997-
//
#define MLZ_FILE_ZONE ZONE_ORDER
//
// OE2_HostStarting()
//
BOOL ASHost::OE2_HostStarting(void) { DebugEntry(ASHost::OE2_HostStarting);
//
// Set up the pointers for 2nd level encoding
//
m_oe2Tx.LastOrder[OE2_DSTBLT_ORDER ] = &m_oe2Tx.LastDstblt; m_oe2Tx.LastOrder[OE2_PATBLT_ORDER ] = &m_oe2Tx.LastPatblt; m_oe2Tx.LastOrder[OE2_SCRBLT_ORDER ] = &m_oe2Tx.LastScrblt; m_oe2Tx.LastOrder[OE2_MEMBLT_ORDER ] = &m_oe2Tx.LastMemblt; m_oe2Tx.LastOrder[OE2_MEM3BLT_ORDER ] = &m_oe2Tx.LastMem3blt; m_oe2Tx.LastOrder[OE2_TEXTOUT_ORDER ] = &m_oe2Tx.LastTextOut; m_oe2Tx.LastOrder[OE2_EXTTEXTOUT_ORDER] = &m_oe2Tx.LastExtTextOut; m_oe2Tx.LastOrder[OE2_RECTANGLE_ORDER ] = &m_oe2Tx.LastRectangle; m_oe2Tx.LastOrder[OE2_LINETO_ORDER ] = &m_oe2Tx.LastLineTo; m_oe2Tx.LastOrder[OE2_OPAQUERECT_ORDER] = &m_oe2Tx.LastOpaqueRect; m_oe2Tx.LastOrder[OE2_SAVEBITMAP_ORDER] = &m_oe2Tx.LastSaveBitmap; m_oe2Tx.LastOrder[OE2_DESKSCROLL_ORDER] = &m_oe2Tx.LastDeskScroll; m_oe2Tx.LastOrder[OE2_MEMBLT_R2_ORDER ] = &m_oe2Tx.LastMembltR2; m_oe2Tx.LastOrder[OE2_MEM3BLT_R2_ORDER] = &m_oe2Tx.LastMem3bltR2; m_oe2Tx.LastOrder[OE2_POLYGON_ORDER ] = &m_oe2Tx.LastPolygon; m_oe2Tx.LastOrder[OE2_PIE_ORDER ] = &m_oe2Tx.LastPie; m_oe2Tx.LastOrder[OE2_ELLIPSE_ORDER ] = &m_oe2Tx.LastEllipse; m_oe2Tx.LastOrder[OE2_ARC_ORDER ] = &m_oe2Tx.LastArc; m_oe2Tx.LastOrder[OE2_CHORD_ORDER ] = &m_oe2Tx.LastChord; m_oe2Tx.LastOrder[OE2_POLYBEZIER_ORDER] = &m_oe2Tx.LastPolyBezier; m_oe2Tx.LastOrder[OE2_ROUNDRECT_ORDER ] = &m_oe2Tx.LastRoundRect;
//
// Set up the last order values to a known value.
//
m_oe2Tx.LastOrderType = OE2_PATBLT_ORDER; m_oe2Tx.pLastOrder = (LPCOM_ORDER)m_oe2Tx.LastOrder[m_oe2Tx.LastOrderType];
DebugExitBOOL(ASHost::OE2_HostStarting, TRUE); return(TRUE); }
//
// OE2_HostEnded()
//
void ASHost::OE2_HostEnded(void) { DebugEntry(ASHost::OE2_HostEnded);
//
// For OUTGOING order encoding, free the last font we cached.
//
if (m_oe2Tx.LastHFONT != NULL) { ASSERT(m_pShare); ASSERT(m_usrWorkDC);
SelectFont(m_usrWorkDC, (HFONT)GetStockObject(SYSTEM_FONT));
DeleteFont(m_oe2Tx.LastHFONT); m_oe2Tx.LastHFONT = NULL; }
DebugExitVOID(ASHost::OE2_HostEnded); }
//
// OE2_SyncOutgoing()
// Called when NEW dude starts to host, a share is created, or somebody new
// joins the share.
// Resets the OUTGOING 2nd level order encoding data.
//
void ASHost::OE2_SyncOutgoing(void) { DebugEntry(ASHost::OE2_SyncOutgoing);
//
// Set up the last order values to a known value.
//
m_oe2Tx.LastOrderType = OE2_PATBLT_ORDER; m_oe2Tx.pLastOrder = (LPCOM_ORDER)m_oe2Tx.LastOrder[m_oe2Tx.LastOrderType];
//
// Clear out all the last orders.
//
ZeroMemory(&m_oe2Tx.LastDstblt, sizeof(m_oe2Tx.LastDstblt)); ((PATBLT_ORDER*)&m_oe2Tx.LastDstblt)->type = ORD_DSTBLT_TYPE;
ZeroMemory(&m_oe2Tx.LastPatblt, sizeof(m_oe2Tx.LastPatblt)); ((PATBLT_ORDER*)&m_oe2Tx.LastPatblt)->type = ORD_PATBLT_TYPE;
ZeroMemory(&m_oe2Tx.LastScrblt, sizeof(m_oe2Tx.LastScrblt)); ((PATBLT_ORDER*)&m_oe2Tx.LastScrblt)->type = ORD_SCRBLT_TYPE;
ZeroMemory(&m_oe2Tx.LastMemblt, sizeof(m_oe2Tx.LastMemblt)); ((PATBLT_ORDER*)&m_oe2Tx.LastMemblt)->type = ORD_MEMBLT_TYPE;
ZeroMemory(&m_oe2Tx.LastMem3blt,sizeof(m_oe2Tx.LastMem3blt)); ((PATBLT_ORDER*)&m_oe2Tx.LastMem3blt)->type = ORD_MEM3BLT_TYPE;
ZeroMemory(&m_oe2Tx.LastTextOut, sizeof(m_oe2Tx.LastTextOut)); ((PATBLT_ORDER*)&m_oe2Tx.LastTextOut)->type = ORD_TEXTOUT_TYPE;
ZeroMemory(&m_oe2Tx.LastExtTextOut, sizeof(m_oe2Tx.LastExtTextOut)); ((PATBLT_ORDER*)&m_oe2Tx.LastExtTextOut)->type = ORD_EXTTEXTOUT_TYPE;
ZeroMemory(&m_oe2Tx.LastRectangle, sizeof(m_oe2Tx.LastRectangle)); ((PATBLT_ORDER*)&m_oe2Tx.LastRectangle)->type = ORD_RECTANGLE_TYPE;
ZeroMemory(&m_oe2Tx.LastPolygon, sizeof(m_oe2Tx.LastPolygon)); ((POLYGON_ORDER*)&m_oe2Tx.LastPolygon)->type = ORD_POLYGON_TYPE;
ZeroMemory(&m_oe2Tx.LastPie, sizeof(m_oe2Tx.LastPie)); ((PIE_ORDER*)&m_oe2Tx.LastPie)->type = ORD_PIE_TYPE;
ZeroMemory(&m_oe2Tx.LastEllipse, sizeof(m_oe2Tx.LastEllipse)); ((ELLIPSE_ORDER*)&m_oe2Tx.LastEllipse)->type = ORD_ELLIPSE_TYPE;
ZeroMemory(&m_oe2Tx.LastArc, sizeof(m_oe2Tx.LastArc)); ((ARC_ORDER*)&m_oe2Tx.LastArc)->type = ORD_ARC_TYPE;
ZeroMemory(&m_oe2Tx.LastChord, sizeof(m_oe2Tx.LastChord)); ((CHORD_ORDER*)&m_oe2Tx.LastChord)->type = ORD_CHORD_TYPE;
ZeroMemory(&m_oe2Tx.LastPolyBezier, sizeof(m_oe2Tx.LastPolyBezier)); ((POLYBEZIER_ORDER*)&m_oe2Tx.LastPolyBezier)->type = ORD_POLYBEZIER_TYPE;
ZeroMemory(&m_oe2Tx.LastRoundRect, sizeof(m_oe2Tx.LastRoundRect)); ((ROUNDRECT_ORDER*)&m_oe2Tx.LastRoundRect)->type = ORD_ROUNDRECT_TYPE;
ZeroMemory(&m_oe2Tx.LastLineTo, sizeof(m_oe2Tx.LastLineTo)); ((PATBLT_ORDER*)&m_oe2Tx.LastLineTo)->type = ORD_LINETO_TYPE;
ZeroMemory(&m_oe2Tx.LastOpaqueRect, sizeof(m_oe2Tx.LastOpaqueRect)); ((PATBLT_ORDER*)&m_oe2Tx.LastOpaqueRect)->type = ORD_OPAQUERECT_TYPE;
ZeroMemory(&m_oe2Tx.LastSaveBitmap, sizeof(m_oe2Tx.LastSaveBitmap)); ((PATBLT_ORDER*)&m_oe2Tx.LastSaveBitmap)->type = ORD_SAVEBITMAP_TYPE;
ZeroMemory(&m_oe2Tx.LastDeskScroll, sizeof(m_oe2Tx.LastDeskScroll)); ((PATBLT_ORDER*)&m_oe2Tx.LastDeskScroll)->type = ORD_DESKSCROLL_TYPE;
ZeroMemory(&m_oe2Tx.LastMembltR2, sizeof(m_oe2Tx.LastMembltR2)); ((PATBLT_ORDER*)&m_oe2Tx.LastMembltR2)->type = ORD_MEMBLT_R2_TYPE;
ZeroMemory(&m_oe2Tx.LastMem3bltR2, sizeof(m_oe2Tx.LastMem3bltR2)); ((PATBLT_ORDER*)&m_oe2Tx.LastMem3bltR2)->type = ORD_MEM3BLT_R2_TYPE;
ZeroMemory(&m_oe2Tx.LastBounds, sizeof(m_oe2Tx.LastBounds));
DebugExitVOID(ASHost::OE2_SyncOutgoing); }
//
// OE2_EncodeOrder()
//
TSHR_UINT16 ASHost::OE2_EncodeOrder ( LPINT_ORDER pIntOrder, void * pBuffer, TSHR_UINT16 cbBufferSize ) { POE2ETFIELD pTableEntry; LPSTR pNextFreeSpace; UINT thisFlag = 0; RECT Rect; TSHR_RECT16 Rect16; UINT cbEncodedOrderSize; UINT cbMaxEncodedOrderSize; LPBYTE pControlFlags; LPTSHR_UINT32_UA pEncodingFlags; LPSTR pEncodedOrder; UINT numEncodingFlagBytes; LPSTR pVariableField; BOOL useDeltaCoords; UINT i; LPCOM_ORDER pComOrder; UINT fieldLength; UINT numReps;
DebugEntry(ASHost::OE2_EncodeOrder);
#ifdef ORDER_TRACE
if (OE2_DebugOrderTrace) { TrcUnencodedOrder(pIntOrder); } #endif // ORDER_TRACE
//
// Set up a pointer to the Common Order.
//
pComOrder = (LPCOM_ORDER)&(pIntOrder->OrderHeader.Common);
//
// Calculate the maximum bytes required to encode this order.
//
if (pComOrder->OrderHeader.fOrderFlags & OF_PRIVATE) { //
// Private order.
//
cbMaxEncodedOrderSize = OE2_CONTROL_FLAGS_FIELD_SIZE + COM_ORDER_SIZE(pComOrder); } else { //
// Normal (not Private) order.
//
cbMaxEncodedOrderSize = OE2_CONTROL_FLAGS_FIELD_SIZE + OE2_TYPE_FIELD_SIZE + OE2_MAX_FIELD_FLAG_BYTES + OE2_MAX_ADDITIONAL_BOUNDS_BYTES + COM_ORDER_SIZE(pComOrder); }
//
// If we are not absolutely certain that the supplied buffer is big
// enough to hold this order (encoded) then return immediately.
//
if (cbMaxEncodedOrderSize > cbBufferSize) { cbEncodedOrderSize = 0; goto encode_order_exit; }
//
// Set up some local variables to access the encoding buffer in various
// ways.
//
pControlFlags = &((PDCEO2ORDER)pBuffer)->ControlFlags; pEncodedOrder = (LPSTR)&((PDCEO2ORDER)pBuffer)->EncodedOrder[0]; pEncodingFlags = (LPTSHR_UINT32_UA)&pEncodedOrder[0];
//
// Initialise the control flags field to indicate this is a standard
// encoding (ie the rest of the control flags have the meaning defined
// by the rest of the OE2_CF_XXX definitions).
//
*pControlFlags = OE2_CF_STANDARD_ENC;
//
// If the private flag is set then we must return the encoded order
// as it is (ie without doing any further encoding).
//
if (pComOrder->OrderHeader.fOrderFlags & OF_PRIVATE) { *pControlFlags |= OE2_CF_UNENCODED;
cbEncodedOrderSize = SBC_CopyPrivateOrderData( (LPBYTE)pEncodedOrder, pComOrder, cbMaxEncodedOrderSize - FIELD_OFFSET(DCEO2ORDER, EncodedOrder) );
cbEncodedOrderSize += FIELD_OFFSET(DCEO2ORDER, EncodedOrder);
TRACE_OUT(( "PRIVATE order size %u", cbEncodedOrderSize));
goto encode_order_exit; }
//
// If the type of this order is different to the last order encoded,
// get a pointer to the last order of this type encoded and remember
// what type of order it is. We must also tell the decoding end that
// this type is different from the last one, so set the new type flag
// and copy type into buffer
//
// The "type" field come before the encoding flags so that the number
// of flags we have can vary depending on the order. Set up a pointer
// to these flags here depending on whether or not we have to encode
// the order type.
//
if (TEXTFIELD(pComOrder)->type != ((PATBLT_ORDER*)m_oe2Tx.pLastOrder)->type) { TRACE_OUT(( "change type from %04X to %04X", LOWORD(((PATBLT_ORDER*)m_oe2Tx.pLastOrder)->type), LOWORD(TEXTFIELD(pComOrder)->type)));
m_oe2Tx.LastOrderType = OE2GetOrderType(pComOrder); m_oe2Tx.pLastOrder = (LPCOM_ORDER)m_oe2Tx.LastOrder[m_oe2Tx.LastOrderType]; *(LPBYTE)pEncodedOrder = m_oe2Tx.LastOrderType; *pControlFlags |= OE2_CF_TYPE_CHANGE; pEncodingFlags = (LPTSHR_UINT32_UA)&pEncodedOrder[1]; } else { pEncodingFlags = (LPTSHR_UINT32_UA)&pEncodedOrder[0]; }
//
// Work out how many bytes we will need to store the encoding flags in.
// (We have a flag for each field in the order structure). This code
// we have written will cope with up to a DWORD of encoding flags.
//
numEncodingFlagBytes= (s_etable.NumFields[m_oe2Tx.LastOrderType]+7)/8; if (numEncodingFlagBytes > OE2_MAX_FIELD_FLAG_BYTES) { ERROR_OUT(( "Too many flag bytes (%d) for this code", numEncodingFlagBytes)); }
//
// Now we know how many bytes make up the flags we can get a pointer
// to the position at which to start encoding the orders fields into.
//
pNextFreeSpace = ((LPSTR)pEncodingFlags) + numEncodingFlagBytes;
//
// Calculate the bounds. If these are the same as those already in the
// order header then there is no need to send any bounds because we can
// recalculate them at the receiver.
//
m_pShare->OD2_CalculateBounds(pComOrder, &Rect, FALSE, m_pShare->m_pasLocal); TSHR_RECT16_FROM_RECT(&Rect16, Rect); if (memcmp(&(pComOrder->OrderHeader.rcsDst), &Rect16, sizeof(Rect16))) { TRACE_OUT(( "copy bounding rect")); OE2EncodeBounds((LPBYTE*)&pNextFreeSpace, &pComOrder->OrderHeader.rcsDst); *pControlFlags |= OE2_CF_BOUNDS; }
//
// Before we do the field encoding (using s_etable) check all the field
// entries flagged as coordinates to see if we can switch to
// OE2_CF_DELTACOORDS mode.
//
pTableEntry = s_etable.pFields[m_oe2Tx.LastOrderType];
useDeltaCoords = TRUE;
//
// Loop through each fixed field in this order structure...
//
while ( useDeltaCoords && (pTableEntry->FieldPos != 0) && ((pTableEntry->FieldType & OE2_ETF_FIXED) != 0) ) { //
// If this field entry is a coordinate then compare it to the
// previous coordinate we sent for this field to determine whether
// we can send it as a delta
//
if (pTableEntry->FieldType & OE2_ETF_COORDINATES) { useDeltaCoords = OE2CanUseDeltaCoords(((LPSTR)pComOrder->abOrderData) + pTableEntry->FieldPos, ((LPSTR)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos, pTableEntry->FieldUnencodedLen, pTableEntry->FieldSigned, 1); } pTableEntry++; }
//
// Loop through each of the variable fields...
//
pVariableField = ((LPSTR)(pComOrder->abOrderData)) + pTableEntry->FieldPos; while (useDeltaCoords && (pTableEntry->FieldPos != 0)) { //
// The length of the field (in bytes) is given in the first
// TSHR_UINT32 of the variable sized field structure.
//
fieldLength = *(TSHR_UINT32 FAR *)pVariableField; pVariableField += sizeof(TSHR_UINT32);
//
// If this field entry is a coordinate then compare it to the
// previous coordinate we sent for this field to determine whether
// we can send it as a delta
//
if (pTableEntry->FieldType & OE2_ETF_COORDINATES) { //
// The number of coordinates is given by the number of bytes in
// the field divided by the size of each entry
//
numReps = fieldLength / pTableEntry->FieldUnencodedLen; useDeltaCoords = OE2CanUseDeltaCoords(pVariableField, ((LPSTR)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos, pTableEntry->FieldUnencodedLen, pTableEntry->FieldSigned, numReps); }
//
// Move on to the next field in the order structure. Note that
// variable sized fields are packed on the send side. (ie
// increment pVariableField by fieldLength not by
// pTableEntry->FieldLen).
//
pVariableField += fieldLength; pTableEntry++; }
if (useDeltaCoords) { *pControlFlags |= OE2_CF_DELTACOORDS; }
//
// Now do the encoding...
//
pTableEntry = s_etable.pFields[m_oe2Tx.LastOrderType];
//
// Clear the encoding flag bytes.
//
for (i = 0; i < numEncodingFlagBytes; i++) { ((LPBYTE)pEncodingFlags)[i] = 0; }
thisFlag = 0x00000001;
//
// First process all the fixed size fields in the order structure...
// (These come before the variable sized fields).
//
while ( (pTableEntry->FieldPos != 0) && (pTableEntry->FieldType & OE2_ETF_FIXED) ) { //
// If the field has changed since it was previously transmitted then
// we need to send it again.
//
if (memcmp( ((LPBYTE)(pComOrder->abOrderData)) + pTableEntry->FieldPos, ((LPBYTE)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos, pTableEntry->FieldUnencodedLen)) { //
// Update the encoding flags
//
*pEncodingFlags |= thisFlag;
//
// If we are encoding in delta coordinate mode and this field
// is a coordinate...
//
if (useDeltaCoords && ((pTableEntry->FieldType & OE2_ETF_COORDINATES) != 0) ) { OE2CopyToDeltaCoords((LPTSHR_INT8*)&pNextFreeSpace, (((LPSTR)pComOrder->abOrderData) + pTableEntry->FieldPos), (((LPSTR)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos), pTableEntry->FieldUnencodedLen, pTableEntry->FieldSigned, 1); } else { //
// Update the data to be sent
//
OE2EncodeField(((LPBYTE)(pComOrder->abOrderData)) + pTableEntry->FieldPos, (LPBYTE*)&pNextFreeSpace, pTableEntry->FieldUnencodedLen, pTableEntry->FieldEncodedLen, pTableEntry->FieldSigned, 1);
}
//
// Save the current value for comparison next time.
//
memcpy(((LPBYTE)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos, ((LPBYTE)(pComOrder->abOrderData)) + pTableEntry->FieldPos, pTableEntry->FieldUnencodedLen); }
//
// Move on to the next field in the structure.
//
thisFlag = thisFlag << 1; pTableEntry++; }
//
// Now process the variable sized entries...
//
pVariableField = ((LPSTR)(pComOrder->abOrderData)) + pTableEntry->FieldPos; while (pTableEntry->FieldPos != 0) { //
// The length of the field is given in the first UINT of the
// variable sized field structure.
//
fieldLength = *(TSHR_UINT32 FAR *)pVariableField;
//
// If the field has changed (either in size or in contents) then we
// need to copy it across.
//
if (memcmp(pVariableField, ((LPBYTE)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos, fieldLength + sizeof(TSHR_UINT32))) { //
// Update the encoding flags
//
*pEncodingFlags |= thisFlag;
//
// Work out how many elements we are encoding for this field.
//
numReps = fieldLength / pTableEntry->FieldUnencodedLen;
//
// Fill in the length of the field into the encoded buffer
// (this is always encoded in a single byte), then increment
// the pointer ready to encode the actual field.
//
// Note that the length must always be set to the length
// required for regular second level encoding of the field,
// regardless of whether regular encoding or delta encoding is
// used.
//
ASSERT(numReps * pTableEntry->FieldEncodedLen < 256); *pNextFreeSpace = (BYTE)(numReps * pTableEntry->FieldEncodedLen); pNextFreeSpace++;
//
// If we are encoding in delta coordinate mode and this field
// is a coordinate...
//
if (useDeltaCoords && ((pTableEntry->FieldType & OE2_ETF_COORDINATES) != 0) ) { //
// Encode using delta coordinate encoding
//
OE2CopyToDeltaCoords((LPTSHR_INT8*)&pNextFreeSpace, pVariableField + sizeof(TSHR_UINT32), ((LPSTR)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos + sizeof(TSHR_UINT32), pTableEntry->FieldUnencodedLen, pTableEntry->FieldSigned, numReps); } else { //
// Use regular encoding
//
OE2EncodeField((LPBYTE)(pVariableField + sizeof(TSHR_UINT32)), (LPBYTE*)&pNextFreeSpace, pTableEntry->FieldUnencodedLen, pTableEntry->FieldEncodedLen, pTableEntry->FieldSigned, numReps);
}
//
// Keep data for comparison next time.
//
// Note that the variable fields of pLastOrder are not packed
// (unlike the order which we are encoding), so we can use
// pTableEntry->FieldPos to get the start of the field.
//
memcpy(((LPSTR)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos, pVariableField, fieldLength + sizeof(TSHR_UINT32)); }
//
// Move on to the next field in the order structure, remembering to
// step. Note that past the size field. variable sized fields are
// packed on the send side. (ie increment pVariableField by
// fieldLength not by pTableEntry->FieldLen).
//
pVariableField += fieldLength + sizeof(TSHR_UINT32);
//
// Make sure that we are at the next 4-byte boundary
//
if ((((UINT_PTR)pVariableField) % 4) != 0) { pVariableField += 4 - (((UINT_PTR)pVariableField) % 4); }
thisFlag = thisFlag << 1; pTableEntry++; }
//
// record some stats:
// Increment the count of order bytes of this type
// Set the flags on for the fields which have been encoded
//
cbEncodedOrderSize = (UINT)(pNextFreeSpace - (LPSTR)pBuffer);
TRACE_OUT(( "return %u flags %x,%x", cbEncodedOrderSize, (UINT)*pControlFlags, *pEncodingFlags));
encode_order_exit: //
// "Insurance" check that we have not overwritten the end of the buffer.
//
if (cbEncodedOrderSize > cbBufferSize) { //
// Oh dear!
// We should never take this path - if we do, the code has gone
// seriously wrong.
//
ERROR_OUT(( "End of buffer overwritten! enc(%d) buff(%d) type(%d)", cbEncodedOrderSize, cbBufferSize, m_oe2Tx.LastOrderType)); }
//
// Return the length of the encoded order
//
DebugExitDWORD(ASShare::OE2_EncodeOrder, cbEncodedOrderSize); return((TSHR_UINT16)cbEncodedOrderSize); }
//
//
// OE2GetOrderType() - see oe2.h
//
//
BYTE OE2GetOrderType(LPCOM_ORDER pOrder) { BYTE type = 0xff;
DebugEntry(OE2GetOrderType);
TRACE_OUT(( "order type = %hx", TEXTFIELD(pOrder)->type));
switch ( TEXTFIELD(pOrder)->type ) { case ORD_DSTBLT_TYPE: type = OE2_DSTBLT_ORDER; break;
case ORD_PATBLT_TYPE: type = OE2_PATBLT_ORDER; break;
case ORD_SCRBLT_TYPE: type = OE2_SCRBLT_ORDER; break;
case ORD_MEMBLT_TYPE: type = OE2_MEMBLT_ORDER; break;
case ORD_MEM3BLT_TYPE: type = OE2_MEM3BLT_ORDER; break;
case ORD_MEMBLT_R2_TYPE: type = OE2_MEMBLT_R2_ORDER; break;
case ORD_MEM3BLT_R2_TYPE: type = OE2_MEM3BLT_R2_ORDER; break;
case ORD_TEXTOUT_TYPE: type = OE2_TEXTOUT_ORDER; break;
case ORD_EXTTEXTOUT_TYPE: type = OE2_EXTTEXTOUT_ORDER; break;
case ORD_RECTANGLE_TYPE: type = OE2_RECTANGLE_ORDER; break;
case ORD_LINETO_TYPE: type = OE2_LINETO_ORDER; break;
case ORD_OPAQUERECT_TYPE: type = OE2_OPAQUERECT_ORDER; break;
case ORD_SAVEBITMAP_TYPE: type = OE2_SAVEBITMAP_ORDER; break;
case ORD_DESKSCROLL_TYPE: type = OE2_DESKSCROLL_ORDER; break;
case ORD_POLYGON_TYPE: type = OE2_POLYGON_ORDER; break;
case ORD_PIE_TYPE: type = OE2_PIE_ORDER; break;
case ORD_ELLIPSE_TYPE: type = OE2_ELLIPSE_ORDER; break;
case ORD_ARC_TYPE: type = OE2_ARC_ORDER; break;
case ORD_CHORD_TYPE: type = OE2_CHORD_ORDER; break;
case ORD_POLYBEZIER_TYPE: type = OE2_POLYBEZIER_ORDER; break;
case ORD_ROUNDRECT_TYPE: type = OE2_ROUNDRECT_ORDER; break;
default: ERROR_OUT(( "Unknown order type %x", TEXTFIELD(pOrder)->type));
}
DebugExitDWORD(OE2GetOrderType, type); return(type); }
//
// Given a pointer to 2 arrays, work out if the difference between every
// element at corresponding indices in the arrays can be represented by a
// delta (1 byte integer).
//
// ARRAY1 - The first array
// ARRAY2 - The second array
// NUMELEMENTS - The number of elements in the arrays
// DELTASPOSSIBLE - The "return value". Set to TRUE if all differences
// can be represented by deltas, FALSE if not.
//
#define CHECK_DELTA_ARRAY(ARRAY1, ARRAY2, NUMELEMENTS, DELTASPOSSIBLE) \
{ \ UINT index; \ int delta; \ (DELTASPOSSIBLE) = TRUE; \ for (index=0 ; index<(NUMELEMENTS) ; index++) \ { \ delta = (ARRAY1)[index] - (ARRAY2)[index]; \ if (delta != (int)(TSHR_INT8)delta) \ { \ (DELTASPOSSIBLE) = FALSE; \ break; \ } \ } \ }
//
//
// Name: OE2CanUseDeltaCoords
//
// Purpose: This function compares two arrays containing a number of
// coordinate values. If the difference between each
// coordinate pair can be expressed as a byte sized delta
// quantity then the function returns TRUE otherwise it returns
// FALSE.
//
// Returns: TRUE if delta coords can be used, FALSE otherwise
//
// Params: IN pNewCoords - Pointer to the new array
// IN pOldCoords - Pointer to the existing array
// IN fieldLength - The size (in bytes) of each element in the
// array.
// IN signedValue - TRUE of the elements in the arrays are
// signed values, FALSE otherwise.
// IN numElements - The number of elements in the arrays.
//
//
BOOL OE2CanUseDeltaCoords(void * pNewCoords, void * pOldCoords, UINT fieldLength, BOOL signedValue, UINT numElements) { LPTSHR_INT16 pNew16Signed = (LPTSHR_INT16)pNewCoords; LPTSHR_INT32 pNew32Signed = (LPTSHR_INT32)pNewCoords; LPTSHR_UINT16 pNew16Unsigned = (LPTSHR_UINT16)pNewCoords; LPUINT pNew32Unsigned = (LPUINT)pNewCoords; LPTSHR_INT16 pOld16Signed = (LPTSHR_INT16)pOldCoords; LPTSHR_INT32 pOld32Signed = (LPTSHR_INT32)pOldCoords; LPTSHR_UINT16 pOld16Unsigned = (LPTSHR_UINT16)pOldCoords; LPUINT pOld32Unsigned = (LPUINT)pOldCoords; BOOL useDeltaCoords;
DebugEntry(OE2CanUseDeltaCoords);
switch (fieldLength) { case 2: { if (signedValue) { CHECK_DELTA_ARRAY(pNew16Signed, pOld16Signed, numElements, useDeltaCoords); } else { CHECK_DELTA_ARRAY(pNew16Unsigned, pOld16Unsigned, numElements, useDeltaCoords); } } break;
case 4: { if (signedValue) { CHECK_DELTA_ARRAY(pNew32Signed, pOld32Signed, numElements, useDeltaCoords); } else { CHECK_DELTA_ARRAY(pNew32Unsigned, pOld32Unsigned, numElements, useDeltaCoords); } } break;
default: { ERROR_OUT(( "Bad field length %d", fieldLength)); useDeltaCoords = FALSE; } break; }
DebugExitDWORD(OE2CanUseDeltaCoords, useDeltaCoords); return(useDeltaCoords); }
//
// Given two arrays, fill in a delta array with each element holding
// ARRAY1[i] - ARRAY2[i]
//
// DESTARRAY - The delta array. This is an array of TSHR_INT8s
// ARRAY1 - The first array
// ARRAY2 - The second array
// NUMELEMENTS - The number of elements in the arrays
//
//
#define COPY_TO_DELTA_ARRAY(DESTARRAY, ARRAY1, ARRAY2, NUMELEMENTS) \
{ \ UINT index; \ for (index=0 ; index<(NUMELEMENTS) ; index++) \ { \ (DESTARRAY)[index] = (TSHR_INT8)((ARRAY1)[index] - (ARRAY2)[index]); \ } \ }
//
//
// Name: OE2CopyToDeltaCoords
//
// Purpose: Copies an array of coordinate values to an array of delta
// (byte sized) coordinate values relative to a reference array
// of coordinate values.
//
// Returns: Nothing
//
// Params: IN/OUT ppDestination - Pointer to the start of the
// destination delta array. This is
// updated to point to the byte following
// the last delta on exit.
// IN pNewCoords - Pointer to the new array
// IN pOldCoords - Pointer to the reference array
// IN fieldLength - The size (in bytes) of each element in
// New/OldCoords arrays.
// IN signedValue - TRUE of the elements in the coords
// arrays are signed values, FALSE
// otherwise.
// IN numElements - The number of elements in the arrays.
//
// Operation: The caller should call OE2CanUseDeltaCoords() before calling
// this function to ensure that the differences can be
// encoded using delta coordingates.
//
//
void OE2CopyToDeltaCoords(LPTSHR_INT8* ppDestination, void * pNewCoords, void * pOldCoords, UINT fieldLength, BOOL signedValue, UINT numElements) {
LPTSHR_INT16 pNew16Signed = (LPTSHR_INT16)pNewCoords; LPTSHR_INT32 pNew32Signed = (LPTSHR_INT32)pNewCoords; LPTSHR_UINT16 pNew16Unsigned = (LPTSHR_UINT16)pNewCoords; LPUINT pNew32Unsigned = (LPUINT)pNewCoords; LPTSHR_INT16 pOld16Signed = (LPTSHR_INT16)pOldCoords; LPTSHR_INT32 pOld32Signed = (LPTSHR_INT32)pOldCoords; LPTSHR_UINT16 pOld16Unsigned = (LPTSHR_UINT16)pOldCoords; LPUINT pOld32Unsigned = (LPUINT)pOldCoords;
DebugEntry(OE2CopyToDeltaCoords);
switch (fieldLength) { case 2: { if (signedValue) { COPY_TO_DELTA_ARRAY(*ppDestination, pNew16Signed, pOld16Signed, numElements); } else { COPY_TO_DELTA_ARRAY(*ppDestination, pNew16Unsigned, pOld16Unsigned, numElements); } } break;
case 4: { if (signedValue) { COPY_TO_DELTA_ARRAY(*ppDestination, pNew32Signed, pOld32Signed, numElements); } else { COPY_TO_DELTA_ARRAY(*ppDestination, pNew32Unsigned, pOld32Unsigned, numElements); } } break;
default: { ERROR_OUT(( "Bad field length %d", fieldLength)); } break; }
//
// Update the next free position in the destination buffer
//
*ppDestination += numElements; DebugExitVOID(OE2CopyToDeltaCoords); }
//
// OE2EncodeBounds()
//
void ASHost::OE2EncodeBounds ( LPBYTE * ppNextFreeSpace, LPTSHR_RECT16 pRect ) { LPBYTE pFlags;
DebugEntry(ASHost::OE2EncodeBounds);
//
// The encoding used is a byte of flags followed by a variable number
// of 16bit coordinate values and 8bit delta coordinate values (which
// may be interleaved).
//
//
// The first byte of the encoding will contain the flags that represent
// how the coordinates of the rectangle were encoded.
//
pFlags = *ppNextFreeSpace; *pFlags = 0; (*ppNextFreeSpace)++;
//
// For each of the four coordinate values in the rectangle: If the
// coordinate has not changed then the encoding is null. If the
// coordinate can be encoded as a delta then do so and set the
// appropriate flag. Otherwise copy the coordinate as a 16bit value
// and set the appropriate flag.
//
if (m_oe2Tx.LastBounds.left != pRect->left) { if (OE2CanUseDeltaCoords(&pRect->left, &m_oe2Tx.LastBounds.left, sizeof(pRect->left), TRUE, // signed value
1)) { OE2CopyToDeltaCoords((LPTSHR_INT8*)ppNextFreeSpace, &pRect->left, &m_oe2Tx.LastBounds.left, sizeof(pRect->left), TRUE, // signed value
1); *pFlags |= OE2_BCF_DELTA_LEFT; } else { *((LPTSHR_UINT16)(*ppNextFreeSpace)) = pRect->left; *pFlags |= OE2_BCF_LEFT; (*ppNextFreeSpace) = (*ppNextFreeSpace) + sizeof(TSHR_UINT16); } }
if (m_oe2Tx.LastBounds.top != pRect->top) { if (OE2CanUseDeltaCoords(&pRect->top, &m_oe2Tx.LastBounds.top, sizeof(pRect->top), TRUE, // signed value
1)) { OE2CopyToDeltaCoords((LPTSHR_INT8*)ppNextFreeSpace, &pRect->top, &m_oe2Tx.LastBounds.top, sizeof(pRect->top), TRUE, // signed value
1); *pFlags |= OE2_BCF_DELTA_TOP; } else { *((LPTSHR_UINT16)(*ppNextFreeSpace)) = pRect->top; *pFlags |= OE2_BCF_TOP; (*ppNextFreeSpace) = (*ppNextFreeSpace) + sizeof(TSHR_UINT16); } }
if (m_oe2Tx.LastBounds.right != pRect->right) { if (OE2CanUseDeltaCoords(&pRect->right, &m_oe2Tx.LastBounds.right, sizeof(pRect->right), TRUE, // signed value
1)) { OE2CopyToDeltaCoords((LPTSHR_INT8*)ppNextFreeSpace, &pRect->right, &m_oe2Tx.LastBounds.right, sizeof(pRect->right), TRUE, // signed value
1); *pFlags |= OE2_BCF_DELTA_RIGHT; } else { *((LPTSHR_UINT16)(*ppNextFreeSpace)) = pRect->right; *pFlags |= OE2_BCF_RIGHT; (*ppNextFreeSpace) = (*ppNextFreeSpace) + sizeof(TSHR_UINT16); } }
if (m_oe2Tx.LastBounds.bottom != pRect->bottom) { if (OE2CanUseDeltaCoords(&pRect->bottom, &m_oe2Tx.LastBounds.bottom, sizeof(pRect->bottom), TRUE, // signed value
1)) { OE2CopyToDeltaCoords((LPTSHR_INT8*)ppNextFreeSpace, &pRect->bottom, &m_oe2Tx.LastBounds.bottom, sizeof(pRect->bottom), TRUE, // signed value
1); *pFlags |= OE2_BCF_DELTA_BOTTOM; } else { *((LPTSHR_UINT16)(*ppNextFreeSpace)) = pRect->bottom; *pFlags |= OE2_BCF_BOTTOM; (*ppNextFreeSpace) = (*ppNextFreeSpace) + sizeof(TSHR_UINT16); } }
//
// Copy the rectangle for reference with the next encoding.
//
m_oe2Tx.LastBounds = *pRect;
DebugExitVOID(ASHost::OE2EncodeBounds); }
//
// OE2_UseFont()
//
BOOL ASHost::OE2_UseFont ( LPSTR pName, TSHR_UINT16 facelength, TSHR_UINT16 CodePage, TSHR_UINT16 MaxHeight, TSHR_UINT16 Height, TSHR_UINT16 Width, TSHR_UINT16 Weight, TSHR_UINT16 flags ) { BOOL rc = TRUE;
DebugEntry(ASHost::OE2_UseFont);
if ((!m_oe2Tx.LastHFONT) || (m_oe2Tx.LastFontFaceLen != facelength) || (memcmp(m_oe2Tx.LastFaceName, pName, facelength)) || (m_oe2Tx.LastCodePage != CodePage) || (m_oe2Tx.LastFontHeight != Height ) || (m_oe2Tx.LastFontWidth != Width ) || (m_oe2Tx.LastFontWeight != Weight ) || (m_oe2Tx.LastFontFlags != flags )) { memcpy(m_oe2Tx.LastFaceName, pName, facelength); m_oe2Tx.LastFaceName[facelength] = '\0'; m_oe2Tx.LastFontFaceLen = facelength; m_oe2Tx.LastCodePage = CodePage; m_oe2Tx.LastFontHeight = Height; m_oe2Tx.LastFontWidth = Width; m_oe2Tx.LastFontWeight = Weight; m_oe2Tx.LastFontFlags = flags;
rc = m_pShare->USR_UseFont(m_usrWorkDC, &m_oe2Tx.LastHFONT, &m_oe2Tx.LastFontMetrics, (LPSTR)m_oe2Tx.LastFaceName, CodePage, MaxHeight, Height, Width, Weight, flags); }
DebugExitBOOL(ASHost::OE2_UseFont, rc); return(rc); }
//
// Copy an array of source elements to an array of destination elements,
// converting the types as the copy takes place.
//
// DESTARRAY - The destination array
// SRCARRAY - The source array
// DESTTYPE - The type of the elements in the destination array
// NUMELEMENTS - The number of elements in the array
//
//
#define CONVERT_ARRAY(DESTARRAY, SRCARRAY, DESTTYPE, NUMELEMENTS) \
{ \ UINT index; \ for (index=0 ; index<(NUMELEMENTS) ; index++) \ { \ (DESTARRAY)[index] = (DESTTYPE)(SRCARRAY)[index]; \ } \ }
//
// OE2EncodeField - see oe2.h
//
void OE2EncodeField(void * pSrc, LPBYTE* ppDest, UINT srcFieldLength, UINT destFieldLength, BOOL signedValue, UINT numElements) { LPTSHR_UINT8 pSrc8 = (LPTSHR_UINT8)pSrc; LPTSHR_INT16 pSrc16Signed = (LPTSHR_INT16)pSrc; LPTSHR_INT32 pSrc32Signed = (LPTSHR_INT32)pSrc; LPTSHR_INT8 pDest8Signed = (LPTSHR_INT8)*ppDest; LPTSHR_INT16_UA pDest16Signed = (LPTSHR_INT16_UA)*ppDest;
//
// Note that the source fields may not be aligned correctly, so we use
// unaligned pointers. The destination is aligned correctly.
//
DebugEntry(OE2EncodeField);
//
// We can ignore signed values since we only ever truncate the data.
// Consider the case where we have a 16 bit integer that we want to
// convert to 8 bits. We know our values are permissable within the
// lower integer size (ie. we know the unsigned value will be less
// than 256 of that a signed value will be -128 >= value >= 127), so we
// just need to make sure that we have the right high bit set.
//
// But this must be the case for a 16-bit equivalent of an 8-bit
// number. No problems - just take the truncated integer.
//
//
// Make sure that the destination field length is larger or equal to
// the source field length. If it isn't, something has gone wrong.
//
if (srcFieldLength < destFieldLength) { ERROR_OUT(( "Source field length %d is smaller than destination %d", srcFieldLength, destFieldLength)); DC_QUIT; }
//
// If the source and destination field lengths are the same, we can
// just do a copy (no type conversion required).
//
if (srcFieldLength == destFieldLength) { memcpy(*ppDest, pSrc, destFieldLength * numElements); } else { //
// We know that srcFieldLength must be greater than destFieldLength
// because of our checks above. So there are only three
// conversions to consider:
//
// 16 bit -> 8 bit
// 32 bit -> 8 bit
// 32 bit -> 16 bit
//
// We can ignore the sign as all we are ever doing is truncating
// the integer.
//
if ((srcFieldLength == 4) && (destFieldLength == 1)) { CONVERT_ARRAY(pDest8Signed, pSrc32Signed, TSHR_INT8, numElements); } else if ((srcFieldLength == 4) && (destFieldLength == 2)) { CONVERT_ARRAY(pDest16Signed, pSrc32Signed, TSHR_INT16, numElements); } else if ((srcFieldLength == 2) && (destFieldLength == 1)) { CONVERT_ARRAY(pDest8Signed, pSrc16Signed, TSHR_INT8, numElements); } else { ERROR_OUT(( "Bad conversion, dest length = %d, src length = %d", destFieldLength, srcFieldLength)); } }
DC_EXIT_POINT: *ppDest += destFieldLength * numElements; DebugExitVOID(OE2EncodeField); }
|