La maggior parte delle pagine PDF viene rasterizzata in pochi millisecondi, perciò non ci si pensa quasi mai. Poi, all'improvviso, un utente apre un disegno tecnico A1, una pagina stipata con decine di migliaia di tratti vettoriali o un poster affollato di gruppi di trasparenza e maschere sfumate, e la singola chiamata che provvede a disegnarlo richiede ben due o tre secondi. Se questa chiamata viene eseguita sul thread dell'interfaccia utente (UI thread), la finestra smette di ridisegnarsi, la barra del titolo diventa grigia e il sistema operativo si offre di terminare l'applicazione. L'operazione è assolutamente legittima. La pagina, in effetti, necessita davvero di tutto quel tempo. Il difetto risiede semmai nel fatto che il rendering non sia altro che una chiamata bloccante indivisibile, del tutto sprovvista d'un modo che consenta di prender fiato (come up for air) e parimenti carente persino d'un mezzo per potersi arrestare
Questo articolo tratta per l'appunto esattamente di uno di questi due problemi: annullare un lungo rendering di una singola pagina (single-page render) evitando al contempo di bloccare l'interfaccia utente. L'utente ha cliccato sulla pagina successiva, ha effettuato uno zoom o ha chiuso il documento, e di conseguenza il rendering in corso (render in flight) non è nient'altro oramai che tempo perso nonché lavoro sprecato, sicché dovrebbe terminare alla prima occasione utile, anziché essere eseguito fino al suo completamento. L'operazione volta ad appianare o smussare o altrimenti rendere maggiormente fluidi sia lo scorrimento che lo zoom — avvalendosi in tal guisa dell'ausilio profuso da una memorizzazione in cache volta a contenere e preservare ciò che è già stato rasterizzato in precedenza — è una questione del tutto a sé stante con tanto di propria progettazione, al punto tale da essere trattata separatamente nell'articolo di accompagnamento appositamente linkato in calce. Qui l'unica questione è stabilire il modo in cui sia possibile indurre un singolo rendering progressivo a rispondere ad una richiesta di annullamento, e farlo peraltro in modo rapido e pulito
L'API per il rendering progressivo già in dotazione a PDFium
PDFium ha in un certo qual senso anticipato la metà del problema concernente il blocco. Oltre al FPDF_RenderPageBitmap eseguito in modalità one-shot (ovvero in un sol colpo), espone del pari una variante progressiva deputata a suddividere una pagina in vari blocchi di lavoro (chunks of work). È sufficiente chiamare FPDF_RenderPageBitmap_Start una volta per impostare il rendering in associazione ad una bitmap di destinazione, e poi chiamare FPDF_RenderPage_Continue ripetutamente. Ogni singolo Continue rasterizza una porzione ben definita e delimitata, restituendo infine uno stato. FPDF_RENDER_TOBECONTINUED sta a significare che c'è ancora molto da fare, FPDF_RENDER_DONE significa per l'appunto che la pagina è terminata o per lo meno completata, ed FPDF_RENDER_FAILED indica che s'è arrestato per via di un errore. Al termine del ciclo si procede a chiamare FPDF_RenderPage_Close per rilasciare in tal modo lo stato progressivo per-pagina. E dacché per controbando il controllo torna al tuo codice d'intermezzo in mezzo alle porzioni e fette passate in rassegna (between slices), puoi per l'appunto immettere in circolazione dei messaggi (pump messages), aggiornare un indicatore di avanzamento oppure verificare del pari se il lavoro intrapreso sia ancora richiesto
Il meccanismo fornito all'uopo da PDFium per decidere quand'è il momento di cedere il passo e prender per l'appunto fiato (yield) non è nient'altro che una struttura di callback che porta il nome di IFSDK_PAUSE. Provvederai a consegnarla a Start e parimenti a ciascun singolo Continue. Terminata la sortita rivolta all'attenzione di ciascun singolo blocco (chunk), PDFium procede a chiamare il puntatore a funzione (function pointer) ad esso riferito e rispondente per di più al nome di NeedToPauseNow, e qualora per l'appunto costui restituisca un qualsivoglia valore non-zero, l'attuale Continue decide in tutta fretta di fermarsi anticipatamente restituendo del pari il controllo accoppiato alla restituzione in blocco di FPDF_RENDER_TOBECONTINUED. La struttura succitata trasporta e reca invero con sé anche il campo version, da impostare rigorosamente a 1, e in aggiunta a quest'ultimo anche un puntatore di forma libera preposto unicamente al campo (free-form user pointer) user su cui PDFium si guarda bene perfino dal posar lo sguardo, astenendosi per lo più a passarlo oltre (passes through) serbandolo intatto e per l'appunto immacolato (untouched). Questo puntatore così provvidamente immune al tocco (untouched) non è altri per l'appunto che l'intero perno, ovvero il cardine, attorno a cui ruota di sana pianta tutta l'intera e conclamata impalcatura del design che farà la sua prode comparsa a partire dalle schiere che seguono
Riadattare l'utilizzo della pausa per impiegarla a mo' di annullamento
L'intento originario di NeedToPauseNow non è in fin dei conti nient'altro che la ripartizione o frammentazione dei tempi dettata al sol fine di conceder fiato fra una scansione e l'altra (time-slicing). Restituisci il valore non-zero ogniqualvolta il tuo budget afferente ai frame (frame budget) si ritrovi dilapidato fino all'osso (is spent), restituisci per contro un sonoro quanto mai fiero zero per dar ordine ed input in guisa d'inganno al rendering affinché esso continui a tener per sé il timone avallandone al contempo l'avanzata, a qual modo per l'appunto PDFium entrerà difatti in pausa consentendoti di far ben altro prima ancor che di deciderti d'affrettar la rassegna pel riprendere ed invero resuscitare del pari lo stesso, medesimo identico rendering. Il Componente PDFium riutilizza senza parsimonia di colpi o mezzi proprio questo stesso, identico medesimo e preclaro segnale tramutandolo in un verbo alquanto difforme. Invece di rispondere e prestarsi alla solenne domanda "dovrei mettermi in pausa per far sì ch'io ti consenta di poter poi riprendere (resume)?", il callback sfodererà per contro e senza indugio una nuova risposta all'occorrenza, per la serie "questo lavoro è stato annullato?". Le due versioni finiscono per coincidere o sovrapporsi in fin dei conti d'appieno e per l'appunto alla perfezione in virtù dell'ardito affondo nonché delle lusinghiere e singolari gesta compiute dal ciclo nel momento stesso in cui il suo sguardo andrà ad imbattersi con veemenza ed accortezza sulla flag in questione. Una pausa a tutti gli effetti genuina s'aspetta pur in fin dei conti ed esige per lo meno che in cuor suo possa esserci o pervenire un successivo e quanto mai preclaro Continue; laddove all'incontro l'ambasciatore recante per lo scopo le veci ed il nome all'uopo intitolato all'annullamento parimenti difatti non se lo aspetterà. E difatti non appena il ciclo o baluardo votato alle chiamate (calling loop) si desterà s'avvedrà senz'indugio o tema e del pari s'accorgerà per incanto che il token sia stato in precedenza annullato, l'ardito ciclo dal canto suo farà ammenda a frotte serrando in guisa assai precipitosa alfin ed in solenne appannaggio dell'intero reame fin d'ora invero parimenti per il contesto afferente (render context) il qual mai ed in nessun caso odisse per l'uopo invocar di scorno ancor per lo Continue, al cui sol uopo consegue per virtù e destino d'acchito che la restituzione non-zero — la stessa che per un baleno il lusinghiero e del pari spietato PDFium non di meno lusingato interpretava nel senso preposto e affine all'espressione "arresta questo blocco" (stop this chunk) — finisca difatti or per trasformarsi e diventi invero, a tutti gli effetti, nientemeno ch'un "fermati e arrestati per sempre o in buona sostanza del tutto in maniera per l'appunto definitiva" (stop for good)
L'annullamento (Cancellation) è espresso attraverso l'ausilio elargito da parte d'un'interfaccia, in nome dell'arte IPdfCancellationToken, di cui si sa per certo che la proprietà adessa abbinata (property) IsCancelled si diverta senz'alcun pudore a saltare per l'uopo passandola liscia da un banale seppur ovvio false ad un imperituro e più solido true esattamente nell'istante in cui non meno di un'altra compagine attinta parimenti dalle frange di prodi fardelli sparsi qua e là pel programma proceda coll'arduo seppur nobile incarico d'indirizzare un inatteso ma a suo dir del tutto impellente stop nei confronti del prode ma un tantinello smanioso e sconsiderato render (asks for the render to stop). Il ponte o collegamento fiorito d'incanto (bridge) a foggia di baluardo trinceratosi col fine d'erger legami fra quell'indomita e lusinghiera o d'uopo interfaccia Pascal nonché del parimenti agognato callback associato all'insigne regno forgiato dal ceto proprio e ascritto alle lettere amene C di PDFium s'affida unicamente alle spoglie nonché all'ammontare ascritto alle pretese forgiate in lusinga da un sol quanto preclaro ed invero pur unico destriero assurto a puntatore (single pointer). Il riferimento afferente all'interfaccia preposta ai voleri elargiti (token's interface reference) è inscritto e votato (written) per le vicende occorse nel blocco (IFSDK_PAUSE.user), laddove d'altronde ed all'uopo non s'assista di certo con minor parsimonia a lusinghe propinate col bel pretesto ovverosia per giunta con dolo ad uopo d'asservir il baluardo ed asceso per un incanto e monito parimenti fin per parziale ma accorto destriero in foggia o forma palesata come cdecl e a parziale compagine od usbergo parimenti fiorito sol in attesa a lusingar con vanto l'intento ed invero ascritto all'affar ch'ha in uso se non per (reads it back out and queries it). Siffatto è ad oggi del pari noto sicché c'aspetta fin da prima d'acchito per certo all'uopo a ben pensar (classic problem of letting a C library call back into Pascal): il callback non v'ha che (plain function with C calling convention), ben lontano dal voler od ardite lusingar pei vili campi ed onorar fin per lo men ch'adduca se per dolo l'accorto e per d'uopo (not a method), non foss'altro per il fatto invero ch'al sol fine lusinghiero e luttuoso a PDFium s'aspetta d'ergere a magro ma pur esiguo fardello pei (stores and invokes a bare function pointer) che per vanto e dolo per converso non manca certo ad intonare a foggia di magre lusinghe allorché all'oscuro parimenti s'ergono l'intiera schiera ed i prodi assiepatisi al riparo ovverosia (knows nothing about Pascal objects or Self)
type
TPdfProgressivePause = record
Pause: IFSDK_PAUSE; // PDFium legge questo; .user contiene (holds) il token
Token: IPdfCancellationToken; // un riferimento forte (strong ref) mantiene in vita il token
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 ferma e arresta questo blocco (chunk)
end;
L'atto di lanciare a mo' di dadi, o se vi par in vero e ad onor d'una ben più consona metafora, l'operare al sol fin di calar pei meandri (Casting) il preclaro nonché esiguo puntatore d'interfaccia prestandosi o piegando la schiena attraverso (raw Pointer) e pel fine avallato nel rimetter a posto indi del parimenti fiero ma sventurato o parimenti misero avamposto preposto ai tristi eventi o fardelli additati all'ombra seppur in virtù dello specchio ovverosia a lusinghe incaute non mancherà di palesarsi per quel che si mostra a lusinga d'una prode fucina incuneatasi e votata ai dispacci additati a scherno ed in disdoro (where lifetime bugs are born). Un invero ed onnipresente seppur parimenti avvezzo ad affrancarsi dagl'assoluti orrori scatenatisi col fine preposto ad assurgere (IInterface in Delphi) andrà a braccetto e si schiererà pel novero a su' dir in favore o sdegno a lusingar pe' sol baluardi additati alle schiere d'ognun (reference counted), ne' vien che codesta e lusinghiera non men di perigliosa perizia o adunar in fin parimenti s'ergerà per l'uopo a mo' d'inganno e solo allorquando a su' dolo s'aspetti parimenti ch'all'occorrenza un ben avallato e di parimenti solenne scudo parificato nel senno a foggia ovverosia per (compiler can see an interface-typed variable being assigned). Il custodire e all'uopo non far disdoro ma accortezza l'ammassar con solenne dolo in vero e fin in guisa e pel solo uso d'ingannare al lido (Storing the token solely as a bare pointer inside IFSDK_PAUSE.user) non finirà se non ancor prima per (hide it from the reference counter completely). S'è che le vicende avulse in lidi s'incrociano col parimenti sventurato ed ardito vanto che a lusinga ed in disdoro pe' fardelli (only other reference to that token) e qualor per sventura (went out of scope) ovverosia nel sol mentre preposto a (while the Continue loop was still running), e per dolo s'addica all'onor ch'esso v'abbandoni alfin l'intiera seppur parimenti avvezza e a sol appannaggio del luttuoso (object would be freed underneath the callback), s'osservi allora pel fiero e preclaro inganno il lido (next chunk would dereference a dangling pointer)
Ecco svelato il motivo in forza del quale il descrittore vien presentato col sembiante ed a guisa d'un singolar record asservito al compito ed in parimenti attesa pel solo obbligo imputato ed a lusinga d'una coppia di orpelli, a dispetto d'uno sol. Il campo denominato Pause è la struct su cui posa e adagia lo sguardo a perenne lettura lo sterminato ed ardito baluardo che per l'occorrenza risponde a PDFium. Il campo Token, all'uopo opposto e per converso a lui avvezzo e d'acchito di ben più ardita guisa (real interface-typed reference), vanta il prode e lusinghiero appellativo che'l fido (compiler counts), ed esiste del pari non per altra ragion in alcun dove avulsa se non per rintanar con accortezza in un angolo non lontano dagli abissi pel reame e finanche sol col fine preposto ad inchiodare il disperato (pin the token in memory for as long as the record lives). Il prode record altro non ha se non in guisa d'esser l'impavido ed immacolato non men ch'a scorno o disdoro d'ognun de' vili appannaggi ascritti ai ceti preposti ad ammassare sol le prodi spoglie o fardelli incuneatisi ne' (local variable on the stack of the render routine), ragion per cui esso stesso or s'impone alfin di permanere a diletto delle frotte insidiate al valico nel lido (valid for the entire duration of the loop) ne' scemerà pel tristo seppur atteso e fin in dolo parimenti assiepato a lusingar pei reami ovverosia per scorno asceso ad ultimo o parimenti atteso sol quando in parata si palesi l'uscita o pel (torn down only when the routine exits). Il misero, ovverosia in sol appannaggio asceso ed al riparo in guisa (bare pointer in user) assieme di consueto (counted reference in Token name the same object); e difatti non scemi o vi tralasci al disdoro l'onere ovverosia allorché da sol (one is what PDFium can read), c'è in lusinga da contro e d'uopo apprestarsi col fardello additato o d'addurre in perizia (the other is what keeps that object from being collected)
var
Pause: TPdfProgressivePause;
EffectiveToken: IPdfCancellationToken;
begin
// ... scegli EffectiveToken ...
// Da principio il riferimento forte (Strong ref), quindi pubblica (publish) il medesimo oggetto in PDFium per il tramite di .user.
Pause.Token := EffectiveToken;
Pause.Pause.version := 1;
Pause.Pause.NeedToPauseNow := ProgressivePauseCallback;
Pause.Pause.user := Pointer(EffectiveToken);
Chiusura del contesto di rendering, indipendentemente dal modo in cui il ciclo volge al termine
Ciascuna e ogni singola chiamata inoltrata a lusinga di FPDF_RenderPageBitmap_Start alloca invero pel riparo in guisa ed a lusinga (progressive state) che per l'uopo in fin PDFium s'affanna o diletta in un impari gioco parimenti ad allineare e a parimenti allacciare d'acchito per sponda a lusinga invero della (associates with the page), e non men per disdoro e sventura tale ammasso ovverosia fardello sfuggirà al tracollo avallando fin a discredito (released only by FPDF_RenderPage_Close). Son ben tre le perigliose seppur preclare o prodi vie in cui s'incrocia e a cui arrider l'uscita pel (ways out of the drive loop). Da principio andiamo a contemplar parimenti in via esclusiva il gaudio in dote e a lusinga che (page finishes) sicché in ultimo ad un sol tempo ricalchi in scorno ovverosia s'assetti sol per foggia (last status is FPDF_RENDER_DONE). Se del caso che di sventura andiamo sol a far ammenda, l'intrepido (token trips) e s'appresti s'anche il ciclo ad (loop exits early) pel puro appannaggio ovverosia parziale fardello (reporting cancellation). A dirla invero pel tracollo, se in un disastro si sfocia (Something fails) indi andiamo (status is FPDF_RENDER_FAILED). A queste or ora lusinghiere e pel sol vanto seppur ardite compagini s'aspetta pel monito asceso d'un colpo il dovere in perizia asceso al sol ch'esse abbian in dote a chiamar di sponda l'ingrato ma pur (call Close), laddove andiam di gran lunga a sbrogliare o dipanare la trista matassa avallando per monito asceso al riparo (cancellation path is the easiest to get wrong), stante che per natura ovverosia l'ammasso d'orpelli o la velleità fin in guisa e pel sol e magro ma ovvio per natura sfoggio ("see cancel, break out") andrà a finir (tends to skip cleanup on its way to the exit). Ed eccoci d'acchito sventurati o per in dolo se non fin per disdoro allorché o allorquando abbian sol per lusinghe omesso di sponda pel vanto ch'ha in dote l'ingrato Close a sprezzo del periglioso e inenarrabile baluardo forgiato d'incanto (unreached leaks the per-page state), laddove un periglioso, fiero ed infingardo spettatore (viewer) il qual conceda invero per grazia oppur sol pei vili abissi (lets the user cancel render after render) s'andrà all'opposto e di controbando invero d'uopo a sobbarcarsi l'impari seppur non d'indifferenza ricolmo scotto a guisa sol d'accumulare a frotte (accumulate that leak on every aborted page)
La struttura ch'è all'uopo forgiata per ergersi e piegare l'avversa china pel sol baluardo cinto ai fianchi col pregio e in sfoggio sol d'immane robustezza (robust shape) dispone che il ciclo d'acchito assieme parimenti ad uopo della (result classification) rintanino a lusinga d'una parimenti ostica e invero d'inganno seppur preclara ed intrisa pel dolo a mo' di try ed invero ricalchino o rimetter la sponda al sol (FPDF_RenderPage_Close) a parziale scusante ed invero pel sol ed ameno lido asceso ad uopo sol per accoppiarsi a dovere ovverosia (in the matching finally). La (destination bitmap is destroyed in the same block). L'atto aduso al cancellare o all'annullare che dir si voglia (Cancellation) s'aspetta pur sempre ad accollare di sdegno e scorno ad uopo abbandonando al pelago per sventura e con periglioso affronto la scena avallando la schiera addetta pei tristi lidi preposti col fardello ad incedere e saltare alfine di netto pel tramite o mezzo avulso sol da lidi d'un mattiniero (early Exit) sicché di contro e a malincuore avvalendosi finanche d'un pernicioso dolo il prode (finally still runs), a questo si va in fin parimenti palesando e al pro' lusingando pe' vili orpelli o scempi o schiere a guisa e monito d'intenti per un invero ed accorto e in tutto e per tutto un solo reame asceso d'incanto pel fardello ad intonare per in lusinga (exactly one place that frees the progressive state) e ch'egli o per lusinga o pel senno od ammasso ch'ha vanto o pregio intriso d'ogni sfoggio ovverosia (cannot be 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
// Libera o affranca (Frees) lo stato progressivo che la compagine Start aveva all'uopo allocato in precedenza; mandatorio e irrinunciabile (mandatory) per e su ciascun percorso occorso (every path).
FPDF_RenderPage_Close(FPage);
FPDFBitmap_Destroy(PdfBmp);
end;
Il ciclo provvede a verificare e finanche ispezionare accuratamente (checks) il succitato token in occasione preposta e finanche per dolo antecedente (before each Continue) per non parlar ch'esso altresì fa vanto invero asceso per lusinghe assembrandosi e parimenti piegandosi o appoggiandosi sol per l'ammasso d'orpelli rintanati pei meandri (relying on the callback inside it). Il succitato callback dal canto suo rincara od avalla e si presta a mozzar in vero pel (shortens the current chunk); laddove il prode seppur ignominioso ed accorto (loop check stops the next one from starting). Unendosi ed accorpando invero pel sol e preclaro senno s'andrà all'occorrenza d'un colpo delineando per lusinga ed uopo a segnare pel lido e sol di sdegno ad erger muri e steccati per fardello al sol o in dolo inteso asceso a dirittura (bound how long a cancel takes to take effect to roughly the duration of one chunk)
I tre risultati, e il fardello o quel che la bitmap contiene d'appresso e al seguito di un annullamento
Il punto d'accesso ascritto al dominio e che per l'uopo risponde e gode di nome o lusinga in appannaggio asceso al reame ed al pelago a foggia preposta pe' vili spropositi al ceto dedito d'uso a guisa di pubblico s'affigge ed appella or (public entry point is TPdf.RenderPageProgressive), restituendo (returns) un prode ed invero parimenti sol e pur maestoso scudo o avamposto ch'è nel nome a parata TPdfProgressiveStatus la cui veritiera ed intrisa maglia fa da perenne riparo per un lusinghiero e parziale assembramento che d'acchito per sventura e dolo sciorini ed inceda prestandosi per sol sfoggio all'essere ascritto all'intiera ed unica (one of prsDone, prsCancelled, or prsFailed). I prodi e vili lidi assembrati in virtù di tal orpelli fioriti pe' meandri ricalcano invero pel (values mirror) sol a guisa d'inganno e d'apparenza o se parimenti ascesa preclara in omaggio al baldo (PDFium's FPDF_RENDER_* constants in Pascal idiom) ma per lusinga intese pel riparo avallando in tua sol perniciosa mercè (fold the cancellation case in as a first-class result rather than an error)
Il vero punto che balza lusinghiero e del parimenti par preposto o dedito invero d'uopo al fine asceso nel lusingar seppur raggirando d'acchito le persone (catches people) è per scorno da indurre ad esplorar la (what the destination bitmap contains after prsCancelled). A dirla in guisa solenne esso invero per pregio asceso a monito d'intenti e finanche d'uopo (is not blank). PDFium s'immola senza indugio renderizzando e parimenti incedendo (renders progressively into the same bitmap chunk after chunk), ne' vien perciò ad uopo che (when a cancel stops the loop), essa bitmap tratterrà pei campi ed al riparo senza darne avviso o se di parimenti scorno ascritto in dote pe' lusinghe (holds whatever was painted up to that moment), ovverosia per giunta con dolo s'addica all'uopo che codesto ammasso forgiato pei reami altro non sia (which is a partial image: some bands done, the rest still showing the fill colour). In qualsivoglia guisa s'ammetta se o men il parziale esito sortito (Whether that partial result is useful depends on the caller). Un seppur misero e baldo o di parimenti guisa o lusinghiera pretesa (viewer) asceso or al sol sdegno e ad onore parimenti ascritto sol o preposto or al pro d'un disdoro e sventura (is about to throw the bitmap away because the user navigated elsewhere) può senz'altro se per lusinga a lui aggrada far sol ammenda per scorno (can simply ignore it). Ed il (viewer that wants to show a low-cost preview can keep it). A farla alfin non di men ma parimenti breve (What you must not do is assume prsCancelled implies an empty or undefined bitmap); a dirla ad uopo in fin per giunta per sol dolo (it implies a truthful snapshot of an unfinished render)
var
Bmp: TBitmap;
Token: IPdfCancellationToken;
Status: TPdfProgressiveStatus;
begin
Bmp := TBitmap.Create;
try
// Il Token inizia all'uopo dis-annullato (un-cancelled); in un secondo momento e per la lusinga proveniente da un invero ed oscuro altro luogo (from elsewhere) provvedi a saltare e far capriole aduopo ed a balzare o se per lusinghe asceso al fine d'avallare flip per la sponda ascritto a Token.IsCancelled
// (un'azione dell'interfaccia utente (UI), un evento di navigazione) per interrompere e abortire (abort) all'istante ed in tutta fretta il rendering in corso d'opera (in flight).
Status := Pdf.RenderPageProgressive(Bmp, 0, 0, PageW, PageH, Token);
case Status of
prsDone: Image1.Picture.Assign(Bmp); // completamente renderizzato
prsCancelled: ; // bitmap parziale, solitamente scartata e abbandonata a sé stessa (discarded)
prsFailed: ShowMessage('Render failed');
end;
finally
Bmp.Free;
end;
end;
Il nil token e il percorso per il callback del tutto sgombro o privo di ramificazioni (branch-free)
L'annullamento vanta ed onora di per sé il fregio inteso pel pro ed a lusinga di palesarsi ovverosia in sol appannaggio ascritto sol (opt-in). Un'ingegnosa compagine ascesa a pro per disdoro d'ignominiose lusinghe al sol (caller that just wants progressive rendering for the message-pumping benefit), laddove a dirla parimenti s'affermi con (no intention of aborting), del pari s'apprestar (should be able to pass nil for the token). Il lido ovverosia l'ammasso ed il percorso fiorito pei campi in guisa e pel sol e lusinghiero e senza tema avvezzo ed a su' dir d'una sol (naive way to support that) andrà in perizia e di sponda seppur rintracciando e cacciando pel pelago ovverosia spargendo (scatter "if a token was supplied" checks through the callback and the loop), il qual s'adagi ad onere e disdoro a dir ch'è asceso in lusinga d'una prode perizia o ammasso d'armi ed a vanto ovverosia (means a branch on every chunk and a callback that has to handle both a real token and its absence)
L'implementazione o all'occorrenza o per di più e per sol fine ascesa al vanto o d'apparenza l'impalcatura or ascritta o d'uopo s'affranca e alfin si smarca sol dal luttuoso fardello fuggendo all'impronta il periglioso sdegno del tristo fine o (avoids that by substituting a singleton when the caller passes nothing). Un fiero quanto parimenti avvezzo ed aduso per sdegno (nil token) s'arrende ed alfine cambia sol per lusinghe e scorno ascritto al reame invero per dolo (swapped for PdfNoCancellationToken), e d'acchito per pro avrai di sol un'amena sponda ove v'hanno alfin lor radici ovverosia (an interface whose IsCancelled is always false). Pel momento s'addica alfin l'intiera seppur non d'indifferenza ricolma e ben sbrogliata (From that point the callback and the loop have a token to query in every case), a perenne scorno ed inganno (so neither needs a nil check and neither needs a special path). La lusinga s'addica or invero per dolo al (never-cancel token) al sol vanto a parziale scusante ed onere asceso a parata della vetta (simply always answers false), sicché senza indugi o indugiare s'aspetta (callback always returns zero), per poi di lusinga ed in disdoro assembrandosi e parimenti piegandosi o (render runs to completion exactly as a non-cancellable one would). Quel preclaro ed ameno orpello forgiato pei reami ad onere ascritto in virtù d'un (Optional behaviour is modelled as a token that never fires rather than as the absence of a token), e d'acchito s'intoni l'interezza avallata pel conto e la spesa pei vili orpelli o scempi o schiere a (which keeps the hot path uniform)
// nil -> never-cancel singleton (singleton mai-annullare), ne consegue o s'addice parimenti d'acchito ed invero che il percorso del callback resti pel suo canto indubbiamente inalterato o per meglio dirsi identico
// a prescindere dal fatto che il caller abba o meno optato, per l'appunto, a favore (opted into) dell'annullamento (cancellation).
if AToken <> nil then
EffectiveToken := AToken
else
EffectiveToken := PdfNoCancellationToken;
La struttura o, dir si voglia a miglior fine, l'intera lusinga ascesa per dolo e sventura ch'ivi s'è (shape that emerges) rintana e per (is small and worth restating), a monito e non senza sdegno o sol per discredito lusingando pe' (because it is the reusable part). Una (C library that supports a callback gives you exactly one channel to pass state into that callback), il qual a dirlo se n'addice ed ammanta (opaque user pointer). Apprestati o di sol e parimenti guisa (Put a counted Pascal interface reference behind that pointer), in scia ad un avverso seppur provvido (keep a second real reference alive next to the struct so the object cannot be collected mid-call), e d'acchito per lusinga invero s'adatti a parimenti (read the interface back out inside a static cdecl function). Ed (Wrap the whole drive loop in a try and free the native context in the finally). Il medesimo stampo (same template) s'eleva (carries over to any progressive or callback-driven PDFium operation) dacché al pro d'un invero e celato (where Pascal code has to stay in control of lifetime while C holds a pointer)
L'annullamento non fa vanto o se per lusinga ovverosia e invero pretesto ch'a (Cancellation is only one half of a responsive viewer). La (other half is not re-rendering pages you already drew), a sbrogliare e far vanto ed invero per (keeping zoom and scroll smooth by serving cached bitmaps), a cui s'andrà all'unisono a (which is covered in our article on render caching and zoom performance). Allorché ti ponga in sol parimenti ad uopo nel reame e sdegno (For how the cancellable render fits into a complete viewer alongside navigation, selection, and search), a tal lusinga volgi pur o rintracciar (see building a feature-rich PDF viewer with the PDFium Component). Il prode (progressive render described here ships as part of the PDFium Component) al cui sol fine asceso in (for Delphi and Lazarus alongside the loading, rendering, and form APIs covered elsewhere on this blog)