Artikel Teknis

Rendering PDF Progresif yang Dapat Dibatalkan di Delphi (PDFium)

Kebanyakan halaman PDF dirasterisasi dalam beberapa milidetik dan Anda tidak pernah memikirkannya. Kemudian seorang pengguna membuka gambar teknik A1, sebuah halaman yang dipenuhi dengan puluhan ribu sapuan vektor, atau sebuah poster yang sesak dengan grup transparansi dan topeng lembut (soft masks), dan panggilan tunggal yang mengecatnya membutuhkan dua atau tiga detik. Jika panggilan itu berjalan di utas antarmuka (UI thread), jendela tersebut berhenti mengecat ulang, bilah judul menjadi abu-abu, dan sistem operasi menawarkan untuk mematikan aplikasi. Pekerjaan itu sah. Halaman tersebut benar-benar membutuhkan waktu selama itu. Cacatnya adalah rendering tersebut merupakan satu panggilan pemblokiran yang tak terpisahkan tanpa cara untuk muncul ke permukaan demi udara dan tanpa cara untuk berhenti

Artikel ini adalah persis tentang salah satu dari dua masalah tersebut: membatalkan rendering satu halaman yang panjang tanpa membekukan antarmuka. Pengguna mengklik halaman berikutnya, atau memperbesar, atau menutup dokumen, dan rendering yang sedang berlangsung sekarang menjadi pekerjaan sia-sia yang harus berakhir pada kesempatan berikutnya daripada berjalan hingga selesai. Memperlancar gulir dan perbesaran dengan melakukan cache (menyembunyikan) pada apa yang telah dirasterisasi merupakan perhatian yang terpisah dengan desainnya sendiri, yang dibahas pada artikel pendamping yang ditautkan di bagian akhir. Di sini satu-satunya pertanyaannya adalah bagaimana membuat satu rendering progresif menjawab permintaan batal (cancel) dengan cepat dan bersih

API rendering progresif yang sudah dikirimkan PDFium

PDFium telah mengantisipasi separuh masalah pembekuan itu. Di samping tembakan-tunggal (one-shot) FPDF_RenderPageBitmap, ia memaparkan sebuah varian progresif yang membagi halaman ke dalam potongan-potongan pekerjaan. Anda memanggil FPDF_RenderPageBitmap_Start sekali untuk menyiapkan perenderan ke sebuah bitmap tujuan, kemudian memanggil FPDF_RenderPage_Continue berulang-ulang. Setiap Continue merasterisasi sebuah irisan berbatas (bounded slice) dan mengembalikan sebuah status. FPDF_RENDER_TOBECONTINUED berarti masih ada yang harus dilakukan, FPDF_RENDER_DONE berarti halamannya telah selesai, dan FPDF_RENDER_FAILED berarti ia berhenti pada sebuah galat (error). Bila perulangan berakhir Anda memanggil FPDF_RenderPage_Close untuk melepaskan status progresif per-halaman. Dikarenakan kendali kembali ke kode Anda di antara irisan, Anda dapat memompa pesan (pump messages), memperbarui indikator progres, atau memeriksa apakah pekerjaannya masih diinginkan

Mekanisme yang PDFium sediakan untuk memutuskan kapan harus mengalah adalah struktur panggil balik (callback struct) bernama IFSDK_PAUSE. Anda menyerahkannya pada Start dan ke tiap Continue. Seusai masing-masing serpihan PDFium memanggil petunjuk fungsinya NeedToPauseNow, lalu jika itu mengembalikan suatu nilai bukan-nol, Continue saat ini berhenti lekas dan menyerahkan kembali kendali lewat FPDF_RENDER_TOBECONTINUED. Struktur tersebut juga menyandang medan version, yang mesti ditetapkan menuruti angka 1, seraya penunjuk bentuk-bebas user yang mana tak pernah disentuh oleh PDFium lalu melalukannya dengan utuh tanpa tersentuh. Petunjuk utuh tak tersentuh itu merupakan keseluruhan inti pertimbangan mengenai desain yang meruntut sehabisnya ini

Menata Ulang Fungsi Jeda Sebagai Batal

Tujuan awal NeedToPauseNow ialah memenggal waktu. Mengembalikan angka bukan-nol saat jatah bingkai Anda habis, mengembalikan nol buat mempertahankan rendernya, lalu PDFium rehat agar Anda merampungkan kegiatan lain sebelum memulai kembali alur rendernya yang serupa itu. Komponen PDFium menata ulang pertanda sama serupa tadi untuk perbuatan berbeda yang tak serupa. Alih-alih menjawab "bila sebaiknya saya jeda agar supaya Anda melanjutkan", timbal balik merespon "apakah pekerjaan ini dibatalkan." Keduanya terpetakan ke atasnya secara jernih sebab perlakuan perulangannya kapan kala ia menangkap aba-aba benderanya (the flag). Jeda sesungguh-sungguhnya menanti Continue berikutnya; sebuah penundaan perulangan (cancel) tidak berlaku demikian halnya. Pabila perulangan si pemanggil menangkap tanda batal, ia membubarkan konteks rendernya lantas seketika menyudahi panggilan Continue buat sekian kalinya secara berulang, sehingga balasan bukan-nol sediakala bagi PDFium disimak dengan pemaknaan berbalut "stop pecahan rincian ini" menjadilah, menilik hasil, "sepenuhnya stop."

