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.

1867 lines
41 KiB

  1. //
  2. // DRAWOBJ.CPP
  3. // Drawing objects: point, openpolyline, closepolyline, ellipse
  4. //
  5. // Copyright Microsoft 1998-
  6. //
  7. #include "precomp.h"
  8. #define DECIMAL_PRECISION 100
  9. DrawObj::DrawObj(UINT drawingType, UINT toolType):
  10. m_drawingType(drawingType),
  11. m_isDrawingCompleted(FALSE)
  12. {
  13. SetMyWorkspace(NULL);
  14. SetOwnerID(g_MyMemberID);
  15. m_ToolType = toolType;
  16. //
  17. // Created locally, not selected, not editing or deleting.
  18. //
  19. CreatedLocally();
  20. ClearSelectionFlags();
  21. ClearEditionFlags();
  22. ClearDeletionFlags();
  23. SetFillColor(0,FALSE);
  24. //
  25. // No attributes changed, they will be set as we change them
  26. //
  27. ResetAttrib();
  28. DBG_SAVE_FILE_LINE
  29. m_points = new DCDWordArray();
  30. SetWorkspaceHandle(g_pCurrentWorkspace == NULL ? 0 : g_pCurrentWorkspace->GetWorkspaceHandle());
  31. SetType(drawingCreatePDU_chosen);
  32. SetPenNib(circular_chosen);
  33. SetROP(R2_NOTXORPEN);
  34. SetPlaneID(1);
  35. SetMyPosition(NULL);
  36. SetMyWorkspace(NULL);
  37. RECT rect;
  38. ::SetRectEmpty(&rect);
  39. SetBoundsRect(&rect);
  40. SetRect(&rect);
  41. }
  42. DrawObj::DrawObj (DrawingCreatePDU * pdrawingCreatePDU)
  43. {
  44. SetType(drawingCreatePDU_chosen);
  45. SetMyWorkspace(NULL);
  46. //
  47. // Created remotely, not selected, not editing or deleting.
  48. //
  49. ClearCreationFlags();
  50. ClearSelectionFlags();
  51. ClearEditionFlags();
  52. ClearDeletionFlags();
  53. ResetAttrib();
  54. //
  55. // Get the drawing handle
  56. //
  57. SetThisObjectHandle(pdrawingCreatePDU->drawingHandle);
  58. //
  59. // Get the destination address
  60. //
  61. UINT workspaceHandle;
  62. UINT planeID;
  63. GetDrawingDestinationAddress(&pdrawingCreatePDU->destinationAddress, &workspaceHandle, &planeID);
  64. SetWorkspaceHandle(workspaceHandle);
  65. SetPlaneID(planeID);
  66. TRACE_DEBUG(("Destination address, Workspace Handle = %d", workspaceHandle));
  67. TRACE_DEBUG(("Destination address, Plane ID = %d", planeID));
  68. //
  69. // Get the drawing type, line, circle, etc ...
  70. //
  71. SetDrawingType(pdrawingCreatePDU->drawingType.choice);
  72. //
  73. // Set defaults
  74. //
  75. // m_T126Drawing.m_sampleRate = INVALID_SAMPLE_RATE;
  76. //
  77. // Default attributes
  78. //
  79. // Pen color black
  80. SetPenColor(0,TRUE);
  81. // No fill color
  82. SetFillColor(0,FALSE);
  83. // 1 Pixels for pen thickness
  84. SetPenThickness(1);
  85. // Pen Nib is circular
  86. SetPenNib(circular_chosen);
  87. // Solid line
  88. SetLineStyle(PS_SOLID);
  89. // No highlight
  90. SetHighlight(FALSE);
  91. // Not selected
  92. SetViewState(unselected_chosen);
  93. // Top object
  94. SetZOrder(front);
  95. // This is a complete drawing
  96. SetIsCompleted(TRUE);
  97. //
  98. // Get attributes
  99. //
  100. if(pdrawingCreatePDU->bit_mask & DrawingCreatePDU_attributes_present)
  101. {
  102. GetDrawingAttrib((PVOID)pdrawingCreatePDU->attributes);
  103. }
  104. DBG_SAVE_FILE_LINE
  105. m_points = new DCDWordArray();
  106. //
  107. // Get Anchor point
  108. //
  109. POINT Point;
  110. //
  111. // For open polylines the first point will be an offset of the anchor point
  112. //
  113. if(pdrawingCreatePDU->drawingType.choice == openPolyLine_chosen)
  114. {
  115. Point.x = 0;
  116. Point.y = 0;
  117. AddPoint(Point);
  118. }
  119. SetAnchorPoint(pdrawingCreatePDU->anchorPoint.xCoordinate, pdrawingCreatePDU->anchorPoint.yCoordinate);
  120. GetAnchorPoint(&Point);
  121. RECT rect;
  122. rect.left = pdrawingCreatePDU->anchorPoint.xCoordinate;
  123. rect.top = pdrawingCreatePDU->anchorPoint.yCoordinate;
  124. rect.right = pdrawingCreatePDU->anchorPoint.xCoordinate;
  125. rect.bottom = pdrawingCreatePDU->anchorPoint.yCoordinate;
  126. SetRect(&rect);
  127. SetBoundsRect(&rect);
  128. AddPointToBounds(pdrawingCreatePDU->anchorPoint.xCoordinate, pdrawingCreatePDU->anchorPoint.yCoordinate);
  129. //
  130. // Since we don't know ahead of time how many points we have, set the type as a polyline
  131. //
  132. m_ToolType = TOOLTYPE_PEN;
  133. //
  134. // Get consecutive points
  135. //
  136. UINT nPoints;
  137. nPoints = GetSubsequentPoints(pdrawingCreatePDU->pointList.choice, &Point, &pdrawingCreatePDU->pointList);
  138. //
  139. // Find out what UI tool are we, and set the correct ROP
  140. //
  141. SetUIToolType();
  142. if(nPoints == 1)
  143. {
  144. POINT *point;
  145. point = m_points->GetBuffer();
  146. rect.right = point->x + pdrawingCreatePDU->anchorPoint.xCoordinate;
  147. rect.bottom = point->y + pdrawingCreatePDU->anchorPoint.yCoordinate;
  148. SetRect(&rect);
  149. ::InflateRect(&rect, GetPenThickness()/2, GetPenThickness()/2);
  150. SetBoundsRect(&rect);
  151. }
  152. //
  153. // Get Non standard stuff
  154. //
  155. if(pdrawingCreatePDU->bit_mask & DrawingCreatePDU_nonStandardParameters_present)
  156. {
  157. ; // NYI
  158. }
  159. }
  160. DrawObj::~DrawObj( void )
  161. {
  162. RemoveObjectFromResendList(this);
  163. RemoveObjectFromRequestHandleList(this);
  164. TRACE_DEBUG(("drawingHandle = %d", GetThisObjectHandle() ));
  165. //
  166. // Tell other nodes that we are gone
  167. //
  168. if(GetMyWorkspace() != NULL && WasDeletedLocally())
  169. {
  170. OnObjectDelete();
  171. }
  172. //
  173. // Clear the list of points
  174. //
  175. delete m_points;
  176. }
  177. void DrawObj::DrawEditObj ( DrawingEditPDU * pdrawingEditPDU )
  178. {
  179. RECT rect;
  180. POSITION pos;
  181. POINT anchorPoint;
  182. LONG deltaX = 0;
  183. LONG deltaY = 0;
  184. TRACE_DEBUG(("DrawEditObj drawingHandle = %d", pdrawingEditPDU->drawingHandle ));
  185. //
  186. // Was edited remotely
  187. //
  188. ClearEditionFlags();
  189. //
  190. // Read attributes
  191. //
  192. if(pdrawingEditPDU->bit_mask & DrawingEditPDU_attributeEdits_present)
  193. {
  194. GetDrawingAttrib((PVOID)pdrawingEditPDU->attributeEdits);
  195. }
  196. //
  197. // Change the anchor point
  198. //
  199. GetAnchorPoint(&anchorPoint);
  200. if(pdrawingEditPDU->bit_mask & DrawingEditPDU_anchorPointEdit_present)
  201. {
  202. TRACE_DEBUG(("Old anchor point (%d,%d)", anchorPoint.x, anchorPoint.y));
  203. TRACE_DEBUG(("New anchor point (%d,%d)",
  204. pdrawingEditPDU->anchorPointEdit.xCoordinate, pdrawingEditPDU->anchorPointEdit.yCoordinate));
  205. //
  206. // Get the delta from previous anchor point
  207. //
  208. deltaX = pdrawingEditPDU->anchorPointEdit.xCoordinate - anchorPoint.x;
  209. deltaY = pdrawingEditPDU->anchorPointEdit.yCoordinate - anchorPoint.y;
  210. TRACE_DEBUG(("Delta (%d,%d)", deltaX , deltaY));
  211. //
  212. // Was edited remotely
  213. //
  214. ClearEditionFlags();
  215. }
  216. //
  217. // Get Rotation
  218. //
  219. // if(pdrawingEditPDU->bit_mask & rotationEdit_present)
  220. // {
  221. // m_T126Drawing.m_rotation.m_bIsPresent = TRUE;
  222. // m_T126Drawing.m_rotation.m_rotation.rotationAngle = pdrawingEditPDU->rotation.rotationAngle;
  223. // m_T126Drawing.m_rotation.m_rotation.rotationAxis.xCoordinate = pdrawingEditPDU->rotation.rotationAxis.xCoordinate;
  224. // m_T126Drawing.m_rotation.m_rotation.rotationAxis.yCoordinate = pdrawingEditPDU->rotation.rotationAxis.yCoordinate;
  225. // }
  226. // else
  227. // {
  228. // m_T126Drawing.m_rotation.m_bIsPresent = FALSE;
  229. // }
  230. //
  231. // Get the list of points
  232. //
  233. if(pdrawingEditPDU->bit_mask & pointListEdits_present)
  234. {
  235. UINT i, initialIndex, xInitial,yInitial,numberOfPoints;
  236. PointListEdits_Seq pointList;
  237. POINT initialPoint;
  238. TRACE_DEBUG(("Number of point edit lists %d", pdrawingEditPDU->pointListEdits.count));
  239. for (i = 0; i<pdrawingEditPDU->pointListEdits.count; i++)
  240. {
  241. pointList = pdrawingEditPDU->pointListEdits.value[i];
  242. initialIndex = pointList.initialIndex;
  243. TRACE_DEBUG(("Points cached = %d", m_points->GetSize()));
  244. TRACE_DEBUG(("initialIndex = %d", initialIndex));
  245. initialPoint.x = pointList.initialPointEdit.xCoordinate;
  246. initialPoint.y = pointList.initialPointEdit.yCoordinate;
  247. POINT * pPoint = m_points->GetBuffer();
  248. TRACE_DEBUG(("initialPoint=(%d, %d), previousPoint=(%d, %d), anchorPoint=(%d, %d)",
  249. initialPoint.x, initialPoint.y,
  250. pPoint[initialIndex-1].x, pPoint[initialIndex-1].y,
  251. anchorPoint.x , anchorPoint.y
  252. ));
  253. if(initialIndex > 1)
  254. {
  255. for(UINT i = 0; i< initialIndex; i++)
  256. {
  257. deltaX += pPoint[i].x;
  258. deltaY += pPoint[i].y;
  259. }
  260. initialPoint.x -= deltaX;
  261. initialPoint.y -= deltaY;
  262. }
  263. m_points->SetSize(initialIndex);
  264. AddPoint(initialPoint);
  265. if(GetDrawingType() == rectangle_chosen || GetDrawingType() == ellipse_chosen)
  266. {
  267. GetRect(&rect);
  268. rect.right = initialPoint.x + anchorPoint.x;
  269. rect.bottom = initialPoint.y + anchorPoint.y;
  270. SetRect(&rect);
  271. ::InflateRect(&rect, GetPenThickness()/2, GetPenThickness()/2);
  272. SetBoundsRect(&rect);
  273. }
  274. if(pointList.bit_mask & subsequentPointEdits_present)
  275. {
  276. GetSubsequentPoints(pointList.subsequentPointEdits.choice,
  277. &anchorPoint,
  278. &pointList.subsequentPointEdits);
  279. }
  280. ChangedPointList();
  281. }
  282. }
  283. //
  284. // Just changed the anchor point, the other points have to change as well
  285. //
  286. if(pdrawingEditPDU->bit_mask & DrawingEditPDU_anchorPointEdit_present)
  287. {
  288. //
  289. // Set new anchor point
  290. //
  291. anchorPoint.x = pdrawingEditPDU->anchorPointEdit.xCoordinate;
  292. anchorPoint.y = pdrawingEditPDU->anchorPointEdit.yCoordinate;
  293. SetAnchorPoint(anchorPoint.x, anchorPoint.y);
  294. GetRect(&rect);
  295. ::OffsetRect(&rect, deltaX, deltaY);
  296. SetRect(&rect);
  297. GetBoundsRect(&rect);
  298. ::OffsetRect(&rect, deltaX, deltaY);
  299. SetBoundsRect(&rect);
  300. }
  301. if(pdrawingEditPDU->bit_mask & DrawingEditPDU_nonStandardParameters_present)
  302. {
  303. ; // Do the non Standard Edit PDU NYI
  304. }
  305. if(HasAnchorPointChanged() ||
  306. HasPointListChanged() ||
  307. HasFillColorChanged() ||
  308. HasPenColorChanged()||
  309. HasPenThicknessChanged()||
  310. HasLineStyleChanged())
  311. {
  312. g_pDraw->EraseInitialDrawFinal(0 - deltaX,0 - deltaY, FALSE, (T126Obj*)this);
  313. ::InvalidateRect(g_pDraw->m_hwnd, NULL, TRUE);
  314. }
  315. else if(HasZOrderChanged())
  316. {
  317. if(GetZOrder() == front)
  318. {
  319. g_pDraw->BringToTopSelection(FALSE, this);
  320. }
  321. else
  322. {
  323. g_pDraw->SendToBackSelection(FALSE, this);
  324. }
  325. }
  326. //
  327. // If it just select/unselected it
  328. //
  329. else if(HasViewStateChanged())
  330. {
  331. ; // do nothing
  332. }
  333. //
  334. // If we have a valid pen.
  335. //
  336. else if(GetPenThickness())
  337. {
  338. Draw();
  339. }
  340. //
  341. // Reset all the attributes
  342. //
  343. ResetAttrib();
  344. }
  345. void DrawObj::GetDrawingAttrib(PVOID pAttribPDU)
  346. {
  347. PDrawingEditPDU_attributeEdits attributes;
  348. attributes = (PDrawingEditPDU_attributeEdits)pAttribPDU;
  349. COLORREF rgb;
  350. while(attributes)
  351. {
  352. switch(attributes->value.choice)
  353. {
  354. case(penColor_chosen):
  355. {
  356. switch(attributes->value.u.penColor.choice)
  357. {
  358. // case(workspacePaletteIndex_chosen):
  359. // {
  360. // ASN1uint16_t workspacePaletteIndex = ((attributes->value.u.penColor).u).workspacePaletteIndex;
  361. // break;
  362. // }
  363. case(rgbTrueColor_chosen):
  364. {
  365. rgb = RGB(attributes->value.u.penColor.u.rgbTrueColor.r,
  366. attributes->value.u.penColor.u.rgbTrueColor.g,
  367. attributes->value.u.penColor.u.rgbTrueColor.b);
  368. SetPenColor(rgb, TRUE);
  369. TRACE_DEBUG(("Attribute penColor (r,g,b)=(%d, %d,%d)",
  370. attributes->value.u.penColor.u.rgbTrueColor.r,
  371. attributes->value.u.penColor.u.rgbTrueColor.g,
  372. attributes->value.u.penColor.u.rgbTrueColor.b));
  373. break;
  374. }
  375. case(transparent_chosen):
  376. {
  377. SetPenColor(0,FALSE);
  378. break;
  379. }
  380. default:
  381. ERROR_OUT(("Invalid penColor choice"));
  382. break;
  383. }
  384. break;
  385. }
  386. case(fillColor_chosen):
  387. {
  388. TRACE_DEBUG(("Attribute fillColor"));
  389. switch(attributes->value.u.fillColor.choice)
  390. {
  391. // case(workspacePaletteIndex_chosen):
  392. // {
  393. // ASN1uint16_t workspacePaletteIndex = ((attributes->value.u.fillColor).u).workspacePaletteIndex;
  394. // break;
  395. // }
  396. case(rgbTrueColor_chosen):
  397. {
  398. rgb = RGB(attributes->value.u.fillColor.u.rgbTrueColor.r,
  399. attributes->value.u.fillColor.u.rgbTrueColor.g,
  400. attributes->value.u.fillColor.u.rgbTrueColor.b);
  401. SetFillColor(rgb, TRUE);
  402. TRACE_DEBUG(("Attribute fillColor (r,g,b)=(%d, %d,%d)",
  403. attributes->value.u.fillColor.u.rgbTrueColor.r,
  404. attributes->value.u.fillColor.u.rgbTrueColor.g,
  405. attributes->value.u.fillColor.u.rgbTrueColor.b));
  406. break;
  407. }
  408. case(transparent_chosen):
  409. {
  410. SetFillColor(0,FALSE);
  411. break;
  412. }
  413. default:
  414. ERROR_OUT(("Invalid fillColor choice"));
  415. break;
  416. }
  417. break;
  418. }
  419. case(penThickness_chosen):
  420. {
  421. SetPenThickness(attributes->value.u.penThickness);
  422. TRACE_DEBUG(("Attribute penThickness %d", attributes->value.u.penThickness));
  423. break;
  424. }
  425. case(penNib_chosen):
  426. {
  427. if (attributes->value.u.penNib.choice != nonStandardNib_chosen)
  428. {
  429. SetPenNib(attributes->value.u.penNib.choice);
  430. TRACE_DEBUG(("Attribute penNib %d",attributes->value.u.penNib.choice));
  431. }
  432. else
  433. {
  434. // Do the non Standard penNib NYI
  435. ;
  436. }
  437. break;
  438. }
  439. case(lineStyle_chosen):
  440. {
  441. if((attributes->value.u.lineStyle).choice != nonStandardStyle_chosen)
  442. {
  443. SetLineStyle(attributes->value.u.lineStyle.choice - 1);
  444. TRACE_DEBUG(("Attribute lineStyle %d", attributes->value.u.lineStyle.choice));
  445. }
  446. else
  447. {
  448. // Do the non Standard lineStyle NYI
  449. ;
  450. }
  451. break;
  452. }
  453. case(highlight_chosen):
  454. {
  455. SetHighlight(attributes->value.u.highlight);
  456. TRACE_DEBUG(("Attribute highlight %d", attributes->value.u.highlight));
  457. break;
  458. }
  459. case(DrawingAttribute_viewState_chosen):
  460. {
  461. if((attributes->value.u.viewState).choice != nonStandardViewState_chosen)
  462. {
  463. SetViewState(attributes->value.u.viewState.choice);
  464. //
  465. // If the other node is selecting the drawing or unselecting
  466. //
  467. if(attributes->value.u.viewState.choice == selected_chosen)
  468. {
  469. SelectedRemotely();
  470. }
  471. else if(attributes->value.u.viewState.choice == unselected_chosen)
  472. {
  473. ClearSelectionFlags();
  474. }
  475. TRACE_DEBUG(("Attribute viewState %d", attributes->value.u.viewState.choice));
  476. }
  477. else
  478. {
  479. // Do the non Standard lineStyle NYI
  480. ;
  481. }
  482. break;
  483. }
  484. case(DrawingAttribute_zOrder_chosen):
  485. {
  486. SetZOrder(attributes->value.u.zOrder);
  487. TRACE_DEBUG(("Attribute zOrder %d", attributes->value.u.zOrder));
  488. break;
  489. }
  490. case(DrawingAttribute_nonStandardAttribute_chosen):
  491. {
  492. break; // NYI
  493. }
  494. default:
  495. ERROR_OUT(("Invalid attributes choice"));
  496. break;
  497. }
  498. attributes = attributes->next;
  499. }
  500. }
  501. UINT DrawObj::GetSubsequentPoints(UINT choice, POINT * initialPoint, PointList * pointList)
  502. {
  503. UINT numberOfPoints = 0;
  504. INT deltaX, deltaY;
  505. POINT point;
  506. if(choice == pointsDiff16_chosen)
  507. {
  508. PPointList_pointsDiff16 drawingPoint = pointList->u.pointsDiff16;
  509. deltaX = (SHORT)initialPoint->x;
  510. deltaY = (SHORT)initialPoint->y;
  511. TRACE_DEBUG(("initialpoint (%d,%d)", deltaX, deltaY));
  512. while(drawingPoint)
  513. {
  514. numberOfPoints++;
  515. point.x = drawingPoint->value.xCoordinate;
  516. point.y = drawingPoint->value.yCoordinate;
  517. m_points->Add(point);
  518. deltaX += point.x;
  519. deltaY += point.y;
  520. drawingPoint = drawingPoint->next;
  521. }
  522. }
  523. else
  524. {
  525. TRACE_DEBUG(("GetSubsequentPoints got points != pointsDiff16_chosen"));
  526. }
  527. TRACE_DEBUG(("Got %d points", numberOfPoints));
  528. return numberOfPoints;
  529. }
  530. void DrawObj::CreateDrawingCreatePDU(DrawingCreatePDU *pCreatePDU)
  531. {
  532. int nPoints = 1;
  533. pCreatePDU->bit_mask = 0;
  534. //
  535. // Pass the drawing Handle
  536. //
  537. pCreatePDU->bit_mask |=drawingHandle_present;
  538. pCreatePDU->drawingHandle = GetThisObjectHandle();
  539. //
  540. // Pass the destination adress
  541. //
  542. pCreatePDU->destinationAddress.choice = DrawingDestinationAddress_softCopyAnnotationPlane_chosen;
  543. pCreatePDU->destinationAddress.u.softCopyAnnotationPlane.workspaceHandle = GetWorkspaceHandle();
  544. pCreatePDU->destinationAddress.u.softCopyAnnotationPlane.plane = (DataPlaneID)GetPlaneID();
  545. //
  546. // Pass the drawing type
  547. //
  548. pCreatePDU->drawingType.choice = (ASN1choice_t)GetDrawingType();
  549. //
  550. // Pass the attributes
  551. //
  552. SetDrawingAttrib(&pCreatePDU->attributes);
  553. if(pCreatePDU->attributes != NULL)
  554. {
  555. pCreatePDU->bit_mask |=DrawingCreatePDU_attributes_present;
  556. }
  557. //
  558. // Pass the anchor point
  559. //
  560. POINT point;
  561. GetAnchorPoint(&point);
  562. pCreatePDU->anchorPoint.xCoordinate = point.x;
  563. pCreatePDU->anchorPoint.yCoordinate = point.y;
  564. RECT rect;
  565. GetRect(&rect);
  566. pCreatePDU->pointList.choice = pointsDiff16_chosen;
  567. DBG_SAVE_FILE_LINE
  568. pCreatePDU->pointList.u.pointsDiff16 = (PPointList_pointsDiff16)new BYTE[sizeof(PointList_pointsDiff16)];
  569. PPointList_pointsDiff16 drawingPoint = pCreatePDU->pointList.u.pointsDiff16;
  570. PPointList_pointsDiff16 drawingPointLast = NULL;
  571. drawingPoint->next = NULL;
  572. switch(GetDrawingType())
  573. {
  574. case point_chosen:
  575. drawingPoint->value.xCoordinate = 0;
  576. drawingPoint->value.yCoordinate = 0;
  577. drawingPoint->next = NULL;
  578. break;
  579. case openPolyLine_chosen:
  580. case closedPolyLine_chosen:
  581. case rectangle_chosen:
  582. case ellipse_chosen:
  583. {
  584. UINT nPoints = m_points->GetSize();
  585. UINT maxPoints = 1;
  586. POINT * pPoint = m_points->GetBuffer();
  587. while(nPoints && maxPoints < (MAX_POINT_LIST_VALUES + 1))
  588. {
  589. drawingPoint->value.xCoordinate = (SHORT)pPoint->x;
  590. drawingPoint->value.yCoordinate = (SHORT)pPoint->y;
  591. drawingPointLast = drawingPoint;
  592. DBG_SAVE_FILE_LINE
  593. drawingPoint->next = (PPointList_pointsDiff16)new BYTE[sizeof(PointList_pointsDiff16)];
  594. drawingPoint = drawingPoint->next;
  595. nPoints--;
  596. pPoint++;
  597. maxPoints++;
  598. }
  599. if(drawingPointLast)
  600. {
  601. delete drawingPointLast->next;
  602. drawingPointLast->next = NULL;
  603. }
  604. }
  605. break;
  606. }
  607. }
  608. void DrawObj::CreateDrawingEditPDU(DrawingEditPDU *pEditPDU)
  609. {
  610. pEditPDU->bit_mask = (ASN1uint16_t) GetPresentAttribs();
  611. //
  612. // Pass the anchor point
  613. //
  614. POINT point;
  615. GetAnchorPoint(&point);
  616. if(HasAnchorPointChanged())
  617. {
  618. pEditPDU->anchorPointEdit.xCoordinate = point.x;
  619. pEditPDU->anchorPointEdit.yCoordinate = point.y;
  620. }
  621. pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16 = NULL;
  622. //
  623. // Pass point list changes
  624. //
  625. if(HasPointListChanged())
  626. {
  627. UINT nPoints = m_points->GetSize();
  628. POINT * pPoint = m_points->GetBuffer();
  629. pPoint = &pPoint[1];
  630. //
  631. // Just send the last 255 points
  632. //
  633. if(nPoints > 256)
  634. {
  635. pEditPDU->pointListEdits.value[0].initialIndex = nPoints - 256;
  636. nPoints = 256;
  637. }
  638. else
  639. {
  640. pEditPDU->pointListEdits.value[0].initialIndex = 0;
  641. }
  642. //
  643. // Calculate the initial point
  644. //
  645. point.x = 0;
  646. point.y = 0;
  647. for(UINT i = 0; i < pEditPDU->pointListEdits.value[0].initialIndex; i++)
  648. {
  649. point.x += pPoint[i].x;
  650. point.y += pPoint[i].y;
  651. }
  652. pEditPDU->pointListEdits.count = 1;
  653. pEditPDU->pointListEdits.value[0].bit_mask = subsequentPointEdits_present;
  654. pEditPDU->pointListEdits.value[0].subsequentPointEdits.choice = pointsDiff16_chosen;
  655. pEditPDU->pointListEdits.value[0].initialPointEdit.xCoordinate = (SHORT)point.x;
  656. pEditPDU->pointListEdits.value[0].initialPointEdit.yCoordinate = (SHORT)point.y;
  657. TRACE_DEBUG(("Sending List of points starting at Index = %d point(%d,%d)",
  658. pEditPDU->pointListEdits.value[0].initialIndex, point.x, point.y));
  659. pPoint = &pPoint[pEditPDU->pointListEdits.value[0].initialIndex];
  660. DBG_SAVE_FILE_LINE
  661. pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16 = (PPointList_pointsDiff16)new BYTE[sizeof(PointList_pointsDiff16)];
  662. PPointList_pointsDiff16 drawingPointLast = NULL;
  663. PPointList_pointsDiff16 drawingPoint = pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16;
  664. pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16->next = NULL;
  665. pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16->value.xCoordinate = 0;
  666. pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16->value.yCoordinate = 0;
  667. nPoints--;
  668. while(nPoints)
  669. {
  670. drawingPoint->value.xCoordinate = (SHORT)pPoint->x;
  671. drawingPoint->value.yCoordinate = (SHORT)pPoint->y;
  672. drawingPointLast = drawingPoint;
  673. DBG_SAVE_FILE_LINE
  674. drawingPoint->next = (PPointList_pointsDiff16)new BYTE[sizeof(PointList_pointsDiff16)];
  675. drawingPoint = drawingPoint->next;
  676. nPoints--;
  677. pPoint++;
  678. }
  679. if(drawingPointLast)
  680. {
  681. delete drawingPointLast->next;
  682. drawingPointLast->next = NULL;
  683. }
  684. }
  685. //
  686. // JOSEF Pass rotation if we ever do it (FEATURE)
  687. //
  688. //
  689. // Pass all the changed attributes, if any.
  690. //
  691. if(pEditPDU->bit_mask & DrawingEditPDU_attributeEdits_present)
  692. {
  693. SetDrawingAttrib((PDrawingCreatePDU_attributes *)&pEditPDU->attributeEdits);
  694. }
  695. pEditPDU->drawingHandle = GetThisObjectHandle();
  696. }
  697. void DrawObj::CreateDrawingDeletePDU(DrawingDeletePDU *pDeletePDU)
  698. {
  699. pDeletePDU->bit_mask = 0;
  700. pDeletePDU->drawingHandle = GetThisObjectHandle();
  701. }
  702. void DrawObj::AllocateAttrib(PDrawingCreatePDU_attributes *pAttributes)
  703. {
  704. DBG_SAVE_FILE_LINE
  705. PDrawingCreatePDU_attributes pAttrib = (PDrawingCreatePDU_attributes)new BYTE[sizeof(DrawingCreatePDU_attributes)];
  706. if(*pAttributes == NULL)
  707. {
  708. *pAttributes = pAttrib;
  709. pAttrib->next = NULL;
  710. }
  711. else
  712. {
  713. ((PDrawingCreatePDU_attributes)pAttrib)->next = *pAttributes;
  714. *pAttributes = pAttrib;
  715. }
  716. }
  717. void DrawObj::SetDrawingAttrib(PDrawingCreatePDU_attributes *pattributes)
  718. {
  719. PDrawingCreatePDU_attributes attributes = NULL;
  720. RGBTRIPLE color;
  721. //
  722. // Do the pen Color
  723. //
  724. if(HasPenColorChanged())
  725. {
  726. if(GetPenColor(&color))
  727. {
  728. AllocateAttrib(&attributes);
  729. attributes->value.choice = penColor_chosen;
  730. attributes->value.u.penColor.choice = rgbTrueColor_chosen;
  731. attributes->value.u.penColor.u.rgbTrueColor.r = color.rgbtRed;
  732. attributes->value.u.penColor.u.rgbTrueColor.g = color.rgbtGreen;
  733. attributes->value.u.penColor.u.rgbTrueColor.b = color.rgbtBlue;
  734. }
  735. }
  736. //
  737. // Do the fillColor
  738. //
  739. if(HasFillColorChanged())
  740. {
  741. if(GetFillColor(&color))
  742. {
  743. AllocateAttrib(&attributes);
  744. attributes->value.choice = fillColor_chosen;
  745. attributes->value.u.fillColor.choice = rgbTrueColor_chosen;
  746. attributes->value.u.fillColor.u.rgbTrueColor.r = color.rgbtRed;
  747. attributes->value.u.fillColor.u.rgbTrueColor.g = color.rgbtGreen;
  748. attributes->value.u.fillColor.u.rgbTrueColor.b = color.rgbtBlue;
  749. }
  750. }
  751. //
  752. // Do the penThickness
  753. //
  754. if(HasPenThicknessChanged())
  755. {
  756. AllocateAttrib(&attributes);
  757. attributes->value.choice = penThickness_chosen;
  758. attributes->value.u.penThickness = (PenThickness)GetPenThickness();
  759. }
  760. //
  761. // Do the penNib
  762. //
  763. if(HasPenNibChanged())
  764. {
  765. AllocateAttrib(&attributes);
  766. attributes->value.choice = penNib_chosen;
  767. attributes->value.u.penNib.choice = (ASN1choice_t)GetPenNib();
  768. }
  769. //
  770. // Do the lineStyle
  771. //
  772. if(HasLineStyleChanged())
  773. {
  774. AllocateAttrib(&attributes);
  775. attributes->value.choice = lineStyle_chosen;
  776. attributes->value.u.lineStyle.choice = GetLineStyle()+1;
  777. }
  778. //
  779. // Do the Highlight
  780. //
  781. if(HasHighlightChanged())
  782. {
  783. AllocateAttrib(&attributes);
  784. attributes->value.choice = highlight_chosen;
  785. attributes->value.u.highlight = (ASN1bool_t)GetHighlight();
  786. }
  787. //
  788. // Do the viewState
  789. //
  790. if(HasViewStateChanged())
  791. {
  792. AllocateAttrib(&attributes);
  793. attributes->value.choice = DrawingAttribute_viewState_chosen;
  794. attributes->value.u.viewState.choice = (ASN1choice_t)GetViewState();
  795. }
  796. //
  797. // Do the zOrder
  798. //
  799. if(HasZOrderChanged())
  800. {
  801. AllocateAttrib(&attributes);
  802. attributes->value.choice = DrawingAttribute_zOrder_chosen;
  803. attributes->value.u.zOrder = GetZOrder();
  804. }
  805. *pattributes = attributes;
  806. }
  807. //
  808. // CircleHit()
  809. //
  810. // Checks for overlap between circle at PcxPcy with uRadius and
  811. // lpHitRect. If overlap TRUE is returned, otherwise FALSE.
  812. //
  813. BOOL CircleHit( LONG Pcx, LONG Pcy, UINT uRadius, LPCRECT lpHitRect,
  814. BOOL bCheckPt )
  815. {
  816. RECT hr = *lpHitRect;
  817. RECT ellipse;
  818. ellipse.left = Pcx - uRadius;
  819. ellipse.right= Pcx + uRadius;
  820. ellipse.bottom = Pcy + uRadius;
  821. ellipse.top = Pcy - uRadius;
  822. // check the easy thing first (don't use PtInRect)
  823. if( bCheckPt &&(lpHitRect->left >= ellipse.left)&&(ellipse.right >= lpHitRect->right)&&
  824. (lpHitRect->top >= ellipse.top)&&(ellipse.bottom >= lpHitRect->bottom))
  825. {
  826. return( TRUE );
  827. }
  828. //
  829. // The circle is just a boring ellipse
  830. //
  831. return EllipseHit(&ellipse, bCheckPt, uRadius, lpHitRect );
  832. }
  833. //
  834. // EllipseHit()
  835. //
  836. // Checks for overlap between ellipse defined by lpEllipseRect and
  837. // lpHitRect. If overlap TRUE is returned, otherwise FALSE.
  838. //
  839. BOOL EllipseHit(LPCRECT lpEllipseRect, BOOL bBorderHit, UINT uPenWidth,
  840. LPCRECT lpHitRect )
  841. {
  842. RECT hr = *lpHitRect;
  843. RECT er = *lpEllipseRect;
  844. // Some code below assumes l<r and t<b
  845. NormalizeRect(&er);
  846. lpEllipseRect = &er;
  847. // Check easy thing first. If lpEllipseRect is inside lpHitRect
  848. // then we have a hit (no duh...)
  849. if( (hr.left <= lpEllipseRect->left)&&(hr.right >= lpEllipseRect->right)&&
  850. (hr.top <= lpEllipseRect->top)&&(hr.bottom >= lpEllipseRect->bottom) )
  851. return( TRUE );
  852. // Check easy thing first. If lpEllipseRect is disjoint from lpHitRect
  853. // then we have a miss (no duh...)
  854. if( (hr.left > lpEllipseRect->right)||(hr.right < lpEllipseRect->left)||
  855. (hr.top > lpEllipseRect->bottom)||(hr.bottom < lpEllipseRect->top) )
  856. return( FALSE );
  857. // If this is an ellipse....
  858. //
  859. // * * ^
  860. // * | b | Y
  861. // * | a +-------> X
  862. // *-------+--------
  863. // |
  864. //
  865. //
  866. // Look for the ellipse hit. (x/a)^2 + (y/b)^2 = 1
  867. // If it is > 1 than the point is outside the ellipse
  868. // If it is < 1 it is inside
  869. //
  870. LONG a,b,aOuter, bOuter, x, y, xCenter, yCenter;
  871. BOOL bInsideOuter = FALSE;
  872. BOOL bOutsideInner = FALSE;
  873. //
  874. // Calculate a and b
  875. //
  876. a = (lpEllipseRect->right - lpEllipseRect->left)/2;
  877. b = (lpEllipseRect->bottom - lpEllipseRect->top)/2;
  878. //
  879. // Get the center of the ellipse
  880. //
  881. xCenter = lpEllipseRect->left + a;
  882. yCenter = lpEllipseRect->top + b;
  883. //
  884. // a and b generates a inner ellipse
  885. // aOuter and bOuter generates a outer ellipse
  886. //
  887. aOuter = a + uPenWidth/2;
  888. bOuter = b + uPenWidth/2;
  889. a = a - uPenWidth/2;
  890. b = b - uPenWidth/2;
  891. //
  892. // Make our coordinates relative to the center of the ellipse
  893. //
  894. y = abs(hr.bottom - yCenter);
  895. x = abs(hr.right - xCenter);
  896. //
  897. // Be carefull not to divide by 0
  898. //
  899. if((a && b && aOuter && bOuter) == 0)
  900. {
  901. return FALSE;
  902. }
  903. //
  904. // We are using LONG instead of double and we need to have some precision
  905. // that is why we multiply the equation of the ellipse
  906. // ((x/a)^2 + (y/b)^2 = 1) by DECIMAL_PRECISION
  907. // Note that the multiplication has to be done before the division, if we didn't do that
  908. // we will always get 0 or 1 for x/a
  909. //
  910. if(x*x*DECIMAL_PRECISION/(aOuter*aOuter) + y*y*DECIMAL_PRECISION/(bOuter*bOuter) <= DECIMAL_PRECISION)
  911. {
  912. bInsideOuter = TRUE;
  913. }
  914. if(x*x*DECIMAL_PRECISION/(a*a)+ y*y*DECIMAL_PRECISION/(b*b) >= DECIMAL_PRECISION)
  915. {
  916. bOutsideInner = TRUE;
  917. }
  918. //
  919. // If we are checking for border hit,
  920. // we need to be inside the outer ellipse and inside the inner
  921. //
  922. if( bBorderHit )
  923. {
  924. return( bInsideOuter & bOutsideInner );
  925. }
  926. // just need to be inside the outer ellipse
  927. else
  928. {
  929. return( bInsideOuter );
  930. }
  931. }
  932. //
  933. // LineHit()
  934. //
  935. // Checks for overlap (a "hit") between lpHitRect and the line
  936. // P1P2 accounting for line width. If bCheckP1End or bCheckP2End is
  937. // TRUE then a circle of radius 0.5 * uPenWidth is also checked for
  938. // a hit to account for the rounded ends of wide lines.
  939. //
  940. // If a hit is found TRUE is returned, otherwise FALSE.
  941. //
  942. BOOL LineHit( LONG P1x, LONG P1y, LONG P2x, LONG P2y, UINT uPenWidth,
  943. BOOL bCheckP1End, BOOL bCheckP2End,
  944. LPCRECT lpHitRect )
  945. {
  946. LONG uHalfPenWidth = uPenWidth/2;
  947. //
  948. // It is really hard to hit if the width is only 2
  949. //
  950. if(uHalfPenWidth == 1)
  951. {
  952. uHalfPenWidth = 2;
  953. }
  954. LONG a,b,x,y;
  955. x = lpHitRect->left + (lpHitRect->right - lpHitRect->left)/2;
  956. y = lpHitRect->bottom + (lpHitRect->top - lpHitRect->bottom)/2;
  957. //
  958. // This code assume the rectangle is normalized
  959. //
  960. RECT rect;
  961. rect.top = P1y;
  962. rect.left = P1x;
  963. rect.bottom = P2y;
  964. rect.right = P2x;
  965. NormalizeRect(&rect);
  966. if( (P1x == P2x)&&(P1y == P2y) )
  967. {
  968. // just check one end point's circle
  969. return( CircleHit( P1x, P1y, uHalfPenWidth, lpHitRect, TRUE ) );
  970. }
  971. // check rounded end at P1
  972. if( bCheckP1End && CircleHit( P1x, P1y, uHalfPenWidth, lpHitRect, FALSE ) )
  973. return( TRUE );
  974. // check rounded end at P2
  975. if( bCheckP2End && CircleHit( P2x, P2y, uHalfPenWidth, lpHitRect, FALSE ) )
  976. return( TRUE );
  977. //
  978. // The function of a line is Y = a.X + b
  979. //
  980. // a = (Y1-Y2)/(X1 -X2)
  981. // if we found a we get b = y1 -a.X1
  982. //
  983. if(P1x == P2x)
  984. {
  985. a=0;
  986. b = DECIMAL_PRECISION*P1x;
  987. }
  988. else
  989. {
  990. a = (P1y - P2y)*DECIMAL_PRECISION/(P1x - P2x);
  991. b = DECIMAL_PRECISION*P1y - a*P1x;
  992. }
  993. //
  994. // Paralel to Y
  995. //
  996. if(P1x == P2x && ((x >= P1x - uHalfPenWidth) && x <= P1x + uHalfPenWidth))
  997. {
  998. return (P1y <= y && P2y >= y);
  999. }
  1000. //
  1001. // Paralel to X
  1002. //
  1003. if(P1y == P2y && ((y >= P1y - uHalfPenWidth) && y <= P1y + uHalfPenWidth))
  1004. {
  1005. return (P1x <= x && P2x >= x);
  1006. }
  1007. //
  1008. // General line
  1009. //
  1010. return(( y*DECIMAL_PRECISION <= a*x + b + DECIMAL_PRECISION*uHalfPenWidth) &&
  1011. ( y*DECIMAL_PRECISION >= a*x + b - DECIMAL_PRECISION*uHalfPenWidth)&&
  1012. ((rect.top <= y && rect.bottom >= y) && (rect.left <= x && rect.right >= x)));
  1013. }
  1014. //
  1015. // Checks object for an actual overlap with pRectHit. This
  1016. // function assumes that the boundingRect has already been
  1017. // compared with pRectHit.
  1018. //
  1019. BOOL DrawObj::PolyLineHit(LPCRECT pRectHit)
  1020. {
  1021. POINT *lpPoints;
  1022. int iCount;
  1023. int i;
  1024. POINT ptLast;
  1025. UINT uRadius;
  1026. RECT rectHit;
  1027. iCount = m_points->GetSize();
  1028. lpPoints = (POINT *)m_points->GetBuffer();
  1029. if( iCount == 0 )
  1030. return( FALSE );
  1031. // addjust hit rect to lpPoints coord space.
  1032. rectHit = *pRectHit;
  1033. POINT anchorPoint;
  1034. GetAnchorPoint(&anchorPoint);
  1035. if( (iCount > 0)&&(iCount < 2) )
  1036. {
  1037. // only one point, just hit check it
  1038. uRadius = GetPenThickness() >> 1; // m_uiPenWidth/2
  1039. return(CircleHit( anchorPoint.x + lpPoints->x, anchorPoint.y - lpPoints->y, uRadius, &rectHit, TRUE ));
  1040. }
  1041. // look for a hit on each line segment body
  1042. ptLast = anchorPoint;
  1043. for( i=1; i<iCount; i++ )
  1044. {
  1045. RECT rect;
  1046. rect.top = ptLast.y;
  1047. rect.left = ptLast.x;
  1048. rect.bottom = ptLast.y + lpPoints->y;
  1049. rect.right = ptLast.x + lpPoints->x;
  1050. NormalizeRect(&rect);
  1051. if( LineHit(rect.left, rect.top, rect.right, rect.bottom, GetPenThickness(), TRUE, TRUE, &rectHit))
  1052. {
  1053. return( TRUE ); // got a hit
  1054. }
  1055. lpPoints++;
  1056. ptLast.x +=lpPoints->x;
  1057. ptLast.y +=lpPoints->y;
  1058. }
  1059. // now, look for a hit on the line endpoints if m_uiPenWidth > 1
  1060. if( GetPenThickness() > 1 )
  1061. {
  1062. uRadius = GetPenThickness() >> 1; // m_uiPenWidth/2
  1063. lpPoints = (POINT *)m_points->GetBuffer();
  1064. for( i=0; i<iCount; i++, lpPoints++ )
  1065. {
  1066. if( CircleHit( anchorPoint.x + lpPoints->x, anchorPoint.y + lpPoints->y, uRadius, &rectHit, FALSE ))
  1067. {
  1068. return( TRUE ); // got a hit
  1069. }
  1070. }
  1071. }
  1072. return( FALSE ); // no hits
  1073. }
  1074. DrawObj::CheckReallyHit(LPCRECT pRectHit)
  1075. {
  1076. RECT rect;
  1077. switch(GetDrawingType())
  1078. {
  1079. case point_chosen:
  1080. case openPolyLine_chosen:
  1081. {
  1082. UINT nPoints = m_points->GetSize();
  1083. if(nPoints > 2 )
  1084. {
  1085. POINT point;
  1086. RECT rect;
  1087. GetBoundsRect(&rect);
  1088. point.y = pRectHit->top;
  1089. point.x = pRectHit->left;
  1090. return PolyLineHit(pRectHit);
  1091. }
  1092. else
  1093. {
  1094. GetRect(&rect);
  1095. return(LineHit(rect.left, rect.top, rect.right, rect.bottom, GetPenThickness(), TRUE, TRUE, pRectHit));
  1096. }
  1097. }
  1098. break;
  1099. case rectangle_chosen:
  1100. {
  1101. // Draw the rectangle
  1102. return(RectangleHit(!HasFillColor(), pRectHit));
  1103. }
  1104. break;
  1105. case ellipse_chosen:
  1106. {
  1107. GetRect(&rect);
  1108. return( EllipseHit( &rect, !HasFillColor(), GetPenThickness(), pRectHit ));
  1109. }
  1110. break;
  1111. }
  1112. return FALSE;
  1113. }
  1114. void DrawObj::UnDraw(void)
  1115. {
  1116. RECT rect;
  1117. UINT penThickness;
  1118. GetBoundsRect(&rect);
  1119. penThickness = GetPenThickness();
  1120. ::InflateRect(&rect, penThickness, penThickness);
  1121. g_pDraw->InvalidateSurfaceRect(&rect,TRUE);
  1122. BitmapObj* remotePointer = NULL;
  1123. WBPOSITION pos = NULL;
  1124. remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect, penThickness, NULL);
  1125. while(remotePointer)
  1126. {
  1127. remotePointer->DeleteSavedBitmap();
  1128. remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect, penThickness, remotePointer->GetMyPosition());
  1129. }
  1130. }
  1131. void DrawObj::Draw(HDC hDC, BOOL bForcedDraw, BOOL bPrinting)
  1132. {
  1133. if(!bPrinting)
  1134. {
  1135. //
  1136. // Don't draw anything if we don't belong in this workspace
  1137. //
  1138. if(!(GraphicTool() == TOOLTYPE_SELECT || GraphicTool() == TOOLTYPE_ERASER) && GetWorkspaceHandle() != g_pCurrentWorkspace->GetThisObjectHandle())
  1139. {
  1140. return;
  1141. }
  1142. }
  1143. HPEN hPen = NULL;
  1144. HPEN hOldPen = NULL;
  1145. HBRUSH hBrush = NULL;
  1146. HBRUSH hOldBrush = NULL;
  1147. BOOL bHasPenColor;
  1148. BOOL bHasFillColor;
  1149. BitmapObj* remotePointer = NULL;
  1150. COLORREF color;
  1151. COLORREF fillColor;
  1152. RECT boundsRect;
  1153. RECT rect;
  1154. UINT penThickness = GetPenThickness();
  1155. if(hDC == NULL)
  1156. {
  1157. hDC = g_pDraw->m_hDCCached;
  1158. }
  1159. MLZ_EntryOut(ZONE_FUNCTION, "DrawObj::Draw");
  1160. // Select the required pen and fill color
  1161. bHasPenColor = GetPenColor(&color);
  1162. bHasFillColor = GetFillColor(&fillColor);
  1163. if(bHasFillColor)
  1164. {
  1165. hBrush = ::CreateSolidBrush(SET_PALETTERGB(fillColor));
  1166. hOldBrush = SelectBrush(hDC, hBrush);
  1167. }
  1168. else
  1169. {
  1170. hOldBrush = SelectBrush(hDC, ::GetStockObject(NULL_BRUSH));
  1171. }
  1172. //
  1173. // Get rect
  1174. //
  1175. GetBoundsRect(&boundsRect);
  1176. GetRect(&rect);
  1177. hPen = ::CreatePen(GetLineStyle(), penThickness, SET_PALETTERGB(color));
  1178. hOldPen = SelectPen(hDC, hPen);
  1179. if (hOldPen != NULL)
  1180. {
  1181. // Select the raster operation
  1182. int iOldROP = ::SetROP2(hDC, GetROP());
  1183. switch(GetDrawingType())
  1184. {
  1185. case point_chosen:
  1186. case openPolyLine_chosen:
  1187. {
  1188. UINT nPoints = m_points->GetSize();
  1189. //
  1190. // This is a redraw of a pen or highlight
  1191. // We have to draw all the segments
  1192. //
  1193. if( (bForcedDraw || GetIsCompleted()) && nPoints > 1)
  1194. {
  1195. POINT anchorPoint;
  1196. GetAnchorPoint(&anchorPoint);
  1197. AddPointToBounds(anchorPoint.x, anchorPoint.y);
  1198. //
  1199. // Go to the beggining
  1200. //
  1201. ::MoveToEx(hDC, anchorPoint.x, anchorPoint.y, NULL);
  1202. //
  1203. // Get the list of points
  1204. //
  1205. POINT *point = m_points->GetBuffer();
  1206. while(nPoints)
  1207. {
  1208. anchorPoint.x += point->x;
  1209. anchorPoint.y += point->y;
  1210. ::LineTo(hDC, anchorPoint.x, anchorPoint.y);
  1211. ::MoveToEx(hDC, anchorPoint.x, anchorPoint.y, NULL);
  1212. point++;
  1213. nPoints--;
  1214. RECT rect;
  1215. MAKE_HIT_RECT(rect, anchorPoint);
  1216. if(remotePointer)
  1217. {
  1218. remotePointer->Draw();
  1219. remotePointer = NULL;
  1220. }
  1221. AddPointToBounds(anchorPoint.x, anchorPoint.y);
  1222. ::InflateRect(&rect, GetPenThickness()/2, GetPenThickness()/2);
  1223. remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect, GetPenThickness()/2, NULL);
  1224. }
  1225. }
  1226. else
  1227. {
  1228. // Draw the line
  1229. ::MoveToEx(hDC, rect.left, rect.top, NULL);
  1230. ::LineTo(hDC, rect.right, rect.bottom);
  1231. }
  1232. }
  1233. break;
  1234. case rectangle_chosen:
  1235. {
  1236. TRACE_DEBUG(("RECTANGLE %d, %d, %d , %d", rect.left, rect.top, rect.right, rect.bottom ));
  1237. // Draw the rectangle
  1238. ::Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom);
  1239. }
  1240. break;
  1241. case ellipse_chosen:
  1242. {
  1243. ::Ellipse(hDC, rect.left, rect.top, rect.right, rect.bottom);
  1244. }
  1245. break;
  1246. case closedPolyLine_chosen:
  1247. default:
  1248. TRACE_DEBUG(("Unsupported DrawingType", GetDrawingType()));
  1249. break;
  1250. }
  1251. //
  1252. // De-select the brush
  1253. //
  1254. SelectBrush(hDC, hOldBrush);
  1255. // De-select the pen and ROP
  1256. ::SetROP2(hDC, iOldROP);
  1257. SelectPen(hDC, hOldPen);
  1258. }
  1259. //
  1260. // Do NOT draw focus if clipboard or printing
  1261. //
  1262. if (WasSelectedLocally() && (hDC == g_pDraw->m_hDCCached))
  1263. {
  1264. DrawRect();
  1265. }
  1266. if (hPen != NULL)
  1267. {
  1268. ::DeletePen(hPen);
  1269. }
  1270. if (hBrush != NULL)
  1271. {
  1272. ::DeleteBrush(hBrush);
  1273. }
  1274. if(remotePointer)
  1275. {
  1276. remotePointer->Draw();
  1277. }
  1278. //
  1279. // Now for rectangles ellipses and lines, check if we are on top of any remote pointer
  1280. //
  1281. remotePointer = NULL;
  1282. WBPOSITION pos = NULL;
  1283. ::InflateRect(&rect, GetPenThickness()/2, GetPenThickness()/2);
  1284. remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect, GetPenThickness()/2, NULL);
  1285. while(remotePointer)
  1286. {
  1287. remotePointer->DeleteSavedBitmap();
  1288. remotePointer->Draw();
  1289. remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect, GetPenThickness()/2, remotePointer->GetMyPosition());
  1290. }
  1291. }
  1292. void DrawObj::SetPenColor(COLORREF rgb, BOOL isPresent)
  1293. {
  1294. ChangedPenColor();
  1295. m_bIsPenColorPresent = isPresent;
  1296. if(!isPresent)
  1297. {
  1298. return;
  1299. }
  1300. m_penColor.rgbtRed = GetRValue(rgb);
  1301. m_penColor.rgbtGreen = GetGValue(rgb);
  1302. m_penColor.rgbtBlue = GetBValue(rgb);
  1303. }
  1304. BOOL DrawObj::GetPenColor(COLORREF * rgb)
  1305. {
  1306. if(m_bIsPenColorPresent)
  1307. {
  1308. *rgb = RGB(m_penColor.rgbtRed, m_penColor.rgbtGreen, m_penColor.rgbtBlue);
  1309. }
  1310. return m_bIsPenColorPresent;
  1311. }
  1312. BOOL DrawObj::GetPenColor(RGBTRIPLE* rgb)
  1313. {
  1314. if(m_bIsPenColorPresent)
  1315. {
  1316. *rgb = m_penColor;
  1317. }
  1318. return m_bIsPenColorPresent;
  1319. }
  1320. void DrawObj::SetFillColor(COLORREF rgb, BOOL isPresent)
  1321. {
  1322. ChangedFillColor();
  1323. m_bIsFillColorPresent = isPresent;
  1324. if(!isPresent)
  1325. {
  1326. return;
  1327. }
  1328. m_fillColor.rgbtRed = GetRValue(rgb);
  1329. m_fillColor.rgbtGreen = GetGValue(rgb);
  1330. m_fillColor.rgbtBlue = GetBValue(rgb);
  1331. }
  1332. BOOL DrawObj::GetFillColor(COLORREF* rgb)
  1333. {
  1334. if(m_bIsFillColorPresent && rgb !=NULL)
  1335. {
  1336. *rgb = RGB(m_fillColor.rgbtRed, m_fillColor.rgbtGreen, m_fillColor.rgbtBlue);
  1337. }
  1338. return m_bIsFillColorPresent;
  1339. }
  1340. BOOL DrawObj::GetFillColor(RGBTRIPLE* rgb)
  1341. {
  1342. if(m_bIsFillColorPresent && rgb!= NULL)
  1343. {
  1344. *rgb = m_fillColor;
  1345. }
  1346. return m_bIsFillColorPresent;
  1347. }
  1348. BOOL DrawObj::AddPoint(POINT point)
  1349. {
  1350. BOOL bSuccess = TRUE;
  1351. MLZ_EntryOut(ZONE_FUNCTION, "DrawObj::::AddPoint");
  1352. int nPoints = m_points->GetSize();
  1353. // if we've reached the maximum number of points then quit with failure
  1354. if (nPoints >= MAX_FREEHAND_POINTS)
  1355. {
  1356. bSuccess = FALSE;
  1357. TRACE_DEBUG(("Maximum number of points for freehand object reached."));
  1358. return(bSuccess);
  1359. }
  1360. m_points->Add(point);
  1361. nPoints++;
  1362. ChangedPointList();
  1363. //
  1364. // If we hit the 256 limit fake a timer notification and resend the polyline
  1365. //
  1366. if((nPoints & 0xff) == 0)
  1367. {
  1368. g_pDraw->OnTimer(0);
  1369. }
  1370. return(bSuccess);
  1371. }
  1372. void DrawObj::AddPointToBounds(int x, int y)
  1373. {
  1374. // Create a rectangle containing the point just added (expanded
  1375. // by the width of the pen being used).
  1376. RECT rect;
  1377. RECT boundsRect;
  1378. rect.left = x - 1;
  1379. rect.top = y - 1;
  1380. rect.right = x + 1;
  1381. rect.bottom = y + 1;
  1382. GetBoundsRect(&boundsRect);
  1383. ::UnionRect(&boundsRect, &boundsRect, &rect);
  1384. SetBoundsRect(&boundsRect);
  1385. }
  1386. void GetDrawingDestinationAddress(DrawingDestinationAddress *destinationAddress, PUINT workspaceHandle, PUINT planeID)
  1387. {
  1388. //
  1389. // Get the destination address
  1390. //
  1391. switch(destinationAddress->choice)
  1392. {
  1393. case(DrawingDestinationAddress_softCopyAnnotationPlane_chosen):
  1394. {
  1395. *workspaceHandle = (destinationAddress->u.softCopyAnnotationPlane.workspaceHandle);
  1396. *planeID = (destinationAddress->u.softCopyAnnotationPlane.plane);
  1397. break;
  1398. }
  1399. // case(DrawingDestinationAddress_nonStandardDestination_chosen):
  1400. // {
  1401. // break;
  1402. // }
  1403. default:
  1404. ERROR_OUT(("Invalid destinationAddress"));
  1405. break;
  1406. }
  1407. }
  1408. void DrawObj::SetUIToolType(void)
  1409. {
  1410. UINT drawingType = GetDrawingType();
  1411. BOOL filled = HasFillColor();
  1412. UINT rop = R2_COPYPEN;
  1413. switch (drawingType)
  1414. {
  1415. case openPolyLine_chosen:
  1416. {
  1417. if(m_points->GetSize() > 1)
  1418. {
  1419. if(GetHighlight())
  1420. {
  1421. m_ToolType = TOOLTYPE_HIGHLIGHT;
  1422. rop = R2_MASKPEN;
  1423. }
  1424. else
  1425. {
  1426. m_ToolType = TOOLTYPE_PEN;
  1427. }
  1428. }
  1429. else
  1430. {
  1431. m_ToolType = TOOLTYPE_LINE;
  1432. }
  1433. }
  1434. break;
  1435. case rectangle_chosen:
  1436. {
  1437. if(filled)
  1438. {
  1439. m_ToolType = TOOLTYPE_FILLEDBOX;
  1440. }
  1441. else
  1442. {
  1443. m_ToolType = TOOLTYPE_BOX;
  1444. }
  1445. }
  1446. break;
  1447. case ellipse_chosen:
  1448. {
  1449. if(filled)
  1450. {
  1451. m_ToolType = TOOLTYPE_FILLEDELLIPSE;
  1452. }
  1453. else
  1454. {
  1455. m_ToolType = TOOLTYPE_ELLIPSE;
  1456. }
  1457. }
  1458. break;
  1459. }
  1460. SetROP(rop);
  1461. }
  1462. //
  1463. // UI Edited the Drawing Object
  1464. //
  1465. void DrawObj::OnObjectEdit(void)
  1466. {
  1467. g_bContentsChanged = TRUE;
  1468. SIPDU *sipdu = NULL;
  1469. DBG_SAVE_FILE_LINE
  1470. sipdu = (SIPDU *) new BYTE[sizeof(SIPDU)];
  1471. if(sipdu)
  1472. {
  1473. sipdu->choice = drawingEditPDU_chosen;
  1474. CreateDrawingEditPDU(&sipdu->u.drawingEditPDU);
  1475. TRACE_DEBUG(("Sending Drawing Edit >> Drawing handle = %d", sipdu->u.drawingEditPDU.drawingHandle ));
  1476. T120Error rc = SendT126PDU(sipdu);
  1477. if(rc == T120_NO_ERROR)
  1478. {
  1479. SIPDUCleanUp(sipdu);
  1480. ResetAttrib();
  1481. }
  1482. }
  1483. else
  1484. {
  1485. TRACE_MSG(("Failed to create sipdu"));
  1486. ::PostMessage(g_pMain->m_hwnd, WM_USER_DISPLAY_ERROR, WBFE_RC_WINDOWS, 0);
  1487. }
  1488. }
  1489. //
  1490. // UI Deleted the Drawing Object
  1491. //
  1492. void DrawObj::OnObjectDelete(void)
  1493. {
  1494. SIPDU *sipdu = NULL;
  1495. DBG_SAVE_FILE_LINE
  1496. sipdu = (SIPDU *) new BYTE[sizeof(SIPDU)];
  1497. if(sipdu)
  1498. {
  1499. sipdu->choice = drawingDeletePDU_chosen;
  1500. CreateDrawingDeletePDU(&sipdu->u.drawingDeletePDU);
  1501. T120Error rc = SendT126PDU(sipdu);
  1502. if(rc == T120_NO_ERROR)
  1503. {
  1504. SIPDUCleanUp(sipdu);
  1505. }
  1506. }
  1507. else
  1508. {
  1509. TRACE_MSG(("Failed to create sipdu"));
  1510. ::PostMessage(g_pMain->m_hwnd, WM_USER_DISPLAY_ERROR, WBFE_RC_WINDOWS, 0);
  1511. }
  1512. }
  1513. //
  1514. // Get the encoded buffer for Drawing Create PDU
  1515. //
  1516. void DrawObj::GetEncodedCreatePDU(ASN1_BUF *pBuf)
  1517. {
  1518. SIPDU *sipdu = NULL;
  1519. DBG_SAVE_FILE_LINE
  1520. sipdu = (SIPDU *) new BYTE[sizeof(SIPDU)];
  1521. if(sipdu)
  1522. {
  1523. sipdu->choice = drawingCreatePDU_chosen;
  1524. CreateDrawingCreatePDU(&sipdu->u.drawingCreatePDU);
  1525. ASN1_BUF encodedPDU;
  1526. g_pCoder->Encode(sipdu, pBuf);
  1527. SIPDUCleanUp(sipdu);
  1528. }
  1529. else
  1530. {
  1531. TRACE_MSG(("Failed to create penMenu"));
  1532. ::PostMessage(g_pMain->m_hwnd, WM_USER_DISPLAY_ERROR, WBFE_RC_WINDOWS, 0);
  1533. }
  1534. }
  1535. //
  1536. // UI Created a new Drawing Object
  1537. //
  1538. void DrawObj::SendNewObjectToT126Apps(void)
  1539. {
  1540. SIPDU *sipdu = NULL;
  1541. DBG_SAVE_FILE_LINE
  1542. sipdu = (SIPDU *) new BYTE[sizeof(SIPDU)];
  1543. if(sipdu)
  1544. {
  1545. sipdu->choice = drawingCreatePDU_chosen;
  1546. CreateDrawingCreatePDU(&sipdu->u.drawingCreatePDU);
  1547. TRACE_DEBUG(("Sending Drawing >> Drawing handle = %d", sipdu->u.drawingCreatePDU.drawingHandle ));
  1548. T120Error rc = SendT126PDU(sipdu);
  1549. if(rc == T120_NO_ERROR)
  1550. {
  1551. SIPDUCleanUp(sipdu);
  1552. }
  1553. }
  1554. else
  1555. {
  1556. TRACE_MSG(("Failed to create sipdu"));
  1557. ::PostMessage(g_pMain->m_hwnd, WM_USER_DISPLAY_ERROR, WBFE_RC_WINDOWS, 0);
  1558. }
  1559. }