GraphicsPath.jvm.cs 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. //
  2. // System.Drawing.Drawing2D.GraphicsPath.cs
  3. //
  4. // Author:
  5. // Konstantin Triger <[email protected]>
  6. // Bors Kirzner <[email protected]>
  7. //
  8. // Copyright (C) 2005 Mainsoft Corporation, (http://www.mainsoft.com)
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System;
  30. using System.Drawing;
  31. using System.Collections;
  32. using java.awt.geom;
  33. using java.awt;
  34. namespace System.Drawing.Drawing2D
  35. {
  36. public sealed class GraphicsPath : BasicShape, ICloneable
  37. {
  38. internal enum JPI {
  39. SEG_MOVETO = ExtendedGeneralPath.SEG_MOVETO,
  40. SEG_LINETO = ExtendedGeneralPath.SEG_LINETO,
  41. SEG_QUADTO = ExtendedGeneralPath.SEG_QUADTO,
  42. SEG_CUBICTO = ExtendedGeneralPath.SEG_CUBICTO,
  43. SEG_CLOSE = ExtendedGeneralPath.SEG_CLOSE
  44. }
  45. #region Internal
  46. internal ExtendedGeneralPath NativeObject
  47. {
  48. get
  49. {
  50. return (ExtendedGeneralPath)Shape;
  51. }
  52. }
  53. GraphicsPath (ExtendedGeneralPath ptr) : base(ptr)
  54. {
  55. }
  56. #endregion
  57. #region C-tors.
  58. public GraphicsPath ():
  59. this(FillMode.Alternate)
  60. {
  61. }
  62. public GraphicsPath (FillMode fillMode) : this(new ExtendedGeneralPath ())
  63. {
  64. FillMode = fillMode;
  65. }
  66. public GraphicsPath (Point[] pts, byte[] types) : this(pts, types, FillMode.Alternate)
  67. {
  68. }
  69. public GraphicsPath (PointF [] pts, byte [] types) : this(pts, types, FillMode.Alternate)
  70. {
  71. }
  72. public GraphicsPath (Point [] pts, byte [] types, FillMode fillMode) : this(new ExtendedGeneralPath ())
  73. {
  74. FillMode = fillMode;
  75. SetPath (pts, types);
  76. }
  77. public GraphicsPath (PointF [] pts, byte [] types, FillMode fillMode) : this(new ExtendedGeneralPath ())
  78. {
  79. FillMode = fillMode;
  80. SetPath (pts, types);
  81. }
  82. #endregion
  83. #region Clone
  84. public object Clone ()
  85. {
  86. return new GraphicsPath ((ExtendedGeneralPath) NativeObject.Clone ());
  87. }
  88. #endregion
  89. #region Properties
  90. public FillMode FillMode
  91. {
  92. get
  93. { if(NativeObject.getWindingRule() == GeneralPath.WIND_EVEN_ODD)
  94. return FillMode.Alternate;
  95. else
  96. return FillMode.Winding;
  97. }
  98. set
  99. {
  100. if (value == FillMode.Alternate)
  101. NativeObject.setWindingRule (GeneralPath.WIND_EVEN_ODD);
  102. else
  103. NativeObject.setWindingRule (GeneralPath.WIND_NON_ZERO);
  104. }
  105. }
  106. public PathData PathData
  107. {
  108. get { return NativeObject.PathData; }
  109. }
  110. public PointF [] PathPoints
  111. {
  112. get
  113. {
  114. return PathData.Points;
  115. }
  116. }
  117. public byte [] PathTypes
  118. {
  119. get
  120. {
  121. return PathData.Types;
  122. }
  123. }
  124. #endregion
  125. #region PointCount
  126. public int PointCount
  127. {
  128. get
  129. {
  130. return NativeObject.PointCount;
  131. }
  132. }
  133. #endregion
  134. #region AddArc
  135. public void AddArc (Rectangle rect, float startAngle, float sweepAngle)
  136. {
  137. AddArc(rect.X,rect.Y,rect.Width,rect.Height,startAngle,sweepAngle);
  138. }
  139. public void AddArc (RectangleF rect, float startAngle, float sweepAngle)
  140. {
  141. AddArc(rect.X,rect.Y,rect.Width,rect.Height,startAngle,sweepAngle);
  142. }
  143. public void AddArc (int x, int y, int width, int height, float startAngle, float sweepAngle)
  144. {
  145. AddArc((float)x,(float)y,(float)width,(float)height,startAngle,sweepAngle);
  146. }
  147. public void AddArc (float x, float y, float width, float height, float startAngle, float sweepAngle)
  148. {
  149. Shape shape = null;
  150. if (sweepAngle >= 360)
  151. shape = new Ellipse2D.Float(x, y, width, height);
  152. else {
  153. double d1Tod2 = width/height;
  154. double sqrd1Tod2 = d1Tod2*d1Tod2;
  155. double start = ConvertArcAngle(sqrd1Tod2, startAngle);
  156. double extent = ConvertArcAngle(sqrd1Tod2, startAngle+sweepAngle) - start;
  157. shape = new Arc2D.Double(x,y,width,height,-start,-extent,Arc2D.OPEN);
  158. }
  159. NativeObject.append(shape);
  160. }
  161. /// <summary>
  162. /// .Net computes an angle by intersection of ellipse with a ray
  163. /// java does the following: x1 = d1*cos(a), y1 = d2*sin(a)
  164. /// where: d1 = width/2, d2 = height/2
  165. /// we need to find angle x, which satisfies:
  166. /// x1 = m*cos(a) = d1*cos(x)
  167. /// y1 = m*sin(a) = d2*sin(x)
  168. /// (x1*x1)/(d1*d1) + (x2*x2)/(d2*d2) = 1
  169. /// </summary>
  170. /// <param name="sqrd1Tod2">(d1/d2)*(d1/d2)</param>
  171. /// <param name="angle">angle in degrees</param>
  172. /// <returns>converted angle in degrees</returns>
  173. static double ConvertArcAngle(double sqrd1Tod2, double angle) {
  174. double angleRad = java.lang.Math.toRadians(angle);
  175. double tan = Math.Tan(angleRad);
  176. double cosx = 1/Math.Sqrt( sqrd1Tod2 * (tan*tan) + 1);
  177. double xRad = Math.Acos(cosx);
  178. double x = java.lang.Math.toDegrees(xRad);
  179. int q = (Math.Abs((int)angle))/90;
  180. switch (q&3) {
  181. case 1:
  182. x = 180-x;
  183. break;
  184. case 2:
  185. x = 180+x;
  186. break;
  187. case 3:
  188. x = 360-x;
  189. break;
  190. }
  191. if (angle < 0)
  192. x = -x;
  193. x += (((int)angle)/360)*360;
  194. return x;
  195. }
  196. #endregion
  197. #region AddBezier(s)
  198. public void AddBezier (Point pt1, Point pt2, Point pt3, Point pt4)
  199. {
  200. AddBezier(pt1.X,pt1.Y,pt2.X,pt2.Y,pt3.X,pt3.Y,pt4.X,pt4.Y);
  201. }
  202. public void AddBezier (PointF pt1, PointF pt2, PointF pt3, PointF pt4)
  203. {
  204. AddBezier(pt1.X,pt1.Y,pt2.X,pt2.Y,pt3.X,pt3.Y,pt4.X,pt4.Y);
  205. }
  206. public void AddBezier (int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
  207. {
  208. AddBezier((float)x1,(float)y1,(float)x2,(float)y2,(float)x3,(float)y3,(float)x4,(float)y4);
  209. }
  210. public void AddBezier (float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
  211. {
  212. CubicCurve2D cc = new CubicCurve2D.Float(x1,y1,x2,y2,x3,y3,x4,y4);
  213. NativeObject.append(cc);
  214. }
  215. public void AddBeziers (Point [] pts)
  216. {
  217. if (pts == null)
  218. throw new ArgumentNullException("points");
  219. AddBezier(pts [0].X,pts [0].Y,
  220. pts [1].X,pts [1].Y,
  221. pts [2].X,pts [2].Y,
  222. pts [3].X,pts [3].Y);
  223. for (int i = 4; i < pts.Length; i += 3) {
  224. NativeObject.curveTo(
  225. pts [i].X,pts [i].Y,
  226. pts [i+1].X,pts [i+1].Y,
  227. pts [i+2].X,pts [i+2].Y);
  228. }
  229. }
  230. public void AddBeziers (PointF [] pts)
  231. {
  232. if (pts == null)
  233. throw new ArgumentNullException("points");
  234. AddBezier(pts [0].X,pts [0].Y,
  235. pts [1].X,pts [1].Y,
  236. pts [2].X,pts [2].Y,
  237. pts [3].X,pts [3].Y);
  238. for (int i = 4; i < pts.Length; i += 3) {
  239. NativeObject.curveTo(
  240. pts [i].X,pts [i].Y,
  241. pts [i+1].X,pts [i+1].Y,
  242. pts [i+2].X,pts [i+2].Y);
  243. }
  244. }
  245. #endregion
  246. #region AddEllipse
  247. public void AddEllipse (float x, float y, float width, float height)
  248. {
  249. Ellipse2D e = new Ellipse2D.Float(x,y,width,height);
  250. NativeObject.append(e,false);
  251. }
  252. public void AddEllipse (RectangleF r)
  253. {
  254. AddEllipse(r.X,r.Y,r.Width,r.Height);
  255. }
  256. public void AddEllipse (Rectangle r)
  257. {
  258. AddEllipse(r.X,r.Y,r.Width,r.Height);
  259. }
  260. public void AddEllipse (int x, int y, int width, int height)
  261. {
  262. AddEllipse((float)x, (float)y, (float)width, (float)height);
  263. }
  264. #endregion
  265. #region AddLine
  266. public void AddLine (float x1, float y1, float x2, float y2)
  267. {
  268. Line2D l = new Line2D.Float(x1,y1,x2,y2);
  269. NativeObject.append(l);
  270. }
  271. public void AddLine (Point a, Point b)
  272. {
  273. AddLine(a.X,a.Y,b.X,b.Y);
  274. }
  275. public void AddLine (PointF a, PointF b)
  276. {
  277. AddLine(a.X,a.Y,b.X,b.Y);
  278. }
  279. public void AddLine (int x1, int y1, int x2, int y2)
  280. {
  281. AddLine((float)x1,(float)y1,(float)x2,(float)y2);
  282. }
  283. public void AddLines (Point [] points)
  284. {
  285. if (points == null)
  286. throw new ArgumentNullException("points");
  287. if (points.Length == 0)
  288. return;
  289. if (NativeObject.LastFigureClosed)
  290. NativeObject.moveTo(points[0].X, points[0].Y);
  291. else
  292. NativeObject.lineTo(points[0].X, points[0].Y);
  293. for (int i = 1; i < points.Length; i ++)
  294. NativeObject.lineTo(points[i].X, points[i].Y);
  295. }
  296. public void AddLines (PointF [] points)
  297. {
  298. if (points == null)
  299. throw new ArgumentNullException("points");
  300. if (points.Length == 0)
  301. return;
  302. if (NativeObject.LastFigureClosed)
  303. NativeObject.moveTo(points[0].X, points[0].Y);
  304. else
  305. NativeObject.lineTo(points[0].X, points[0].Y);
  306. for (int i = 1; i < points.Length; i ++)
  307. NativeObject.lineTo(points[i].X, points[i].Y);
  308. }
  309. #endregion
  310. #region AddPie
  311. public void AddPie (float x, float y, float width, float height, float startAngle, float sweepAngle)
  312. {
  313. Shape shape = null;
  314. if (sweepAngle >= 360)
  315. shape = new Ellipse2D.Float(x, y, width, height);
  316. else {
  317. double d1Tod2 = width/height;
  318. double sqrd1Tod2 = d1Tod2*d1Tod2;
  319. double start = ConvertArcAngle(sqrd1Tod2, startAngle);
  320. double extent = ConvertArcAngle(sqrd1Tod2, startAngle+sweepAngle) - start;
  321. shape = new Arc2D.Double(x,y,width,height,-start,-extent,Arc2D.PIE);
  322. }
  323. NativeObject.append(shape,false);
  324. }
  325. public void AddPie (Rectangle rect, float startAngle, float sweepAngle)
  326. {
  327. AddPie((float)rect.X, (float)rect.Y,(float)rect.Width,(float)rect.Height,startAngle,sweepAngle);
  328. }
  329. public void AddPie (int x, int y, int width, int height, float startAngle, float sweepAngle)
  330. {
  331. AddPie((float)x,(float)y,(float)width,(float)height,startAngle,sweepAngle);
  332. }
  333. #endregion
  334. #region AddPolygon
  335. public void AddPolygon (Point [] points)
  336. {
  337. if (points == null)
  338. throw new ArgumentNullException("points");
  339. if (points.Length < 3)
  340. throw new ArgumentException("Invalid parameter used.");
  341. NativeObject.moveTo((float)points[0].X,(float)points[0].Y);
  342. for (int i = 1; i< points.Length; i++)
  343. {
  344. NativeObject.lineTo((float)points[i].X,(float)points[i].Y);
  345. }
  346. NativeObject.closePath();
  347. }
  348. public void AddPolygon (PointF [] points)
  349. {
  350. if (points == null)
  351. throw new ArgumentNullException("points");
  352. if (points.Length < 3)
  353. throw new ArgumentException("Invalid parameter used.");
  354. NativeObject.moveTo(points[0].X,points[0].Y);
  355. for (int i = 1; i < points.Length; i++)
  356. {
  357. NativeObject.lineTo(points[i].X,points[i].Y);
  358. }
  359. NativeObject.closePath();
  360. }
  361. #endregion
  362. #region AddRectangle(s)
  363. internal void AddRectangle(float x,float y, float w, float h)
  364. {
  365. NativeObject.moveTo(x, y);
  366. NativeObject.lineTo (x + w, y);
  367. NativeObject.lineTo (x + w, y + h);
  368. NativeObject.lineTo (x, y + h);
  369. NativeObject.closePath ();
  370. }
  371. public void AddRectangle (RectangleF rect)
  372. {
  373. AddRectangle(rect.X,rect.Y,rect.Width,rect.Height);
  374. }
  375. public void AddRectangle (Rectangle rect)
  376. {
  377. AddRectangle(rect.X,rect.Y,rect.Width,rect.Height);
  378. }
  379. public void AddRectangles (Rectangle [] rects)
  380. {
  381. foreach(Rectangle rect in rects)
  382. AddRectangle(rect.X,rect.Y,rect.Width,rect.Height);
  383. }
  384. public void AddRectangles (RectangleF [] rects)
  385. {
  386. foreach(RectangleF rect in rects)
  387. AddRectangle(rect.X,rect.Y,rect.Width,rect.Height);
  388. }
  389. #endregion
  390. #region AddPath
  391. public void AddPath (GraphicsPath addingPath, bool connect)
  392. {
  393. if (NativeObject.LastFigureClosed || addingPath.NativeObject.LastFigureClosed)
  394. connect = false;
  395. NativeObject.append(addingPath.NativeObject,connect);
  396. }
  397. #endregion
  398. #region GetLastPoint
  399. public PointF GetLastPoint ()
  400. {
  401. return NativeObject.GetLastPoint ();
  402. }
  403. #endregion
  404. #region Reset
  405. public void Reset ()
  406. {
  407. NativeObject.reset();
  408. }
  409. #endregion
  410. #region GetBounds
  411. public RectangleF GetBounds ()
  412. {
  413. return GetBounds (null, null);
  414. }
  415. public RectangleF GetBounds (Matrix matrix)
  416. {
  417. return GetBounds (matrix, null);
  418. }
  419. public RectangleF GetBounds (Matrix matrix, Pen pen)
  420. {
  421. // FIXME : we do not know exacly how the bounding rectangle
  422. // is calculated so this implementation obtains different bounds
  423. // that still contains the path widened by oen and transformed by matrix
  424. // the order of operations is similar to widening, as .Net does.
  425. // first get original shape bounds
  426. //Shape shape = NativeObject.getBounds2D();
  427. Shape shape = NativeObject;
  428. // stroke bounds
  429. if (pen != null)
  430. shape = ((Stroke)pen).createStrokedShape (shape);
  431. Rectangle2D rect = shape.getBounds2D ();
  432. // transform bounds
  433. if (matrix != null)
  434. rect = matrix.NativeObject.createTransformedShape(rect).getBounds2D();
  435. return new RectangleF (rect);
  436. }
  437. #endregion
  438. #region Transform
  439. public void Transform (Matrix matrix)
  440. {
  441. if(matrix == null)
  442. return;
  443. NativeObject.transform(matrix.NativeObject);
  444. }
  445. #endregion
  446. #region IsVisible
  447. public bool IsVisible (Point point)
  448. {
  449. return IsVisible (point.X, point.Y, null);
  450. }
  451. public bool IsVisible (PointF point)
  452. {
  453. return IsVisible (point.X, point.Y, null);
  454. }
  455. public bool IsVisible (int x, int y)
  456. {
  457. return IsVisible (x, y, null);
  458. }
  459. public bool IsVisible (float x, float y)
  460. {
  461. return IsVisible (x, y, null);
  462. }
  463. public bool IsVisible (Point pt, Graphics graphics)
  464. {
  465. return IsVisible (pt.X, pt.Y, graphics);
  466. }
  467. public bool IsVisible (PointF pt, Graphics graphics)
  468. {
  469. return IsVisible (pt.X, pt.Y, graphics);
  470. }
  471. public bool IsVisible (int x, int y, Graphics graphics)
  472. {
  473. return IsVisible((float)x,(float)y,null);
  474. }
  475. public bool IsVisible (float x, float y, Graphics graphics)
  476. {
  477. // LAMESPEC : .Net is currently ignorig Graphics object
  478. //if (graphics != null && !graphics.IsVisible(x,y))
  479. // return false;
  480. return NativeObject.contains(x,y);
  481. }
  482. #endregion
  483. #region Reverse
  484. public void Reverse ()
  485. {
  486. NativeObject.Reverse ();
  487. }
  488. #endregion
  489. #region AddClosedCurve
  490. public void AddClosedCurve (Point [] points)
  491. {
  492. AddClosedCurve(points, 0.5f);
  493. }
  494. public void AddClosedCurve (PointF [] points)
  495. {
  496. AddClosedCurve(points, 0.5f);
  497. }
  498. public void AddClosedCurve (Point [] points, float tension)
  499. {
  500. if (points == null)
  501. throw new ArgumentNullException("points");
  502. if (points.Length < 3)
  503. throw new ArgumentException("Invalid parameter used.");
  504. int length = (points.Length + 3)*2;
  505. float[] pts = new float[length];
  506. pts[--length] = points[1].Y;
  507. pts[--length] = points[1].X;
  508. pts[--length] = points[0].Y;
  509. pts[--length] = points[0].X;
  510. for (int i = points.Length-1; i >= 0; i--) {
  511. pts[--length] = points[i].Y;
  512. pts[--length] = points[i].X;
  513. }
  514. pts[--length] = points[points.Length-1].Y;
  515. pts[--length] = points[points.Length-1].X;
  516. AddCurve(pts, !NativeObject.LastFigureClosed, tension);
  517. CloseFigure ();
  518. }
  519. public void AddClosedCurve (PointF [] points, float tension)
  520. {
  521. if (points == null)
  522. throw new ArgumentNullException("points");
  523. if (points.Length < 3)
  524. throw new ArgumentException("Invalid parameter used.");
  525. int length = (points.Length + 3)*2;
  526. float[] pts = new float[length];
  527. pts[--length] = points[1].Y;
  528. pts[--length] = points[1].X;
  529. pts[--length] = points[0].Y;
  530. pts[--length] = points[0].X;
  531. for (int i = points.Length-1; i >= 0; i--) {
  532. pts[--length] = points[i].Y;
  533. pts[--length] = points[i].X;
  534. }
  535. pts[--length] = points[points.Length-1].Y;
  536. pts[--length] = points[points.Length-1].X;
  537. AddCurve(pts, !NativeObject.LastFigureClosed, tension);
  538. CloseFigure ();
  539. }
  540. #endregion
  541. #region AddCurve
  542. //we have now two approaches for drawing cardinal curves
  543. //the first one is to convert cardinals into approximate beziers
  544. //the second one - to draw curve ourself with all interpolation staff
  545. //here. I preffer the first one because we could utilize java antialiasing and
  546. //flattening features, otherwise curves will be more strict but less cool
  547. public void AddCurve (Point [] points)
  548. {
  549. AddCurve(points,0.5F);
  550. }
  551. public void AddCurve (PointF [] points)
  552. {
  553. AddCurve(points,0.5f);
  554. }
  555. public void AddCurve (Point [] points, float tension)
  556. {
  557. AddCurve(points, 0, points.Length-1, tension);
  558. }
  559. public void AddCurve (PointF [] points, float tension)
  560. {
  561. AddCurve(points, 0, points.Length-1, tension);
  562. }
  563. public void AddCurve (Point [] points, int offset, int numberOfSegments, float tension)
  564. {
  565. int nPoints = numberOfSegments + 1;
  566. int length = nPoints*2 + 4;
  567. float[] pts = new float[length];
  568. int lastP = offset + nPoints;
  569. if (lastP == points.Length) {
  570. lastP--;
  571. pts[--length] = points[lastP].Y;
  572. pts[--length] = points[lastP].X;
  573. }
  574. for (; length > 0 && lastP >= 0; lastP--) {
  575. pts[--length] = points[lastP].Y;
  576. pts[--length] = points[lastP].X;
  577. }
  578. if (length > 0) {
  579. pts[1] = points[0].Y;
  580. pts[0] = points[0].X;
  581. }
  582. AddCurve(pts, !NativeObject.LastFigureClosed, tension);
  583. }
  584. public void AddCurve (PointF [] points, int offset, int numberOfSegments, float tension)
  585. {
  586. int nPoints = numberOfSegments + 1;
  587. int length = nPoints*2 + 4;
  588. float[] pts = new float[length];
  589. int lastP = offset + nPoints;
  590. if (lastP == points.Length) {
  591. lastP--;
  592. pts[--length] = points[lastP].Y;
  593. pts[--length] = points[lastP].X;
  594. }
  595. for (; length > 0 && lastP >= 0; lastP--) {
  596. pts[--length] = points[lastP].Y;
  597. pts[--length] = points[lastP].X;
  598. }
  599. if (length > 0) {
  600. pts[1] = points[0].Y;
  601. pts[0] = points[0].X;
  602. }
  603. AddCurve(pts, !NativeObject.LastFigureClosed, tension);
  604. }
  605. /// <summary>
  606. /// Based on http://pubpages.unh.edu/~cs770/a5/cardinal.html
  607. /// </summary>
  608. /// <param name="pts">point array (x1,y1,x2,y2 ...).
  609. /// The first and last points considered only for calculations, but are not added.</param>
  610. void AddCurve(float[] pts, bool connect, float tension) {
  611. tension /= 3f; //looks like a good pick
  612. if (connect)
  613. NativeObject.lineTo(pts[2],pts[3]);
  614. else
  615. NativeObject.moveTo(pts[2],pts[3]);
  616. float dx = pts[4] - pts[0];
  617. float dy = pts[5] - pts[1];
  618. float sx = pts[2] + tension*dx;
  619. float sy = pts[3] + tension*dy;
  620. for (int offset = 2, total = pts.Length-4; offset < total; offset += 2) {
  621. int cur_offset = offset;
  622. int pX = cur_offset++;
  623. int pY = cur_offset++;
  624. int X = cur_offset++;
  625. int Y = cur_offset++;
  626. int nX = cur_offset++;
  627. int nY = cur_offset++;
  628. dx = pts[nX] - pts[pX];
  629. dy = pts[nY] - pts[pY];
  630. float rx = pts[X] - tension*dx;
  631. float ry = pts[Y] - tension*dy;
  632. NativeObject.curveTo(sx, sy, rx, ry, pts[X], pts[Y]);
  633. sx = pts[X] + tension*dx;
  634. sy = pts[Y] + tension*dy;
  635. }
  636. }
  637. #endregion
  638. #region AddString
  639. [MonoTODO]
  640. public void AddString (string s, FontFamily family, int style, float emSize, Point origin, StringFormat format)
  641. {
  642. throw new NotImplementedException ();
  643. }
  644. [MonoTODO]
  645. public void AddString (string s, FontFamily family, int style, float emSize, PointF origin, StringFormat format)
  646. {
  647. throw new NotImplementedException ();
  648. }
  649. [MonoTODO]
  650. public void AddString (string s, FontFamily family, int style, float emSize, Rectangle layoutRect, StringFormat format)
  651. {
  652. throw new NotImplementedException ();
  653. }
  654. [MonoTODO]
  655. public void AddString (string s, FontFamily family, int style, float emSize, RectangleF layoutRect, StringFormat format)
  656. {
  657. throw new NotImplementedException ();
  658. }
  659. #endregion
  660. #region ClearMarkers
  661. public void ClearMarkers()
  662. {
  663. NativeObject.ClearMarkers ();
  664. }
  665. #endregion
  666. #region Close
  667. public void CloseAllFigures()
  668. {
  669. ExtendedGeneralPath p = new ExtendedGeneralPath();
  670. PathIterator pi = NativeObject.getPathIterator(null);
  671. JPI lastSeg = JPI.SEG_CLOSE;
  672. float [] points = new float[6];
  673. p.setWindingRule(pi.getWindingRule());
  674. while(!pi.isDone())
  675. {
  676. JPI curSeg = (JPI)pi.currentSegment(points);
  677. switch(curSeg)
  678. {
  679. case JPI.SEG_CLOSE:
  680. p.closePath();
  681. break;
  682. case JPI.SEG_MOVETO:
  683. if(lastSeg != JPI.SEG_CLOSE)
  684. p.closePath();
  685. p.moveTo(points[0],points[1]);
  686. break;
  687. case JPI.SEG_LINETO:
  688. p.lineTo(points[0],points[1]);
  689. break;
  690. case JPI.SEG_QUADTO:
  691. p.quadTo(points[0],points[1],points[2],points[3]);
  692. break;
  693. case JPI.SEG_CUBICTO:
  694. p.curveTo(points[0],points[1],points[2],points[3],points[4],points[5]);
  695. break;
  696. default:
  697. break;
  698. }
  699. lastSeg = curSeg;
  700. pi.next();
  701. }
  702. p.closePath();
  703. Shape = p;
  704. }
  705. public void CloseFigure() {
  706. if (!NativeObject.LastFigureClosed)
  707. NativeObject.closePath();
  708. }
  709. #endregion
  710. #region Flatten
  711. public void Flatten ()
  712. {
  713. // 1/4 is the FlatnessDefault as defined in GdiPlusEnums.h
  714. Flatten (null, 1.0f / 4.0f);
  715. }
  716. public void Flatten (Matrix matrix)
  717. {
  718. Flatten (matrix, 1.0f / 4.0f);
  719. }
  720. public void Flatten (Matrix matrix, float flatness)
  721. {
  722. AffineTransform tr = null;
  723. if(matrix != null)
  724. tr = matrix.NativeObject;
  725. //FIXME : Review (perfomance reasons).
  726. PathIterator pi = NativeObject.getPathIterator(tr,flatness);
  727. ExtendedGeneralPath newPath = new ExtendedGeneralPath();
  728. newPath.append(pi,false);
  729. Shape = newPath;
  730. }
  731. #endregion
  732. #region GetOutlineVisible
  733. public bool IsOutlineVisible (Point point, Pen pen)
  734. {
  735. return IsOutlineVisible (point.X, point.Y, pen, null);
  736. }
  737. public bool IsOutlineVisible (PointF point, Pen pen)
  738. {
  739. return IsOutlineVisible (point.X, point.Y, pen, null);
  740. }
  741. public bool IsOutlineVisible (int x, int y, Pen pen)
  742. {
  743. return IsOutlineVisible (x, y, pen, null);
  744. }
  745. public bool IsOutlineVisible (float x, float y, Pen pen)
  746. {
  747. return IsOutlineVisible (x, y, pen, null);
  748. }
  749. public bool IsOutlineVisible (Point pt, Pen pen, Graphics graphics)
  750. {
  751. return IsOutlineVisible (pt.X, pt.Y, pen, graphics);
  752. }
  753. public bool IsOutlineVisible (PointF pt, Pen pen, Graphics graphics)
  754. {
  755. return IsOutlineVisible (pt.X, pt.Y, pen, graphics);
  756. }
  757. public bool IsOutlineVisible (int x, int y, Pen pen, Graphics graphics)
  758. {
  759. // LAMESPEC : .Net is currently ignorig Graphics object
  760. //if (graphics != null) {
  761. // if (!graphics.IsVisible (x, y))
  762. // return false;
  763. //}
  764. return ((Stroke)pen).createStrokedShape (NativeObject).contains (x, y);
  765. }
  766. public bool IsOutlineVisible (float x, float y, Pen pen, Graphics graphics)
  767. {
  768. return ((Stroke)pen).createStrokedShape (NativeObject).contains (x, y);
  769. }
  770. #endregion
  771. #region SetMarkers
  772. public void SetMarkers ()
  773. {
  774. NativeObject.SetMarkers ();
  775. }
  776. #endregion
  777. #region StartFigure
  778. public void StartFigure()
  779. {
  780. NativeObject.StartFigure ();
  781. }
  782. #endregion
  783. #region Warp
  784. [MonoTODO]
  785. public void Warp (PointF[] destPoints, RectangleF srcRect)
  786. {
  787. Warp (destPoints, srcRect, null, WarpMode.Perspective, 1.0f / 4.0f);
  788. }
  789. [MonoTODO]
  790. public void Warp (PointF[] destPoints, RectangleF srcRect, Matrix matrix)
  791. {
  792. Warp (destPoints, srcRect, matrix, WarpMode.Perspective, 1.0f / 4.0f);
  793. }
  794. [MonoTODO]
  795. public void Warp (PointF[] destPoints, RectangleF srcRect, Matrix matrix, WarpMode warpMode)
  796. {
  797. Warp (destPoints, srcRect, matrix, warpMode, 1.0f / 4.0f);
  798. }
  799. [MonoTODO]
  800. public void Warp (PointF[] destPoints, RectangleF srcRect, Matrix matrix, WarpMode warpMode, float flatness)
  801. {
  802. throw new NotImplementedException();
  803. }
  804. #endregion
  805. #region Widen
  806. public void Widen (Pen pen)
  807. {
  808. Widen (pen, null);
  809. }
  810. public void Widen (Pen pen, Matrix matrix)
  811. {
  812. Widen (pen, matrix, 2f/3f);
  813. }
  814. public void Widen (Pen pen, Matrix matrix, float flatness)
  815. {
  816. if (pen == null)
  817. throw new ArgumentNullException("pen");
  818. Shape = new ExtendedGeneralPath(((Stroke)pen).createStrokedShape(this));
  819. Flatten(matrix, flatness);
  820. }
  821. #endregion
  822. private void SetPath (Point [] pts, byte [] types)
  823. {
  824. NativeObject.Clear ();
  825. if (((PathPointType)types [0] & PathPointType.PathTypeMask) != PathPointType.Start)
  826. NativeObject.moveTo (pts [0].X, pts [0].Y);
  827. for (int i=0; i < pts.Length; i++) {
  828. switch (((PathPointType)types [i] & PathPointType.PathTypeMask)) {
  829. case PathPointType.Start :
  830. NativeObject.moveTo (pts [i].X, pts [i].Y);
  831. break;
  832. case PathPointType.Line :
  833. NativeObject.lineTo (pts [i].X, pts [i].Y);
  834. break;
  835. case PathPointType.Bezier3 :
  836. float x1 = pts [i].X;
  837. float y1 = pts [i].Y;
  838. i++;
  839. float x2 = pts [i].X;
  840. float y2 = pts [i].Y;
  841. i++;
  842. float x3 = pts [i].X;
  843. float y3 = pts [i].Y;
  844. NativeObject.curveTo (x1,y1, x2, y2, x3, y3);
  845. break;
  846. }
  847. if (((PathPointType)types [i] & PathPointType.CloseSubpath) != 0)
  848. NativeObject.closePath();
  849. if (((PathPointType)types [i] & PathPointType.PathMarker) != 0)
  850. NativeObject.SetMarkers ();
  851. }
  852. }
  853. internal void SetPath (PointF [] pts, byte [] types)
  854. {
  855. NativeObject.Clear ();
  856. if (((PathPointType)types [0] & PathPointType.PathTypeMask) != PathPointType.Start)
  857. NativeObject.moveTo (pts [0].X, pts [0].Y);
  858. for (int i=0; i < pts.Length; i++) {
  859. switch (((PathPointType)types [i] & PathPointType.PathTypeMask)) {
  860. case PathPointType.Start :
  861. NativeObject.moveTo (pts [i].X, pts [i].Y);
  862. break;
  863. case PathPointType.Line :
  864. NativeObject.lineTo (pts [i].X, pts [i].Y);
  865. break;
  866. case PathPointType.Bezier3 :
  867. float x1 = pts [i].X;
  868. float y1 = pts [i].Y;
  869. i++;
  870. float x2 = pts [i].X;
  871. float y2 = pts [i].Y;
  872. i++;
  873. float x3 = pts [i].X;
  874. float y3 = pts [i].Y;
  875. NativeObject.curveTo (x1,y1, x2, y2, x3, y3);
  876. break;
  877. }
  878. if (((PathPointType)types [i] & PathPointType.CloseSubpath) != 0)
  879. NativeObject.closePath();
  880. if (((PathPointType)types [i] & PathPointType.PathMarker) != 0)
  881. NativeObject.SetMarkers ();
  882. }
  883. }
  884. }
  885. }