123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776 |
- {
- This file is part of the Free Component Library.
- Copyright (c) WISA b.v.b.a
- FPReport PDF export filter.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit fpreportpdfexport;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes,
- SysUtils,
- fpImage,
- fpreport,
- fpPDF;
- {$IF FPC_FULLVERSION>=30101}
- {$DEFINE PDF_HASISSTANDARDPDFFONT}
- {$DEFINE PDF_HASEXTERNALLINK}
- {$ENDIF}
- type
- TFPReportExportPDF = class(TFPReportExporter)
- private
- FCurrentPage: TPDFPage;
- FOptions: TPDFOptions;
- FPageLayout: TPDFPageLayout;
- FFileName: string;
- FDocument: TPDFDocument;
- FAutoSave: boolean;
- protected
- procedure RenderElement(pg: TPDFPage; ABand: TFPReportCustomBand; el: TFPReportElement); virtual;
- Procedure RenderImage(aRect : TFPReportRect; var AImage: TFPCustomImage) ; override;
- procedure DoExecute(const ARTObjects: TFPList); override;
- procedure SetupPDFDocument; virtual;
- procedure RenderFrame(const APage: TPDFPage; const ABand: TFPReportCustomBand; const AFrame: TFPReportFrame; const APos: TPDFCoord; const AWidth, AHeight: TFPReportUnits); virtual;
- procedure RenderMemo(const APage: TPDFPage; const ABand: TFPReportCustomBand; const AMemo: TFPReportCustomMemo); virtual;
- procedure RenderShape(const APage: TPDFPage; const ABand: TFPReportCustomBand; const AShape: TFPReportCustomShape); virtual;
- procedure RenderImage(const APage: TPDFPage; const ABand: TFPReportCustomBand; const AImage: TFPReportCustomImage); virtual;
- procedure RenderCheckbox(const APage: TPDFPage; const ABand: TFPReportCustomBand; const ACheckbox: TFPReportCustomCheckbox); virtual;
- procedure RenderShape(const APage: TPDFPage; const AOrigin: TPDFCoord; const AShape: TFPReportCustomShape); virtual;
- procedure RenderShapeCircle(const APage: TPDFPage; const lpt1: TPDFCoord; const ALayout: TFPReportLayout);
- procedure RenderShapeEllipse(const APage: TPDFPage; const lpt1: TPDFCoord; const ALayout: TFPReportLayout);
- procedure RenderShapeLine(const APage: TPDFPage; lpt1: TPDFCoord; const AOrientation: TFPReportOrientation; const ALayout: TFPReportLayout);
- procedure RenderShapeRect(const APage: TPDFPage; const lpt1: TPDFCoord; const ALayout: TFPReportLayout);
- procedure RenderShapeTriangle(const APage: TPDFPage; Alpt: TPDFCoord; const AOrientation: TFPReportOrientation; const ALayout: TFPReportLayout);
- procedure RenderShapeRoundedRect(const APage: TPDFPage; const lpt1: TPDFCoord; const ARadius: TFPReportUnits; const ALayout: TFPReportLayout);
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- Class Function Name : String; override;
- Class Function Description : String; override;
- Class Function DefaultExtension: String; override;
- Procedure SetFileName(const aFileName: String); override;
- function FindFontIndex(const ADoc: TPDFDocument; const AFontName: string): integer;
- procedure SaveToFile;
- property Document: TPDFDocument read FDocument;
- Property CurrentPage: TPDFPage Read FCurrentPage;
- published
- property AutoSave: boolean read FAutoSave write FAutoSave default True;
- property FileName: string read FFileName write FFileName;
- Property Options : TPDFOptions Read FOptions Write FOptions;
- property PageLayout : TPDFPageLayout read FPageLayout write FPageLayout default lSingle;
- end;
- implementation
- uses
- FPCanvas,
- fpTTF,
- fpparsettf;
- { TFPReportExportPDF }
- function TFPReportExportPDF.FindFontIndex(const ADoc: TPDFDocument; const AFontName: string): integer;
- function isStandardPdfFont: Boolean;
- begin
- {$IFDEF PDF_HASISSTANDARDPDFFONT}
- Result:=aDoc.IsStandardPDFFont(aFontName)
- {$ELSE}
- Result:=(AFontName='Courier') or (AFontName='Courier-Bold') or (AFontName='Courier-Oblique') or (AFontName='Courier-BoldOblique')
- or (AFontName='Helvetica') or (AFontName='Helvetica-Bold') or (AFontName='Helvetica-Oblique') or (AFontName='Helvetica-BoldOblique')
- or (AFontName='Times-Roman') or (AFontName='Times-Bold') or (AFontName='Times-Italic') or (AFontName='Times-BoldItalic')
- or (AFontName='Symbol')
- or (AFontName='ZapfDingbats');
- {$ENDIF}
- end;
- var
- i: integer;
- fnt: TFPFontCacheItem;
- begin
- Result := -1;
- for i := 0 to Document.Fonts.Count-1 do
- begin
- if Document.Fonts.FontDefs[i].Name = AFontName then
- begin
- Result := i;
- break;
- end;
- end; { for i ... }
- if Result = -1 then
- begin
- if IsStandardPDFFont then
- begin
- Result := Document.AddFont(AFontName);
- end
- else
- begin
- fnt := gTTFontCache.Find(AFontName); // we are doing a PostScript Name lookup (it contains Bold, Italic info)
- if not Assigned(fnt) then
- fnt:=gTTFontCache.FindFont(AFontName);
- if fnt=Nil then
- raise Exception.CreateFmt('fpreport: Could not find the font <%s> in the font cache.', [AFontName]);
- Result := Document.AddFont(fnt.FileName, AFontName)
- end;
- end;
- end;
- procedure TFPReportExportPDF.SetupPDFDocument;
- begin
- if Assigned(FDocument) then
- FDocument.Free;
- FDocument := TPDFDocument.Create(Nil);
- FDocument.Infos.Title := TFPReport(Report).Title;
- FDocument.Infos.Author := TFPReport(Report).Author;
- FDocument.Infos.ApplicationName := ApplicationName;
- FDocument.Infos.CreationDate := Now;
- FDocument.Options:=Self.Options;
- FDocument.PageLayout:=Self.PageLayout;
- FDocument.StartDocument;
- { we always need at least one section }
- FDocument.Sections.AddSection;
- end;
- procedure TFPReportExportPDF.SaveToFile;
- var
- F: TFileStream;
- begin
- if not Assigned(FDocument) then
- Exit;
- F := TFileStream.Create(FFileName, fmCreate);
- try
- FDocument.SaveToStream(F);
- finally
- F.Free;
- end;
- end;
- procedure TFPReportExportPDF.RenderFrame(const APage: TPDFPage; const ABand: TFPReportCustomBand;
- const AFrame: TFPReportFrame; const APos: TPDFCoord; const AWidth, AHeight: TFPReportUnits);
- var
- bStroke, bFill: boolean;
- begin
- bStroke := AFrame.Color <> clNone;
- bFill := AFrame.BackgroundColor <> clNone;
- // We only support TPDFPenStyle types. (ppsSolid,ppsDash,ppsDot,ppsDashDot,ppsDashDotDot)
- case AFrame.Pen of
- psSolid: APage.SetPenStyle(ppsSolid);
- psDash: APage.SetPenStyle(ppsDash);
- psDot: APage.SetPenStyle(ppsDot);
- psDashDot: APage.SetPenStyle(ppsDashDot);
- psDashDotDot: APage.SetPenStyle(ppsDashDotDot);
- // These FPCanvas pen styles are unsupported
- // psInsideFrame: ;
- // psPattern: ;
- // psClear: ;
- else
- // give a sane fallback for now
- APage.SetPenStyle(ppsSolid);
- end;
- if (AFrame.Shape = fsRectangle) and (bStroke or bFill) then
- begin
- APage.SetColor(AFrame.BackgroundColor, False); // fill color
- APage.SetColor(AFrame.Color, True); // stroke color
- APage.DrawRect(APos.X, APos.Y, AWidth, AHeight, AFrame.Width, bFill, bStroke);
- end;
- if AFrame.Shape = fsNone then
- begin
- if AFrame.Lines <> [] then
- begin
- APage.SetColor(AFrame.Color, True);
- APage.SetColor(AFrame.Color, False);
- end;
- { PDF origin coordinate is Bottom-Left, and Report Layout is Top-Left, so adjust them }
- if flTop in AFrame.Lines then
- APage.DrawLine(APos.X, APos.Y-AHeight, APos.X+AWidth, APos.Y-AHeight, AFrame.Width);
- if flBottom in AFrame.Lines then
- APage.DrawLine(APos.X, APos.Y, APos.X+AWidth, APos.Y, AFrame.Width);
- if flLeft in AFrame.Lines then
- APage.DrawLine(APos.X, APos.Y, APos.X, APos.Y-AHeight, AFrame.Width);
- if flRight in AFrame.Lines then
- APage.DrawLine(APos.X+AWidth, APos.Y, APos.X+AWidth, APos.Y-AHeight, AFrame.Width);
- end; { Frame.Shape = fsNone }
- end;
- procedure TFPReportExportPDF.RenderMemo(const APage: TPDFPage; const ABand: TFPReportCustomBand;
- const AMemo: TFPReportCustomMemo);
- var
- lPt1: TPDFCoord; // original Report point
- lFontIdx: integer;
- lMemo: TFPReportMemo;
- i: integer;
- lYPos: TPDFFloat;
- txtblk: TFPTextBlock;
- begin
- lMemo := TFPReportMemo(AMemo);
- { PDF origin coordinate is Bottom-Left, and Report Layout is Top-Left }
- lPt1.X := ABand.RTLayout.Left + AMemo.RTLayout.Left;
- lPt1.Y := ABand.RTLayout.Top + AMemo.RTLayout.Top + AMemo.RTLayout.Height;
- { Frame must be drawn before the text as it could have a fill color. }
- RenderFrame(APage, ABand, AMemo.Frame, lPt1, AMemo.RTLayout.Width, AMemo.RTLayout.Height);
- { Store the Top-Left coordinate of the Memo. We will be reusing this info. }
- lPt1.X := ABand.RTLayout.Left + AMemo.RTLayout.Left;
- lPt1.Y := ABand.RTLayout.Top + AMemo.RTLayout.Top;
- { render the TextBlocks as-is. }
- for i := 0 to lMemo.TextBlockList.Count-1 do
- begin
- txtblk := lMemo.TextBlockList[i];
- lFontIdx := FindFontIndex(Document, txtblk.FontName);
- APage.SetFont(lFontIdx, lMemo.Font.Size);
- { PDF origin coordinate is Bottom-Left, and Report Layout is Top-Left }
- lYPos := lPt1.Y + txtblk.Pos.Top + txtblk.Height;
- if txtblk.BGColor <> clNone then
- begin
- { draw highlighting background rectangle }
- APage.SetColor(txtblk.BGColor, false);
- APage.DrawRect(lPt1.X + txtblk.Pos.Left, lYPos+txtblk.Descender, txtblk.Width, txtblk.Height+(txtblk.Descender*2), 1.0, True, False);
- end;
- { Text color is always a fill color, hence the False parameter. }
- APage.SetColor(txtblk.FGColor, false);
- APage.WriteText(lPt1.X + txtblk.Pos.Left, lYPos, txtblk.Text);
- // process hyperlink if available
- if txtblk is TFPHTTPTextBlock then
- begin
- {$IFDEF PDF_HASEXTERNALLINK}
- APage.AddExternalLink(lPt1.X + txtblk.Pos.Left, lYPos, txtblk.Width, txtblk.Height, TFPHTTPTextBlock(txtblk).URL);
- {$ENDIF}
- end;
- end;
- end;
- procedure TFPReportExportPDF.RenderShape(const APage: TPDFPage; const ABand: TFPReportCustomBand;
- const AShape: TFPReportCustomShape);
- var
- lPt1: TPDFCoord; // original Report point
- begin
- APage.SetColor(clblack, True);
- APage.SetColor(clblack, False);
- { PDF origin coordinate is Bottom-Left, and Report Layout is Top-Left }
- lPt1.X := ABand.RTLayout.Left + AShape.RTLayout.Left;
- lPt1.Y := ABand.RTLayout.Top + AShape.RTLayout.Top + AShape.RTLayout.Height;
- { Frame must be drawn before the shape as it could have a fill color. }
- RenderFrame(APage, ABand, AShape.Frame, lPt1, AShape.RTLayout.Width, AShape.RTLayout.Height);
- { Only render shape when color is set and color is different to frame background color. }
- if (TFPReportShape(AShape).Color <> clNone) and
- (TFPReportShape(AShape).Color <> AShape.Frame.BackgroundColor) then
- RenderShape(APage, lPt1, AShape);
- end;
- type
- { for access to Protected methods }
- TReportImageFriend = class(TFPReportCustomImage);
- procedure TFPReportExportPDF.RenderImage(const APage: TPDFPage; const ABand: TFPReportCustomBand;
- const AImage: TFPReportCustomImage);
- var
- lPt: TPDFCoord;
- img: TReportImageFriend;
- idx, i: integer;
- pdfimg: TPDFImageItem;
- begin
- img := TReportImageFriend(AImage); { for access to Protected methods }
- lPt.X := ABand.RTLayout.Left + AImage.RTLayout.Left;
- { PDF origin coordinate is Bottom-Left, and Report Layout is Top-Left }
- lPt.Y := ABand.RTLayout.Top + AImage.RTLayout.Top + AImage.RTLayout.Height;
- { Frame must be drawn before the Image as it could have a fill color. }
- RenderFrame(APage, ABand, AImage.Frame, lPt, AImage.RTLayout.Width, AImage.RTLayout.Height);
- if not Assigned(img.Image) then
- Exit; { nothing further to do }
- idx := -1;
- for i := 0 to Document.Images.Count-1 do
- begin
- if Document.Images.Images[i].Equals(img.Image) then
- begin
- idx := i;
- break;
- end;
- end;
- if idx = -1 then
- begin
- pdfimg := Document.Images.AddImageItem;
- pdfimg.Image := img.Image;
- idx := Document.Images.Count-1;
- end;
- if img.Stretched then
- begin
- case APage.UnitOfMeasure of
- uomMillimeters:
- begin
- APage.DrawImage(lPt, AImage.RTLayout.Width, AImage.RTLayout.Height, idx);
- end;
- uomCentimeters:
- begin
- APage.DrawImage(lPt, AImage.RTLayout.Width, AImage.RTLayout.Height, idx);
- end;
- uomInches:
- begin
- APage.DrawImage(lPt, AImage.RTLayout.Width, AImage.RTLayout.Height, idx);
- end;
- uomPixels:
- begin
- APage.DrawImage(lPt, Integer(round(AImage.RTLayout.Width)), Integer(round(AImage.RTLayout.Height)), idx);
- end;
- end; { case UnitOfMeasure }
- end
- else
- APage.DrawImage(lPt, img.Image.Width, img.Image.Height, idx);
- end;
- procedure TFPReportExportPDF.RenderCheckbox(const APage: TPDFPage; const ABand: TFPReportCustomBand;
- const ACheckbox: TFPReportCustomCheckbox);
- var
- lPt: TPDFCoord;
- idx: integer;
- pdfimg: TPDFImageItem;
- lImage: TFPCustomImage;
- i: integer;
- begin
- lPt.X := ABand.RTLayout.Left + ACheckbox.RTLayout.Left;
- { PDF origin coordinate is Bottom-Left, and Report Layout is Top-Left }
- lPt.Y := ABand.RTLayout.Top + ACheckbox.RTLayout.Top + ACheckbox.RTLayout.Height;
- // { Frame must be drawn before the Image as it could have a fill color. }
- // RenderFrame(Document, APage, ABand, AImage.Frame, lPt, AImage.RTLayout.Width, AImage.RTLayout.Height);
- lImage:=ACheckBox.GetRTImage;
- idx := -1;
- for i := 0 to Document.Images.Count-1 do
- begin
- if Document.Images.Images[i].Equals(lImage) then
- begin
- idx := i;
- break;
- end;
- end;
- if idx = -1 then
- begin
- pdfimg := Document.Images.AddImageItem;
- pdfimg.Image := lImage;
- idx := Document.Images.Count-1;
- end;
- case APage.UnitOfMeasure of
- uomMillimeters:
- begin
- APage.DrawImage(lPt, ACheckBox.RTLayout.Width, ACheckBox.RTLayout.Height, idx);
- end;
- uomCentimeters:
- begin
- APage.DrawImage(lPt, ACheckBox.RTLayout.Width, ACheckBox.RTLayout.Height, idx);
- end;
- uomInches:
- begin
- APage.DrawImage(lPt, ACheckBox.RTLayout.Width, ACheckBox.RTLayout.Height, idx);
- end;
- uomPixels:
- begin
- APage.DrawImage(lPt, Integer(round(ACheckBox.RTLayout.Width)), Integer(round(ACheckBox.RTLayout.Height)), idx);
- end;
- end; { case UnitOfMeasure }
- end;
- procedure TFPReportExportPDF.RenderShape(const APage: TPDFPage; const AOrigin: TPDFCoord;
- const AShape: TFPReportCustomShape);
- begin
- APage.SetColor(TFPReportShape(AShape).Color, True);
- APage.SetColor(TFPReportShape(AShape).Color, False);
- case TFPReportShape(AShape).ShapeType of
- stEllipse: RenderShapeEllipse(APage, AOrigin, AShape.RTLayout);
- stCircle: RenderShapeCircle(APage, AOrigin, AShape.RTLayout);
- stLine: RenderShapeLine(APage, AOrigin, TFPReportShape(AShape).Orientation, AShape.RTLayout);
- stSquare: RenderShapeRect(APage, AOrigin, AShape.RTLayout);
- stTriangle: RenderShapeTriangle(APage, AOrigin, TFPReportShape(AShape).Orientation, AShape.RTLayout);
- stRoundedRect: RenderShapeRoundedRect(APage, AOrigin, TFPReportShape(AShape).CornerRadius, AShape.RTLayout);
- end;
- end;
- procedure TFPReportExportPDF.RenderShapeCircle(const APage: TPDFPage; const lpt1: TPDFCoord;
- const ALayout: TFPReportLayout);
- var
- lPt2: TPDFCoord;
- ldx, ldy, lw: TFPReportUnits;
- begin
- if ALayout.Width = ALayout.Height then
- begin
- ldx := 0;
- ldy := 0;
- lw := ALayout.Width;
- end
- else if ALayout.Width > ALayout.Height then
- begin
- ldx := (ALayout.Width - ALayout.Height) / 2;
- ldy := 0;
- lw := ALayout.Height;
- end
- else if ALayout.Width < ALayout.Height then
- begin
- ldx := 0;
- ldy := (ALayout.Height - ALayout.Width) / 2;
- lw := ALayout.Width;
- end;
- { PDF origin coordinate is Bottom-Left, and Report Layout is Top-Left }
- lPt2.X := lPt1.X + ldx;
- lPt2.Y := lPt1.Y - ldy;
- APage.DrawEllipse(lPt2, lw, lw, 1, False, True);
- end;
- procedure TFPReportExportPDF.RenderShapeEllipse(const APage: TPDFPage; const lpt1: TPDFCoord;
- const ALayout: TFPReportLayout);
- begin
- APage.DrawEllipse(lPt1, ALayout.Width, ALayout.Height, 1, False, True);
- end;
- procedure TFPReportExportPDF.RenderShapeLine(const APage: TPDFPage; lpt1: TPDFCoord;
- const AOrientation: TFPReportOrientation; const ALayout: TFPReportLayout);
- var
- lPt2: TPDFCoord;
- begin
- case AOrientation of
- orNorth, orSouth:
- begin // | (1)
- lPt1.X := lPt1.X + (ALayout.Width / 2); // |
- lPt2.X := lPt1.X ; // |
- lPt2.Y := lPt1.Y; // | (2)
- lPt1.Y := lPt1.Y - ALayout.Height;
- end;
- orNorthEast, orSouthWest:
- begin // / (1)
- lPt2.X := lPt1.X; // /
- lPt1.X := lPt1.X + ALayout.Width; // /
- lPt2.Y := lPt1.Y; // / (2)
- lPt1.Y := lPt1.Y - ALayout.Height;
- end;
- orEast, orWest:
- begin // (1) (2)
- lPt2.X := lPt1.X + ALayout.Width; // ----------
- lPt1.Y := lPt1.Y - (ALayout.Height / 2); //
- lPt2.Y := lPt1.Y; //
- end;
- orSouthEast, orNorthWest:
- begin
- lPt1.Y := lPt1.Y - ALayout.Height; // \ (1)
- lPt2.X := lPt1.X + ALayout.Width; // \
- lPt2.Y := lPt1.Y + ALayout.Height; // \
- end; // \ (2)
- end;
- APage.DrawLine(lPt1, lPt2, 1);
- end;
- procedure TFPReportExportPDF.RenderShapeRect(const APage: TPDFPage; const lpt1: TPDFCoord;
- const ALayout: TFPReportLayout);
- var
- ldx, ldy, lw: TFPReportUnits;
- P: TPDFCoord;
- begin
- if ALayout.Width = ALayout.Height then
- begin
- ldx := 0;
- ldy := 0;
- lw := ALayout.Width;
- end
- else if ALayout.Width > ALayout.Height then
- begin
- ldx := (ALayout.Width - ALayout.Height) / 2;
- ldy := 0;
- lw := ALayout.Height;
- end
- else if ALayout.Width < ALayout.Height then
- begin
- ldx := 0;
- ldy := (ALayout.Height - ALayout.Width) / 2;
- lw := ALayout.Width;
- end;
- P.X := lPt1.X + ldx;
- { PDF origin coordinate is Bottom-Left, and Report Layout is Top-Left }
- P.Y := lPt1.Y - ldy;
- APage.DrawRect(P, lw, lw, 1, False, True);
- end;
- procedure TFPReportExportPDF.RenderShapeTriangle(const APage: TPDFPage; Alpt: TPDFCoord;
- const AOrientation: TFPReportOrientation; const ALayout: TFPReportLayout);
- var
- lPt1, lPt2, lPt3: TPDFCoord; // original Report point
- lOrigin: TPDFCoord;
- W, H: TFPReportUnits;
- begin
- lOrigin.X := AlPt.X;
- lOrigin.Y := ALPT.Y - ALayout.Height;
- W:=ALayout.Width;
- H:=ALayout.Height;
- case AOrientation of
- orNorth:
- begin
- lPt1.X := lOrigin.X + (W / 2); // 1
- lPt1.Y := lOrigin.Y; // /\
- lPt2.X := lOrigin.X; // / \
- lPt2.Y := lOrigin.Y + H; // /____\
- lPt3.X := lOrigin.X + W; // 2 3
- lPt3.Y := lPt2.Y;
- end;
- orNorthEast:
- begin
- lPt1.X := lOrigin.X + (W ); // +-------1
- lPt1.Y := lOrigin.Y; // | |
- lPt2.X := lOrigin.X; // 2 |
- lPt2.Y := lOrigin.Y + H/2; // | |
- lPt3.X := lOrigin.X + W/2; // +---3---+
- lPt3.Y := lPt1.Y + H;
- end;
- orSouth:
- begin
- lPt1.X := lOrigin.X; // 1 ------ 2
- lPt1.Y := lOrigin.Y; // \ /
- lPt2.X := lOrigin.X+ W; // \ /
- lPt2.Y := lOrigin.Y; // \/
- lPt3.X := lOrigin.X + (W / 2); // 3
- lPt3.Y := lOrigin.Y+H;
- end;
- orSouthEast:
- begin
- lPt1.X := lOrigin.X + (W/2); // +---1---+
- lPt1.Y := lOrigin.Y; // | |
- lPt2.X := lOrigin.X; // 2 |
- lPt2.Y := lOrigin.Y + H/2; // | |
- lPt3.X := lOrigin.X + W; // +-------3
- lPt3.Y := lPt1.Y + H;
- end;
- orEast:
- begin
- lPt1.X := lOrigin.X; // 1
- lPt1.Y := lOrigin.Y ; // |\
- lPt2.X := lOrigin.X + W; // | \ 2
- lPt2.Y := lOrigin.Y + (H / 2); // | /
- lPt3.X := lOrigin.X; // |/
- lPt3.Y := lOrigin.Y + H; // 3
- end;
- orNorthWest:
- begin
- lPt1.X := lOrigin.X; // 1-------+
- lPt1.Y := lOrigin.Y; // | |
- lPt2.X := lOrigin.X+W; // | 2
- lPt2.Y := lOrigin.Y + H/2; // | |
- lPt3.X := lOrigin.X + W/2; // +---3---+
- lPt3.Y := lPt1.Y + H;
- end;
- orWest:
- begin
- lPt1.X := lOrigin.X + W; // 1
- lPt1.Y := lOrigin.Y; // /|
- lPt2.X := lOrigin.X; // 2 / |
- lPt2.Y := lOrigin.Y + H / 2; // \ |
- lPt3.X := lOrigin.X + W; // \|
- lPt3.Y := lOrigin.Y+ H; // 3
- end;
- orSouthWest:
- begin
- lPt1.X := lOrigin.X+ H/2; // +---1---+
- lPt1.Y := lOrigin.Y; // | |
- lPt2.X := lOrigin.X+W; // | 2
- lPt2.Y := lOrigin.Y + H/2; // | |
- lPt3.X := lOrigin.X ; // 3-------+
- lPt3.Y := lPt1.Y + H;
- end;
- end;
- APage.DrawLine(lPt1, lPt2, 1);
- APage.DrawLine(lPt2, lPt3, 1);
- APage.DrawLine(lPt3, lPt1, 1);
- end;
- procedure TFPReportExportPDF.RenderShapeRoundedRect(const APage: TPDFPage; const lpt1: TPDFCoord;
- const ARadius: TFPReportUnits; const ALayout: TFPReportLayout);
- begin
- end;
- constructor TFPReportExportPDF.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FDocument := nil;
- FFileName := ApplicationName + '.pdf';
- FAutoSave := True;
- end;
- destructor TFPReportExportPDF.Destroy;
- begin
- FDocument.Free;
- inherited Destroy;
- end;
- class function TFPReportExportPDF.Name: String;
- begin
- Result:='PDF';
- end;
- class function TFPReportExportPDF.Description: String;
- begin
- Result:='PDF file';
- end;
- class function TFPReportExportPDF.DefaultExtension: String;
- begin
- Result:='.pdf';
- end;
- procedure TFPReportExportPDF.SetFileName(const aFileName: String);
- begin
- Filename:=aFileName;
- end;
- procedure TFPReportExportPDF.RenderImage(aRect: TFPReportRect; var AImage: TFPCustomImage);
- var
- LPT : TPDFCoord;
- Idx : Integer;
- pdfimg: TPDFImageItem;
- begin
- LPT.X:=aRect.Left;
- LPT.Y:=aRect.Top;
- idx:=Document.Images.Count-1;
- While (Idx>=0) and not Document.Images.Images[idx].Equals(AImage) do
- Dec(Idx);
- if idx = -1 then
- begin
- pdfimg := Document.Images.AddImageItem;
- pdfimg.Image := AImage;
- pdfimg.OwnsImage:=True;
- idx := Document.Images.Count-1;
- end;
- CurrentPage.DrawImage(lPt, aRect.Width, ARect.Height, idx);
- aImage:=Nil; // PDF now owns the image
- end;
- procedure TFPReportExportPDF.DoExecute(const ARTObjects: TFPList);
- var
- pg: TPDFPage;
- p, b, m: integer;
- rpage: TFPReportPage;
- rband: TFPReportCustomBand;
- lPt1: TPDFCoord; // original Report point
- lPDFPaper: TPDFPaper;
- begin
- SetupPDFDocument;
- for p := 0 to (ARTObjects.Count - 1) do
- begin
- rpage := TFPReportPage(ARTObjects[p]);
- pg := FDocument.Pages.AddPage;
- FCurrentPage:=pg;
- case rpage.PageSize.PaperName of
- 'A4': pg.PaperType := ptA4;
- 'A5': pg.PaperType := ptA5;
- 'Letter': pg.PaperType := ptLetter;
- 'Legal': pg.PaperType := ptLegal;
- 'DL': pg.PaperType := ptDL;
- 'C5': pg.PaperType := ptC5;
- 'B5': pg.PaperType := ptB5
- else
- begin
- lPDFPaper.W := Round(mmToPDF(rpage.PageSize.Width));
- lPDFPaper.H := Round(mmToPDF(rpage.PageSize.Height));
- pg.Paper := lPDFPaper;
- pg.PaperType := ptCustom;
- end;
- end; { case PaperName }
- pg.UnitOfMeasure := uomMillimeters; { report measurements are always in millimeter units }
- // This must appear before configuring the pg.Matrix
- if rpage.Orientation = poLandscape then
- pg.Orientation := ppoLandscape;
- // Convert from the Cartesian coordinate system to the Screen coordinate system
- pg.Matrix.SetYScalation(-1);
- pg.Matrix.SetYTranslation(pg.GetPaperHeight);
- for b := 0 to (rpage.BandCount - 1) do
- begin
- rband := rpage.Bands[b];
- lPt1.X := rband.RTLayout.Left;
- { PDF origin coordinate is Bottom-Left, and Report Layout is Top-Left }
- lPt1.Y := rband.RTLayout.Top + rband.RTLayout.Height;
- RenderFrame(pg, rband, rband.Frame, lPt1, rband.RTLayout.Width, rband.RTLayout.Height);
- for m := 0 to (rband.ChildCount - 1) do
- RenderElement(pg, rband, rband.Child[m]);
- end;
- Document.Sections[0].AddPage(pg);
- end;
- if FAutoSave then
- SaveToFile;
- end;
- procedure TFPReportExportPDF.RenderElement(pg : TPDFPage; ABand : TFPReportCustomBand; el : TFPReportElement);
- Var
- C : TFPReportPoint;
- lpt : TPDFCoord;
- begin
- if (el is TFPReportCustomMemo) then
- RenderMemo(pg, aband, TFPReportCustomMemo(el))
- else if (el is TFPReportCustomShape) then
- RenderShape(pg, aband, TFPReportCustomShape(el))
- else if (el is TFPReportCustomImage) then
- RenderImage(pg, aband, TFPReportCustomImage(el))
- else if (el is TFPReportCustomCheckbox) then
- RenderCheckbox(pg, aband, TFPReportCustomCheckbox(el))
- else
- begin
- // PDF coords
- lPt.X := ABand.RTLayout.Left + el.RTLayout.Left;
- lPt.Y := ABand.RTLayout.Top + el.RTLayout.Top + el.RTLayout.Height;
- RenderFrame(pg, ABand, el.Frame, lPt, el.RTLayout.Width, el.RTLayout.Height);
- C.Left:=aband.RTLayout.Left;
- // Compensate for add of height which RenderUnknownElement will do
- C.Top:=aband.RTLayout.Top + el.RTLayout.Height;
- RenderUnknownElement(C,El,72);
- end;
- end;
- initialization
- TFPReportExportPDF.RegisterExporter;
- end.
|