LazReport: Added a PDF exporter using fcl-pdf, from Aleksey Lagunov

git-svn-id: trunk@52919 -
This commit is contained in:
jesus 2016-09-05 17:55:46 +00:00
parent 444a926616
commit 6db7447b69
14 changed files with 3227 additions and 0 deletions

13
.gitattributes vendored
View File

@ -2727,6 +2727,19 @@ components/lazreport/source/addons/lrEmailExport/lremailappthebat.pas svneol=nat
components/lazreport/source/addons/lrEmailExport/lremailexport.lpk svneol=native#text/plain
components/lazreport/source/addons/lrEmailExport/lremailexport.pas svneol=native#text/pascal
components/lazreport/source/addons/lrEmailExport/lremailexport.res -text
components/lazreport/source/addons/lrFclPDFExport/demo/aaa.lrf svneol=LF#text/xml eol=lf
components/lazreport/source/addons/lrFclPDFExport/demo/project1.ico -text
components/lazreport/source/addons/lrFclPDFExport/demo/project1.lpi svneol=native#text/plain
components/lazreport/source/addons/lrFclPDFExport/demo/project1.lpr svneol=native#text/pascal
components/lazreport/source/addons/lrFclPDFExport/demo/project1.res -text
components/lazreport/source/addons/lrFclPDFExport/demo/unit1.lfm svneol=native#text/plain
components/lazreport/source/addons/lrFclPDFExport/demo/unit1.pas svneol=native#text/pascal
components/lazreport/source/addons/lrFclPDFExport/lr_e_fclpdf.pas svneol=native#text/pascal
components/lazreport/source/addons/lrFclPDFExport/lr_pdfexport.lpk svneol=native#text/plain
components/lazreport/source/addons/lrFclPDFExport/lr_pdfexport.pas svneol=native#text/pascal
components/lazreport/source/addons/lrFclPDFExport/lrpdfexport.pas svneol=native#text/pascal
components/lazreport/source/addons/lrFclPDFExport/lrpdfexport_icon.lrs svneol=native#text/plain
components/lazreport/source/addons/lrFclPDFExport/resources/TlrPDFExport.png -text svneol=unset#image/png
components/lazreport/source/addons/lrOfficeImport/lr_officeimport.lpk svneol=native#text/plain
components/lazreport/source/addons/lrOfficeImport/lr_officeimport.pas svneol=native#text/pascal
components/lazreport/source/addons/lrOfficeImport/lr_officeimport_img.res -text

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<General>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="project1"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="3">
<Item1>
<PackageName Value="lr_pdfexport"/>
</Item1>
<Item2>
<PackageName Value="lazreport"/>
</Item2>
<Item3>
<PackageName Value="LCL"/>
</Item3>
</RequiredPackages>
<Units Count="2">
<Unit0>
<Filename Value="project1.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="unit1.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="Unit1"/>
</Unit1>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="project1"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="4">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
<Item4>
<Name Value="ETTF"/>
</Item4>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,20 @@
program project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, Unit1;
{$R *.res}
begin
RequireDerivedFormResource:=True;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@ -0,0 +1,92 @@
object Form1: TForm1
Left = 501
Height = 378
Top = 408
Width = 570
Caption = 'Form1'
ClientHeight = 378
ClientWidth = 570
OnCreate = FormCreate
LCLVersion = '1.7'
object Button1: TButton
AnchorSideLeft.Control = Owner
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = Owner
AnchorSideTop.Side = asrCenter
Left = 234
Height = 36
Top = 171
Width = 103
AutoSize = True
Caption = 'Design report'
OnClick = Button1Click
TabOrder = 0
end
object Button2: TButton
AnchorSideLeft.Control = Owner
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = Button1
AnchorSideTop.Side = asrBottom
Left = 211
Height = 36
Top = 213
Width = 149
AutoSize = True
BorderSpacing.Top = 6
Caption = 'Export report to PDF'
OnClick = Button2Click
TabOrder = 1
end
object Button3: TButton
AnchorSideLeft.Control = Owner
AnchorSideLeft.Side = asrCenter
AnchorSideTop.Side = asrCenter
AnchorSideBottom.Control = Button1
Left = 237
Height = 36
Top = 129
Width = 96
Anchors = [akLeft, akBottom]
AutoSize = True
BorderSpacing.Bottom = 6
Caption = 'Show report'
OnClick = Button3Click
TabOrder = 2
end
object frReport1: TfrReport
InitialZoom = pzDefault
Options = []
PreviewButtons = [pbZoom, pbLoad, pbSave, pbPrint, pbFind, pbHelp, pbExit]
DataType = dtDataSet
left = 80
top = 41
end
object lrPDFExport1: TlrPDFExport
left = 250
top = 41
end
object frDesigner1: TfrDesigner
left = 33
top = 37
end
object frRoundRectObject1: TfrRoundRectObject
left = 458
top = 44
end
object frBarCodeObject1: TfrBarCodeObject
left = 498
top = 43
end
object frShapeObject1: TfrShapeObject
left = 28
top = 104
end
object frCheckBoxObject1: TfrCheckBoxObject
left = 74
top = 103
end
object lrCrossObject1: TlrCrossObject
left = 140
top = 98
end
end

View File

