![]() |
SynPdf - ungültige Gleitkommaoperation
Ich hab einen ViewerBilder der je Seite eine Metafile erstellt. Das können schon mal mehrere hundert Seiten sein. Zum pdf export werden diese aufs Pdf.VCLCanvas von SynPdf gezeichnet.
Bei machen Metafiles bekomme ich aber eine Exception. // *** Siehe dort Kann dazu vielleicht jemand was sagen? :gruebel:
Delphi-Quellcode:
/// EMF enumeration callback function, called from GDI
// - draw most content on PDF canvas (do not render 100% GDI content yet) function EnumEMFFunc(DC: HDC; var Table: THandleTable; R: PEnhMetaRecord; NumObjects: DWord; E: TPdfEnum): LongBool; stdcall; var i: integer; InitTransX: XForm; polytypes: PByteArray; begin result := true; with E.DC[E.nDC] do case R^.iType of .. EMR_EXTTEXTOUTA, EMR_EXTTEXTOUTW: E.TextOut(PEMRExtTextOut(R)^); // *** ungültige Gleitkommaoperation
Delphi-Quellcode:
procedure TViewerBuilder.BuildPdf;
var I, Count: integer; Pdf: TPdfDocumentGdi; MF: TMetaFile; begin MF := TMetaFile.Create; Pdf := TPdfDocumentGdi.Create; try Pdf.Info.Author := 'Abel-Software'; Pdf.Info.Creator := 'Abel-Software'; Pdf.Info.CreationDate := Now; Pdf.DefaultPaperSize := psA4; Pdf.ScreenLogPixels := Round(FPlot.DotsPerInch); Count := 0; while FileExists(Tea.ViewFileName(FFileName, Count)) do Inc(Count); for I := 0 to Count - 1 do begin MF.LoadFromFile(Tea.ViewFileName(FFileName, I)); Pdf.AddPage; Pdf.VCLCanvas.Draw(0, 0, MF); end; Pdf.SaveToFile(ChangeFileExt(FFileName, '.pdf')); finally Pdf.Free; MF.Free; end; end; |
AW: SynPdf - ungültige Gleitkommaoperation
Was mir direkt auffällt:
Delphi-Quellcode:
Warum nicht:
Count := 0;
while FileExists(Tea.ViewFileName(FFileName, Count)) do Inc(Count); for I := 0 to Count - 1 do begin MF.LoadFromFile(Tea.ViewFileName(FFileName, I)); Pdf.AddPage; Pdf.VCLCanvas.Draw(0, 0, MF); end;
Delphi-Quellcode:
Count := 0;
while FileExists(Tea.ViewFileName(FFileName, Count)) do begin MF.LoadFromFile(Tea.ViewFileName(FFileName, count)); Pdf.AddPage; Pdf.VCLCanvas.Draw(0, 0, MF); inc(count) end; Aber um auf Dein eigentlicher Problem zu kommen, hast Du mal im Debugger nachgeschaut was in PEMRExtTextOut(R)^ drinsteht? oder wenn es machbar ist hänge doch bitte so ein Metafile mal hier an |
AW: SynPdf - ungültige Gleitkommaoperation
Hab erst mal gern ein Count, ist ja auch sowas von wurschd..
Man kann emfs wohl nicht hochladen? Jedenfalls sagt "er" mir -> ungültige Datei. |
AW: SynPdf - ungültige Gleitkommaoperation
Zitat:
Also ab in 'ne ZIP und hoch damit. :zwinker: |
AW: SynPdf - ungültige Gleitkommaoperation
Liste der Anhänge anzeigen (Anzahl: 1)
Ja, das geht natürlich.
|
AW: SynPdf - ungültige Gleitkommaoperation
Hallo
Du benutzt bei der MetafIle Erzeugung die function SetWorldTransform mit (0, -1, 1, 0, 252, 3313) die fliegt Dir um die Ohren Das setzt intern die Transformation auf 0 --> Param 1 und 4 dürfen eigentlich nie 0 sein da durch diese die Skalierung berechnet wird. Mit dem aktuellen Stand von Synpdf hast Du verloren, die Worldtransformationen der GDI werden nur im Bereich skalierung und translation unterstützt. Und das auch nicht wirklich richtig....... Lustigerweise sitze ich seit 2 Tagen genau vor diesem Problem :-D |
AW: SynPdf - ungültige Gleitkommaoperation
Hey, hey, du bist ja richtig gut. Danke Kumpel. :-D
Aber, was machen wir da?? Bringts was, die 90 Grad gedrehte Metafile nachmal auf eine andere zu zeichnen? :gruebel: Was darf da nicht null sein? Das Drehen (-90°) mache ich so, das funktioniert eigentlich schon immer problemlos? eM sind ja nichts ander als die cos/sin.
Delphi-Quellcode:
procedure TFemGraphic.SaveToDefaultEmfFile(const FileName: string);
begin FMetafile.SaveToFile(FileName); end; procedure TFemGraphic.SaveToEmfFile(const FileName: string); var MF: TMetafile; MC: TMetafileCanvas; XForm: tagXFORM; begin if not FWantHaveRotate90 then SaveToDefaultEmfFile(FileName) else begin // -90°; MF := TMetafile.Create; try MF.Width := FMetafile.Height; MF.Height := FMetafile.Width; MC := TMetafileCanvas.Create(MF, 0); try XForm.eM11 := 0; XForm.eM12 := -1; XForm.eM21 := 1; XForm.eM22 := 0; XForm.eDx := 0; XForm.eDy := FMetafile.Width; SetGraphicsMode(MC.Handle, GM_ADVANCED); SetWorldTransform(MC.Handle, XForm); MC.Draw(0, 0, FMetafile); finally MC.Free; end; finally MF.SaveToFile(FileName); MF.Free; end; end; end; |
AW: SynPdf - ungültige Gleitkommaoperation
Zitat:
Es werden nur Skalierung und Translation übernommen. Habe im Moment genau das gleiche Problem. Wir wollten den bestehenden Export ersetzen durch SynPDF aber in der aktuellen Form geht das nicht. Die einzige Möglichkeit die Du aktuell hast ist
|
AW: SynPdf - ungültige Gleitkommaoperation
Ok. Ist bei mir genauso (hab PowerPdf gegen SynPdf ausgetauscht). Möchte das eigentlich nicht mehr rückgängig machen. Die 90 Grad Drehung lass ich dann lieber weg.
Sollen wir uns mal an die SynPdf Gemeinde wenden? Die ist für doch solche gravierenden Erweiterungen der Ansprechpartner und dein Chef hat dich auch wieder lieb? :mrgreen: |
AW: SynPdf - ungültige Gleitkommaoperation
Zitat:
wir können versuchen das direkt by Synopse zu melden, ich denke aber das wir damit keinen grossen Erfolg haben werden. Für den Anwendungsfall wie es dort eingesetzt wird, funktioniert es ja wirklich gut. Ich habe mich jetzt schon gute 2 Tage durch die Source und Die Adobe PDF Beschreibung gewühlt. Mit dem aktuellen Design der SynPdf geht das nicht so einfach. Was da im PDF Format wirklich fehlt ist eine komplettes setzen der Transformation. Im Moment kann man nur verändern :-( Dann noch was habe ich gestern nicht aufgepasst Du solltest für Manipulationen am WorldTransform aufpassen das die Werte auch stimmen Da Du die ganze Transformation setzt solltest Du die eM11 und eM22 auf 1 setzen Windows selber ist da zwar unempfindlich aber die Werte stimmen sonst nicht also:
Delphi-Quellcode:
Besser wäre folgendes dann ist es egal was vorher schon da war
procedure TFemGraphic.SaveToEmfFile(const FileName: string);
var MF: TMetafile; MC: TMetafileCanvas; XForm: tagXFORM; begin if not FWantHaveRotate90 then SaveToDefaultEmfFile(FileName) else begin // -90°; MF := TMetafile.Create; try MF.Width := FMetafile.Height; MF.Height := FMetafile.Width; MC := TMetafileCanvas.Create(MF, 0); try XForm.eM11 := 1; //0; change XForm.eM12 := -1; XForm.eM21 := 1; XForm.eM22 := 1; // 0; change XForm.eDx := 0; XForm.eDy := FMetafile.Width; SetGraphicsMode(MC.Handle, GM_ADVANCED); SetWorldTransform(MC.Handle, XForm); MC.Draw(0, 0, FMetafile); finally MC.Free; end; finally MF.SaveToFile(FileName); MF.Free; end; end; end; Wie gesagt windows ist unempfindlich aber andere EMF Interpreter reagieren da schon mal komisch
Delphi-Quellcode:
procedure TFemGraphic.SaveToEmfFile(const FileName: string);
var MF: TMetafile; MC: TMetafileCanvas; XForm: tagXFORM; begin if not FWantHaveRotate90 then SaveToDefaultEmfFile(FileName) else begin // -90°; MF := TMetafile.Create; try MF.Width := FMetafile.Height; MF.Height := FMetafile.Width; MC := TMetafileCanvas.Create(MF, 0); try XForm.eM11 := 1; XForm.eM12 := -1; XForm.eM21 := 1; XForm.eM22 := 1; XForm.eDx := 0; XForm.eDy := FMetafile.Width; SetGraphicsMode(MC.Handle, GM_ADVANCED); GetWorldTransform(MC.Handle, orgXForm); // So wird nur zusätzlich die Drehung eingebaut ModifyWorldTransform(MC.Handle, XForm, MWT_LEFTMULTIPLY); MC.Draw(0, 0, FMetafile); // und wieder zurück auf Normal ModifyWorldTransform(MC.Handle, XForm, MWT_IDENTITY); finally MC.Free; end; finally MF.SaveToFile(FileName); MF.Free; end; end; end; |
AW: SynPdf - ungültige Gleitkommaoperation
Ok. Danke für deine Hinweise :thumb:
Bei SynPdf ist zur Zeit wohl nicht viel los, das Forum scheint auch "readonly" zu sein. Meine Wenigkeit hat sich deshalb auch mal überlegt, wie man das machen könnte. Ich würde in SynDpf nichts machen sondern einen Parser vorschalten und dann deren Dest nach SynPdf übergeben!?
Delphi-Quellcode:
TXFormMetafileToMetafile = class
private FDevice: HDC; FSource, FDest: TMetafile; procedure ProcessMetafile; public property Dest: TMetafile read FDest; procedure LoadSourceFromFile(const FileName: string); procedure SaveDestToFile(const FileName: string); constructor Create(const Device: HDC); destructor Destroy; override; end; .. function MFProc(DC: HDC; P: Pointer; MF: TXFormMetafileToMetafile): Integer; stdcall; begin Result := 1; case PEMR(P).iType of // -> TXFormMetafileToMetafile Methoden; end; end; constructor TXFormMetafileToMetafile.Create(const Device: HDC); begin FDevice := Device; FSource := TMetafile.Create; FDest := TMetafile.Create; end; destructor TXFormMetafileToMetafile.Destroy; begin FSource.Free; FDest.Free; inherited; end; procedure TXFormMetafileToMetafile.LoadSourceFromFile(const Filename: string); var Stream: TStream; begin Stream := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite); try FSource.LoadFromStream(Stream); finally Stream.Free; end; end; procedure TXFormMetafileToMetafile.SaveDestToFile(const FileName: string); var Stream: TStream; begin ProcessMetafile; Stream := TFileStream.Create(Filename, fmCreate); try FDest.SaveToStream(Stream); finally Stream.Free; end; end; procedure TXFormMetafileToMetafile.ProcessMetafile; begin FDest.Clear; Windows.EnumEnhMetaFile(FDevice, FSource.Handle, @MFProc, Self, Rect(0, 0, 0, 0)); end; |
AW: SynPdf - ungültige Gleitkommaoperation
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Ich habe jetzt eine Lösung gefunden die für mich funktioniert mit beliebigen Rotationswinkeln. Habe aber die SynPdf etwas erweitern müssen. Wenn Du willst schicke ich es Dir. Denke nicht das mein "Hack" in die offiziellen Repos geht. Habe Arnold angeschrieben mal abwarten. |
AW: SynPdf - ungültige Gleitkommaoperation
Liste der Anhänge anzeigen (Anzahl: 1)
Ja, ich würde es gerne mal testen. Meine Mail Adresse findest du in der angehängten Unit. Ich hab nur mal probiert die Metafile iTypes auszulesen. Ich werde das sicherlich nicht weiterverfolgen, du hast völlig recht, das wird ein mittleres 2D CAD Programm. Würde mich aber dennoch mal interessieren wieso es nicht gegangen ist? Nur wenn du Zeit und Lust hast..
LG Thomas |
AW: SynPdf - ungültige Gleitkommaoperation
Hallo,
auf die Schnelle: Deine Callback Routine ist falsch deklariert. MSDN:
Delphi-Quellcode:
Also muss die so aussehen:
int CALLBACK EnhMetaFileProc(
_In_ HDC hDC, _In_ HANDLETABLE *lpHTable, // fehlt bei Dir _In_ const ENHMETARECORD *lpEMFR, _In_ int nObj, // fehlt bei Dir _In_ LPARAM lpData );
Delphi-Quellcode:
function MFProc(DC: HDC; PT : Pointer; P: Pointer; NumObjects: integer; MF: TXFormMetafileToMetafile): Integer; stdcall;
Damit funktioniert Dein Testprogramm. Ich werde Dir meine angepasste SynPDF schicken. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:39 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz