Leaked source code of windows server 2003
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.

388 lines
16 KiB

  1. /******************************************************************************/
  2. /* T_CURVE.CPP: IMPLEMENTATION OF THE CCurveTool CLASS */
  3. /* */
  4. /* */
  5. /******************************************************************************/
  6. /* */
  7. /* Methods in this file */
  8. /* */
  9. /* CCurve Tool Class Object */
  10. /* CCurveTool::CCurveTool */
  11. /* CCurveTool::~CCurveTool */
  12. /* CCurveTool::AdjustBoundingRect */
  13. /* CCurveTool::AddPoint */
  14. /* CCurveTool::SetCurrentPoint */
  15. /* CCurveTool::DrawCurve */
  16. /* CCurveTool::AdjustPointsForConstraint */
  17. /* CCurveTool::PreProcessPoints */
  18. /* CCurveTool::Render */
  19. /* CCurveTool::OnStartDrag */
  20. /* CCurveTool::OnEndDrag */
  21. /* CCurveTool::OnDrag */
  22. /* CCurveTool::OnCancel */
  23. /* CCurveTool::CanEndMultiptOperation */
  24. /* CCurveTool::EndMultiptOperation */
  25. /******************************************************************************/
  26. /* */
  27. /* Briefly, this Object draws a curve from 4 (currently) points. It generates */
  28. /* a list of points which are placed in the array, and then calls polyline */
  29. /* to draw line segments to build a curve. */
  30. /* */
  31. /* The array is divided into 2 pieces. The first piece is the anchor points, */
  32. /* the 2nd piece is the array of points which will be passed to polyline. */
  33. /* The anchor points are placed in the array in the following order */
  34. /* 2,3,4,...1. See the addpoint method below for info on this order. */
  35. /* */
  36. /******************************************************************************/
  37. #include "stdafx.h"
  38. #include "global.h"
  39. #include "pbrush.h"
  40. #include "pbrusdoc.h"
  41. #include "pbrusfrm.h"
  42. #include "bmobject.h"
  43. #include "imgsuprt.h"
  44. #include "imgwnd.h"
  45. #include "imgwell.h"
  46. #include "pbrusvw.h"
  47. #include "t_curve.h"
  48. #ifdef _DEBUG
  49. #undef THIS_FILE
  50. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  51. #endif
  52. IMPLEMENT_DYNAMIC(CCurveTool, CRubberTool)
  53. #include "memtrace.h"
  54. extern CLineTool NEAR g_lineTool;
  55. CCurveTool NEAR g_curveTool;
  56. /******************************************************************************/
  57. CCurveTool::CCurveTool()
  58. {
  59. m_nCmdID = IDMB_CURVETOOL;
  60. m_iNumAnchorPoints = 0;
  61. m_cRectBounding.SetRectEmpty();
  62. }
  63. /******************************************************************************/
  64. CCurveTool::~CCurveTool()
  65. {
  66. m_cRectBounding.SetRectEmpty();
  67. }
  68. /******************************************************************************/
  69. /* recalculate the bounding rectangle for the polyline/curve */
  70. void CCurveTool::AdjustBoundingRect(void)
  71. {
  72. int iStrokeWidth = GetStrokeWidth();
  73. int i;
  74. if (m_iNumAnchorPoints >= 1)
  75. {
  76. //set the rect to equal the 1st value
  77. m_cRectBounding.SetRect(m_PolyPoints[0].x, m_PolyPoints[0].y,
  78. m_PolyPoints[0].x, m_PolyPoints[0].y);
  79. }
  80. for (i=1; i < m_iNumAnchorPoints; i++)
  81. {
  82. m_cRectBounding.SetRect( min(m_PolyPoints[i].x, m_cRectBounding.left),
  83. min(m_PolyPoints[i].y, m_cRectBounding.top),
  84. max(m_PolyPoints[i].x, m_cRectBounding.right),
  85. max(m_PolyPoints[i].y, m_cRectBounding.bottom));
  86. }
  87. // Adjust rectangle for Windows GDI (Non-inclusive right/bottom)
  88. m_cRectBounding.bottom++; m_cRectBounding.right++;
  89. // Adjust for width of current drawing line/border
  90. m_cRectBounding.OffsetRect(-(iStrokeWidth/2),-(iStrokeWidth/2));
  91. m_cRectBounding.InflateRect(iStrokeWidth, iStrokeWidth);
  92. }
  93. /******************************************************************************/
  94. // This method adds a new point into the array and increases the number of
  95. // anchor points currently in the array. If there are no points in the
  96. // array, it adds a point to the 1st position (index 0). If there are any
  97. // points currently in the array, it copies the last point to the new
  98. // location, and then adds the new point where the old last point was (1 point
  99. // before the last point. The 1st point added is always the last point in the
  100. // array, and the 2nd point added is always the 1st point.
  101. // The order of the points in the array are: 2,3,4,....,1
  102. void CCurveTool::AddPoint(POINT ptNewPoint)
  103. {
  104. BOOL bRC = TRUE;
  105. if (m_iNumAnchorPoints == 0)
  106. {
  107. m_PolyPoints[m_iNumAnchorPoints] = ptNewPoint;
  108. m_iNumAnchorPoints++;
  109. }
  110. else
  111. {
  112. if (m_iNumAnchorPoints < MAX_ANCHOR_POINTS)
  113. {
  114. m_PolyPoints[m_iNumAnchorPoints] = m_PolyPoints[m_iNumAnchorPoints-1];
  115. m_PolyPoints[m_iNumAnchorPoints-1] = ptNewPoint;
  116. m_iNumAnchorPoints++;
  117. }
  118. }
  119. AdjustBoundingRect();
  120. }
  121. /******************************************************************************/
  122. // This method changes the value of the last point in the array. If there are
  123. // 2 points, then it modifies the 2nd point, knowing that when there are only
  124. // 2 points, we are draing a straight line (between 2 points). If there are
  125. // more than 2 points, it modified the second to last point in the array,
  126. // which is actually the last point dropped/placed. See above for expl of
  127. // order of points in the array.
  128. void CCurveTool::SetCurrentPoint(POINT ptNewPoint)
  129. {
  130. if (m_iNumAnchorPoints == 2)
  131. {
  132. m_PolyPoints[m_iNumAnchorPoints-1] = ptNewPoint;
  133. }
  134. else
  135. {
  136. if (m_iNumAnchorPoints > 2)
  137. {
  138. m_PolyPoints[m_iNumAnchorPoints-2] = ptNewPoint;
  139. }
  140. }
  141. AdjustBoundingRect();
  142. }
  143. /******************************************************************************/
  144. BOOL CCurveTool::DrawCurve(CDC* pDC)
  145. {
  146. POINT ptCurve[MAX_ANCHOR_POINTS];
  147. UINT uPoints = m_iNumAnchorPoints;
  148. int i;
  149. for (i=uPoints-1; i>=0; --i)
  150. {
  151. ptCurve[i] = m_PolyPoints[i];
  152. }
  153. // HACK: PolyBezier cannot handle 3 points, so repeat the middle point
  154. if (uPoints == 3)
  155. {
  156. ptCurve[3] = ptCurve[2];
  157. ptCurve[2] = ptCurve[1];
  158. uPoints = 4;
  159. }
  160. PolyBezier(pDC->m_hDC, ptCurve, uPoints);
  161. return(TRUE);
  162. }
  163. /******************************************************************************/
  164. /* Call the line's adjustpointsforconstraint member function */
  165. /* only do this if there are 2 points (i.e. drawing a straight line */
  166. void CCurveTool::AdjustPointsForConstraint(MTI *pmti)
  167. {
  168. if (m_iNumAnchorPoints == 2)
  169. {
  170. g_lineTool.AdjustPointsForConstraint(pmti);
  171. }
  172. }
  173. /******************************************************************************/
  174. // ptDown must be anchor point for our line, not where we did mouse button down
  175. // on a subsequent point in the multipt operation
  176. void CCurveTool::PreProcessPoints(MTI *pmti)
  177. {
  178. pmti->ptDown = m_PolyPoints[0];
  179. CRubberTool::PreProcessPoints(pmti);
  180. }
  181. /******************************************************************************/
  182. /* Render sets up the pen and brush, and then calls either Render */
  183. /* The pen and brush is set up exactly the same as the parent routine in */
  184. /* CRubberTool. If there are only 2 points, do the standard line drawing */
  185. /* using moveto and lineto, instead of trying to create a curve between 2 pts */
  186. void CCurveTool::Render(CDC* pDC, CRect& rect, BOOL bDraw, BOOL bCommit, BOOL bCtrlDown)
  187. {
  188. // Setup Pen/Brush
  189. SetupPenBrush( pDC->m_hDC, bDraw, TRUE, bCtrlDown );
  190. if (m_iNumAnchorPoints == 2)
  191. {
  192. pDC->MoveTo( m_PolyPoints[0].x, m_PolyPoints[0].y );
  193. pDC->LineTo( m_PolyPoints[1].x, m_PolyPoints[1].y );
  194. }
  195. else
  196. {
  197. if (m_iNumAnchorPoints > 2)
  198. {
  199. DrawCurve( pDC );
  200. }
  201. }
  202. // Cleanup Pen/Brush
  203. SetupPenBrush( pDC->m_hDC, bDraw, FALSE, bCtrlDown );
  204. // Need to return the bounding rect
  205. rect = m_cRectBounding;
  206. }
  207. void CCurveTool::OnActivate( BOOL bActivate )
  208. {
  209. if (!bActivate && m_bMultPtOpInProgress)
  210. {
  211. CImgWnd* pImgWnd = ((CPBView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView())->m_pImgWnd;
  212. // Stolen from CPBView::OnEscape
  213. // I don't think this can ever be NULL, but just in case
  214. if (pImgWnd != NULL)
  215. {
  216. EndMultiptOperation( FALSE ); // end the multipt operation
  217. Render(CDC::FromHandle(pImgWnd->m_pImg->hDC), m_cRectBounding, TRUE, TRUE, FALSE);
  218. InvalImgRect(pImgWnd->m_pImg, &m_cRectBounding);
  219. CommitImgRect(pImgWnd->m_pImg, &m_cRectBounding);
  220. pImgWnd->FinishUndo(m_cRectBounding);
  221. ClearStatusBarSize();
  222. }
  223. }
  224. CRubberTool::OnActivate( bActivate );
  225. }
  226. /******************************************************************************/
  227. /* On Start Drag is called on mouse button down. We basically call on Start */
  228. /* Drag of the parent (default) class after adding in our point(s) into the */
  229. /* array of points. If this is the first point (i.e. bMultiptOpInProgress == */
  230. /* False, then we need 2 points in our array, and we can call the default */
  231. /* OnStartDrag. If it is not the first point, then we just add the new point */
  232. /* and call our OnDrag. In either case, OnDrag is called which eventually */
  233. /* calls render to do our drawing on the mouse down */
  234. /* We only call the parent OnStartDrag the first time, because it does some */
  235. /* setup which we do not want done each time */
  236. void CCurveTool::OnStartDrag( CImgWnd* pImgWnd, MTI* pmti )
  237. {
  238. if (m_bMultPtOpInProgress)
  239. {
  240. AddPoint(pmti->pt);
  241. OnDrag(pImgWnd, pmti);
  242. }
  243. else
  244. {
  245. // must reset numAnchorPoints before calling addpoint the 1st time.
  246. m_iNumAnchorPoints = 0;
  247. AddPoint(pmti->pt);
  248. m_bMultPtOpInProgress = TRUE;
  249. // No Mult Pt In Progress => 1st Click
  250. //
  251. // add a 2nd point, last point is what we are draing to
  252. // 1st point is anchor. 1st time, need 2 points to draw a line
  253. // subsequent times, just add 1 point in array of points.
  254. AddPoint(pmti->pt);
  255. CRubberTool::OnStartDrag(pImgWnd, pmti);
  256. }
  257. }
  258. /******************************************************************************/
  259. /* On End Drag is sent on a mouse button up. This basically is a clone of the*/
  260. /* CRubberTool::OnEndDrag method, except that we use our bounding rect for all*/
  261. /* the image invalidation, and commit, and undo function calls. */
  262. /* if we are in the middle of a multipoint operation, we do not want to call */
  263. /* all the routines to fix the drawing (e.g. invalImgRect, CommitImgRect, */
  264. /* FinishUndo). We just want to save the current point, render, and return */
  265. void CCurveTool::OnEndDrag( CImgWnd* pImgWnd, MTI* pmti )
  266. {
  267. PreProcessPoints(pmti);
  268. SetCurrentPoint(pmti->pt);
  269. if (m_bMultPtOpInProgress)
  270. {
  271. // can't call OnDrag for this object/class, since it calls preprocesspt
  272. // again, and then onDrag. If you call preproces again, you will lose
  273. // bounding rectange box prev, and not be able to invalidate / repaint
  274. // Still have to invalidate bounding rect, since if rect is larger than
  275. // current rect, must invalidate to paint. E.g. If let off shift, then
  276. // let off button, end point would be adjusted and bouning rect would
  277. // also be correct, but rect calculated in CRubberTool::OnDrag is
  278. // incorrect.
  279. InvalImgRect(pImgWnd->m_pImg, &m_cRectBounding);
  280. CRubberTool::OnDrag(pImgWnd, pmti);
  281. }
  282. else
  283. {
  284. OnDrag(pImgWnd, pmti); // one last time to refresh display in prep for final render
  285. Render(CDC::FromHandle(pImgWnd->m_pImg->hDC), m_cRectBounding, pmti->fLeft, TRUE, pmti->fCtrlDown);
  286. InvalImgRect(pImgWnd->m_pImg, &m_cRectBounding);
  287. CommitImgRect(pImgWnd->m_pImg, &m_cRectBounding);
  288. pImgWnd->FinishUndo(m_cRectBounding);
  289. ClearStatusBarSize();
  290. CImgTool::OnEndDrag(pImgWnd, pmti);
  291. }
  292. }
  293. /******************************************************************************/
  294. /* On Drag is sent when the mouse is moved with the button down. We basically*/
  295. /* save the current point, and call the base class processing. Since the base*/
  296. /* class processing invalidates the rect on the screen and cleans it up so we */
  297. /* can paint a new line, we have to adjust the previous rectangle to be the */
  298. /* bounding rectangle of our polyline. If we did not do this, our previous */
  299. /* drawing would not get erased, and we would be drawing our new line over */
  300. /* part of the previous line. The default processing finally calls Render */
  301. /* which since our render is virtual, will call our render method above. */
  302. void CCurveTool::OnDrag( CImgWnd* pImgWnd, MTI* pmti )
  303. {
  304. PreProcessPoints(pmti);
  305. SetCurrentPoint(pmti->pt);
  306. CRubberTool::OnDrag(pImgWnd, pmti);
  307. }
  308. /******************************************************************************/
  309. /* On Cancel is sent when the user aborts an operation while in progress */
  310. /* EndMultiptOperation with TRUE will do all our cleanup */
  311. void CCurveTool::OnCancel(CImgWnd* pImgWnd)
  312. {
  313. EndMultiptOperation(TRUE);
  314. CImgTool::OnCancel(pImgWnd);
  315. }
  316. /******************************************************************************/
  317. /* we can only end if the number of maximum points was entered. We must stay */
  318. /* in capture/multiptmode until we get EXACTLY the desired number of anchor */
  319. /* points */
  320. BOOL CCurveTool::CanEndMultiptOperation(MTI* pmti )
  321. {
  322. if (m_iNumAnchorPoints == MAX_ANCHOR_POINTS)
  323. {
  324. m_bMultPtOpInProgress = FALSE;
  325. }
  326. else
  327. {
  328. m_bMultPtOpInProgress = TRUE;
  329. }
  330. return (CRubberTool::CanEndMultiptOperation(pmti));
  331. }
  332. /******************************************************************************/
  333. /* If bAbort is true, this means an error occurred, or the user cancelled the */
  334. /* multipoint operation in the middle of it. We just set the num of anchor */
  335. /* points to 0 to stop drawing and call the default endmultiptoperation */
  336. void CCurveTool::EndMultiptOperation(BOOL bAbort)
  337. {
  338. if (bAbort)
  339. {
  340. m_iNumAnchorPoints = 0;
  341. m_cRectBounding.SetRectEmpty();
  342. }
  343. CRubberTool::EndMultiptOperation();
  344. }