@ -0,0 +1,77 @@
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, LR_Class, LR_Desgn, LR_RRect,
LR_BarC, LR_Shape, LR_ChBox, lr_CrossTab,
lrPDFExport, Forms, Controls, Graphics, Dialogs, StdCtrls,
LazFileUtils;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
frBarCodeObject1: TfrBarCodeObject;
frCheckBoxObject1: TfrCheckBoxObject;
frDesigner1: TfrDesigner;
frReport1: TfrReport;
frRoundRectObject1: TfrRoundRectObject;
frShapeObject1: TfrShapeObject;
lrCrossObject1: TlrCrossObject;
lrPDFExport1: TlrPDFExport;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
FFileName:string;
public
end;
var
Form1: TForm1;
implementation
uses lr_e_fclpdf, LCLIntf;
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button2Click(Sender: TObject);
var
S: String;
begin
S:=AppendPathDelim(ExtractFileDir(ParamStr(0))) + 'aaa1.pdf';
frReport1.PrepareReport;
frReport1.ExportTo(TlrPdfExportFilter, S);
OpenDocument(S);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
frReport1.ShowReport;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FFileName:=AppendPathDelim(ExtractFileDir(ParamStr(0))) + 'aaa.lrf';
if FileExistsUTF8(FFileName) then
frReport1.LoadFromFile(FFileName);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
frReport1.DesignReport;
end;
end.

View File