Penundaan perulangan (Cancellation) dinyatakan melewati sebuah celah rute antarmuka, IPdfCancellationToken, dan IsCancelled miliknya mendadak terjungkal dari salah menuju benar apabila celah ragam bagian program selebihnya memerintahkan kegiatan rendernya segera putus berhenti. Penghubung celah pertalian rute antarmuka di Pascal dengan sambungan panggil balik (callback) C rute pihak PDFium melintang selaku pointer perujuk satu mata rute murni. Pertalian rute antarmuka milik (token) ini terekam menembus jalur IFSDK_PAUSE.user, dan disambut laju sambungan cdecl kaku (static callback) merujuk balik kembali menyimak rute lalu bertanya padanya (queries it). Kendala klasik ini sering terjerat tatkala membiarkan perpustakaan C rute menyambar masuk menuju rute Pascal: pertalian baliknya mesti terwujud berbentuk petunjuk lumrah bermuat sepakat peruntukan konvensi C, usah metode (method), pasalnya PDFium mengekalkan pertalian laju petunjuk usangnya (bare function pointer) perihal segala sesuatu berwujud ragam obyek Pascal atau apalagi berbau Self

type
  TPdfProgressivePause = record
    Pause: IFSDK_PAUSE;            // PDFium reads this; .user holds the token
    Token: IPdfCancellationToken; // strong ref keeps the token alive
  end;

function ProgressivePauseCallback(pThis: PIFSDK_PAUSE): FPDF_BOOL; cdecl;
var
  Token: IPdfCancellationToken;
begin
  Result := 0;
  if (pThis = nil) or (pThis^.user = nil) then
    Exit;
  Token := IPdfCancellationToken(pThis^.user);
  if Token.IsCancelled then
    Result := 1; // non-zero: PDFium stops this chunk
end;

Pertalian panggil kembali memulihkan rute token menyadur kembali pThis^.user menyesuaikan ragam asali miliknya (interface type) lantas kemudian membaca rute IsCancelled. Sejurus tiada satupun di sananya hal hal bermuara mengalokasikan (allocates), gembok pembatas (locks), maupun merintangi pembekuan (blocks), di mana sungguh berarti pasal PDFium memanggil ke atas rute lintasan kegiatan render sehabis serpihan satu dengan selanjutnya terurai dan seonggok kegiatan apapun rute tertaut sini bakal ditambah menyertai pembebanan hitungan ongkos jalannya alur sang perendernya perihal dirinya tersendiri. Pelindung pengawal berbekal seonggok tiada-struktur (nil struct) maupun bentang medan penggarap nihil bermuatan user itu mensuratkan pertalian fungsional (function) laras serupa yang sungguh jitu aman terkendali saat dicangkokkan meskipun terhadap rute luasan render tanpa sesekali menjumpai pembawa keabsahan isyarat yang sebetulnya murni nyata-nyatanya (real token)

Menjaga kelangsungan hidupan pertalian pembawa serpihan melintangi putaran gelungnya

Mencetak sebuah pertalian penyambung lewat pembawa rute Pointer dan mundur ulang jadi ranah celah di mana sarang pepatah hama pengunyah kutu lahir (lifetime bugs). Susunan antarmuka ragam sebuah IInterface bermukim kental terasuh menghimpun perhitungan (reference counted), dan raupan hitungannya sanggup bernyawa kapan seketika sang mesin penyusun pengubah rupa (compiler) menjumpai sesosok variabel-ragam penyambung antarmuka seolah ditugasi tugas barunya (being assigned). Menaruh pertalian tersebut sebatas penyambung peranti polosan pada pusaran celah rute terdalam IFSDK_PAUSE.user pastilah menciutkannya terselubung menembusi pelacak sang perhitungan rujuk acuan sama sekali selamanya. Andai rujukan pertalian penyambungnya hanya semata-mata yang menahkodai pertalian rute rujukan satu belaka dari pertalian itu menghilang pupus tak tentu meruap seketika pusaran gasing putaran roda Continue teguh kekar berpendar perputarannya (was still running), perwujudan tersebut di atas lantas disapih sirna dari naungan celah dasar pijakan panggilan putar baliknya, lantas seonggok celah rincian kepingan setelah rutenya ini lantas mengusung penunjuk acuan buntung terbengkalai tanpa kaitan (dangling pointer)

