PictureObjectBase.cs 32 KB

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