@ -0,0 +1,977 @@
{
LazReport PDF export
Copyright (C) 2016 alexs alexs75.at.yandex.ru
The module is designed to create an image of the report with the exact
positioning of objects and subsequent binding to the worksheet
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version with the following modification:
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent modules,and
to copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the terms
and conditions of the license of that module. An independent module is a
module which is not derived from or based on this library. If you modify
this library, you may extend this exception to your version of the library,
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
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. See the GNU Library General Public License
for more details.
You should have received a copy of the GNU Library General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
}
unit lr_e_fclpdf;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LR_Class, LR_ChBox, LR_BarC, LR_Shape, LR_RRect, fpPDF, Graphics, fpTTF;
type
TExportFonts = class;
TlrPdfExportFilter = class;
{ TExportFontItem }
TExportFontItem = class
private
FFontColor: TColor;
FFontName: string;
FFontSize: Integer;
FFontStyle: TFontStyles;
FOwner:TExportFonts;
FDefaultFont: boolean;
//
FPdfFont:integer;
FTTFFontInfo: TFPFontCacheItem;
function GetBold: boolean;
function GetItalic: boolean;
procedure SetFontSize(AValue: Integer);
//
function TextWidth(const AText: utf8string) : single;
function TextHeight(const AText: utf8string) : single;
public
constructor Create(AOwner:TExportFonts; AFontName:string; AFontStyle: TFontStyles);
destructor Destroy; override;
procedure Activate;
property FontStyle: TFontStyles read FFontStyle;
property FontSize:Integer read FFontSize write SetFontSize;
property FontColor:TColor read FFontColor write FFontColor;
property Bold:boolean read GetBold;
property Italic:boolean read GetItalic;
property DefaultFont:boolean read FDefaultFont;
property FontName:string read FFontName;
end;
{ TExportFonts }
TExportFonts = class
private
//FDefaultFontBold: TExportFontItem;
FDefaultFontNormal: TExportFontItem;
FOwner:TlrPdfExportFilter;
FList:TFPList;
function GetCount: integer;
function GetItem(Index: integer): TExportFontItem;
public
constructor Create(AOwner:TlrPdfExportFilter);
destructor Destroy; override;
procedure Clear;
function AddItem(AFontName: string; AFontStyle:TFontStyles = []): TExportFontItem;
function FindItem(AFontName: string; AFontStyle:TFontStyles = []):TExportFontItem;
property DefaultFontNormal:TExportFontItem read FDefaultFontNormal;
//property DefaultFontBold:TExportFontItem read FDefaultFontBold;
property Count:integer read GetCount;
property Item[Index:integer]:TExportFontItem read GetItem;
end;
{ TlrPdfExportFilter }
TlrPdfExportFilter = class(TfrExportFilter)
private
FPDFDocument: TPDFDocument;
FCurSection: TPDFSection;
FCurPageNo : integer;
FCurPage: TPDFPage;
FFontItems:TExportFonts;
FCurFont: TExportFontItem;
procedure SetupFonts;
procedure InitFonts;
private
InternalGapX:integer;
InternalGapY:integer;
procedure WriteTextRectJustify(AExportFont: TExportFontItem; X, Y, W, H: TPDFFloat; const Text: string; Trimmed: boolean);
procedure WriteTextRect(AExportFont:TExportFontItem; X, Y, W{, H}:TPDFFloat; AText:string; AHAlign:TAlignment);
procedure DrawRect(X, Y, W, H: TPDFFloat; ABorderColor, AFillColor: TColor;
AFrames: TfrFrameBorders; ABorderWidth: TPDFFloat);
procedure DrawRectView(AView: TfrView);
procedure WriteURL(X, Y, W, H: TPDFFloat; AUrlText:string);
procedure DrawLine(X1, Y1, X2, Y2: TPDFFloat; ABorderColor: TColor; ABorderWidth: TPDFFloat);
procedure DrawEllipse(X, Y, W, H: TPDFFloat; ABorderColor, AFillColor: TColor;
AFrames: TfrFrameBorders; ABorderWidth: TPDFFloat);
procedure DrawImage(X, Y, W, H: integer; ABmp:TBitmap);
procedure DrawLRObjectInternal(View:TfrView);
private
procedure DoMemoView(View:TfrMemoView);
procedure DoImageView(View:TfrPictureView);
procedure DoLineView(View:TfrLineView);
procedure DoCheckBoxView(View:TfrCheckBoxView);
procedure DoShapeView(View:TfrShapeView);
procedure DoBarCodeView(View:TfrCustomBarCodeView);
procedure DoRoundRectView(View:TfrRoundRectView);
public
constructor Create(AStream: TStream); override;
destructor Destroy; override;
procedure OnBeginDoc; override;
procedure OnEndDoc; override;
procedure OnBeginPage; override;
procedure OnEndPage; override;
procedure OnData(x, y: Integer; View: TfrView); override;
procedure OnText({%H-}x, {%H-}y: Integer; const {%H-}Text: String; {%H-}View: TfrView); override;
procedure OnExported({%H-}x, {%H-}y: Integer; {%H-}View: TfrView); override;
end;
implementation
uses Forms, LR_Utils, LazUTF8, Printers, FPReadBMP, FPReadPNG, FPReadJPEG;
const
cInchToMM = 25.4;
function ConvetUnits(AUnits:TPDFFloat):TPDFFloat; inline;
begin
Result := (AUnits * cInchToMM) / gTTFontCache.DPI;
end;
function ConvetUnits1(AUnits:TPDFFloat):TPDFFloat; inline;
begin
Result:= AUnits * gTTFontCache.DPI / cInchToMM;
end;
function ColorToPdfColor(C:Graphics.TColor):TARGBColor;
var
A:array [1..4] of byte absolute C;
begin
if C = clWindow then
Result:=clWhite
else
Result:={A[1] shl 24 +} A[1] shl 16 + A[2] shl 8 + A[3];
end;
type
TfrHackView = class(TfrView);
{ TExportFonts }
function TExportFonts.GetCount: integer;
begin
Result:=FList.Count;
end;
function TExportFonts.GetItem(Index: integer): TExportFontItem;
begin
Result:=TExportFontItem(FList[Index]);
end;
constructor TExportFonts.Create(AOwner: TlrPdfExportFilter);
begin
inherited Create;
FOwner:=AOwner;
FList:=TFPList.Create;
end;
destructor TExportFonts.Destroy;
begin
Clear;
FreeAndNil(FList);
inherited Destroy;
end;
procedure TExportFonts.Clear;
var
I: Integer;
begin
for I:=0 to FList.Count-1 do
TExportFontItem(FList[i]).Free;
FList.Clear;
end;
function TExportFonts.AddItem(AFontName: string; AFontStyle: TFontStyles
): TExportFontItem;
var
S1, S2, S3: String;
begin
Result:=FindItem(AFontName, AFontStyle);
if Assigned(Result) then exit;
if Assigned(gTTFontCache.Find(AFontName, Graphics.fsBold in AFontStyle, Graphics.fsItalic in AFontStyle)) then
begin
Result:=TExportFontItem.Create(Self, AFontName, AFontStyle);
S1:=ExtractFileDir(Result.FTTFFontInfo.FileName);
S2:=ExtractFileName(Result.FTTFFontInfo.FileName);
S3:=AFontName;
FOwner.FPDFDocument.FontDirectory:=S1;
Result.FPdfFont:=FOwner.FPDFDocument.AddFont(S2, S3);
end
else
Result:=FDefaultFontNormal;
end;
function TExportFonts.FindItem(AFontName: string; AFontStyle: TFontStyles
): TExportFontItem;
var
K: TExportFontItem;
i: Integer;
begin
Result:=nil;
if AFontName = 'default' then
begin
{ if Graphics.fsBold in AFontStyle then
Result:=FDefaultFontBold
else}
Result:=FDefaultFontNormal;
end
else
begin
for i:=0 to FList.Count-1 do
begin
K:=TExportFontItem(FList[i]);
if (K.FontName = AFontName) and (K.FontStyle = AFontStyle) then
begin
Result:=K;
exit;
end
end;
end;
end;
{ TExportFontItem }
function TExportFontItem.GetBold: boolean;
begin
Result:=Graphics.fsBold in FFontStyle;
end;
function TExportFontItem.GetItalic: boolean;
begin
Result:=Graphics.fsItalic in FFontStyle;
end;
procedure TExportFontItem.SetFontSize(AValue: Integer);
begin
if AValue = 0 then
FFontSize:=10
else
FFontSize:=AValue;
end;
function TExportFontItem.TextWidth(const AText: utf8string): single;
begin
Result:=ConvetUnits(FTTFFontInfo.TextWidth(AText, FFontSize));
end;
function TExportFontItem.TextHeight(const AText: utf8string): single;
var
ADescender: single;
begin
Result:=FTTFFontInfo.TextHeight(AText, FFontSize, ADescender);
Result:=ConvetUnits(Result + ADescender);
{ FTH:=ConvetUnits(AExportFont.FTTFFontInfo.TextHeight(AText, AExportFont.FontSize, ADescender));
FTH:=FTH + ConvetUnits(ADescender);}
end;
constructor TExportFontItem.Create(AOwner: TExportFonts; AFontName: string;
AFontStyle: TFontStyles);
begin
inherited Create;
FOwner:=AOwner;
FOwner.FList.Add(Self);
FFontStyle:=AFontStyle;
FFontName:=AFontName;
FTTFFontInfo:=gTTFontCache.Find(AFontName, Graphics.fsBold in AFontStyle, Graphics.fsItalic in AFontStyle);
if not Assigned(FTTFFontInfo) then
raise Exception.CreateFmt('fpTTF:in gTTFontCache not found font "%s" info.', [AFontName]);
end;
destructor TExportFontItem.Destroy;
begin
inherited Destroy;
end;
procedure TExportFontItem.Activate;
begin
FOwner.FOwner.FCurPage.SetFont(FPdfFont, FontSize);
FOwner.FOwner.FCurPage.SetColor(ColorToPdfColor(FontColor), false);
end;
{ TlrPdfExportFilter }
procedure TlrPdfExportFilter.SetupFonts;
//Find default font name
function DefFontName:string;
const
DefFontNames : array [1..3] of string =
('Liberation Sans', 'Arial', 'FreeSans');
var
i: Integer;
begin
for i:=1 to 3 do
if Assigned(gTTFontCache.Find(DefFontNames[i], false, false)) then
begin
Result:=DefFontNames[i];
exit;
end;
raise Exception.Create('Not found Sans font');
end;
var
i: Integer;
sDefFontName:string;
begin
sDefFontName:=DefFontName;
FFontItems.FDefaultFontNormal:=FFontItems.AddItem(sDefFontName, []);
end;
procedure TlrPdfExportFilter.InitFonts;
procedure CreateFontDirList;
{$IFDEF WINDOWS}
var
s: String;
{$ENDIF}
begin
{$IFDEF WINDOWS}
s := SHGetFolderPathUTF8(20); // CSIDL_FONTS = 20
if s <> '' then
gTTFontCache.SearchPath.Add(s);
{$ENDIF}
{$IFDEF linux}
//tested on Fedora 24
gTTFontCache.SearchPath.Add('/usr/share/cups/fonts/');
gTTFontCache.SearchPath.Add('/usr/share/fonts/');
gTTFontCache.SearchPath.Add('/usr/share/wine/fonts/');
gTTFontCache.SearchPath.Add('/usr/local/lib/X11/fonts/');
gTTFontCache.SearchPath.Add(GetUserDir + '.fonts/');
{$ENDIF}
end;
begin
if gTTFontCache.Count = 0 then
begin
gTTFontCache.BuildFontFacheIgnoresErrors:=true;
CreateFontDirList;
gTTFontCache.BuildFontCache;
end;
end;
procedure TlrPdfExportFilter.DoMemoView(View: TfrMemoView);
var
S: String;
begin
DrawRectView(View);
S:=UpperCase(TfrMemoView(View).URLInfo);
if (S <> '') and ((Copy(S, 1, 7) = 'HTTP://') or (Copy(S, 1, 8) = 'HTTPS://')) then
WriteURL(View.Left, View.Top, View.Width, View.Height, TfrMemoView(View).URLInfo);
//prepare font
FCurFont:=FFontItems.AddItem(View.Font.Name, View.Font.Style);
if Assigned(FCurFont) then
begin
FCurFont.FontSize:=View.Font.Size;
FCurFont.FontColor:=View.Font.Color;
FCurFont.Activate;
end;
end;
procedure TlrPdfExportFilter.DoImageView(View: TfrPictureView);
var
IDX: Integer;
function LoadImage:boolean;
var
S: TMemoryStream;
begin
Result:=false;
S:=TMemoryStream.Create;
try
View.Picture.SaveToStream(S);
S.Position:=0;
if View.Picture.Graphic is TJPegImage then
IDX := FPDFDocument.Images.AddFromStream(S, TFPReaderJPEG, False)
else
if View.Picture.Graphic is TPortableNetworkGraphic then
IDX := FPDFDocument.Images.AddFromStream(S, TFPReaderPNG, False)
else
IDX := FPDFDocument.Images.AddFromStream(S, TFPReaderBMP, False);
Result:=true;
finally
S.Free;
end;
end;
var
fX, fY, fW, fH: TPDFFloat;
X, Y, W, H, L: Double;
R: Extended;
begin
DrawRectView(View);
if not ((View.Picture.Graphic = nil) or View.Picture.Graphic.Empty) then
begin
if not LoadImage then exit;
if View.Stretched then
begin
X:=View.Left;
Y:=View.Top;
W:=View.Width;
H:=View.Height;
if View.KeepAspect then
begin
R:=FPDFDocument.Images[IDX].Width / FPDFDocument.Images[IDX].Height;
if (W / H) < R then
begin
L := H;
H := W/R;
if View.Centered then
Y := Y + (L - H) / 2;
end
else
begin
L := W;
W := H * R;
if View.Centered then
X := X + (L - W) / 2;
end;
end;
end
else
if View.Centered then
begin
if FPDFDocument.Images[IDX].Width < View.dx then
begin
X:=View.X + (View.dx - FPDFDocument.Images[IDX].Width) div 2;
W:=FPDFDocument.Images[IDX].Width;
end
else
begin
X:=View.x;
W:=View.dx;
end;
if FPDFDocument.Images[IDX].Height < View.dy then
begin
Y:=View.y + (View.dy - FPDFDocument.Images[IDX].Height) div 2;
H:=FPDFDocument.Images[IDX].Height;
end
else
begin
Y:=View.y;
H:=View.dy;
end;
end
else
begin
X:=View.X;
Y:=View.Y;
W:=FPDFDocument.Images[IDX].Width;
H:=FPDFDocument.Images[IDX].Height;
end;
fX:=ConvetUnits(X);
fY:=ConvetUnits(Y);
fW:=ConvetUnits(W);
fH:=ConvetUnits(H);
FCurPage.DrawImage(fX, fY + fH, fW, fH, IDX); // left-bottom coordinate of image
end;
end;
procedure TlrPdfExportFilter.DoLineView(View: TfrLineView);
begin
DrawRect(View.Left, View.Top, View.Width, View.Height, View.FrameColor, clNone, View.Frames, View.FrameWidth);
end;
procedure TlrPdfExportFilter.DoCheckBoxView(View: TfrCheckBoxView);
var
C: Boolean;
GX, GY: Integer;
begin
DrawRectView(View);
C:=View.Checked;
if View.Memo.Count > 0 then
C:=View.Memo[0] = '1';
View.CalcGaps;
GX:= TfrHackView(View).InternalGapX * 2; //View.GapX + View.FrameWidth + 2;
GY:= TfrHackView(View).InternalGapY * 2; //View.GapY + View.FrameWidth + 2;
if C then
begin
DrawLine(
View.X + GX,
View.Y + GY,
View.X + View.DX - GX * 2,
View.Y + View.DY - GY * 2,
View.FrameColor,
ConvetUnits1(3)
);
DrawLine(
View.X + View.DX - GX * 2,
View.Y + GY,
View.X + GX * 2,
View.Y + View.DY - GY * 2,
View.FrameColor,
ConvetUnits1(3)
);
end;
end;
procedure TlrPdfExportFilter.DoShapeView(View: TfrShapeView);
begin
case View.ShapeType of
frstRectangle:
DrawRect(View.X, View.Y, View.DX, View.DY, View.FrameColor, View.FillColor, [frbLeft, frbTop, frbRight, frbBottom], View.FrameWidth);
frstRoundRect:
DrawLRObjectInternal(View);
frstEllipse:
DrawEllipse(View.X, View.Y, View.DX, View.DY, View.FrameColor, View.FillColor, View.Frames, View.FrameWidth);
frstTriangle:
DrawLRObjectInternal(View);
frstDiagonal1:
DrawLine( View.X, View.Y, View.X + View.DX, View.Y + View.DY, View.FrameColor,View.FrameWidth);
frstDiagonal2:
DrawLine( View.X + View.DX, View.Y, View.X, View.Y + View.DY, View.FrameColor,View.FrameWidth);
end;
end;
procedure TlrPdfExportFilter.DoBarCodeView(View: TfrCustomBarCodeView);
var
FBmp: TBitmap;
X, Y: Integer;
begin
DrawRectView(View);
FBmp:=View.GenerateBitmap;
try
DrawImage(View.X, View.Y, FBmp.Width, FBmp.Height, FBmp);
finally
FBmp.Free;
end;
end;
procedure TlrPdfExportFilter.DoRoundRectView(View: TfrRoundRectView);
begin
// DrawRectView(View);
DrawLRObjectInternal(View);
end;
procedure TlrPdfExportFilter.WriteTextRectJustify(AExportFont: TExportFontItem;
X, Y, W, H: TPDFFloat; const Text: string; Trimmed: boolean);
var
S: String;
Arr: TArrUTF8Item;
AvailWidth, PxSpc, RxSpc, Extra: TPDFFloat;
WordCount, SpcCount, SpcSize, Cini, CEnd, i: Integer;
SpaceWidth, FTH: Single;
begin
//Calc text height
FTH:=AExportFont.TextHeight('Wg');
X:=ConvetUnits(X);
Y:=ConvetUnits(Y);
W:=ConvetUnits(W);
H:=ConvetUnits(H);
AvailWidth:=W;
// count words
Arr := UTF8CountWords(Text, WordCount, SpcCount, SpcSize);
// handle trimmed text
S := Text;
if (SpcCount>0) then
begin
Cini := 0;
CEnd := Length(Arr)-1;
if Trimmed then
begin
s := UTF8Trim(Text, [u8tKeepStart]);
if Arr[CEnd].Space then
begin
Dec(CEnd);
Dec(SpcCount);
end;
end;
AvailWidth := AvailWidth - AExportFont.TextWidth(S);
end;
// check if long way is needed
if (SpcCount>0) and (AvailWidth>0) then
begin
SpaceWidth := AExportFont.TextWidth(' ');
PxSpc := AvailWidth / SpcCount;
RxSpc := AvailWidth - PxSpc * SpcCount;
if PxSPC=0 then
begin
PxSPC := 1;
RxSpc := 0;
end;
for i:=CIni to CEnd do
if Arr[i].Space then
begin
X := X + Arr[i].Count * SpaceWidth;
if AvailWidth>0 then
begin
Extra := PxSpc;
if RxSpc>0 then
begin
Extra:=Extra + ConvetUnits1(1);
RxSpc:=RxSpc - ConvetUnits1(1);
end;
X := X + Extra;
AvailWidth:=AvailWidth - Extra;
end;
end
else
begin
s := Copy(Text, Arr[i].Index, Arr[i].Count);
FCurPage.WriteText(X, Y + FTH, S);
X := X + AExportFont.TextWidth(S)
end;
end
else
FCurPage.WriteText(X, Y + FTH, S);
SetLength(Arr, 0);
end;
procedure TlrPdfExportFilter.WriteTextRect(AExportFont: TExportFontItem; X, Y,
W: TPDFFloat; AText: string; AHAlign: TAlignment);
var
FTW, FTH: Single;
X1: TPDFFloat;
Y1, fX, fY, fW: TPDFFloat;
begin
fX := ConvetUnits(X);
fY := ConvetUnits(Y);
fW := ConvetUnits(W);
//Calc text width
FTW:=AExportFont.TextWidth(AText);
//Calc text height
FTH:=AExportFont.TextHeight(AText);
case AHAlign of
taLeftJustify:
begin
Y1:=fY + FTH;
X1:=fX;
end;
taRightJustify:
begin
Y1:=fY + FTH;
X1:=fX + fW - FTW;
if X1 < fX then
X1:=fX;
end;
taCenter:
begin
Y1:=fY + FTH;
X1:=fX + fW / 2 - FTW / 2;
if X1 < fX then
X1:=fX;
end;
end;
FCurPage.WriteText(X1, Y1, AText);
end;
procedure TlrPdfExportFilter.DrawRect(X, Y, W, H: TPDFFloat; ABorderColor,
AFillColor: TColor; AFrames: TfrFrameBorders; ABorderWidth: TPDFFloat);
var
fX, fY, fW, fH: Extended;
begin
if (AFillColor = clNone) and (ABorderColor = clNone) then exit;
if ABorderColor <> clNone then
FCurPage.SetColor(ColorToPdfColor(ABorderColor), true);
if (AFillColor <> clNone) then
FCurPage.SetColor(ColorToPdfColor(AFillColor), false);
fW:= ConvetUnits(W);
fH:= ConvetUnits(H);
fX:= ConvetUnits(X);
fY:= ConvetUnits(Y);
ABorderWidth:=ConvetUnits(ABorderWidth);
if AFrames = [frbLeft, frbTop, frbRight, frbBottom] then
FCurPage.DrawRect(fX, fY + fH, fW, fH, ABorderWidth, (AFillColor <> clNone), (ABorderColor <> clNone))
else
begin
if frbLeft in AFrames then
FCurPage.DrawLine(fX, fY, fX, fY + fH, ABorderWidth);
if frbTop in AFrames then
FCurPage.DrawLine(fX, fY, fX + fW, fY, ABorderWidth);
if frbRight in AFrames then
FCurPage.DrawLine(fX + fW, fY, fX + fW, fY + fH, ABorderWidth);
if frbBottom in AFrames then
FCurPage.DrawLine(fX, fY + fH, fX + fW, fY + fH, ABorderWidth);
end;
end;
procedure TlrPdfExportFilter.DrawRectView(AView: TfrView);
begin
if AView.Frames <> [] then
DrawRect(AView.Left, AView.Top, AView.Width, AView.Height, AView.FrameColor, AView.FillColor, AView.Frames, AView.FrameWidth);
end;
procedure TlrPdfExportFilter.WriteURL(X, Y, W, H: TPDFFloat; AUrlText: string);
begin
X := ConvetUnits(X);
Y := ConvetUnits(Y);
W := ConvetUnits(W);
H := ConvetUnits(H);
FCurPage.AddExternalLink(X, Y + H, W, H, AUrlText, false);
end;
procedure TlrPdfExportFilter.DrawLine(X1, Y1, X2, Y2: TPDFFloat;
ABorderColor: TColor; ABorderWidth: TPDFFloat);
begin
if (ABorderColor = clNone) then exit;
if ABorderColor <> clNone then
FCurPage.SetColor(ColorToPdfColor(ABorderColor), true);
FCurPage.DrawLine(
ConvetUnits(X1),
ConvetUnits(Y1),
ConvetUnits(X2),
ConvetUnits(Y2),
ConvetUnits(ABorderWidth));
end;
procedure TlrPdfExportFilter.DrawEllipse(X, Y, W, H: TPDFFloat; ABorderColor,
AFillColor: TColor; AFrames: TfrFrameBorders; ABorderWidth: TPDFFloat);
var
fX, fY, fW, fH: Extended;
begin
if (AFillColor = clNone) and (ABorderColor = clNone) then exit;
if ABorderColor <> clNone then
FCurPage.SetColor(ColorToPdfColor(ABorderColor), true);
if (AFillColor <> clNone) then
FCurPage.SetColor(ColorToPdfColor(AFillColor), false);
fW:= ConvetUnits(W);
fH:= ConvetUnits(H);
fX:= ConvetUnits(X);
fY:= ConvetUnits(Y);
ABorderWidth:=ConvetUnits(ABorderWidth);
FCurPage.DrawEllipse(fX, fY + fH, fW, fH, ABorderWidth, (AFillColor <> clNone), (ABorderColor <> clNone))
end;
procedure TlrPdfExportFilter.DrawImage(X, Y, W, H: integer; ABmp: TBitmap);
var
X1, Y1, W1, H1: TPDFFloat;
S: TMemoryStream;
IDX: Integer;
begin
begin
S:=TMemoryStream.Create;
try
ABmp.SaveToStream(S);
S.Position:=0;
IDX := FPDFDocument.Images.AddFromStream(S, TFPReaderBMP, False);
X1:=ConvetUnits(X);
Y1:=ConvetUnits(Y);
W1 := ConvetUnits(W); // FPDFDocument.Images[IDX].Width);
H1 := ConvetUnits(H); // FPDFDocument.Images[IDX].Height);
FCurPage.DrawImage(X1, Y1 + H1, W1, H1, IDX); // left-bottom coordinate of image
finally
S.Free;
end;
end;
end;
procedure TlrPdfExportFilter.DrawLRObjectInternal(View: TfrView);
var
FBmp: TBitmap;
X, Y: Integer;
begin
X:=View.X;
Y:=View.Y;
FBmp:=TBitmap.Create;
try
FBmp.Width:=View.DX + 1;
FBmp.Height:=View.DY + 1;
FBmp.Canvas.Brush.Color := clWhite;
FBmp.Canvas.Brush.style := bsSolid;
FBmp.Canvas.FillRect(0, 0, FBmp.Width, FBmp.Height);
View.X:=0;
View.Y:=0;
View.Draw(FBmp.Canvas);
DrawImage(X, Y, FBmp.Width, FBmp.Height, FBmp);
finally
FBmp.Free;
end;
end;
constructor TlrPdfExportFilter.Create(AStream: TStream);
begin
inherited Create(AStream);
FPDFDocument:=TPDFDocument.Create(nil);
FFontItems:=TExportFonts.Create(Self);
InitFonts;
end;
destructor TlrPdfExportFilter.Destroy;
begin
FreeAndNil(FFontItems);
FreeAndNil(FPDFDocument);
inherited Destroy;
end;
procedure TlrPdfExportFilter.OnBeginDoc;
begin
inherited OnBeginDoc;
FCurPageNo:=-1;
FPDFDocument.Infos.Title := Application.Title;
{ FPDFDocument.Infos.Author := FAuthorPDF;
FPDFDocument.Infos.Producer := FProducerPDF;}
FPDFDocument.Infos.ApplicationName := ApplicationName;
FPDFDocument.Infos.CreationDate := Now;
// FPDFDocument.Options:=FPdfOptions.FOptions;
FPDFDocument.DefaultOrientation := ppoPortrait; // FPdfOptions.PaperOrientation;
FPDFDocument.StartDocument;
FCurSection := FPDFDocument.Sections.AddSection; // we always need at least one section
SetupFonts;
end;
procedure TlrPdfExportFilter.OnEndDoc;
begin
inherited OnEndDoc;
FPDFDocument.SaveToStream(Stream);
end;
procedure TlrPdfExportFilter.OnBeginPage;
var
lrPg: PfrPageInfo;
begin
inherited OnBeginPage;
Inc(FCurPageNo);
FCurPage := FPDFDocument.Pages.AddPage;
FCurPage.UnitOfMeasure := uomMillimeters; //normal work only whis mm ??
FCurSection.AddPage(FCurPage);
//setup page size
lrPg:=CurReport.EMFPages[FCurPageNo];
case lrPg^.pgSize of
9:FCurPage.PaperType := ptA4;
11:FCurPage.PaperType := ptA5;
1,2:FCurPage.PaperType := ptLetter;
5:FCurPage.PaperType := ptLegal;
7:FCurPage.PaperType := ptExecutive;
//:FCurPage.PaperType := ptComm10;
37:FCurPage.PaperType := ptMonarch;
27:FCurPage.PaperType := ptDL;
28:FCurPage.PaperType := ptC5;
34:FCurPage.PaperType := ptB5;
else
FCurPage.PaperType := ptA4;
end;
if lrPg^.pgOr in [poPortrait, poReversePortrait] then
FCurPage.Orientation:=ppoPortrait
else //poReverseLandscape, poLandscape,
FCurPage.Orientation:=ppoLandscape;
end;
procedure TlrPdfExportFilter.OnEndPage;
begin
inherited OnEndPage;
end;
procedure TlrPdfExportFilter.OnData(x, y: Integer; View: TfrView);
begin
InternalGapX:=2 + View.GapX;
InternalGapY:=2 + View.GapY;
if (View is TfrRoundRectView) then
DoRoundRectView(TfrRoundRectView(View))
else
if (View is TfrMemoView) then
DoMemoView(TfrMemoView(View))
else
if (View is TfrPictureView) then
DoImageView(TfrPictureView(View))
else
if (View is TfrLineView) then
DoLineView(TfrLineView(View))
else
if (View is TfrCheckBoxView) then
DoCheckBoxView(TfrCheckBoxView(View))
else
if (View is TfrShapeView) then
DoShapeView(TfrShapeView(View))
else
if (View is TfrCustomBarCodeView) then
DoBarCodeView(TfrCustomBarCodeView(View))
;
end;
procedure TlrPdfExportFilter.OnText(x, y: Integer; const Text: String;
View: TfrView);
var
W: Double;
begin
if (View is TfrMemoView) and Assigned(FCurFont) then
begin
if TfrMemoView(View).FirstLine then
W:=TfrMemoView(View).Width - TfrMemoView(View).ParagraphGap - InternalGapX * 2
else
W:=TfrMemoView(View).Width - InternalGapX * 2;
if TfrMemoView(View).Justify and not TfrMemoView(View).LastLine then
WriteTextRectJustify(FCurFont, X + InternalGapX, Y, W, View.dy, Text, true)
else
WriteTextRect(FCurFont, X + InternalGapX, Y, W, Text, TfrMemoView(View).Alignment);
end;
end;
procedure TlrPdfExportFilter.OnExported(x, y: Integer; View: TfrView);
begin
end;
initialization
frRegisterExportFilter(TlrPdfExportFilter, 'PDF file (*.pdf)', '*.pdf');
end.

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<Package Version="4">
<Name Value="lr_pdfexport"/>
<Type Value="RunAndDesignTime"/>
<Author Value="Copyright (C) 2016 alexs alexs75.at.yandex.ru"/>
<CompilerOptions>
<Version Value="11"/>
<SearchPaths>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
</CompilerOptions>
<Description Value="A LazReport PDF export addon using the fcl-pdf package"/>
<License Value="
The module is designed to create an image of the report with the exact
positioning of objects and subsequent binding to the worksheet
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version with the following modification:
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent modules,and
to copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the terms
and conditions of the license of that module. An independent module is a
module which is not derived from or based on this library. If you modify
this library, you may extend this exception to your version of the library,
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
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. See the GNU Library General Public License
for more details.
You should have received a copy of the GNU Library General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA."/>
<Version Minor="9"/>
<Files Count="2">
<Item1>
<Filename Value="lrpdfexport.pas"/>
<HasRegisterProc Value="True"/>
<UnitName Value="lrPDFExport"/>
</Item1>
<Item2>
<Filename Value="lr_e_fclpdf.pas"/>
<UnitName Value="lr_e_fclpdf"/>
</Item2>
</Files>
<RequiredPkgs Count="2">
<Item1>
<PackageName Value="lazreport"/>
</Item1>
<Item2>
<PackageName Value="IDEIntf"/>
</Item2>
</RequiredPkgs>
<UsageOptions>
<UnitPath Value="$(PkgOutDir)"/>
</UsageOptions>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
</Package>
</CONFIG>

