reportpolygon.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. unit reportpolygon;
  2. {$mode objfpc}{$H+}
  3. {$DEFINE NATIVERENDERER}
  4. { $DEFINE EXPORTFPIMAGE}
  5. { $DEFINE EXPORTPDF}
  6. { $DEFINE EXPORTLCL}
  7. { $DEFINE EXPORTAGGPAS}
  8. { $DEFINE EXPORTFPGUI}
  9. interface
  10. uses
  11. Classes, fpReport, fpReportStreamer;
  12. Type
  13. { TReportPolygon }
  14. TReportPolygon = class(TFPReportElement)
  15. private
  16. FColor: TFPReportColor;
  17. FCorners: Cardinal;
  18. FLineWidth: Cardinal;
  19. FRotateAngle: Double;
  20. procedure SetCLineWidth(AValue: Cardinal);
  21. procedure SetCorners(AValue: Cardinal);
  22. Protected
  23. Procedure RecalcLayout; override;
  24. procedure DoWriteLocalProperties(AWriter: TFPReportStreamer; AOriginal: TFPReportElement = nil); override;
  25. public
  26. procedure ReadElement(AReader: TFPReportStreamer); override;
  27. Procedure Assign(Source: TPersistent); override;
  28. Published
  29. Property Corners : Cardinal Read FCorners Write SetCorners;
  30. Property LineWidth : Cardinal Read FLineWidth Write SetCLineWidth;
  31. Property Color : TFPReportColor Read FColor Write FColor;
  32. // In degrees
  33. Property RotateAngle : Double Read FRotateAngle Write FRotateAngle;
  34. end;
  35. implementation
  36. {$IF DEFINED(EXPORTFPGUI) or DEFINED(EXPORTAGGPAS)}
  37. {$DEFINE NEEDAGGPAS}
  38. {$ENDIF}
  39. uses
  40. {$IFDEF EXPORTPDF}
  41. fppdf,
  42. fpreportpdfexport,
  43. {$ENDIF}
  44. {$IFDEF EXPORTLCL}
  45. graphics,
  46. fpreportlclexport,
  47. {$ENDIF}
  48. {$IFDEF EXPORTFPIMAGE}
  49. fpreportfpimageexport,
  50. {$ENDIF}
  51. {$IFDEF EXPORTFPGUI}
  52. fpreport_export_fpgui,
  53. {$ENDIF}
  54. {$IFDEF NEEDAGGPAS}
  55. fpreportaggpasexport,
  56. agg_2D,
  57. {$ENDIF}
  58. sysutils, fpimage, fpcanvas, FPImgCanv;
  59. // Angle in degrees.
  60. {$IFDEF EXPORTLCL}
  61. Procedure LCLPaintPolygon(Canvas : TCanvas; ARect : Trect; ANumber : Integer; AStartAngle : Double; ALineWidth : Integer; AColor : TColor);
  62. Var
  63. CX,CY,R,I : Integer;
  64. P : Array of TPoint;
  65. A,Step : Double;
  66. AWidth,AHeight : Integer;
  67. begin
  68. AWidth:=ARect.Right-ARect.Left+1;
  69. AHeight:=ARect.Bottom-ARect.Top+1;
  70. Canvas.Pen.Color:=AColor;
  71. Canvas.Pen.style:=psSolid;
  72. Canvas.Pen.Width:=aLineWidth;
  73. if ANumber<3 then
  74. exit;
  75. CX:=ARect.Left+AWidth div 2;
  76. CY:=ARect.Top+AHeight div 2;
  77. if aWidth<aHeight then
  78. R:=AWidth div 2
  79. else
  80. R:=AHeight div 2;
  81. SetLength(P,ANumber);
  82. A:=AStartAngle;
  83. Step:=(2*Pi)/ANumber;
  84. For I:=0 to ANumber-1 do
  85. begin
  86. P[i].X:=CX+Round(R*Cos(a));
  87. P[i].Y:=CY-Round(R*Sin(a));
  88. A:=A+Step;
  89. end;
  90. For I:=0 to ANumber-2 do
  91. Canvas.Line(P[I],P[I+1]);
  92. Canvas.Line(P[ANumber-1],P[0]);
  93. end;
  94. Procedure RenderPolygonInLCL(AOffset : TFPReportPoint; E: TFPReportElement; RE : TFPReportExporter; ADPI : Integer);
  95. var
  96. PR : TFPReportExportCanvas;
  97. PG : TReportPolygon;
  98. R : Trect;
  99. rPt : TFPReportPoint;
  100. pt : TPoint;
  101. begin
  102. PR:=RE as TFPReportExportCanvas;
  103. PG:=E as TReportPolygon;
  104. rpt.Left:=AOffset.Left+E.RTLayout.Left;
  105. rpt.Top:=AOffset.Top+E.RTLayout.top;
  106. Pt:=PR.CoordToPoint(rpt,0,0);
  107. R.TopLeft:=pt;
  108. R.Right:=R.Left+PR.HmmToPixels(E.RTLayout.Width);
  109. R.Bottom:= R.Top+PR.VmmToPixels(E.RTLayout.Height);
  110. PR.Canvas.Brush.Color:=e.Frame.BackgroundColor;
  111. PR.Canvas.Brush.Style:=bsSolid;
  112. PR.Canvas.FillRect(R);
  113. LCLPaintPolygon(PR.Canvas,R,PG.Corners,PG.RotateAngle,PG.LineWidth,PR.RGBToBGR(PG.Color));
  114. end;
  115. {$ENDIF}
  116. {$IFDEF EXPORTPDF}
  117. Procedure RenderPolygonInPDF(AOffset : TFPReportPoint; E: TFPReportElement; RE : TFPReportExporter; ADPI : Integer);
  118. Var
  119. PR : TFPReportExportPDF;
  120. PG : TReportPolygon;
  121. C : TPDFCoord;
  122. I,ANumber : Integer;
  123. P : Array of TPDFCoord;
  124. R,A,Step : Double;
  125. APage: TPDFPage;
  126. begin
  127. PR:=RE as TFPReportExportPDF;
  128. PG:=E as TReportPolygon;
  129. APage:=PR.CurrentPage;
  130. ANumber:=PG.Corners;
  131. if ANumber<3 then
  132. exit;
  133. C.X:=AOffset.Left+E.RTLayout.Left+E.RTLayout.Width / 2;
  134. C.Y:=AOffset.Top+E.RTLayout.Top+E.RTLayout.Height / 2;
  135. if E.RTLayout.Width<E.RTLayout.Height then
  136. R:=E.RTLayout.Width / 2
  137. else
  138. R:=E.RTLayout.Height / 2;
  139. SetLength(P,ANumber);
  140. A:=PG.RotateAngle;
  141. Step:=(2*Pi)/ANumber;
  142. For I:=0 to ANumber-1 do
  143. begin
  144. P[i].X:=C.X+R*Cos(a);
  145. P[i].Y:=C.Y-R*Sin(a);
  146. A:=A+Step;
  147. end;
  148. APage.SetColor(PG.Color,True);
  149. // For I:=0 to ANumber-2 do
  150. // APage.DrawLine(P[I],P[I+1],PG.LineWidth,True);
  151. // aPage.DrawLine(P[ANumber-1],P[0],PG.LineWidth,True);
  152. APage.DrawPolyGon(P,PG.LineWidth);
  153. APage.StrokePath;
  154. end;
  155. {$ENDIF}
  156. function GetColorComponent(Var AColor: UInt32): Word;
  157. begin
  158. Result:=AColor and $FF;
  159. Result:=Result or (Result shl 8);
  160. AColor:=AColor shr 8;
  161. end;
  162. function ColorToRGBTriple(const AColor: UInt32): TFPColor;
  163. Var
  164. C : UInt32;
  165. begin
  166. C:=AColor;
  167. with Result do
  168. begin
  169. Blue := GetColorComponent(C);
  170. Green := GetColorComponent(C);
  171. Red := GetColorComponent(C);
  172. Alpha := GetColorComponent(C);
  173. end
  174. end;
  175. Procedure PaintPolygon(Canvas : TFPCustomCanvas; AOffset : TPoint; AWidth,AHeight : Integer; ANumber : Integer; AStartAngle : Double; ALineWidth : Integer; AColor : TFPColor);
  176. Var
  177. CX,CY,R,I : Integer;
  178. P : Array of TPoint;
  179. A,Step : Double;
  180. begin
  181. Canvas.Pen.FPColor:=AColor;
  182. Canvas.Pen.Width:=aLineWidth;
  183. Canvas.Pen.Style:=psSolid;
  184. if ANumber<3 then
  185. exit;
  186. CX:=AOffset.x+AWidth div 2;
  187. CY:=AOffset.y+AHeight div 2;
  188. if aWidth<aHeight then
  189. R:=AWidth div 2
  190. else
  191. R:=AHeight div 2;
  192. SetLength(P,ANumber);
  193. A:=AStartAngle;
  194. Step:=(2*Pi)/ANumber;
  195. For I:=0 to ANumber-1 do
  196. begin
  197. P[i].X:=CX+Round(R*Cos(a));
  198. P[i].Y:=CY-Round(R*Sin(a));
  199. A:=A+Step;
  200. end;
  201. For I:=0 to ANumber-2 do
  202. Canvas.Line(P[I],P[I+1]);
  203. Canvas.Line(P[ANumber-1],P[0]);
  204. SetLength(P,0);
  205. end;
  206. Procedure RenderPolygonToImage(aElement : TFPReportElement;AImage : TFPCustomImage);
  207. Var
  208. C : TFPImageCanvas;
  209. P : TReportPolygon;
  210. begin
  211. P:=AElement as TReportPolygon;
  212. C:=TFPImageCanvas.Create(AImage);
  213. try
  214. if (AElement.Frame.BackgroundColor<>fpreport.clNone) then
  215. begin
  216. C.Brush.FPColor:=ColorToRGBTriple(AElement.Frame.BackgroundColor);
  217. C.Brush.Style:=bsSolid;
  218. C.FillRect(0,0,AImage.Width-1,AImage.Height-1);
  219. end;
  220. PaintPolygon(C,Point(0,0),AImage.Width,AImage.Height,P.Corners,P.RotateAngle,P.linewidth,ColorToRGBTriple(P.Color));
  221. finally
  222. C.Free;
  223. end;
  224. end;
  225. {$IFDEF EXPORTFPIMAGE}
  226. Procedure RenderPolygonInFPImage(AOffset : TFPReportPoint; E: TFPReportElement; RE : TFPReportExporter; ADPI : Integer);
  227. Var
  228. PR : TFPReportExportFPImage;
  229. PG : TReportPolygon;
  230. R : TPoint;
  231. AWidth,AHeight : Integer;
  232. begin
  233. PR:=RE as TFPReportExportFPImage;
  234. PG:=E as TReportPolygon;
  235. R.X:=PR.mmToPixels(AOffset.Left+E.RTLayout.Left);
  236. R.Y:=PR.mmToPixels(AOffset.Top+E.RTLayout.Top);
  237. AWidth:=PR.mmToPixels(E.RTLayout.Width);
  238. AHeight:=PR.mmToPixels(E.RTLayout.Height);
  239. PaintPolygon(PR.Canvas,R,AWidth,AHeight, PG.Corners,PG.RotateAngle,PG.LineWidth,PR.ColorToRGBTriple(PG.Color));
  240. end;
  241. {$ENDIF}
  242. { TReportPolygon }
  243. procedure TReportPolygon.SetCLineWidth(AValue: Cardinal);
  244. begin
  245. If AValue<1 then
  246. AValue:=1;
  247. if FLineWidth=AValue then Exit;
  248. FLineWidth:=AValue;
  249. end;
  250. procedure TReportPolygon.SetCorners(AValue: Cardinal);
  251. begin
  252. If AValue<3 then
  253. AValue:=3;
  254. if FCorners=AValue then Exit;
  255. FCorners:=AValue;
  256. end;
  257. procedure TReportPolygon.RecalcLayout;
  258. begin
  259. // Do nothing
  260. end;
  261. procedure TReportPolygon.DoWriteLocalProperties(AWriter: TFPReportStreamer;
  262. AOriginal: TFPReportElement);
  263. Var
  264. P : TReportPolygon;
  265. begin
  266. inherited DoWriteLocalProperties(AWriter, AOriginal);
  267. if AOriginal is TReportPolygon then
  268. begin
  269. P:=AOriginal as TReportPolygon;
  270. AWriter.WriteIntegerDiff('Color', Color, P.Color);
  271. AWriter.WriteIntegerDiff('Corners',Corners,P.Color);
  272. AWriter.WriteIntegerDiff('LineWidth',LineWidth,P.LineWidth);
  273. AWriter.WriteFloatDiff('RotateAngle',RotateAngle,P.RotateAngle);
  274. end
  275. else
  276. begin
  277. AWriter.WriteInteger('Color', Color);
  278. AWriter.WriteInteger('Corners',Corners);
  279. AWriter.WriteInteger('LineWidth',LineWidth);
  280. AWriter.WriteFloat('RotateAngle',RotateAngle);
  281. end;
  282. end;
  283. procedure TReportPolygon.ReadElement(AReader: TFPReportStreamer);
  284. begin
  285. inherited ReadElement(AReader);
  286. Color:= AReader.ReadInteger('Color', clBlack);
  287. Corners:=AReader.ReadInteger('Corners',3);
  288. LineWidth:=AReader.ReadInteger('LineWidth',1);
  289. RotateAngle:=AReader.ReadFloat('RotateAngle',0);
  290. end;
  291. procedure TReportPolygon.Assign(Source: TPersistent);
  292. Var
  293. P : TReportPolygon;
  294. begin
  295. if (Source is TReportPolygon) then
  296. begin
  297. P:=Source as TReportPolygon;
  298. Corners:=P.Corners;
  299. Color:=P.Color;
  300. LineWidth:=P.LineWidth;
  301. RotateAngle:=P.RotateAngle;
  302. end;
  303. inherited Assign(Source);
  304. end;
  305. {$IFDEF EXPORTFPGUI}
  306. Procedure AggPasPaintPolygon(Ex: TFPReportExportAggPas; ARect : TFPReportRect; ANumber : Integer; AStartAngle : Double; ALineWidth : Integer; AColor : TRGBTriple);
  307. Var
  308. C : TFPReportPoint;
  309. I : Integer;
  310. P : Array of TFPReportPoint;
  311. R,A,Step : Double;
  312. AWidth,AHeight : Double;
  313. begin
  314. ex.Agg.noFill;
  315. ex.Agg.lineColor(aColor.Red, aColor.Green, aColor.Blue);
  316. ex.Agg.lineWidth(aLineWidth);
  317. if ANumber<3 then
  318. exit;
  319. AWidth:=ARect.Width;
  320. AHeight:=ARect.Height;
  321. C.Left:=ARect.Left+AWidth / 2;
  322. C.Top:=ARect.Top+AHeight / 2;
  323. if aWidth<aHeight then
  324. R:=AWidth / 2
  325. else
  326. R:=AHeight / 2;
  327. SetLength(P,ANumber);
  328. A:=AStartAngle;
  329. Step:=(2*Pi)/ANumber;
  330. For I:=0 to ANumber-1 do
  331. begin
  332. P[i].Left:=Ex.mmToPixels(C.Left+R*Cos(a));
  333. P[i].Top:=Ex.mmToPixels(C.Top-R*Sin(a));
  334. A:=A+Step;
  335. end;
  336. For I:=0 to ANumber-2 do
  337. ex.agg.Line(P[I].Left,P[i].Top,P[I+1].Left,P[I+1].Top);
  338. ex.agg.Line(P[ANumber-1].Left,P[ANumber-1].Top,P[0].Left,P[0].Top);
  339. end;
  340. Procedure RenderPolygonInAggPas(AOffset : TFPReportPoint; E: TFPReportElement; RE : TFPReportExporter; ADPI : Integer);
  341. var
  342. PR : TFPReportExportAggPas;
  343. PG : TReportPolygon;
  344. rPt : TFPReportRect;
  345. begin
  346. PR:=RE as TFPReportExportAggPas;
  347. PG:=E as TReportPolygon;
  348. rpt.Left:=AOffset.Left+E.RTLayout.Left;
  349. rpt.Top:=AOffset.Top+E.RTLayout.top;
  350. Rpt.Width:=E.RTLayout.Width;
  351. Rpt.Height:=E.RTLayout.Height;
  352. AggPasPaintPolygon(PR,rpt,PG.Corners,PG.RotateAngle,PG.LineWidth,PR.ColorToRGBTriple(PG.Color));
  353. end;
  354. {$ENDIF}
  355. begin
  356. gElementFactory.RegisterClass('Polygon',TReportPolygon);
  357. // Fallback renderer
  358. gElementFactory.RegisterImageRenderer(TReportPolygon,@RenderPolygonToImage);
  359. {$IFDEF NATIVERENDERER}
  360. {$IFDEF EXPORTPDF}
  361. gElementFactory.RegisterElementRenderer(TReportPolygon,TFPReportExportPDF,@RenderPolygonInPDF);
  362. {$ENDIF}
  363. {$IFDEF EXPORTFPIMAGE}
  364. gElementFactory.RegisterElementRenderer(TReportPolygon,TFPReportExportfpImage,@RenderPolygonInFPImage);
  365. {$ENDIF}
  366. {$IFDEF EXPORTLCL}
  367. gElementFactory.RegisterElementRenderer(TReportPolygon,TFPReportExportCanvas,@RenderPolygonInLCL);
  368. {$ENDIF}
  369. {$IFDEF EXPORTFPGUI}
  370. gElementFactory.RegisterElementRenderer(TReportPolygon,TFPReportExportAggPas,@RenderPolygonInAggPas);
  371. gElementFactory.RegisterElementRenderer(TReportPolygon,TFPReportExportCanvas,@RenderPolygonInAggPas);
  372. {$ENDIF}
  373. {$ENDIF}
  374. end.