Inilah yang kemudian menjelaskan pasalnya alat pelukis lukis rupa (descriptor) adalah sejilid lempengan rekaman menggenggam eratan kepingan belah duanya, bukanlah sebatas sisa selingkar semata jua belaka. Lebaran celah Pause itu wujud bangun gurat yang PDFium cerna tangkap mengerti maknanya. Penampang celah Token menjadi sebuah penunjuk bertalian perujukan tulen sejati bermuatan laras panduan pembawa sifat penyambung pertalian sungguh dihitung mutlak dengan alat pengolah jaring mesin pengubahnya (compiler counts), dan sesungguhnya jalinan jaring rute tatanan bentuk tersebut lahir untuk sekedar mencangkok patok kokoh di celah ruang memori sekokoh usia rekam jilidan selingkup ruang masa jilid hidup semata. Lempengan tersebut bermukim jadi satu sosok rute tempatan memori lokal menjalar lewat rentengan palet kegiatan rentetan kegiatan lintasan sang perender tersebut yang terpacak setia dan tahan menahan hantaman sampai menuntaskan perulangan (entire duration) masa gulirnya yang seutuhnya sirna manakala jalannya terpecah ruah bubar tersudahi seusai putaran jalan (exits). Penunjuk polosan tak merias jalinan luaran pada selingkupan bilik rute rongga sang celah user dengan sekuntum panduan perujukan merengkuh berpegang kuat dari bentangan sisi Token senada menyemat sebarisan baris menunjuk obyek yang merujuk senada jua hal serupanya; sesuatu hal sebisanya perlakuan yang sanggup dilafal oleh si perambah (PDFium), dengan yang hal selubung sebalik sisa satunya mempertahankan jalinan agar jalinan wujud obyek tak lantas segera kena usung rombongan pemburu sapu bersih penyeka sapu angkut lenyap dari pusaran tempat (collected)

var
  Pause: TPdfProgressivePause;
  EffectiveToken: IPdfCancellationToken;
begin
  // ... choose EffectiveToken ...

  // Strong ref first, then publish the same object to PDFium via .user.
  Pause.Token := EffectiveToken;
  Pause.Pause.version := 1;
  Pause.Pause.NeedToPauseNow := ProgressivePauseCallback;
  Pause.Pause.user := Pointer(EffectiveToken);

Menutup konteks rendernya dengan wujud kelar tiada mengandaikan cara apalagi bagaimanapun gelungnya itu berkesudahan usai

Setiap laras seruan rentetan panggilan lintasan buat lajunya rute FPDF_RenderPageBitmap_Start mempersiapkan alokasi persinggahan bertahap maju pesat yang PDFium sangkut-paut pautannya berdampingan ke penjuru lintasan laras seruan halaman, yang serta kondisinya tersendiri hanyalah dicabut penaliannya usai dibebaskan seutuhnya menuruti langkah beranjaknya lajunya putaran kehendak FPDF_RenderPage_Close. Ada berkelebat tiga pintu rongga terbentang lapang sebagai jembatan pembuka laras dari pusingan lajunya putaran sirkuit yang mengejawantahkan penggerak putaran (drive loop). Laras lembar cetak halamannya telah tuntas sampai paripurna usai penatnya menapaki status jalinan penyimpul rute keterselesaian paripurna FPDF_RENDER_DONE. Gelung pemicu lintasan pemencet tuas perangkai petunjuk pertautan terputus menelusuri patahan perulangan seketika meletus ruah dari sarang melompat mundur dari jalinan laporkan kegagalan status beringsut menepi membatalkan cetak perihal penundaan membatalkannya. Satu hal yang celaka tertimpa patahan melandai pudar tertimpa reruntuhan yang mengakibatkan rute laras sandangan ketersandungan status petunjuk peruntuhan celah patahan menampakkan kedok petunjuk isyarat FPDF_RENDER_FAILED. Serombongan sekelompok petunjuk ke-tiga tiganya mewajibkan panggil tutup sela lintasan rute Close, seraya langkah patahan langkah peruntuhan penunda urungnya ini lah rute titian licin tersulit menjauh dari perihal ketersesatan kekhilafan melangkah, pasalnya lintasan lumrah cetakan kelokan berlandas wujud rupa "lihat penundaan perulangan pembatalan, lepas terjang keluar melenceng membuyarkan (break out)" terdorong membiarkan keterluputan membersihkan runtuhan di perlintasan peruntuhan jalan menuju jalan keluar. Kesampingkan sela Close luput tersentuh tiada termaknai seraya membiarkan pautan runtuhan tiris bertahap bocor pada laras tatanan per-halaman yang merendam sisa pautan (leaks the per-page state), dan seonggok alat rute layar pertunjukan penampil yang mengandai merelakan laras sandaran panggung lintasan pementasan kepada laras wewenang perintah pembatal pengguna merunut peruntuhan pementasan lintasan dari layar panggung merengkuh layar penumpukan kelolosan tumpukan tirisan puing rute pada perihal penampang layarnya rute yang ditunda digagalkan rutenya merangkak satu ke tiap laras patahan reruntuh halaman yang diaborsi dari kehamilan pentas lakon rutenya

