You are not logged in.
I'm trying to implement a "multiple pages per sheet" feature for my PDF output. I'm currently rendering a single metafile to each page of the PDF document, calling TPdfCanvas.RenderMetaFile to achieve that. It works a treat.
However, I'm not trying to call this function multiple times on the same page with no luck. I'm seeing nothing at all in the generated PDF, or sometimes just a couple of parts of one of the metafiles. But certainly not multiple metafile graphics around the page.
Before I carry on, is this something that I can expect to do, or do I need to find another approach? I know that I can create my own metafile canvas, render my metafiles to that canvas, and finally render the composite metafile to the PDF document with a single call to TPdfCanvas.RenderMetaFile. I was hoping to avoid having to use that extra metafile to prepare my pages.
If I should be able to call TPdfCanvas.RenderMetaFile multiple times per page, and you'd like to dig into this, I'll prepare a reproduction of the issue. I've not done that yet because it would take a little while to extract it from my complex application code. And I didn't want to spend that time if the answer was a simple, "this can never work, do it a different way".
Offline
Hmm, I think I'm going to have to make a small reproduction. The issue seems perhaps to be related to the inclusion of text in the metafile. Without that, behaviour is fine. Let me put together a reproduction.
Offline
I'm not sure what you mean by "the main metafile". Anyway, I'm working on a repro. No point doing any more until I have something concrete.
Last edited by davidheffernan (2017-06-14 12:31:47)
Offline
OK, here's a simple reproduction:
program RenderMetafile;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
Winapi.Windows,
Vcl.Graphics,
SynCommons in 'SynCommons.pas',
SynLZ in 'SynLZ.pas',
SynPdf in 'SynPdf.pas';
var
Doc: TPdfDocument;
Page: TPdfPage;
Metafile: TMetafile;
Canvas: TMetafileCanvas;
i: Integer;
begin
Metafile := TMetafile.Create;
Metafile.SetSize(200, 200);
Canvas := TMetafileCanvas.Create(Metafile, GetDC(0));
Canvas.TextOut(10, 10, 'SynPDF is the best!');
Canvas.Free;
Doc := TPdfDocument.Create;
Doc.DefaultPaperSize := psA4;
Page := Doc.AddPage;
Page.PageLandscape := False;
for i := 1 to 20 do begin
Doc.Canvas.RenderMetaFile(Metafile, 1.0, 0.0, 20.0, i*20.0);
end;
Doc.SaveToFile('test.pdf');
Doc.Free;
end.
There should be 20 instances of the text of the page, but there is just the first one. If instead of the TextOut, I make a call to MoveTo/LineTo, then multiple instances of the line appear.
Offline
RenderMetaFile is not expected to be called more than once on a page, I guess.
But you can play your MetaFile text content several times.
The easiest way is to use TPdfDocumentGDI, not plain TPdfDocument, and draw the MetaFile text content on its VCL canvas.
As an alternative, you may create a new metafile, on which you draw the MetaFile text content several times.
Offline
Isn't this a bug though. Why would it be possible to use RenderMetafile multiple times, apart from when there is text? It feels like the metafile enumeration code is failing to handle text properly.
Offline
It may be a bug, you are right.
But we never observed it up to now - this is not how we use RenderMetaFile.
Using TPdfDocumentGDI has other advantages, like ability to have a preview, and direct use of the VCL canvas.
Did you try to debug and find out why you don't obtain what you expect?
Isn't any problem with the offset?
Did you try to let uncompressed pdf be generated and inspect the resulting postscript commands?
Offline
I'm actually mixing metafiles and raster images. For the former, I can, as you say, use TPdfDocumentGDI and render the metafile to the VCL canvas. That seems to have no problems with multiple metafiles. For my raster images, I think it is better to use AddXObject and DrawXObject because that embeds the image in the document, which can be stretched appropriately by the PDF render process. A bit of a fankle, but I think I can make it work!
Offline