View File

@ -0,0 +1,22 @@
{ This file was automatically created by Lazarus. Do not edit!
This source is only used to compile and install the package.
}
unit lr_pdfexport;
{$warn 5023 off : no warning about unused units}
interface
uses
lrPDFExport, lr_e_fclpdf, LazarusPackageIntf;
implementation
procedure Register;
begin
RegisterUnit('lrPDFExport', @lrPDFExport.Register);
end;
initialization
RegisterPackage('lr_pdfexport', @Register);
end.

View File

@ -0,0 +1,71 @@
{
LazReport PDF export
Copyright (C) 2016 alexs alexs75.at.yandex.ru
The module is designed to create an image of the report with the exact
positioning of objects and subsequent binding to the worksheet
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version with the following modification:
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent modules,and
to copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the terms
and conditions of the license of that module. An independent module is a
module which is not derived from or based on this library. If you modify
this library, you may extend this exception to your version of the library,
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
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. See the GNU Library General Public License
for more details.
You should have received a copy of the GNU Library General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
}
{$IF (FPC_FULLVERSION < 30101)}
!!! This component compiled only FPC 3.1.1 or hight
{$ENDIF}
unit lrPDFExport;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs;
type
TlrPDFExport = class(TComponent)
private
protected
public
published
end;
procedure Register;
implementation
uses lr_e_fclpdf;
procedure Register;
begin
{$I lrpdfexport_icon.lrs}
RegisterComponents('LazReport',[TlrPDFExport]);
end;
end.

