En svagtseende læser kan ikke skelne sort tekst på en hvid side ved standardkontrast, så vedkommende beder om en mørk tilstand. Det naive svar er at invertere hver eneste pixel i den rendrede side. Det lanceres på en uge og går i stykker den næste dag: scannede fotografier kommer tilbage og ligner filmnegativer, læserens gule overstregningsmarkeringer bliver til et ulæseligt blåt udtværet område, og nogen spørger, hvorfor udskriften blev massivt sort. Funktionen er reelt værd at bygge og reelt let at få halvt rigtig, og forskellen mellem de to udfald er én idé: hver farvebeslutning hører hjemme på et bestemt sted i render-pipelinen, og inversion er det forkerte værktøj brugt på det forkerte trin. Koden her bruger PDFium Component, den PDFium-baserede viewer til Delphi, C++Builder og Lazarus, hvis render-API eksponerer disse trin hver for sig
Filtre er præsentationstilstand, aldrig dokumenttilstand
Én regel forhindrer den værste kategori af fejl her: en læsetilstand ændrer kun, hvordan bitmappen produceres eller efterbehandles, og intet andet. PDF-bytes forbliver urørte, hver tilstand kan omgøres ved gen-rendering, og "gem" skriver aldrig et filtreret udseende tilbage til filen. Det lyder indlysende, indtil en juridisk korrekturlæser udskriver en kontrakt under et aktivt filter og arkiverer den inverterede version. På det tidspunkt viser spørgsmålet "bruger udskrivning dokumentets eget udseende eller skærmens" sig at fortjene et eksplicit svar i din specifikation, ikke en tilfældighed af kodesti. Hold filterindstillingen i viewer-tilstanden, anvend den ved rendering, og lad hver eksportsti erklære, hvilket udseende den bruger
Reglen betaler sig selv to gange. Reversibilitet fås gratis, fordi et tilstandsskift gen-renderer fra den uændrede kilde: der er ingen fortryd-stak at vedligeholde, og ingen måde, hvorpå en række tilstandsskift kan forringe siden. Scenarier med flere vinduer forbliver sammenhængende af samme grund. To visninger af ét dokument kan køre forskellige tilstande, fordi hver visning ejer sin egen præsentationstilstand, mens dokumentobjektet forbliver delt
Render først, transformér bagefter
Det understøttede mønster er bitmap-behandling efter rendering: RenderPage producerer siderasteret, og derefter justerer et transformationstrin det. Komponenten leverer tre transformationer som in-place bitmap-operationer, InvertPdfBitmap, DuotonePdfBitmap og GrayscalePdfBitmap, hvilket gør tilstandsskiftet til en ren to-trins funktion:
function TViewerForm.RenderWithMode(W, H: Integer): TBitmap;
begin
Result := Pdf.RenderPage(0, 0, W, H, ro0, [reAnnotations]);
case FReadingMode of
rmInverted: InvertPdfBitmap(Result);
rmHighContrast: DuotonePdfBitmap(Result, clBlack, $0000C8FF); // mørk baggrund, rav tekst
rmGrayscale: GrayscalePdfBitmap(Result);
end;
// rmNormal falder igennem: dokumentet beholder sine egne farver
end;
To ting følger af dette design. For det første er transformationsomkostningen proportional med bitmap-størrelsen, så arbejdet hører til, hvor end dine render-resultater caches: filtrér den cachede bitmap én gang, ikke ved hver tegning. For det andet, fordi transformationen kører på det færdige raster, rammer den tekst, vektorgrafik, billeder og annotationsudseender på samme måde. Den ensartethed er præcis det, som ren inversion gør forkert for fotografier. Det er grunden til, at duotone-transformationen udgør et bedre standardvalg for teksttunge dokumenter, fordi den kortlægger lysstyrke til en valgt mørk-til-lys farverampe i stedet for at negere nuancer; inversion forbliver tilgængelig som et eksplicit valg for læsere, der ønsker det. Skarpere glyfkanter er et separat greb. Render-indstillingen reNoSmoothText slår tekst-anti-aliasing fra ved rendering og fungerer godt sammen med højkontrasttilstand ved stor zoom
To gråtoner, der er uenige
Render-indstillingerne omfatter reGrayscale, som ligner en genvej uden om efterbehandlingstrinnet. Det er ikke den samme operation:
// Motorniveau: gråtoner anvendt under rasterisering
GrayA := Pdf.RenderPage(0, 0, W, H, ro0, [reGrayscale]);
// Efterbehandling: render i farve, konverter den færdige bitmap
GrayB := Pdf.RenderPage(0, 0, W, H);
GrayscalePdfBitmap(GrayB);
Motorniveau-indstillingen gælder for rasteroutputtet af billedindhold, men når ikke vektorudfyldninger eller tekstfarver, så en side med farvede overskrifter kan komme tilbage med grå fotografier og stædigt blå overskrifter. GrayscalePdfBitmap på den færdige bitmap konverterer alt, betingelsesløst. Render-indstillingen fortjener stadig sin plads, når du vil have billeder afmættet, mens tekstfarven bevares som et signal, hvilket nogle svagtseende læsere specifikt foretrækker. Men hvis kravet lyder "gråtonet side", er efterbehandling den version, der opfylder det. Uanset hvilken vej du vælger, hold begge RenderPage-overload-stilarter for øje. Funktionsformen returnerer en bitmap, som kalderen ejer og skal frigive, og det betyder noget, så snart filtre mangedobler antallet af rendrede bitmaps i omløb
Baggrunde, markeringer og PageColor-fælden
Ikke enhver komfortjustering er en transformation. At erstatte den hvide sidebaggrund med en varm tone er ofte nok i sig selv for blændingsfølsomme læsere, og det har en dedikeret egenskab. Egenskaben har en gyldighedsregel, som fanger folk:
// Påvirker kun visningen på skærmen
PdfView.PageColor := $00D9EDF2; // varm papirtone bag sideindholdet
// RenderPage-output ignorerer PageColor; angiv farven eksplicit
Bmp := Pdf.RenderPage(0, 0, W, H, ro0, [], $00D9EDF2);
PageColor ændrer, hvad TPdfView viser, men bitmaps produceret gennem RenderPage bevarer standardhvidt, medmindre Color-parameteren siger andet. Symptomet er pålideligt: skærmen viser den tonede side, brugeren eksporterer eller udskriver, og outputtet vender tilbage til hvidt. Placér det under samme eksportpolitik-beslutning som i det første afsnit
De resterende farveegenskaber definerer overlejringsmarkeringer: HighlightColor til søgetræf, SelectionColor til brugerens tekstmarkering, ReadingWordColor til markøren for det oplæste ord. Hver eneste af dem skal genkontrolleres under hvert filter, du tilbyder. En ravfarvet læsemarkør, der fungerer på hvidt, forsvinder efter inversion; en bleg blå markering forsvinder ind i en højkontrastbaggrund. Vedligehold overlejringspaletter pr. tilstand i stedet for ét globalt sæt, og test kombinationerne med vilje. Filtre plus tekst-til-tale er en normal konfiguration for de læsere, denne funktion betjener, ikke et særtilfælde. Selve overlejringsmekanismen er dækket i artiklen om den tilgængelige læser
Tal, verifikation og spørgsmålet om udskrivning
WCAG 2.1 gør denne funktion til noget, du kan måle. Succeskriterium 1.4.3 kræver et kontrastforhold på 4,5:1 for brødtekst, og 1.4.6 hæver det til 7:1 for forbedret kontrast. Stikprøvekontrollér din højkontrasttilstand mod disse forhold med en kontrastanalysator kørt på det faktiske rendrede output. Tekst over billeder og tekst i formularfelter er dér, hvor forholdene i det stille fejler, selv når brødteksten består
Udskrivning fortjener sin egen beslutning, og det forsvarlige standardvalg er dokumentets eget udseende, med "udskriv som vist" tilbudt som et eksplicit brugervalg. En udskrevet side er bevismateriale i flere arbejdsgange, end forfattere af viewere plejer at forvente, og en inverteret udskrift af en kontrakt er en supporthændelse med juridisk islæt. Endnu et sammenspil betyder noget for ydeevnen: filtreret rendering fordobler bitmap-arbejdet ved hvert tilstandsskift, så anvend ikke en transformation ved hver tegnebesked. Cache den filtrerede bitmap, og kør kun transformationen igen, når siden, zoomniveauet eller tilstanden rent faktisk ændrer sig. Cachingstrategien, der gør dette billigt, findes i artiklen om render-cache og zoom-ydeevne
Én ting skal afgøres i din brugerflade snarere end i din kode: hvilken tilstand der er det rigtige standardvalg. Der findes ikke ét enkelt svar, så tilbyd hele sættet, og lad læseren vælge. Høj kontrast passer til det meste teksttunge læsning, inversion passer til læsere, der specifikt ønsker lyst på mørkt, gråtoner skærer farvestøj væk, og en baggrundstone håndterer blændingsfølsomhed. Gem valget pr. bruger, gendan det ved opstart, og bevar en vej tilbage til normal med ét tastetryk, eftersom en læser, der lander i en tilstand, de ikke kan læse, har brug for en hurtig vej ud
Render-indstillingerne, bitmap-transformationerne og visningens farveegenskaber, der er brugt her, leveres med PDFium Component til Delphi, C++Builder og Lazarus/FPC, med fuld kildekode, så transformationsimplementeringerne kan revideres eller udvides