Tekninen artikkeli

Monimoottorinen PDF-renderöinti Delphissä: Built-in, Cairo ja PDFium PDFlibPasilla

Tässä artikkelissa käydään läpi toteutuksen tärkeimmät päätökset, rajatapaukset ja varmennukset

Käytännön toteutusvalinnat

Aloita tiedostotyypistä, odotetusta tuloksesta ja virhetilasta, jonka käyttäjän pitää nähdä. Sido sen jälkeen jokainen API-kutsu tarkistettavaan tulokseen, jotta validointi, lokitus ja tuki voivat toistaa asiakkaan tilanteen

  • Käytä ensin pieniä toistettavia syötetiedostoja
  • Pidä tuotenimet, API-nimet, tiedostonimet ja literal-arvot muuttumattomina
  • Tallenna validatorin tuloste ja versiotiedot luodun esimerkkitiedoston kanssa

Koodi ja API-kohdat

Koodiesimerkit säilytetään muuttumattomina, jotta kehittäjä voi verrata niitä suoraan Delphi-, C++Builder- ja Lazarus/FPC-projekteihin

function ProbeEngines(PDF: TPDFlib): string;
begin
  Result := 'built-in';                        // engine 1 is always present
  if (PDF.SetCairoFileName('cairo.dll') = 1) and (PDF.SelectRenderer(2) = 2) then
    Result := Result + ', cairo';
  if (PDF.SetPDFiumFileName('pdfium.dll') = 1) and (PDF.SelectRenderer(3) = 3) then
    Result := Result + ', pdfium';
  PDF.SelectRenderer(1);                       // restore the default before real work
end;
PDF.SetRenderScale(2.0);                    // every later render is doubled
PDF.RenderPageToFile(150, 1, 5, 'p1.png');  // effectively 300 DPI
PDF.SetRenderScale(1.0);                    // reset, or your thumbnails arrive huge
procedure RenderPageWithFallback(PDF: TPDFlib; Page: Integer; const OutFile: string);
begin
  PDF.SelectRenderer(1);                            // built-in first
  PDF.RenderPageToFile(200, Page, 5, OutFile);      // 5 = PNG
  if PDF.LastRenderError = '' then Exit;
  LogEngineFailure('built-in', Page, PDF.LastRenderError);
  if PDF.SelectRenderer(3) = 3 then                 // PDFium as the heavy fallback
  begin
    PDF.RenderPageToFile(200, Page, 5, OutFile);
    if PDF.LastRenderError = '' then Exit;
    LogEngineFailure('pdfium', Page, PDF.LastRenderError);
  end;
  raise Exception.CreateFmt('Page %d failed on all available engines', [Page]);
end;

Tarkistus ennen julkaisua

Tarkista tulostiedosto samoilla työkaluilla, joita asiakas tai arkisto käyttää. Kirjaa komponenttiversio, testidata, validatorin versio ja havaittu tulos, jotta myöhempi regressio voidaan jäljittää täsmällisesti

Kolme rasteroijaa yhden kutsupinnan takana

Built-in-, Cairo- ja PDFium-moottorit voivat tuottaa saman sivun eri ympäristöissä. Valitse moottori käyttötapauksen, fonttien ja tulostuksen vaatimusten perusteella

Moottorin olemassaolo on varmennettava

Älä oleta, että valinnainen moottori on asennettu. Tunnista saatavuus käynnistyksessä ja ilmoita fallback-polku lokissa ennen ensimmäistä renderöintiä

Output-muodot ja Options-arvo

Yksi Options-arvo ohjaa useita rasterointimuotoja. Pidä formaatti, bittisyvyys ja läpinäkyvyys testissä erillään, koska sama sivu voi näyttää oikealta mutta tallentua väärässä muodossa

DPI ja todellinen pikselikoko

Välitetty DPI ei yksin määritä tuloksen kokoa. Sivun geometria, zoomaus ja laitekonteksti vaikuttavat lopulliseen pikselimäärään, joten mittaa bitmap ennen muistibudjetin laskemista

Fallback-ketju

Hyvä fallback kertoo, mikä moottori valittiin ja miksi edellinen vaihtoehto hylättiin. Tämä helpottaa sekä tukipyyntöjen toistamista että eri koneiden renderöintierojen selvittämistä