Ketangguhan gurat pembentuk membubuhi selingkaran serta gurat pemilah cap corak penjenisan penggolongan rupa klasifikasi tersarung selimut try merajut FPDF_RenderPage_Close menyemat kancing pakaian pelindung selubung perajut pembatas pemungkas finally. Peta corak bit target lintasan diredam meluap luluh serbuk seketika itu pada sebingkai batas lintasan senada selaras di tempat kejadian bernaung (the same block). Penundaan perulangan aborsi pembatalan seketika mungkin kelak sanggup saja kelonggaran melempar perulangan lekas minggat seketika menyelinap usai celah pembuka Exit lebih lekas serta barikade rute kancing pakaian pemungkas rute perajut sebetulnya penyimpul selubung purna pengawal pengamannya celah finally tersebut sejatinya melaju, sehinggalah perwujudan sesungguhnya menyisakan sisa jejak titik berjejak persis cuma tepat pada suatu posisi tiang pasak tunggal tempat persinggahan sandaran sandi perantara pencabut selubung status sandi rute setelan pautan celah penunda (progressive state) terkemas murni tak bakal usah sesekali dikelabuhi disingkiri merunduk melewatinya terlewat (bypassed)

Status := FPDF_RenderPageBitmap_Start(PdfBmp, FPage, Left, Top,
  Width, Height, Ord(Rotation), EncodeRenderOptions(Options), Pause.Pause);
try
  while Status = FPDF_RENDER_TOBECONTINUED do
  begin
    if EffectiveToken.IsCancelled then
    begin
      Result := prsCancelled;
      Exit;
    end;
    Status := FPDF_RenderPage_Continue(FPage, Pause.Pause);
  end;

  if EffectiveToken.IsCancelled then
    Result := prsCancelled
  else if Status = FPDF_RENDER_DONE then
    Result := prsDone
  else
    Result := prsFailed;
finally
  // Frees the progressive state Start allocated; mandatory on every path.
  FPDF_RenderPage_Close(FPage);
  FPDFBitmap_Destroy(PdfBmp);
end;

Laras kelokan putaran melangkah memerinci pertalian kelengkapan pengawas dari tiap selingkar putaran seruannya laras pijakan perintah lintasan kelokan Continue sekaligus seraya berjejak menyandar penuh tertimpa punggung andalan ke seruan langkah lintasan celah laras rute panggil ulangnya yang senantiasa menopang bersandar kuat tepat bermukim di rute dasar rute biliknya jua. Panggil baliknya menetak memenggal secercah cuilan rute potongan sekumpulan patah-patah per langkah perulangan berjalan; pemeriksaan perulangannya melempar rem menyetopin perulangan laju perlintasannya selingkar seketika lintasan laras melenggang setelah perulangan tadi (stops the next one from starting). Menunggal padu saling berjejer menangkup memperkokoh rentangan lajur memanjang penambat dari berbekalnya penundaan penunda laras menyabotase pengerjaan peruntuhan sela langkah lintasan berwujud usang meraup gurat takaran sebingkai sebongkah setakar serpih secuil kelokan yang tersandangnya

Tiga keluaran luaran purna coraknya, beserta gerak langkah pertautan kelokan rekam peta rute titik laras bit gambar usai purna pembatalannya laras gurat aborsi langkah merentang patahan peruntuhan

Lubang portal masuk utama laras penunjuk untuk titik lintasan portal penjalur di khalayak publik ranahnya tersapa sebagai TPdf.RenderPageProgressive, lajunya mengembalikan arus nilai wujud sapaan sandi rute sandi penyimpul jejak sandangan berwujud lajur laras peruntukan TPdfProgressiveStatus penunjuk jalan rute sandaran tunggal semata laras sela tunggal beranjak selaras salah satun ragam gurat kelokan antara sandi pembuka jejak lajur dari ranah lintasan seruan diantara balutan prsDone, setelan jalinan sandi sandangan sejenis lintasan sandi berwujud prsCancelled, sela balutan ranah rute lain menyertakan sandi corak pelengkap gurat sandi yang merasuk yakni prsFailed. Tata letak lintasan jejak wujud corak rincian laras harga balutan sandi lintasan ketersamaan mencerminkan pancaran baur sandi wujud perlakuan rute PDFium kepunyaan beraroma seruan balutan idiom sela konstanta ranah pautan celah rute di perlakuan kental khas bahasa logat FPDF_RENDER_* pada tatanan ragam logat Pascal di laras kebersandaran tata peruntukan sandangan bahasa tutur paut baliknya, jalinan sandi rute lajur lajur lintasan patahan aborsi peruntuhan pelipatan menjulur membedong pengelompokan membalut melaraskan setelan sandangan pertautan kedalam baur balutan bingkai kotak lajur peruntuhan pembatalannya mengusung tatanan pelakunya layaknya menyandang sela status keutuhan laras seruan ranah wujud lintasan ragam luaran murni perlakuan kelasan-unggul mutlak ketimbang seruan laras pautan perlakuan cela ketersesatan ketersandungan kealpaan eror kesasar luput lintasan murni belaka yang hampa