View File

@ -0,0 +1,21 @@
LazarusResources.Add('TlrPDFExport','PNG',[
#137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#6#0#0#0#224'w='#248#0
+#0#0#4'sBIT'#8#8#8#8'|'#8'd'#136#0#0#0#9'pHYs'#0#0#14#196#0#0#14#196#1#149'+'
+#14#27#0#0#1#135'IDATH'#137#173#148'/o'#194'@'#24#198#159'[P'#251#4#224'f'
+#235#230#0';'#209'Pj'#246#9'*H'#218#5'B2?'#177#180#19#248'%'#164'K'#134'#'
+#153#159#233'hN`'#1#177'd'#142#143#192#212'$'#246'&'#202#29#253'sm'#175'-'
+#143#186#220'5'#207#239'}'#222'{{'#196#177'm'#6'E'#189'/'#22'D'#245'[!'#199
+#182#153#138#28#219'f'#187#205'F'#185#24#174#22'_'#12't='#247#163#144#210#202
+#133'g'#0'ML'#148#0#215#221''''#0#192'q7'#203#164#9')'#197#237#253#11#30'?'
+#246#232'M'#215#162'M'#150#161'abv'#10#239#165'%'#219',Kc'#25#26#0'`'#185#218
+#195#15#14#172#8'"'#5#200#18#252'|>'#227'u4'#194#247#223#13#150#171'=,C'#131
+'eh'#165#16#1'8'#238'fJ'#9'&f'#135#248#193#129#165'!'#165#9#154'NQ^'#138#202
+'S'#212#155#174'E'#245'\<Eo'#186'f'#219#249']'#2'R'#152' '#164#20#3']'#23#240
+'n'#191#15'?8'#228#182#196'24l'#231'H'#252#140#165#9#210#251#227'a'#27#0#16
+'O'#193#215#227'a'#27'cv'#246''''#132'D'#128#7#199#145#154#231')'#14#225#149
+#243#189#180#170'>^'#140#197'*|'#251#250#141#128'f'#7'`'#217'g'#138#16#210#12
+'pr'#225'''R'#192'UE@'#30#22#0#224'y'#222#5#172'Nr]7ZD'#246#137#167#157#159#1
+'`'#151'kQt'#154':'#170#217#162'L+'#184'1'#201#214#219','#129#196'0m.}M'#149
+'T0=qp'#189')'#202'1'#23#173#227'W_C'#210#201#17#19#149#18#234'LQ'#213#138
+#254#1#151#236#29'Y&C'#187'+'#0#0#0#0'IEND'#174'B`'#130
]);

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B