#1 2010-06-28 17:22:32

chadjerzy
Member
Registered: 2010-06-28
Posts: 3

PDF Engine and htmlViewer

Can PDF Engine be used in companion with pbear's htmlViewer to produce PDF from HTML? Or maybe there is another way to do this?
Thanks.

Offline

#2 2010-06-28 21:01:27

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: PDF Engine and htmlViewer

Yes it's possible. It could be an handy way of converting a HTML file into a PDF content.
See the print preview feature of htmlViewer to guess how to print to a metafile canvas, then draw this metafile using the corresponding method of our PDF engine.

Offline

#3 2010-07-04 15:10:02

chadjerzy
Member
Registered: 2010-06-28
Posts: 3

Re: PDF Engine and htmlViewer

It works but I have some problems with calculation of page size. Currently it's hard-coded. Also I don't know which method 1 or 2 is better in terms of SynPdf. If there is no difference I would stick with method 1 as this method not depend on current printer.
Thanks.

procedure TForm1.FormActivate(Sender: TObject);
var
    i: Integer;
    Pdf: TPdfDocument;
    Pages: TList;
    MyMetafile: TMetafile;
    Gdi: TPdfDocumentGDI;
    MFPrinter: TMetaFilePrinter;
begin
    // 1. Using TPdfDocument and Viewer.MakePagedMetaFiles
    Pdf := TPdfDocument.Create;
    try
        Pdf.DefaultPaperSize := psA4;
        Pages := Viewer.MakePagedMetaFiles(Trunc(Pdf.DefaultPageWidth * 1.30), Trunc(Pdf.DefaultPageHeight * 1.30)); // Not very elegant...
        for i := 0 to Pages.Count - 1 do
        begin
            Pdf.AddPage;
            MyMetafile := TMetafile.Create;
            with TMetafileCanvas.Create(MyMetafile, 0) do
            try
                Draw(51, 18, TMetafile(Pages[i])); // To center metafile on page create new metafile...
            finally
                Free;
            end;
            Pdf.Canvas.RenderMetaFile(MyMetafile);
            TMetafile(Pages[i]).Free;
            MyMetafile.Free;
        end;
        Pages.Free;
        Pdf.SaveToFile('c:\temp\output.pdf');
    finally
        Pdf.Free;
    end;
    // 2. Using TPdfDocumentGDI
    Gdi := TPdfDocumentGDI.Create;
    try
        Printer.Orientation := poPortrait;
        MFPrinter := TMetaFilePrinter.Create(nil);
        Viewer.PrintPreview(MFPrinter);
        Gdi.DefaultPageWidth := Trunc(MFPrinter.PaperWidth / MFPrinter.PixelsPerInchX * PixelsPerInch); // This is not A4 but should be
        Gdi.DefaultPageHeight := Trunc(MFPrinter.PaperHeight / MFPrinter.PixelsPerInchY * PixelsPerInch);
        for i := 0 to MFPrinter.LastAvailablePage - 1 do
        begin
            Gdi.AddPage;
            SetMapMode(Gdi.VCLCanvas.Handle, MM_ANISOTROPIC);
            SetWindowExtEx(Gdi.VCLCanvas.Handle, MFPrinter.PaperWidth, MFPrinter.PaperHeight, nil);
            SetViewportExtEx(Gdi.VCLCanvas.Handle, Trunc(Gdi.DefaultPageWidth * 2.86), Trunc(Gdi.DefaultPageHeight * 2.86), nil);
            SetWindowOrgEx(Gdi.VCLCanvas.Handle, 0, 0, nil);
            Gdi.VCLCanvas.Draw(-10, 0, MFPrinter.MetaFiles[i]);
        end;
        MFPrinter.Free;
        Gdi.SaveToFile('c:\temp\gdioutput.pdf');
    finally
        Gdi.Free;
    end;
end;

Offline

#4 2010-07-04 15:59:32

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: PDF Engine and htmlViewer

About page size, see code available in function CurrentPrinterPaperSize to guess TPDFPaperSize from current printer setting. But I think you already find out this function. wink

I think you can put whatever value for TMetaFile size calculation: 1.30 is good but you can use *2 or *4... perhaps if you've a lot of bitmap files, it will change. I guess your 1.30 value was obtained from experiment to obtain some margins...

As far as I understand (I'm no HtmlView expert), both method do play metafiles inside metafiles. For SynPdf library, it's almost the same... I suspect that MakePagedMetaFiles()  code is faster (and cleaner) than using a TMetaFilePrinter. So I'd guess that method 1 is to be recommended.

In order to easily center the metafile on page, I've added optional XOff,YOff parameters to the RenderMetaFile() method. You should adjust the scale parameter to maintain the aspect ratio, and have margins without playing with the 1.3 multiplier above. And won't have to play the metafile inside another metafile just for centering it on the page...

You can download 1.8.2 version of SynPDF from http://synopse.info/fossil

In all cases, method 1 just looks more elegant to me.

What about making a html2pdf command-line or with easy GUI utility? It would be great if we could publish this Synopse's web site, with your permission and credit for the idea and debugging, of course.

Offline

#5 2010-07-13 17:18:03

chadjerzy
Member
Registered: 2010-06-28
Posts: 3

Re: PDF Engine and htmlViewer

I have done it. If you send me email i'll send it to you.

Offline

#6 2010-07-14 07:29:13

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: PDF Engine and htmlViewer

Great news!

Mail sent. smile

Offline

#7 2010-07-14 17:12:34

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: PDF Engine and htmlViewer

I received the code, made some enhancements, spend time on the THmlView source code in order to fix some issues (compatibility with Delphi 2010), fix some bugs in our SynPdf library... and here is the htm2pdf tool!

  http://synopse.info/forum/viewtopic.php?pid=187

Internal version of the PDF Engine is now in 1.8.3 - available in our Source Code Repository:
  - now handle EMR_STRETCHDIBITS (used in Html2Pdf)
  - fix strike out line position (was too low)

Thanks Pawel for this great idea and source code!

Offline

#8 2010-10-26 18:45:04

jonhnn
Member
Registered: 2010-10-25
Posts: 2

Re: PDF Engine and htmlViewer

I can not compile in Delphi 2006, appears several errors.

1. File not found: DockForm.dcu in ToolsAPI.pas
2. File note found: Proxies.dcu
3. file not found: 'DesignEditors.dcu

Offline

#9 2010-10-27 07:56:55

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: PDF Engine and htmlViewer

This is an issue in the THtmlView part of the code, IMHO.

I don't have D2006 at hand, so perhaps you could find out what's wrong here.

Offline

Board footer

Powered by FluxBB