PictureObjectBase.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Drawing.Design;
  6. using System.IO;
  7. using System.Windows.Forms;
  8. using FastReport.Utils;
  9. namespace FastReport
  10. {
  11. /// <summary>
  12. /// Specifies the alignment of a image in the border.
  13. /// </summary>
  14. public enum ImageAlign
  15. {
  16. /// <summary>
  17. /// Specifies that image is not aligned in the layout rectangle.
  18. /// </summary>
  19. None,
  20. /// <summary>
  21. /// Specifies that image is aligned in the top-left of the layout rectangle.
  22. /// </summary>
  23. Top_Left,
  24. /// <summary>
  25. /// Specifies that image is aligned in the top-center of the layout rectangle.
  26. /// </summary>
  27. Top_Center,
  28. /// <summary>
  29. /// Specifies that image is aligned in the top-right of the layout rectangle.
  30. /// </summary>
  31. Top_Right,
  32. /// <summary>
  33. /// Specifies that image is aligned in the center-left of the layout rectangle.
  34. /// </summary>
  35. Center_Left,
  36. /// <summary>
  37. /// Specifies that image is aligned in the center-center of the layout rectangle.
  38. /// </summary>
  39. Center_Center,
  40. /// <summary>
  41. /// Specifies that image is aligned in the center-right of the layout rectangle.
  42. /// </summary>
  43. Center_Right,
  44. /// <summary>
  45. /// Specifies that image is aligned in the center-left of the layout rectangle.
  46. /// </summary>
  47. Bottom_Left,
  48. /// <summary>
  49. /// Specifies that image is aligned in the center-center of the layout rectangle.
  50. /// </summary>
  51. Bottom_Center,
  52. /// <summary>
  53. /// Specifies that image is aligned in the center-right of the layout rectangle.
  54. /// </summary>
  55. Bottom_Right,
  56. }
  57. /// <summary>
  58. /// the base class for all picture objects
  59. /// </summary>
  60. public abstract partial class PictureObjectBase : ReportComponentBase
  61. {
  62. #region Internal Fields
  63. #endregion Internal Fields
  64. #region Private Fields
  65. private int angle;
  66. private string dataColumn;
  67. private bool grayscale;
  68. private string imageLocation;
  69. private string imageSourceExpression;
  70. private float maxHeight;
  71. private float maxWidth;
  72. private Padding padding;
  73. private PictureBoxSizeMode saveSizeMode;
  74. private bool showErrorImage;
  75. private PictureBoxSizeMode sizeModeInternal;
  76. private ImageAlign imageAlign;
  77. private ShapeKind shape;
  78. #endregion Private Fields
  79. #region Public Properties
  80. /// <summary>
  81. /// Gets or sets the image rotation angle, in degrees. Possible values are 0, 90, 180, 270.
  82. /// </summary>
  83. [DefaultValue(0)]
  84. [Category("Appearance")]
  85. public int Angle
  86. {
  87. get { return angle; }
  88. set { angle = value; }
  89. }
  90. /// <summary>
  91. /// Gets or sets the data column name to get the image from.
  92. /// </summary>
  93. [Category("Data")]
  94. [Editor("FastReport.TypeEditors.DataColumnEditor, FastReport", typeof(UITypeEditor))]
  95. public string DataColumn
  96. {
  97. get { return dataColumn; }
  98. set { dataColumn = value; }
  99. }
  100. /// <summary>
  101. /// Gets or sets a value indicating that the image should be displayed in grayscale mode.
  102. /// </summary>
  103. [DefaultValue(false)]
  104. [Category("Appearance")]
  105. public virtual bool Grayscale
  106. {
  107. get { return grayscale; }
  108. set
  109. {
  110. grayscale = value;
  111. }
  112. }
  113. /// <inheritdoc/>
  114. public override float Height
  115. {
  116. get { return base.Height; }
  117. set
  118. {
  119. if (MaxHeight != 0 && value > MaxHeight)
  120. value = MaxHeight;
  121. base.Height = value;
  122. }
  123. }
  124. /// <summary>
  125. /// Gets or sets the path for the image to display in the PictureObject.
  126. /// </summary>
  127. /// <remarks>
  128. /// This property may contain the path to the image file as well as external URL.
  129. /// </remarks>
  130. [Category("Data")]
  131. public string ImageLocation
  132. {
  133. get { return imageLocation; }
  134. set
  135. {
  136. if (!String.IsNullOrEmpty(Config.ReportSettings.ImageLocationRoot))
  137. imageLocation = value.Replace(Config.ReportSettings.ImageLocationRoot, "");
  138. else
  139. imageLocation = value;
  140. LoadImage();
  141. ResetImageIndex();
  142. }
  143. }
  144. /// <summary>
  145. /// Gets or sets the expression that determines the source for the image to display in the PictureObject.
  146. /// </summary>
  147. /// <remarks>
  148. /// The result of the expression should be data column name or path to the image file.
  149. /// The data column name will be saved to the <see cref="DataColumn"/> property.
  150. /// The path will be savetd to the <see cref="ImageLocation"/> property.
  151. /// </remarks>
  152. [Category("Data")]
  153. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  154. public string ImageSourceExpression
  155. {
  156. get { return imageSourceExpression; }
  157. set
  158. {
  159. imageSourceExpression = value;
  160. if (!String.IsNullOrEmpty(ImageSourceExpression) && Report != null)
  161. {
  162. string expression = ImageSourceExpression;
  163. if (ImageSourceExpression.StartsWith("[") && ImageSourceExpression.EndsWith("]"))
  164. {
  165. expression = ImageSourceExpression.Substring(1, ImageSourceExpression.Length - 2);
  166. }
  167. if (Data.DataHelper.IsValidColumn(Report.Dictionary, expression))
  168. {
  169. DataColumn = expression;
  170. }
  171. if (Data.DataHelper.IsValidParameter(Report.Dictionary, expression))
  172. {
  173. ImageLocation = Report.GetParameterValue(expression).ToString();
  174. }
  175. }
  176. }
  177. }
  178. /// <summary>
  179. /// Gets a value indicating that the image stored in the databases column
  180. /// </summary>
  181. [Browsable(false)]
  182. public bool IsDataColumn
  183. {
  184. get { return !String.IsNullOrEmpty(DataColumn); }
  185. }
  186. /// <summary>
  187. /// Gets a value indicating that the image stored in the separate file
  188. /// </summary>
  189. [Browsable(false)]
  190. public bool IsFileLocation
  191. {
  192. get
  193. {
  194. if (String.IsNullOrEmpty(ImageLocation))
  195. return false;
  196. Uri uri = CalculateUri();
  197. return uri.IsFile;
  198. }
  199. }
  200. /// <summary>
  201. /// Gets a value indicating that the image stored in the Web
  202. /// </summary>
  203. [Browsable(false)]
  204. public bool IsWebLocation
  205. {
  206. get
  207. {
  208. if (String.IsNullOrEmpty(ImageLocation))
  209. return false;
  210. Uri uri = CalculateUri();
  211. return !uri.IsFile;
  212. }
  213. }
  214. /// <summary>
  215. /// Gets or sets the maximum height of a Picture object, in pixels.
  216. /// </summary>
  217. /// <remarks>
  218. /// Use this property to restrict the object size if the <see cref="SizeMode"/> property
  219. /// is set to <b>AutoSize</b>.
  220. /// </remarks>
  221. [DefaultValue(0f)]
  222. [Category("Layout")]
  223. [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  224. public float MaxHeight
  225. {
  226. get { return maxHeight; }
  227. set { maxHeight = value; }
  228. }
  229. /// <summary>
  230. /// Gets or sets the maximum width of a Picture object, in pixels.
  231. /// </summary>
  232. /// <remarks>
  233. /// Use this property to restrict the object size if the <see cref="SizeMode"/> property
  234. /// is set to <b>AutoSize</b>.
  235. /// </remarks>
  236. [DefaultValue(0f)]
  237. [Category("Layout")]
  238. [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  239. public float MaxWidth
  240. {
  241. get { return maxWidth; }
  242. set { maxWidth = value; }
  243. }
  244. /// <summary>
  245. /// Gets or sets padding within the PictureObject.
  246. /// </summary>
  247. [Category("Layout")]
  248. public Padding Padding
  249. {
  250. get { return padding; }
  251. set { padding = value; }
  252. }
  253. /// <summary>
  254. /// Gets or sets a value indicating whether the PictureObject should display
  255. /// the error indicator if there is no image in it.
  256. /// </summary>
  257. [DefaultValue(false)]
  258. [Category("Behavior")]
  259. public bool ShowErrorImage
  260. {
  261. get { return showErrorImage; }
  262. set { showErrorImage = value; }
  263. }
  264. /// <summary>
  265. /// Gets or sets a value that specifies how an image is positioned within a PictureObject.
  266. /// </summary>
  267. [DefaultValue(PictureBoxSizeMode.Zoom)]
  268. [Category("Behavior")]
  269. public virtual PictureBoxSizeMode SizeMode
  270. {
  271. get { return sizeModeInternal; }
  272. set
  273. {
  274. sizeModeInternal = value;
  275. UpdateAutoSize();
  276. }
  277. }
  278. /// <inheritdoc/>
  279. public override float Width
  280. {
  281. get { return base.Width; }
  282. set
  283. {
  284. if (MaxWidth != 0 && value > MaxWidth)
  285. value = MaxWidth;
  286. base.Width = value;
  287. }
  288. }
  289. /// <summary>
  290. /// Gets or sets the alignment of a image in the border.
  291. /// </summary>
  292. [DefaultValue(ImageAlign.None)]
  293. [Category("Appearance")]
  294. public ImageAlign ImageAlign
  295. {
  296. get { return imageAlign; }
  297. set { imageAlign = value; }
  298. }
  299. /// <summary>
  300. /// Gets or sets a shape kind.
  301. /// </summary>
  302. [DefaultValue(ShapeKind.Rectangle)]
  303. [Category("Appearance")]
  304. public ShapeKind Shape
  305. {
  306. get { return shape; }
  307. set { shape = value; }
  308. }
  309. #endregion Public Properties
  310. #region Protected Properties
  311. /// <summary>
  312. /// Return base size of image, internal use only
  313. /// </summary>
  314. [Browsable(false)]
  315. protected abstract float ImageHeight { get; }
  316. /// <summary>
  317. /// Return base size of image, internal use only
  318. /// </summary>
  319. [Browsable(false)]
  320. protected abstract float ImageWidth { get; }
  321. #endregion Protected Properties
  322. #region Public Constructors
  323. /// <inheritdoc/>
  324. public PictureObjectBase()
  325. {
  326. sizeModeInternal = PictureBoxSizeMode.Zoom;
  327. shape = ShapeKind.Rectangle;
  328. padding = new Padding();
  329. imageLocation = "";
  330. dataColumn = "";
  331. imageSourceExpression = "";
  332. }
  333. #endregion Public Constructors
  334. #region Public Methods
  335. /// <inheritdoc/>
  336. public override void Assign(Base source)
  337. {
  338. base.Assign(source);
  339. PictureObjectBase src = source as PictureObjectBase;
  340. if (src != null)
  341. {
  342. imageLocation = src.ImageLocation;
  343. DataColumn = src.DataColumn;
  344. ImageSourceExpression = src.ImageSourceExpression;
  345. Padding = src.Padding;
  346. SizeMode = src.SizeMode;
  347. MaxWidth = src.MaxWidth;
  348. MaxHeight = src.MaxHeight;
  349. Angle = src.Angle;
  350. Grayscale = src.Grayscale;
  351. ShowErrorImage = src.ShowErrorImage;
  352. ImageAlign = src.ImageAlign;
  353. Shape = src.Shape;
  354. }
  355. }
  356. /// <summary>
  357. /// Calculates URI from ImageLocation
  358. /// </summary>
  359. /// <returns></returns>
  360. public Uri CalculateUri()
  361. {
  362. try
  363. {
  364. return new Uri(ImageLocation);
  365. }
  366. catch (UriFormatException)
  367. {
  368. // TODO
  369. // the problem with linux???? PATH!!!
  370. string path;
  371. if (!String.IsNullOrEmpty(Config.ReportSettings.ImageLocationRoot))
  372. path = Path.Combine(Config.ReportSettings.ImageLocationRoot, ImageLocation.Replace('/', '\\'));
  373. else
  374. path = Path.GetFullPath(ImageLocation);
  375. return new Uri(path);
  376. }
  377. }
  378. /// <inheritdoc/>
  379. public override void Draw(FRPaintEventArgs e)
  380. {
  381. UpdateAutoSize();
  382. base.Draw(e);
  383. DrawImage(e);
  384. DrawMarkers(e);
  385. Border.Draw(e, new RectangleF(AbsLeft, AbsTop, Width, Height));
  386. DrawDesign(e);
  387. }
  388. public abstract void DrawImage(FRPaintEventArgs e);
  389. /// <summary>
  390. /// gets points for transform this image
  391. /// </summary>
  392. /// <param name="drawRect">the box where to draw image</param>
  393. /// <param name="imageWidth">image width</param>
  394. /// <param name="imageHeight">image height</param>
  395. /// <param name="scaleX">scale horizontal</param>
  396. /// <param name="scaleY">scale vertical</param>
  397. /// <param name="offsetX">offset of left</param>
  398. /// <param name="offsetY">offset of top</param>
  399. /// <param name="upperLeft">out start of vectors</param>
  400. /// <param name="upperRight">out end of frist vector</param>
  401. /// <param name="lowerLeft">out end of second vector</param>
  402. public void GetImageAngleTransform(RectangleF drawRect, float imageWidth, float imageHeight, float scaleX, float scaleY, float offsetX, float offsetY, out PointF upperLeft, out PointF upperRight, out PointF lowerLeft)
  403. {
  404. RectangleF rect = drawRect;
  405. switch (SizeMode)
  406. {
  407. case PictureBoxSizeMode.Normal:
  408. case PictureBoxSizeMode.AutoSize:
  409. rect.Width = imageWidth * scaleX;
  410. rect.Height = imageHeight * scaleY;
  411. if (Angle == 90 || Angle == 180)
  412. rect.X -= rect.Width - drawRect.Width;
  413. if (Angle == 180)
  414. rect.Y -= rect.Height - drawRect.Height;
  415. break;
  416. case PictureBoxSizeMode.CenterImage:
  417. rect.Offset((Width - imageWidth) * scaleX / 2, (Height - imageHeight) * scaleY / 2);
  418. rect.Width = imageWidth * scaleX;
  419. rect.Height = imageHeight * scaleY;
  420. break;
  421. case PictureBoxSizeMode.StretchImage:
  422. break;
  423. case PictureBoxSizeMode.Zoom:
  424. /*float kx = drawRect.Width / imageWidth;
  425. float ky = drawRect.Height / imageHeight;
  426. if (kx < ky)
  427. rect.Height = imageHeight * kx;
  428. else
  429. rect.Width = imageWidth * ky;
  430. rect.Offset(
  431. (Width * e.ScaleX - rect.Width) / 2,
  432. (Height * e.ScaleY - rect.Height) / 2);*/
  433. break;
  434. }
  435. float gridCompensationX = offsetX + rect.X;
  436. gridCompensationX = (int)gridCompensationX - gridCompensationX;
  437. float gridCompensationY = offsetY + rect.Y;
  438. gridCompensationY = (int)gridCompensationY - gridCompensationY;
  439. if (gridCompensationX < 0)
  440. gridCompensationX = 1 + gridCompensationX;
  441. if (gridCompensationY < 0)
  442. gridCompensationY = 1 + gridCompensationY;
  443. rect.Offset(gridCompensationX, gridCompensationY);
  444. upperLeft = new PointF(0, 0);
  445. upperRight = new PointF(rect.Width, 0);
  446. lowerLeft = new PointF(0, rect.Height);
  447. float angle = Angle;
  448. switch (SizeMode)
  449. {
  450. case PictureBoxSizeMode.Normal:
  451. {
  452. upperLeft = MovePointOnAngle(drawRect.Location, drawRect.Size, Angle);
  453. PointF ur = rotateVector(upperRight, angle);
  454. PointF ll = rotateVector(lowerLeft, angle);
  455. upperRight = PointF.Add(upperLeft, new SizeF(ur));
  456. lowerLeft = PointF.Add(upperLeft, new SizeF(ll));
  457. }
  458. break;
  459. case PictureBoxSizeMode.StretchImage:
  460. {
  461. upperLeft = MovePointOnAngle(drawRect.Location, drawRect.Size, Angle);
  462. upperRight = MovePointOnAngle(
  463. drawRect.Location,
  464. drawRect.Size, Angle + 90);
  465. lowerLeft = MovePointOnAngle(
  466. drawRect.Location,
  467. drawRect.Size, Angle + 270);
  468. }
  469. break;
  470. case PictureBoxSizeMode.CenterImage:
  471. {
  472. PointF rotatedVector;
  473. float w = rect.Left - (drawRect.Left + drawRect.Width / 2);
  474. float h = rect.Top - (drawRect.Top + drawRect.Height / 2);
  475. rotatedVector = rotateVector(new PointF(w, h), Angle);
  476. upperLeft = new PointF(rect.Left + rotatedVector.X - w, rect.Top + rotatedVector.Y - h);
  477. rotatedVector = rotateVector(new PointF(rect.Width, 0), Angle);
  478. upperRight = new PointF(upperLeft.X + rotatedVector.X, upperLeft.Y + rotatedVector.Y);
  479. rotatedVector = rotateVector(new PointF(0, rect.Height), Angle);
  480. lowerLeft = new PointF(upperLeft.X + rotatedVector.X, upperLeft.Y + rotatedVector.Y);
  481. }
  482. break;
  483. case PictureBoxSizeMode.AutoSize:
  484. case PictureBoxSizeMode.Zoom:
  485. {
  486. rect = new RectangleF(0, 0, imageWidth * 100f, imageHeight * 100f);
  487. PointF center = new PointF(drawRect.Left + drawRect.Width / 2,
  488. drawRect.Top + drawRect.Height / 2);
  489. PointF[] p = new PointF[4];
  490. p[0] = new PointF(-rect.Width / 2, -rect.Height / 2);
  491. p[1] = new PointF(rect.Width / 2, -rect.Height / 2);
  492. p[2] = new PointF(rect.Width / 2, rect.Height / 2);
  493. p[3] = new PointF(-rect.Width / 2, rect.Height / 2);
  494. float scaleToMin = 1;
  495. for (int i = 0; i < 4; i++)
  496. p[i] = rotateVector(p[i], Angle);
  497. for (int i = 0; i < 4; i++)
  498. {
  499. if (p[i].X * scaleToMin < -drawRect.Width / 2)
  500. scaleToMin = -drawRect.Width / 2 / p[i].X;
  501. if (p[i].X * scaleToMin > drawRect.Width / 2)
  502. scaleToMin = drawRect.Width / 2 / p[i].X;
  503. if (p[i].Y * scaleToMin < -drawRect.Height / 2)
  504. scaleToMin = -drawRect.Height / 2 / p[i].Y;
  505. if (p[i].Y * scaleToMin > drawRect.Height / 2)
  506. scaleToMin = drawRect.Height / 2 / p[i].Y;
  507. }
  508. upperLeft = PointF.Add(center, new SizeF(p[0].X * scaleToMin, p[0].Y * scaleToMin));
  509. upperRight = PointF.Add(center, new SizeF(p[1].X * scaleToMin, p[1].Y * scaleToMin));
  510. lowerLeft = PointF.Add(center, new SizeF(p[3].X * scaleToMin, p[3].Y * scaleToMin));
  511. }
  512. break;
  513. }
  514. if (ImageAlign != ImageAlign.None)
  515. UpdateAlign(drawRect, ref upperLeft, ref upperRight, ref lowerLeft);
  516. /*switch (Angle)
  517. {
  518. case 90:
  519. upperLeft = new PointF(rect.Right, rect.Top);
  520. upperRight = new PointF(rect.Right, rect.Bottom);
  521. lowerLeft = new PointF(rect.Left, rect.Top);
  522. break;
  523. case 180:
  524. upperLeft = new PointF(rect.Right, rect.Bottom);
  525. upperRight = new PointF(rect.Left, rect.Bottom);
  526. lowerLeft = new PointF(rect.Right, rect.Top);
  527. break;
  528. case 270:
  529. upperLeft = new PointF(rect.Left, rect.Bottom);
  530. upperRight = new PointF(rect.Left, rect.Top);
  531. lowerLeft = new PointF(rect.Right, rect.Bottom);
  532. break;
  533. default:
  534. upperLeft = new PointF(rect.Left, rect.Top);
  535. upperRight = new PointF(rect.Right, rect.Top);
  536. lowerLeft = new PointF(rect.Left, rect.Bottom);
  537. break;
  538. }*/
  539. /* default:
  540. PointF rotatedVector;
  541. float w = rect.Left - (drawRect.Left + drawRect.Width / 2) ;
  542. float h = rect.Top - (drawRect.Top + drawRect.Height/2);
  543. rotatedVector = rotateVector(new PointF(w, h), Angle);
  544. upperLeft = new PointF(rect.Left + rotatedVector.X - w, rect.Top + rotatedVector.Y - h);
  545. rotatedVector = rotateVector(new PointF(rect.Width, 0), Angle);
  546. upperRight = new PointF(upperLeft.X + rotatedVector.X, upperLeft.Y + rotatedVector.Y);
  547. rotatedVector = rotateVector(new PointF(0, rect.Height), Angle);
  548. lowerLeft = new PointF(upperLeft.X + rotatedVector.X, upperLeft.Y + rotatedVector.Y);
  549. break;
  550. }*/
  551. }
  552. private void UpdateAlign(RectangleF drawRect, ref PointF upperLeft, ref PointF upperRight, ref PointF lowerLeft)
  553. {
  554. PointF lowerRight = new PointF(upperRight.X + lowerLeft.X - upperLeft.X,
  555. upperRight.Y + lowerLeft.Y - upperLeft.Y);
  556. float top = Math.Min(Math.Min(upperLeft.Y, Math.Min(upperRight.Y, lowerLeft.Y)), lowerRight.Y);
  557. float botom = Math.Max(Math.Max(upperLeft.Y, Math.Max(upperRight.Y, lowerLeft.Y)), lowerRight.Y);
  558. float height = botom - top;
  559. float offsetY = drawRect.Y - top;
  560. float left = Math.Min(Math.Min(upperLeft.X, Math.Min(upperRight.X, lowerLeft.X)), lowerRight.X);
  561. float right = Math.Max(Math.Max(upperLeft.X, Math.Max(upperRight.X, lowerLeft.X)), lowerRight.X);
  562. float width = right - left;
  563. float offsetX = drawRect.X - left;
  564. switch (ImageAlign)
  565. {
  566. case ImageAlign.Top_Left:
  567. break;
  568. case ImageAlign.Top_Center:
  569. offsetX += (drawRect.Width - width) / 2;
  570. break;
  571. case ImageAlign.Top_Right:
  572. offsetX += drawRect.Width - width;
  573. break;
  574. case ImageAlign.Center_Left:
  575. offsetY += (drawRect.Height - height) / 2;
  576. break;
  577. case ImageAlign.Center_Center:
  578. offsetX += (drawRect.Width - width) / 2;
  579. offsetY += (drawRect.Height - height) / 2;
  580. break;
  581. case ImageAlign.Center_Right:
  582. offsetX += drawRect.Width - width;
  583. offsetY += (drawRect.Height - height) / 2;
  584. break;
  585. case ImageAlign.Bottom_Left:
  586. offsetY += drawRect.Height - height;
  587. break;
  588. case ImageAlign.Bottom_Center:
  589. offsetX += (drawRect.Width - width) / 2;
  590. offsetY += drawRect.Height - height;
  591. break;
  592. case ImageAlign.Bottom_Right:
  593. offsetX += drawRect.Width - width;
  594. offsetY += drawRect.Height - height;
  595. break;
  596. }
  597. upperLeft.X += offsetX;
  598. upperRight.X += offsetX;
  599. lowerLeft.X += offsetX;
  600. upperLeft.Y += offsetY;
  601. upperRight.Y += offsetY;
  602. lowerLeft.Y += offsetY;
  603. }
  604. /// <summary>
  605. /// Loads image
  606. /// </summary>
  607. public abstract void LoadImage();
  608. /// <summary>
  609. /// Moves the point on specified angle
  610. /// </summary>
  611. /// <param name="p"></param>
  612. /// <param name="size"></param>
  613. /// <param name="fangle"></param>
  614. /// <returns></returns>
  615. public PointF MovePointOnAngle(PointF p, SizeF size, float fangle)
  616. {
  617. while (fangle >= 360) fangle -= 360;
  618. while (fangle < 0) fangle += 360;
  619. float x, y;
  620. if (fangle < 90)
  621. {
  622. x = fangle / 90f * size.Width;
  623. y = 0;
  624. }
  625. else if (fangle < 180)
  626. {
  627. x = size.Width;
  628. y = (fangle - 90f) / 90f * size.Height;
  629. }
  630. else if (fangle < 270)
  631. {
  632. x = size.Width - (fangle - 180f) / 90f * size.Width;
  633. y = size.Height;
  634. }
  635. else
  636. {
  637. x = 0;
  638. y = size.Height - (fangle - 270f) / 90f * size.Height;
  639. }
  640. return PointF.Add(p, new SizeF(x, y));
  641. }
  642. /// <inheritdoc/>
  643. public override void RestoreState()
  644. {
  645. base.RestoreState();
  646. // avoid UpdateAutoSize call, use sizeModeInternal
  647. sizeModeInternal = saveSizeMode;
  648. }
  649. /// <summary>
  650. /// Rotates vector on specified angle
  651. /// </summary>
  652. /// <param name="p"></param>
  653. /// <param name="fangle"></param>
  654. /// <returns></returns>
  655. public PointF rotateVector(PointF p, float fangle)
  656. {
  657. float angle = (float)(fangle / 180.0 * Math.PI);
  658. float ax = p.X;
  659. float ay = p.Y;
  660. float bx = ax * (float)Math.Cos(angle) - ay * (float)Math.Sin(angle);
  661. float by = ax * (float)Math.Sin(angle) + ay * (float)Math.Cos(angle);
  662. return new PointF(bx, by);
  663. }
  664. /// <inheritdoc/>
  665. public override void SaveState()
  666. {
  667. base.SaveState();
  668. saveSizeMode = SizeMode;
  669. }
  670. public override void Serialize(FRWriter writer)
  671. {
  672. PictureObjectBase c = writer.DiffObject as PictureObjectBase;
  673. base.Serialize(writer);
  674. if (writer.SerializeTo != SerializeTo.Preview
  675. && writer.SerializeTo != SerializeTo.SourcePages
  676. && ImageLocation != c.ImageLocation)
  677. writer.WriteStr("ImageLocation", ImageLocation);
  678. if (DataColumn != c.DataColumn)
  679. writer.WriteStr("DataColumn", DataColumn);
  680. if (ImageSourceExpression != c.ImageSourceExpression)
  681. writer.WriteStr("ImageSourceExpression", ImageSourceExpression);
  682. if (Padding != c.Padding)
  683. writer.WriteValue("Padding", Padding);
  684. if (SizeMode != c.SizeMode)
  685. writer.WriteValue("SizeMode", SizeMode);
  686. if (FloatDiff(MaxWidth, c.MaxWidth))
  687. writer.WriteFloat("MaxWidth", MaxWidth);
  688. if (FloatDiff(MaxHeight, c.MaxHeight))
  689. writer.WriteFloat("MaxHeight", MaxHeight);
  690. if (Angle != c.Angle)
  691. writer.WriteInt("Angle", Angle);
  692. if (Grayscale != c.Grayscale)
  693. writer.WriteBool("Grayscale", Grayscale);
  694. if (ShowErrorImage != c.ShowErrorImage)
  695. writer.WriteBool("ShowErrorImage", ShowErrorImage);
  696. if (ImageAlign != ImageAlign.None)
  697. writer.WriteValue("ImageAlign", ImageAlign);
  698. if (Shape != c.Shape)
  699. writer.WriteValue("Shape", Shape);
  700. }
  701. #endregion Public Methods
  702. #region Internal Methods
  703. /// <summary>
  704. /// Draws not tiled image
  705. /// </summary>
  706. /// <param name="e"></param>
  707. /// <param name="drawRect"></param>
  708. internal virtual void DrawImageInternal(FRPaintEventArgs e, RectangleF drawRect)
  709. {
  710. bool rotate = Angle == 90 || Angle == 270;
  711. float imageWidth = ImageWidth;//rotate ? Image.Height : Image.Width;
  712. float imageHeight = ImageHeight;//rotate ? Image.Width : Image.Height;
  713. PointF upperLeft;
  714. PointF upperRight;
  715. PointF lowerLeft;
  716. System.Drawing.Drawing2D.Matrix matrix = e.Graphics.Transform;
  717. GetImageAngleTransform(drawRect, imageWidth, imageHeight, e.ScaleX, e.ScaleY, matrix.OffsetX, matrix.OffsetY, out upperLeft, out upperRight, out lowerLeft);
  718. DrawImageInternal2(e.Graphics, upperLeft, upperRight, lowerLeft);
  719. }
  720. #endregion Internal Methods
  721. #region Protected Methods
  722. protected abstract void DrawImageInternal2(IGraphics graphics, PointF upperLeft, PointF upperRight, PointF lowerLeft);
  723. /// <summary>
  724. /// Reset index of image
  725. /// </summary>
  726. protected abstract void ResetImageIndex();
  727. /// <summary>
  728. /// When auto size was updated, internal use only
  729. /// </summary>
  730. protected void UpdateAutoSize()
  731. {
  732. if (SizeMode == PictureBoxSizeMode.AutoSize)
  733. {
  734. if (ImageWidth == 0 || ImageHeight == 0)
  735. {
  736. if (IsRunning && !IsPrinting)
  737. {
  738. Width = 0;
  739. Height = 0;
  740. }
  741. }
  742. else
  743. {
  744. //bool rotate = Angle == 90 || Angle == 270;
  745. //Width = (rotate ? Image.Height : Image.Width) + Padding.Horizontal;
  746. //Height = (rotate ? Image.Width : Image.Height) + Padding.Vertical;
  747. PointF[] p = new PointF[4];
  748. p[0] = new PointF(-ImageWidth / 2, -ImageHeight / 2);
  749. p[1] = new PointF(ImageWidth / 2, -ImageHeight / 2);
  750. p[2] = new PointF(ImageWidth / 2, ImageHeight / 2);
  751. p[3] = new PointF(-ImageWidth / 2, ImageHeight / 2);
  752. float minX = float.MaxValue;
  753. float maxX = float.MinValue;
  754. float minY = float.MaxValue;
  755. float maxY = float.MinValue;
  756. for (int i = 0; i < 4; i++)
  757. {
  758. p[i] = rotateVector(p[i], Angle);
  759. if (minX > p[i].X) minX = p[i].X;
  760. if (maxX < p[i].X) maxX = p[i].X;
  761. if (minY > p[i].Y) minY = p[i].Y;
  762. if (maxY < p[i].Y) maxY = p[i].Y;
  763. }
  764. Width = maxX - minX;
  765. Height = maxY - minY;
  766. // if width/height restrictions are set, use zoom mode to keep aspect ratio
  767. if (IsRunning && (MaxWidth != 0 || MaxHeight != 0))
  768. SizeMode = PictureBoxSizeMode.Zoom;
  769. }
  770. }
  771. }
  772. #endregion Protected Methods
  773. /// <inheritdoc/>
  774. public override string[] GetExpressions()
  775. {
  776. List<string> expressions = new List<string>();
  777. expressions.AddRange(base.GetExpressions());
  778. if (!String.IsNullOrEmpty(DataColumn))
  779. expressions.Add(DataColumn);
  780. if (!String.IsNullOrEmpty(ImageSourceExpression))
  781. {
  782. if (ImageSourceExpression.StartsWith("[") && ImageSourceExpression.EndsWith("]"))
  783. {
  784. expressions.Add(ImageSourceExpression.Substring(1, ImageSourceExpression.Length - 2));
  785. }
  786. else
  787. {
  788. expressions.Add(ImageSourceExpression);
  789. }
  790. }
  791. return expressions.ToArray();
  792. }
  793. }
  794. }