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.

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