<commit_before>{
    << Impressions >>  U_Imprime.pas

    Copyright (C) 2010 - JM.Levecque - <<EMAIL>>

   This library is a free software coming as a add-on to fpGUI toolkit
   See the copyright included in the fpGUI distribution for details about redistribution

   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.

    Description:
      This unit interfaces with the user program
}

unit U_Imprime;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, StrUtils,
  fpg_base, fpg_main,
  fpg_panel,
  U_Commande, U_Pdf;

type
  TTypePapier= (A4,Letter,Legal,Executive,Comm10,Monarch,DL,C5,B5);
  TOrient= (oPortrait,oLandscape);
  TMesure = (msMM,msInch);
  TPreparation= (ppPrepare,ppVisualise,ppFichierPDF);

  T_Imprime = class(TObject)
    private
      OldSeparator: Char;
      FVersion: Char;
      FPapier: TPapier;
      FTypePapier: TTypePapier;
      FOrientation: TOrient;
      FMargeCourante: TDimensions;
      FMesure: TMesure;
      FPreparation: TPreparation;
      FVisualisation: Boolean;
      FCanevas: TfpgCanvas;
      FFonteCourante: Integer;
      FInterLCourante: Integer;
      FColorCourante: Integer;
      FNmSection: Integer;
      FNmPage: Integer;
      FNmPageSect: Integer;
      FPosRef: TRefPos;              // absolute writting position
      FEnTeteHeight: Single;       // end of text vertical position in the header
      FPageHeight: Single;         // end of text vertical position in the page
      FPiedHeight: Single;         // beginning of text vertical position in the footer
      FGroupe: Boolean;
      FDefaultFile: string;
      function Dim2Pixels(Value: Single): Single;
      function Pixels2Dim(Value: Single): Single;
      function AddLineBreaks(const Txt: TfpgString; AMaxLineWidth: integer; AFnt: TfpgFont): string;
      function TxtHeight(AWid: Integer; const ATxt: TfpgString; AFnt: TfpgFont; ALSpace: Integer= 2): Integer;
      function ConvertitEnAlpha(Valeur: Integer): string;
      function GetHauteurPapier: Integer;
      function GetLargeurPapier: Integer;
      procedure Bv_VisuPaint(Sender: TObject);
      procedure PrepareFormat;
      procedure CreateVisu;
      procedure ImprimePage(PageNumero: Integer);
      procedure DecaleLignesPied(Decalage: Single);
      procedure DecaleLigne(Decalage: Single);
      procedure DecaleGroupe(Decalage: Single);
      function EcritLigne(PosX,PosY: Single; Colonne,Texte,FonteNum,FondNum,BordNum,InterL: Integer;
                TxtFlags: TfpgTextFlags; Zone: TZone): Single;
      function EcritNum(PosX,PosY: Single; Colonne,TexteNum,TexteTot,FonteNum,FondNum,BordNum,InterL: Integer;
                TxtFlags: TfpgTextFlags; Total,Alpha: Boolean; Zone: TZone; SPNum: TSectPageNum): Single;
      function InsereEspace(PosY: Single; Colonne: Integer; EspHeight: Single; FondNum: Integer; Zone: TZone): Single;
      procedure FinLigne(Zone: TZone);
      procedure TraceCadre(StTrait: Integer; Zone: TZone);
      procedure TraceTrait(XDebut,YDebut,XFin,YFin: Single; StTrait: Integer);
      procedure TraceTraitHoriz(XDebut,YDebut: Single; Colonne: Integer; XFin: Single; StTrait: Integer; Zone: TZone);
      procedure PaintSurface(Points: T_Points; Couleur: TfpgColor);
      function GetTitreSection: string;
      procedure SetTitreSection(ATitre: string);
    public
      constructor Create;
      destructor Destroy; override;
      procedure Debut(IniOriente: TOrient= oPortrait; IniTypePapier: TTypePapier= A4;
                IniMesure: TMesure= msMM; IniVersion: Char= 'F'; IniVisu: Boolean= True);
                // starts preview and printing process with initializations
                // IniOriente = paper orientation >> oPortrait or oLandscape
                // IniTypePapier = (A4, Letter,Legal,Executive,Comm10,Monarch,DL,C5,B5)
                // IniMesure = millimeters (msMM) or inches (msInches)
                // IniVersion = version française 'F' or version English 'E', or other, to come
                // IniVisu = True (visualisation) or False (direct printing or PDF generation)
      procedure Fin;
      procedure ImprimeDocument;
      procedure Visualisation;
      procedure Section(MgGauche,MgDroite,MgHaute,MgBasse: Single; Retrait: Single= 0;
                IniOriente: TOrient= oPortrait);
                // new section with initialization of margins
                // Retrait = additional margin which can be necessary when frames are drawn
                // IniOriente = paper orientation >> oPortrait or oLandscape
      procedure Page;
                // new page in the current section
      function Fond(FdColor: TfpgColor): Integer;
               // returns the number allocated to the color
               // FdColor = background color
      function Fonte(FtNom: string; FtColor: TfpgColor): Integer;
               // returns the number allocated to the font
               // FtNom = FontDesc of the font
               // FtColor = font color
      function StyleTrait(StEpais: Single; StColor: Tfpgcolor; StStyle: TfpgLineStyle): Integer;
               // returns the number allocated to the line style
               // StEpais = thickness of the line in pixels
               // StColor = line color
               // StStyle = line style
      function Bordure(BdFlags: TFBordFlags; BdStyle: Integer): Integer;
               // returns the number allocated to the border
               // BdFlags = position of the border (bdTop,bdBottom,bdLeft,bdRight)
               // BdStyle = border line style: thickness, color, style
      function Colonne(ClnPos,ClnWidth: Single; ClnMargin: Single= 0; ClnColor: TfpgColor= clWhite): Integer;
               // returns the number allocated to the column
               // ClnPos = left position in numeric value in the measurement unit (msMM or msInch)
               // ClnWidth = width in numeric value in the measurement unit (msMM or msInch)
               // ClnMargin = left and right margins in numeric value in the measurement unit (msMM or msInch)
               // ClnColor = column background color
      procedure EcritEnTete(Horiz,Verti: Single; Texte: string; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Texte = texte to be written
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      function EcritPage(Horiz,Verti: Single; Texte: string; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1): Single;
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Texte = texte to be written
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure EcritPied(Horiz,Verti: Single; Texte: string; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Texte = texte to be written
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumSectionEnTete(Horiz,Verti: Single; TexteSect: string= ''; TexteTot: string= '';
                Total: Boolean= False; Alpha: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TexteSection = text to be written before the section number
                // TexteTotal = text to be written before the number of sections
                // Total= True => displays the number of sections
                // Alpha= True => displays the number of sections using letters in alphabetic order
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumSectionPied(Horiz,Verti: Single; TexteSect: string= ''; TexteTot: string= '';
                Total: Boolean= False; Alpha: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TexteSection = text to be written before the section number
                // TexteTotal = text to be written before the number of sections
                // Total= True => displays the number of sections
                // Alpha= True => displays the number of sections using letters in alphabetic order
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumPageEnTete(Horiz,Verti: Single; TextePage: string= ''; TexteTotal: string= '';
                Total: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0; InterNum: Integer= 0;
                CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TextePage = text to be written before the page number in the document
                // TexteTotal = text to be written before the number of pages of the document
                // Total= True > displays the number of pages of the document
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumPagePied(Horiz,Verti: Single; TextePage: string= ''; TexteTotal: string= '';
                Total: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0; InterNum: Integer= 0;
                CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TextePage = text to be written before the page number in the document
                // TexteTotal = text to be written before the number of pages of the document
                // Total= True > displays the number of pages of the document
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumPageSectionEnTete(Horiz,Verti: Single; TexteSect: string= ''; TexteTot: string= '';
                Total: Boolean= False; Alpha: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TextePage = text to ba written before the page number in the section
                // TexteTotal = text to be written before the number of pages of the section
                // Total= True > displays the number of pages of the section
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumPageSectionPied(Horiz,Verti: Single; TexteSect: string= ''; TexteTot: string= '';
                Total: Boolean= False; Alpha: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TextePage = text to ba written before the page number in the section
                // TexteTotal = text to be written before the number of pages of the section
                // Total= True > displays the number of pages of the section
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure TraitHorizEnTete(EspAvant,EspApres: Single; ColNum: Integer= 0; StyleNum: Integer= 0);
                // EspAvant = empty space before the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // EspApres =  empty space after the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // StyleNum = reference of the line style
      procedure TraitHorizPage(EspAvant,EspApres: Single; ColNum: Integer= 0; StyleNum: Integer= 0);
                // EspAvant = empty space before the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // EspApres =  empty space after the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // StyleNum = reference of the line style
      procedure TraitHorizPied(EspAvant,EspApres: Single; ColNum: Integer= 0; StyleNum: Integer= 0);
                // EspAvant = empty space before the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // EspApres =  empty space after the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // StyleNum = reference of the line style
      procedure EspaceEnTete(Verti: Single; ColNum: Integer=0; CoulFdNum: Integer= -1);
                // Verti = height of the empty space : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
      procedure EspacePage(Verti: Single; ColNum: Integer=0; CoulFdNum: Integer= -1);
                // Verti = height of the empty space : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
      procedure EspacePied(Verti: Single; ColNum: Integer=0; CoulFdNum: Integer= -1);
                // Verti = height of the empty space : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
      function Interligne(ItlSup,ItlInt,ItlInf: Single): Integer;
               // IntSup = space between lines, top : numeric value in the measurement unit (msMM or msInch)
               // IntInt = space between lines, internal if wrapping : numeric value in the measurement unit (msMM or msInch)
               // IntInf = space between lines, botom : numeric value in the measurement unit (msMM or msInch)
      procedure Groupe(SautPage: Boolean= False);
                // SautPage = True >> forces new page before the group
                //          = False >> does not create a new page if the whole group can stand on the same page as the preceding text
      procedure FinGroupe(SautPage: Boolean= False);
                // SautPage = True >> forces new page after the group
                //          = False >> lets continue on the same page after the group
      procedure ColorColChange(ColNum: Integer; ColColor: TfpgColor);
                // Changes the background color of a column
                // ColNum = column reference
                // ColColor = new background color for the column
      procedure CadreMarges(AStyle: Integer);
                // draw a frame at the page margins
                // AStyle = reference of the line style of the frame
      procedure CadreEnTete(AStyle: Integer);
                // draw a frame at the limits of the header
                // AStyle = reference of the line style of the frame
      procedure CadrePage(AStyle: Integer);
                // draw a frame at the page limits : left and right margins, header bottom and footer top
                // AStyle = reference of the line style of the frame
      procedure CadrePied(AStyle: Integer);
                // draw a frame at the limits of the footer
                // AStyle = reference of the line style of the frame
      procedure TraitPage(XDebut,YDebut,XFin,YFin: Single; AStyle: Integer);
                // draw a line at absolute position
                // XDebut = horizontal position of starting point in numeric value in the measurement unit (msMM or msInch)
                // YDebut = vertical position of starting point in numeric value in the measurement unit (msMM or msInch)
                // XFin = horizontal position of ending point in numeric value in the measurement unit (msMM or msInch)
                // YFin = vertical position of ending point in numeric value in the measurement unit (msMM or msInch)
                // AStyle = reference of the line style of the line
      procedure SurfPage(XLimits,YLimits: array of Single; AColor: TfpgColor);
      property Langue: Char read FVersion write FVersion;
      property Visualiser: Boolean read FVisualisation write FVisualisation;
      property NumeroSection: Integer read FNmSection write FNmSection;
      property NumeroPage: Integer read FNmPage write FNmPage;
      property NumeroPageSection: Integer read FNmPageSect write FNmPageSect;
      property HauteurPapier: Integer read GetHauteurPapier;
      property LargeurPapier: Integer read GetLargeurPapier;
      property DefaultFile: string read FDefaultFile write FDefaultFile;
      property CouleurCourante: Integer read FColorCourante write FColorCourante;
      property TitreSection: string read GetTitreSection write SetTitreSection;
    end;

  // classes for interface with PDF generation

  TPdfElement = class
    end;

  TPdfTexte= class(TPdfElement)
    private
      FPage: Integer;
      FFont: Integer;
      FSize: string;
      FPosX: Single;
      FPosY: Single;
      FLarg: Single;
      FText: string;
      FColor: TfpgColor;
    public
      property PageId: Integer read FPage write FPage;
      property FontName: Integer read FFont write FFont;
      property FontSize: string read FSize write FSize;
      property TextPosX: Single read FPosX write FPosX;
      property TextPosY: Single read FPosY write FPosY;
      property TextLarg: Single read FLarg write FLarg;
      property Ecriture: string read FText write FText;
      property Couleur: TfpgColor read FColor write FColor;
    end;

  TPdfRect = class(TPdfElement)
    private
      FPage: Integer;
      FEpais: Single;
      FGauche: Single;
      FBas: Single;
      FHaut: Single;
      FLarg: Single;
      FColor: Integer;
      FFill: Boolean;
      FStroke: Boolean;
      FLineStyle: TfpgLineStyle;
    protected
    public
      property PageId: Integer read FPage write FPage;
      property RectEpais: Single read FEpais write FEpais;
      property RectGauche: Single read FGauche write FGauche;
      property RectBas: Single read FBas write FBas;
      property RectHaut: Single read FHaut write FHaut;
      property RectLarg: Single read FLarg write FLarg;
      property RectCouleur: Integer read FColor write FColor;
      property RectEmplit: Boolean read FFill write FFill;
      property RectTrace: Boolean read FStroke write FStroke;
      property RectLineStyle: TfpgLineStyle read FLineStyle write FLineStyle;
    end;

  TPdfLine = class(TPdfElement)
    private
      FPage: Integer;
      FEpais: Single;
      FStartX: Single;
      FStartY: Single;
      FEndX: Single;
      FEndY: Single;
      FColor: Integer;
      FStyle: TfpgLineStyle;
    protected
    public
      property PageId: Integer read FPage write FPage;
      property LineEpais: Single read FEpais write FEpais;
      property LineStartX: Single read FSTartX write FStartX;
      property LineStartY: Single read FStartY write FStartY;
      property LineEndX: Single read FEndX write FEndX;
      property LineEndY: Single read FEndY write FEndY;
      property LineColor: Integer read FColor write FColor;
      property LineStyle: TfpgLineStyle read FStyle write FStyle;
    end;

  TPdfSurf = class(TPdfElement)
    private
      FPage: Integer;
      FPoints: T_Points;
      FColor: Integer;
    protected
    public
      property PageId: Integer read FPage write FPage;
      property Points: T_Points read FPoints;
      property SurfColor: Integer read FColor write FColor;
    end;

var
  Imprime: T_Imprime;

  Infos: record
    Titre: string;
    Auteur: string;
    end;

  PdfPage: TList;
  PdfTexte: TPdfTexte;
  PdfRect: TPdfRect;
  PdfLine: TPdfLine;
  PdfSurf: TPdfSurf;

const
  FontDefaut= 0;
  ColDefaut= 0;
  lnCourante= -1;
  lnFin= -2;
//  cnSuite= -1;
  cnLeft= -2;
  cnCenter= -3;
  cnRight= -4;
  PPI= 72;

implementation

uses
  U_Visu;

const
  InchToMM= 25.4;
  Cent= 100;

function T_Imprime.Dim2Pixels(Value: Single): Single;
begin
if FMesure= msMM
then
  Result:= Value*PPI/InchToMM
else
  Result:= Value*PPI;
end;

function T_Imprime.Pixels2Dim(Value: Single): Single;
begin
if FMesure= msMM
then<commit_msg>pdf reporting: moved the PPI constant to implementation section<commit_after>{
    << Impressions >>  U_Imprime.pas

    Copyright (C) 2010 - JM.Levecque - <<EMAIL>>

   This library is a free software coming as a add-on to fpGUI toolkit
   See the copyright included in the fpGUI distribution for details about redistribution

   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.

    Description:
      This unit interfaces with the user program
}

unit U_Imprime;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, StrUtils,
  fpg_base, fpg_main,
  fpg_panel,
  U_Commande, U_Pdf;

type
  TTypePapier= (A4,Letter,Legal,Executive,Comm10,Monarch,DL,C5,B5);
  TOrient= (oPortrait,oLandscape);
  TMesure = (msMM,msInch);
  TPreparation= (ppPrepare,ppVisualise,ppFichierPDF);

  T_Imprime = class(TObject)
    private
      OldSeparator: Char;
      FVersion: Char;
      FPapier: TPapier;
      FTypePapier: TTypePapier;
      FOrientation: TOrient;
      FMargeCourante: TDimensions;
      FMesure: TMesure;
      FPreparation: TPreparation;
      FVisualisation: Boolean;
      FCanevas: TfpgCanvas;
      FFonteCourante: Integer;
      FInterLCourante: Integer;
      FColorCourante: Integer;
      FNmSection: Integer;
      FNmPage: Integer;
      FNmPageSect: Integer;
      FPosRef: TRefPos;              // absolute writting position
      FEnTeteHeight: Single;       // end of text vertical position in the header
      FPageHeight: Single;         // end of text vertical position in the page
      FPiedHeight: Single;         // beginning of text vertical position in the footer
      FGroupe: Boolean;
      FDefaultFile: string;
      function Dim2Pixels(Value: Single): Single;
      function Pixels2Dim(Value: Single): Single;
      function AddLineBreaks(const Txt: TfpgString; AMaxLineWidth: integer; AFnt: TfpgFont): string;
      function TxtHeight(AWid: Integer; const ATxt: TfpgString; AFnt: TfpgFont; ALSpace: Integer= 2): Integer;
      function ConvertitEnAlpha(Valeur: Integer): string;
      function GetHauteurPapier: Integer;
      function GetLargeurPapier: Integer;
      procedure Bv_VisuPaint(Sender: TObject);
      procedure PrepareFormat;
      procedure CreateVisu;
      procedure ImprimePage(PageNumero: Integer);
      procedure DecaleLignesPied(Decalage: Single);
      procedure DecaleLigne(Decalage: Single);
      procedure DecaleGroupe(Decalage: Single);
      function EcritLigne(PosX,PosY: Single; Colonne,Texte,FonteNum,FondNum,BordNum,InterL: Integer;
                TxtFlags: TfpgTextFlags; Zone: TZone): Single;
      function EcritNum(PosX,PosY: Single; Colonne,TexteNum,TexteTot,FonteNum,FondNum,BordNum,InterL: Integer;
                TxtFlags: TfpgTextFlags; Total,Alpha: Boolean; Zone: TZone; SPNum: TSectPageNum): Single;
      function InsereEspace(PosY: Single; Colonne: Integer; EspHeight: Single; FondNum: Integer; Zone: TZone): Single;
      procedure FinLigne(Zone: TZone);
      procedure TraceCadre(StTrait: Integer; Zone: TZone);
      procedure TraceTrait(XDebut,YDebut,XFin,YFin: Single; StTrait: Integer);
      procedure TraceTraitHoriz(XDebut,YDebut: Single; Colonne: Integer; XFin: Single; StTrait: Integer; Zone: TZone);
      procedure PaintSurface(Points: T_Points; Couleur: TfpgColor);
      function GetTitreSection: string;
      procedure SetTitreSection(ATitre: string);
    public
      constructor Create;
      destructor Destroy; override;
      procedure Debut(IniOriente: TOrient= oPortrait; IniTypePapier: TTypePapier= A4;
                IniMesure: TMesure= msMM; IniVersion: Char= 'F'; IniVisu: Boolean= True);
                // starts preview and printing process with initializations
                // IniOriente = paper orientation >> oPortrait or oLandscape
                // IniTypePapier = (A4, Letter,Legal,Executive,Comm10,Monarch,DL,C5,B5)
                // IniMesure = millimeters (msMM) or inches (msInches)
                // IniVersion = version française 'F' or version English 'E', or other, to come
                // IniVisu = True (visualisation) or False (direct printing or PDF generation)
      procedure Fin;
      procedure ImprimeDocument;
      procedure Visualisation;
      procedure Section(MgGauche,MgDroite,MgHaute,MgBasse: Single; Retrait: Single= 0;
                IniOriente: TOrient= oPortrait);
                // new section with initialization of margins
                // Retrait = additional margin which can be necessary when frames are drawn
                // IniOriente = paper orientation >> oPortrait or oLandscape
      procedure Page;
                // new page in the current section
      function Fond(FdColor: TfpgColor): Integer;
               // returns the number allocated to the color
               // FdColor = background color
      function Fonte(FtNom: string; FtColor: TfpgColor): Integer;
               // returns the number allocated to the font
               // FtNom = FontDesc of the font
               // FtColor = font color
      function StyleTrait(StEpais: Single; StColor: Tfpgcolor; StStyle: TfpgLineStyle): Integer;
               // returns the number allocated to the line style
               // StEpais = thickness of the line in pixels
               // StColor = line color
               // StStyle = line style
      function Bordure(BdFlags: TFBordFlags; BdStyle: Integer): Integer;
               // returns the number allocated to the border
               // BdFlags = position of the border (bdTop,bdBottom,bdLeft,bdRight)
               // BdStyle = border line style: thickness, color, style
      function Colonne(ClnPos,ClnWidth: Single; ClnMargin: Single= 0; ClnColor: TfpgColor= clWhite): Integer;
               // returns the number allocated to the column
               // ClnPos = left position in numeric value in the measurement unit (msMM or msInch)
               // ClnWidth = width in numeric value in the measurement unit (msMM or msInch)
               // ClnMargin = left and right margins in numeric value in the measurement unit (msMM or msInch)
               // ClnColor = column background color
      procedure EcritEnTete(Horiz,Verti: Single; Texte: string; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Texte = texte to be written
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      function EcritPage(Horiz,Verti: Single; Texte: string; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1): Single;
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Texte = texte to be written
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure EcritPied(Horiz,Verti: Single; Texte: string; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Texte = texte to be written
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumSectionEnTete(Horiz,Verti: Single; TexteSect: string= ''; TexteTot: string= '';
                Total: Boolean= False; Alpha: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TexteSection = text to be written before the section number
                // TexteTotal = text to be written before the number of sections
                // Total= True => displays the number of sections
                // Alpha= True => displays the number of sections using letters in alphabetic order
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumSectionPied(Horiz,Verti: Single; TexteSect: string= ''; TexteTot: string= '';
                Total: Boolean= False; Alpha: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TexteSection = text to be written before the section number
                // TexteTotal = text to be written before the number of sections
                // Total= True => displays the number of sections
                // Alpha= True => displays the number of sections using letters in alphabetic order
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumPageEnTete(Horiz,Verti: Single; TextePage: string= ''; TexteTotal: string= '';
                Total: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0; InterNum: Integer= 0;
                CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TextePage = text to be written before the page number in the document
                // TexteTotal = text to be written before the number of pages of the document
                // Total= True > displays the number of pages of the document
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumPagePied(Horiz,Verti: Single; TextePage: string= ''; TexteTotal: string= '';
                Total: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0; InterNum: Integer= 0;
                CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TextePage = text to be written before the page number in the document
                // TexteTotal = text to be written before the number of pages of the document
                // Total= True > displays the number of pages of the document
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumPageSectionEnTete(Horiz,Verti: Single; TexteSect: string= ''; TexteTot: string= '';
                Total: Boolean= False; Alpha: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TextePage = text to ba written before the page number in the section
                // TexteTotal = text to be written before the number of pages of the section
                // Total= True > displays the number of pages of the section
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure NumPageSectionPied(Horiz,Verti: Single; TexteSect: string= ''; TexteTot: string= '';
                Total: Boolean= False; Alpha: Boolean= False; ColNum: Integer= 0; FonteNum: Integer= 0;
                InterNum: Integer= 0; CoulFdNum: Integer= -1; BordNum: Integer= -1);
                // Horiz = horizontal position in column (cnLeft,cnCenter,cnRight)
                //         or numeric value in the measurement unit (msMM or msInch)
                // Verti = line position in column (lnCourante,lnFin)
                //         or numeric value in the measurement unit (msMM or msInch)
                // TextePage = text to ba written before the page number in the section
                // TexteTotal = text to be written before the number of pages of the section
                // Total= True > displays the number of pages of the section
                // ColNum = column reference, default between left and right margins
                // FonteNum = font reference
                // InterNum = space between lines reference
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
                // BordNum = border reference, if > -1
      procedure TraitHorizEnTete(EspAvant,EspApres: Single; ColNum: Integer= 0; StyleNum: Integer= 0);
                // EspAvant = empty space before the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // EspApres =  empty space after the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // StyleNum = reference of the line style
      procedure TraitHorizPage(EspAvant,EspApres: Single; ColNum: Integer= 0; StyleNum: Integer= 0);
                // EspAvant = empty space before the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // EspApres =  empty space after the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // StyleNum = reference of the line style
      procedure TraitHorizPied(EspAvant,EspApres: Single; ColNum: Integer= 0; StyleNum: Integer= 0);
                // EspAvant = empty space before the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // EspApres =  empty space after the horizontal line : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // StyleNum = reference of the line style
      procedure EspaceEnTete(Verti: Single; ColNum: Integer=0; CoulFdNum: Integer= -1);
                // Verti = height of the empty space : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
      procedure EspacePage(Verti: Single; ColNum: Integer=0; CoulFdNum: Integer= -1);
                // Verti = height of the empty space : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
      procedure EspacePied(Verti: Single; ColNum: Integer=0; CoulFdNum: Integer= -1);
                // Verti = height of the empty space : numeric value in the measurement unit (msMM or msInch)
                // ColNum = column reference, default between left and right margins
                // CoulFdNum = background color reference, if > -1, replaces the column background color if any
      function Interligne(ItlSup,ItlInt,ItlInf: Single): Integer;
               // IntSup = space between lines, top : numeric value in the measurement unit (msMM or msInch)
               // IntInt = space between lines, internal if wrapping : numeric value in the measurement unit (msMM or msInch)
               // IntInf = space between lines, botom : numeric value in the measurement unit (msMM or msInch)
      procedure Groupe(SautPage: Boolean= False);
                // SautPage = True >> forces new page before the group
                //          = False >> does not create a new page if the whole group can stand on the same page as the preceding text
      procedure FinGroupe(SautPage: Boolean= False);
                // SautPage = True >> forces new page after the group
                //          = False >> lets continue on the same page after the group
      procedure ColorColChange(ColNum: Integer; ColColor: TfpgColor);
                // Changes the background color of a column
                // ColNum = column reference
                // ColColor = new background color for the column
      procedure CadreMarges(AStyle: Integer);
                // draw a frame at the page margins
                // AStyle = reference of the line style of the frame
      procedure CadreEnTete(AStyle: Integer);
                // draw a frame at the limits of the header
                // AStyle = reference of the line style of the frame
      procedure CadrePage(AStyle: Integer);
                // draw a frame at the page limits : left and right margins, header bottom and footer top
                // AStyle = reference of the line style of the frame
      procedure CadrePied(AStyle: Integer);
                // draw a frame at the limits of the footer
                // AStyle = reference of the line style of the frame
      procedure TraitPage(XDebut,YDebut,XFin,YFin: Single; AStyle: Integer);
                // draw a line at absolute position
                // XDebut = horizontal position of starting point in numeric value in the measurement unit (msMM or msInch)
                // YDebut = vertical position of starting point in numeric value in the measurement unit (msMM or msInch)
                // XFin = horizontal position of ending point in numeric value in the measurement unit (msMM or msInch)
                // YFin = vertical position of ending point in numeric value in the measurement unit (msMM or msInch)
                // AStyle = reference of the line style of the line
      procedure SurfPage(XLimits,YLimits: array of Single; AColor: TfpgColor);
      property Langue: Char read FVersion write FVersion;
      property Visualiser: Boolean read FVisualisation write FVisualisation;
      property NumeroSection: Integer read FNmSection write FNmSection;
      property NumeroPage: Integer read FNmPage write FNmPage;
      property NumeroPageSection: Integer read FNmPageSect write FNmPageSect;
      property HauteurPapier: Integer read GetHauteurPapier;
      property LargeurPapier: Integer read GetLargeurPapier;
      property DefaultFile: string read FDefaultFile write FDefaultFile;
      property CouleurCourante: Integer read FColorCourante write FColorCourante;
      property TitreSection: string read GetTitreSection write SetTitreSection;
    end;

  // classes for interface with PDF generation

  TPdfElement = class
    end;

  TPdfTexte= class(TPdfElement)
    private
      FPage: Integer;
      FFont: Integer;
      FSize: string;
      FPosX: Single;
      FPosY: Single;
      FLarg: Single;
      FText: string;
      FColor: TfpgColor;
    public
      property PageId: Integer read FPage write FPage;
      property FontName: Integer read FFont write FFont;
      property FontSize: string read FSize write FSize;
      property TextPosX: Single read FPosX write FPosX;
      property TextPosY: Single read FPosY write FPosY;
      property TextLarg: Single read FLarg write FLarg;
      property Ecriture: string read FText write FText;
      property Couleur: TfpgColor read FColor write FColor;
    end;

  TPdfRect = class(TPdfElement)
    private
      FPage: Integer;
      FEpais: Single;
      FGauche: Single;
      FBas: Single;
      FHaut: Single;
      FLarg: Single;
      FColor: Integer;
      FFill: Boolean;
      FStroke: Boolean;
      FLineStyle: TfpgLineStyle;
    protected
    public
      property PageId: Integer read FPage write FPage;
      property RectEpais: Single read FEpais write FEpais;
      property RectGauche: Single read FGauche write FGauche;
      property RectBas: Single read FBas write FBas;
      property RectHaut: Single read FHaut write FHaut;
      property RectLarg: Single read FLarg write FLarg;
      property RectCouleur: Integer read FColor write FColor;
      property RectEmplit: Boolean read FFill write FFill;
      property RectTrace: Boolean read FStroke write FStroke;
      property RectLineStyle: TfpgLineStyle read FLineStyle write FLineStyle;
    end;

  TPdfLine = class(TPdfElement)
    private
      FPage: Integer;
      FEpais: Single;
      FStartX: Single;
      FStartY: Single;
      FEndX: Single;
      FEndY: Single;
      FColor: Integer;
      FStyle: TfpgLineStyle;
    protected
    public
      property PageId: Integer read FPage write FPage;
      property LineEpais: Single read FEpais write FEpais;
      property LineStartX: Single read FSTartX write FStartX;
      property LineStartY: Single read FStartY write FStartY;
      property LineEndX: Single read FEndX write FEndX;
      property LineEndY: Single read FEndY write FEndY;
      property LineColor: Integer read FColor write FColor;
      property LineStyle: TfpgLineStyle read FStyle write FStyle;
    end;

  TPdfSurf = class(TPdfElement)
    private
      FPage: Integer;
      FPoints: T_Points;
      FColor: Integer;
    protected
    public
      property PageId: Integer read FPage write FPage;
      property Points: T_Points read FPoints;
      property SurfColor: Integer read FColor write FColor;
    end;

var
  Imprime: T_Imprime;

  Infos: record
    Titre: string;
    Auteur: string;
    end;

  PdfPage: TList;
  PdfTexte: TPdfTexte;
  PdfRect: TPdfRect;
  PdfLine: TPdfLine;
  PdfSurf: TPdfSurf;

const
  FontDefaut= 0;
  ColDefaut= 0;
  lnCourante= -1;
  lnFin= -2;
//  cnSuite= -1;
  cnLeft= -2;
  cnCenter= -3;
  cnRight= -4;

implementation

uses
  U_Visu;

const
  PPI= 72;
  InchToMM= 25.4;
  Cent= 100;

function T_Imprime.Dim2Pixels(Value: Single): Single;
begin
if FMesure= msMM
then
  Result:= Value*PPI/InchToMM
else
  Result:= Value*PPI;
end;

function T_Imprime.Pixels2Dim(Value: Single): Single;
begin
if FMesure= msMM
then
{'fraction_non_alphanumeric': 0.0698841399620258, 'fraction_numerical': 0.0044949044832797306, 'mean_word_length': 2.2669789227166275, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6813205', 'n_tokens_mistral': 14309, 'n_tokens_neox': 13493, 'n_words': 5313}