Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1746 lines
60 KiB

  1. #include "precomp.h"
  2. //
  3. // OD2.CPP
  4. // Order Decoding Second Level
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. #define MLZ_FILE_ZONE ZONE_ORDER
  9. //
  10. // OD2_ViewStarting()
  11. //
  12. // For 3.0 nodes, we create the decoding data each time they start hosting.
  13. // For 2.x nodes, we create the decoding data once and use it until they
  14. // leave the share.
  15. //
  16. BOOL ASShare::OD2_ViewStarting(ASPerson * pasPerson)
  17. {
  18. PPARTYORDERDATA pThisParty;
  19. BOOL rc = FALSE;
  20. DebugEntry(ASShare::OD2_ViewStarting);
  21. ValidatePerson(pasPerson);
  22. //
  23. // Allocate memory for the required structure.
  24. //
  25. pThisParty = new PARTYORDERDATA;
  26. pasPerson->od2Party = pThisParty;
  27. if (!pThisParty)
  28. {
  29. ERROR_OUT(( "Failed to get memory for od2Party entry"));
  30. DC_QUIT;
  31. }
  32. //
  33. // Ensure the pointers are correctly set up.
  34. //
  35. ZeroMemory(pThisParty, sizeof(*pThisParty));
  36. SET_STAMP(pThisParty, PARTYORDERDATA);
  37. pThisParty->LastOrder[OE2_DSTBLT_ORDER ] = &pThisParty->LastDstblt;
  38. pThisParty->LastOrder[OE2_PATBLT_ORDER ] = &pThisParty->LastPatblt;
  39. pThisParty->LastOrder[OE2_SCRBLT_ORDER ] = &pThisParty->LastScrblt;
  40. pThisParty->LastOrder[OE2_MEMBLT_ORDER ] = &pThisParty->LastMemblt;
  41. pThisParty->LastOrder[OE2_MEM3BLT_ORDER ] = &pThisParty->LastMem3blt;
  42. pThisParty->LastOrder[OE2_TEXTOUT_ORDER ] = &pThisParty->LastTextOut;
  43. pThisParty->LastOrder[OE2_EXTTEXTOUT_ORDER] = &pThisParty->LastExtTextOut;
  44. pThisParty->LastOrder[OE2_RECTANGLE_ORDER ] = &pThisParty->LastRectangle;
  45. pThisParty->LastOrder[OE2_LINETO_ORDER ] = &pThisParty->LastLineTo;
  46. pThisParty->LastOrder[OE2_OPAQUERECT_ORDER] = &pThisParty->LastOpaqueRect;
  47. pThisParty->LastOrder[OE2_SAVEBITMAP_ORDER] = &pThisParty->LastSaveBitmap;
  48. pThisParty->LastOrder[OE2_DESKSCROLL_ORDER] = &pThisParty->LastDeskScroll;
  49. pThisParty->LastOrder[OE2_MEMBLT_R2_ORDER ] = &pThisParty->LastMembltR2;
  50. pThisParty->LastOrder[OE2_MEM3BLT_R2_ORDER] = &pThisParty->LastMem3bltR2;
  51. pThisParty->LastOrder[OE2_POLYGON_ORDER ] = &pThisParty->LastPolygon;
  52. pThisParty->LastOrder[OE2_PIE_ORDER ] = &pThisParty->LastPie;
  53. pThisParty->LastOrder[OE2_ELLIPSE_ORDER ] = &pThisParty->LastEllipse;
  54. pThisParty->LastOrder[OE2_ARC_ORDER ] = &pThisParty->LastArc;
  55. pThisParty->LastOrder[OE2_CHORD_ORDER ] = &pThisParty->LastChord;
  56. pThisParty->LastOrder[OE2_POLYBEZIER_ORDER] = &pThisParty->LastPolyBezier;
  57. pThisParty->LastOrder[OE2_ROUNDRECT_ORDER] = &pThisParty->LastRoundRect;
  58. OD2_SyncIncoming(pasPerson);
  59. rc = TRUE;
  60. DC_EXIT_POINT:
  61. DebugExitBOOL(ASShare::OD2_ViewStarting, rc);
  62. return(rc);
  63. }
  64. //
  65. // OD2_SyncIncoming()
  66. // Called when NEW dude starts to share, a share is created, or someone new
  67. // joins the share.
  68. //
  69. void ASShare::OD2_SyncIncoming(ASPerson * pasPerson)
  70. {
  71. PPARTYORDERDATA pThisParty;
  72. DebugEntry(ASShare::OD2_SyncIncoming);
  73. ValidateView(pasPerson);
  74. pThisParty = pasPerson->od2Party;
  75. pThisParty->LastOrderType = OE2_PATBLT_ORDER;
  76. pThisParty->pLastOrder =
  77. (LPCOM_ORDER)(pThisParty->LastOrder[pThisParty->LastOrderType]);
  78. //
  79. // Set all buffers to NULL Fill in the datalength fields and the type
  80. // field. Note that because the type field is always the first one in
  81. // an order we can cast each pointer to a TEXTOUT order to get the
  82. // correct position for this field
  83. //
  84. #define Reset(field, ord) \
  85. { \
  86. ZeroMemory(&pThisParty->field, sizeof(pThisParty->field)); \
  87. ((LPCOM_ORDER_HEADER)pThisParty->field)->cbOrderDataLength = \
  88. sizeof(pThisParty->field) - sizeof(COM_ORDER_HEADER); \
  89. TEXTFIELD(((LPCOM_ORDER)pThisParty->field))->type = LOWORD(ord); \
  90. }
  91. //
  92. // The compiler generates a warning for our use of LOWORD here on a
  93. // constant. We disable the warning just for now.
  94. //
  95. Reset(LastDstblt, ORD_DSTBLT);
  96. Reset(LastPatblt, ORD_PATBLT);
  97. Reset(LastScrblt, ORD_SCRBLT);
  98. Reset(LastMemblt, ORD_MEMBLT);
  99. Reset(LastMem3blt, ORD_MEM3BLT);
  100. Reset(LastTextOut, ORD_TEXTOUT);
  101. Reset(LastExtTextOut, ORD_EXTTEXTOUT);
  102. Reset(LastRectangle, ORD_RECTANGLE);
  103. Reset(LastLineTo, ORD_LINETO);
  104. Reset(LastOpaqueRect, ORD_OPAQUERECT);
  105. Reset(LastSaveBitmap, ORD_SAVEBITMAP);
  106. Reset(LastDeskScroll, ORD_DESKSCROLL);
  107. Reset(LastMembltR2, ORD_MEMBLT_R2);
  108. Reset(LastMem3bltR2, ORD_MEM3BLT_R2);
  109. Reset(LastPolygon, ORD_POLYGON);
  110. Reset(LastPie, ORD_PIE);
  111. Reset(LastEllipse, ORD_ELLIPSE);
  112. Reset(LastArc, ORD_ARC);
  113. Reset(LastChord, ORD_CHORD);
  114. Reset(LastPolyBezier, ORD_POLYBEZIER);
  115. Reset(LastRoundRect, ORD_ROUNDRECT);
  116. //
  117. // Reset the bounds rectangle
  118. //
  119. ZeroMemory(&pThisParty->LastBounds, sizeof(pThisParty->LastBounds));
  120. //
  121. // The sender and the receiver both set their structures to the same
  122. // NULL state and the sender only ever sends differences from the
  123. // current state. However the fontID fields in the received orders
  124. // refer to the sender, so we must actually set our fontID fields to
  125. // the local equivalent of the NULL entries just set.
  126. // We cannot do this until we have actually received the font details
  127. // so set the field to a dummy value we can recognise later.
  128. //
  129. TEXTFIELD(((LPCOM_ORDER)pThisParty->LastTextOut))->common.FontIndex =
  130. DUMMY_FONT_ID;
  131. EXTTEXTFIELD(((LPCOM_ORDER)pThisParty->LastExtTextOut))->common.
  132. FontIndex = DUMMY_FONT_ID;
  133. DebugExitVOID(ASShare::OD2_SyncIncoming);
  134. }
  135. //
  136. // OD2_ViewEnded()
  137. //
  138. void ASShare::OD2_ViewEnded(ASPerson * pasPerson)
  139. {
  140. DebugEntry(ASShare::OD2_ViewEnded);
  141. ValidatePerson(pasPerson);
  142. //
  143. // For 3.0 nodes, we can free the decode data; 3.0 senders clear theirs
  144. // every time they host.
  145. // For 2.x nodes, we must keep it around while they are in the share.
  146. //
  147. OD2FreeIncoming(pasPerson);
  148. DebugExitVOID(ASShare::OD2_ViewEnded);
  149. }
  150. //
  151. // OD2_PartyLeftShare()
  152. // For 2.x nodes, frees the incoming OD2 data
  153. //
  154. void ASShare::OD2_PartyLeftShare(ASPerson * pasPerson)
  155. {
  156. DebugEntry(ASShare::OD2_PartyLeftShare);
  157. ValidatePerson(pasPerson);
  158. DebugExitVOID(ASShare::OD2_PartyLeftShare);
  159. }
  160. //
  161. // OD2FreeIncoming()
  162. // Frees per-party incoming OD2 resources
  163. //
  164. void ASShare::OD2FreeIncoming(ASPerson * pasPerson)
  165. {
  166. DebugEntry(OD2FreeIncoming);
  167. if (pasPerson->od2Party != NULL)
  168. {
  169. if (pasPerson->od2Party->LastHFONT != NULL)
  170. {
  171. if (pasPerson->m_pView)
  172. {
  173. // For 3.0 nodes, pView won't be NULL; for 2.x nodes it may.
  174. //
  175. // This font might be currently selected into the DC for
  176. // this person's desktop. Select it out.
  177. //
  178. SelectFont(pasPerson->m_pView->m_usrDC, (HFONT)GetStockObject(SYSTEM_FONT));
  179. }
  180. DeleteFont(pasPerson->od2Party->LastHFONT);
  181. pasPerson->od2Party->LastHFONT = NULL;
  182. }
  183. delete pasPerson->od2Party;
  184. pasPerson->od2Party = NULL;
  185. }
  186. DebugExitVOID(ASShare::OD2FreeIncoming);
  187. }
  188. //
  189. // OD2_DecodeOrder()
  190. //
  191. LPCOM_ORDER ASShare::OD2_DecodeOrder
  192. (
  193. void * pEOrder,
  194. LPUINT pLengthDecoded,
  195. ASPerson * pasPerson
  196. )
  197. {
  198. POE2ETFIELD pTableEntry;
  199. UINT FieldChangedBits;
  200. UINT FieldsChanged;
  201. LPBYTE pNextDataToCopy;
  202. RECT Rect;
  203. LPBYTE pControlFlags;
  204. LPTSHR_UINT32_UA pEncodingFlags;
  205. LPSTR pEncodedOrder;
  206. UINT numEncodingFlagBytes;
  207. UINT encodedFieldLength;
  208. UINT unencodedFieldLength;
  209. UINT numReps;
  210. UINT i;
  211. LPBYTE pDest;
  212. DebugEntry(ASShare::OD2_DecodeOrder);
  213. ValidatePerson(pasPerson);
  214. //
  215. // Set up some local variables to access the encoding buffer in various
  216. // ways.
  217. //
  218. pControlFlags = &((PDCEO2ORDER)pEOrder)->ControlFlags;
  219. pEncodedOrder = (LPSTR)&((PDCEO2ORDER)pEOrder)->EncodedOrder[0];
  220. pEncodingFlags = (LPTSHR_UINT32_UA)pEncodedOrder;
  221. if ( (*pControlFlags & OE2_CF_STANDARD_ENC) == 0)
  222. {
  223. ERROR_OUT(("Specially encoded order received from %d", pasPerson));
  224. return(NULL);
  225. }
  226. //
  227. // If the unencoded flag is set, the order has not been encoded, so
  228. // just return a pointer to the start of the data.
  229. //
  230. if ( (*pControlFlags & OE2_CF_UNENCODED) != 0)
  231. {
  232. //
  233. // Convert the fields of the order header from wire format. Note
  234. // that unencoded orders are also PRIVATE, and hence do not
  235. // actually have the rcsDst field.
  236. //
  237. *pLengthDecoded = sizeof(COM_ORDER_HEADER)
  238. + EXTRACT_TSHR_UINT16_UA(
  239. &(((LPCOM_ORDER_UA)pEncodedOrder)->OrderHeader.cbOrderDataLength))
  240. + FIELD_OFFSET(DCEO2ORDER, EncodedOrder);
  241. TRACE_OUT(("Person [%d] Returning unencoded buffer length %u",
  242. pasPerson->mcsID, *pLengthDecoded));
  243. return((LPCOM_ORDER)pEncodedOrder);
  244. }
  245. //
  246. // If type has changed, new type will be first byte in encoded order.
  247. // Get pointer to last order of this type. The encoding flags follow
  248. // this byte (if it is present).
  249. //
  250. if ( (*pControlFlags & OE2_CF_TYPE_CHANGE) != 0)
  251. {
  252. TRACE_OUT(("Person [%d] change type from %d to %d", pasPerson->mcsID,
  253. (UINT)pasPerson->od2Party->LastOrderType,
  254. (UINT)*(LPBYTE)pEncodedOrder));
  255. pasPerson->od2Party->LastOrderType = *(LPTSHR_UINT8)pEncodedOrder;
  256. pasPerson->od2Party->pLastOrder =
  257. (LPCOM_ORDER)(pasPerson->od2Party->LastOrder[pasPerson->od2Party->LastOrderType]);
  258. pEncodingFlags = (LPTSHR_UINT32_UA)&pEncodedOrder[1];
  259. }
  260. else
  261. {
  262. pEncodingFlags = (LPTSHR_UINT32_UA)&pEncodedOrder[0];
  263. }
  264. TRACE_OUT(("Person [%d] type %x", pasPerson->mcsID, pasPerson->od2Party->LastOrderType));
  265. //
  266. // Work out how many bytes we will need to store the encoding flags in.
  267. // (We have a flag for each field in the order structure). This code
  268. // we have written will cope with up to a DWORD of encoding flags.
  269. //
  270. numEncodingFlagBytes = (s_etable.NumFields[pasPerson->od2Party->LastOrderType]+7)/8;
  271. if (numEncodingFlagBytes > 4)
  272. {
  273. ERROR_OUT(( "[%#lx] Too many flag bytes (%d) for this code",
  274. pasPerson, numEncodingFlagBytes));
  275. }
  276. //
  277. // Now we know how many bytes make up the flags we can get a pointer
  278. // to the position at which to start encoding the orders fields into.
  279. //
  280. pNextDataToCopy = (LPBYTE)pEncodingFlags + numEncodingFlagBytes;
  281. //
  282. // Reset the flags field to zero
  283. //
  284. pasPerson->od2Party->pLastOrder->OrderHeader.fOrderFlags = 0;
  285. //
  286. // Rebuild the Order Common Header in the same order as it was
  287. // encoded:
  288. //
  289. //
  290. // If a bounding rectangle is included, copy it into the order header
  291. //
  292. if ( *pControlFlags & OE2_CF_BOUNDS )
  293. {
  294. OD2DecodeBounds((LPTSHR_UINT8*)&pNextDataToCopy,
  295. &pasPerson->od2Party->pLastOrder->OrderHeader.rcsDst,
  296. pasPerson);
  297. }
  298. //
  299. // locate entry in encoding table for this ORDER type and extract the
  300. // encoded order flags from the Encoded order
  301. //
  302. pTableEntry = s_etable.pFields[pasPerson->od2Party->LastOrderType];
  303. FieldChangedBits = 0;
  304. for (i=numEncodingFlagBytes; i>0; i--)
  305. {
  306. FieldChangedBits = FieldChangedBits << 8;
  307. FieldChangedBits |= (UINT)((LPBYTE)pEncodingFlags)[i-1];
  308. }
  309. //
  310. // We need to keep a record of which fields we change.
  311. //
  312. FieldsChanged = FieldChangedBits;
  313. //
  314. // Now decode the order: While field changed bits are non-zero
  315. // If rightmost bit is non-zero
  316. // copy data from the buffer to the copy of this order type
  317. // skip to next entry in Encoding table
  318. // shift field changed bits right one bit
  319. //
  320. while (FieldChangedBits != 0)
  321. {
  322. //
  323. // If this field was encoded (ie changed since the last order)...
  324. //
  325. if ((FieldChangedBits & 1) != 0)
  326. {
  327. //
  328. // Set up a pointer to the destination (unencoded) field.
  329. //
  330. pDest = ((LPBYTE)pasPerson->od2Party->pLastOrder)
  331. + pTableEntry->FieldPos
  332. + sizeof(COM_ORDER_HEADER);
  333. //
  334. // If the field type is OE2_ETF_DATA, we just copy the number
  335. // of bytes given by the encoded length in the table.
  336. //
  337. if ((pTableEntry->FieldType & OE2_ETF_DATA) != 0)
  338. {
  339. encodedFieldLength = 1;
  340. unencodedFieldLength = 1;
  341. numReps = pTableEntry->FieldEncodedLen;
  342. TRACE_OUT(("Byte data field, len %d", numReps));
  343. }
  344. else
  345. {
  346. //
  347. // This is not a straightforward data copy. The length of
  348. // the source and destination data is given in the table in
  349. // the FieldEncodedLen and FieldUnencodedLen elements
  350. // respectively.
  351. //
  352. encodedFieldLength = pTableEntry->FieldEncodedLen;
  353. unencodedFieldLength = pTableEntry->FieldUnencodedLen;
  354. if ((pTableEntry->FieldType & OE2_ETF_FIXED) != 0)
  355. {
  356. //
  357. // If the field type is fixed (OE2_ETF_FIXED is set),
  358. // we just have to decode one element of the given
  359. // size.
  360. //
  361. numReps = 1;
  362. TRACE_OUT(("Fixed fld: encoded size %d, unencoded size %d",
  363. encodedFieldLength,
  364. unencodedFieldLength));
  365. }
  366. else
  367. {
  368. //
  369. // This is a variable field. The next byte to be
  370. // decoded contains the number of BYTES of encoded data
  371. // (not elements), so divide by the encoded field size
  372. // to get numReps.
  373. //
  374. numReps = *pNextDataToCopy / encodedFieldLength;
  375. TRACE_OUT(("Var field: encoded size %d, unencoded size " \
  376. "%d, reps %d",
  377. encodedFieldLength,
  378. unencodedFieldLength,
  379. numReps));
  380. //
  381. // Step past the length field in the encoded order
  382. //
  383. pNextDataToCopy++;
  384. //
  385. // For a variable length field, the unencoded version
  386. // contains a UINT for the length (in bytes) of the
  387. // following variable data, followed by the actual
  388. // data. Fill in the length field in the unencoded
  389. // order.
  390. //
  391. *(LPTSHR_UINT32)pDest = numReps * unencodedFieldLength;
  392. pDest += sizeof(TSHR_UINT32);
  393. }
  394. }
  395. //
  396. // If the order was encoded using delta coordinate mode and
  397. // this field is a coordinate then convert the coordinate from
  398. // the single byte sized delta to a value of the size given by
  399. // unencodedFieldLen...
  400. //
  401. // Note that we've already handled the leading length field of
  402. // variable length fields above, so we don't have to worry
  403. // about FIXED / VARIABLE issues here.
  404. //
  405. if ( (*pControlFlags & OE2_CF_DELTACOORDS) &&
  406. (pTableEntry->FieldType & OE2_ETF_COORDINATES) )
  407. {
  408. //
  409. // NOTE:
  410. // numReps can be zero in the case of an EXTTEXTOUT
  411. // order that needs the opaque rect but has no absolute
  412. // char positioning
  413. //
  414. OD2CopyFromDeltaCoords((LPTSHR_INT8*)&pNextDataToCopy,
  415. pDest,
  416. unencodedFieldLength,
  417. pTableEntry->FieldSigned,
  418. numReps);
  419. }
  420. else
  421. {
  422. if ((pasPerson->od2Party->LastOrderType == OE2_POLYGON_ORDER) ||
  423. (pasPerson->od2Party->LastOrderType == OE2_POLYBEZIER_ORDER))
  424. {
  425. //
  426. // numReps can never be zero in this case
  427. //
  428. ASSERT(numReps);
  429. }
  430. OD2DecodeField(&pNextDataToCopy,
  431. pDest,
  432. encodedFieldLength,
  433. unencodedFieldLength,
  434. pTableEntry->FieldSigned,
  435. numReps);
  436. }
  437. }
  438. //
  439. // Move on to the next field in the order structure...
  440. //
  441. FieldChangedBits = FieldChangedBits >> 1;
  442. pTableEntry++;
  443. }
  444. //
  445. // Check to see if we just got a font handle.
  446. // Because of the rather nasty test against an unnamed bit in the
  447. // FieldsChanged bits, we have a compile time check against the number
  448. // of fields in the TEXT orders structures.
  449. // The requirement for this code not to break is that the font handle
  450. // field must stay as the 13th field (hence 1 << 12).
  451. //
  452. #if (OE2_NUM_TEXTOUT_FIELDS != 15) || (OE2_NUM_EXTTEXTOUT_FIELDS != 22)
  453. #error code breaks if font handle not 13th field
  454. #endif // OE2_NUM_TEXTOUT_FIELDS is 15 or 22
  455. if (((pasPerson->od2Party->LastOrderType == OE2_EXTTEXTOUT_ORDER) &&
  456. ((FieldsChanged & (1 << 12)) ||
  457. (EXTTEXTFIELD(((LPCOM_ORDER)pasPerson->od2Party->LastExtTextOut))->common.
  458. FontIndex == DUMMY_FONT_ID))) ||
  459. ((pasPerson->od2Party->LastOrderType == OE2_TEXTOUT_ORDER) &&
  460. ((FieldsChanged & (1 << 12)) ||
  461. (TEXTFIELD(((LPCOM_ORDER)pasPerson->od2Party->LastTextOut))->common.
  462. FontIndex == DUMMY_FONT_ID))))
  463. {
  464. //
  465. // This was a text order, and the font changed for it.
  466. //
  467. FH_ConvertAnyFontIDToLocal(pasPerson->od2Party->pLastOrder, pasPerson);
  468. }
  469. //
  470. // if the OE2_CF_BOUNDS flag is not set, we have not yet constructed
  471. // the bounding rectangle, so call OD2ReconstructBounds to do so
  472. //
  473. if ( (*pControlFlags & OE2_CF_BOUNDS) == 0)
  474. {
  475. OD2_CalculateBounds(pasPerson->od2Party->pLastOrder,
  476. &Rect,
  477. TRUE,
  478. pasPerson);
  479. pasPerson->od2Party->pLastOrder->OrderHeader.rcsDst.left
  480. = (TSHR_INT16)Rect.left;
  481. pasPerson->od2Party->pLastOrder->OrderHeader.rcsDst.right
  482. = (TSHR_INT16)Rect.right;
  483. pasPerson->od2Party->pLastOrder->OrderHeader.rcsDst.top
  484. = (TSHR_INT16)Rect.top;
  485. pasPerson->od2Party->pLastOrder->OrderHeader.rcsDst.bottom
  486. = (TSHR_INT16)Rect.bottom;
  487. pasPerson->od2Party->pLastOrder->OrderHeader.fOrderFlags |= OF_NOTCLIPPED;
  488. }
  489. //
  490. // Return the decoded order length and a pointer to the order.
  491. //
  492. *pLengthDecoded = (UINT)(pNextDataToCopy - (LPBYTE)pEOrder);
  493. TRACE_OUT(("Person [%d] Return decoded order length %u",
  494. pasPerson->mcsID, *pLengthDecoded));
  495. DebugExitPVOID(ASShare::OD2_DecodeOrder, pasPerson->od2Party->pLastOrder);
  496. return(pasPerson->od2Party->pLastOrder);
  497. }
  498. //
  499. // FUNCTION: OD2UseFont
  500. //
  501. // DESCRIPTION:
  502. //
  503. // Selects the font described by the parameters into the person's DC.
  504. // so that we can then query the text extent etc.
  505. // The queried metrics are available from pasPerson->od2Party->LastFontMetrics.
  506. //
  507. // PARAMETERS:
  508. //
  509. // RETURNS: TRUE if successful, FALSE otherwise.
  510. //
  511. //
  512. BOOL ASShare::OD2UseFont
  513. (
  514. ASPerson * pasPerson,
  515. LPSTR pName,
  516. UINT facelength,
  517. UINT codePage,
  518. UINT MaxHeight,
  519. UINT Height,
  520. UINT Width,
  521. UINT Weight,
  522. UINT flags
  523. )
  524. {
  525. BOOL rc = TRUE;
  526. DebugEntry(ASShare::OD2UseFont);
  527. ValidatePerson(pasPerson);
  528. if ((pasPerson->od2Party->LastFontFaceLen != facelength ) ||
  529. (memcmp((LPSTR)(pasPerson->od2Party->LastFaceName),pName,
  530. facelength) != 0 ) ||
  531. (pasPerson->od2Party->LastCodePage != codePage) ||
  532. (pasPerson->od2Party->LastFontHeight != Height ) ||
  533. (pasPerson->od2Party->LastFontWidth != Width ) ||
  534. (pasPerson->od2Party->LastFontWeight != Weight ) ||
  535. (pasPerson->od2Party->LastFontFlags != flags ))
  536. {
  537. TRACE_OUT(("Person [%d] Font %s (CP%d,w%d,h%d,f%04X,wgt%d) to %s (CP%d,w%d,h%d,f%04X,wgt%d)",
  538. pasPerson->mcsID, pasPerson->od2Party->LastFaceName,
  539. pasPerson->od2Party->LastCodePage, pasPerson->od2Party->LastFontWidth,
  540. pasPerson->od2Party->LastFontHeight,
  541. pasPerson->od2Party->LastFontFlags,
  542. pasPerson->od2Party->LastFontWeight,
  543. pName,
  544. codePage,
  545. Width,
  546. Height,
  547. flags,
  548. Weight ));
  549. memcpy(pasPerson->od2Party->LastFaceName,pName,facelength);
  550. pasPerson->od2Party->LastFontFaceLen = facelength;
  551. pasPerson->od2Party->LastFaceName[facelength] = '\0';
  552. pasPerson->od2Party->LastFontHeight = Height;
  553. pasPerson->od2Party->LastCodePage = codePage;
  554. pasPerson->od2Party->LastFontWidth = Width;
  555. pasPerson->od2Party->LastFontWeight = Weight;
  556. pasPerson->od2Party->LastFontFlags = flags;
  557. rc = USR_UseFont(pasPerson->m_pView->m_usrDC,
  558. &pasPerson->od2Party->LastHFONT,
  559. &pasPerson->od2Party->LastFontMetrics,
  560. (LPSTR)pasPerson->od2Party->LastFaceName,
  561. codePage,
  562. MaxHeight,
  563. Height,
  564. Width,
  565. Weight,
  566. flags);
  567. }
  568. else
  569. {
  570. //
  571. // The font hasn't changed, so LastHFONT should be the one we
  572. // want. We must still select it in however, since several fonts
  573. // get selected into usrDC.
  574. //
  575. ASSERT(pasPerson->od2Party->LastHFONT != NULL);
  576. SelectFont(pasPerson->m_pView->m_usrDC, pasPerson->od2Party->LastHFONT);
  577. }
  578. DebugExitBOOL(ASShare::OD2UseFont, rc);
  579. return(rc);
  580. }
  581. //
  582. // OD2_CalculateTextOutBounds()
  583. //
  584. void ASShare::OD2_CalculateTextOutBounds
  585. (
  586. LPTEXTOUT_ORDER pTextOut,
  587. LPRECT pRect,
  588. BOOL fDecoding,
  589. ASPerson * pasPerson
  590. )
  591. {
  592. LPSTR pString;
  593. int cbString;
  594. BOOL fExtTextOut;
  595. LPEXTTEXTOUT_ORDER pExtTextOut = NULL;
  596. LPCOMMON_TEXTORDER pCommon;
  597. LPSTR faceName;
  598. UINT faceNameLength;
  599. BOOL fFontSelected;
  600. UINT FontIndex;
  601. UINT width;
  602. UINT maxFontHeight;
  603. UINT nFontFlags;
  604. UINT nCodePage;
  605. DebugEntry(ASShare::OD2_CalculateTextOutBounds);
  606. ValidatePerson(pasPerson);
  607. //
  608. // Workout if this is a TextOut or ExtTextOut order.
  609. //
  610. if (pTextOut->type == ORD_EXTTEXTOUT_TYPE)
  611. {
  612. fExtTextOut = TRUE;
  613. pExtTextOut = (LPEXTTEXTOUT_ORDER)pTextOut;
  614. pCommon = &(pExtTextOut->common);
  615. //
  616. // This code does not cope with calculating the bounds of an
  617. // ExtTextOut order with a delta X array. We return a NULL
  618. // rectangle in this case to force the OE2 code to transmit the
  619. // bounds explicitly. However if we are decoding then we must
  620. // calculate the rectangle (even though it may be wrong) to
  621. // maintain backward compatability to previous versions of the
  622. // product (R11) which did not return a NULL rect if delta-x was
  623. // present.
  624. //
  625. if ( (pExtTextOut->fuOptions & ETO_LPDX)
  626. && (!fDecoding) )
  627. {
  628. TRACE_OUT(( "Delta X so return NULL rect"));
  629. pRect->left = 0;
  630. pRect->right = 0;
  631. pRect->top = 0;
  632. pRect->bottom = 0;
  633. return;
  634. }
  635. }
  636. else if (pTextOut->type == ORD_TEXTOUT_TYPE)
  637. {
  638. fExtTextOut = FALSE;
  639. pCommon = &(pTextOut->common);
  640. }
  641. else
  642. {
  643. ERROR_OUT(( "{%p} Unexpected order type %x",
  644. pasPerson, (int)pTextOut->type));
  645. return;
  646. }
  647. //
  648. // The order structures both have the variableString as their first
  649. // variable field. If this were not the case then the code here would
  650. // have to take into account that the encoding side packs variable
  651. // sized fields while the decoding side does not pack them.
  652. //
  653. if (fExtTextOut)
  654. {
  655. cbString = pExtTextOut->variableString.len;
  656. pString = (LPSTR)&pExtTextOut->variableString.string;
  657. }
  658. else
  659. {
  660. cbString = pTextOut->variableString.len;
  661. pString = (LPSTR)&pTextOut->variableString.string;
  662. }
  663. FontIndex = pCommon->FontIndex;
  664. width = pCommon->FontWidth;
  665. //
  666. // Get the facename from the handle, and get the various font width/
  667. // height adjusted values.
  668. //
  669. faceName = FH_GetFaceNameFromLocalHandle(FontIndex,
  670. &faceNameLength);
  671. maxFontHeight = (UINT)FH_GetMaxHeightFromLocalHandle(FontIndex);
  672. //
  673. // Get the local font flags for the font, so that we can merge in any
  674. // specific local flag information when setting up the font. The prime
  675. // example of this is whether the local font we matched is TrueType or
  676. // not, which information is not sent over the wire, but does need to
  677. // be used when setting up the font - or else we may draw using a local
  678. // fixed font of the same facename.
  679. //
  680. nFontFlags = FH_GetFontFlagsFromLocalHandle(FontIndex);
  681. //
  682. // Get the local codePage for the font.
  683. //
  684. nCodePage = FH_GetCodePageFromLocalHandle(FontIndex);
  685. //
  686. // Hosting only version does not ever decode orders.
  687. //
  688. //
  689. // Select the font into the appropriate DC and query the text extent.
  690. //
  691. if (fDecoding)
  692. {
  693. fFontSelected = OD2UseFont(pasPerson,
  694. faceName,
  695. faceNameLength,
  696. nCodePage,
  697. maxFontHeight,
  698. pCommon->FontHeight,
  699. width,
  700. pCommon->FontWeight,
  701. pCommon->FontFlags
  702. | (nFontFlags & NF_LOCAL));
  703. if (!fFontSelected)
  704. {
  705. //
  706. // We failed to select the correct font - so we cannot
  707. // calculate the bounds correctly. However, the fact that we
  708. // are in this routine means that on the host the text was
  709. // unclipped. Therefore we just return a (fairly arbitrary)
  710. // very big rect.
  711. //
  712. // This is far from a perfect answer (for example, it will
  713. // force a big repaint), but allow us to keep running in a
  714. // difficult situation (i.e. acute resource shortage).
  715. //
  716. pRect->left = 0;
  717. pRect->right = 2000;
  718. pRect->top = -2000;
  719. pRect->bottom = 2000;
  720. return;
  721. }
  722. OE_GetStringExtent(pasPerson->m_pView->m_usrDC,
  723. &pasPerson->od2Party->LastFontMetrics,
  724. pString, cbString, pRect );
  725. }
  726. else
  727. {
  728. ASSERT(m_pHost);
  729. fFontSelected = m_pHost->OE2_UseFont(faceName,
  730. (TSHR_UINT16)faceNameLength,
  731. (TSHR_UINT16)nCodePage,
  732. (TSHR_UINT16)maxFontHeight,
  733. (TSHR_UINT16)pCommon->FontHeight,
  734. (TSHR_UINT16)width,
  735. (TSHR_UINT16)pCommon->FontWeight,
  736. (TSHR_UINT16)(pCommon->FontFlags
  737. | (nFontFlags & NF_LOCAL)));
  738. if (!fFontSelected)
  739. {
  740. //
  741. // We failed to select the correct font. We return a NULL
  742. // rectangle in this case to force the OE2 code to transmit
  743. // the bounds explicitly.
  744. //
  745. pRect->left = 0;
  746. pRect->right = 0;
  747. pRect->top = 0;
  748. pRect->bottom = 0;
  749. return;
  750. }
  751. OE_GetStringExtent(m_pHost->m_usrWorkDC, NULL, pString, cbString, pRect );
  752. }
  753. //
  754. // We have a rectangle with the text extent in it relative to (0,0) so
  755. // add in the text starting position to this to give us the bounding
  756. // rectangle. At the same time we will convert the exclusive rect
  757. // returned by OE_GetStringExtent to an inclusive rectangle as us
  758. //
  759. pRect->left += pCommon->nXStart;
  760. pRect->right += pCommon->nXStart - 1;
  761. pRect->top += pCommon->nYStart;
  762. pRect->bottom += pCommon->nYStart - 1;
  763. //
  764. // If this is an ExtTextOut order then we must take into account the
  765. // opaque/clipping rectangle if there is one.
  766. //
  767. if (fExtTextOut)
  768. {
  769. //
  770. // If the rectangle is an opaque rectangle then expand the bounding
  771. // rectangle to bound the opaque rectangle also.
  772. //
  773. if (pExtTextOut->fuOptions & ETO_OPAQUE)
  774. {
  775. pRect->left = min(pExtTextOut->rectangle.left, pRect->left);
  776. pRect->right = max(pExtTextOut->rectangle.right,
  777. pRect->right);
  778. pRect->top = min(pExtTextOut->rectangle.top,
  779. pRect->top);
  780. pRect->bottom = max(pExtTextOut->rectangle.bottom,
  781. pRect->bottom);
  782. }
  783. //
  784. // If the rectangle is a clip rectangle then restrict the bounding
  785. // rectangle to be within the clip rectangle.
  786. //
  787. if (pExtTextOut->fuOptions & ETO_CLIPPED)
  788. {
  789. pRect->left = max(pExtTextOut->rectangle.left,
  790. pRect->left);
  791. pRect->right = min(pExtTextOut->rectangle.right,
  792. pRect->right);
  793. pRect->top = max(pExtTextOut->rectangle.top,
  794. pRect->top);
  795. pRect->bottom = min(pExtTextOut->rectangle.bottom,
  796. pRect->bottom);
  797. }
  798. }
  799. DebugExitVOID(ASShare::OD2_CalculateTextOutBounds);
  800. }
  801. //
  802. // OD2_CalculateBounds()
  803. //
  804. void ASShare::OD2_CalculateBounds
  805. (
  806. LPCOM_ORDER pOrder,
  807. LPRECT pRect,
  808. BOOL fDecoding,
  809. ASPerson * pasPerson
  810. )
  811. {
  812. UINT i;
  813. UINT numPoints;
  814. DebugEntry(ASShare::OD2_CalculateBounds);
  815. ValidatePerson(pasPerson);
  816. //
  817. // Calculate the bounds according to the order type.
  818. // All blts can be handled in the same way.
  819. //
  820. switch ( ((LPPATBLT_ORDER)pOrder->abOrderData)->type )
  821. {
  822. //
  823. // Calculate bounds for the blts.
  824. // This is the destination rectangle. Bounds are inclusive.
  825. //
  826. case ORD_DSTBLT_TYPE:
  827. pRect->left =
  828. ((LPDSTBLT_ORDER)(pOrder->abOrderData))->nLeftRect;
  829. pRect->top = ((LPDSTBLT_ORDER)(pOrder->abOrderData))->nTopRect;
  830. pRect->right = pRect->left
  831. + ((LPDSTBLT_ORDER)(pOrder->abOrderData))->nWidth
  832. - 1;
  833. pRect->bottom = pRect->top
  834. + ((LPDSTBLT_ORDER)(pOrder->abOrderData))->nHeight
  835. - 1;
  836. break;
  837. case ORD_PATBLT_TYPE:
  838. pRect->left =
  839. ((LPPATBLT_ORDER)(pOrder->abOrderData))->nLeftRect;
  840. pRect->top =
  841. ((LPPATBLT_ORDER)(pOrder->abOrderData))->nTopRect;
  842. pRect->right =
  843. pRect->left +
  844. ((LPPATBLT_ORDER)(pOrder->abOrderData))->nWidth - 1;
  845. pRect->bottom =
  846. pRect->top +
  847. ((LPPATBLT_ORDER)(pOrder->abOrderData))->nHeight - 1;
  848. break;
  849. case ORD_SCRBLT_TYPE:
  850. pRect->left =
  851. ((LPSCRBLT_ORDER)(pOrder->abOrderData))->nLeftRect;
  852. pRect->top =
  853. ((LPSCRBLT_ORDER)(pOrder->abOrderData))->nTopRect;
  854. pRect->right =
  855. pRect->left +
  856. ((LPSCRBLT_ORDER)(pOrder->abOrderData))->nWidth - 1;
  857. pRect->bottom =
  858. pRect->top +
  859. ((LPSCRBLT_ORDER)(pOrder->abOrderData))->nHeight - 1;
  860. break;
  861. case ORD_MEMBLT_TYPE:
  862. pRect->left =
  863. ((LPMEMBLT_ORDER)(pOrder->abOrderData))->nLeftRect;
  864. pRect->top =
  865. ((LPMEMBLT_ORDER)(pOrder->abOrderData))->nTopRect;
  866. pRect->right =
  867. pRect->left +
  868. ((LPMEMBLT_ORDER)(pOrder->abOrderData))->nWidth - 1;
  869. pRect->bottom =
  870. pRect->top +
  871. ((LPMEMBLT_ORDER)(pOrder->abOrderData))->nHeight - 1;
  872. break;
  873. case ORD_MEM3BLT_TYPE:
  874. pRect->left =
  875. ((LPMEM3BLT_ORDER)(pOrder->abOrderData))->nLeftRect;
  876. pRect->top =
  877. ((LPMEM3BLT_ORDER)(pOrder->abOrderData))->nTopRect;
  878. pRect->right =
  879. pRect->left +
  880. ((LPMEM3BLT_ORDER)(pOrder->abOrderData))->nWidth - 1;
  881. pRect->bottom =
  882. pRect->top +
  883. ((LPMEM3BLT_ORDER)(pOrder->abOrderData))->nHeight - 1;
  884. break;
  885. case ORD_MEMBLT_R2_TYPE:
  886. pRect->left =
  887. ((LPMEMBLT_R2_ORDER)(pOrder->abOrderData))->nLeftRect;
  888. pRect->top =
  889. ((LPMEMBLT_R2_ORDER)(pOrder->abOrderData))->nTopRect;
  890. pRect->right =
  891. pRect->left +
  892. ((LPMEMBLT_R2_ORDER)(pOrder->abOrderData))->nWidth - 1;
  893. pRect->bottom =
  894. pRect->top +
  895. ((LPMEMBLT_R2_ORDER)(pOrder->abOrderData))->nHeight - 1;
  896. break;
  897. case ORD_MEM3BLT_R2_TYPE:
  898. pRect->left =
  899. ((LPMEM3BLT_R2_ORDER)(pOrder->abOrderData))->nLeftRect;
  900. pRect->top =
  901. ((LPMEM3BLT_R2_ORDER)(pOrder->abOrderData))->nTopRect;
  902. pRect->right =
  903. pRect->left +
  904. ((LPMEM3BLT_R2_ORDER)(pOrder->abOrderData))->nWidth - 1;
  905. pRect->bottom =
  906. pRect->top +
  907. ((LPMEM3BLT_R2_ORDER)(pOrder->abOrderData))->nHeight - 1;
  908. break;
  909. //
  910. // Calculate bounds for Rectangle.
  911. // This is the rectangle itself. Bounds are inclusive.
  912. //
  913. case ORD_RECTANGLE_TYPE:
  914. pRect->left =
  915. ((LPRECTANGLE_ORDER)(pOrder->abOrderData))->nLeftRect;
  916. pRect->top =
  917. ((LPRECTANGLE_ORDER)(pOrder->abOrderData))->nTopRect;
  918. pRect->right =
  919. ((LPRECTANGLE_ORDER)(pOrder->abOrderData))->nRightRect;
  920. pRect->bottom =
  921. ((LPRECTANGLE_ORDER)(pOrder->abOrderData))->nBottomRect;
  922. break;
  923. case ORD_ROUNDRECT_TYPE:
  924. pRect->left =
  925. ((LPROUNDRECT_ORDER)(pOrder->abOrderData))->nLeftRect;
  926. pRect->top =
  927. ((LPROUNDRECT_ORDER)(pOrder->abOrderData))->nTopRect;
  928. pRect->right =
  929. ((LPROUNDRECT_ORDER)(pOrder->abOrderData))->nRightRect;
  930. pRect->bottom =
  931. ((LPROUNDRECT_ORDER)(pOrder->abOrderData))->nBottomRect;
  932. break;
  933. case ORD_POLYGON_TYPE:
  934. //
  935. // Calculate bounds for Polygon.
  936. //
  937. pRect->left = 0x7fff;
  938. pRect->right = 0;
  939. pRect->top = 0x7fff;
  940. pRect->bottom = 0;
  941. //
  942. // BOGUS! LAURABU BUGBUG
  943. //
  944. // In NM 2.0, the wrong fields were being compared. x to top/
  945. // bottom, and y to left/right.
  946. //
  947. // Effectively, this meant that we never matched the bounds
  948. // in the rcsDst rect.
  949. //
  950. numPoints = ((LPPOLYGON_ORDER)(pOrder->abOrderData))->
  951. variablePoints.len
  952. / sizeof(((LPPOLYGON_ORDER)(pOrder->abOrderData))->
  953. variablePoints.aPoints[0]);
  954. for (i = 0; i < numPoints; i++ )
  955. {
  956. if ( ((LPPOLYGON_ORDER)(pOrder->abOrderData))
  957. ->variablePoints.aPoints[i].y > pRect->bottom )
  958. {
  959. pRect->bottom = ((LPPOLYGON_ORDER)(pOrder->abOrderData))
  960. ->variablePoints.aPoints[i].y;
  961. }
  962. if ( ((LPPOLYGON_ORDER)(pOrder->abOrderData))
  963. ->variablePoints.aPoints[i].y < pRect->top )
  964. {
  965. pRect->top = ((LPPOLYGON_ORDER)(pOrder->abOrderData))
  966. ->variablePoints.aPoints[i].y;
  967. }
  968. if ( ((LPPOLYGON_ORDER)(pOrder->abOrderData))
  969. ->variablePoints.aPoints[i].x > pRect->right )
  970. {
  971. pRect->right = ((LPPOLYGON_ORDER)(pOrder->abOrderData))
  972. ->variablePoints.aPoints[i].x;
  973. }
  974. if ( ((LPPOLYGON_ORDER)(pOrder->abOrderData))
  975. ->variablePoints.aPoints[i].x < pRect->left )
  976. {
  977. pRect->left = ((LPPOLYGON_ORDER)(pOrder->abOrderData))
  978. ->variablePoints.aPoints[i].x;
  979. }
  980. }
  981. TRACE_OUT(("Poly bounds: left:%d, right:%d, top:%d, bottom:%d",
  982. pRect->left, pRect->right, pRect->top, pRect->bottom ));
  983. break;
  984. case ORD_PIE_TYPE:
  985. //
  986. // Pull out the bounding rectangle directly from the PIE order.
  987. //
  988. pRect->left = ((LPPIE_ORDER)(pOrder->abOrderData))->nLeftRect;
  989. pRect->top = ((LPPIE_ORDER)(pOrder->abOrderData))->nTopRect;
  990. pRect->right = ((LPPIE_ORDER)(pOrder->abOrderData))->nRightRect;
  991. pRect->bottom = ((LPPIE_ORDER)(pOrder->abOrderData))->nBottomRect;
  992. break;
  993. case ORD_ELLIPSE_TYPE:
  994. //
  995. // Pull out the bounding rectangle directly from ELLIPSE order.
  996. //
  997. pRect->left = ((LPELLIPSE_ORDER)(pOrder->abOrderData))->nLeftRect;
  998. pRect->top = ((LPELLIPSE_ORDER)(pOrder->abOrderData))->nTopRect;
  999. pRect->right =
  1000. ((LPELLIPSE_ORDER)(pOrder->abOrderData))->nRightRect;
  1001. pRect->bottom =
  1002. ((LPELLIPSE_ORDER)(pOrder->abOrderData))->nBottomRect;
  1003. break;
  1004. case ORD_ARC_TYPE:
  1005. //
  1006. // Pull out the bounding rectangle directly from the ARC order.
  1007. //
  1008. pRect->left = ((LPARC_ORDER)(pOrder->abOrderData))->nLeftRect;
  1009. pRect->top = ((LPARC_ORDER)(pOrder->abOrderData))->nTopRect;
  1010. pRect->right = ((LPARC_ORDER)(pOrder->abOrderData))->nRightRect;
  1011. pRect->bottom = ((LPARC_ORDER)(pOrder->abOrderData))->nBottomRect;
  1012. break;
  1013. case ORD_CHORD_TYPE:
  1014. //
  1015. // Pull out the bounding rectangle directly from the CHORD
  1016. // order.
  1017. //
  1018. pRect->left = ((LPCHORD_ORDER)(pOrder->abOrderData))->nLeftRect;
  1019. pRect->top = ((LPCHORD_ORDER)(pOrder->abOrderData))->nTopRect;
  1020. pRect->right = ((LPCHORD_ORDER)(pOrder->abOrderData))->nRightRect;
  1021. pRect->bottom =
  1022. ((LPCHORD_ORDER)(pOrder->abOrderData))->nBottomRect;
  1023. break;
  1024. case ORD_POLYBEZIER_TYPE:
  1025. //
  1026. // Calculate bounds for PolyBezier.
  1027. //
  1028. pRect->left = 0x7fff;
  1029. pRect->right = 0;
  1030. pRect->top = 0x7fff;
  1031. pRect->bottom = 0;
  1032. numPoints = ((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))->
  1033. variablePoints.len
  1034. / sizeof(((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))->
  1035. variablePoints.aPoints[0]);
  1036. //
  1037. // BOGUS! LAURABU BUGBUG
  1038. //
  1039. // In NM 2.0, the wrong fields were being compared. x to top/
  1040. // bottom, and y to left/right.
  1041. //
  1042. // Effectively, this meant that we never matched the bounds
  1043. // in the rcsDst rect.
  1044. //
  1045. for (i = 0; i < numPoints; i++ )
  1046. {
  1047. if ( ((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))
  1048. ->variablePoints.aPoints[i].y > pRect->bottom )
  1049. {
  1050. pRect->bottom = ((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))
  1051. ->variablePoints.aPoints[i].y;
  1052. }
  1053. if ( ((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))
  1054. ->variablePoints.aPoints[i].y < pRect->top )
  1055. {
  1056. pRect->top = ((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))
  1057. ->variablePoints.aPoints[i].y;
  1058. }
  1059. if ( ((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))
  1060. ->variablePoints.aPoints[i].x > pRect->right )
  1061. {
  1062. pRect->right = ((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))
  1063. ->variablePoints.aPoints[i].x;
  1064. }
  1065. if ( ((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))
  1066. ->variablePoints.aPoints[i].x < pRect->left )
  1067. {
  1068. pRect->left = ((LPPOLYBEZIER_ORDER)(pOrder->abOrderData))
  1069. ->variablePoints.aPoints[i].x;
  1070. }
  1071. }
  1072. TRACE_OUT((
  1073. "PolyBezier bounds: left:%d, right:%d, top:%d, bot:%d",
  1074. pRect->left, pRect->right, pRect->top, pRect->bottom));
  1075. break;
  1076. case ORD_LINETO_TYPE:
  1077. //
  1078. // Calculate bounds for LineTo. This is the rectangle with
  1079. // opposite vertices on the start and end points of the line.
  1080. // The gradient of the line determines whether the start or end
  1081. // point provides the top or bottom, left or right of the
  1082. // rectangle. Bounds are inclusive.
  1083. //
  1084. if ( ((LPLINETO_ORDER)(pOrder->abOrderData))->nXStart <
  1085. ((LPLINETO_ORDER)(pOrder->abOrderData))->nXEnd )
  1086. {
  1087. pRect->left =
  1088. ((LPLINETO_ORDER)(pOrder->abOrderData))->nXStart;
  1089. pRect->right =
  1090. ((LPLINETO_ORDER)(pOrder->abOrderData))->nXEnd;
  1091. }
  1092. else
  1093. {
  1094. pRect->right =
  1095. ((LPLINETO_ORDER)pOrder->abOrderData)->nXStart;
  1096. pRect->left =
  1097. ((LPLINETO_ORDER)pOrder->abOrderData)->nXEnd;
  1098. }
  1099. if ( ((LPLINETO_ORDER)pOrder->abOrderData)->nYStart <
  1100. ((LPLINETO_ORDER)pOrder->abOrderData)->nYEnd )
  1101. {
  1102. pRect->top =
  1103. ((LPLINETO_ORDER)pOrder->abOrderData)->nYStart;
  1104. pRect->bottom =
  1105. ((LPLINETO_ORDER)pOrder->abOrderData)->nYEnd;
  1106. }
  1107. else
  1108. {
  1109. pRect->bottom =
  1110. ((LPLINETO_ORDER)pOrder->abOrderData)->nYStart;
  1111. pRect->top =
  1112. ((LPLINETO_ORDER)pOrder->abOrderData)->nYEnd;
  1113. }
  1114. break;
  1115. case ORD_OPAQUERECT_TYPE:
  1116. //
  1117. // Calculate bounds for OpaqueRect. This is the rectangle
  1118. // itself. Bounds are inclusive.
  1119. //
  1120. pRect->left =
  1121. ((LPOPAQUERECT_ORDER)(pOrder->abOrderData))->nLeftRect;
  1122. pRect->top =
  1123. ((LPOPAQUERECT_ORDER)(pOrder->abOrderData))->nTopRect;
  1124. pRect->right =
  1125. pRect->left +
  1126. ((LPOPAQUERECT_ORDER)(pOrder->abOrderData))->nWidth - 1;
  1127. pRect->bottom =
  1128. pRect->top +
  1129. ((LPOPAQUERECT_ORDER)(pOrder->abOrderData))->nHeight - 1;
  1130. break;
  1131. case ORD_SAVEBITMAP_TYPE:
  1132. //
  1133. // Calculate bounds for SaveBitmap. This is the rectangle
  1134. // itself. Bounds are inclusive.
  1135. //
  1136. pRect->left =
  1137. ((LPSAVEBITMAP_ORDER)(pOrder->abOrderData))->nLeftRect;
  1138. pRect->top =
  1139. ((LPSAVEBITMAP_ORDER)(pOrder->abOrderData))->nTopRect;
  1140. pRect->bottom =
  1141. ((LPSAVEBITMAP_ORDER)(pOrder->abOrderData))->nBottomRect;
  1142. pRect->right =
  1143. ((LPSAVEBITMAP_ORDER)(pOrder->abOrderData))->nRightRect;
  1144. break;
  1145. case ORD_TEXTOUT_TYPE:
  1146. case ORD_EXTTEXTOUT_TYPE:
  1147. //
  1148. // TextOut and ExtTextOut bounds calculations are done by the
  1149. // OD2_CalculateTextOutBounds function.
  1150. //
  1151. OD2_CalculateTextOutBounds((LPTEXTOUT_ORDER)pOrder->abOrderData,
  1152. pRect,
  1153. fDecoding,
  1154. pasPerson);
  1155. break;
  1156. case ORD_DESKSCROLL_TYPE:
  1157. pRect->left = 0;
  1158. pRect->top = 0;
  1159. pRect->right = 0;
  1160. pRect->bottom = 0;
  1161. break;
  1162. default:
  1163. ERROR_OUT((
  1164. "{%p} unrecognized type passed to OD2ReconstructBounds: %d",
  1165. pasPerson,
  1166. (int)((LPPATBLT_ORDER)pOrder->abOrderData)->type));
  1167. break;
  1168. }
  1169. DebugExitVOID(ASShare::OD2_CalculateBounds);
  1170. }
  1171. //
  1172. // OD2DecodeBounds()
  1173. //
  1174. void ASShare::OD2DecodeBounds
  1175. (
  1176. LPBYTE* ppNextDataToCopy,
  1177. LPTSHR_RECT16 pRect,
  1178. ASPerson * pasPerson
  1179. )
  1180. {
  1181. LPBYTE pFlags;
  1182. DebugEntry(ASShare::OD2DecodeBounds);
  1183. ValidatePerson(pasPerson);
  1184. //
  1185. // The encoding used is a byte of flags followed by a variable number
  1186. // of 16bit coordinate values and 8bit delta coordinate values (which
  1187. // may be interleaved).
  1188. //
  1189. //
  1190. // The first byte of the encoding will contain the flags that represent
  1191. // how the coordinates of the rectangle were encoded.
  1192. //
  1193. pFlags = *ppNextDataToCopy;
  1194. (*ppNextDataToCopy)++;
  1195. //
  1196. // Initialise the rectangle with the last decoded coordinates.
  1197. //
  1198. *pRect = pasPerson->od2Party->LastBounds;
  1199. //
  1200. // If the flags indicate that none of the coordinates have changed then
  1201. // fast path and exit now.
  1202. //
  1203. if (*pFlags == 0)
  1204. {
  1205. return;
  1206. }
  1207. //
  1208. // For each of the four coordinate values in the rectangle: If the
  1209. // coordinate was encoded as an 8bit delta then add on the delta to the
  1210. // previous value. If the coordinate was encoded as a 16bit value
  1211. // then copy the value across. Otherwise the coordinate was the same
  1212. // as the previous one so leave it alone.
  1213. //
  1214. if (*pFlags & OE2_BCF_DELTA_LEFT)
  1215. {
  1216. OD2CopyFromDeltaCoords((LPTSHR_INT8*)ppNextDataToCopy,
  1217. &pRect->left,
  1218. sizeof(pRect->left),
  1219. TRUE, // The value is signed
  1220. 1);
  1221. }
  1222. else if (*pFlags & OE2_BCF_LEFT)
  1223. {
  1224. pRect->left = EXTRACT_TSHR_INT16_UA(*ppNextDataToCopy);
  1225. (*ppNextDataToCopy) += sizeof(TSHR_INT16);
  1226. }
  1227. if (*pFlags & OE2_BCF_DELTA_TOP)
  1228. {
  1229. OD2CopyFromDeltaCoords((LPTSHR_INT8*)ppNextDataToCopy,
  1230. &pRect->top,
  1231. sizeof(pRect->top),
  1232. TRUE, // The value is signed
  1233. 1);
  1234. }
  1235. else if (*pFlags & OE2_BCF_TOP)
  1236. {
  1237. pRect->top = EXTRACT_TSHR_INT16_UA(*ppNextDataToCopy);
  1238. (*ppNextDataToCopy) += sizeof(TSHR_INT16);
  1239. }
  1240. if (*pFlags & OE2_BCF_DELTA_RIGHT)
  1241. {
  1242. OD2CopyFromDeltaCoords((LPTSHR_INT8*)ppNextDataToCopy,
  1243. &pRect->right,
  1244. sizeof(pRect->right),
  1245. TRUE, // The value is signed
  1246. 1);
  1247. }
  1248. else if (*pFlags & OE2_BCF_RIGHT)
  1249. {
  1250. pRect->right = EXTRACT_TSHR_INT16_UA(*ppNextDataToCopy);
  1251. (*ppNextDataToCopy) += sizeof(TSHR_INT16);
  1252. }
  1253. if (*pFlags & OE2_BCF_DELTA_BOTTOM)
  1254. {
  1255. OD2CopyFromDeltaCoords((LPTSHR_INT8*)ppNextDataToCopy,
  1256. &pRect->bottom,
  1257. sizeof(pRect->bottom),
  1258. TRUE, // The value is signed
  1259. 1);
  1260. }
  1261. else if (*pFlags & OE2_BCF_BOTTOM)
  1262. {
  1263. pRect->bottom = EXTRACT_TSHR_INT16_UA(*ppNextDataToCopy);
  1264. (*ppNextDataToCopy) += sizeof(TSHR_INT16);
  1265. }
  1266. //
  1267. // Copy the rectangle for reference with the next encoding.
  1268. //
  1269. pasPerson->od2Party->LastBounds = *pRect;
  1270. DebugExitVOID(ASShare::OD2DecodeBounds);
  1271. }
  1272. //
  1273. // Copy an array of source elements to an array of destination elements,
  1274. // converting the types as the copy takes place.
  1275. //
  1276. // DESTARRAY - The destination array
  1277. // SRCARRAY - The source array
  1278. // DESTTYPE - The type of the elements in the destination array
  1279. // NUMELEMENTS - The number of elements in the array
  1280. //
  1281. //
  1282. #define CONVERT_ARRAY(DESTARRAY, SRCARRAY, DESTTYPE, NUMELEMENTS) \
  1283. { \
  1284. UINT index; \
  1285. for (index=0 ; index<(NUMELEMENTS) ; index++) \
  1286. { \
  1287. (DESTARRAY)[index] = (DESTTYPE)(SRCARRAY)[index]; \
  1288. } \
  1289. }
  1290. //
  1291. // Copy an array of source elements to an array of destination elements,
  1292. // converting the types as the copy takes place. This version allows for
  1293. // unaligned INT16 pointers
  1294. //
  1295. // DESTARRAY - The destination array
  1296. // SRCARRAY - The source array
  1297. // DESTTYPE - The type of the elements in the destination array
  1298. // NUMELEMENTS - The number of elements in the array
  1299. //
  1300. //
  1301. #define CONVERT_ARRAY_INT16_UA(DESTARRAY, SRCARRAY, DESTTYPE, NUMELEMENTS) \
  1302. { \
  1303. UINT index; \
  1304. TSHR_INT16 value; \
  1305. for (index=0 ; index<(NUMELEMENTS) ; index++) \
  1306. { \
  1307. value = EXTRACT_TSHR_INT16_UA((SRCARRAY)+index); \
  1308. (DESTARRAY)[index] = (DESTTYPE)value; \
  1309. } \
  1310. }
  1311. //
  1312. // Copy an array of source elements to an array of destination elements,
  1313. // converting the types as the copy takes place. This version allows for
  1314. // unaligned TSHR_UINT16 pointers
  1315. //
  1316. // DESTARRAY - The destination array
  1317. // SRCARRAY - The source array
  1318. // DESTTYPE - The type of the elements in the destination array
  1319. // NUMELEMENTS - The number of elements in the array
  1320. //
  1321. //
  1322. #define CONVERT_ARRAY_UINT16_UA(DESTARRAY, SRCARRAY, DESTTYPE, NUMELEMENTS) \
  1323. { \
  1324. UINT index; \
  1325. TSHR_UINT16 value; \
  1326. for (index=0 ; index<(NUMELEMENTS) ; index++) \
  1327. { \
  1328. value = EXTRACT_TSHR_UINT16_UA((SRCARRAY)+index); \
  1329. (DESTARRAY)[index] = (DESTTYPE)((TSHR_INT16)value); \
  1330. } \
  1331. }
  1332. //
  1333. // OD2DecodeField()
  1334. //
  1335. void ASShare::OD2DecodeField
  1336. (
  1337. LPBYTE* ppSrc,
  1338. LPVOID pDst,
  1339. UINT cbSrcField,
  1340. UINT cbDstField,
  1341. BOOL fSigned,
  1342. UINT numElements
  1343. )
  1344. {
  1345. LPTSHR_UINT8 pDst8 = (LPTSHR_UINT8)pDst;
  1346. LPTSHR_INT16 pDst16Signed = (LPTSHR_INT16)pDst;
  1347. LPTSHR_INT32 pDst32Signed = (LPTSHR_INT32)pDst;
  1348. LPTSHR_UINT16 pDst16Unsigned = (LPTSHR_UINT16)pDst;
  1349. LPTSHR_UINT32 pDst32Unsigned = (LPTSHR_UINT32)pDst;
  1350. LPTSHR_INT8 pSrc8Signed = (LPTSHR_INT8)*ppSrc;
  1351. LPTSHR_UINT8 pSrc8Unsigned = (LPTSHR_UINT8)*ppSrc;
  1352. LPTSHR_INT16_UA pSrc16Signed = (LPTSHR_INT16_UA)*ppSrc;
  1353. LPTSHR_UINT16_UA pSrc16Unsigned = (LPTSHR_UINT16_UA)*ppSrc;
  1354. //
  1355. // Note that the source fields may not be aligned correctly, so we use
  1356. // unaligned pointers. The destination is aligned correctly.
  1357. //
  1358. DebugEntry(ASShare::OD2DecodeField);
  1359. //
  1360. // Make sure that the destination field length is larger or equal to
  1361. // the source field length. If it isn't, something has gone wrong.
  1362. //
  1363. if (cbDstField < cbSrcField)
  1364. {
  1365. ERROR_OUT(( "Source field length %d is larger than destination %d",
  1366. cbSrcField,
  1367. cbDstField));
  1368. DC_QUIT;
  1369. }
  1370. //
  1371. // If the source and destination field lengths are the same, we can
  1372. // just do a copy (no type conversion required).
  1373. //
  1374. if (cbSrcField == cbDstField)
  1375. {
  1376. memcpy(pDst8, *ppSrc, cbDstField * numElements);
  1377. }
  1378. else
  1379. {
  1380. //
  1381. // We know that cbDstField must be greater than cbSrcField
  1382. // because of our checks above. So there are only three
  1383. // conversions to consider:
  1384. //
  1385. // 8 bit -> 16 bit
  1386. // 8 bit -> 32 bit
  1387. // 16 bit -> 32 bit
  1388. //
  1389. // We also have to get the signed / unsigned attributes correct. If
  1390. // we try to promote a signed value using unsigned pointers, we
  1391. // will get the wrong result.
  1392. //
  1393. // e.g. Consider converting the value -1 from a TSHR_INT16 to TSHR_INT32
  1394. // using unsigned pointers.
  1395. //
  1396. // -1 -> TSHR_UINT16 == 65535
  1397. // -> UINT == 65535
  1398. // -> TSHR_INT32 == 65535
  1399. //
  1400. //
  1401. if ((cbDstField == 4) && (cbSrcField == 1))
  1402. {
  1403. if (fSigned)
  1404. {
  1405. CONVERT_ARRAY(pDst32Signed,
  1406. pSrc8Signed,
  1407. TSHR_INT32,
  1408. numElements);
  1409. }
  1410. else
  1411. {
  1412. CONVERT_ARRAY(pDst32Unsigned,
  1413. pSrc8Unsigned,
  1414. TSHR_UINT32,
  1415. numElements);
  1416. }
  1417. }
  1418. else if ((cbDstField == 4) && (cbSrcField == 2))
  1419. {
  1420. if (fSigned)
  1421. {
  1422. CONVERT_ARRAY_INT16_UA(pDst32Signed,
  1423. pSrc16Signed,
  1424. TSHR_INT32,
  1425. numElements);
  1426. }
  1427. else
  1428. {
  1429. CONVERT_ARRAY_UINT16_UA(pDst32Unsigned,
  1430. pSrc16Unsigned,
  1431. TSHR_UINT32,
  1432. numElements);
  1433. }
  1434. }
  1435. else if ((cbDstField == 2) && (cbSrcField == 1))
  1436. {
  1437. if (fSigned)
  1438. {
  1439. CONVERT_ARRAY(pDst16Signed,
  1440. pSrc8Signed,
  1441. TSHR_INT16,
  1442. numElements);
  1443. }
  1444. else
  1445. {
  1446. CONVERT_ARRAY(pDst16Unsigned,
  1447. pSrc8Unsigned,
  1448. TSHR_UINT16,
  1449. numElements);
  1450. }
  1451. }
  1452. else
  1453. {
  1454. ERROR_OUT(( "Bad conversion, dest length = %d, src length = %d",
  1455. cbDstField,
  1456. cbSrcField));
  1457. }
  1458. }
  1459. DC_EXIT_POINT:
  1460. *ppSrc += cbSrcField * numElements;
  1461. DebugExitVOID(ASShare::OD2DecodeField);
  1462. }
  1463. //
  1464. // Given two arrays, a source array and an array of deltas, add each delta
  1465. // to the corresponding element in the source array, storing the results in
  1466. // the source array.
  1467. //
  1468. // srcArray - The array of source values
  1469. // srcArrayType - The type of the array of source values
  1470. // deltaArray - The array of deltas
  1471. // numElements - The number of elements in the arrays
  1472. //
  1473. //
  1474. #define COPY_DELTA_ARRAY(srcArray, srcArrayType, deltaArray, numElements) \
  1475. { \
  1476. UINT index; \
  1477. for (index = 0; index < (numElements); index++) \
  1478. { \
  1479. (srcArray)[index] = (srcArrayType) \
  1480. ((srcArray)[index] + (deltaArray)[index]); \
  1481. } \
  1482. }
  1483. //
  1484. // OD2CopyFromDeltaCoords()
  1485. //
  1486. void ASShare::OD2CopyFromDeltaCoords
  1487. (
  1488. LPTSHR_INT8* ppSrc,
  1489. LPVOID pDst,
  1490. UINT cbDstField,
  1491. BOOL fSigned,
  1492. UINT numElements
  1493. )
  1494. {
  1495. LPTSHR_INT8 pDst8Signed = (LPTSHR_INT8)pDst;
  1496. LPTSHR_INT16 pDst16Signed = (LPTSHR_INT16)pDst;
  1497. LPTSHR_INT32 pDst32Signed = (LPTSHR_INT32)pDst;
  1498. LPTSHR_UINT8 pDst8Unsigned = (LPTSHR_UINT8)pDst;
  1499. LPTSHR_UINT16 pDst16Unsigned = (LPTSHR_UINT16)pDst;
  1500. LPTSHR_UINT32 pDst32Unsigned = (LPTSHR_UINT32)pDst;
  1501. DebugEntry(ASShare::OD2CopyFromDeltaCoords);
  1502. switch (cbDstField)
  1503. {
  1504. case 1:
  1505. if (fSigned)
  1506. {
  1507. COPY_DELTA_ARRAY(pDst8Signed, TSHR_INT8, *ppSrc, numElements);
  1508. }
  1509. else
  1510. {
  1511. COPY_DELTA_ARRAY(pDst8Unsigned, TSHR_UINT8, *ppSrc, numElements);
  1512. }
  1513. break;
  1514. case 2:
  1515. if (fSigned)
  1516. {
  1517. COPY_DELTA_ARRAY(pDst16Signed, TSHR_INT16, *ppSrc, numElements);
  1518. }
  1519. else
  1520. {
  1521. COPY_DELTA_ARRAY(pDst16Unsigned, TSHR_UINT16, *ppSrc, numElements);
  1522. }
  1523. break;
  1524. case 4:
  1525. if (fSigned)
  1526. {
  1527. COPY_DELTA_ARRAY(pDst32Signed, TSHR_INT32, *ppSrc, numElements);
  1528. }
  1529. else
  1530. {
  1531. COPY_DELTA_ARRAY(pDst32Unsigned, TSHR_UINT32, *ppSrc, numElements);
  1532. }
  1533. break;
  1534. default:
  1535. ERROR_OUT(( "Bad destination field length %d",
  1536. cbDstField));
  1537. DC_QUIT;
  1538. // break;
  1539. }
  1540. DC_EXIT_POINT:
  1541. *ppSrc += numElements;
  1542. DebugExitVOID(ASShare::OD2CopyFromDeltaCoords);
  1543. }
  1544.