GraphicsPath.jvm.cs 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  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_NON_ZERO)
  94. return FillMode.Alternate;
  95. else
  96. return FillMode.Winding;
  97. }
  98. set
  99. {
  100. if (value == FillMode.Alternate)
  101. NativeObject.setWindingRule (GeneralPath.WIND_NON_ZERO);
  102. else
  103. NativeObject.setWindingRule (GeneralPath.WIND_EVEN_ODD);
  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 = ((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. NativeObject.append(addingPath.NativeObject,connect);
  394. }
  395. #endregion
  396. #region GetLastPoint
  397. public PointF GetLastPoint ()
  398. {
  399. return NativeObject.GetLastPoint ();
  400. }
  401. #endregion
  402. #region Reset
  403. public void Reset ()
  404. {
  405. NativeObject.reset();
  406. }
  407. #endregion
  408. #region GetBounds
  409. public RectangleF GetBounds ()
  410. {
  411. return GetBounds (null, null);
  412. }
  413. public RectangleF GetBounds (Matrix matrix)
  414. {
  415. return GetBounds (matrix, null);
  416. }
  417. public RectangleF GetBounds (Matrix matrix, Pen pen)
  418. {
  419. // FIXME : we do not know exacly how the bounding rectangle
  420. // is calculated so this implementation obtains different bounds
  421. // that still contains the path widened by oen and transformed by matrix
  422. // the order of operations is similar to widening, as .Net does.
  423. // first get original shape bounds
  424. //Shape shape = NativeObject.getBounds2D();
  425. Shape shape = NativeObject;
  426. // stroke bounds
  427. if (pen != null)
  428. shape = ((Stroke)pen).createStrokedShape (shape);
  429. Rectangle2D rect = shape.getBounds2D ();
  430. // transform bounds
  431. if (matrix != null)
  432. rect = matrix.NativeObject.createTransformedShape(rect).getBounds2D();
  433. return new RectangleF (rect);
  434. }
  435. #endregion
  436. #region Transform
  437. public void Transform (Matrix matrix)
  438. {
  439. if(matrix == null)
  440. return;
  441. NativeObject.transform(matrix.NativeObject);
  442. }
  443. #endregion
  444. #region IsVisible
  445. public bool IsVisible (Point point)
  446. {
  447. return IsVisible (point.X, point.Y, null);
  448. }
  449. public bool IsVisible (PointF point)
  450. {
  451. return IsVisible (point.X, point.Y, null);
  452. }
  453. public bool IsVisible (int x, int y)
  454. {
  455. return IsVisible (x, y, null);
  456. }
  457. public bool IsVisible (float x, float y)
  458. {
  459. return IsVisible (x, y, null);
  460. }
  461. public bool IsVisible (Point pt, Graphics graphics)
  462. {
  463. return IsVisible (pt.X, pt.Y, graphics);
  464. }
  465. public bool IsVisible (PointF pt, Graphics graphics)
  466. {
  467. return IsVisible (pt.X, pt.Y, graphics);
  468. }
  469. public bool IsVisible (int x, int y, Graphics graphics)
  470. {
  471. return IsVisible((float)x,(float)y,null);
  472. }
  473. public bool IsVisible (float x, float y, Graphics graphics)
  474. {
  475. // LAMESPEC : .Net is currently ignorig Graphics object
  476. //if (graphics != null && !graphics.IsVisible(x,y))
  477. // return false;
  478. return NativeObject.contains(x,y);
  479. }
  480. #endregion
  481. #region Reverse
  482. public void Reverse ()
  483. {
  484. NativeObject.Reverse ();
  485. }
  486. #endregion
  487. #region AddClosedCurve
  488. public void AddClosedCurve (Point [] points)
  489. {
  490. AddClosedCurve(points, 0.5f);
  491. }
  492. public void AddClosedCurve (PointF [] points)
  493. {
  494. AddClosedCurve(points, 0.5f);
  495. }
  496. public void AddClosedCurve (Point [] points, float tension)
  497. {
  498. if (points == null)
  499. throw new ArgumentNullException("points");
  500. if (points.Length < 3)
  501. throw new ArgumentException("Invalid parameter used.");
  502. int length = (points.Length + 3)*2;
  503. float[] pts = new float[length];
  504. pts[--length] = points[1].Y;
  505. pts[--length] = points[1].X;
  506. pts[--length] = points[0].Y;
  507. pts[--length] = points[0].X;
  508. for (int i = points.Length-1; i >= 0; i--) {
  509. pts[--length] = points[i].Y;
  510. pts[--length] = points[i].X;
  511. }
  512. pts[--length] = points[points.Length-1].Y;
  513. pts[--length] = points[points.Length-1].X;
  514. AddCurve(pts, !NativeObject.LastFigureClosed, tension);
  515. CloseFigure ();
  516. }
  517. public void AddClosedCurve (PointF [] points, float tension)
  518. {
  519. if (points == null)
  520. throw new ArgumentNullException("points");
  521. if (points.Length < 3)
  522. throw new ArgumentException("Invalid parameter used.");
  523. int length = (points.Length + 3)*2;
  524. float[] pts = new float[length];
  525. pts[--length] = points[1].Y;
  526. pts[--length] = points[1].X;
  527. pts[--length] = points[0].Y;
  528. pts[--length] = points[0].X;
  529. for (int i = points.Length-1; i >= 0; i--) {
  530. pts[--length] = points[i].Y;
  531. pts[--length] = points[i].X;
  532. }
  533. pts[--length] = points[points.Length-1].Y;
  534. pts[--length] = points[points.Length-1].X;
  535. AddCurve(pts, !NativeObject.LastFigureClosed, tension);
  536. CloseFigure ();
  537. }
  538. #endregion
  539. #region AddCurve
  540. //we have now two approaches for drawing cardinal curves
  541. //the first one is to convert cardinals into approximate beziers
  542. //the second one - to draw curve ourself with all interpolation staff
  543. //here. I preffer the first one because we could utilize java antialiasing and
  544. //flattening features, otherwise curves will be more strict but less cool
  545. public void AddCurve (Point [] points)
  546. {
  547. AddCurve(points,0.5F);
  548. }
  549. public void AddCurve (PointF [] points)
  550. {
  551. AddCurve(points,0.5f);
  552. }
  553. public void AddCurve (Point [] points, float tension)
  554. {
  555. AddCurve(points, 0, points.Length-1, tension);
  556. }
  557. public void AddCurve (PointF [] points, float tension)
  558. {
  559. AddCurve(points, 0, points.Length-1, tension);
  560. }
  561. public void AddCurve (Point [] points, int offset, int numberOfSegments, float tension)
  562. {
  563. int nPoints = numberOfSegments + 1;
  564. int length = nPoints*2 + 4;
  565. float[] pts = new float[length];
  566. int lastP = offset + nPoints;
  567. if (lastP == points.Length) {
  568. lastP--;
  569. pts[--length] = points[lastP].Y;
  570. pts[--length] = points[lastP].X;
  571. }
  572. for (; length > 0 && lastP >= 0; lastP--) {
  573. pts[--length] = points[lastP].Y;
  574. pts[--length] = points[lastP].X;
  575. }
  576. if (length > 0) {
  577. pts[1] = points[0].Y;
  578. pts[0] = points[0].X;
  579. }
  580. AddCurve(pts, !NativeObject.LastFigureClosed, tension);
  581. }
  582. public void AddCurve (PointF [] points, int offset, int numberOfSegments, float tension)
  583. {
  584. int nPoints = numberOfSegments + 1;
  585. int length = nPoints*2 + 4;
  586. float[] pts = new float[length];
  587. int lastP = offset + nPoints;
  588. if (lastP == points.Length) {
  589. lastP--;
  590. pts[--length] = points[lastP].Y;
  591. pts[--length] = points[lastP].X;
  592. }
  593. for (; length > 0 && lastP >= 0; lastP--) {
  594. pts[--length] = points[lastP].Y;
  595. pts[--length] = points[lastP].X;
  596. }
  597. if (length > 0) {
  598. pts[1] = points[0].Y;
  599. pts[0] = points[0].X;
  600. }
  601. AddCurve(pts, !NativeObject.LastFigureClosed, tension);
  602. }
  603. /// <summary>
  604. /// Based on http://pubpages.unh.edu/~cs770/a5/cardinal.html
  605. /// </summary>
  606. /// <param name="pts">point array (x1,y1,x2,y2 ...).
  607. /// The first and last points considered only for calculations, but are not added.</param>
  608. void AddCurve(float[] pts, bool connect, float tension) {
  609. tension /= 3f; //looks like a good pick
  610. if (connect)
  611. NativeObject.lineTo(pts[2],pts[3]);
  612. else
  613. NativeObject.moveTo(pts[2],pts[3]);
  614. float dx = pts[4] - pts[0];
  615. float dy = pts[5] - pts[1];
  616. float sx = pts[2] + tension*dx;
  617. float sy = pts[3] + tension*dy;
  618. for (int offset = 2, total = pts.Length-4; offset < total; offset += 2) {
  619. int cur_offset = offset;
  620. int pX = cur_offset++;
  621. int pY = cur_offset++;
  622. int X = cur_offset++;
  623. int Y = cur_offset++;
  624. int nX = cur_offset++;
  625. int nY = cur_offset++;
  626. dx = pts[nX] - pts[pX];
  627. dy = pts[nY] - pts[pY];
  628. float rx = pts[X] - tension*dx;
  629. float ry = pts[Y] - tension*dy;
  630. NativeObject.curveTo(sx, sy, rx, ry, pts[X], pts[Y]);
  631. sx = pts[X] + tension*dx;
  632. sy = pts[Y] + tension*dy;
  633. }
  634. }
  635. #endregion
  636. #region AddString
  637. [MonoTODO]
  638. public void AddString (string s, FontFamily family, int style, float emSize, Point origin, StringFormat format)
  639. {
  640. throw new NotImplementedException ();
  641. }
  642. [MonoTODO]
  643. public void AddString (string s, FontFamily family, int style, float emSize, PointF origin, StringFormat format)
  644. {
  645. throw new NotImplementedException ();
  646. }
  647. [MonoTODO]
  648. public void AddString (string s, FontFamily family, int style, float emSize, Rectangle layoutRect, StringFormat format)
  649. {
  650. throw new NotImplementedException ();
  651. }
  652. [MonoTODO]
  653. public void AddString (string s, FontFamily family, int style, float emSize, RectangleF layoutRect, StringFormat format)
  654. {
  655. throw new NotImplementedException ();
  656. }
  657. #endregion
  658. #region ClearMarkers
  659. public void ClearMarkers()
  660. {
  661. NativeObject.ClearMarkers ();
  662. }
  663. #endregion
  664. #region Close
  665. public void CloseAllFigures()
  666. {
  667. ExtendedGeneralPath p = new ExtendedGeneralPath();
  668. PathIterator pi = NativeObject.getPathIterator(null);
  669. JPI lastSeg = JPI.SEG_CLOSE;
  670. float [] points = new float[6];
  671. p.setWindingRule(pi.getWindingRule());
  672. while(!pi.isDone())
  673. {
  674. JPI curSeg = (JPI)pi.currentSegment(points);
  675. switch(curSeg)
  676. {
  677. case JPI.SEG_CLOSE:
  678. p.closePath();
  679. break;
  680. case JPI.SEG_MOVETO:
  681. if(lastSeg != JPI.SEG_CLOSE)
  682. p.closePath();
  683. p.moveTo(points[0],points[1]);
  684. break;
  685. case JPI.SEG_LINETO:
  686. p.lineTo(points[0],points[1]);
  687. break;
  688. case JPI.SEG_QUADTO:
  689. p.quadTo(points[0],points[1],points[2],points[3]);
  690. break;
  691. case JPI.SEG_CUBICTO:
  692. p.curveTo(points[0],points[1],points[2],points[3],points[4],points[5]);
  693. break;
  694. default:
  695. break;
  696. }
  697. lastSeg = curSeg;
  698. pi.next();
  699. }
  700. p.closePath();
  701. Shape = p;
  702. }
  703. public void CloseFigure()
  704. {
  705. NativeObject.closePath();
  706. }
  707. #endregion
  708. #region Flatten
  709. public void Flatten ()
  710. {
  711. // 1/4 is the FlatnessDefault as defined in GdiPlusEnums.h
  712. Flatten (null, 1.0f / 4.0f);
  713. }
  714. public void Flatten (Matrix matrix)
  715. {
  716. Flatten (matrix, 1.0f / 4.0f);
  717. }
  718. public void Flatten (Matrix matrix, float flatness)
  719. {
  720. AffineTransform tr = null;
  721. if(matrix != null)
  722. tr = matrix.NativeObject;
  723. //FIXME : Review (perfomance reasons).
  724. PathIterator pi = NativeObject.getPathIterator(tr,flatness);
  725. ExtendedGeneralPath newPath = new ExtendedGeneralPath();
  726. newPath.append(pi,false);
  727. Shape = newPath;
  728. }
  729. #endregion
  730. #region GetOutlineVisible
  731. public bool IsOutlineVisible (Point point, Pen pen)
  732. {
  733. return IsOutlineVisible (point.X, point.Y, pen, null);
  734. }
  735. public bool IsOutlineVisible (PointF point, Pen pen)
  736. {
  737. return IsOutlineVisible (point.X, point.Y, pen, null);
  738. }
  739. public bool IsOutlineVisible (int x, int y, Pen pen)
  740. {
  741. return IsOutlineVisible (x, y, pen, null);
  742. }
  743. public bool IsOutlineVisible (float x, float y, Pen pen)
  744. {
  745. return IsOutlineVisible (x, y, pen, null);
  746. }
  747. public bool IsOutlineVisible (Point pt, Pen pen, Graphics graphics)
  748. {
  749. return IsOutlineVisible (pt.X, pt.Y, pen, graphics);
  750. }
  751. public bool IsOutlineVisible (PointF pt, Pen pen, Graphics graphics)
  752. {
  753. return IsOutlineVisible (pt.X, pt.Y, pen, graphics);
  754. }
  755. public bool IsOutlineVisible (int x, int y, Pen pen, Graphics graphics)
  756. {
  757. // LAMESPEC : .Net is currently ignorig Graphics object
  758. //if (graphics != null) {
  759. // if (!graphics.IsVisible (x, y))
  760. // return false;
  761. //}
  762. return ((Stroke)pen).createStrokedShape (NativeObject).contains (x, y);
  763. }
  764. public bool IsOutlineVisible (float x, float y, Pen pen, Graphics graphics)
  765. {
  766. return ((Stroke)pen).createStrokedShape (NativeObject).contains (x, y);
  767. }
  768. #endregion
  769. #region SetMarkers
  770. public void SetMarkers ()
  771. {
  772. NativeObject.SetMarkers ();
  773. }
  774. #endregion
  775. #region StartFigure
  776. public void StartFigure()
  777. {
  778. NativeObject.StartFigure ();
  779. }
  780. #endregion
  781. #region Warp
  782. [MonoTODO]
  783. public void Warp (PointF[] destPoints, RectangleF srcRect)
  784. {
  785. Warp (destPoints, srcRect, null, WarpMode.Perspective, 1.0f / 4.0f);
  786. }
  787. [MonoTODO]
  788. public void Warp (PointF[] destPoints, RectangleF srcRect, Matrix matrix)
  789. {
  790. Warp (destPoints, srcRect, matrix, WarpMode.Perspective, 1.0f / 4.0f);
  791. }
  792. [MonoTODO]
  793. public void Warp (PointF[] destPoints, RectangleF srcRect, Matrix matrix, WarpMode warpMode)
  794. {
  795. Warp (destPoints, srcRect, matrix, warpMode, 1.0f / 4.0f);
  796. }
  797. [MonoTODO]
  798. public void Warp (PointF[] destPoints, RectangleF srcRect, Matrix matrix, WarpMode warpMode, float flatness)
  799. {
  800. throw new NotImplementedException();
  801. }
  802. #endregion
  803. #region Widen
  804. public void Widen (Pen pen)
  805. {
  806. Widen (pen, null);
  807. }
  808. public void Widen (Pen pen, Matrix matrix)
  809. {
  810. Widen (pen, matrix, 2f/3f);
  811. }
  812. public void Widen (Pen pen, Matrix matrix, float flatness)
  813. {
  814. if (pen == null)
  815. throw new ArgumentNullException("pen");
  816. Shape = new ExtendedGeneralPath(((Stroke)pen).createStrokedShape(this));
  817. Flatten(matrix, flatness);
  818. }
  819. #endregion
  820. private void SetPath (Point [] pts, byte [] types)
  821. {
  822. NativeObject.Clear ();
  823. if (((PathPointType)types [0] & PathPointType.PathTypeMask) != PathPointType.Start)
  824. NativeObject.moveTo (pts [0].X, pts [0].Y);
  825. for (int i=0; i < pts.Length; i++) {
  826. switch (((PathPointType)types [i] & PathPointType.PathTypeMask)) {
  827. case PathPointType.Start :
  828. NativeObject.moveTo (pts [i].X, pts [i].Y);
  829. break;
  830. case PathPointType.Line :
  831. NativeObject.lineTo (pts [i].X, pts [i].Y);
  832. break;
  833. case PathPointType.Bezier3 :
  834. float x1 = pts [i].X;
  835. float y1 = pts [i].Y;
  836. i++;
  837. float x2 = pts [i].X;
  838. float y2 = pts [i].Y;
  839. i++;
  840. float x3 = pts [i].X;
  841. float y3 = pts [i].Y;
  842. NativeObject.curveTo (x1,y1, x2, y2, x3, y3);
  843. break;
  844. }
  845. if (((PathPointType)types [i] & PathPointType.CloseSubpath) != 0)
  846. NativeObject.closePath();
  847. if (((PathPointType)types [i] & PathPointType.PathMarker) != 0)
  848. NativeObject.SetMarkers ();
  849. }
  850. }
  851. internal void SetPath (PointF [] pts, byte [] types)
  852. {
  853. NativeObject.Clear ();
  854. if (((PathPointType)types [0] & PathPointType.PathTypeMask) != PathPointType.Start)
  855. NativeObject.moveTo (pts [0].X, pts [0].Y);
  856. for (int i=0; i < pts.Length; i++) {
  857. switch (((PathPointType)types [i] & PathPointType.PathTypeMask)) {
  858. case PathPointType.Start :
  859. NativeObject.moveTo (pts [i].X, pts [i].Y);
  860. break;
  861. case PathPointType.Line :
  862. NativeObject.lineTo (pts [i].X, pts [i].Y);
  863. break;
  864. case PathPointType.Bezier3 :
  865. float x1 = pts [i].X;
  866. float y1 = pts [i].Y;
  867. i++;
  868. float x2 = pts [i].X;
  869. float y2 = pts [i].Y;
  870. i++;
  871. float x3 = pts [i].X;
  872. float y3 = pts [i].Y;
  873. NativeObject.curveTo (x1,y1, x2, y2, x3, y3);
  874. break;
  875. }
  876. if (((PathPointType)types [i] & PathPointType.CloseSubpath) != 0)
  877. NativeObject.closePath();
  878. if (((PathPointType)types [i] & PathPointType.PathMarker) != 0)
  879. NativeObject.SetMarkers ();
  880. }
  881. }
  882. }
  883. }