windows-nt/Source/XPSP1/NT/termsrv/remdsk/rds/as/cpi32/od.cpp
2020-09-26 16:20:57 +08:00

2576 lines
75 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "precomp.h"
//
// OD.CPP
// Order Decoding
//
// Copyright(c) Microsoft 1997-
//
#define MLZ_FILE_ZONE ZONE_ORDER
//
// OD_ViewStarting()
//
// Sets up the odLast... vars
//
BOOL ASShare::OD_ViewStarting(ASPerson * pasPerson)
{
BOOL rc = FALSE;
TSHR_COLOR colorWhite = {0xFF,0xFF,0xFF};
BYTE brushExtra[7] = {0,0,0,0,0,0,0};
DebugEntry(ASShare::OD_ViewStarting);
ValidateView(pasPerson);
//
// Invalidate OD results
//
pasPerson->m_pView->m_odInvalRgnTotal = CreateRectRgn(0, 0, 0, 0);
if (pasPerson->m_pView->m_odInvalRgnTotal == NULL)
{
ERROR_OUT(("OD_PartyStartingHosting: Couldn't create total invalid OD region"));
DC_QUIT;
}
pasPerson->m_pView->m_odInvalRgnOrder = CreateRectRgn(0, 0, 0, 0);
if (pasPerson->m_pView->m_odInvalRgnOrder == NULL)
{
ERROR_OUT(("OD_PartyStartingHosting: Couldn't create order invalid OD region"));
DC_QUIT;
}
//
// Back color.
//
pasPerson->m_pView->m_odLastBkColor = 0;
ODUseBkColor(pasPerson, TRUE, colorWhite);
//
// Text color.
//
pasPerson->m_pView->m_odLastTextColor = 0;
ODUseTextColor(pasPerson, TRUE, colorWhite);
//
// Background mode.
//
pasPerson->m_pView->m_odLastBkMode = TRANSPARENT;
ODUseBkMode(pasPerson, OPAQUE);
//
// ROP2.
//
pasPerson->m_pView->m_odLastROP2 = R2_BLACK;
ODUseROP2(pasPerson, R2_COPYPEN);
//
// Fill Mode. It's zero, we don't need to do anything since 0 isn't
// a valid mode, so we'll change it the first order we get that uses
// one.
//
ASSERT(pasPerson->m_pView->m_odLastFillMode == 0);
//
// Arc Direction. It's zero, we don't need to do anything since 0
// isn't a valid dir, so we'll change it the first order we get that
// uses one.
//
ASSERT(pasPerson->m_pView->m_odLastArcDirection == 0);
//
// Pen.
//
pasPerson->m_pView->m_odLastPenStyle = PS_DASH;
pasPerson->m_pView->m_odLastPenWidth = 2;
pasPerson->m_pView->m_odLastPenColor = 0;
ODUsePen(pasPerson, TRUE, PS_SOLID, 1, colorWhite);
//
// Brush.
//
pasPerson->m_pView->m_odLastBrushOrgX = 1;
pasPerson->m_pView->m_odLastBrushOrgY = 1;
pasPerson->m_pView->m_odLastBrushBkColor = 0;
pasPerson->m_pView->m_odLastBrushTextColor = 0;
pasPerson->m_pView->m_odLastLogBrushStyle = BS_NULL;
pasPerson->m_pView->m_odLastLogBrushHatch = HS_VERTICAL;
pasPerson->m_pView->m_odLastLogBrushColor.red = 0;
pasPerson->m_pView->m_odLastLogBrushColor.green = 0;
pasPerson->m_pView->m_odLastLogBrushColor.blue = 0;
ODUseBrush(pasPerson, TRUE, 0, 0, BS_SOLID, HS_HORIZONTAL,
colorWhite, brushExtra);
//
// Char extra.
//
pasPerson->m_pView->m_odLastCharExtra = 1;
ODUseTextCharacterExtra(pasPerson, 0);
//
// Text justification.
//
pasPerson->m_pView->m_odLastJustExtra = 1;
pasPerson->m_pView->m_odLastJustCount = 1;
ODUseTextJustification(pasPerson, 0, 0);
// odLastBaselineOffset. This is zero, which is the default in the DC
// right now so need to change anything.
//
// Font.
//
// We don't call ODUseFont because we know that the following values
// are invalid. The first valid font to arrive will be selected.
//
ASSERT(pasPerson->m_pView->m_odLastFontID == NULL);
pasPerson->m_pView->m_odLastFontCodePage = 0;
pasPerson->m_pView->m_odLastFontWidth = 0;
pasPerson->m_pView->m_odLastFontHeight = 0;
pasPerson->m_pView->m_odLastFontWeight = 0;
pasPerson->m_pView->m_odLastFontFlags = 0;
pasPerson->m_pView->m_odLastFontFaceLen = 0;
ZeroMemory(pasPerson->m_pView->m_odLastFaceName, sizeof(pasPerson->m_pView->m_odLastFaceName));
//
// These next 4 variables which describe the current clip rectangle are
// only valid if fRectReset is FALSE. If fRectReset is true then no
// clipping is in force.
//
pasPerson->m_pView->m_odRectReset = TRUE;
pasPerson->m_pView->m_odLastLeft = 0x12345678;
pasPerson->m_pView->m_odLastTop = 0x12345678;
pasPerson->m_pView->m_odLastRight = 0x12345678;
pasPerson->m_pView->m_odLastBottom = 0x12345678;
// odLastVGAColor?
// odLastVGAResult?
rc = TRUE;
DC_EXIT_POINT:
DebugExitBOOL(ASShare::OD_ViewStarting, rc);
return(rc);
}
//
// OD_ViewEnded()
// Cleans up any created objects
//
void ASShare::OD_ViewEnded(ASPerson * pasPerson)
{
DebugEntry(ASShare::OD_ViewEnded);
ValidateView(pasPerson);
//
// We may create and select in a font and a pen for our drawing decode.
// Select them out and delete them. Since we can't delete stock objects,
// if we didn't actually create one, there's no harm in it.
//
if (pasPerson->m_pView->m_usrDC != NULL)
{
DeleteBrush(SelectBrush(pasPerson->m_pView->m_usrDC, (HBRUSH)GetStockObject(BLACK_BRUSH)));
DeletePen(SelectPen(pasPerson->m_pView->m_usrDC, (HPEN)GetStockObject(BLACK_PEN)));
}
//
// Destroy the brush patern
//
if (pasPerson->m_pView->m_odLastBrushPattern != NULL)
{
DeleteBitmap(pasPerson->m_pView->m_odLastBrushPattern);
pasPerson->m_pView->m_odLastBrushPattern = NULL;
}
//
// Destroy the font -- but in this case we don't know that our font is
// actually the one in the DC. od2 also selects in fonts.
//
if (pasPerson->m_pView->m_odLastFontID != NULL)
{
// Make sure this isn't selected in to usrDC
SelectFont(pasPerson->m_pView->m_usrDC, (HFONT)GetStockObject(SYSTEM_FONT));
DeleteFont(pasPerson->m_pView->m_odLastFontID);
pasPerson->m_pView->m_odLastFontID = NULL;
}
if (pasPerson->m_pView->m_odInvalRgnTotal != NULL)
{
DeleteRgn(pasPerson->m_pView->m_odInvalRgnTotal);
pasPerson->m_pView->m_odInvalRgnTotal = NULL;
}
if (pasPerson->m_pView->m_odInvalRgnOrder != NULL)
{
DeleteRgn(pasPerson->m_pView->m_odInvalRgnOrder);
pasPerson->m_pView->m_odInvalRgnOrder = NULL;
}
DebugExitVOID(ASShare::OD_ViewEnded);
}
//
// OD_ReceivedPacket()
//
// Handles incoming orders packet from a host. Replays the drawing orders
// into the screen bitmap for the host, then repaints the view with the
// results.
//
void ASShare::OD_ReceivedPacket
(
ASPerson * pasPerson,
PS20DATAPACKET pPacket
)
{
PORDPACKET pOrders;
HPALETTE hOldPalette;
HPALETTE hOldSavePalette;
UINT cOrders;
UINT cUpdates;
UINT i;
LPCOM_ORDER_UA pOrder;
UINT decodedLength;
LPBYTE pEncodedOrder;
TSHR_INT32 xOrigin;
TSHR_INT32 yOrigin;
BOOL fPalRGB;
DebugEntry(ASShare::OD_ReceivedPacket);
ValidateView(pasPerson);
pOrders = (PORDPACKET)pPacket;
//
// The color type is RGB if we or they are < 256 colors
// Else it's PALETTE if they are old, or new and not sending 24bpp
//
fPalRGB = TRUE;
if ((g_usrScreenBPP < 8) || (pasPerson->cpcCaps.screen.capsBPP < 8))
{
TRACE_OUT(("OD_ReceivedPacket: no PALRGB"));
fPalRGB = FALSE;
}
else
{
// At 24bpp, no palette matching for RGB values unless we're <= 8
if ((g_usrScreenBPP > 8) && (pOrders->sendBPP > 8))
{
TRACE_OUT(("OD_ReceivedPacket: no PALRGB"));
fPalRGB = FALSE;
}
}
if (g_usrPalettized)
{
//
// Select and realize the current remote palette into the device
// context.
//
hOldPalette = SelectPalette(pasPerson->m_pView->m_usrDC, pasPerson->pmPalette, FALSE);
RealizePalette(pasPerson->m_pView->m_usrDC);
//
// We must select the same palette into the Save Bitmap DC so that
// no color conversion occurs during save and restore operations.
//
if (pasPerson->m_pView->m_ssiDC != NULL)
{
hOldSavePalette = SelectPalette(pasPerson->m_pView->m_ssiDC,
pasPerson->pmPalette, FALSE);
RealizePalette(pasPerson->m_pView->m_ssiDC);
}
}
//
// Extract the number of orders supplied.
//
cOrders = pOrders->cOrders;
if (m_oefOE2EncodingOn)
{
pEncodedOrder = (LPBYTE)(&pOrders->data);
pOrder = NULL;
}
else
{
pOrder = (LPCOM_ORDER_UA)(&pOrders->data);
pEncodedOrder = NULL;
}
//
// Get the desktop origin for this person.
//
TRACE_OUT(( "Begin replaying %u orders ((", cOrders));
//
// This should be empty, we should have reset it when we invalidated
// the view of the host the last time we got a packet.
//
#ifdef _DEBUG
{
RECT rcBounds;
ASSERT(pasPerson->m_pView->m_odInvalTotal == 0);
GetRgnBox(pasPerson->m_pView->m_odInvalRgnTotal, &rcBounds);
ASSERT(IsRectEmpty(&rcBounds));
}
#endif // _DEBUG
//
// Repeat for each of the received orders.
//
for (i = 0; i < cOrders; i++)
{
if (m_oefOE2EncodingOn)
{
//
// Decode the first order. The pOrder returned by
// OD2_DecodeOrder should have all fields in local byte order
//
pOrder = OD2_DecodeOrder( (PDCEO2ORDER)pEncodedOrder,
&decodedLength,
pasPerson );
if (pOrder == NULL)
{
ERROR_OUT(( "Failed to decode order from pasPerson %u", pasPerson));
DC_QUIT;
}
}
else
{
//
// Convert any font ids to be local ids.
//
//
// BOGUS LAURABU
// pOrder is unaligned, FH_Convert... takes an aligned order
//
FH_ConvertAnyFontIDToLocal((LPCOM_ORDER)pOrder, pasPerson);
decodedLength = pOrder->OrderHeader.cbOrderDataLength +
sizeof(COM_ORDER_HEADER);
}
//
// If the order is a Private Order then it is dealt with by
// the Bitmap Cache Controller.
//
if (EXTRACT_TSHR_UINT16_UA(&(pOrder->OrderHeader.fOrderFlags)) &
OF_PRIVATE)
{
RBC_ProcessCacheOrder(pasPerson, pOrder);
}
else if ( EXTRACT_TSHR_UINT16_UA(
&(((LPPATBLT_ORDER)pOrder->abOrderData)->type)) ==
LOWORD(ORD_DESKSCROLL))
{
ERROR_OUT(("Received DESKSCROLL order, obsolete, from 3.0 node [%d]",
pasPerson->mcsID));
}
else
{
//
// Replay the received order. This will also add the
// bounds to the invalidate region.
//
//
OD_ReplayOrder(pasPerson, (LPCOM_ORDER)pOrder, fPalRGB);
}
if (m_oefOE2EncodingOn)
{
pEncodedOrder += decodedLength;
}
else
{
pOrder = (LPCOM_ORDER_UA)((LPBYTE)pOrder + decodedLength);
}
}
TRACE_OUT(( "End replaying orders ))"));
//
// Pass the Update Region to the Shadow Window Presenter.
//
OD_UpdateView(pasPerson);
DC_EXIT_POINT:
if (g_usrPalettized)
{
//
// Reinstate the old palette(s).
//
SelectPalette(pasPerson->m_pView->m_usrDC, hOldPalette, FALSE);
if (pasPerson->m_pView->m_ssiDC != NULL)
{
SelectPalette(pasPerson->m_pView->m_ssiDC, hOldSavePalette, FALSE);
}
}
DebugExitVOID(ASShare::OD_ReceivedPacket);
}
//
// OD_UpdateView()
//
// This is called after we've processed an order packet and replayed the
// drawing into our bitmap for the host.
//
// Replaying the drawing keeps a running tally of the area changed. This
// function invalidates the changed area in the view of the host, so it
// will repaint and show the updates.
//
void ASShare::OD_UpdateView(ASPerson * pasHost)
{
RECT rcBounds;
DebugEntry(ASShare::OD_UpdateView);
ValidateView(pasHost);
//
// Do nothing if there are no updates.
//
if (pasHost->m_pView->m_odInvalTotal == 0)
{
// Nothing got played back, nothing to repaint
}
else if (pasHost->m_pView->m_odInvalTotal <= MAX_UPDATE_REGION_ORDERS)
{
VIEW_InvalidateRgn(pasHost, pasHost->m_pView->m_odInvalRgnTotal);
}
else
{
//
// Rather than invalidating a very complex region, which will
// chew up a lot of memory, just invalidate the bounding box.
//
GetRgnBox(pasHost->m_pView->m_odInvalRgnTotal, &rcBounds);
TRACE_OUT(("OD_UpdateView: Update region too complex; use bounds {%04d, %04d, %04d, %04d}",
rcBounds.left, rcBounds.top, rcBounds.right, rcBounds.bottom));
//
// BOGUS LAURABU!
// This code used to add one to the right & bottom, which was
// bogus EXCLUSIVE coordinate confusion. I fixed this--the bound
// box is the right area.
//
SetRectRgn(pasHost->m_pView->m_odInvalRgnTotal, rcBounds.left, rcBounds.top,
rcBounds.right, rcBounds.bottom);
VIEW_InvalidateRgn(pasHost, pasHost->m_pView->m_odInvalRgnTotal);
}
// Now reset the update region to empty
SetRectRgn(pasHost->m_pView->m_odInvalRgnTotal, 0, 0, 0, 0);
pasHost->m_pView->m_odInvalTotal = 0;
DebugExitVOID(ASShare::OD_UpdateView);
}
//
// OD_ReplayOrder()
//
// Replays one drawing operation, the next one, in the packet of orders
// we received from a host.
//
void ASShare::OD_ReplayOrder
(
ASPerson * pasPerson,
LPCOM_ORDER pOrder,
BOOL fPalRGB
)
{
LPPATBLT_ORDER pDrawing;
LPSTR faceName;
UINT faceNameLength;
UINT trueFontWidth;
UINT maxFontHeight;
TSHR_UINT16 nFontFlags;
TSHR_UINT16 nCodePage;
UINT i;
RECT rcDst;
DebugEntry(ASShare::OD_ReplayOrder);
ValidateView(pasPerson);
pDrawing = (LPPATBLT_ORDER)pOrder->abOrderData;
//
// These are VD coords.
// WHEN 2.X INTEROP IS GONE, GET RID OF m_pView->m_dsScreenOrigin
//
RECT_FROM_TSHR_RECT16(&rcDst, pOrder->OrderHeader.rcsDst);
//
// The host bitmap is in screen, not VD, coords
//
if (pOrder->OrderHeader.fOrderFlags & OF_NOTCLIPPED)
{
//
// The rectangle associated with this order is the bounding
// rectangle of the order and does not clip it. We optimise this
// case by passing in a large rectangle that will not result in
// clipping to ODUseRectRegion. ODUseRectRegion will spot if this
// is the same as the last clip region we set and take a fast exit
// path. This improves performance substantially.
//
ODUseRectRegion(pasPerson, 0, 0, 10000, 10000);
}
else
{
ODUseRectRegion(pasPerson, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
}
switch (pDrawing->type)
{
case ORD_DSTBLT_TYPE:
ODReplayDSTBLT(pasPerson, (LPDSTBLT_ORDER)pDrawing, fPalRGB);
break;
case ORD_PATBLT_TYPE:
ODReplayPATBLT(pasPerson, (LPPATBLT_ORDER)pDrawing, fPalRGB);
break;
case ORD_SCRBLT_TYPE:
ODReplaySCRBLT(pasPerson, (LPSCRBLT_ORDER)pDrawing, fPalRGB);
break;
case ORD_MEMBLT_TYPE:
case ORD_MEMBLT_R2_TYPE:
ODReplayMEMBLT(pasPerson, (LPMEMBLT_ORDER)pDrawing, fPalRGB);
break;
case ORD_MEM3BLT_TYPE:
case ORD_MEM3BLT_R2_TYPE:
ODReplayMEM3BLT(pasPerson, (LPMEM3BLT_ORDER)pDrawing, fPalRGB);
break;
case ORD_RECTANGLE_TYPE:
ODReplayRECTANGLE(pasPerson, (LPRECTANGLE_ORDER)pDrawing, fPalRGB);
break;
case ORD_POLYGON_TYPE:
ODReplayPOLYGON(pasPerson, (LPPOLYGON_ORDER)pDrawing, fPalRGB);
break;
case ORD_PIE_TYPE:
ODReplayPIE(pasPerson, (LPPIE_ORDER)pDrawing, fPalRGB);
break;
case ORD_ELLIPSE_TYPE:
ODReplayELLIPSE(pasPerson, (LPELLIPSE_ORDER)pDrawing, fPalRGB);
break;
case ORD_ARC_TYPE:
ODReplayARC(pasPerson, (LPARC_ORDER)pDrawing, fPalRGB);
break;
case ORD_CHORD_TYPE:
ODReplayCHORD(pasPerson, (LPCHORD_ORDER)pDrawing, fPalRGB);
break;
case ORD_POLYBEZIER_TYPE:
ODReplayPOLYBEZIER(pasPerson, (LPPOLYBEZIER_ORDER)pDrawing, fPalRGB);
break;
case ORD_ROUNDRECT_TYPE:
ODReplayROUNDRECT(pasPerson, (LPROUNDRECT_ORDER)pDrawing, fPalRGB);
break;
case ORD_LINETO_TYPE:
ODReplayLINETO(pasPerson, (LPLINETO_ORDER)pDrawing, fPalRGB);
break;
case ORD_EXTTEXTOUT_TYPE:
ODReplayEXTTEXTOUT(pasPerson, (LPEXTTEXTOUT_ORDER)pDrawing, fPalRGB);
break;
case ORD_TEXTOUT_TYPE:
ODReplayTEXTOUT(pasPerson, (LPTEXTOUT_ORDER)pDrawing, fPalRGB);
break;
case ORD_OPAQUERECT_TYPE:
ODReplayOPAQUERECT(pasPerson, (LPOPAQUERECT_ORDER)pDrawing, fPalRGB);
break;
case ORD_SAVEBITMAP_TYPE:
SSI_SaveBitmap(pasPerson, (LPSAVEBITMAP_ORDER)pDrawing);
break;
default:
ERROR_OUT(( "ORDER: Unrecognised order %d from [%d]",
(int)pDrawing->type, pasPerson->mcsID));
break;
}
//
// rcDst is INCLUSIVE coords still
//
if ((rcDst.left <= rcDst.right) && (rcDst.top <= rcDst.bottom))
{
SetRectRgn(pasPerson->m_pView->m_odInvalRgnOrder, rcDst.left, rcDst.top,
rcDst.right+1, rcDst.bottom+1);
//
// Combine the rectangle region with the update region.
//
if (UnionRgn(pasPerson->m_pView->m_odInvalRgnTotal, pasPerson->m_pView->m_odInvalRgnTotal, pasPerson->m_pView->m_odInvalRgnOrder) <= ERROR)
{
RECT rcCur;
//
// Union failed; so simplyify the current region
//
WARNING_OUT(("OD_ReplayOrder: UnionRgn failed"));
//
// BOGUS LAURABU!
// This code used to add one to the right & bottom, which is
// bogus exclusive coord confusion. The bound box is the right
// area.
//
GetRgnBox(pasPerson->m_pView->m_odInvalRgnTotal, &rcCur);
SetRectRgn(pasPerson->m_pView->m_odInvalRgnTotal, rcCur.left, rcCur.top, rcCur.right,
rcCur.bottom);
//
// Reset odInvalTotal count -- this is really a # of bounds rects
// count, and now we have just one.
//
pasPerson->m_pView->m_odInvalTotal = 1;
if (UnionRgn(pasPerson->m_pView->m_odInvalRgnTotal, pasPerson->m_pView->m_odInvalRgnTotal, pasPerson->m_pView->m_odInvalRgnOrder) <= ERROR)
{
ERROR_OUT(("OD_ReplayOrder: UnionRgn failed after simplification"));
}
}
pasPerson->m_pView->m_odInvalTotal++;
}
DebugExitVOID(ASShare::OD_ReplayOrder);
}
//
// ODReplayDSTBLT()
// Replays a DSTBLT order
//
void ASShare::ODReplayDSTBLT
(
ASPerson * pasPerson,
LPDSTBLT_ORDER pDstBlt,
BOOL fPalRGB
)
{
DebugEntry(ASShare::ODReplayDSTBLT);
TRACE_OUT(("ORDER: DstBlt X %hd Y %hd w %hd h %hd rop %08lX",
pDstBlt->nLeftRect,
pDstBlt->nTopRect,
pDstBlt->nWidth,
pDstBlt->nHeight,
(UINT)ODConvertToWindowsROP(pDstBlt->bRop)));
//
// Apply DS origin offset ourselves (do not use transform)
//
PatBlt(pasPerson->m_pView->m_usrDC,
pDstBlt->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pDstBlt->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pDstBlt->nWidth,
pDstBlt->nHeight,
ODConvertToWindowsROP(pDstBlt->bRop));
DebugExitVOID(ASShare::ODReplayDSTBLT);
}
//
// ASShare::ODReplayPATBLT()
// Replays a PATBLT order
//
void ASShare::ODReplayPATBLT
(
ASPerson * pasPerson,
LPPATBLT_ORDER pPatblt,
BOOL fPalRGB
)
{
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
DebugEntry(ASShare::ODReplayPATBLT);
TRACE_OUT(("ORDER: PatBlt BC %08lX FC %08lX Brush %02X %02X X %d Y %d w %d h %d rop %08lX",
pPatblt->BackColor,
pPatblt->ForeColor,
pPatblt->BrushStyle,
pPatblt->BrushHatch,
pPatblt->nLeftRect,
pPatblt->nTopRect,
pPatblt->nWidth,
pPatblt->nHeight,
ODConvertToWindowsROP(pPatblt->bRop) ));
ODAdjustColor(pasPerson, &(pPatblt->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pPatblt->ForeColor), &ForeColor, OD_FORE_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBrush(pasPerson, fPalRGB, pPatblt->BrushOrgX, pPatblt->BrushOrgY,
pPatblt->BrushStyle, pPatblt->BrushHatch, ForeColor, pPatblt->BrushExtra);
//
// Apply DS origin offset ourselves (do not use transform)
//
PatBlt(pasPerson->m_pView->m_usrDC,
pPatblt->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pPatblt->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pPatblt->nWidth,
pPatblt->nHeight,
ODConvertToWindowsROP(pPatblt->bRop));
DebugExitVOID(ASShare::ODReplayPATBLT);
}
//
// ASShare::ODReplaySCRBLT()
// Replays SCRBLT order
//
void ASShare::ODReplaySCRBLT
(
ASPerson * pasPerson,
LPSCRBLT_ORDER pScrBlt,
BOOL fPalRGB
)
{
DebugEntry(ASShare::ODReplaySCRBLT);
TRACE_OUT(("ORDER: ScrBlt dx %d dy %d w %d h %d sx %d sy %d rop %08lX",
pScrBlt->nLeftRect,
pScrBlt->nTopRect,
pScrBlt->nWidth,
pScrBlt->nHeight,
pScrBlt->nXSrc,
pScrBlt->nYSrc,
ODConvertToWindowsROP(pScrBlt->bRop)));
//
// Apply DS origin offset ourselves (do not use transform)
//
BitBlt(pasPerson->m_pView->m_usrDC,
pScrBlt->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pScrBlt->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pScrBlt->nWidth,
pScrBlt->nHeight,
pasPerson->m_pView->m_usrDC,
pScrBlt->nXSrc - pasPerson->m_pView->m_dsScreenOrigin.x,
pScrBlt->nYSrc - pasPerson->m_pView->m_dsScreenOrigin.y,
ODConvertToWindowsROP(pScrBlt->bRop));
DebugExitVOID(ASShare::ODReplaySCRBLT);
}
//
// ASShare::ODReplayMEMBLT()
// Replays MEMBLT and MEMBLT_R2 orders
//
void ASShare::ODReplayMEMBLT
(
ASPerson * pasPerson,
LPMEMBLT_ORDER pMemBlt,
BOOL fPalRGB
)
{
HPALETTE hpalOld;
HPALETTE hpalOld2;
TSHR_UINT16 cacheIndex;
UINT nXSrc;
HBITMAP cacheBitmap;
HBITMAP hOldBitmap;
COLORREF clrBk;
COLORREF clrText;
DebugEntry(ASShare::ODReplayMEMBLT);
ValidateView(pasPerson);
TRACE_OUT(("MEMBLT nXSrc %d",pMemBlt->nXSrc));
hpalOld = SelectPalette(pasPerson->m_pView->m_usrWorkDC, pasPerson->pmPalette, FALSE);
RealizePalette(pasPerson->m_pView->m_usrWorkDC);
hpalOld2 = SelectPalette( pasPerson->m_pView->m_usrDC, pasPerson->pmPalette, FALSE );
RealizePalette(pasPerson->m_pView->m_usrDC);
//
// Now get the source bitmap. The cache is defined by
// hBitmap. For R1 protocols the cache index is indicated
// by the source offset on the order. For R2 it is
// indicated by a separate field in the order.
// The color table index is in the high order of hBitmap
//
cacheIndex = ((LPMEMBLT_R2_ORDER)pMemBlt)->cacheIndex;
nXSrc = pMemBlt->nXSrc;
TRACE_OUT(( "MEMBLT color %d cache %d:%d",
MEMBLT_COLORINDEX(pMemBlt),
MEMBLT_CACHETABLE(pMemBlt),
cacheIndex));
cacheBitmap = RBC_MapCacheIDToBitmapHandle(pasPerson,
MEMBLT_CACHETABLE(pMemBlt), cacheIndex, MEMBLT_COLORINDEX(pMemBlt));
hOldBitmap = SelectBitmap(pasPerson->m_pView->m_usrWorkDC, cacheBitmap);
TRACE_OUT(("ORDER: MemBlt dx %d dy %d w %d h %d sx %d sy %d rop %08lX",
pMemBlt->nLeftRect,
pMemBlt->nTopRect,
pMemBlt->nWidth,
pMemBlt->nHeight,
nXSrc,
pMemBlt->nYSrc,
ODConvertToWindowsROP(pMemBlt->bRop)));
//
// ALWAYS set back/fore color to white/black in case of rops like
// SRCAND or SRCINVERT which will use their values.
//
clrBk = SetBkColor(pasPerson->m_pView->m_usrDC, RGB(255, 255, 255));
clrText = SetTextColor(pasPerson->m_pView->m_usrDC, RGB(0, 0, 0));
//
// Apply DS origin offset ourselves (do not use transform)
//
BitBlt(pasPerson->m_pView->m_usrDC,
pMemBlt->nLeftRect- pasPerson->m_pView->m_dsScreenOrigin.x,
pMemBlt->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pMemBlt->nWidth,
pMemBlt->nHeight,
pasPerson->m_pView->m_usrWorkDC,
nXSrc,
pMemBlt->nYSrc,
ODConvertToWindowsROP(pMemBlt->bRop));
//
// If the relevant property is set hatch the area in blue.
//
if (m_usrHatchBitmaps)
{
SDP_DrawHatchedRect(pasPerson->m_pView->m_usrDC,
pMemBlt->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pMemBlt->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pMemBlt->nWidth,
pMemBlt->nHeight,
USR_HATCH_COLOR_BLUE);
}
//
// Restore back, text colors
//
SetTextColor(pasPerson->m_pView->m_usrDC, clrText);
SetBkColor(pasPerson->m_pView->m_usrDC, clrBk);
//
// Deselect the bitmap from the DC.
//
SelectBitmap(pasPerson->m_pView->m_usrWorkDC, hOldBitmap);
SelectPalette(pasPerson->m_pView->m_usrWorkDC, hpalOld, FALSE);
SelectPalette(pasPerson->m_pView->m_usrDC, hpalOld2, FALSE);
DebugExitVOID(ASShare::ODReplayMEMBLT);
}
//
// ASShare::ODReplayMEM3BLT()
// Replays MEM3BLT and MEM3BLT_R2 orders
//
void ASShare::ODReplayMEM3BLT
(
ASPerson * pasPerson,
LPMEM3BLT_ORDER pMem3Blt,
BOOL fPalRGB
)
{
HPALETTE hpalOld;
HPALETTE hpalOld2;
TSHR_UINT16 cacheIndex;
int nXSrc;
HBITMAP cacheBitmap;
HBITMAP hOldBitmap;
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
DebugEntry(ASShare::ODReplayMEM3BLT);
ValidateView(pasPerson);
TRACE_OUT(("MEM3BLT nXSrc %d",pMem3Blt->nXSrc));
TRACE_OUT(("ORDER: Mem3Blt brush %04lX %04lX dx %d dy %d "\
"w %d h %d sx %d sy %d rop %08lX",
pMem3Blt->BrushStyle,
pMem3Blt->BrushHatch,
pMem3Blt->nLeftRect,
pMem3Blt->nTopRect,
pMem3Blt->nWidth,
pMem3Blt->nHeight,
pMem3Blt->nXSrc,
pMem3Blt->nYSrc,
(UINT)ODConvertToWindowsROP(pMem3Blt->bRop)));
hpalOld = SelectPalette(pasPerson->m_pView->m_usrWorkDC, pasPerson->pmPalette, FALSE);
RealizePalette(pasPerson->m_pView->m_usrWorkDC);
hpalOld2 = SelectPalette( pasPerson->m_pView->m_usrDC, pasPerson->pmPalette, FALSE);
RealizePalette(pasPerson->m_pView->m_usrDC);
//
// Now get the source bitmap. The cache is defined by
// hBitmap. For R1 protocols the cache index is indicated
// by the source offset on the order. For R2 it is
// indicated by a separate field in the order.
// The color table index is in the high order of hBitmap
//
cacheIndex = ((LPMEM3BLT_R2_ORDER)pMem3Blt)->cacheIndex;
nXSrc = pMem3Blt->nXSrc;
TRACE_OUT(("MEM3BLT color %d cache %d:%d",
MEMBLT_COLORINDEX(pMem3Blt),
MEMBLT_CACHETABLE(pMem3Blt),
cacheIndex));
cacheBitmap = RBC_MapCacheIDToBitmapHandle(pasPerson,
MEMBLT_CACHETABLE(pMem3Blt), cacheIndex, MEMBLT_COLORINDEX(pMem3Blt));
hOldBitmap = SelectBitmap(pasPerson->m_pView->m_usrWorkDC, cacheBitmap);
ODAdjustColor(pasPerson, &(pMem3Blt->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pMem3Blt->ForeColor), &ForeColor, OD_FORE_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBrush(pasPerson, fPalRGB, pMem3Blt->BrushOrgX, pMem3Blt->BrushOrgY,
pMem3Blt->BrushStyle, pMem3Blt->BrushHatch, ForeColor,
pMem3Blt->BrushExtra);
//
// Apply DS origin offset ourselves (do not use transform)
//
BitBlt(pasPerson->m_pView->m_usrDC,
pMem3Blt->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pMem3Blt->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pMem3Blt->nWidth,
pMem3Blt->nHeight,
pasPerson->m_pView->m_usrWorkDC,
nXSrc,
pMem3Blt->nYSrc,
ODConvertToWindowsROP(pMem3Blt->bRop));
//
// If the relevant property is set hatch the area in blue.
//
if (m_usrHatchBitmaps)
{
SDP_DrawHatchedRect(pasPerson->m_pView->m_usrDC,
pMem3Blt->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pMem3Blt->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pMem3Blt->nWidth,
pMem3Blt->nHeight,
USR_HATCH_COLOR_BLUE);
}
//
// Deselect the bitmap from the DC.
//
SelectBitmap(pasPerson->m_pView->m_usrWorkDC, hOldBitmap);
SelectPalette(pasPerson->m_pView->m_usrWorkDC, hpalOld, FALSE);
SelectPalette(pasPerson->m_pView->m_usrDC, hpalOld2, FALSE);
DebugExitVOID(ASShare::ODReplayMEM3BLT);
}
//
// ASShare::ODReplayRECTANGLE()
// Replays RECTANGLE order
//
void ASShare::ODReplayRECTANGLE
(
ASPerson * pasPerson,
LPRECTANGLE_ORDER pRectangle,
BOOL fPalRGB
)
{
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
TSHR_COLOR PenColor;
DebugEntry(ASShare::ODReplayRECTANGLE);
TRACE_OUT(("ORDER: Rectangle BC %08lX FC %08lX BM %04hX brush %02hX " \
"%02hX rop2 %04hX pen %04hX %04hX %08lX rect %d %d %d %d",
pRectangle->BackColor,
pRectangle->ForeColor,
(TSHR_UINT16)pRectangle->BackMode,
(TSHR_UINT16)pRectangle->BrushStyle,
(TSHR_UINT16)pRectangle->BrushHatch,
(TSHR_UINT16)pRectangle->ROP2,
(TSHR_UINT16)pRectangle->PenStyle,
(TSHR_UINT16)pRectangle->PenWidth,
pRectangle->PenColor,
(int)pRectangle->nLeftRect,
(int)pRectangle->nTopRect,
(int)pRectangle->nRightRect + 1,
(int)pRectangle->nBottomRect + 1));
ODAdjustColor(pasPerson, &(pRectangle->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pRectangle->ForeColor), &ForeColor, OD_FORE_COLOR);
ODAdjustColor(pasPerson, &(pRectangle->PenColor), &PenColor, OD_PEN_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBkMode(pasPerson, pRectangle->BackMode);
ODUseBrush(pasPerson, fPalRGB, pRectangle->BrushOrgX, pRectangle->BrushOrgY,
pRectangle->BrushStyle, pRectangle->BrushHatch, ForeColor,
pRectangle->BrushExtra);
ODUseROP2(pasPerson, pRectangle->ROP2);
ODUsePen(pasPerson, fPalRGB, pRectangle->PenStyle, pRectangle->PenWidth,
PenColor);
//
// The rectangle in the order is inclusive but Windows works
// with exclusive rectangles.
//
// Apply DS origin offset ourselves (do not use transform)
//
Rectangle(pasPerson->m_pView->m_usrDC,
pRectangle->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pRectangle->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pRectangle->nRightRect - pasPerson->m_pView->m_dsScreenOrigin.x + 1,
pRectangle->nBottomRect- pasPerson->m_pView->m_dsScreenOrigin.y + 1);
DebugExitVOID(ASShare::ODReplayRECTANGLE);
}
//
// ASShare::ODReplayPOLYGON()
// Replays POLYGON order
//
void ASShare::ODReplayPOLYGON
(
ASPerson * pasPerson,
LPPOLYGON_ORDER pPolygon,
BOOL fPalRGB
)
{
POINT aP[ORD_MAX_POLYGON_POINTS];
UINT i;
UINT cPoints;
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
TSHR_COLOR PenColor;
DebugEntry(ASShare::ODReplayPOLYGON);
cPoints = pPolygon->variablePoints.len /
sizeof(pPolygon->variablePoints.aPoints[0]);
TRACE_OUT(("ORDER: Polygon BC %08lX FC %08lX BM %04hX brush %02hX %02hX "
"%02hX %02hX rop2 %04hX pen %04hX %04hX %08lX points %d",
pPolygon->BackColor,
pPolygon->ForeColor,
(TSHR_UINT16)pPolygon->BackMode,
(TSHR_UINT16)pPolygon->BrushStyle,
(TSHR_UINT16)pPolygon->BrushHatch,
(TSHR_UINT16)pPolygon->ROP2,
(TSHR_UINT16)pPolygon->PenStyle,
(TSHR_UINT16)pPolygon->PenWidth,
pPolygon->PenColor,
cPoints));
//
// Apply DS origin offset ourselves (do not use transform)
// while copying to native size point array.
//
for (i = 0; i < cPoints; i++)
{
TRACE_OUT(( "aPoints[%u]: %d,%d", i,
(int)(pPolygon->variablePoints.aPoints[i].x),
(int)(pPolygon->variablePoints.aPoints[i].y)));
aP[i].x = pPolygon->variablePoints.aPoints[i].x -
pasPerson->m_pView->m_dsScreenOrigin.x;
aP[i].y = pPolygon->variablePoints.aPoints[i].y -
pasPerson->m_pView->m_dsScreenOrigin.y;
}
ODAdjustColor(pasPerson, &(pPolygon->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pPolygon->ForeColor), &ForeColor, OD_FORE_COLOR);
ODAdjustColor(pasPerson, &(pPolygon->PenColor), &PenColor, OD_PEN_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBkMode(pasPerson, pPolygon->BackMode);
ODUseBrush(pasPerson, fPalRGB, pPolygon->BrushOrgX, pPolygon->BrushOrgY,
pPolygon->BrushStyle, pPolygon->BrushHatch, ForeColor,
pPolygon->BrushExtra);
ODUseROP2(pasPerson, pPolygon->ROP2);
ODUsePen(pasPerson, fPalRGB, pPolygon->PenStyle, pPolygon->PenWidth,
PenColor);
ODUseFillMode(pasPerson, pPolygon->FillMode);
Polygon(pasPerson->m_pView->m_usrDC, aP, cPoints);
DebugExitVOID(ASShare::ODReplayPOLYGON);
}
//
// ASShare::ODReplayPIE()
// Replays PIE order
//
void ASShare::ODReplayPIE
(
ASPerson * pasPerson,
LPPIE_ORDER pPie,
BOOL fPalRGB
)
{
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
TSHR_COLOR PenColor;
DebugEntry(ASShare::ODReplayPIE);
TRACE_OUT(("ORDER: Pie BC %08lX FC %08lX BM %04hX brush %02hX "
" %02hX rop2 %04hX pen %04hX %04hX %08lX rect %d %d %d %d",
pPie->BackColor,
pPie->ForeColor,
(TSHR_UINT16)pPie->BackMode,
(TSHR_UINT16)pPie->BrushStyle,
(TSHR_UINT16)pPie->BrushHatch,
(TSHR_UINT16)pPie->ROP2,
(TSHR_UINT16)pPie->PenStyle,
(TSHR_UINT16)pPie->PenWidth,
pPie->PenColor,
(int)pPie->nLeftRect,
(int)pPie->nTopRect,
(int)pPie->nRightRect + 1,
(int)pPie->nBottomRect + 1));
ODAdjustColor(pasPerson, &(pPie->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pPie->ForeColor), &ForeColor, OD_FORE_COLOR);
ODAdjustColor(pasPerson, &(pPie->PenColor), &PenColor, OD_PEN_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBkMode(pasPerson, pPie->BackMode);
ODUseBrush(pasPerson, fPalRGB, pPie->BrushOrgX, pPie->BrushOrgY,
pPie->BrushStyle, pPie->BrushHatch, ForeColor, pPie->BrushExtra);
ODUseROP2(pasPerson, pPie->ROP2);
ODUsePen(pasPerson, fPalRGB, pPie->PenStyle, pPie->PenWidth,
PenColor);
ODUseArcDirection(pasPerson, (int)pPie->ArcDirection);
Pie(pasPerson->m_pView->m_usrDC,
pPie->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pPie->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pPie->nRightRect - pasPerson->m_pView->m_dsScreenOrigin.x + 1,
pPie->nBottomRect - pasPerson->m_pView->m_dsScreenOrigin.y + 1,
pPie->nXStart - pasPerson->m_pView->m_dsScreenOrigin.x,
pPie->nYStart - pasPerson->m_pView->m_dsScreenOrigin.y,
pPie->nXEnd - pasPerson->m_pView->m_dsScreenOrigin.x,
pPie->nYEnd - pasPerson->m_pView->m_dsScreenOrigin.y);
DebugExitVOID(ASShare::ODReplayPIE);
}
//
// ASShare::ODReplayELLIPSE()
// Replays ELLIPSE order
//
void ASShare::ODReplayELLIPSE
(
ASPerson * pasPerson,
LPELLIPSE_ORDER pEllipse,
BOOL fPalRGB
)
{
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
TSHR_COLOR PenColor;
DebugEntry(ASShare::ODReplayELLIPSE);
TRACE_OUT(("ORDER: Ellipse BC %08lX FC %08lX BM %04hX brush %02hX %02hX "
"rop2 %04hX pen %04hX %04hX %08lX rect %d %d %d %d",
pEllipse->BackColor,
pEllipse->ForeColor,
(TSHR_UINT16)pEllipse->BackMode,
(TSHR_UINT16)pEllipse->BrushStyle,
(TSHR_UINT16)pEllipse->BrushHatch,
(TSHR_UINT16)pEllipse->ROP2,
(TSHR_UINT16)pEllipse->PenStyle,
(TSHR_UINT16)pEllipse->PenWidth,
pEllipse->PenColor,
(int)pEllipse->nLeftRect,
(int)pEllipse->nTopRect,
(int)pEllipse->nRightRect + 1,
(int)pEllipse->nBottomRect + 1));
ODAdjustColor(pasPerson, &(pEllipse->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pEllipse->ForeColor), &ForeColor, OD_FORE_COLOR);
ODAdjustColor(pasPerson, &(pEllipse->PenColor), &PenColor, OD_PEN_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBkMode(pasPerson, pEllipse->BackMode);
ODUseBrush(pasPerson, fPalRGB, pEllipse->BrushOrgX, pEllipse->BrushOrgY,
pEllipse->BrushStyle, pEllipse->BrushHatch, ForeColor,
pEllipse->BrushExtra);
ODUseROP2(pasPerson, pEllipse->ROP2);
ODUsePen(pasPerson, fPalRGB, pEllipse->PenStyle, pEllipse->PenWidth,
PenColor);
Ellipse(pasPerson->m_pView->m_usrDC,
pEllipse->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pEllipse->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pEllipse->nRightRect - pasPerson->m_pView->m_dsScreenOrigin.x + 1,
pEllipse->nBottomRect - pasPerson->m_pView->m_dsScreenOrigin.y + 1);
DebugExitVOID(ASShare::ODReplayELLIPSE);
}
//
// ASShare::ODReplayARC()
// Replays ARC order
//
void ASShare::ODReplayARC
(
ASPerson * pasPerson,
LPARC_ORDER pArc,
BOOL fPalRGB
)
{
TSHR_COLOR BackColor;
TSHR_COLOR PenColor;
DebugEntry(ASShare::ODReplayARC);
TRACE_OUT(("ORDER: Arc BC %08lX BM %04hX rop2 %04hX pen %04hX "
"%04hX %08lX rect %d %d %d %d",
pArc->BackColor,
(TSHR_UINT16)pArc->BackMode,
(TSHR_UINT16)pArc->ROP2,
(TSHR_UINT16)pArc->PenStyle,
(TSHR_UINT16)pArc->PenWidth,
pArc->PenColor,
(int)pArc->nLeftRect,
(int)pArc->nTopRect,
(int)pArc->nRightRect + 1,
(int)pArc->nBottomRect + 1));
ODAdjustColor(pasPerson, &(pArc->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pArc->PenColor), &PenColor, OD_PEN_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseBkMode(pasPerson, pArc->BackMode);
ODUseROP2(pasPerson, pArc->ROP2);
ODUsePen(pasPerson, fPalRGB, pArc->PenStyle, pArc->PenWidth,
PenColor);
ODUseArcDirection(pasPerson, pArc->ArcDirection);
Arc(pasPerson->m_pView->m_usrDC,
pArc->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pArc->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pArc->nRightRect - pasPerson->m_pView->m_dsScreenOrigin.x + 1,
pArc->nBottomRect - pasPerson->m_pView->m_dsScreenOrigin.y + 1,
pArc->nXStart - pasPerson->m_pView->m_dsScreenOrigin.x,
pArc->nYStart - pasPerson->m_pView->m_dsScreenOrigin.y,
pArc->nXEnd - pasPerson->m_pView->m_dsScreenOrigin.x,
pArc->nYEnd - pasPerson->m_pView->m_dsScreenOrigin.y);
DebugExitVOID(ASShare::ODReplayARC);
}
//
// ASShare::ODReplayCHORD()
// Replays CHORD order
//
void ASShare::ODReplayCHORD
(
ASPerson * pasPerson,
LPCHORD_ORDER pChord,
BOOL fPalRGB
)
{
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
TSHR_COLOR PenColor;
DebugEntry(ASShare::ODReplayCHORD);
TRACE_OUT(("ORDER: Chord BC %08lX FC %08lX BM %04hX brush "
"%02hX %02hX rop2 %04hX pen %04hX %04hX %08lX rect "
"%d %d %d %d",
pChord->BackColor,
pChord->ForeColor,
(TSHR_UINT16)pChord->BackMode,
(TSHR_UINT16)pChord->BrushStyle,
(TSHR_UINT16)pChord->BrushHatch,
(TSHR_UINT16)pChord->ROP2,
(TSHR_UINT16)pChord->PenStyle,
(TSHR_UINT16)pChord->PenWidth,
pChord->PenColor,
(int)pChord->nLeftRect,
(int)pChord->nTopRect,
(int)pChord->nRightRect + 1,
(int)pChord->nBottomRect + 1));
ODAdjustColor(pasPerson, &(pChord->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pChord->ForeColor), &ForeColor, OD_FORE_COLOR);
ODAdjustColor(pasPerson, &(pChord->PenColor), &PenColor, OD_PEN_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBkMode(pasPerson, pChord->BackMode);
ODUseBrush(pasPerson, fPalRGB, pChord->BrushOrgX, pChord->BrushOrgY,
pChord->BrushStyle, pChord->BrushHatch, ForeColor,
pChord->BrushExtra);
ODUseROP2(pasPerson, pChord->ROP2);
ODUsePen(pasPerson, fPalRGB, pChord->PenStyle, pChord->PenWidth,
PenColor);
ODUseArcDirection(pasPerson, pChord->ArcDirection);
Chord(pasPerson->m_pView->m_usrDC,
pChord->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pChord->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pChord->nRightRect - pasPerson->m_pView->m_dsScreenOrigin.x + 1,
pChord->nBottomRect - pasPerson->m_pView->m_dsScreenOrigin.y + 1,
pChord->nXStart - pasPerson->m_pView->m_dsScreenOrigin.x,
pChord->nYStart - pasPerson->m_pView->m_dsScreenOrigin.y,
pChord->nXEnd - pasPerson->m_pView->m_dsScreenOrigin.x,
pChord->nYEnd - pasPerson->m_pView->m_dsScreenOrigin.y);
DebugExitVOID(ASShare::ODReplayCHORD);
}
//
// ASShare::ODReplayPOLYBEZIER()
// Replays POLYBEZIER order
//
void ASShare::ODReplayPOLYBEZIER
(
ASPerson * pasPerson,
LPPOLYBEZIER_ORDER pPolyBezier,
BOOL fPalRGB
)
{
POINT aP[ORD_MAX_POLYBEZIER_POINTS];
UINT i;
UINT cPoints;
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
TSHR_COLOR PenColor;
DebugEntry(ASShare::ODReplayPOLYBEZIER);
cPoints = pPolyBezier->variablePoints.len /
sizeof(pPolyBezier->variablePoints.aPoints[0]);
TRACE_OUT(("ORDER: PolyBezier BC %08lX FC %08lX BM %04hX rop2 "
"%04hX pen %04hX %04hX %08lX points %d",
pPolyBezier->BackColor,
pPolyBezier->ForeColor,
(TSHR_UINT16)pPolyBezier->BackMode,
(TSHR_UINT16)pPolyBezier->ROP2,
(TSHR_UINT16)pPolyBezier->PenStyle,
(TSHR_UINT16)pPolyBezier->PenWidth,
pPolyBezier->PenColor,
(int)cPoints));
//
// Apply DS origin offset ourselves (do not use transform)
// while copying to native size point array.
//
for (i = 0; i < cPoints; i++)
{
TRACE_OUT(("aPoints[%u]: %d,%d",(UINT)i,
(int)(pPolyBezier->variablePoints.aPoints[i].x),
(int)(pPolyBezier->variablePoints.aPoints[i].y)));
aP[i].x = pPolyBezier->variablePoints.aPoints[i].x -
pasPerson->m_pView->m_dsScreenOrigin.x;
aP[i].y = pPolyBezier->variablePoints.aPoints[i].y -
pasPerson->m_pView->m_dsScreenOrigin.y;
}
ODAdjustColor(pasPerson, &(pPolyBezier->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pPolyBezier->ForeColor), &ForeColor, OD_FORE_COLOR);
ODAdjustColor(pasPerson, &(pPolyBezier->PenColor), &PenColor, OD_PEN_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBkMode(pasPerson, pPolyBezier->BackMode);
ODUseROP2(pasPerson, pPolyBezier->ROP2);
ODUsePen(pasPerson, fPalRGB, pPolyBezier->PenStyle, pPolyBezier->PenWidth,
PenColor);
PolyBezier(pasPerson->m_pView->m_usrDC, aP, cPoints);
DebugExitVOID(ASShare::ODReplayPOLYBEZIER);
}
//
// ASShare::ODReplayROUNDRECT()
//
void ASShare::ODReplayROUNDRECT
(
ASPerson * pasPerson,
LPROUNDRECT_ORDER pRoundRect,
BOOL fPalRGB
)
{
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
TSHR_COLOR PenColor;
DebugEntry(ASShare::ODReplayROUNDRECT);
TRACE_OUT(("ORDER: RoundRect BC %08lX FC %08lX BM %04hX " \
"brush %02hX %02hX rop2 %04hX pen %04hX %04hX " \
"%08lX rect %d %d %d %d ellipse %d %d",
pRoundRect->BackColor,
pRoundRect->ForeColor,
(TSHR_UINT16)pRoundRect->BackMode,
(TSHR_UINT16)pRoundRect->BrushStyle,
(TSHR_UINT16)pRoundRect->BrushHatch,
(TSHR_UINT16)pRoundRect->ROP2,
(TSHR_UINT16)pRoundRect->PenStyle,
(TSHR_UINT16)pRoundRect->PenWidth,
pRoundRect->PenColor,
(int)pRoundRect->nLeftRect,
(int)pRoundRect->nTopRect,
(int)pRoundRect->nRightRect,
(int)pRoundRect->nBottomRect,
(int)pRoundRect->nEllipseWidth,
(int)pRoundRect->nEllipseHeight));
ODAdjustColor(pasPerson, &(pRoundRect->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pRoundRect->ForeColor), &ForeColor, OD_FORE_COLOR);
ODAdjustColor(pasPerson, &(pRoundRect->PenColor), &PenColor, OD_PEN_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBkMode(pasPerson, pRoundRect->BackMode);
ODUseBrush(pasPerson, fPalRGB, pRoundRect->BrushOrgX, pRoundRect->BrushOrgY,
pRoundRect->BrushStyle, pRoundRect->BrushHatch, ForeColor,
pRoundRect->BrushExtra);
ODUseROP2(pasPerson, pRoundRect->ROP2);
ODUsePen(pasPerson, fPalRGB, pRoundRect->PenStyle, pRoundRect->PenWidth,
PenColor);
//
// Apply DS origin offset ourselves (do not use transform).
//
RoundRect(pasPerson->m_pView->m_usrDC,
pRoundRect->nLeftRect - pasPerson->m_pView->m_dsScreenOrigin.x,
pRoundRect->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y,
pRoundRect->nRightRect - pasPerson->m_pView->m_dsScreenOrigin.x + 1,
pRoundRect->nBottomRect- pasPerson->m_pView->m_dsScreenOrigin.y + 1,
pRoundRect->nEllipseWidth,
pRoundRect->nEllipseHeight);
DebugExitVOID(ASShare::ODReplayROUNDRECT);
}
//
// ASShare::ODReplayLINETO()
// Replays LINETO order
//
void ASShare::ODReplayLINETO
(
ASPerson * pasPerson,
LPLINETO_ORDER pLineTo,
BOOL fPalRGB
)
{
TSHR_COLOR BackColor;
TSHR_COLOR PenColor;
DebugEntry(ASShare::ODReplayLINETO);
TRACE_OUT(("ORDER: LineTo BC %08lX BM %04X rop2 %04X pen " \
"%04X %04X %08lX x1 %d y1 %d x2 %d y2 %d",
pLineTo->BackColor,
pLineTo->BackMode,
pLineTo->ROP2,
pLineTo->PenStyle,
pLineTo->PenWidth,
pLineTo->PenColor,
pLineTo->nXStart,
pLineTo->nYStart,
pLineTo->nXEnd,
pLineTo->nYEnd));
ODAdjustColor(pasPerson, &(pLineTo->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pLineTo->PenColor), &PenColor, OD_PEN_COLOR);
ODUseBkColor(pasPerson, fPalRGB, BackColor);
ODUseBkMode(pasPerson, pLineTo->BackMode);
ODUseROP2(pasPerson, pLineTo->ROP2);
ODUsePen(pasPerson, fPalRGB, pLineTo->PenStyle, pLineTo->PenWidth,
PenColor);
//
// Apply DS origin offset ourselves (do not use transform)
//
MoveToEx(pasPerson->m_pView->m_usrDC,
pLineTo->nXStart - pasPerson->m_pView->m_dsScreenOrigin.x,
pLineTo->nYStart - pasPerson->m_pView->m_dsScreenOrigin.y,
NULL);
LineTo(pasPerson->m_pView->m_usrDC,
pLineTo->nXEnd - pasPerson->m_pView->m_dsScreenOrigin.x,
pLineTo->nYEnd - pasPerson->m_pView->m_dsScreenOrigin.y);
DebugExitVOID(ASShare::ODReplayLINETO);
}
//
// ASShare::ODReplayEXTTEXTOUT()
// Replays EXTTEXTOUT order
//
void ASShare::ODReplayEXTTEXTOUT
(
ASPerson * pasPerson,
LPEXTTEXTOUT_ORDER pExtTextOut,
BOOL fPalRGB
)
{
LPINT lpDx;
RECT rect;
DebugEntry(ASShare::ODReplayEXTTEXTOUT);
ValidateView(pasPerson);
//
// Convert from TSHR_RECT32 to RECT we can manipulate
// And convert to screen coords
//
rect.left = pExtTextOut->rectangle.left;
rect.top = pExtTextOut->rectangle.top;
rect.right = pExtTextOut->rectangle.right;
rect.bottom = pExtTextOut->rectangle.bottom;
OffsetRect(&rect, -pasPerson->m_pView->m_dsScreenOrigin.x, -pasPerson->m_pView->m_dsScreenOrigin.y);
//
// Get pointers to the optional/variable parameters.
//
if (pExtTextOut->fuOptions & ETO_WINDOWS)
{
//
// Make the rectangle exclusive for Windows to use.
//
rect.right++;
rect.bottom++;
}
if (pExtTextOut->fuOptions & ETO_LPDX)
{
//
// if OE2 encoding is in use, the 'variable' string is
// in fact fixed at its maximum possible value, hence
// deltaX is always in the same place.
//
if (m_oefOE2EncodingOn)
{
lpDx = (LPINT)(pExtTextOut->variableDeltaX.deltaX);
}
else
{
//
// If OE2 encoding is not in use, the variable string is
// truly variable, hence the position of deltaX depends
// on the length of the string.
//
lpDx = (LPINT)( ((LPBYTE)pExtTextOut) +
FIELD_OFFSET(EXTTEXTOUT_ORDER, variableString.string) +
pExtTextOut->variableString.len +
sizeof(pExtTextOut->variableDeltaX.len) );
}
//
// Note that deltaLen contains the number of bytes used
// for the deltas, NOT the number of deltas.
//
//
// THERE IS A BUG IN THE ORDER ENCODING - THE DELTA
// LENGTH FIELD IS NOT ALWAYS SET UP CORRECTLY. USE
// THE STRING LENGTH INSTEAD.
//
}
else
{
lpDx = NULL;
}
TRACE_OUT(( "ORDER: ExtTextOut %u %s",
pExtTextOut->variableString.len,
pExtTextOut->variableString.string));
//
// Call our internal routine to draw the text
//
ODDrawTextOrder(pasPerson,
TRUE, // ExtTextOut
fPalRGB,
&pExtTextOut->common,
pExtTextOut->variableString.string,
pExtTextOut->variableString.len,
&rect,
pExtTextOut->fuOptions,
lpDx);
DebugExitVOID(ASShare::ODReplayEXTTEXTOUT);
}
//
// ASShare::ODReplayTEXTOUT()
// Replays TEXTOUT order
//
void ASShare::ODReplayTEXTOUT
(
ASPerson * pasPerson,
LPTEXTOUT_ORDER pTextOut,
BOOL fPalRGB
)
{
DebugEntry(ASShare::ODReplayTEXTOUT);
TRACE_OUT(("ORDER: TextOut len %hu '%s' flags %04hx bc %08lX " \
"fc %08lX bm %04hx",
(TSHR_UINT16)(pTextOut->variableString.len),
pTextOut->variableString.string,
pTextOut->common.FontFlags,
pTextOut->common.BackColor,
pTextOut->common.ForeColor,
pTextOut->common.BackMode));
//
// Call our internal routine to draw the text
//
ODDrawTextOrder(pasPerson,
FALSE, // Not ExtTextOut
fPalRGB,
&pTextOut->common,
pTextOut->variableString.string,
pTextOut->variableString.len,
NULL, // ExtTextOut specific
0, // ExtTextOut specific
NULL); // ExtTextOut specific
DebugExitVOID(ASShare::ODReplayTEXTOUT);
}
//
// ASShare::ODReplayOPAQUERECT()
// Replays OPAQUERECT order
//
void ASShare::ODReplayOPAQUERECT
(
ASPerson * pasPerson,
LPOPAQUERECT_ORDER pOpaqueRect,
BOOL fPalRGB
)
{
RECT rect;
TSHR_COLOR ForeColor;
DebugEntry(ASShare::ODReplayOPAQUERECT);
TRACE_OUT(( "ORDER: OpaqueRect BC %08lX x %d y %d w %x h %d",
pOpaqueRect->Color,
(int)pOpaqueRect->nLeftRect,
(int)pOpaqueRect->nTopRect,
(int)pOpaqueRect->nWidth,
(int)pOpaqueRect->nHeight));
ODAdjustColor(pasPerson, &(pOpaqueRect->Color), &ForeColor, OD_FORE_COLOR);
ODUseBkColor(pasPerson, fPalRGB, ForeColor);
//
// Apply DS origin offset ourselves (do not use transform)
//
rect.left = pOpaqueRect->nLeftRect- pasPerson->m_pView->m_dsScreenOrigin.x;
rect.top = pOpaqueRect->nTopRect - pasPerson->m_pView->m_dsScreenOrigin.y;
rect.right = rect.left + pOpaqueRect->nWidth;
rect.bottom = rect.top + pOpaqueRect->nHeight;
ExtTextOut(pasPerson->m_pView->m_usrDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
DebugExitVOID(ASShare::ODReplayOPAQUERECT);
}
//
// OD_ResetRectRegion()
//
void ASShare::OD_ResetRectRegion(ASPerson * pasPerson)
{
DebugEntry(ASShare::OD_ResetRectRegion);
ValidateView(pasPerson);
if (!pasPerson->m_pView->m_odRectReset)
{
SelectClipRgn(pasPerson->m_pView->m_usrDC, NULL);
//
// Indicate that the region is currently reset.
//
pasPerson->m_pView->m_odRectReset = TRUE;
}
DebugExitVOID(ASShare::OD_ResetRectRegion);
}
//
// ODUseFont()
//
void ASShare::ODUseFont
(
ASPerson * pasPerson,
LPSTR pName,
UINT facelength,
UINT CodePage,
UINT MaxHeight,
UINT Height,
UINT Width,
UINT Weight,
UINT flags
)
{
BOOL rc = TRUE;
TEXTMETRIC* pfm = NULL;
UINT textAlign;
DebugEntry(ASShare::ODUseFont);
ValidateView(pasPerson);
//
// If the baseline alignment flag has been set or cleared, change the
// alignment in our surface (do this now before we reset the
// odLastFontFlags variable).
//
if ((flags & NF_BASELINE) != (pasPerson->m_pView->m_odLastFontFlags & NF_BASELINE))
{
textAlign = GetTextAlign(pasPerson->m_pView->m_usrDC);
if ((flags & NF_BASELINE) != 0)
{
//
// We are setting the baseline alignment flag. We have to
// clear the top alignment flag and set the baseline flag (they
// are mutually exclusive).
//
textAlign &= ~TA_TOP;
textAlign |= TA_BASELINE;
}
else
{
//
// We are clearing the baseline alignment flag. We have to set
// the top alignment flag and clear the baseline flag (they are
// mutually exclusive).
//
textAlign |= TA_TOP;
textAlign &= ~TA_BASELINE;
}
SetTextAlign(pasPerson->m_pView->m_usrDC, textAlign);
}
//
// The font face string is NOT null terminated in the order data so we
// must use strncmp.
//
if ((pasPerson->m_pView->m_odLastFontFaceLen != facelength ) ||
(memcmp((LPSTR)pasPerson->m_pView->m_odLastFaceName,pName,facelength) != 0 ) ||
(pasPerson->m_pView->m_odLastFontCodePage != CodePage ) ||
(pasPerson->m_pView->m_odLastFontHeight != Height ) ||
(pasPerson->m_pView->m_odLastFontWidth != Width ) ||
(pasPerson->m_pView->m_odLastFontWeight != Weight ) ||
(pasPerson->m_pView->m_odLastFontFlags != flags ))
{
TRACE_OUT((
"Change font from %s (CodePage %d height %d width %d " \
"weight %d flags %04X) to %s (CodePage %d height %d " \
"width %d weight %u flags %04X)",
pasPerson->m_pView->m_odLastFaceName,
pasPerson->m_pView->m_odLastFontCodePage,
pasPerson->m_pView->m_odLastFontHeight,
pasPerson->m_pView->m_odLastFontWidth,
pasPerson->m_pView->m_odLastFontWeight,
pasPerson->m_pView->m_odLastFontFlags,
pName,
CodePage,
Height,
Width,
Weight,
flags));
memcpy(pasPerson->m_pView->m_odLastFaceName, pName, facelength);
pasPerson->m_pView->m_odLastFontFaceLen = facelength;
pasPerson->m_pView->m_odLastFaceName[facelength] = '\0';
pasPerson->m_pView->m_odLastFontCodePage = CodePage;
pasPerson->m_pView->m_odLastFontHeight = Height;
pasPerson->m_pView->m_odLastFontWidth = Width;
pasPerson->m_pView->m_odLastFontWeight = Weight;
pasPerson->m_pView->m_odLastFontFlags = flags;
rc = USR_UseFont(pasPerson->m_pView->m_usrDC, &pasPerson->m_pView->m_odLastFontID,
pfm, (LPSTR)pasPerson->m_pView->m_odLastFaceName, CodePage, MaxHeight,
Height, Width, Weight, flags);
}
else
{
//
// The font hasn't changed. But we must still select it in since
// both OD2 and OD code select in fonts.
//
ASSERT(pasPerson->m_pView->m_odLastFontID != NULL);
SelectFont(pasPerson->m_pView->m_usrDC, pasPerson->m_pView->m_odLastFontID);
}
DebugExitVOID(ASShare::ODUseFont);
}
//
// FUNCTION: ASShare::ODUseRectRegion
//
// DESCRIPTION:
//
// Set the clipping rectangle in the ScreenBitmap to the given rectangle.
// The values passed are inclusive.
//
// PARAMETERS:
//
void ASShare::ODUseRectRegion
(
ASPerson * pasPerson,
int left,
int top,
int right,
int bottom
)
{
POINT aPoints[2];
HRGN hrgnRect;
DebugEntry(ASShare::ODUseRectRegion);
ValidateView(pasPerson);
// Adjust for 2.x desktop scrolling
left -= pasPerson->m_pView->m_dsScreenOrigin.x;
top -= pasPerson->m_pView->m_dsScreenOrigin.y;
right -= pasPerson->m_pView->m_dsScreenOrigin.x;
bottom -= pasPerson->m_pView->m_dsScreenOrigin.y;
if ((pasPerson->m_pView->m_odRectReset) ||
(left != pasPerson->m_pView->m_odLastLeft) ||
(top != pasPerson->m_pView->m_odLastTop) ||
(right != pasPerson->m_pView->m_odLastRight) ||
(bottom != pasPerson->m_pView->m_odLastBottom))
{
//
// The region clip rectangle has changed, so we change the region
// in the screen bitmap DC.
//
aPoints[0].x = left;
aPoints[0].y = top;
aPoints[1].x = right;
aPoints[1].y = bottom;
//
// Windows requires that the coordinates are in DEVICE values for
// its SelectClipRgn call.
//
LPtoDP(pasPerson->m_pView->m_usrDC, aPoints, 2);
if ((left > right) || (top > bottom))
{
//
// We get this for SaveScreenBitmap orders. SFR5292
//
TRACE_OUT(( "Null bounds of region rect"));
hrgnRect = CreateRectRgn(0, 0, 0, 0);
}
else
{
// We must add one to right & bottom since coords were inclusive
hrgnRect = CreateRectRgn( aPoints[0].x,
aPoints[0].y,
aPoints[1].x+1,
aPoints[1].y+1);
}
SelectClipRgn(pasPerson->m_pView->m_usrDC, hrgnRect);
pasPerson->m_pView->m_odLastLeft = left;
pasPerson->m_pView->m_odLastTop = top;
pasPerson->m_pView->m_odLastRight = right;
pasPerson->m_pView->m_odLastBottom = bottom;
pasPerson->m_pView->m_odRectReset = FALSE;
if (hrgnRect != NULL)
{
DeleteRgn(hrgnRect);
}
}
DebugExitVOID(ASShare::ODUseRectRegion);
}
//
// ODUseBrush creates the correct brush to use. NB. We rely on
// UseTextColor and UseBKColor being called before this routine to set up
// pasPerson->m_pView->m_odLastTextColor and pasPerson->m_pView->m_odLastBkColor correctly.
//
void ASShare::ODUseBrush
(
ASPerson * pasPerson,
BOOL fPalRGB,
int x,
int y,
UINT Style,
UINT Hatch,
TSHR_COLOR Color,
BYTE Extra[7]
)
{
HBRUSH hBrushNew = NULL;
DebugEntry(ASShare::ODUseBrush);
// Reset the origin
if ((x != pasPerson->m_pView->m_odLastBrushOrgX) ||
(y != pasPerson->m_pView->m_odLastBrushOrgY))
{
SetBrushOrgEx(pasPerson->m_pView->m_usrDC, x, y, NULL);
// Update saved brush org
pasPerson->m_pView->m_odLastBrushOrgX = x;
pasPerson->m_pView->m_odLastBrushOrgY = y;
}
if ((Style != pasPerson->m_pView->m_odLastLogBrushStyle) ||
(Hatch != pasPerson->m_pView->m_odLastLogBrushHatch) ||
(memcmp(&Color, &pasPerson->m_pView->m_odLastLogBrushColor, sizeof(Color))) ||
(memcmp(Extra,pasPerson->m_pView->m_odLastLogBrushExtra,sizeof(pasPerson->m_pView->m_odLastLogBrushExtra))) ||
((pasPerson->m_pView->m_odLastLogBrushStyle == BS_PATTERN) &&
((pasPerson->m_pView->m_odLastTextColor != pasPerson->m_pView->m_odLastBrushTextColor) ||
(pasPerson->m_pView->m_odLastBkColor != pasPerson->m_pView->m_odLastBrushBkColor))))
{
pasPerson->m_pView->m_odLastLogBrushStyle = Style;
pasPerson->m_pView->m_odLastLogBrushHatch = Hatch;
pasPerson->m_pView->m_odLastLogBrushColor = Color;
memcpy(pasPerson->m_pView->m_odLastLogBrushExtra, Extra, sizeof(pasPerson->m_pView->m_odLastLogBrushExtra));
if (pasPerson->m_pView->m_odLastLogBrushStyle == BS_PATTERN)
{
//
// A pattern from a bitmap is required.
//
if (pasPerson->m_pView->m_odLastBrushPattern == NULL)
{
TRACE_OUT(( "Creating bitmap to use for brush setup"));
pasPerson->m_pView->m_odLastBrushPattern = CreateBitmap(8,8,1,1,NULL);
}
if (pasPerson->m_pView->m_odLastBrushPattern != NULL)
{
char lpBits[16];
//
// Place the bitmap bits into an array of bytes in the
// correct form for SetBitmapBits which uses 16 bits per
// scanline.
//
lpBits[14] = (char)Hatch;
lpBits[12] = Extra[0];
lpBits[10] = Extra[1];
lpBits[8] = Extra[2];
lpBits[6] = Extra[3];
lpBits[4] = Extra[4];
lpBits[2] = Extra[5];
lpBits[0] = Extra[6];
SetBitmapBits(pasPerson->m_pView->m_odLastBrushPattern,8*2,lpBits);
hBrushNew = CreatePatternBrush(pasPerson->m_pView->m_odLastBrushPattern);
if (hBrushNew == NULL)
{
ERROR_OUT(( "Failed to create pattern brush"));
}
else
{
pasPerson->m_pView->m_odLastBrushTextColor = pasPerson->m_pView->m_odLastTextColor;
pasPerson->m_pView->m_odLastBrushBkColor = pasPerson->m_pView->m_odLastBkColor;
}
}
}
else
{
LOGBRUSH logBrush;
logBrush.lbStyle = pasPerson->m_pView->m_odLastLogBrushStyle;
logBrush.lbHatch = pasPerson->m_pView->m_odLastLogBrushHatch;
logBrush.lbColor = ODCustomRGB(pasPerson->m_pView->m_odLastLogBrushColor.red,
pasPerson->m_pView->m_odLastLogBrushColor.green,
pasPerson->m_pView->m_odLastLogBrushColor.blue,
fPalRGB);
hBrushNew = CreateBrushIndirect(&logBrush);
}
if (hBrushNew == NULL)
{
ERROR_OUT(( "Failed to create brush"));
}
else
{
TRACE_OUT(( "Selecting new brush 0x%08x", hBrushNew));
DeleteBrush(SelectBrush(pasPerson->m_pView->m_usrDC, hBrushNew));
}
}
DebugExitVOID(ASShare::ODUseBrush);
}
//
// ODDrawTextOrder()
// Common text order playback code for EXTTEXTOUT and TEXTOUT
//
void ASShare::ODDrawTextOrder
(
ASPerson * pasPerson,
BOOL isExtTextOut,
BOOL fPalRGB,
LPCOMMON_TEXTORDER pCommon,
LPSTR pText,
UINT textLength,
LPRECT pExtRect,
UINT extOptions,
LPINT pExtDx
)
{
LPSTR faceName;
UINT faceNameLength;
UINT maxFontHeight;
TSHR_UINT16 nFontFlags;
TSHR_UINT16 nCodePage;
TSHR_COLOR BackColor;
TSHR_COLOR ForeColor;
DebugEntry(ASShare::ODDrawTextOrder);
ODAdjustColor(pasPerson, &(pCommon->BackColor), &BackColor, OD_BACK_COLOR);
ODAdjustColor(pasPerson, &(pCommon->ForeColor), &ForeColor, OD_FORE_COLOR);
ODUseTextBkColor(pasPerson, fPalRGB, BackColor);
ODUseTextColor(pasPerson, fPalRGB, ForeColor);
ODUseBkMode(pasPerson, pCommon->BackMode);
ODUseTextCharacterExtra(pasPerson, pCommon->CharExtra);
ODUseTextJustification(pasPerson, pCommon->BreakExtra, pCommon->BreakCount);
faceName = FH_GetFaceNameFromLocalHandle(pCommon->FontIndex,
&faceNameLength);
maxFontHeight = FH_GetMaxHeightFromLocalHandle(pCommon->FontIndex);
//
// Get the local font flags for the font, so that we can merge in any
// specific local flag information when setting up the font. The prime
// example of this is whether the local font we matched is TrueType or
// not, which information is not sent over the wire, but does need to
// be used when setting up the font - or else we may draw using a local
// fixed font of the same facename.
//
nFontFlags = (TSHR_UINT16)FH_GetFontFlagsFromLocalHandle(pCommon->FontIndex);
//
// Get the local CodePage for the font.
//
nCodePage = (TSHR_UINT16)FH_GetCodePageFromLocalHandle(pCommon->FontIndex);
ODUseFont(pasPerson, faceName, faceNameLength, nCodePage,
maxFontHeight, pCommon->FontHeight, pCommon->FontWidth,
pCommon->FontWeight, pCommon->FontFlags | (nFontFlags & NF_LOCAL));
//
// Make the call.
//
if (isExtTextOut)
{
//
// Apply DS origin offset ourselves (do not use transform)
//
ExtTextOut(pasPerson->m_pView->m_usrDC,
pCommon->nXStart - pasPerson->m_pView->m_dsScreenOrigin.x,
pCommon->nYStart - pasPerson->m_pView->m_dsScreenOrigin.y,
extOptions & ETO_WINDOWS,
pExtRect,
pText,
textLength,
pExtDx);
}
else
{
//
// Apply DS origin offset ourselves (do not use transform)
//
TextOut(pasPerson->m_pView->m_usrDC,
pCommon->nXStart - pasPerson->m_pView->m_dsScreenOrigin.x,
pCommon->nYStart - pasPerson->m_pView->m_dsScreenOrigin.y,
pText,
textLength);
}
DebugExitVOID(ASShare::ODDrawTextOrder);
}
//
// ODAdjustColor()
//
// Used for playback on 4bpp devices. We convert colors that are 'close'
// to VGA to their VGA equivalents.
//
// This function tries to find a close match in the VGA color set for a
// given input color. Close is defined as follows: each color element
// (red, green, blue) must be within 7 of the corresponding element in a
// VGA color, without wrapping. For example
//
// - 0xc7b8c6 is 'close' to 0xc0c0c0
//
// - 0xf8f8f8 is 'close' to 0xffffff
//
// - 0xff0102 is not 'close' to 0x000000, but is 'close' to 0xff0000
//
// Closeness is determined as follows:
//
// - for each entry in the table s_odVGAColors
// - ADD the addMask to the color
// - AND the result with the andMask
// - if the result equals the testMask, this VGA color is close match
//
// Think about it. It works.
//
//
void ASShare::ODAdjustColor
(
ASPerson * pasPerson,
const TSHR_COLOR * pColorIn,
LPTSHR_COLOR pColorOut,
int type
)
{
int i;
COLORREF color;
COLORREF work;
DebugEntry(ASShare::ODAdjustColor);
*pColorOut = *pColorIn;
if (g_usrScreenBPP > 4)
{
// Nothing to convert; bail out
DC_QUIT;
}
//
// Convert the color to a single integer
//
color = (pColorOut->red << 16) + (pColorOut->green << 8) + pColorOut->blue;
//
// See if this is the same as the last call of this type
//
if (color == pasPerson->m_pView->m_odLastVGAColor[type])
{
*pColorOut = pasPerson->m_pView->m_odLastVGAResult[type];
TRACE_OUT(("Same as last %s color",
(type == OD_BACK_COLOR ? "background" :
type == OD_FORE_COLOR ? "foreground" : "pen")));
DC_QUIT;
}
//
// Scan the table for a close match.
//
for (i = 0; i < 16; i++)
{
//
// Check for a close match. Don't bother to look for an exact
// match, as that is caught by this code. The trade off is between
// - an additional test and jump in non-exact cases
// - an 'add' and an 'and' in the exact case.
//
work = color;
work += s_odVGAColors[i].addMask;
work &= s_odVGAColors[i].andMask;
if (work == s_odVGAColors[i].testMask)
{
TRACE_OUT(( "%#6.6lx is close match for %#6.6lx (%s)",
s_odVGAColors[i].color, color,
type == OD_BACK_COLOR ? "background" :
type == OD_FORE_COLOR ? "foreground" : "pen"));
*pColorOut = s_odVGAColors[i].result;
break;
}
}
if (i == 16)
{
TRACE_OUT(( "No close VGA match found for %#6.6lx (%s)",
color,
type == OD_BACK_COLOR ? "background" :
type == OD_FORE_COLOR ? "foreground" : "pen"));
}
//
// Save the result for next time.
//
pasPerson->m_pView->m_odLastVGAColor[type] = color;
pasPerson->m_pView->m_odLastVGAResult[type] = *pColorOut;
DC_EXIT_POINT:
DebugExitVOID(ASShare::ODAdjustColor);
}
//
// LITTLE ASShare::ODUse() functions
//
//
// ASShare::ODUseTextBkColor()
//
void ASShare::ODUseTextBkColor
(
ASPerson * pasPerson,
BOOL fPalRGB,
TSHR_COLOR color
)
{
COLORREF rgb;
ValidateView(pasPerson);
rgb = ODCustomRGB(color.red, color.green, color.blue, fPalRGB);
SetBkColor(pasPerson->m_pView->m_usrDC, rgb);
// Update BK COLOR cache
pasPerson->m_pView->m_odLastBkColor = rgb;
}
//
// ASShare::ODUseBkColor()
//
void ASShare::ODUseBkColor
(
ASPerson * pasPerson,
BOOL fPalRGB,
TSHR_COLOR color
)
{
COLORREF rgb;
ValidateView(pasPerson);
rgb = ODCustomRGB(color.red, color.green, color.blue, fPalRGB);
if (rgb != pasPerson->m_pView->m_odLastBkColor)
{
SetBkColor(pasPerson->m_pView->m_usrDC, rgb);
// Update BK COLOR cache
pasPerson->m_pView->m_odLastBkColor = rgb;
}
}
//
// ASShare::ODUseTextColor()
//
void ASShare::ODUseTextColor
(
ASPerson * pasPerson,
BOOL fPalRGB,
TSHR_COLOR color
)
{
COLORREF rgb;
ValidateView(pasPerson);
rgb = ODCustomRGB(color.red, color.green, color.blue, fPalRGB);
if (rgb != pasPerson->m_pView->m_odLastTextColor)
{
SetTextColor(pasPerson->m_pView->m_usrDC, rgb);
// Update TEXT COLOR cache
pasPerson->m_pView->m_odLastTextColor = rgb;
}
}
//
// ASShare::ODUseBkMode()
//
void ASShare::ODUseBkMode(ASPerson * pasPerson, int mode)
{
if (mode != pasPerson->m_pView->m_odLastBkMode)
{
SetBkMode(pasPerson->m_pView->m_usrDC, mode);
// Update BK MODE cache
pasPerson->m_pView->m_odLastBkMode = mode;
}
}
//
// ASShare::ODUsePen()
//
void ASShare::ODUsePen
(
ASPerson * pasPerson,
BOOL fPalRGB,
UINT style,
UINT width,
TSHR_COLOR color
)
{
HPEN hPenNew;
COLORREF rgb;
ValidateView(pasPerson);
rgb = ODCustomRGB(color.red, color.green, color.blue, fPalRGB);
if ((style != pasPerson->m_pView->m_odLastPenStyle) ||
(rgb != pasPerson->m_pView->m_odLastPenColor) ||
(width != pasPerson->m_pView->m_odLastPenWidth))
{
hPenNew = CreatePen(style, width, rgb);
DeletePen(SelectPen(pasPerson->m_pView->m_usrDC, hPenNew));
// Update PEN cache
pasPerson->m_pView->m_odLastPenStyle = style;
pasPerson->m_pView->m_odLastPenColor = rgb;
pasPerson->m_pView->m_odLastPenWidth = width;
}
}
//
// ASShare::ODUseROP2()
//
void ASShare::ODUseROP2(ASPerson * pasPerson, int rop2)
{
if (rop2 != pasPerson->m_pView->m_odLastROP2)
{
SetROP2(pasPerson->m_pView->m_usrDC, rop2);
// Update ROP2 cache
pasPerson->m_pView->m_odLastROP2 = rop2;
}
}
//
// ASShare::ODUseTextCharacterExtra()
//
void ASShare::ODUseTextCharacterExtra(ASPerson * pasPerson, int extra)
{
if (extra != pasPerson->m_pView->m_odLastCharExtra)
{
SetTextCharacterExtra(pasPerson->m_pView->m_usrDC, extra);
// Update TEXT EXTRA cache
pasPerson->m_pView->m_odLastCharExtra = extra;
}
}
//
// ASShare::ODUseTextJustification()
//
void ASShare::ODUseTextJustification(ASPerson * pasPerson, int extra, int count)
{
if ((extra != pasPerson->m_pView->m_odLastJustExtra) ||
(count != pasPerson->m_pView->m_odLastJustCount))
{
SetTextJustification(pasPerson->m_pView->m_usrDC, extra, count);
// Update TEXT JUST cache
pasPerson->m_pView->m_odLastJustExtra = extra;
pasPerson->m_pView->m_odLastJustCount = count;
}
}
//
// ASShare::ODUseFillMode()
//
void ASShare::ODUseFillMode(ASPerson * pasPerson, UINT mode)
{
if (mode != pasPerson->m_pView->m_odLastFillMode)
{
SetPolyFillMode(pasPerson->m_pView->m_usrDC, (mode == ORD_FILLMODE_WINDING) ?
WINDING : ALTERNATE);
// Update FILL MODE cache
pasPerson->m_pView->m_odLastFillMode = mode;
}
}
//
// ASShare::ODUseArcDirection()
//
void ASShare::ODUseArcDirection(ASPerson * pasPerson, UINT dir)
{
if (dir != pasPerson->m_pView->m_odLastArcDirection)
{
SetArcDirection(pasPerson->m_pView->m_usrDC, (dir == ORD_ARC_CLOCKWISE) ?
AD_CLOCKWISE : AD_COUNTERCLOCKWISE);
// Update ARC DIR cache
pasPerson->m_pView->m_odLastArcDirection = dir;
}
}