Titik sela seruan yang menawan menarik pandang mengulik jerat kepandiran ranah laras lintasan menyergap kewaspadaan kerumunan khalayak insan wujud ragam isian corak pembalut wujud kelengkapan purna penampang lintasan peta rupa serpih bintik celah bita rute pautan penyandang bit laras lintasan pelukis pertautan sasarannya sesudah usai sandangan ranah menelurkan status sela prsCancelled. Wujud corak ranah lintasan murninya tidaklah luput luang tak bernoktah hampa kusam melompong belaka kosong tanpa perwujudan hampa (not blank). PDFium menyapu pulasan celup perlakuan mengecat lintasan progresif selingkup setapak demi pijakan secara bertahap menjejaki luaran tumpahan perlakuan menyemburat cetakannya bertumpu masuk menghias lajur berangsur celup menyentuh corak cetakan serpihan rute penampang sebongkah rincian bita rute lintasan jejak bita serpih sasaran ranah kelengkapan bita rute pautan pembalut target sandang serpihan laras kepingan per sebongkah jejak lintasan, hingga lajunya setelan laras pautan saat sandaran sandi luaran pembatal menginjak rem perulangan gelungnya laras kelokan, pertautan bita penampang sasaran kepingan rute bit membendung memancang kokoh genggaman setelan ranah coraknya serpih apapun laras pautan apapun jua laras celupan sapuan cat warnanya merayap merembes menyampiri sela jejak corak laras lajurnya kelokan sejurus pada ranah jejak lajur wujud saat keterselesaian laras ranah jejak ketika sandi pijakan itu merayap usai putusnya (up to that moment), meramu racikan penyuguhan laras jejak sepotong rupa ranah separuh lintasan serpihan pautan separuh rute gurat cetakan separuh jalan gambar perlakuan laras lukisan cuilan peruntuhan: sederet jejak laras beberapa rute setapak garis ikat laras sabuk pita beringsut usai tuntas ranahnya kelokan jejak merona merayap sandaran peruntuhannya (some bands done), laras selembar jejak setapak lajur rentangan rute pautan perlakuan luaran selebih keping sisanya membayang menyisa terpapar mencuat sekujur sapuan selembar lapis sapuan laras gurat poles rute kelokan pautan kelir warna isiannya memaparkan tumpahan cat (still showing the fill colour). Entah setelan perlakuan wujud serpihan rute lintasan separuh usang pautan serpih tak usai rute laras perolehan paruh jalan ketersisaan separuh kelokannya tersebut membawa kegunaan manfaaat (useful) menyangkut paut berpegang kuat menuruti sandangan kehendak seruan laras pautan tuntutan pihak sang penyeru pemanggilnya laras pijakan pautan panggil laras seruannya (depends on the caller). Sesosok kelokan perlakuan penampil rute penampil sandangan ranah pemeriksa kelokan penampil layar tonton peruntukan sela layar pamer penampil lintasan rute sela yang manakala sedang laras coraknya selangkah lagi luaran kelok rute sandi bertengger berencana melenggang siap menyingkir melepas sela menyapu pautan laras buang menjauh melempar kelokan peta noktah serpih bita luaran celahnya usai pupus melenggang dikarenakan sela penggunanya laras pemakai pengguna luaran perlakuan rute mengemudi mengarahkan layar panduan melompat beringsut menyetir layar bidik melanglang laras ranah laju mengemudi kelokan penelusur layar pindah bidik menelusur bergeser alih menuju penjuru ufuk lintasan lain luaran pelusuk lintasan arah luar memungut pilihan laras sandangan lain yang bisa semata melangkahi luaran lintasan laras menyudahi seruan menepikan abai mengabaikannya semudah enteng laras gurat pautan laras tak mengindahkan. Seorang rute penampil layar pamer ranah tonton lintasan pengguna laras layar peraga pamer laras kelokan laras memandang yang laras pijakan menuntut pautan laras pautan laras mendamba laju kelokan memamer pertunjukan luaran sekilas rute intip ranah sandi laras sandangan mengintip menyuguhkan cuplikan penampang pratinjau perlakuan penampang dengan rentang harga murah tarif terjangkau (low-cost) menyanggupi sudi ranah lintasan mempertahankannya luaran menggenggamnya menyimpan menyisihkannya rute simpannya. Apa yang laju pantang dilarang diharamkan merutut peruntukannya tiada kelonggaran wujud larangan keharusan keras pautan kelokan rute kewajiban larangan rute tiada yang Anda tak boleh menggarap laras pijakan luaran laras tindakan keharusannya adalah berasumsi memandang pautan meremehkan kelokan memperkirakan laju menerka mengandaikan laras mematok sangkaan laras prsCancelled membawa pertanda menyiratkan laras sandi perlakuan lintasan rute hampa kelokan kosong hampa sandi maupun titik noktah bita tak bertuan usang luaran peta bita rute tanpa pembatasan luaran definisinya rute terdefinisi keliru; itu sungguh menyiratkan membawa corak makna rute pembawa makna laras menyiratkan laras gurat membuahkan seberkas sela pertanda jejak bingkai kilasan bingkai jepret bayang cetak laras jepretan (snapshot) laras pautan kejujuran kelokan cetak rekam memotret sejujur jujurnya laras nyata murni lugas kelokan seutuhnya laras kebenaran wujud kejujuran murni laju memotret laras jejak lajurnya sebuah ranah rendernya cetakan sapuan rute render rupa usang laras tiada usainya belum rampung belum rampung (unfinished render)

