ShapeObject.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Drawing2D;
  4. using System.ComponentModel;
  5. using FastReport.Utils;
  6. using System.Linq;
  7. namespace FastReport
  8. {
  9. /// <summary>
  10. /// Specifies a kind of the shape.
  11. /// </summary>
  12. public enum ShapeKind
  13. {
  14. /// <summary>
  15. /// Specifies a rectangle shape.
  16. /// </summary>
  17. Rectangle,
  18. /// <summary>
  19. /// Specifies a round rectangle shape.
  20. /// </summary>
  21. RoundRectangle,
  22. /// <summary>
  23. /// Specifies an ellipse shape.
  24. /// </summary>
  25. Ellipse,
  26. /// <summary>
  27. /// Specifies a triangle shape.
  28. /// </summary>
  29. Triangle,
  30. /// <summary>
  31. /// Specifies a diamond shape.
  32. /// </summary>
  33. Diamond
  34. }
  35. /// <summary>
  36. /// Represents a shape object.
  37. /// </summary>
  38. /// <remarks>
  39. /// Use the <see cref="ShapeKind"/> property to specify a shape. To set the width, style and color of the
  40. /// shape's border, use the <b>Border.Width</b>, <b>Border.Style</b> and <b>Border.Color</b> properties.
  41. /// </remarks>
  42. public partial class ShapeObject : ReportComponentBase
  43. {
  44. #region Fields
  45. private ShapeKind shape;
  46. private float curve;
  47. private FloatCollection dashPattern;
  48. #endregion
  49. #region Properties
  50. /// <summary>
  51. /// Gets or sets collection of values for custom dash pattern.
  52. /// </summary>
  53. /// <remarks>
  54. /// Each element should be a non-zero positive number.
  55. /// If the number is negative or zero, that number is replaced by one.
  56. /// </remarks>
  57. [Category("Appearance")]
  58. public FloatCollection DashPattern
  59. {
  60. get { return dashPattern; }
  61. set { dashPattern = value; }
  62. }
  63. /// <summary>
  64. /// Gets or sets a shape kind.
  65. /// </summary>
  66. [DefaultValue(ShapeKind.Rectangle)]
  67. [Category("Appearance")]
  68. public ShapeKind Shape
  69. {
  70. get { return shape; }
  71. set { shape = value; }
  72. }
  73. /// <summary>
  74. /// Gets or sets a shape curvature if <see cref="ShapeKind"/> is <b>RoundRectangle</b>.
  75. /// </summary>
  76. /// <remarks>
  77. /// 0 value means automatic curvature.
  78. /// </remarks>
  79. [DefaultValue(0f)]
  80. [Category("Appearance")]
  81. public float Curve
  82. {
  83. get { return curve; }
  84. set { curve = value; }
  85. }
  86. #endregion
  87. #region Private Methods
  88. private GraphicsPath GetRoundRectPath(float x, float y, float x1, float y1, float radius)
  89. {
  90. GraphicsPath gp = new GraphicsPath();
  91. if (radius < 1)
  92. radius = 1;
  93. gp.AddArc(x1 - radius, y, radius, radius, 270, 90);
  94. gp.AddArc(x1 - radius, y1 - radius, radius, radius, 0, 90);
  95. gp.AddArc(x, y1 - radius, radius, radius, 90, 90);
  96. gp.AddArc(x, y, radius, radius, 180, 90);
  97. gp.CloseFigure();
  98. return gp;
  99. }
  100. #endregion
  101. #region Public Methods
  102. /// <inheritdoc/>
  103. public override void Assign(Base source)
  104. {
  105. base.Assign(source);
  106. ShapeObject src = source as ShapeObject;
  107. Shape = src.Shape;
  108. Curve = src.Curve;
  109. DashPattern.Assign(src.DashPattern);
  110. }
  111. /// <inheritdoc/>
  112. public override void Draw(FRPaintEventArgs e)
  113. {
  114. if (Math.Abs(Width) < 1 || Math.Abs(Height) < 1)
  115. return;
  116. IGraphics g = e.Graphics;
  117. float x = (AbsLeft + Border.Width / 2) * e.ScaleX;
  118. float y = (AbsTop + Border.Width / 2) * e.ScaleY;
  119. float dx = (Width - Border.Width) * e.ScaleX - 1;
  120. float dy = (Height - Border.Width) * e.ScaleY - 1;
  121. float x1 = x + dx;
  122. float y1 = y + dy;
  123. Pen pen = e.Cache.GetPen(Border.Color, Border.Width * e.ScaleX, Border.DashStyle);
  124. DrawUtils.SetPenDashPatternOrStyle(DashPattern, pen, Border);
  125. Brush brush = null;
  126. if (Fill is SolidFill)
  127. brush = e.Cache.GetBrush((Fill as SolidFill).Color);
  128. else
  129. brush = Fill.CreateBrush(new RectangleF(x, y, dx, dy), e.ScaleX, e.ScaleY);
  130. Report report = Report;
  131. if (report != null && report.SmoothGraphics && Shape != ShapeKind.Rectangle)
  132. {
  133. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
  134. g.SmoothingMode = SmoothingMode.AntiAlias;
  135. }
  136. switch (Shape)
  137. {
  138. case ShapeKind.Rectangle:
  139. g.FillAndDrawRectangle(pen, brush, x, y, dx, dy);
  140. break;
  141. case ShapeKind.RoundRectangle:
  142. float min = Math.Min(dx, dy);
  143. if (curve == 0)
  144. min = min / 4;
  145. else
  146. min = Math.Min(min, curve * e.ScaleX * 10);
  147. GraphicsPath gp = GetRoundRectPath(x, y, x1, y1, min);
  148. g.FillAndDrawPath(pen, brush, gp);
  149. gp.Dispose();
  150. break;
  151. case ShapeKind.Ellipse:
  152. g.FillAndDrawEllipse(pen, brush, x, y, dx, dy);
  153. break;
  154. case ShapeKind.Triangle:
  155. PointF[] triPoints = {
  156. new PointF(x1, y1), new PointF(x, y1), new PointF(x + dx / 2, y), new PointF(x1, y1) };
  157. g.FillAndDrawPolygon(pen, brush, triPoints);
  158. break;
  159. case ShapeKind.Diamond:
  160. PointF[] diaPoints = {
  161. new PointF(x + dx / 2, y), new PointF(x1, y + dy / 2), new PointF(x + dx / 2, y1),
  162. new PointF(x, y + dy / 2) };
  163. g.FillAndDrawPolygon(pen, brush, diaPoints);
  164. break;
  165. }
  166. if (!(Fill is SolidFill))
  167. brush.Dispose();
  168. if (report != null && report.SmoothGraphics)
  169. {
  170. g.InterpolationMode = InterpolationMode.Default;
  171. g.SmoothingMode = SmoothingMode.Default;
  172. }
  173. }
  174. /// <inheritdoc/>
  175. public override void Serialize(FRWriter writer)
  176. {
  177. Border.SimpleBorder = true;
  178. base.Serialize(writer);
  179. ShapeObject c = writer.DiffObject as ShapeObject;
  180. if (Shape != c.Shape)
  181. writer.WriteValue("Shape", Shape);
  182. if (Curve != c.Curve)
  183. writer.WriteFloat("Curve", Curve);
  184. if (DashPattern?.Count > 0)
  185. writer.WriteValue("DashPattern", DashPattern);
  186. }
  187. #endregion
  188. /// <summary>
  189. /// Initializes a new instance of the <see cref="ShapeObject"/> class with default settings.
  190. /// </summary>
  191. public ShapeObject()
  192. {
  193. shape = ShapeKind.Rectangle;
  194. FlagSimpleBorder = true;
  195. dashPattern = new FloatCollection();
  196. }
  197. }
  198. }