PictureObject.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.ComponentModel;
  5. using System.Drawing.Drawing2D;
  6. using System.IO;
  7. using System.Drawing.Imaging;
  8. using FastReport.Utils;
  9. using System.Windows.Forms;
  10. using System.Drawing.Design;
  11. namespace FastReport
  12. {
  13. /// <summary>
  14. /// Represents a Picture object that can display pictures.
  15. /// </summary>
  16. /// <remarks>
  17. /// The Picture object can display the following kind of pictures:
  18. /// <list type="bullet">
  19. /// <item>
  20. /// <description>picture that is embedded in the report file. Use the <see cref="Image"/>
  21. /// property to do this;</description>
  22. /// </item>
  23. /// <item>
  24. /// <description>picture that is stored in the database BLOb field. Use the <see cref="DataColumn"/>
  25. /// property to specify the name of data column you want to show;</description>
  26. /// </item>
  27. /// <item>
  28. /// <description>picture that is stored in the local disk file. Use the <see cref="ImageLocation"/>
  29. /// property to specify the name of the file;</description>
  30. /// </item>
  31. /// <item>
  32. /// <description>picture that is stored in the Web. Use the <see cref="ImageLocation"/>
  33. /// property to specify the picture's URL.</description>
  34. /// </item>
  35. /// </list>
  36. /// <para/>Use the <see cref="SizeMode"/> property to specify a size mode. The <see cref="MaxWidth"/>
  37. /// and <see cref="MaxHeight"/> properties can be used to restrict the image size if <b>SizeMode</b>
  38. /// is set to <b>AutoSize</b>.
  39. /// <para/>The <see cref="TransparentColor"/> property can be used to display an image with
  40. /// transparent background. Use the <see cref="Transparency"/> property if you want to display
  41. /// semi-transparent image.
  42. /// </remarks>
  43. public partial class PictureObject : PictureObjectBase
  44. {
  45. #region Fields
  46. private Image image;
  47. private int imageIndex;
  48. private Color transparentColor;
  49. private float transparency;
  50. private bool tile;
  51. private Bitmap transparentImage;
  52. private byte[] imageData;
  53. private bool shouldDisposeImage;
  54. private Bitmap grayscaleBitmap;
  55. private int grayscaleHash;
  56. private ImageFormat imageFormat;
  57. #endregion
  58. #region Properties
  59. /// <summary>
  60. /// Gets or sets the image.
  61. /// </summary>
  62. /// <remarks>
  63. /// By default, image that you assign to this property is never disposed - you should
  64. /// take care about it. If you want to dispose the image when this <b>PictureObject</b> is disposed,
  65. /// set the <see cref="ShouldDisposeImage"/> property to <b>true</b> right after you assign an image:
  66. /// <code>
  67. /// myPictureObject.Image = new Bitmap("file.bmp");
  68. /// myPictureObject.ShouldDisposeImage = true;
  69. /// </code>
  70. /// </remarks>
  71. [Category("Data")]
  72. [Editor("FastReport.TypeEditors.ImageEditor, FastReport", typeof(UITypeEditor))]
  73. public virtual Image Image
  74. {
  75. get { return image; }
  76. set
  77. {
  78. image = value;
  79. imageData = null;
  80. UpdateAutoSize();
  81. UpdateTransparentImage();
  82. ResetImageIndex();
  83. imageFormat = CheckImageFormat();
  84. ShouldDisposeImage = false;
  85. }
  86. }
  87. /// <summary>
  88. /// Gets or sets the extension of image.
  89. /// </summary>
  90. [Category("Data")]
  91. public virtual ImageFormat ImageFormat
  92. {
  93. get { return imageFormat; }
  94. set
  95. {
  96. if (image == null)
  97. return;
  98. bool wasC = false;
  99. using (MemoryStream stream = new MemoryStream())
  100. {
  101. wasC = ImageHelper.SaveAndConvert(Image, stream, value);
  102. imageData = stream.ToArray();
  103. }
  104. if (!wasC)
  105. return;
  106. ForceLoadImage();
  107. imageFormat = CheckImageFormat();
  108. }
  109. }
  110. /// <summary>
  111. /// Gets or sets a value indicating that the image should be displayed in grayscale mode.
  112. /// </summary>
  113. [DefaultValue(false)]
  114. [Category("Appearance")]
  115. public override bool Grayscale
  116. {
  117. get { return base.Grayscale; }
  118. set
  119. {
  120. base.Grayscale = value;
  121. if (!value && grayscaleBitmap != null)
  122. {
  123. grayscaleBitmap.Dispose();
  124. grayscaleBitmap = null;
  125. }
  126. }
  127. }
  128. /// <summary>
  129. /// Gets or sets a hash of grayscale svg image
  130. /// </summary>
  131. [Browsable(false)]
  132. public int GrayscaleHash
  133. {
  134. get { return grayscaleHash; }
  135. set { grayscaleHash = value; }
  136. }
  137. /// <summary>
  138. /// Gets or sets the color of the image that will be treated as transparent.
  139. /// </summary>
  140. [Category("Appearance")]
  141. [Editor("FastReport.TypeEditors.ColorEditor, FastReport", typeof(UITypeEditor))]
  142. public Color TransparentColor
  143. {
  144. get { return transparentColor; }
  145. set
  146. {
  147. transparentColor = value;
  148. UpdateTransparentImage();
  149. }
  150. }
  151. /// <summary>
  152. /// Gets or sets the transparency of the PictureObject.
  153. /// </summary>
  154. /// <remarks>
  155. /// Valid range of values is 0..1. Default value is 0.
  156. /// </remarks>
  157. [DefaultValue(0f)]
  158. [Category("Appearance")]
  159. public float Transparency
  160. {
  161. get { return transparency; }
  162. set
  163. {
  164. if (value < 0)
  165. value = 0;
  166. if (value > 1)
  167. value = 1;
  168. transparency = value;
  169. UpdateTransparentImage();
  170. }
  171. }
  172. /// <summary>
  173. /// Gets or sets a value indicating that the image should be tiled.
  174. /// </summary>
  175. [DefaultValue(false)]
  176. [Category("Appearance")]
  177. public bool Tile
  178. {
  179. get { return tile; }
  180. set { tile = value; }
  181. }
  182. /// <summary>
  183. /// Gets or sets a value indicating that the image stored in the <see cref="Image"/>
  184. /// property should be disposed when this object is disposed.
  185. /// </summary>
  186. /// <remarks>
  187. /// By default, image assigned to the <see cref="Image"/> property is never disposed - you should
  188. /// take care about it. If you want to dispose the image when this <b>PictureObject</b> is disposed,
  189. /// set this property to <b>true</b> right after you assign an image to the <see cref="Image"/> property.
  190. /// </remarks>
  191. [Browsable(false)]
  192. public bool ShouldDisposeImage
  193. {
  194. get { return shouldDisposeImage; }
  195. set { shouldDisposeImage = value; }
  196. }
  197. /// <summary>
  198. /// Gets or sets a bitmap transparent image
  199. /// </summary>
  200. [Browsable(false)]
  201. public Bitmap TransparentImage
  202. {
  203. get { return transparentImage; }
  204. set { transparentImage = value; }
  205. }
  206. /// <inheritdoc/>
  207. [Browsable(false)]
  208. protected override float ImageWidth
  209. {
  210. get
  211. {
  212. if (Image == null) return 0;
  213. return Image.Width;
  214. }
  215. }
  216. /// <inheritdoc/>
  217. [Browsable(false)]
  218. protected override float ImageHeight
  219. {
  220. get
  221. {
  222. if (Image == null) return 0;
  223. return Image.Height;
  224. }
  225. }
  226. #endregion
  227. #region Private Methods
  228. private ImageFormat CheckImageFormat()
  229. {
  230. if (Image == null || Image.RawFormat == null)
  231. return null;
  232. ImageFormat format = null;
  233. if (ImageFormat.Jpeg.Equals(image.RawFormat))
  234. {
  235. format = ImageFormat.Jpeg;
  236. }
  237. else if (ImageFormat.Gif.Equals(image.RawFormat))
  238. {
  239. format = ImageFormat.Gif;
  240. }
  241. else if (ImageFormat.Png.Equals(image.RawFormat))
  242. {
  243. format = ImageFormat.Png;
  244. }
  245. else if (ImageFormat.Emf.Equals(image.RawFormat))
  246. {
  247. format = ImageFormat.Emf;
  248. }
  249. else if (ImageFormat.Icon.Equals(image.RawFormat))
  250. {
  251. format = ImageFormat.Icon;
  252. }
  253. else if (ImageFormat.Tiff.Equals(image.RawFormat))
  254. {
  255. format = ImageFormat.Tiff;
  256. }
  257. else if (ImageFormat.Bmp.Equals(image.RawFormat) || ImageFormat.MemoryBmp.Equals(image.RawFormat))
  258. {
  259. format = ImageFormat.Bmp;
  260. }
  261. else if (ImageFormat.Wmf.Equals(image.RawFormat))
  262. {
  263. format = ImageFormat.Wmf;
  264. }
  265. if (format != null)
  266. return format;
  267. return ImageFormat.Bmp;
  268. }
  269. private void UpdateTransparentImage()
  270. {
  271. if (transparentImage != null)
  272. transparentImage.Dispose();
  273. transparentImage = null;
  274. if (Image is Bitmap)
  275. {
  276. if (TransparentColor != Color.Transparent)
  277. {
  278. transparentImage = new Bitmap(Image);
  279. transparentImage.MakeTransparent(TransparentColor);
  280. }
  281. else if (Transparency != 0)
  282. {
  283. transparentImage = ImageHelper.GetTransparentBitmap(Image, Transparency);
  284. }
  285. }
  286. }
  287. #if MONO
  288. private GraphicsPath GetRoundRectPath(RectangleF rectangleF, float radius)
  289. {
  290. GraphicsPath gp = new GraphicsPath();
  291. if (radius < 1)
  292. radius = 1;
  293. gp.AddLine(rectangleF.X + radius, rectangleF.Y, rectangleF.Width + rectangleF.X - radius, rectangleF.Y);
  294. gp.AddArc(rectangleF.Width + rectangleF.X - radius - 1, rectangleF.Y, radius + 1, radius + 1, 270, 90);
  295. gp.AddLine(rectangleF.Width + rectangleF.X, rectangleF.Y + radius, rectangleF.Width + rectangleF.X, rectangleF.Height + rectangleF.Y - radius);
  296. gp.AddArc(rectangleF.Width + rectangleF.X - radius - 1, rectangleF.Height + rectangleF.Y - radius - 1, radius + 1, radius + 1, 0, 90);
  297. gp.AddLine(rectangleF.Width + rectangleF.X - radius, rectangleF.Height + rectangleF.Y, rectangleF.X + radius, rectangleF.Height + rectangleF.Y);
  298. gp.AddArc(rectangleF.X, rectangleF.Height + rectangleF.Y - radius - 1, radius + 1, radius + 1, 90, 90);
  299. gp.AddLine(rectangleF.X, rectangleF.Height + rectangleF.Y - radius, rectangleF.X, rectangleF.Y + radius);
  300. gp.AddArc(rectangleF.X, rectangleF.Y, radius, radius, 180, 90);
  301. gp.CloseFigure();
  302. return gp;
  303. }
  304. #else
  305. private GraphicsPath GetRoundRectPath(RectangleF rectangleF, float radius)
  306. {
  307. GraphicsPath gp = new GraphicsPath();
  308. if (radius < 1)
  309. radius = 1;
  310. gp.AddArc(rectangleF.Width + rectangleF.X - radius - 1, rectangleF.Y, radius + 1, radius + 1, 270, 90);
  311. gp.AddArc(rectangleF.Width + rectangleF.X - radius - 1, rectangleF.Height + rectangleF.Y - radius - 1, radius + 1, radius + 1, 0, 90);
  312. gp.AddArc(rectangleF.X, rectangleF.Height + rectangleF.Y - radius - 1, radius + 1, radius + 1, 90, 90);
  313. gp.AddArc(rectangleF.X, rectangleF.Y, radius, radius, 180, 90);
  314. gp.CloseFigure();
  315. return gp;
  316. }
  317. #endif
  318. #endregion
  319. #region Protected Methods
  320. /// <inheritdoc/>
  321. protected override void Dispose(bool disposing)
  322. {
  323. if (disposing)
  324. DisposeImage();
  325. base.Dispose(disposing);
  326. }
  327. #endregion
  328. #region Public Methods
  329. /// <inheritdoc/>
  330. public override void Assign(Base source)
  331. {
  332. base.Assign(source);
  333. PictureObject src = source as PictureObject;
  334. if (src != null)
  335. {
  336. TransparentColor = src.TransparentColor;
  337. Transparency = src.Transparency;
  338. Tile = src.Tile;
  339. Image = src.Image == null ? null : src.Image.Clone() as Image;
  340. if (src.Image == null && src.imageData != null)
  341. imageData = src.imageData;
  342. ShouldDisposeImage = true;
  343. ImageFormat = src.ImageFormat;
  344. }
  345. }
  346. /// <summary>
  347. /// Draws the image.
  348. /// </summary>
  349. /// <param name="e">Paint event args.</param>
  350. public override void DrawImage(FRPaintEventArgs e)
  351. {
  352. IGraphics g = e.Graphics;
  353. if (Image == null)
  354. ForceLoadImage();
  355. if (Image == null)
  356. {
  357. DrawErrorImage(g, e);
  358. return;
  359. }
  360. float drawLeft = (AbsLeft + Padding.Left) * e.ScaleX;
  361. float drawTop = (AbsTop + Padding.Top) * e.ScaleY;
  362. float drawWidth = (Width - Padding.Horizontal) * e.ScaleX;
  363. float drawHeight = (Height - Padding.Vertical) * e.ScaleY;
  364. RectangleF drawRect = new RectangleF(
  365. drawLeft,
  366. drawTop,
  367. drawWidth,
  368. drawHeight);
  369. GraphicsPath path = new GraphicsPath();
  370. IGraphicsState state = g.Save();
  371. try
  372. {
  373. //if (Config.IsRunningOnMono) // strange behavior of mono - we need to reset clip before we set new one
  374. g.ResetClip();
  375. EstablishImageForm(path, drawLeft, drawTop, drawWidth, drawHeight);
  376. g.SetClip(path, CombineMode.Replace);
  377. Report report = Report;
  378. if (report != null && report.SmoothGraphics)
  379. {
  380. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
  381. g.SmoothingMode = SmoothingMode.AntiAlias;
  382. }
  383. if (!Tile)
  384. DrawImageInternal(e, drawRect);
  385. else
  386. {
  387. float y = drawRect.Top;
  388. float width = Image.Width * e.ScaleX;
  389. float height = Image.Height * e.ScaleY;
  390. while (y < drawRect.Bottom)
  391. {
  392. float x = drawRect.Left;
  393. while (x < drawRect.Right)
  394. {
  395. if (transparentImage != null)
  396. g.DrawImage(transparentImage, x, y, width, height);
  397. else
  398. g.DrawImage(Image, x, y, width, height);
  399. x += width;
  400. }
  401. y += height;
  402. }
  403. }
  404. }
  405. finally
  406. {
  407. g.Restore(state);
  408. g.ResetClip();
  409. #if !SKIA
  410. path.Dispose();
  411. #else
  412. path = null;
  413. #endif
  414. }
  415. if (IsPrinting)
  416. {
  417. DisposeImage();
  418. }
  419. }
  420. protected override void DrawImageInternal2(IGraphics graphics, PointF upperLeft, PointF upperRight, PointF lowerLeft)
  421. {
  422. Image image = transparentImage != null ? transparentImage.Clone() as Image : Image.Clone() as Image;
  423. if (image == null)
  424. return;
  425. if (Grayscale)
  426. {
  427. if (grayscaleHash != image.GetHashCode() || grayscaleBitmap == null)
  428. {
  429. if (grayscaleBitmap != null)
  430. grayscaleBitmap.Dispose();
  431. grayscaleBitmap = ImageHelper.GetGrayscaleBitmap(image);
  432. grayscaleHash = image.GetHashCode();
  433. }
  434. image = grayscaleBitmap;
  435. }
  436. //graphics.DrawImage(image, new PointF[] { upperLeft, upperRight, lowerLeft });
  437. DrawImage3Points(graphics, image, upperLeft, upperRight, lowerLeft);
  438. image.Dispose();
  439. }
  440. // This is analogue of graphics.DrawImage(image, PointF[] points) method.
  441. // The original gdi+ method does not work properly in mono on linux/macos.
  442. private void DrawImage3Points(IGraphics g, Image image, PointF p0, PointF p1, PointF p2)
  443. {
  444. // Skip drawing image, when height or width of the image equal zero.
  445. if (image == null || image.Width == 0 || image.Height == 0)
  446. return;
  447. // Skip drawing image, when height or width of the parallelogram for drawing equal zero.
  448. if (p0 == p1 || p0 == p2)
  449. return;
  450. RectangleF rect = new RectangleF(0, 0, image.Width, image.Height);
  451. float m11 = (p1.X - p0.X) / rect.Width;
  452. float m12 = (p1.Y - p0.Y) / rect.Width;
  453. float m21 = (p2.X - p0.X) / rect.Height;
  454. float m22 = (p2.Y - p0.Y) / rect.Height;
  455. g.MultiplyTransform(new System.Drawing.Drawing2D.Matrix(m11, m12, m21, m22, p0.X, p0.Y), MatrixOrder.Prepend);
  456. g.DrawImage(image, rect);
  457. }
  458. /// <summary>
  459. /// Sets image data to FImageData
  460. /// </summary>
  461. /// <param name="data"></param>
  462. public void SetImageData(byte[] data)
  463. {
  464. imageData = data;
  465. // if autosize is on, load the image.
  466. if (SizeMode == PictureBoxSizeMode.AutoSize)
  467. ForceLoadImage();
  468. }
  469. /// <inheritdoc/>
  470. public override void Serialize(FRWriter writer)
  471. {
  472. PictureObject c = writer.DiffObject as PictureObject;
  473. base.Serialize(writer);
  474. #if PRINT_HOUSE
  475. writer.WriteStr("ImageLocation", ImageLocation);
  476. #endif
  477. if (TransparentColor != c.TransparentColor)
  478. writer.WriteValue("TransparentColor", TransparentColor);
  479. if (FloatDiff(Transparency, c.Transparency))
  480. writer.WriteFloat("Transparency", Transparency);
  481. if (Tile != c.Tile)
  482. writer.WriteBool("Tile", Tile);
  483. if (ImageFormat != c.ImageFormat)
  484. writer.WriteValue("ImageFormat", ImageFormat);
  485. // store image data
  486. if (writer.SerializeTo != SerializeTo.SourcePages)
  487. {
  488. if (writer.SerializeTo == SerializeTo.Preview ||
  489. (String.IsNullOrEmpty(ImageLocation) && String.IsNullOrEmpty(DataColumn)))
  490. {
  491. if (writer.BlobStore != null)
  492. {
  493. // check FImageIndex >= writer.BlobStore.Count is needed when we close the designer
  494. // and run it again, the BlobStore is empty, but FImageIndex is pointing to
  495. // previous BlobStore item and is not -1.
  496. if (imageIndex == -1 || imageIndex >= writer.BlobStore.Count)
  497. {
  498. byte[] bytes = imageData;
  499. if (bytes == null)
  500. {
  501. using (MemoryStream stream = new MemoryStream())
  502. {
  503. ImageHelper.Save(Image, stream, imageFormat);
  504. bytes = stream.ToArray();
  505. }
  506. }
  507. if (bytes != null)
  508. {
  509. string imgHash = BitConverter.ToString(new Murmur3().ComputeHash(bytes));
  510. imageIndex = writer.BlobStore.AddOrUpdate(bytes, imgHash);
  511. }
  512. }
  513. }
  514. else
  515. {
  516. if (Image == null && imageData != null)
  517. writer.WriteStr("Image", Convert.ToBase64String(imageData));
  518. else if (!writer.AreEqual(Image, c.Image))
  519. writer.WriteValue("Image", Image);
  520. }
  521. if (writer.BlobStore != null || writer.SerializeTo == SerializeTo.Undo)
  522. writer.WriteInt("ImageIndex", imageIndex);
  523. }
  524. }
  525. }
  526. /// <inheritdoc/>
  527. public override void Deserialize(FRReader reader)
  528. {
  529. base.Deserialize(reader);
  530. if (reader.HasProperty("ImageIndex"))
  531. {
  532. imageIndex = reader.ReadInt("ImageIndex");
  533. if (reader.BlobStore != null && imageIndex != -1)
  534. {
  535. //int saveIndex = FImageIndex;
  536. //Image = ImageHelper.Load(reader.BlobStore.Get(FImageIndex));
  537. //FImageIndex = saveIndex;
  538. SetImageData(reader.BlobStore.Get(imageIndex));
  539. }
  540. }
  541. }
  542. /// <summary>
  543. /// Loads image
  544. /// </summary>
  545. public override void LoadImage()
  546. {
  547. if (!String.IsNullOrEmpty(ImageLocation))
  548. {
  549. //
  550. try
  551. {
  552. Uri uri = CalculateUri();
  553. if (uri.IsFile)
  554. SetImageData(ImageHelper.Load(uri.LocalPath));
  555. else
  556. SetImageData(ImageHelper.LoadURL(uri.ToString()));
  557. }
  558. catch
  559. {
  560. Image = null;
  561. }
  562. ShouldDisposeImage = true;
  563. }
  564. }
  565. /// <summary>
  566. /// Disposes image
  567. /// </summary>
  568. public void DisposeImage()
  569. {
  570. if (Image != null && ShouldDisposeImage)
  571. Image.Dispose();
  572. Image = null;
  573. }
  574. protected override void ResetImageIndex()
  575. {
  576. imageIndex = -1;
  577. }
  578. /// <summary>
  579. /// The shape of the image is set using GraphicsPath
  580. /// </summary>
  581. /// <param name="path"></param>
  582. /// <param name="drawLeft"></param>
  583. /// <param name="drawTop"></param>
  584. /// <param name="drawWidth"></param>
  585. /// <param name="drawHeight"></param>
  586. public void EstablishImageForm(GraphicsPath path, float drawLeft, float drawTop, float drawWidth, float drawHeight)
  587. {
  588. RectangleF drawRect = new RectangleF(
  589. drawLeft,
  590. drawTop,
  591. drawWidth,
  592. drawHeight);
  593. switch (Shape)
  594. {
  595. case ShapeKind.Rectangle:
  596. path.AddRectangle(drawRect);
  597. break;
  598. case ShapeKind.RoundRectangle:
  599. float min = Math.Min(drawWidth, drawHeight) / 4;
  600. path.AddPath(GetRoundRectPath(drawRect, min), false);
  601. break;
  602. case ShapeKind.Ellipse:
  603. path.AddEllipse(drawLeft, drawTop, drawWidth, drawHeight);
  604. break;
  605. case ShapeKind.Triangle:
  606. PointF[] triPoints =
  607. {
  608. new PointF(drawLeft + drawWidth, drawTop + drawHeight), new PointF(drawLeft, drawTop + drawHeight),
  609. new PointF(drawLeft + drawWidth / 2, drawTop), new PointF(drawLeft + drawWidth, drawTop + drawHeight)
  610. };
  611. path.AddPolygon(triPoints);
  612. break;
  613. case ShapeKind.Diamond:
  614. PointF[] diaPoints =
  615. {
  616. new PointF(drawLeft + drawWidth / 2, drawTop), new PointF(drawLeft + drawWidth, drawTop + drawHeight / 2),
  617. new PointF(drawLeft + drawWidth / 2, drawTop + drawHeight), new PointF(drawLeft, drawTop + drawHeight / 2)
  618. };
  619. path.AddPolygon(diaPoints);
  620. break;
  621. }
  622. }
  623. #endregion
  624. #region Report Engine
  625. /// <inheritdoc/>
  626. public override void InitializeComponent()
  627. {
  628. base.InitializeComponent();
  629. ResetImageIndex();
  630. }
  631. /// <inheritdoc/>
  632. public override void FinalizeComponent()
  633. {
  634. base.FinalizeComponent();
  635. ResetImageIndex();
  636. }
  637. /// <inheritdoc/>
  638. public override void GetData()
  639. {
  640. base.GetData();
  641. if (!String.IsNullOrEmpty(DataColumn))
  642. {
  643. // reset the image
  644. Image = null;
  645. imageData = null;
  646. object data = Report.GetColumnValueNullable(DataColumn);
  647. if (data is byte[])
  648. {
  649. SetImageData((byte[])data);
  650. }
  651. else if (data is Image)
  652. {
  653. Image = data as Image;
  654. }
  655. else if (data is string)
  656. {
  657. ImageLocation = data.ToString();
  658. }
  659. }
  660. }
  661. /// <summary>
  662. /// Forces loading the image from a data column.
  663. /// </summary>
  664. /// <remarks>
  665. /// Call this method in the <b>AfterData</b> event handler to force loading an image
  666. /// into the <see cref="Image"/> property. Normally, the image is stored internally as byte[] array
  667. /// and never loaded into the <b>Image</b> property, to save the time. The side effect is that you
  668. /// can't analyze the image properties such as width and height. If you need this, call this method
  669. /// before you access the <b>Image</b> property. Note that this will significantly slow down the report.
  670. /// </remarks>
  671. public void ForceLoadImage()
  672. {
  673. if (imageData == null)
  674. return;
  675. byte[] saveImageData = imageData;
  676. // FImageData will be reset after this line, keep it
  677. Image = ImageHelper.Load(imageData);
  678. imageData = saveImageData;
  679. ShouldDisposeImage = true;
  680. }
  681. #endregion
  682. /// <summary>
  683. /// Initializes a new instance of the <see cref="PictureObject"/> class with default settings.
  684. /// </summary>
  685. public PictureObject()
  686. {
  687. transparentColor = Color.Transparent;
  688. SetFlags(Flags.HasSmartTag, true);
  689. ResetImageIndex();
  690. }
  691. }
  692. }