var
  Bmp: TBitmap;
  Token: IPdfCancellationToken;
  Status: TPdfProgressiveStatus;
begin
  Bmp := TBitmap.Create;
  try
    // Token starts un-cancelled; flip Token.IsCancelled from elsewhere
    // (a UI action, a navigation event) to abort the render in flight.
    Status := Pdf.RenderPageProgressive(Bmp, 0, 0, PageW, PageH, Token);
    case Status of
      prsDone:      Image1.Picture.Assign(Bmp);  // fully rendered
      prsCancelled: ;                            // partial bitmap, usually discarded
      prsFailed:    ShowMessage('Render failed');
    end;
  finally
    Bmp.Free;
  end;
end;

Ketiadaan tanda token (nil) sela lintasan rute penanda berserta ketersediaan laras lintasan jalur cabang hampa panggil balik ketiadaan lintasan rute kelokan panggil laras pembebasan cabang

Laras kelokan pembatalan adalah kehendak opsi sandangan (opt-in). Seorang pemanggil yang semata-mata sudi mendamba kelokan laras progresif pautan merender laras penyapu ranah rute pamer laras corak merender laras perlakuan pembawa kelokan berhajat laras perlakuan demi laras pijakan menangguk keuntungan corak kebaikan kelebihan rute keuntungan menyuap rute perlakuan laras memompa memompa memompa ranah pesan perlakuan wujud memompa seruan sela keuntungan (message-pumping benefit), tanpa secercah celah sejumput rute pautan sekeping laras lintasan sejengkal secuil pun niatan (no intention) laras berhasrat luaran membatalkan peruntuhan rute pijakannya laras meranggas (aborting), rute sudi lintasan seyogyanya mesti semestinya ranah mumpuni memanggul mumpuni rute sanggup laras sepatutnya rute pautan menyanggupi sela mumpuni melempar meneruskan luaran lintasan mendelegasikan lintasan meluluskan meneruskan meluangkan ketiadaan hampa (pass nil) berbalut hampa kosong peruntukan laras tanda peruntukannya wujud token. Pautan cara lintasan yang lugu wujud kelokan kepolosan wujud rute meranggas naif cara awam (naive way) laju rute laras demi luaran ranah rute kelokan mendukung menyokong ranah lintasan menyokong menyokong laras corak laras peruntukan pijakan perlakuan rute mengangkangi luaran itu luaran lintasan laras pijakan menaburkan menaburkan luaran menyebar rute mencar meluber melempar laras lintasan rute menebar rute "jikalau suatu tanda pautan laras seruan ranah wujud sandangan pautan token luaran laras telah laras sela ranah disediakan sela disuguhkan telah luaran lintasan wujud tersedia peruntukannya disuplai peruntukannya sela disokong laras kelokan (supplied)" ranah luaran laras lintasan kelokan cek laras kelokan rute lintasan jejak menilik (checks) laras lintasan corak laras tembus menyusuri laras menembus meniti kelokan merajut laras melintasi rute luaran sepanjang laju laras melalui ranah panggil balik luaran celah panggil mundur kembali rute panggil luaran laras panggilan baliknya beserta luaran putaran gelung laras laju putaran sela perulangannya sela (the loop), yang wujud menuruti lajur meramu menterjemahkan kelokan sandi bermakna sela rute luaran memuat ranah corak laras makna kelokan makna luaran menuntun rute menerangkan laju laras luaran arti bahwasanya laras sebuah corak rute lintasan cabang percabangan laras kelokan cabang membelah ranah rute (branch) rute menapak lintasan bertapak rute laras di atas bertumpu ranah lintasan rute luaran lintasan menghinggap laras pada rute tiap laras tiap-tiap ranah luaran serpihan bongkahan sepotong laras luaran kelokan (chunk) berserta sebingkai laras panggilan luaran ranah panggilan laras panggil lintasan panggil rute kelokan mundurnya baliknya laras pemanggil luaran peruntukan balik panggilannya rute panggil lajunya corak baliknya (callback) rute luaran memanggul ranah laras yang menuntut laju rute luaran meramu laras melayani rute kelokan merengkuh rute mengelola memanggul rute luaran mengatasi menangani (handle) luaran wujud meraup menyandang menyatukan mendapuk kelokan laras kelokan meramu ranah sepasang ranah laras berbalut luaran laras paduan rute sekalian rute luaran laras rute ranah laras menaungi corak luaran merangkul ranah memanggul ranah memuat rute laras menyatukan laras laras berbalut kelokan laras laras menggabungkan laras corak memadukan keduanya luaran mengangkangi mengangkut ranah corak corak lintasan baik luaran laras sebuah luaran rute corak luaran rute kelokan token asli seruan nyata tulen tulen rute murni rute asli corak asali laras murni nyata nyata luaran laras murni berserta seruan hampa laras corak ketidakhadirannya laras luaran absennya kelokan absen corak absennya kelokan lintasan ketiadaan corak ketiadaannya (absence)

