GraphicsPath.jvm.cs 28 KB

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