#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); }