delphi (DelphiUnit.pas) – the last “Hello World!” example, which uses the Delphi interface. It's basically the same as the example for the C++ Builder, but completely written in the Pascal. It also contains Delphi version of attachments, docinfo, drawtoresource, encrypt, fromdoc, pagesperpage and sign examples, in a simplified form.

    1 unit DelphiUnit;
    2 
    3 {*
    4  * (c) 2013-2017 http://www.litePDF.cz
    5  *
    6  * The example code is supplied "AS IS". It disclaims all warranties, expressed
    7  * or implied, including, without limitation, the warranties of merchantability
    8  * and of fitness for any purpose. It assumes no liability for direct, indirect,
    9  * incidental, special, exemplary, or consequential damages, which may result
   10  * from the use of the code, even if advised of the possibility of such damage.
   11  *
   12  * Permission is hereby granted to use, copy, modify, and distribute this
   13  * source code, or portions hereof, for any purpose, without fee.
   14  *}
   15 
   16 interface
   17 
   18 uses
   19    Winapi.Windows, Winapi.Messages, Winapi.ShellAPI, System.SysUtils,
   20    System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
   21    Vcl.Dialogs, Vcl.StdCtrls, litePDF, Vcl.ExtCtrls;
   22 
   23 type
   24    TDelphiFrm = class(TForm)
   25     HelloWorldBtn: TButton;
   26     OpenHelloWorldBtn: TButton;
   27     DivideBvl: TBevel;
   28     AttachmentsBtn: TButton;
   29     DocinfoBtn: TButton;
   30     DrawtoresourceBtn: TButton;
   31     EncryptBtn: TButton;
   32     FromdocBtn: TButton;
   33     PagesperpageBtn: TButton;
   34     SignManualBtn: TButton;
   35     procedure HelloWorldBtnClick(Sender: TObject);
   36     procedure OpenHelloWorldBtnClick(Sender: TObject);
   37     procedure AttachmentsBtnClick(Sender: TObject);
   38     procedure DocinfoBtnClick(Sender: TObject);
   39     procedure DrawtoresourceBtnClick(Sender: TObject);
   40     procedure EncryptBtnClick(Sender: TObject);
   41     procedure FromdocBtnClick(Sender: TObject);
   42     procedure PagesperpageBtnClick(Sender: TObject);
   43     procedure SignManualBtnClick(Sender: TObject);
   44    private
   45     { Private declarations }
   46     procedure AddPage(lpdf: TLitePDF; pageWidthMM, pageHeightMM : UInt;
   47                       text: String);
   48    public
   49     { Public declarations }
   50    end;
   51 
   52 var
   53    DelphiFrm: TDelphiFrm;
   54 
   55 implementation
   56 
   57 {$R *.dfm}
   58 
   59 var crlf : String = AnsiString(Chr(13)) + AnsiString(Chr(10));
   60 
   61 //----------------------------------------------------------------------------
   62 //   helloworld example
   63 //----------------------------------------------------------------------------
   64 
   65 procedure TDelphiFrm.HelloWorldBtnClick(Sender: TObject);
   66 var lpdf : TLitePDF;
   67    canvas : TCanvas;
   68    hdc : THandle;
   69 begin
   70    // create a TLitePDF instance
   71    lpdf := TLitePDF.Create;
   72    try
   73       try
   74          // create a new PDF document
   75          lpdf.CreateMemDocument;
   76 
   77          // create a canvas to draw to
   78          canvas := TCanvas.Create;
   79          if canvas = nil then
   80          begin
   81             raise Exception.Create('Low memory!');
   82          end;
   83 
   84          try
   85             // add a page, with large-enough pixel scale
   86             hdc := lpdf.AddPage(Trunc(lpdf.MMToUnit(210)),
   87                                 Trunc(lpdf.MMToUnit(297)),
   88                                 2100, 2970, LongWord(LitePDFDrawFlag_None));
   89 
   90             // initialize the canvas
   91             canvas.Handle := hdc;
   92 
   93             // prepare text print
   94             canvas.Font.Name := 'Arial';
   95             canvas.Font.Size := -240;
   96             canvas.Font.Color := clGreen;
   97 
   98             // print text
   99             canvas.TextOut(100, 100, 'Hello World!');
  100 
  101             canvas.Font.Size := -100;
  102             canvas.Font.Color := clBlack;
  103             canvas.TextOut(100, 450, 'from Delphi');
  104 
  105             // prepare a pen
  106             canvas.Pen.Width := 10;
  107             canvas.Pen.Style := psSolid;
  108 
  109             // draw three lines
  110             canvas.Pen.Color := clRed;
  111             canvas.MoveTo(1800, 100);
  112             canvas.LineTo(1800, 550);
  113 
  114             canvas.Pen.Color := clGreen;
  115             canvas.MoveTo(1810, 100);
  116             canvas.LineTo(1810, 550);
  117 
  118             canvas.Pen.Color := clBlue;
  119             canvas.MoveTo(1820, 100);
  120             canvas.LineTo(1820, 550);
  121          finally
  122             canvas.Destroy;
  123          end;
  124 
  125          if hdc <> THandle(0) then
  126          begin
  127             // finish drawing
  128             lpdf.FinishPage(hdc);
  129 
  130             // save the document
  131             lpdf.SaveToFile('delphi-1.pdf');
  132          end;
  133 
  134          // close the document
  135          lpdf.Close();
  136       except
  137          // do something on TLitePDFException exception
  138          on ex : TLitePDFException do raise;
  139       end;
  140    finally
  141       // destroy the TLitePDF instance
  142       lpdf.Destroy;
  143    end;
  144 end;
  145 
  146 procedure TDelphiFrm.OpenHelloWorldBtnClick(Sender: TObject);
  147 var errCode : Integer;
  148 begin
  149    errCode := Integer(ShellExecute(HWND(nil), 'open', 'delphi-1.pdf',
  150                                    nil, nil, SW_SHOW));
  151    if errCode < 32 then
  152    begin
  153       raise Exception.Create('Failed to open PDF file');
  154    end;
  155 end;
  156 
  157 //----------------------------------------------------------------------------
  158 //   Helper function
  159 //----------------------------------------------------------------------------
  160 
  161 procedure TDelphiFrm.AddPage(lpdf: TLitePDF; pageWidthMM, pageHeightMM : UInt;
  162                              text: String);
  163 var hDC : THandle;
  164     canvas : TCanvas;
  165 begin
  166    // add a new page to it, with large-enough pixel scale
  167    hDC := lpdf.AddPage(Trunc(lpdf.MMToUnit(pageWidthMM)),
  168                        Trunc(lpdf.MMToUnit(pageHeightMM)),
  169                        pageWidthMM * 10, pageHeightMM * 10,
  170                        LongWord(LitePDFDrawFlag_SubstituteFonts));
  171 
  172    // some examples need an empty page, thus test for it
  173    if Length(text) > 0 then
  174    begin
  175       // prepare drawing
  176       canvas := TCanvas.Create;
  177       try
  178          canvas.Handle := hdc;
  179          canvas.Font.Name := 'Helvetica';
  180          canvas.Font.Size := -50; // ~5mm
  181          canvas.Font.Color := clBlack;
  182 
  183          // print the text
  184          canvas.TextOut(100, 100, text);
  185       finally
  186          canvas.Destroy;
  187       end;
  188    end;
  189 
  190    // finish drawing
  191    lpdf.FinishPage(hDC);
  192 end;
  193 
  194 //----------------------------------------------------------------------------
  195 //   attachments example
  196 //----------------------------------------------------------------------------
  197 
  198 procedure TDelphiFrm.AttachmentsBtnClick(Sender: TObject);
  199 var lpdf : TLitePDF;
  200     customData : PAnsiChar;
  201     ii, sz : Integer;
  202     fileName : AnsiString;
  203     dataLength : LongWord;
  204     data : PByte;
  205     msg : String;
  206 begin
  207    lpdf := TLitePDF.Create;
  208 
  209    try
  210       // create a document
  211       lpdf.CreateMemDocument();
  212 
  213       // check expected counts
  214       if lpdf.GetEmbeddedFileCount <> 0 then
  215       begin
  216          raise TLitePDFException.Create(ERROR_CANNOT_MAKE,
  217                'Newly created document reports non-zero embedded files');
  218       end;
  219 
  220       // create a page
  221       AddPage(lpdf, 210, 297, 'Document with two attachments');
  222 
  223       // embed data and file
  224       customData := 'This is' + Chr(13) + Chr(10) + 'a multiline' +
  225                     Chr(13) + Chr(10) + 'custom data.';
  226       lpdf.EmbedData('custom data.txt', PByte(customData), Length(customData));
  227       lpdf.EmbedFile('..\\examples\\delphi\\delphi.dpr');
  228 
  229       // check expected counts
  230       if lpdf.GetEmbeddedFileCount <> 2 then
  231       begin
  232          raise TLitePDFException.Create(ERROR_CANNOT_MAKE,
  233                'Newly created document reports other than two embedded files');
  234       end;
  235 
  236       // save to file
  237       lpdf.SaveToFile('delphi-attachments-1.pdf');
  238 
  239       // close the document
  240       lpdf.Close;
  241 
  242       //-----------------------------------------------------------------
  243 
  244       // load from file
  245       lpdf.LoadFromFile('delphi-attachments-1.pdf', '', True);
  246 
  247       // check expected counts
  248       if lpdf.GetEmbeddedFileCount <> 2 then
  249       begin
  250          raise TLitePDFException.Create(ERROR_CANNOT_MAKE,
  251                'Loaded document reports other than two embedded files');
  252       end;
  253 
  254       sz := lpdf.GetEmbeddedFileCount;
  255       for ii := 0 to sz - 1 do
  256       begin
  257          fileName := lpdf.GetEmbeddedFileName(ii);
  258          msg := msg + '[' + IntToStr(ii) + '] fileName: ''' + String(fileName) + '''';
  259 
  260          dataLength := 0;
  261          if not lpdf.GetEmbeddedFileData(ii, nil, dataLength) then
  262          begin
  263             raise TLitePDFException.Create(ERROR_CANNOT_MAKE,
  264                   'Failed to get attachment data length');
  265          end;
  266 
  267          GetMem(data, dataLength);
  268 
  269          if not lpdf.GetEmbeddedFileData(ii, data, dataLength) then
  270          begin
  271             FreeMem(data);
  272             raise TLitePDFException.Create(ERROR_CANNOT_MAKE,
  273                   'Failed to get attachment data');
  274          end;
  275 
  276          msg := msg + ' dataLength: ' + IntToStr(dataLength) + crlf;
  277 
  278          FreeMem(data);
  279       end;
  280 
  281       // close the document
  282       lpdf.Close;
  283    finally
  284       // destroy the TLitePDF instance
  285       lpdf.Destroy;
  286    end;
  287 
  288    ShowMessage(msg);
  289 end;
  290 
  291 //----------------------------------------------------------------------------
  292 //   docinfo example
  293 //----------------------------------------------------------------------------
  294 
  295 procedure TDelphiFrm.DocinfoBtnClick(Sender: TObject);
  296 type MDocInfos = record
  297     key : AnsiString;
  298     value : WideString;
  299 end;
  300 var lpdf : TLitePDF;
  301     docinfo : array[0..9] of MDocInfos;
  302     ii : Integer;
  303     value : WideString;
  304     msg : String;
  305 begin
  306    // initialzie the array with items
  307    docinfo[0].key := LitePDFDocumentInfo_Author;
  308    docinfo[0].value := 'Document''s Author ěščřžýáíéúůöĚŠČŘŽÝÁÍÉÚŮÖ §';
  309    docinfo[1].key := LitePDFDocumentInfo_Creator;
  310    docinfo[1].value := 'Document''s Creator';
  311    docinfo[2].key := LitePDFDocumentInfo_Keywords;
  312    docinfo[2].value := 'Keyword1;Keyword2';
  313    docinfo[3].key := LitePDFDocumentInfo_Subject;
  314    docinfo[3].value := 'Document''s subject ěščřžýáíéúůöĚŠČŘŽÝÁÍÉÚŮÖ §';
  315    docinfo[4].key := LitePDFDocumentInfo_Title;
  316    docinfo[4].value := 'Document''s Title ěščřžýáíéúůöĚŠČŘŽÝÁÍÉÚŮÖ §';
  317    docinfo[5].key := 'CustomProperty';
  318    docinfo[5].value := 'CustomPropertyValue';
  319    docinfo[6].key := LitePDFDocumentInfo_Producer;
  320    docinfo[6].value := ''; // cannot be written
  321    docinfo[7].key := LitePDFDocumentInfo_Trapped;
  322    docinfo[7].value := '';
  323    docinfo[8].key := LitePDFDocumentInfo_CreationDate;
  324    docinfo[8].value := ''; // this is set automatically on save
  325    docinfo[9].key := LitePDFDocumentInfo_ModificationDate;
  326    docinfo[9].value := ''; // this is set automatically on save
  327 
  328    lpdf := TLitePDF.Create;
  329 
  330    try
  331       // create a document
  332       lpdf.CreateMemDocument();
  333 
  334       // create a page
  335       AddPage(lpdf, 210, 297, 'Document with set information about an author and such');
  336 
  337       for ii := 0 to 9 do
  338       begin
  339          if Length(docinfo[ii].value) > 0 then
  340          begin
  341             lpdf.SetDocumentInfo(docinfo[ii].key, docinfo[ii].value);
  342          end;
  343       end;
  344 
  345       // save to file
  346       lpdf.SaveToFile('delphi-docinfo-1.pdf');
  347 
  348       // close the document
  349       lpdf.Close;
  350 
  351       //-----------------------------------------------------------------
  352 
  353       // load from file
  354       lpdf.LoadFromFile('delphi-docinfo-1.pdf', '', False);
  355 
  356       for ii := 0 to 9 do
  357       begin
  358          if lpdf.GetDocumentInfoExists(docinfo[ii].key) then
  359          begin
  360             value := lpdf.GetDocumentInfo(docinfo[ii].key);
  361 
  362             msg := msg + '"' + String(docinfo[ii].key) + '" = "' + value + '"';
  363 
  364             if Length(docinfo[ii].value) > 0 then
  365             begin
  366                if docinfo[ii].value = value then
  367                   msg := msg + ', as expected'
  368                else
  369                   msg := msg + ', unexpected!';
  370             end;
  371          end else begin
  372             msg := msg + 'key "' + String(docinfo[ii].key) + '" not found';
  373          end;
  374 
  375          msg := msg + crlf;
  376       end;
  377 
  378       // close the document
  379       lpdf.Close;
  380    finally
  381       // destroy the TLitePDF instance
  382       lpdf.Destroy;
  383    end;
  384 
  385    ShowMessage(msg);
  386 end;
  387 
  388 //----------------------------------------------------------------------------
  389 //   drawtoresource example
  390 //----------------------------------------------------------------------------
  391 
  392 procedure TDelphiFrm.DrawtoresourceBtnClick(Sender: TObject);
  393 function createResource(lpdf : TLitePDF) : LongWord;
  394 var hDC : THandle;
  395     canvas : TCanvas;
  396 begin
  397    // create a resource
  398    hDC := lpdf.AddResource(Trunc(lpdf.MMToUnit(100)),
  399                            Trunc(lpdf.MMToUnit(100)),
  400                            Trunc(lpdf.MMToUnit(100)),
  401                            Trunc(lpdf.MMToUnit(100)),
  402                            LongWord(LitePDFDrawFlag_None));
  403 
  404    canvas := TCanvas.Create;
  405    try
  406       canvas.Handle := hDC;
  407       canvas.Pen.Style := psSolid;
  408       canvas.Pen.Color := clBlack;
  409       canvas.Pen.Width := 1;
  410 
  411       canvas.MoveTo(0, 0);
  412       canvas.LineTo(0, 10);
  413       canvas.LineTo(45, 50);
  414       canvas.LineTo(0, 90);
  415       canvas.LineTo(0, 100);
  416       canvas.LineTo(10, 100);
  417       canvas.LineTo(50, 55);
  418       canvas.LineTo(90, 100);
  419       canvas.LineTo(100, 100);
  420       canvas.LineTo(100, 90);
  421       canvas.LineTo(55, 50);
  422       canvas.LineTo(100, 10);
  423       canvas.LineTo(100, 0);
  424       canvas.LineTo(90, 0);
  425       canvas.LineTo(50, 45);
  426       canvas.LineTo(10, 0);
  427       canvas.LineTo(0, 0);
  428    finally
  429       canvas.Destroy;
  430    end;
  431 
  432    // finish drawing into the resource
  433    Result := lpdf.FinishResource(hDC);
  434 end;
  435 var lpdf : TLitePDF;
  436     resourceID : LongWord;
  437     hDC : THandle;
  438 begin
  439    lpdf := TLitePDF.Create;
  440 
  441    try
  442       // create a document
  443       lpdf.CreateMemDocument();
  444 
  445       // create the resource
  446       resourceID := createResource(lpdf);
  447 
  448       // add an empty page, with large-enough pixel scale
  449       hDC := lpdf.AddPage(Trunc(lpdf.MMToUnit(210)),
  450                           Trunc(lpdf.MMToUnit(297)),
  451                           2100, 2970, LongWord(LitePDFDrawFlag_None));
  452       lpdf.FinishPage(hDC);
  453 
  454       // draw the resource
  455       lpdf.DrawResource(resourceID, 0,
  456          LitePDFUnit_1000th_mm, // for better accuracy
  457          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 10)),
  458          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 10)),
  459          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 1.0)),
  460          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 1.0)));
  461       lpdf.DrawResource(resourceID, 0,
  462          LitePDFUnit_1000th_mm, // for better accuracy
  463          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 150)),
  464          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 10)),
  465          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 1.0)),
  466          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 1.0)));
  467       lpdf.DrawResource(resourceID, 0,
  468          LitePDFUnit_1000th_mm, // for better accuracy
  469          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 150)),
  470          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 120)),
  471          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 0.3)),
  472          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 0.3)));
  473       lpdf.DrawResource(resourceID, 0,
  474          LitePDFUnit_1000th_mm, // for better accuracy
  475          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 10)),
  476          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 150)),
  477          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 0.5)),
  478          Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 1.5)));
  479 
  480       lpdf.DrawResourceWithMatrix(resourceID, 0, 1.0, 0.3, -0.3, 1.2, 123, 153);
  481 
  482       // save to file
  483       lpdf.SaveToFile('delphi-drawtoresource-1.pdf');
  484 
  485       // close the document
  486       lpdf.Close;
  487    finally
  488       // destroy the TLitePDF instance
  489       lpdf.Destroy;
  490    end;
  491 end;
  492 
  493 //----------------------------------------------------------------------------
  494 //   encrypt example
  495 //----------------------------------------------------------------------------
  496 
  497 procedure TDelphiFrm.EncryptBtnClick(Sender: TObject);
  498 // helper function
  499 procedure createEncryptedFiles;
  500 var lpdf : TLitePDF;
  501 begin
  502    lpdf := TLitePDF.Create;
  503 
  504    try
  505       //-----------------------------------------------------------------
  506 
  507       // setup encryption to be used when creating the document
  508       lpdf.PrepareEncryption('', 'owner',
  509                              LongWord(LitePDFEncryptPermission_All),
  510                              LongWord(LitePDFEncryptAlgorithm_RC4V1));
  511 
  512       // begin write-only PDF file
  513       lpdf.CreateFileDocument('delphi-encrypt-rc4v1-no-user-pass.pdf');
  514 
  515       // fill a page
  516       AddPage(lpdf, 210, 297, 'Encrypted, without user password, RC4 V1');
  517 
  518       // close the document
  519       lpdf.Close;
  520 
  521       //-----------------------------------------------------------------
  522 
  523       // setup encryption to be used when creating the document
  524       lpdf.PrepareEncryption('user', 'owner',
  525                              LongWord(LitePDFEncryptPermission_All),
  526                              LongWord(LitePDFEncryptAlgorithm_RC4V2));
  527 
  528       // begin memory-based PDF document
  529       lpdf.CreateMemDocument;
  530 
  531       // fill a page
  532       AddPage(lpdf, 210, 297, 'Encrypted, with user and owner password, RC4 V2');
  533 
  534       // save to file
  535       lpdf.SaveToFile('delphi-encrypt-rc4v2.pdf');
  536 
  537       // close the document
  538       lpdf.Close;
  539 
  540       //-----------------------------------------------------------------
  541 
  542       // setup encryption to be used when creating the document
  543       lpdf.PrepareEncryption('user', 'owner',
  544                              LongWord(LitePDFEncryptPermission_All),
  545                              LongWord(LitePDFEncryptAlgorithm_AESV2));
  546 
  547       // begin memory-based PDF document
  548       lpdf.CreateMemDocument;
  549 
  550       // fill a page
  551       AddPage(lpdf, 210, 297, 'Encrypted, with user and owner password, AES V2');
  552 
  553       // save to file
  554       lpdf.SaveToFile('delphi-encrypt-aesv2.pdf');
  555 
  556       // close the document
  557       lpdf.Close;
  558 
  559       //-----------------------------------------------------------------
  560 
  561       // setup encryption to be used when creating the document
  562       lpdf.PrepareEncryption('user', 'owner',
  563                              LongWord(LitePDFEncryptPermission_All),
  564                              LongWord(LitePDFEncryptAlgorithm_AESV3));
  565 
  566       // begin memory-based PDF document
  567       lpdf.CreateMemDocument;
  568 
  569       // fill a page
  570       AddPage(lpdf, 210, 297, 'Encrypted, with user and owner password, AES V3');
  571 
  572       // save to file
  573       lpdf.SaveToFile('delphi-encrypt-aesv3.pdf');
  574 
  575       // close the document
  576       lpdf.Close;
  577    finally
  578       // destroy the TLitePDF instance
  579       lpdf.Destroy;
  580    end;
  581 end;
  582 
  583 var lpdf : TLitePDF;
  584 begin
  585    lpdf := TLitePDF.Create;
  586 
  587    try
  588       // create the files
  589       createEncryptedFiles;
  590 
  591       //-----------------------------------------------------------------
  592       // now try to open them
  593       //-----------------------------------------------------------------
  594 
  595       // no user password, then open it as a user
  596       lpdf.LoadFromFile('delphi-encrypt-rc4v1-no-user-pass.pdf', '', False);
  597 
  598       // close the document
  599       lpdf.Close;
  600 
  601       //-----------------------------------------------------------------
  602 
  603       try
  604          // this should fail, because no password was provided
  605          lpdf.LoadFromFile('delphi-encrypt-rc4v2.pdf', '', False);
  606 
  607          raise TLitePDFException.Create(ERROR_CANNOT_MAKE,
  608                'Should fail to open encrypted file without provided password');
  609       except
  610          on ex : TLitePDFException do
  611          begin
  612             if ex.getCode <> ERROR_WRONG_PASSWORD then
  613             begin
  614                raise;
  615             end;
  616 
  617             // re-try with user's password
  618             lpdf.LoadFromFile('delphi-encrypt-rc4v2.pdf', 'user', False);
  619          end;
  620       end;
  621 
  622       // close the document
  623       lpdf.Close;
  624 
  625       //-----------------------------------------------------------------
  626 
  627       // try to open as owner
  628       lpdf.LoadFromFile('delphi-encrypt-rc4v1-no-user-pass.pdf', 'owner', False);
  629 
  630       // close the document
  631       lpdf.Close;
  632 
  633       //-----------------------------------------------------------------
  634 
  635       // try to open as user
  636       lpdf.LoadFromFile('delphi-encrypt-rc4v2.pdf', 'user', False);
  637 
  638       // close the document
  639       lpdf.Close;
  640 
  641       //-----------------------------------------------------------------
  642 
  643       // try to open as owner
  644       lpdf.LoadFromFile('delphi-encrypt-rc4v2.pdf', 'owner', False);
  645 
  646       // close the document
  647       lpdf.Close;
  648 
  649       //-----------------------------------------------------------------
  650 
  651       // try to open as user
  652       lpdf.LoadFromFile('delphi-encrypt-aesv2.pdf', 'user', False);
  653 
  654       // close the document
  655       lpdf.Close;
  656 
  657       //-----------------------------------------------------------------
  658 
  659       // try to open as owner
  660       lpdf.LoadFromFile('delphi-encrypt-aesv2.pdf', 'owner', False);
  661 
  662       // close the document
  663       lpdf.Close;
  664 
  665       //-----------------------------------------------------------------
  666 
  667       // try to open as user
  668       lpdf.LoadFromFile('delphi-encrypt-aesv3.pdf', 'user', False);
  669 
  670       // close the document
  671       lpdf.Close;
  672 
  673       //-----------------------------------------------------------------
  674 
  675       // try to open as owner
  676       lpdf.LoadFromFile('delphi-encrypt-aesv3.pdf', 'owner', False);
  677 
  678       // close the document
  679       lpdf.Close;
  680    finally
  681       // destroy the TLitePDF instance
  682       lpdf.Destroy;
  683    end;
  684 end;
  685 
  686 //----------------------------------------------------------------------------
  687 //   fromdoc example
  688 //----------------------------------------------------------------------------
  689 
  690 procedure TDelphiFrm.FromdocBtnClick(Sender: TObject);
  691 var lpdfFrom, lpdfTo : TLitePDF;
  692     resourceID : LongWord;
  693 begin
  694    lpdfFrom := TLitePDF.Create;
  695    lpdfTo := TLitePDF.Create;
  696 
  697    try
  698       // create a document
  699       lpdfFrom.CreateMemDocument;
  700 
  701       // create the source document's pages
  702       AddPage(lpdfFrom, 210, 297, 'Page 1');
  703       AddPage(lpdfFrom, 210, 297, 'Page 2');
  704       AddPage(lpdfFrom, 210, 297, 'Page 3');
  705 
  706       // save to file
  707       lpdfFrom.SaveToFile('delphi-fromdoc-1.pdf');
  708 
  709       // close the document
  710       lpdfFrom.Close;
  711 
  712       //-----------------------------------------------------------------
  713 
  714       // load from file
  715       lpdfFrom.LoadFromFile('delphi-fromdoc-1.pdf', '', False);
  716 
  717       //-----------------------------------------------------------------
  718 
  719       // create a new document
  720       lpdfTo.CreateMemDocument;
  721 
  722       // copy all, but the first page
  723       lpdfTo.AddPagesFrom(lpdfFrom, 1, lpdfFrom.GetPageCount - 1);
  724 
  725       // save to file
  726       lpdfTo.SaveToFile('delphi-fromdoc-2.pdf');
  727 
  728       // close the document
  729       lpdfTo.Close;
  730 
  731       //-----------------------------------------------------------------
  732 
  733       // create a new document
  734       lpdfTo.CreateMemDocument;
  735 
  736       // copy all, but the first page
  737       lpdfTo.AddPagesFrom(lpdfFrom, 1, lpdfFrom.GetPageCount - 1);
  738 
  739       // insert page 0 as page 1 - note, page inserting is PDF-resource hungry
  740       lpdfTo.InsertPageFrom(1, lpdfFrom, 0);
  741 
  742       // save to file
  743       lpdfTo.SaveToFile('delphi-fromdoc-3.pdf');
  744 
  745       // close the document
  746       lpdfTo.Close;
  747 
  748       //-----------------------------------------------------------------
  749 
  750       // create a new document
  751       lpdfTo.CreateMemDocument;
  752 
  753       // copy the third page
  754       lpdfTo.AddPagesFrom(lpdfFrom, 2, 1);
  755 
  756       // add new empty page, it has index 1
  757       AddPage(lpdfTo, 210, 297, '');
  758 
  759       // copy page 2 as a resource
  760       resourceID := lpdfTo.AddPageFromAsResource(lpdfFrom, 1);
  761 
  762       // draw the added page (twice)
  763       lpdfTo.DrawResource(resourceID, 1,
  764                           LitePDFUnit_1000th_mm, // for better accuracy
  765                           Trunc(lpdfTo.MMToUnitEx(LitePDFUnit_1000th_mm, 10)),
  766                           Trunc(lpdfTo.MMToUnitEx(LitePDFUnit_1000th_mm, 10)),
  767                           Trunc(lpdfTo.MMToUnitEx(LitePDFUnit_1000th_mm, 0.3)),
  768                           Trunc(lpdfTo.MMToUnitEx(LitePDFUnit_1000th_mm, 0.3)));
  769       lpdfTo.DrawResource(resourceID, 1,
  770                           LitePDFUnit_1000th_mm, // for better accuracy
  771                           Trunc(lpdfTo.MMToUnitEx(LitePDFUnit_1000th_mm, 150)),
  772                           Trunc(lpdfTo.MMToUnitEx(LitePDFUnit_1000th_mm, 150)),
  773                           Trunc(lpdfTo.MMToUnitEx(LitePDFUnit_1000th_mm, 0.2)),
  774                           Trunc(lpdfTo.MMToUnitEx(LitePDFUnit_1000th_mm, 0.2)));
  775 
  776       // insert page 0 as page 1 - note, page inserting is PDF-resource hungry
  777       lpdfTo.InsertPageFrom(1, lpdfFrom, 0);
  778 
  779       // save to file
  780       lpdfTo.SaveToFile('delphi-fromdoc-4.pdf');
  781 
  782       // close the document
  783       lpdfTo.Close;
  784 
  785       //-----------------------------------------------------------------
  786 
  787       // close the source document
  788       lpdfFrom.Close;
  789    finally
  790       // destroy the TLitePDF instances
  791       lpdfFrom.Destroy;
  792       lpdfTo.Destroy;
  793    end;
  794 end;
  795 
  796 //----------------------------------------------------------------------------
  797 //   pagesperpage example
  798 //----------------------------------------------------------------------------
  799 
  800 procedure TDelphiFrm.PagesperpageBtnClick(Sender: TObject);
  801 // helper function
  802 procedure AddPage2(lpdf: TLitePDF;
  803                    pageWidthMM, pageHeightMM : Integer;
  804                    text: String;
  805                    center : Boolean;
  806                    insertPos : Integer);
  807 var hDC : THandle;
  808     canvas : TCanvas;
  809     len : Integer;
  810 begin
  811    // add a new page to it, with large-enough pixel scale
  812    if insertPos = -1 then
  813       hDC := lpdf.AddPage(Trunc(lpdf.MMToUnit(pageWidthMM)),
  814                           Trunc(lpdf.MMToUnit(pageHeightMM)),
  815                           pageWidthMM * 10, pageHeightMM * 10,
  816                           LongWord(LitePDFDrawFlag_SubstituteFonts))
  817    else
  818       hDC := lpdf.InsertPage(insertPos,
  819                              Trunc(lpdf.MMToUnit(pageWidthMM)),
  820                              Trunc(lpdf.MMToUnit(pageHeightMM)),
  821                              pageWidthMM * 10, pageHeightMM * 10,
  822                              LongWord(LitePDFDrawFlag_SubstituteFonts));
  823 
  824    // prepare drawing
  825    canvas := TCanvas.Create;
  826    try
  827       canvas.Handle := hdc;
  828       canvas.Font.Name := 'Helvetica';
  829       canvas.Font.Size := -50; // ~5mm
  830       if center then
  831          canvas.Font.Size := -150; // ~15mm
  832       canvas.Font.Color := clBlack;
  833 
  834       // print the text
  835       if center then
  836       begin
  837          len := Length(text);
  838          canvas.TextOut(Trunc((pageWidthMM - 5 * len) * 10 / 2),
  839                         Trunc((pageHeightMM - 15) * 10 / 2), text);
  840       end else begin
  841          canvas.TextOut(100, 100, text);
  842       end;
  843    finally
  844       canvas.Destroy;
  845    end;
  846 
  847    // finish drawing
  848    lpdf.FinishPage(hDC);
  849 end;
  850 
  851 // helper function
  852 procedure DrawPageRect(lpdf: TLitePDF; pageIndex : LongWord);
  853 var hDC : THandle;
  854     canvas : TCanvas;
  855     width_mm, height_mm : LongWord;
  856 begin
  857    lpdf.GetPageSize(pageIndex, width_mm, height_mm);
  858 
  859    // the conversion is not needed here, because the current
  860    // unit set on the lpdf is in millimeters, but done anyway,
  861    // to show the usage of the conversion routine
  862    width_mm := Trunc(lpdf.UnitToMM(width_mm));
  863    height_mm := Trunc(lpdf.UnitToMM(height_mm));
  864 
  865    // use the same scale as the AddPage2() function
  866    hDC := lpdf.UpdatePage(pageIndex,
  867                           width_mm * 10, height_mm * 10,
  868                           LongWord(LitePDFDrawFlag_None));
  869 
  870    // prepare drawing
  871    canvas := TCanvas.Create;
  872    try
  873       canvas.Handle := hdc;
  874       canvas.Pen.Style := psSolid;
  875       canvas.Pen.Color := clBlack;
  876       canvas.Pen.Width := 1;
  877 
  878       canvas.MoveTo(10, 10);
  879       canvas.LineTo(width_mm * 10 - 10, 10);
  880       canvas.LineTo(width_mm * 10 - 10, height_mm * 10 - 10);
  881       canvas.LineTo(10, height_mm * 10 - 10);
  882       canvas.LineTo(10, 10);
  883    finally
  884       canvas.Destroy;
  885    end;
  886 
  887    // finish drawing
  888    lpdf.FinishPage(hDC);
  889 end;
  890 
  891 type MSize = record
  892     cx, cy : LongWord;
  893 end;
  894 var lpdf : TLitePDF;
  895     sizes : array[0..4] of MSize;
  896     resources : array[0..4] of LongWord;
  897     ii, idx, pages, width_mm, height_mm : LongWord;
  898     pageSzX, pageSzY : LongWord;
  899     scaleX, scaleY, offsetY : Real;
  900     hDC : THandle;
  901 begin
  902    sizes[0].cx := 210;
  903    sizes[0].cy := 297;
  904    sizes[1].cx := 210;
  905    sizes[1].cy := 297;
  906    sizes[2].cx := 210;
  907    sizes[2].cy := 297;
  908    sizes[3].cx := 297;
  909    sizes[3].cy := 210;
  910    sizes[4].cx := 297;
  911    sizes[4].cy := 210;
  912 
  913    lpdf := TLitePDF.Create;
  914 
  915    try
  916       // create a to-be-multipage document
  917       lpdf.CreateMemDocument;
  918 
  919       // add pages
  920       idx := 0;
  921       for ii := 0 to 3 do
  922       begin
  923          AddPage2(lpdf, sizes[idx].cx, sizes[idx].cy, 'Page ' + IntToStr(idx + 1), True, -1);
  924 
  925          pages := idx;
  926          if pages > 1 then
  927             Dec(pages);
  928 
  929          // draw page rectangle
  930          DrawPageRect(lpdf, pages);
  931 
  932          // skip the third page, it'll be inserted
  933          if ii = 1 then
  934             Inc(idx);
  935 
  936          // add one the same as for 'ii'
  937          Inc(idx);
  938       end;
  939 
  940       // insert the third page
  941       AddPage2(lpdf, sizes[2].cx, sizes[2].cy, 'Page 3 [inserted]', True, 2);
  942 
  943       // draw page rectangle
  944       DrawPageRect(lpdf, 2);
  945 
  946       // test stored page sizes
  947       for ii := 0 to 4 do
  948       begin
  949          width_mm := 0;
  950          height_mm := 0;
  951 
  952          lpdf.GetPageSize(ii, width_mm, height_mm);
  953 
  954          // the conversion is not needed here, because the current
  955          // unit set on the lpdf is in millimeters, but done anyway,
  956          // to show the usage of the conversion routine
  957          width_mm := Trunc(lpdf.UnitToMM(width_mm));
  958          height_mm := Trunc(lpdf.UnitToMM(height_mm));
  959 
  960          if (width_mm <> sizes[ii].cx) or (height_mm <> sizes[ii].cy) then
  961          begin
  962             raise TLitePDFException.Create(ERROR_CANNOT_MAKE, AnsiString(
  963                   'page[' + IntToStr(ii) + '] size doesn''t match; expected ' +
  964                   IntToStr(sizes[ii].cx) + ' x ' + IntToStr(sizes[ii].cy) +
  965                   ', but got ' + IntToStr(width_mm) + ' x ' + IntToStr(height_mm)));
  966          end;
  967       end;
  968 
  969       // save to file
  970       lpdf.SaveToFile('delphi-pagesperpage-1.pdf');
  971 
  972       // close the document
  973       lpdf.Close;
  974 
  975       //-----------------------------------------------------------------
  976 
  977       // load from file
  978       lpdf.LoadFromFile('delphi-pagesperpage-1.pdf', '', True);
  979 
  980       // check the opened file has correct page count
  981       pages := lpdf.GetPageCount;
  982       if pages <> 5 then
  983       begin
  984          raise TLitePDFException.Create(ERROR_CANNOT_MAKE, AnsiString(
  985             'The opened document doesn''t have 5 pages, but ' + IntToStr(pages)));
  986       end;
  987 
  988       // convert pages to resources
  989       for ii := 0 to 4 do
  990       begin
  991          width_mm := 0;
  992          height_mm := 0;
  993 
  994          lpdf.GetPageSize(ii, width_mm, height_mm);
  995 
  996          // the conversion is not needed here, because the current
  997          // unit set on the lpdf is in millimeters, but done anyway,
  998          // to show the usage of the conversion routine
  999          width_mm := Trunc(lpdf.UnitToMM(width_mm));
 1000          height_mm := Trunc(lpdf.UnitToMM(height_mm));
 1001 
 1002          if (width_mm <> sizes[ii].cx) or (height_mm <> sizes[ii].cy) then
 1003          begin
 1004             raise TLitePDFException.Create(ERROR_CANNOT_MAKE, AnsiString(
 1005                   'page[' + IntToStr(ii) + '] size doesn''t match; expected ' +
 1006                   IntToStr(sizes[ii].cx) + ' x ' + IntToStr(sizes[ii].cy) +
 1007                   ', but got ' + IntToStr(width_mm) + ' x ' + IntToStr(height_mm)));
 1008          end;
 1009 
 1010          resources[ii] := lpdf.PageToResource(ii);
 1011 
 1012          width_mm := 0;
 1013          height_mm := 0;
 1014 
 1015          lpdf.GetResourceSize(resources[ii], width_mm, height_mm);
 1016 
 1017          // the conversion is not needed here, because the current
 1018          // unit set on the lpdf is in millimeters, but done anyway,
 1019          // to show the usage of the conversion routine
 1020          width_mm := Trunc(lpdf.UnitToMM(width_mm));
 1021          height_mm := Trunc(lpdf.UnitToMM(height_mm));
 1022 
 1023          if (width_mm <> sizes[ii].cx) or (height_mm <> sizes[ii].cy) then
 1024          begin
 1025             raise TLitePDFException.Create(ERROR_CANNOT_MAKE, AnsiString(
 1026                   'resource ID ' + IntToStr(resources[ii]) + ' from ' +
 1027                   'page[' + IntToStr(ii) + '] size doesn''t match; expected ' +
 1028                   IntToStr(sizes[ii].cx) + ' x ' + IntToStr(sizes[ii].cy) +
 1029                   ', but got ' + IntToStr(width_mm) + ' x ' + IntToStr(height_mm)));
 1030          end;
 1031       end;
 1032 
 1033       // delete pages
 1034       for ii := 0 to 4 do
 1035       begin
 1036          lpdf.DeletePage(0);
 1037       end;
 1038 
 1039       // there should be no pages now
 1040       pages := lpdf.GetPageCount;
 1041       if pages <> 0 then
 1042       begin
 1043          raise TLitePDFException.Create(ERROR_CANNOT_MAKE, AnsiString(
 1044                'The opened document doesn''t have 0 pages, but ' + IntToStr(pages)));
 1045       end;
 1046 
 1047       // draw resources (former pages) into new pages
 1048       ii := 0;
 1049       while ii <= 4 do
 1050       begin
 1051          pageSzX := sizes[ii].cy;
 1052          pageSzY := sizes[ii].cx;
 1053 
 1054          // create a new page without drawing into it
 1055          hDC := lpdf.AddPage(Trunc(lpdf.MMToUnit(pageSzX)),
 1056                              Trunc(lpdf.MMToUnit(pageSzY)),
 1057                              pageSzX, pageSzY,
 1058                              LongWord(LitePDFDrawFlag_None));
 1059          lpdf.FinishPage(hDC);
 1060 
 1061          offsetY := 0.0;
 1062          lpdf.GetResourceSize(resources[ii], width_mm, height_mm);
 1063 
 1064          // the conversion is not needed here, because the current
 1065          // unit set on the lpdf is in millimeters, but done anyway,
 1066          // to show the usage of the conversion routine
 1067          width_mm := Trunc(lpdf.UnitToMM(width_mm));
 1068          height_mm := Trunc(lpdf.UnitToMM(height_mm));
 1069 
 1070          scaleX := pageSzX / 2.0 / width_mm;
 1071          scaleY := pageSzY / height_mm;
 1072 
 1073          if width_mm > height_mm then
 1074          begin
 1075             scaleY := scaleY / 2.0;
 1076             scaleX := scaleX * 2.0;
 1077             offsetY := pageSzY / 2.0;
 1078          end;
 1079 
 1080          // draw the first page on the left part
 1081          lpdf.DrawResourceWithMatrix(resources[ii], lpdf.GetPageCount - 1,
 1082                                      scaleX, 0.0, 0.0, scaleY, 0.0, offsetY);
 1083 
 1084          if ii + 1 < 5 then
 1085          begin
 1086             lpdf.GetResourceSize(resources[ii + 1], width_mm, height_mm);
 1087 
 1088             // the conversion is not needed here, because the current
 1089             // unit set on the lpdf is in millimeters, but done anyway,
 1090             // to show the usage of the conversion routine
 1091             width_mm := Trunc(lpdf.UnitToMM(width_mm));
 1092             height_mm := Trunc(lpdf.UnitToMM(height_mm));
 1093 
 1094             scaleX := pageSzX / 2.0 / width_mm;
 1095             scaleY := pageSzY / height_mm;
 1096 
 1097             if width_mm > height_mm then
 1098             begin
 1099                scaleY := scaleY / 2.0;
 1100             end;
 1101 
 1102             // draw the second page on the right part
 1103             lpdf.DrawResource(resources[ii + 1], lpdf.GetPageCount - 1,
 1104                               LitePDFUnit_1000th_mm, // for better accuracy
 1105                               Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, pageSzX / 2)),
 1106                               Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, 0.0)),
 1107                               Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, scaleX)),
 1108                               Trunc(lpdf.MMToUnitEx(LitePDFUnit_1000th_mm, scaleY)));
 1109          end;
 1110 
 1111          ii := ii + 2;
 1112       end;
 1113 
 1114       // save to file
 1115       lpdf.SaveToFile('delphi-pagesperpage-2.pdf');
 1116 
 1117       // close the document
 1118       lpdf.Close;
 1119    finally
 1120       // destroy the TLitePDF instance
 1121       lpdf.Destroy;
 1122    end;
 1123 end;
 1124 
 1125 //----------------------------------------------------------------------------
 1126 //   helper definitions for sign example
 1127 //----------------------------------------------------------------------------
 1128 
 1129 {$IFDEF WIN64}
 1130 {$ALIGN ON}
 1131 {$ELSE}
 1132 {$ALIGN 4}
 1133 {$ENDIF}
 1134 
 1135 {$MINENUMSIZE 4}
 1136 
 1137 type
 1138    PCRYPT_DATA_BLOB = ^CRYPT_DATA_BLOB;
 1139    CRYPT_DATA_BLOB = record
 1140       cbData : DWORD;
 1141       pbData : PByte;
 1142    end;
 1143 
 1144    {$EXTERNALSYM CRYPT_DATA_BLOB}
 1145    CRYPT_OBJID_BLOB = CRYPT_DATA_BLOB;
 1146    {$EXTERNALSYM CRYPT_OBJID_BLOB}
 1147 
 1148    PCCERT_CONTEXT = Pointer;
 1149    {$EXTERNALSYM PCCERT_CONTEXT}
 1150 
 1151    HCERTSTORE = Pointer;
 1152    {$EXTERNALSYM HCERTSTORE}
 1153 
 1154    PCRYPT_ALGORITHM_IDENTIFIER = ^CRYPT_ALGORITHM_IDENTIFIER;
 1155    CRYPT_ALGORITHM_IDENTIFIER = record
 1156     pszObjId : LPSTR;
 1157     Parameters : CRYPT_OBJID_BLOB;
 1158    end;
 1159    {$EXTERNALSYM CRYPT_ALGORITHM_IDENTIFIER}
 1160 
 1161    PCRYPT_SIGN_MESSAGE_PARA = ^CRYPT_SIGN_MESSAGE_PARA;
 1162    CRYPT_SIGN_MESSAGE_PARA = record
 1163       cbSize : DWORD;
 1164       dwMsgEncodingType : DWORD;
 1165       pSigningCert : PCCERT_CONTEXT;
 1166       HashAlgorithm : CRYPT_ALGORITHM_IDENTIFIER;
 1167       pvHashAuxInfo : Pointer;
 1168       cMsgCert : DWORD;
 1169       rgpMsgCert : ^PCCERT_CONTEXT;
 1170       cMsgCrl : DWORD;
 1171       rgpMsgCrl : ^Pointer;
 1172       cAuthAttr : DWORD;
 1173       rgAuthAttr : Pointer; // PCRYPT_ATTRIBUTE
 1174       cUnauthAttr : DWORD;
 1175       rgUnauthAttr : Pointer; // PCRYPT_ATTRIBUTE
 1176       dwFlags : DWORD;
 1177       dwInnerContentType : DWORD;
 1178    end;
 1179    {$EXTERNALSYM CRYPT_SIGN_MESSAGE_PARA}
 1180 
 1181    PPByte = ^PByte;
 1182 
 1183 const
 1184    PKCS_7_ASN_ENCODING = $00010000;
 1185    X509_ASN_ENCODING = $00000001;
 1186    CERT_FIND_ANY = 0;
 1187 
 1188 function PFXIsPFXBlob(
 1189       pPFX : PCRYPT_DATA_BLOB) : BOOL; stdcall;
 1190       external 'crypt32.dll' name 'PFXIsPFXBlob';
 1191 
 1192 function PFXImportCertStore(
 1193       pPFX: PCRYPT_DATA_BLOB;
 1194       szPassword: PWideChar;
 1195       dwFlags : DWORD) : HCERTSTORE; stdcall;
 1196       external 'crypt32.dll' name 'PFXImportCertStore';
 1197 
 1198 function CertFindCertificateInStore(
 1199       ppCertStore : HCERTSTORE;
 1200       dwCertEncodingType : DWORD;
 1201       dwFindFlags : DWORD;
 1202       dwFindType : DWORD;
 1203       pvFindPara : Pointer;
 1204       pPrevCertContext : PCCERT_CONTEXT) : PCCERT_CONTEXT; stdcall;
 1205       external 'crypt32.dll' name 'CertFindCertificateInStore';
 1206 
 1207 function CryptSignMessage(
 1208       pSignPara : PCRYPT_SIGN_MESSAGE_PARA;
 1209       fDetachedSignature : BOOL;
 1210       cToBeSigned : DWORD;
 1211       rgpbToBeSigned : PPByte;
 1212       rgcbToBeSigned : PDWORD;
 1213       pbSignedBlob : PByte;
 1214       pcbSignedBlob : PLongWord) : BOOL; stdcall;
 1215       external 'crypt32.dll' name 'CryptSignMessage';
 1216 
 1217 function CertFreeCertificateContext(
 1218       ppCertContext : PCCERT_CONTEXT) : BOOL; stdcall;
 1219       external 'crypt32.dll' name 'CertFreeCertificateContext';
 1220 
 1221 function CertCloseStore(
 1222       ppCertStore : HCERTSTORE;
 1223       dwFlags : DWORD) : BOOL; stdcall;
 1224       external 'crypt32.dll' name 'CertCloseStore';
 1225 
 1226 //----------------------------------------------------------------------------
 1227 //   helper class for sign example
 1228 //----------------------------------------------------------------------------
 1229 
 1230 type MPdfSigner = class
 1231  protected
 1232    m_bytes : Pointer;
 1233    m_bytes_len : LongWord;
 1234    m_lastSignatureIndex : LongWord;
 1235 
 1236    procedure loadCertificateStore(var hStore : HCERTSTORE);
 1237    procedure AddData(pBytes : PByte; pBytes_len : LongWord);
 1238    procedure Finish(signature : PByte; signature_len : PLongWord);
 1239    function CreateSignatureField(lpdf : TLitePDF;
 1240                                  signatureName : AnsiString;
 1241                                  dateOfSign : TDateTime;
 1242                                  annotationResourceID : LongWord;
 1243                                  annotationPageIndex : LongWord;
 1244                                  annotationPosition_mm : TRect;
 1245                                  annotationFlags : LongWord;
 1246                                  signatureLen : Integer) : LongWord;
 1247  public
 1248    constructor Create;
 1249    destructor Destroy; override;
 1250 
 1251    procedure Clear;
 1252 
 1253    procedure SignToFile(lpdf : TLitePDF;
 1254                         fileName : AnsiString;
 1255                         signatureName : AnsiString);
 1256 
 1257    procedure SignToFileEx(lpdf : TLitePDF;
 1258                           fileName : AnsiString;
 1259                           signatureName : AnsiString;
 1260                           annotationResourceID : LongWord;
 1261                           annotationPageIndex : LongWord;
 1262                           annotationPosition_mm : TRect;
 1263                           annotationFlags : LongWord);
 1264 
 1265    function SignToData(lpdf : TLitePDF;
 1266                        data : PByte;
 1267                        var dataLength : LongWord;
 1268                        signatureName : AnsiString) : Boolean;
 1269 end;
 1270 
 1271 procedure appendSignatureData(bytes : PByte; bytes_len : LongWord; user_data : Pointer); stdcall;
 1272 var signer : MPdfSigner;
 1273 begin
 1274    signer := MPdfSigner(user_data);
 1275    signer.AddData(bytes, bytes_len);
 1276 end;
 1277 
 1278 procedure finishSignature(signature : PByte; signature_len : PLongWord; user_data : Pointer); stdcall;
 1279 var signer : MPdfSigner;
 1280 begin
 1281    signer := MPdfSigner(user_data);
 1282    signer.Finish(signature, signature_len);
 1283 end;
 1284 
 1285 constructor MPdfSigner.Create;
 1286 begin
 1287    m_bytes := nil;
 1288    m_bytes_len := 0;
 1289    m_lastSignatureIndex := $FFFFFFFF;
 1290 end;
 1291 
 1292 destructor MPdfSigner.Destroy;
 1293 begin
 1294    Clear;
 1295 end;
 1296 
 1297 procedure MPdfSigner.Clear;
 1298 begin
 1299    if m_bytes <> nil then
 1300    begin
 1301       FreeMem(m_bytes);
 1302       m_bytes := nil;
 1303    end;
 1304    m_bytes_len := 0;
 1305    m_lastSignatureIndex := $FFFFFFFF;
 1306 end;
 1307 
 1308 procedure MPdfSigner.loadCertificateStore(var hStore : HCERTSTORE);
 1309 var certFile : TMemoryStream;
 1310     blob : CRYPT_DATA_BLOB;
 1311 begin
 1312    certFile := TMemoryStream.Create;
 1313    try
 1314       certFile.LoadFromFile('cert.pfx');
 1315 
 1316       blob.cbData := certFile.Size;
 1317       blob.pbData := certFile.Memory;
 1318       if PFXIsPFXBlob(@blob) then
 1319          hStore := PFXImportCertStore(@blob, '', 0);
 1320    finally
 1321       certFile.Destroy;
 1322    end;
 1323 end;
 1324 
 1325 procedure MPdfSigner.AddData(pBytes : PByte; pBytes_len : LongWord);
 1326 var shifted_bytes : PByte;
 1327     ii : LongWord;
 1328 begin
 1329    if m_bytes = nil then
 1330       GetMem(m_bytes, SizeOf(Byte) * pBytes_len * 2)
 1331    else
 1332       ReallocMem(m_bytes, SizeOf(Byte) * (m_bytes_len + pBytes_len));
 1333 
 1334    shifted_bytes := PByte(m_bytes) + m_bytes_len;
 1335    for ii := 0 to pBytes_len - 1 do
 1336    begin
 1337       shifted_bytes[ii] := pBytes[ii];
 1338    end;
 1339    m_bytes_len := m_bytes_len + pBytes_len;
 1340 end;
 1341 
 1342 procedure MPdfSigner.Finish(signature : PByte; signature_len : PLongWord);
 1343 var hStore : HCERTSTORE;
 1344     hCertContext : PCCERT_CONTEXT;
 1345     MessageArray : PByte;
 1346     MessageSizeArray : LongWord;
 1347     SigParams : CRYPT_SIGN_MESSAGE_PARA;
 1348 begin
 1349    hStore := nil;
 1350    hCertContext := nil;
 1351 
 1352    MessageArray := m_bytes;
 1353    MessageSizeArray := m_bytes_len;
 1354 
 1355    loadCertificateStore(hStore);
 1356    if hStore = nil then
 1357    begin
 1358       raise TLitePDFException.Create(GetLastError, AnsiString(
 1359                                      'Failed to open a temporary store: ' +
 1360                                      SysErrorMessage(GetLastError)));
 1361    end;
 1362 
 1363    hCertContext := CertFindCertificateInStore(hStore,
 1364          PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, 0, CERT_FIND_ANY,
 1365          nil, nil);
 1366    if hCertContext = nil then
 1367    begin
 1368       CertCloseStore(hStore, 0);
 1369       raise TLitePDFException.Create(GetLastError, AnsiString(
 1370                                      'Failed to find certificate in the store: ' +
 1371                                      SysErrorMessage(GetLastError)));
 1372    end;
 1373 
 1374    FillChar(SigParams, SizeOf(CRYPT_SIGN_MESSAGE_PARA), 0);
 1375 
 1376    SigParams.cbSize := SizeOf(CRYPT_SIGN_MESSAGE_PARA);
 1377    SigParams.dwMsgEncodingType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
 1378    SigParams.pSigningCert := hCertContext;
 1379    SigParams.HashAlgorithm.pszObjId := '1.2.840.113549.1.1.5'; // szOID_RSA_SHA1RSA
 1380    SigParams.HashAlgorithm.Parameters.pbData := nil;
 1381    SigParams.HashAlgorithm.Parameters.cbData := 0;
 1382    SigParams.pvHashAuxInfo := nil;
 1383    SigParams.cMsgCert := 1;
 1384    SigParams.rgpMsgCert := @hCertContext;
 1385    SigParams.cMsgCrl := 0;
 1386    SigParams.rgpMsgCrl := nil;
 1387    SigParams.cAuthAttr := 0;
 1388    SigParams.rgAuthAttr := nil;
 1389    SigParams.cUnauthAttr := 0;
 1390    SigParams.rgUnauthAttr := nil;
 1391    SigParams.dwFlags := 0;
 1392    SigParams.dwInnerContentType := 0;
 1393 
 1394    if not CryptSignMessage(
 1395          @SigParams,            // Signature parameters
 1396          TRUE,                  // detached ?
 1397          1,                     // Number of messages
 1398          @MessageArray,         // Messages to be signed
 1399          @MessageSizeArray,     // Size of messages
 1400          signature,             // Buffer for signed message
 1401          signature_len) then
 1402    begin
 1403       CertFreeCertificateContext(hCertContext);
 1404       CertCloseStore(hStore, 0);
 1405 
 1406       raise TLitePDFException.Create(GetLastError, AnsiString (
 1407          'Failed to sign data: ' + SysErrorMessage(GetLastError)));
 1408    end;
 1409 
 1410    CertFreeCertificateContext(hCertContext);
 1411    CertCloseStore(hStore, 0);
 1412 end;
 1413 
 1414 function MPdfSigner.CreateSignatureField(lpdf : TLitePDF;
 1415                                          signatureName : AnsiString;
 1416                                          dateOfSign : TDateTime;
 1417                                          annotationResourceID : LongWord;
 1418                                          annotationPageIndex : LongWord;
 1419                                          annotationPosition_mm : TRect;
 1420                                          annotationFlags : LongWord;
 1421                                          signatureLen : Integer) : LongWord;
 1422 var signatureIndex : LongWord;
 1423 begin
 1424    lpdf.SetSignatureSize(signatureLen);
 1425 
 1426    signatureIndex := lpdf.CreateSignature(signatureName,
 1427                                           annotationPageIndex,
 1428                                           annotationPosition_mm,
 1429                                           annotationFlags);
 1430 
 1431    lpdf.SetSignatureReason(signatureIndex, 'litePDF example');
 1432    lpdf.SetSignatureDate(signatureIndex, dateOfSign);
 1433 
 1434    if annotationResourceID and annotationPageIndex < lpdf.GetPageCount() then
 1435    begin
 1436       lpdf.SetSignatureAppearance(signatureIndex, LitePDFAppearance_Normal, annotationResourceID, 0, 0);
 1437    end;
 1438 
 1439    Result := signatureIndex;
 1440 end;
 1441 
 1442 procedure MPdfSigner.SignToFile(lpdf : TLitePDF;
 1443                                 fileName : AnsiString;
 1444                                 signatureName : AnsiString);
 1445 var rect_mm : TRect;
 1446 begin
 1447    rect_mm := Rect(0, 0, 0, 0);
 1448 
 1449    SignToFileEx(lpdf, fileName, signatureName, 0, 0, rect_mm, 0);
 1450 end;
 1451 
 1452 procedure MPdfSigner.SignToFileEx(lpdf : TLitePDF;
 1453                                   fileName : AnsiString;
 1454                                   signatureName : AnsiString;
 1455                                   annotationResourceID : LongWord;
 1456                                   annotationPageIndex : LongWord;
 1457                                   annotationPosition_mm : TRect;
 1458                                   annotationFlags : LongWord);
 1459 var signatureIndex : LongWord;
 1460 begin
 1461    signatureIndex := CreateSignatureField(lpdf,
 1462                                           signatureName,
 1463                                           System.SysUtils.EncodeDate(1970, 1, 1), { works as today }
 1464                                           annotationResourceID,
 1465                                           annotationPageIndex,
 1466                                           annotationPosition_mm,
 1467                                           annotationFlags,
 1468                                           0);
 1469 
 1470    lpdf.SaveToFileWithSignManual(fileName,
 1471                                  signatureIndex,
 1472                                  appendSignatureData, self,
 1473                                  finishSignature, self);
 1474 end;
 1475 
 1476 function MPdfSigner.SignToData(lpdf : TLitePDF;
 1477                                data : PByte;
 1478                                var dataLength : LongWord;
 1479                                signatureName : AnsiString) : Boolean;
 1480 var rect_mm : TRect;
 1481     signatureIndex : LongWord;
 1482 begin
 1483    rect_mm := Rect(0, 0, 0, 0);
 1484 
 1485    if m_lastSignatureIndex = $FFFFFFFF then
 1486    begin
 1487       signatureIndex := CreateSignatureField(lpdf,
 1488                                             signatureName,
 1489                                             System.SysUtils.EncodeDate(1970, 1, 1),
 1490                                             0, 0, rect_mm, 0, 0);
 1491       // remember the used signature index for the second call,
 1492       // when populating the 'data'
 1493       m_lastSignatureIndex := signatureIndex;
 1494    end else begin
 1495       signatureIndex := m_lastSignatureIndex;
 1496    end;
 1497 
 1498    Result := lpdf.SaveToDataWithSignManual(signatureIndex,
 1499                                            appendSignatureData, self,
 1500                                            finishSignature, self,
 1501                                            data, dataLength);
 1502 end;
 1503 
 1504 //----------------------------------------------------------------------------
 1505 //   sign example
 1506 //----------------------------------------------------------------------------
 1507 
 1508 procedure TDelphiFrm.SignManualBtnClick(Sender: TObject);
 1509 // helper function
 1510 function createResource(lpdf : TLitePDF) : LongWord;
 1511 var hDC : THandle;
 1512     w, h : Integer;
 1513     canvas : TCanvas;
 1514 begin
 1515    w := 25;
 1516    h := 8;
 1517 
 1518    // create a new resource
 1519    hDC := lpdf.AddResource(Trunc(lpdf.MMToUnit(w)),
 1520                            Trunc(lpdf.MMToUnit(h)),
 1521                            w * 20, h * 20,
 1522                            LongWord(LitePDFDrawFlag_SubstituteFonts));
 1523 
 1524    canvas := TCanvas.Create;
 1525    try
 1526       // prepare canvas
 1527       canvas.Handle := hDC;
 1528       canvas.Pen.Style := psDot;
 1529       canvas.Pen.Color := clGray;
 1530       canvas.Pen.Width := 1;
 1531       canvas.Font.Name := 'Helvetica';
 1532       canvas.Font.Size := -40;
 1533 
 1534       // rectangle on boundaries
 1535       canvas.MoveTo(0, 0);
 1536       canvas.LineTo(w * 20, 0);
 1537       canvas.LineTo(w * 20, h * 20);
 1538       canvas.LineTo(0, h * 20);
 1539       canvas.LineTo(0, 0);
 1540 
 1541       // draw the text
 1542       canvas.TextOut(50, 20, 'litePDF example');
 1543       canvas.TextOut(50, 70, 'Signature');
 1544    finally
 1545       canvas.Destroy;
 1546    end;
 1547 
 1548    // finish drawing
 1549    result := lpdf.FinishResource(hDC);
 1550 end;
 1551 
 1552 var lpdf : TLitePDF;
 1553     signer : MPdfSigner;
 1554     where_mm : TRect;
 1555 begin
 1556    lpdf := TLitePDF.Create;
 1557    signer := MPdfSigner.Create;
 1558 
 1559    try
 1560       // create a document
 1561       lpdf.CreateMemDocument;
 1562 
 1563       // create some pages
 1564       AddPage(lpdf, 210, 297, 'Digitally signed document');
 1565       AddPage(lpdf, 210, 297, 'Page 2');
 1566 
 1567       // create also visual appearance for this signature, on the second page
 1568       where_mm := Rect(Trunc(lpdf.MMToUnit(90)),      Trunc(lpdf.MMToUnit(5)),
 1569                        Trunc(lpdf.MMToUnit(90 + 25)), Trunc(lpdf.MMToUnit(5 + 8)));
 1570 
 1571       // save signed to a file
 1572       signer.Clear;
 1573       signer.SignToFileEx(lpdf, 'delphi-sign-1.pdf', 'Sig1',
 1574          createResource(lpdf),
 1575          1,
 1576          where_mm,
 1577          LongWord(LitePDFAnnotationFlag_None));
 1578 
 1579       // close the document
 1580       lpdf.Close;
 1581    finally
 1582       // destroy the TLitePDF and MPdfSigner instances
 1583       lpdf.Destroy;
 1584       signer.Destroy;
 1585    end;
 1586 end;
 1587 
 1588 end.
TOPlist