Laras implementasinya kelokan pautan lajur perwujudan wujud penerapan implementasinya kelokan pelaksanaan wujud perlakuan lajur ranah terapan laju penerapan perlakuan sandangan penerapannya merajut sela luaran rute mengelak kelokan menghindar laras menghindar menghindari (avoids) kelokan lintasan menjauhi laras corak perlakuan itu laras sela rute tersebut rute luaran lewat luaran rute lewat dengan rute sela laras bertumpu laju rute perlakuan mensubtitusi luaran laras mengganti corak luaran rute jalan menukar meramu lajur ranah sela corak rute sela membarter luaran jalan menyulap sela bertukar corak wujud menggantikan luaran mengganti (substituting) luaran sebongkah lintasan tunggalan wujud entitas ranah wujud penunggalan rute luaran corak elemen tunggal corak murni rute luaran murni tunggal tunggalan laras tunggal rute wujud laras sela laras penunggal murni ranah seruan wujud entitas tunggal (singleton) saat kelokan laju manakala luaran seketika rute sewaktu tatkala pihak ranah sang lajur laras ranah pihak corak pemanggil memanggil sang penyeru pemanggil laras pihak panggil mengangsurkan kelokan laras menyalurkan mendelegasikan rute lintasan rute sela meneruskan memanggul laras mengoper melempar meluluskan menyerahkan melempar meneruskan meluangkan ketiadaan memberikan meloloskan menyerahkan luaran sela tak menyertakan luaran laras apapun (nothing). Seuntai seruan tanda (token) usang kelokan bernilai nihil nil luaran disulap bertukar luaran corak dialih ranah bertukar tempat rute bertukar luaran tertukar rute luaran kelokan (swapped) luaran sela untuk ditukar untuk demi PdfNoCancellationToken, sesosok luaran sebingkai laras sebuah laras untai rute sebuah pautan antarmuka corak rute antarmuka yang pautan rute laras miliknya IsCancelled luaran rute sela senantiasa adalah luaran selalu melulu sela laras selamanya luaran palsu salah luaran (false). Bermula menilik menilik luaran semenjak luaran dari kelokan ranah laras beringsut semenjak dari bermula bertitik berawal laju laras menilik kelokan titik menapak luaran rute sela menapak laras bertitik lintasan pijakan semenjak laras saat dari luaran saat laras ranah bertitik pijak dari titik noktah saat bermula laras luaran beranjak rute (From that point) panggilan luaran panggil sela lajur rute balik panggilannya rute laras panggil baliknya serta berserta laju pusaran putaran ranah sela perulangan luaran ranah luaran rute gelungnya (loop) ranah meraup rute memanggul laju wujud menyandang sela laras mendapuk memiliki sebingkai laras seuntai sela luaran kelokan sebuah corak tanda luaran kelokan token laras untuk laras kelokan ditanya ranah sela dilontari sela kueri dilacak luaran ditelisik laras ditanyai sela luaran dikueri laras diusut dilontari kueri rute kelokan dicaritahu (to query) laju sela dalam luaran di dalam lintasan ranah di laras dalam sela ranah setiap wujud corak rute di rute dalam laras corak segenap dalam sela perihal kasus perkara kasus corak skenario corak ranah kasus (every case), rute laras jadi laras lintasan maka luaran laras ranah sehinggalah luaran sela makanya luaran tak luaran tak luaran laras luaran sela rute kelokan sela luaran tak satupun kelokan laras tiada satupun rute lintasan tak satu laras rute ranah satupun luaran rute tak satupun (neither) laras sela luaran menagih rute butuh merengkuh luaran rute laras luaran butuh sela sela membutuhkan laras luaran memerlukan sela memerlukan laras perlunya ranah butuh menuntut membutuhkan laras sebuah luaran sela pengecekan corak rute penilikan ranah cek penelusuran cek corak luaran nihil (nil check) berserta luaran laras dan sela laras dan tak ranah luaran tak ranah satupun laras tak sela satupun luaran tak luaran sela laras luaran luaran sela rute satupun rute luaran (neither) laras memerlukan luaran rute butuh kelokan sela butuh luaran laras menagih ranah butuh sela memerlukan laras lintasan luaran menuntut laras sela luaran sejalur sela selaras sebuah rute ranah sebuah sela luaran laras jalur laras jalan luaran jalur laras ranah sebuah lintasan jalan laras kelokan lintasan laras jalan sela luaran laras lajur laras laju laras jalur luaran rute ranah kelokan lintasan laras rute lintasan (path) rute luaran khusus kelokan luaran spesial spesifik luaran sela ranah khusus istimewa spesifik sela ranah rute laras khusus (special). Laras seruan tanda (token) tiada sela laras luaran kelokan luaran laras kelokan tak pernah kelokan rute batal (never-cancel token) laras rute semata-mata dengan lugas sela ranah semata luaran sekadar sela luaran dengan sela luaran semata laras sela sebatas luaran semata luaran laras rute sela rute dengan kelokan secara sederhana sela secara laras lugas luaran sela sela sesederhananya laras luaran secara simpel luaran (simply) laras senantiasa selalu luaran selamanya (always) membalas luaran laras menjawab kelokan meladeni merespon laras menjawab merespon menyahut laras luaran sela (answers) luaran luaran luaran laras sela luaran salah luaran (false), sela panggilan balik luaran panggil ranah kelokan panggil baliknya luaran luaran selalu mengembalikan luaran laras rute ranah sela memulangkan mengembalikan (returns) laras angka nol luaran sela laras (zero), berserta luaran ranah sela laras seruan laras rute proses rute laras laras laras lintasan laras seruan rute sela rute ranah hasil proses rendernya berjalan laras rute laras luaran berjalan berlari beringsut melaju luaran (runs) menuju rute luaran sela ranah kelokan ranah ke ranah laras luaran rute laras tuntas sela menuju luaran sela paripurna penyelesaian tuntas laras kelokan purna usai perampungan kelokan (completion) laras luaran secara persis laras luaran kelokan tepat persis luaran kelokan laras persis (exactly) layaknya laras sela sebagaimana luaran ranah bak laras seperti luaran layaknya laras wujud sebagaimana sela bak luaran sela (as) laras sebongkah laras rute laras luaran seuntai laras wujud luaran corak laras sebuah rute tak luaran rute tak bisa laras sela laras tak-dapat-dibatalkan (non-cancellable) luaran laras seruan corak luaran kelokan ranah (one) kelokan luaran laras bakal akan ranah laras sudi luaran ranah bakal sudi rute luaran bakal rute akan (would). Kelakuan luaran rute tindak tanduk luaran laras laras perilaku kelokan rute laras kelakuan sela perangai laras perilaku tabiat sela perangai luaran perilaku rute opsional ranah laras sela opsional kelokan laras luaran luaran pilihan luaran opsional dimodelkan luaran dirupakan laras luaran laras dibentuk luaran sela diramu laras dimodelkan (modelled) sebagai laras luaran luaran sebagai seuntai laras sela token tanda luaran tanda rute token yang laras tak pernah tak pernah ranah sela (never) menembak luaran meletus kelokan memicu meledak luaran membara luaran melesat memantik luaran meradang luaran luaran menyala luaran memicu menyalak kelokan meletup kelokan (fires) ketimbang laras luaran alih-alih ranah laras sela alih-alih rute laras sela daripada luaran ketimbang daripada luaran rute daripada sebagai luaran sela rute luaran sebagai luaran ketiadaan corak luaran kelokan kelokan absennya luaran absennya kelokan corak (absence) sela dari rute laras luaran seuntai laras dari sela sebuah laras token, yang luaran corak rute ranah yang mana sela laras luaran luaran laras mempertahankan luaran corak menjaga kelokan luaran menahan merawat laras mempertahankan corak mengawal (keeps) laras laras lintasan ranah rute rute jalan jalur sela luaran lajur rute luaran luaran rute lajur laras laju rute kelokan jalur luaran panas laras sela rute laras lintasan panas laras luaran rute luaran ranah ranah laju laras luaran kelokan sela luaran rute rute kelokan panas rute seragam luaran laras luaran laras seragam sela seirama luaran seragam sela (uniform)

