You are not logged in.
Pages: 1
In my tests of Result variable is initialized with Boolean=False, Integer=0, String='', Object=nil etc.
But I have not found any official reference about this.
But if my tests is false then it means that i always must start all functions with defining Result, because an exception can happen anywhere in the code.
And that is not the case in mu code at least.
Regards
Roland
By design, the function is expected to return TRUE on success, and FALSE in case of error.
In this case, any error will be an exception. So exceptions have to be catched, and return false in this case.
Just one further note.
What is the reason to eat an exception here in synpdf.pas ?
function TPdfDocument.SaveToFile(const aFileName: TFileName): boolean;
var FS: TFileStream;
begin
try
FS := TFileStream.Create(aFileName,fmCreate);
try
SaveToStream(FS);
result := true;
finally
FS.Free;
end;
except
on E: Exception do // error on file creation (opened in reader?)
result := false;
end;
end;
I think it could be changed to this ?
function TPdfDocument.SaveToFile(const aFileName: TFileName): boolean;
var FS: TFileStream;
begin
FS := TFileStream.Create(aFileName,fmCreate);
try
SaveToStream(FS);
result := true;
finally
FS.Free;
end;
end;
Regards
Roland
Yep, it works fine
Thanks for good cooperation!
Regards
Roland Bengtsson
Team Attracs
If w was overriden, this was a stack corruption issue.
I think it should be fixed by now.
See http://synopse.info/fossil/info/3ca7c5c515
Well, normally I have set
fPdfDocument.ForceNoBitmapReuse := True;
as a workaround. But for this test that code is commented out.
Here is the same method again with some additional logging.
function TPdfDocument.CreateOrGetImage(B: TBitmap; DrawAt: PPdfBox): PDFString;
var J: TJpegImage;
Img: TPdfImage;
Hash: TPdfImageHash;
y,w,h,row: integer;
nPals: cardinal;
Pals: array of TPaletteEntry;
const PERROW: array[TPixelFormat] of byte = (0,1,4,8,15,16,24,32,0);
procedure DoHash(bits: pointer; size: Integer);
begin // "4 algorithms to rule them all"
Hash[0] := Hash[0] xor Hash32(bits,size);
Hash[1] := Hash[1] xor HashOf(bits,size);
Hash[2] := crc32(Hash[2],bits,size);
Hash[3] := adler32(Hash[3],bits,size);
end;
begin
result := '';
if (self=nil) or (B=nil) then exit;
w := B.Width;
h := B.Height;
TraceLog.Trace(Format('Start %d %d', [w, h]));
fillchar(Hash,sizeof(Hash),0);
if not ForceNoBitmapReuse then begin
row := PERROW[B.PixelFormat];
if row=0 then begin
B.PixelFormat := pf24bit;
row := 24;
end;
TraceLog.Trace(Format('row %d %d', [row,w]));
fillchar(Hash,sizeof(Hash),row);
if B.Palette<>0 then begin
nPals := 0;
TraceLog.Trace(Format('GetObject %d', [w]));
if (GetObject(B.Palette,sizeof(nPals),@nPals)<>0) and (nPals>0) then begin
SetLength(Pals,nPals);
TraceLog.Trace(Format('GetPalette %d', [w]));
if GetPaletteEntries(B.Palette,0,nPals,Pals)=nPals then
begin
TraceLog.Trace(Format('DoHash', []));
DoHash(pointer(Pals),nPals*sizeof(TPaletteEntry));
end;
end;
end;
TraceLog.Trace(Format('Scanline1 %d %d', [w, row]));
row := BytesPerScanline(w,row,32);
TraceLog.Trace(Format('Scanline2 %d %d', [w, row]));
for y := 0 to h-1 do
begin
TraceLog.Trace('DoHash 1 ' + IntToStr(y));
DoHash(B.ScanLine[y],row);
TraceLog.Trace('DoHash 2 ' + IntToStr(y));
end;
TraceLog.Trace(Format('GetXObject1 %d %d', [w, h]));
result := GetXObjectImageName(Hash,w,h);
TraceLog.Trace(Format('GetXObject2 %d %d', [w, h]));
end;
if result='' then begin
// create new if no existing TPdfImage match
if ForceJPEGCompression=0 then
Img := TPdfImage.Create(Canvas.fDoc,B,True) else begin
J := TJpegImage.Create;
try
J.Assign(B);
Img := TPdfImage.Create(Canvas.fDoc,J,False);
finally
J.Free;
end;
end;
Img.fHash := Hash;
result := 'SynImg'+PDFString(IntToStr(FXObjectList.ItemCount));
if ForceJPEGCompression=0 then
AddXObject(result,Img) else
RegisterXObject(Img, result);
end;
// draw bitmap as XObject
if DrawAt<>nil then
with DrawAt^ do
Canvas.DrawXObject(Left,Top,Width,Height,result);
end;
And the output in the log.
20120405 22:58:27 (7800) Start 674 155 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5047)]
20120405 22:58:27 (7800) row 24 674 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5055)]
20120405 22:58:27 (7800) GetObject 674 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5059)]
20120405 22:58:27 (7800) GetPalette 674 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5062)]
20120405 22:58:27 (7800) Scanline1 8388608 32768 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5070)]
20120405 22:58:27 (7800) Scanline2 8388608 0 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5072)]
20120405 22:58:27 (7800) DoHash 1 0 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5075)]
So it seems that w is trashed somehow at the call to GetPaletteEntries.
Hope this information help you.
You said:
The ScanLine[] use sounds quite regular here, don't you think?
I don't understand what you mean here.
Regards
Roland Bengtsson
Team Attracs
Hi!
I downloaded and tested the latest trunk, still the same error.
I also added some logs to try to narrow the error for you.
This code:
function TPdfDocument.CreateOrGetImage(B: TBitmap; DrawAt: PPdfBox): PDFString;
var J: TJpegImage;
Img: TPdfImage;
Hash: TPdfImageHash;
y,w,h,row: integer;
nPals: cardinal;
Pals: array of TPaletteEntry;
const PERROW: array[TPixelFormat] of byte = (0,1,4,8,15,16,24,32,0);
procedure DoHash(bits: pointer; size: Integer);
begin // "4 algorithms to rule them all"
Hash[0] := Hash[0] xor Hash32(bits,size);
Hash[1] := Hash[1] xor HashOf(bits,size);
Hash[2] := crc32(Hash[2],bits,size);
Hash[3] := adler32(Hash[3],bits,size);
end;
begin
result := '';
if (self=nil) or (B=nil) then exit;
w := B.Width;
h := B.Height;
fillchar(Hash,sizeof(Hash),0);
if not ForceNoBitmapReuse then begin
row := PERROW[B.PixelFormat];
if row=0 then begin
B.PixelFormat := pf24bit;
row := 24;
end;
fillchar(Hash,sizeof(Hash),row);
TraceLog.Trace('Start');
if B.Palette<>0 then begin
nPals := 0;
TraceLog.Trace('GetObject');
if (GetObject(B.Palette,sizeof(nPals),@nPals)<>0) and (nPals>0) then begin
SetLength(Pals,nPals);
TraceLog.Trace('GetPalette');
if GetPaletteEntries(B.Palette,0,nPals,Pals)=nPals then
begin
TraceLog.Trace('DoHash');
DoHash(pointer(Pals),nPals*sizeof(TPaletteEntry));
end;
end;
end;
TraceLog.Trace('Scanline 1');
row := BytesPerScanline(w,row,32);
TraceLog.Trace('Scanline 2');
for y := 0 to h-1 do
begin
TraceLog.Trace('DoHash 1 ' + IntToStr(y));
DoHash(B.ScanLine[y],row);
TraceLog.Trace('DoHash 2 ' + IntToStr(y));
end;
TraceLog.Trace('GetXObject1');
result := GetXObjectImageName(Hash,w,h);
TraceLog.Trace('GetXObject2');
end;
if result='' then begin
// create new if no existing TPdfImage match
if ForceJPEGCompression=0 then
Img := TPdfImage.Create(Canvas.fDoc,B,True) else begin
J := TJpegImage.Create;
try
J.Assign(B);
Img := TPdfImage.Create(Canvas.fDoc,J,False);
finally
J.Free;
end;
end;
Img.fHash := Hash;
result := 'SynImg'+PDFString(IntToStr(FXObjectList.ItemCount));
if ForceJPEGCompression=0 then
AddXObject(result,Img) else
RegisterXObject(Img, result);
end;
// draw bitmap as XObject
if DrawAt<>nil then
with DrawAt^ do
Canvas.DrawXObject(Left,Top,Width,Height,result);
end;
Produced this output in the log
20120405 09:04:50 (6600) Start [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5054)]
20120405 09:04:50 (6600) GetObject [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5057)]
20120405 09:04:50 (6600) GetPalette [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5060)]
20120405 09:04:50 (6600) Scanline 1 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5068)]
20120405 09:04:50 (6600) Scanline 2 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5070)]
20120405 09:04:50 (6600) DoHash 1 0 [SynPdf.TPdfDocument.CreateOrGetImage (SynPdf.pas:5073)]
So it seems to fail for line
DoHash(B.ScanLine[y],row);
Note that this code is never executed
TraceLog.Trace('DoHash');
DoHash(pointer(Pals),nPals*sizeof(TPaletteEntry));
Regards
Roland Bengtsson
Hi, I am working with the same application as Daniel. I have found more about the exact sourceline why it silently shut down the whole client when running in Citrix Terminal session from Citrix desktop.
We use version 1.16 of SynPDF. PUREPASCAL is defined.
So I try to describe what happens as exact as possible what happens.
Line 7491 in synpdf.pas
E.DrawBitmap(xSrc,ySrc,cxSrc,cySrc, xDest,yDest,cxDest,cyDest,iUsageSrc,
pointer(cardinal(R)+offBmiSrc),pointer(cardinal(R)+offBitsSrc));
calls TPdfEnum.DrawBitmap. That procedure calls
Doc.CreateOrGetImage(B,@Box)
on line 7605.
In TPdfDocument.CreateOrGetImage there is a if statement on line 5047
if B.Palette<>0 then begin
so if this is true then it calls
DoHash(pointer(Pals),GetPaletteEntries(B.Palette,0,256,Pals)*sizeof(TPaletteEntry))
and the whole process is shut down silently.
But when it works the statement is false and DoHash is never called.
This is when application is started outside Citrix Desktop.
I have added more logs to the code and comment out the is the lines
// if B.Palette<>0 then
// begin
// SetLength(Pals,256);
// DoHash(pointer(Pals),GetPaletteEntries(B.Palette,0,256,Pals)*sizeof(TPaletteEntry));
// end;
And it works
But I'm not sure in what cases this is really needed.
Hopefully this is enough information to get it working in all cases.
Regards
Roland Bengtsson
Team Attracs
EDIT:
So I try to investigate why DoHash fails.
I found this comment.
- fixed a potential GPF issue in function HashOf() in PUREPASCAL mode (used
to reuse any existing bitmap content within the PDF document)
So there is a risk of General Protection Fault when using PUREPASCAL mode ?
I have add more logs to the code to isolate the problem.
This code in HashOf method generate general Protection Fault in the loops first element (i=0).
Result := ((Result shl 2) or (Result shr (SizeOf(Result)*8-2))) xor P[i];
My guess is that the array P is somehow broken in the previous method Hash32.
Currently I set ForceNoBitmapReuse := True as a workaround for this problem
Did you use the latest version from trunk?
http://synopse.info/fossilThe upcoming 1.16 revision have some enhancements to improve consistency.
The case statement implementation sounds pretty valid.
It will just ignore any other pattern than PATCOPY...Logging the whole PEMRStretchBlt(R)^ content would make sense, anyway.
Pages: 1