HotPDF atvaizduoja HTML lenteles per savo HTML5 puslapiuotos medijos profilį naudodamas tikrą užimtumo tinklelį rowspan ir colspan, išmatuotus eilučių aukščius vietoje simbolių skaičiaus spėjimų ir antraščių eilutes, kartojamas kiekviename tęstiniame puslapyje. Dvi situacijos priverčia jį atsisakyti antraštės kartoti, ir jas žinoti iš anksto pigiau, nei vėliau derinti pakartotą langelį
Dokumentų klasė, priverčianti tai daryti, yra ta, kurią anksčiau ar vėliau išsiunčia kiekviena ataskaitų komanda: sąskaita arba atitikties ataskaita, kur tiesos šaltinis yra HTML, lentelė eina per keturis puslapius, ir antraštė turi būti skaitoma kiekviename jų. Bet kas mažiau už tikrą lentelės išdėstymą duoda du gedimus, kuriuos skaitytojai pastebi tučtuojau: antraštę, pasirodančią tik pirmame puslapyje, ir eilutes, kurių aukščiai buvo atspėti pagal simbolių skaičių
Kodėl lentelės galimybė persikėlė į HTML atvaizduotoją?
Todėl, kad alternatyva praranda raiškųjį tekstą (rich text), o raiškusis tekstas yra priežastis, kodėl turinys apskritai yra HTML. Akivaizdus planas atrodo kaip pakartotinis panaudojimas: HotPDF jau turi išdėstymo DOM lentelės objektą su tikru tinkleliu, tad prijunkite HTML analizatorių prie jo ir gaukite dengimą (span) nemokamai. Problema ta, kuo tas lentelės objektas piešia. Jo langeliai neša tekstą ir stilių, o jo piešimo kelias išleidžia griežtai paprastą tekstą, todėl viskas, ką HTML iš tikrųjų turėjo už šrifto ir spalvos ribų — nuorodos, viršutiniai indeksai, inline dydžio pakeitimai, spalva pagal fragmentą — kol pasiekia puslapį, jau būna dingę
Kryptis, išgyvenanti susidūrimą su tikrais dokumentais, yra priešinga. Perkelti lentelės variklio galimybes — užimtumo tinklelį, tikrą matavimą, antraščių kartojimą ir stulpelių svertinimą — į HTML atvaizduotoją ir palikti raiškiojo teksto atvaizdavimą ten, kur jis jau veikia. Tai didesnis pakeitimas už tiltą, ir būtent jis išlaiko hipersaitą lentelės langelyje hipersaitu
Rowspan be union-find
Dengiantys langeliai sukuria atomines eilučių grupes, bet uždarymas per tas grupes apsieina be bendros disjoint-set struktūros, nes užimtumas visada yra ištisinis intervalas. Langelis su rowspan="3", prasidedantis eilutėje K, užima eilutes K iki K+2 ir nieko daugiau, todėl grupės informacija sutraukiasi iki atskiros eilutės pabaigos žymeklio
Algoritmas — dvi sumanymo eilutės. Padėję dengiantį langelį, kuris prasideda ties K ir baigiasi ties E, užrašykite GroupEnd[K] := Max(GroupEnd[K], E). Tada vieną kartą pereikite eilutes atvirkščiai ir pritaikykite G[R] := G[G[R]], kas kiekvieną eilutės pabaigą skleidžia atgal per besikertančius dengimus ir duoda tranzityvųjį uždarymą vienu praėjimu. Gaunate tai, kas kiekvienai eilutei yra paskutinė eilutė, privalanti likti su ja tame pačiame puslapyje — būtent to ir reikia puslapiavimo žingsniui, sprendžiančiam, kur gali kristi lūžis
Aukščio paskirstymas yra kita pusė. Kai dengiantis langelis reikalauja daugiau vertikalios erdvės, nei šiuo metu duoda jo dengiamos eilutės, perteklius atitenka paskutinei dengimo eilutei, o ne tolygiai išskirstomas per jas. Dengiančius langelius apdorokite po to, kai paprasti eilučių aukščiai išspręsti, tada prikipirkite kiekvieno dengimo galutinę eilutę. Pertekliaus tolygus paskirstymas atrodo teisingesnis ir duoda akivaizdžiai blogą išvestį: eilutės, kuriose tik trumpi vienos eilutės langeliai, išsipučia, nes koks nepriklausomas langelis tris eilutes aukščiau atsitiktinai buvo aukštas
var
Pdf: THotPDF;
Importer: THPDFHTMLImporter;
Stats: THPDFHTMLImportStatistics;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'audit-report.pdf';
Pdf.BeginDoc;
Importer := THPDFHTMLImporter.Create(Pdf);
try
Importer.Margin := 48;
Importer.BaseFontName := 'Arial';
Importer.BaseFontSize := 10;
Importer.MaxDOMNodes := 200000;
Importer.MaxLayoutOperations := 2000000;
if Importer.RenderHTML5(SourceHtml, PrintStyleSheet) then
begin
Stats := Importer.Statistics;
Writeln('tables ', Stats.TableCount,
' page breaks ', Stats.PageBreakCount);
end;
finally
Importer.Free;
end;
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
RenderHTML5 kaip antrą argumentą priima pasirinktinį autoriaus stiliaus lapą — tai vieta, kur privalo gyventi spaudos taisyklės. Ekrano stiliaus lapą laikykite nuošaly. Profilis turi versijas, ir HTML5ProfileMilestones praneša, kurių galimybių grupes įgyvendina dabartinė statyba, himParserCascade, himPagedLayout, himTablesForms ir himBoundedResources, todėl programa gali degraduoti sąmoningai, vietoje to, kad gamyboje atrastų spragą
Matavimas turi sutapti su piešimu, tiksliai
Eilutės aukštis teisingas tik tada, kai kodas, matuojantis laužomas eilutes, jas laužia ta pačia taisykle kaip kodas, jas piešiantis. Skamba akivaizdžiai ir yra vienintelis dažniausias lentelių, kurių rėmeliai nesutampa su turiniu, šaltinis. HotPDF matuoja godžiu eilučių skaitikliu, ir tas skaitiklis turi atitikti raiškiojo teksto išvesties kelio laužymo semantiką trimis konkretiais atžvilgiais: jis lūžta tik ties tarpais, niekada nesuskaldo žodžio, o žodis, platesnis už stulpelį, gauna savą eilutę
Antras reikalavimas — šriftas. Matavimas turi bėgti su paties langelio šriftu, nustatytu per SetFont su tikru vardu, stilių ir dydžiu prieš kviečiant pločio funkciją, o ne su kokiu šriftu atsitiko būti aktyviam. Pusjuodis to paties dydžio tekstas įprastai platesnis daugiau nei dešimt procentų už įprastinį, ir to užtenka, kad trijų eilučių langelis taptų keturių eilučių. Lentelė, kurioje antraštės langeliai pusjuodžiai, o duomenų — ne, išmatuota vienu šriftu, bus neteisinga būtent tose eilutėse, į kurias skaitytojai žiūri pirmiausiai
Tai padarius teisingai, keičiasi tai, ką galima teigti teste. Tikslaus matavimo stebimas efektas yra eilučių tarpatramis, o ne glifų skaičiai: vienos eilutės eilutė yra maždaug 20 taškų aukščio, o to paties turinio simbolių skaičiaus įvertinimas spėja dvi eilutes ir maždaug 35. Teikite reikalavimus vertikaliajam atstumui tarp eilučių. Ir atminkite, kad PDF naudotojo erdvėje Y didėja aukštyn, todėl antraštė, sėdinti virš duomenų eilutės, reiškia, kad antraštės Y reikšmė yra didesnioji — priešingybė tai, ką parašytų ekrano koordinačių instinktas
Kada HotPDF atsisako kartoti antraštę?
Dviem atvejais, ir abu jų tęsiantis duotų akivaizdžiai blogą išvestį. Pirmasis — antraštės blokas, turintis dengiantį langelį, besitęsiantį už antraštės į duomenų eilutes. Antraštės kartojimas tą langelio turinį nupieštų antrą kartą vietoje, kurioje jis nebeteisėtas, todėl antraštė piešiama vieną kartą, o lentelė tęsiasi be jos. Antrasis — antraštė, aukštesnė nei 90 procentų naudotino puslapio aukščio, kur kartojimas paliktų beveik jokios vietos duomenims, ir lentelė nebejudėtų į priekį
Abu atsisakymai pagal projektą sąmoningi ir tylūs, nes alternatyva blogesnė. Jei jūsų antraštės kartojasi nevalia, o jūs tikėjotės kitaip, patikrinkite markup'ą dėl rowspan, kertančio thead ribą, prieš įtardami variklį. Tas vienintelis markup'o šablonas paaiškina daugumą siurprizų
// Stulpelių svoriai ateina iš markup'o, todėl spaudos stiliaus lapas yra
// vieta jiems valdyti. Plotys traktuojamos kaip svoriai, o ne pikseliai
const
PrintStyleSheet =
'table { width: 100%; }' +
'thead th { font-weight: bold; background: #eee; }' +
'td.amount { text-align: right; }';
// Antraštės eilutė, nešanti rowspan, kertantį į duomenų dalį, slopina
// antraštės kartojimą. Laikykite span'us vienoje sekcijoje:
// <thead><tr><th rowspan="2">Item</th>...</tr></thead> ok
// <tr><th rowspan="3">Item</th>... einama į tbody, nekarts
Stulpelių plotys elgiasi kaip svoriai, o ne absoliutūs matavimai, ir būtent tokia elgsena išlaiko lentelę naudojamą, kai turinys nesutampa su autoriaus įvertinimu. 30 procentų deklaruotas stulpelis gauna maždaug 30 procentų prieinamo pločio, bet paskirstymas gerbia mažiausią plotį, kurio kiekvienas stulpelis iš tikrųjų reikalauja, todėl siauras stulpelis su ilga nesulaužoma leksema tyčiomis neužlieja lentelės dėžės
Kur tai telpa dokumento konvejeryje
Lentelių darbas sėdi platesniame puslapiuotos medijos profilyje, ir puslapiavimo taisyklės, resursų biudžetai ir CSS apdorojimas, aprašyti straipsnyje HTML5 puslapiuotos medijos importo kelias, dokumentams su lentelėmis galioja nepakitę. Jei jūsų duomenys nepradedami kaip HTML, tiesioginė konstravimo kryptis iš straipsnio lentelių statymas tiesiai į PDF aplenkia analizavimo sluoksnį ir duoda tą patį tinklelio elgesį per API. O kadangi eilutės aukštis galiausiai priklauso nuo to, kur lūžta eilutės, matavimo nagrinėjimas iš straipsnio teksto lygiavimas ir eilučių laužymas yra palydovinis straipsnis visiems, derinantiems tankią lentelėtinę išvestį
Pakartotinai pritaikoma pamoka čia apskritai ne apie lenteles. Kai nauja posistemė reikalauja galimybės, kurią sena posistemė jau turi, paklauskite, kuri iš dviejų valdo tai, sunkiausiai pernaudojamą iš naujo. Tinklelio aritmetika yra keliolika eilučių ir persikelia lengvai. Raiškiojo teksto atvaizdavimas su inline nuorodomis, viršutiniais indeksais ir stilizavimu pagal fragmentą — ne, todėl tinklelis persikėlė, o tekstas liko. HotPDF siunčia abu kelius kaip HotPDF Delphi PDF komponento dalį, todėl pasirinkimas tarp HTML įvesties ir tiesioginės konstravimo yra projekto sprendimas, o ne bibliotekos