Synopse Open Source - Tag - Uniscribe - CommentsmORMot MVC / SOA / ORM and friends2024-02-02T17:08:25+00:00urn:md5:cc547126eb580a9adbec2349d7c65274DotclearSynopse PDF engine 1.7.2 - A.Bouchezurn:md5:24cf0058eabdadcf759e01a0cf319edf2010-06-21T11:21:08+02:002010-06-21T10:21:08+02:00A.BouchezPlease discuss about the <i>Synopse PDF Library</i> in <a href="http://synopse.info/forum/viewforum.php?id=1" rel="ugc nofollow">our dedicated forum</a>.[ping] Synopse PDF engine 1.7.2 - oldtype's me2DAYurn:md5:7a7d1df5e5de293a0d76382752c595482010-06-21T08:38:00+02:002010-06-21T07:38:00+02:00oldtype's me2DAY<p><a href="http://me2day.net/oldtype/2010/06/21#15:33:47">우엉의 생각</a></p> <!-- TB -->
<p>Synopse PDF engine 1.7.2 유니코드를 지원하는 오픈소스 PDF 엔진...</p>Synopse PDF engine 1.7.2 - Esmondurn:md5:af8b1b635fc9f0d92c36f3d25e65d82a2010-06-17T00:23:38+02:002010-06-16T23:23:38+02:00Esmond<p>Thanks for the positive comments above.<br />
I've got a slight problem in that Acrobat reader 9 flashes up a message saying
'The file is damaged and is being repaired.' when opening it. The code I'm
using is:<br />
pdfDoc := TPdfDocument.Create;<br />
pdfpage := pdfDoc.AddPage;<br />
JpegImage := TJpegImage.Create;<br />
JpegImage.LoadFromFile('C:\image.jpg');<br />
pdfImage := TPdfImage.Create(pdfDoc, jpegimage);<br />
pdfDoc.AddXObject('image1', pdfimage);<br />
pdfDoc.Canvas.DrawXObject(0, pdfpage.PageHeight-JpegImage.Height,<br />
JpegImage.Width, JpegImage.Height, 'image1');<br />
pdfDoc.SaveToFile('c:\test.pdf');<br />
pdfDoc.Free;<br />
I downloaded the acrobat 9 trial and saved the synopse pdf as a version 1.3
pdf. Apart from re-numbering and reversing the order of the objects, taking out
some new lines and adding some xml the only strange thing was that the name
'image1' was changed to 'Im0' in the page object and page content stream but
left as 'image1' in the jpeg data stream (the object number reference was still
right). Is there a mistake in the code above or is the problem elsewhere?</p>Synopse PDF engine 1.7.2 - A. Bouchezurn:md5:f2b2b19a2e459f6ab1afc70819f5566a2010-06-16T09:51:55+02:002010-06-16T08:51:55+02:00A. Bouchez<p>If you use the VCLCanvas, you don't have to use the PixelsPerInch property:
just use the VCLCanvas methods and coordinates as usual. It has its own dpi. In
order to calculate the page size in VCLCanvas pixels units, use the
VCLCanvasSize property of the current TPdfDocumentGDI instance.</p>
<p>The framework will do all the resolution and coordinates mapping
calculations for you.</p>
<p>Thanks for your interest.</p>Synopse PDF engine 1.7.2 - Alexandreurn:md5:ed7c76eba0dd733889df8f53604d3f092010-06-16T04:45:02+02:002010-06-16T03:45:02+02:00Alexandre<p>First, thank you very much for this great library.</p>
<p>I am drawing a bitmap to VCLCanvas. In order to position it correctly, I
have to multiply all coordinates by Screen.PixelsPerInch/72, as in (where
pagina is the current pdf page - TPDFPage):</p>
<p>pdf.VCLCanvas.StretchDraw(Rect((30*Screen.PixelsPerInch) div 72,
(30*Screen.PixelsPerInch) div 72, ((pagina.PageWidth-30)*Screen.PixelsPerInch)
div 72, ((pagina.PageHeight-30)*Screen.PixelsPerInch) div 72), bmp);</p>
<p>Is this the correct way to do it?</p>Synopse PDF engine 1.7.2 - Renatourn:md5:a4879e5b7f6ad5e66d47b2e91311a2e42010-06-14T15:58:38+02:002010-06-14T14:58:38+02:00Renato<p>What do you think of creating a forum?</p>Synopse PDF engine 1.7.2 - A. Bouchezurn:md5:88cb486a86b10998e4398e219d863c162010-06-14T15:58:03+02:002010-06-14T14:58:03+02:00A. Bouchez<p>You can do it by creating a TPdfImage instance, then use the AddXObject to
register it into the pdf content, then use the DrawXObject method of the
TPdfCanvas on every page to clone it in all pages.</p>
<p>Check the TPdfEnum.DrawBitmap to see how these methods and classes are used.
The trick is just to create one TPdfImage instance, and draw it multiple times
on every page canvas.</p>Synopse PDF engine 1.7.2 - Renatourn:md5:9189b7b11b4485d2cacb99d7326b2ef32010-06-14T15:52:07+02:002010-06-14T14:52:07+02:00Renato<p>Ok,</p>
<p>i will waiting for 1.8 version.</p>
<p>Only one more question: The image printing<br />
It is possible to print image and clone on other pages like this:</p>
<p>Page 1: print bitmap<br />
Page 2: print clone bitmap of Page 1<br />
Page 3: print clone bitmap of Page 1<br />
Page 4: print clone bitmap of Page 1<br />
...</p>Synopse PDF engine 1.7.2 - Renatourn:md5:174f32909199f783ad7c9ea01dfdbac12010-06-14T15:43:37+02:002010-06-14T14:43:37+02:00Renato<p>Thank ya Bouchez..</p>
<p>working now.</p>Synopse PDF engine 1.7.2 - A.Bouchezurn:md5:296e8b6dbed9952aba3e9b3cccba82a82010-06-12T09:08:56+02:002010-06-12T08:08:56+02:00A.Bouchez<p>To Esmond:</p>
<p>Your modification to force producing pages is very interresting, but is a
bit tricky. I'll try to implement it with more respect to the engine
architecture.</p>
<p>About bitmaps and pictures in general, the engine still lack of
auto-compression to jpeg (as an option), and need some code refactoring to save
memory when using a lot of bitmaps.</p>
<p>I didn't need to add any bitmap in my projects, so I didn't make a lot of
tuning about them. IMHO PDF is better with vectorial processing, that's why I
added the internal EMF enumeration and conversion to PDF. But I understand that
you need bitmaps in your PDF.</p>
<p>So OK, I'll made better bitmap handling in the future.<br />
Thanks for your interrest.</p>Synopse PDF engine 1.7.2 - A.Bouchezurn:md5:29ab8dc016fd011cb64b4f938d79d46b2010-06-12T09:03:34+02:002010-06-12T08:03:34+02:00A.Bouchez<p>I had already modified the engine (in its up to come version 1.8) in order
to make font substitution if the font is not available, and use 'Arial' as a
default font if the specified font is not installed.</p>
<p>About dpi, see comment 3 above.</p>Synopse PDF engine 1.7.2 - Renatourn:md5:d296cf380ab8ae68e214ecaab44a8ef22010-06-09T20:23:29+02:002010-06-09T19:23:29+02:00Renato<p>on SynPDf.pas line 4046 the font index its returned -1 if the font is not
installed on system.</p>
<p>Need to hack here to set a default font (Arial) if fontindex returnet
-1.</p>
<p>if (FontIndex<0) then<br />
begin<br />
AName := 'Arial';<br />
FontIndex := fDoc.FTrueTypeFonts.IndexOf(AName);<br />
end;</p>
<p>Now I need to setup a resolution for pdf: 300, 600, 1200 dpi... how could it
is possible?</p>
<p>Gratz</p>Synopse PDF engine 1.7.2 - Esmondurn:md5:45b3bd19f5e027c9e2a1831c8b7d831a2010-06-09T01:53:56+02:002010-06-09T00:53:56+02:00Esmond<p>Using lots of images consumes lots of ram. To reduce this I've tried doing
an incremental save by working out the positions of all 'kids' pages of the
first page initially. After laying out the first page I run the routines below:
'AddFakePages' then 'FlushAddPage'. By freeing the TJpegImages after each page
in an unscientific test I saved 40% on ram. Can you give some tips on
incrementally free the memory used by TPdfDocument or am I barking up the wrong
tree with this method? Also thought about making image loading event driven to
reduce memory.</p>
<p><br />
procedure TPdfDocument.AddFakePages(PageCount, ObjPerPage: integer);<br />
var<br />
p : TPdfObject;<br />
FKids: TPdfArray;<br />
i, ii : integer;<br />
begin<br />
for i := 0 to PageCount - 1 do begin<br />
p := TPdfObject.Create;<br />
p.SetObjectNumber(FXref.ItemCount+(i*ObjPerPage));<br />
FKids := FCurrentPages.PdfArrayByName('Kids');<br />
FKids.AddItem(p);<br />
end;<br />
FCurrentPages.PdfNumberByName('Count').Value := FKids.ItemCount;<br />
end;</p>
<p>function TPdfDocument.FlushAddPage: TPdfPage;<br />
var<br />
FResources: TPdfDictionary;<br />
i, Pos : integer;<br />
begin<br />
for i := FXrefCount to FXref.ItemCount - 1 do // ignore FXref[0] = root
PDF_FREE_ENTRY<br />
with FXref.Items[i] do begin<br />
Pos := fPDFWrite.Position;<br />
Value.WriteValueTo(fPDFWrite);<br />
ByteOffset := Pos;<br />
end;<br />
FXrefCount := FXref.ItemCount;<br />
if FCurrentPages = nil then<br />
raise EPdfInvalidOperation.Create('AddPage');<br />
// create a new page object and add it to the current pages dictionary<br />
result := fTPdfPageClass.Create(self);<br />
FXref.AddObject(result);<br />
fRawPages.Add(result); // pages may be nested<br />
//_Pages_AddKids(FCurrentPages, result);<br />
result.AddItem('Type', 'Page');<br />
result.AddItem('Parent', FCurrentPages);<br />
// create page resources<br />
FResources := TPdfDictionary.Create(FXref);<br />
result.AddItem('Resources',FResources);<br />
FResources.AddItem('Font',TPdfDictionary.Create(FXref));<br />
FResources.AddItem('XObject',TPdfDictionary.Create(FXref));<br />
// create page content<br />
FResources.AddItem('ProcSet',TPdfArray.CreateNames(FXref,['PDF','Text','ImageC']));<br />
result.AddItem('Contents',TPdfStream.Create(self));<br />
// assign this page to the current PDF canvas<br />
FCanvas.SetPage(result);<br />
end;</p>Synopse PDF engine 1.7.2 - A. Bouchezurn:md5:7fe035644f92dd8c8e6a71a3be02ee172010-05-15T14:40:02+02:002010-05-15T13:40:02+02:00A. Bouchez<p>To greymont, about the Rectangle.</p>
<p>1. It looks like you are putting a "Rectangle" command inside a
BeginText/EndText block. This is not correct according to the PDF format.</p>
<p>2. Pay attention to your loops. The SetFont/SetLeading/SetLineWidth should
be ouside the loops, to reduce to PDF content size. You don't need either to
call BeginText/EndText each time if you are just using
MoveTextPoint/ShowText.</p>
<p>Try this code:</p>
<p>pPDF.AddPage;<br />
pPDF.Canvas.SetFont('Courier New',10,[]);<br />
pPDF.Canvas.SetLeading(pPDF.Canvas.Page.FontSize);<br />
pPDF.Canvas.SetLineWidth(0.5);<br />
pPDF.Canvas.BeginText;<br />
for vRow := 1 to 10 do begin<br />
for vCol := 1 to 10 do begin<br />
vX := (vCol-1)*cWidth+1;<br />
vY := pPDF.DefaultPageHeight-((vRow)*pPDF.Canvas.Page.FontSize);<br />
pPDF.Canvas.MoveTextPoint(vX,vY);<br />
pPDF.Canvas.ShowText('.',False);<br />
if vRow = vCol then begin<br />
pPDF.Canvas.EndText;<br />
pPDF.Canvas.Rectangle(vX,vY,cWidth,pPDF.Canvas.Page.FontSize);<br />
pPDF.Canvas.Stroke;<br />
pPDF.Canvas.BeginText;<br />
end;<br />
end;//for<br />
end;//for<br />
pPDF.Canvas.EndText;</p>Synopse PDF engine 1.7.2 - A. Bouchezurn:md5:dcfba3687c0ae324836156c18fd5e8072010-05-15T14:19:48+02:002010-05-15T13:19:48+02:00A. Bouchez<p>Response to greymont:</p>
<p>I'm getting a range check error from SynCommons.pas (version 1.7.4)when I
turn range checking on (Delphi 7). The function is<br />
procedure WinAnsiToUnicodeBuffer<br />
(....)</p>
<p>The range checking error is wrong about this. My code is correct.<br />
As stated by the comment " include S[L+1] = last #0 ", I need to copy also the
trailing #0, which is at S[i+1] i.e. S[L+1] with i=L: so the for loop is
correct.<br />
By compiler design, there is always a #0 at the end of any Delphi string. And
the caller expect this #0 to be appended, since most callers will use the
destination buffer with Win32 wide API.</p>Synopse PDF engine 1.7.2 - Mohammed Nasmanurn:md5:46599e17495ecc77cc85efccbbc7a2612010-05-14T20:20:34+02:002010-05-14T19:20:34+02:00Mohammed Nasman<p>Perfect, working fine now, you did very great work Arnaud,</p>
<p>Thank you for your hard work.</p>
<p>I will do more tests and will give you feedback.</p>Synopse PDF engine 1.7.2 - A. Bouchezurn:md5:101f1a198f0d38dbdaa2a2594f5b85752010-05-14T14:39:02+02:002010-05-14T13:39:02+02:00A. Bouchez<p>I had some time today to add the ETO_RTLREADING handling. The Synopse PDF
Engine should now handle it as expected.</p>
<p>I've uploaded a new version of the engine, 1.7.4.RTL:<br />
- added RightToLeftText property in TPdfCanvas (Uniscribe-only)<br />
- handle ETO_RTLREADING option (Uniscribe-only) in VCLCanvas/TMetaFile</p>
<p>Please give me some feedback about this update. Hope it will meet your
needs.<br />
Thanks for your comments!</p>Synopse PDF engine 1.7.2 - A. Bouchezurn:md5:b6bdf261b4779df21d2f4ac6cea895192010-05-13T18:14:23+02:002010-05-13T17:14:23+02:00A. Bouchez<p>Changing the TextFlags won't change anything, but it is not handled by the
VCLCanvas/metafile enumeration during the PDF conversion.</p>
<p>There should be a problem with the Uniscribe implementation used. Since I
didn't find any code sample on the Net, I had to implement it just following
the MSDN documentation. The ScriptLayout() function is callled as requested,
and should make all the RTL stuff. See <a href="http://msdn.microsoft.com/en-us/library/dd368559(v=VS.85" title="http://msdn.microsoft.com/en-us/library/dd368559(v=VS.85" rel="ugc nofollow">http://msdn.microsoft.com/en-us/lib...</a>).aspx</p>
<p>Perhaps the Textflag is faulty. It should be checked and implemented in
TPdfEnum.TextOut somehow.<br />
Check <a href="http://msdn.microsoft.com/en-us/goglobal/bb688137.aspx" title="http://msdn.microsoft.com/en-us/goglobal/bb688137.aspx" rel="ugc nofollow">http://msdn.microsoft.com/en-us/gog...</a><br />
I don't have time to do it now, so you could see by your own and tell me.</p>Synopse PDF engine 1.7.2 - Mohammed Nasmanurn:md5:3059c0485823f61c1b975f0e5b77375e2010-05-13T12:15:30+02:002010-05-13T11:15:30+02:00Mohammed Nasman<p>the combine with Arabic and English working fine now.</p>
<p>but still the RTL Origination, i have tried to use VCLCanvas, but it show
the same, I made a quick test wit TImage.Canvas to show you the
difference:<br />
=====<br />
Windows.ExtTextOut(img1.Canvas.Handle, 10, 20, img1.Canvas.TextFlags or
ETO_RTLREADING , nil, 'مكتبة SynPDF بدعم اللغة العربية',<br />
Length('مكتبة SynPDF بدعم اللغة العربية'), nil);</p>
<p>Windows.ExtTextOut(img1.Canvas.Handle, 10, 80, img1.Canvas.TextFlags , nil,
'مكتبة SynPDF بدعم اللغة العربية',<br />
Length('مكتبة SynPDF بدعم اللغة العربية'), nil);</p>
<p>===</p>
<p>The first one show the Arabic Origination in right order, but second one use
it in reverse order, that's happen only I have English letters with the Arabic,
I tried to change the TextFlag, but it doesn't change any thing</p>
<p>doc.VCLCanvas.TextFlags := doc.VCLCanvas.TextFlags or ETO_RTLREADING;</p>
<p>doc is object from TPdfDocumentGDI.</p>Synopse PDF engine 1.7.2 - A. Bouchezurn:md5:e79fa36dac8d9f6148b23dfcb8a85f292010-05-13T09:03:54+02:002010-05-13T08:03:54+02:00A. Bouchez<p>Just exchange the page width and height parameters. You'll be in
Landscape.</p>