PDFiumPas atvaizdavimo užraktas turi apgaubti kiekvieną rastravimo iškvietimą, kad puslapis nebūtų iškrautas vykstančio atvaizdavimo metuEnterRenderLockLeaveRenderLockTRTLCriticalSectionTPdfTPdfTPdfView
Šis auditas tikrina šešias PDFium atvaizdavimo vietas ir paaiškina, kodėl be užrakto kylanti lenktynė sunkiai atkuriamacdecl
Ką iš tikrųjų saugo atvaizdavimo užraktas
TPdf turi FRenderLock ir FRenderLockReady, todėl po sunaikinimo atėjęs iškvietimas saugiai tampa tuščia operacijaTPdfTRTLCriticalSectionFRenderLockFRenderLockReadyEnterRenderLockLeaveRenderLock
procedure TPdf.EnterRenderLock;
begin
if FRenderLockReady then
EnterCriticalSection(FRenderLock);
end;
procedure TPdf.LeaveRenderLock;
begin
if FRenderLockReady then
LeaveCriticalSection(FRenderLock);
end;
TPdf.RenderPage, RenderTile ir RenderPageProgressive jau naudojo užraktą, tačiau šeši metodai atrodė kaip prieigos metodai, nors rastravo pikseliusTPdf.RenderPageRenderTileRenderPageProgressivefinallyUnloadPageTPdf
Kurie šeši iškvietimai praleido atvaizdavimo užraktą
TPdf.GetObjectBitmap, TPdf.GetBitmap, TPdf.GetThumbnail ir atitinkami TPdfView metodai galiausiai kviečia FPDFImageObj_GetBitmap arba FPDFPage_GetThumbnailAsBitmapTPdf.GetObjectBitmapTPdf.GetBitmapTPdf.GetThumbnailTPdfView.GetObjectBitmapTPdfView.GetBitmapTPdfView.GetThumbnailFPDFImageObj_GetBitmapFPDFPage_GetThumbnailAsBitmapRenderPageRenderTile
function TPdf.GetObjectBitmap(Index: Integer): TBitmap;
var
Bitmap: FPDF_BITMAP;
begin
Result:= nil;
EnterRenderLock;
try
Bitmap:= FPDFImageObj_GetBitmap(GetObjectHandle(Index));
finally
LeaveRenderLock;
end;
if Bitmap<> nil then
try
Result:= ToBitmap(Bitmap);
finally
FPDFBitmap_Destroy(Bitmap);
end;
end;
Kodėl TPdfView užrakto iškvietimą tikrina su Nil
TPdfView užrakto kvietimus perduoda į FPdf.EnterRenderLock ir FPdf.LeaveRenderLock tik tada, kai susietas TPdf nėra nilTPdfViewFPdf.EnterRenderLockFPdf.LeaveRenderLockTPdfTPdfViewTPdfFPdf
function TPdfView.GetThumbnail: TBitmap;
var
PdfBitmap: FPDF_BITMAP;
begin
CheckActive;
Result:= nil;
if FPdf<> nil then
FPdf.EnterRenderLock;
try
PdfBitmap:= FPDFPage_GetThumbnailAsBitmap(Page);
finally
if FPdf<> nil then
FPdf.LeaveRenderLock;
end;
if PdfBitmap<> nil then
try
Result:= ToBitmap(PdfBitmap);
finally
FPDFBitmap_Destroy(PdfBitmap);
end;
end;
Kodėl RenderPage(HDC) priklauso tam pačiam auditui
TPdfView.RenderPage HDC perkrova ankstesnėje v2.25.0 versijoje taip pat praleido EnterRenderLock ir SetArithmeticMaskTPdfView.RenderPageFPDF_RenderPageEnterRenderLockSetArithmeticMaskTBitmap
procedure TPdfView.RenderPage(DeviceContext: HDC; Left, Top, Width,
Height: Integer; Rotation: TRotation; Options: TRenderOptions);
var
ArithmeticMask: TArithmeticMask;
begin
CheckActive;
if FPdf<> nil then
FPdf.EnterRenderLock;
ArithmeticMask:= SetArithmeticMask;
try
FPDF_RenderPage(DeviceContext, FPage, Left, Top, Width, Height,
Ord(Rotation), EncodeRenderOptions(Options));
finally
RestoreArithmeticMask(ArithmeticMask);
if FPdf<> nil then
FPdf.LeaveRenderLock;
end;
end;
Kodėl šią lenktynę beveik neįmanoma atkartoti
Lenktynė pasireiškia tik sutapus rastravimui ir lygiagrečiam UnloadPage arba ReloadPage tam pačiam TPdfTPdfUnloadPageReloadPagePDF fono išankstinį atvaizdavimą su atšaukiamais futures
Atlaisvintos PDFium struktūros gali grąžinti sugadintus pikselius arba vėliau sugadinti krūvos metaduomenisFPDFImageObj_GetBitmapFPDFPage_GetThumbnailAsBitmapUnloadPage
Kas pasikeičia iškvietėjams
Viešosios GetBitmap, GetObjectBitmap, GetThumbnail ir RenderPage signatūros nesikeičia, nes pataisa yra vidinis užraktasGetBitmapGetObjectBitmapGetThumbnailRenderPageTPdfstraipsnį apie PDFium atvaizdavimo podėlį ir mastelio našumą
Užraktas taikomas vienam TPdf, todėl atskiri dokumentai gali būti atvaizduojami lygiagrečiaiPDFium Component