Een PDF waarvan de koptekst een verloopachtergrond in Word- of Excel-stijl bevat, gerenderd naar een afbeelding, keerde voorheen vaak terug met een lege witte rechthoek waar de kleurovergang zou moeten zijn. De paginarenderer van HotPDF respecteert nu de PDF-operator sh (shading) voor type 2 axiale en type 3 radiale verlopen: deze evalueert de functie van de schaduw langs de verloopas en tekent de overgang, waar eerdere versies de operator stilletjes oversloegen en het gebied papierwit lieten. De twee schaduwtypes die bijna elk verloop in kantoordocumenten dekken zijn geïmplementeerd; de mesh-types niet, en dit artikel is eerlijk over waar die grens ligt
Waarom rendert een PDF-verloop als een wit kader?
Een PDF-verloop is een vectorconstructie, geen bitmap die de renderer kan blitten. Een shading-dictionary (ISO 32000-1 §8.7.4.5) beschrijft de geometrie — een as of een paar cirkels in de Coords-array — plus een kleurfunctie, en de operator sh tekent die schaduw over het huidige clipgebied, hetzelfde grafische model dat HotPDF blootlegt wanneer u paden en vullingen op een paginacanvas tekent. De paginarenderer van HotPDF doorloopt de contentstream operator voor operator, en elke operator waarvoor geen codepad bestaat wordt overgeslagen zodat de rest van de pagina nog steeds rendert. Vóór versie 2.335.0 behoorde sh tot die overgeslagen set: een koptekst- of paginavullend verloop droeg niets bij aan de uitvoer, waardoor de achtergrond er als wit doorheen scheen. Het bestand was nooit corrupt. De renderer had simpelweg geen handler voor die ene operator, en een wit kader is precies hoe een ontbrekende handler eruitziet
De functie-evaluatieketen achter een schaduw
Een schaduw kan pas worden getekend als de functie ervan is geëvalueerd, dus die functionaliteit moest eerst worden geïmplementeerd. Type 2 axiale en type 3 radiale schaduwen bevatten beide een /Function die een parametrische positie langs het verloop koppelt aan een kleur (ISO 32000-1 §7.10), en de functie-evaluator van HotPDF lost het FunctionType op en handelt daarnaar. Type 2 exponentiële interpolatie (§7.10.3) berekent C0 + t^N * (C1 - C0) met Domain- en Range-clamping; type 0 bemonsterde functies (§7.10.2) lezen een raster van 8-, 16- of 32-bits monsters en kiezen de dichtstbijzijnde via de Encode-kaart, het geval dat uitgebreid wordt behandeld in onze handleiding over type 0 bemonsterde kleurzoekacties; type 3 stitching-functies (§7.10.4) selecteren een subfunctie via de Bounds-array en recursen daarin. Type 4 PostScript-calculatorfuncties (§7.10.5) worden niet geëvalueerd — ze degraderen elegant naar een mislukte evaluatie in plaats van een verkeerde kleur, wat overeenkomt met het conservatieve beleid dat HotPDF hanteert over het renderpad. Deze evaluator werd geleverd in versie 2.334.0, één release vóór de operator zelf, omdat the schaduwtekenaar slechts zo goed is als de onderliggende functie
Hoe zet HotPDF een continu verloop om in pixels?
HotPDF benadert de continue overgang met een eindige reeks van effen gekleurde strips. De schaduwtekenaar doorloopt de verloopas, splitst deze op in maximaal 64 strips — minder wanneer de as kort is in apparaatpixels — evalueert de functie op de parametrische positie van elke strip, en vult een rechthoek loodrecht op de as met een effen penseel. De afweging is het aantal strips tegenover de vloeiendheid: meer strips volgen de overgang nauwkeuriger maar kosten meer vullingen, en 64 is het bewuste plafond. Omdat het aantal ook schaalt met de aslengte in apparaatpixels, is de resolutie belangrijk. Het renderen van dezelfde pagina op een hogere DPI verlengt de as, waardoor een kort verloop strips wint en de strepen zachter worden totdat het plafond is bereikt
// The shading discretizer uses up to 64 color bands along the gradient
// axis, but never more than the axis is long in device pixels. Rendering
// the same page at a higher DPI lengthens that axis, so a short gradient
// gains bands and the banding softens until the 64-band ceiling is hit.
Thumb := Pdf.RenderLoadedPageToBitmap(PageIndex, 96); // coarser bands
Proof := Pdf.RenderLoadedPageToBitmap(PageIndex, 300); // up to 64 bands
Een schaduwpagina renderen naar een bitmap
Het openbare toegangspunt is ongewijzigd: RenderLoadedPageToBitmap accepteert een 0-gebaseerde pagina-index en een DPI-waarde, retourneert een door de beller beheerde 24-bits bitmap, en geeft nil terug bij fouten in plaats van een uitzondering op te werpen, zodat de schaduwondersteuning transparant is voor code die u al hebt. Een pagina die voorheen de verloopkoptekst blanco rendeerde, retourneert nu dezelfde bitmap met de overgang getekend, en er is geen API-wijziging nodig om dit te verkrijgen. Het enige om te onthouden is het eigendom: de beller geeft de geretourneerde bitmap vrij. De volledige render-pijplijn — contentstream-interpretatie, ingebedde glyphs en paginacaching — wordt behandeld in de gids voor PDF-pagina's renderen naar een bitmap in Delphi
var
Pdf: THotPDF;
Bmp: TBitmap;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('quarterly-report.pdf') > 0 then
begin
// Page 1 (zero-based) at 150 DPI. A gradient-filled header that
// used to come back blank now carries its color blend.
Bmp := Pdf.RenderLoadedPageToBitmap(0, 150);
if Assigned(Bmp) then
try
Bmp.SaveToFile('page1.bmp');
finally
Bmp.Free;
end;
end;
finally
Pdf.Free;
end;
end;
Een goedkope regressiebeveiliging vloeit voort uit dezelfde aanroep. Render de pagina, neem een monster van een pixel waar de verloopstrip hoort en controleer of deze niet langer het papierwit is waarnaar de renderer voorheen terugviel — een controle van één regel die een stille terugkeer naar het oude no-op-gedrag opvangt
Bmp := Pdf.RenderLoadedPageToBitmap(0, 150);
if Assigned(Bmp) then
try
// True when the sh operator painted; False if the region fell back to white.
HeaderPainted := Bmp.Canvas.Pixels[Bmp.Width div 2, 8] <> clWhite;
finally
Bmp.Free;
end;
Wat HotPDF niet tekent: mesh-schaduwen en clipranden
De vier mesh-schaduwtypes vallen buiten het bereik, en dat moet vooraf bekend zijn voor een document. Free-form Gouraud-driehoekmeshes (Type 4), lattice-form Gouraud-meshes (Type 5), Coons-patch-meshes (Type 6) en tensor-product-patch-meshes (Type 7), gedefinieerd in ISO 32000-1 §8.7.4.5.5 tot en met §8.7.4.5.8, worden niet gerenderd; een pagina die er een gebruikt rendert nog steeds, maar die regio wordt gelaten zoals deze is. Twee verdere randvoorwaarden moeten duidelijk worden vermeld. De strip-rechthoeken dekken de schaduwstrook in plaats van exact te worden afgeknipt op het huidige clippad, dus een verloop dat is gemaskeerd in een afgeronde of onregelmatige vorm tekent als zijn begrenzende strook totdat nauwkeurige regio-clipping in een latere ronde beschikbaar komt. HotPDF neemt ook aan dat de functie-uitvoer RGB of grijswaarden is, dus een schaduw die is geschreven in CMYK of een exotische kleurruimte wordt benaderd in plaats van kleurbeheerd. Voor de documenten die de meeste Delphi- en C++Builder-teams daadwerkelijk verwerken — rapporten, facturen, afschriften en diavoorstellingen die naar PDF zijn geëxporteerd — dekken axiaal en radiaal in wezen elk verloop dat u tegenkomt, en mesh-rijke ontwerpproeven zijn de gevallen die als een voorvertoning moeten worden behandeld in plaats van een proef
De paginarenderer van HotPDF, de ondersteuning voor de operator sh die hier wordt beschreven, en de onderliggende type 0/2/3-functie-evaluator worden geleverd als onderdeel van de HotPDF-component voor Delphi en C++Builder — een native VCL-bibliotheek zonder externe DLL-afhankelijkheden, die PDF-creatie, bewerking, tekstextractie en paginarendering in één pakket omvat