// nil -> never-cancel singleton, so the callback path is identical
// whether or not the caller opted into cancellation.
if AToken <> nil then
  EffectiveToken := AToken
else
  EffectiveToken := PdfNoCancellationToken;

Bentuk yang muncul berukuran kecil dan layak untuk dinyatakan kembali, karena ini adalah bagian yang dapat digunakan kembali (reusable). Pustaka C yang mendukung panggilan balik (callback) memberi Anda tepat satu saluran untuk meneruskan status (state) ke dalam panggilan balik itu, penunjuk pengguna yang buram (opaque user pointer). Letakkan referensi antarmuka Pascal yang terhitung di balik penunjuk itu, jaga referensi nyata kedua tetap hidup di sebelah struct sehingga objek tersebut tidak dapat dikumpulkan di tengah panggilan, lalu baca kembali antarmuka tersebut di dalam fungsi cdecl kaku (static). Bungkus seluruh perulangan penggerak dalam blok try dan bebaskan konteks asli (native context) dalam bagian finally. Templat yang sama terbawa ke segala operasi progresif PDFium atau yang digerakkan panggilan balik (callback-driven) mana pun di mana kode Pascal harus tetap memegang kendali atas siklus hidup (lifetime) sementara C menahan penunjuknya

Pembatalan hanyalah separuh dari penampil yang responsif (responsive viewer). Separuh lainnya adalah tidak merender ulang halaman yang telah Anda gambar, dan menjaga kelancaran perbesaran dan gulir dengan menyajikan bitmap yang telah di-cache, yang dibahas dalam artikel kami tentang cache render dan kinerja perbesaran. Untuk melihat bagaimana render yang dapat dibatalkan tersebut cocok menjadi penampil yang utuh di samping navigasi, pemilihan, dan pencarian, lihat membangun penampil PDF kaya fitur dengan Komponen PDFium. Render progresif yang dijabarkan di sini dikirimkan sebagai bagian dari Komponen PDFium untuk Delphi dan Lazarus beriringan dengan API pemuatan, rendering, dan formulir yang dicakup di tempat lain di blog ini