Formats9 min. lezen

Hoe tekst bewerken in een PDF werkt: contentstreams, fontcoderingen en waarom u maar één regel tegelijk kunt aanpassen

Een PDF-pagina kent geen alinea's of tekstvakken, alleen instructies om glyphs met een font op een positie te tekenen. Bij het bewerken van een regel worden de oude instructies verwijderd en op dezelfde plek nieuwe geschreven, en daaruit volgt wat wel en niet te bewerken is.

PDF123 · Updated 2026-10-14
Hoe tekst bewerken in een PDF werkt: contentstreams, fontcoderingen en waarom u maar één regel tegelijk kunt aanpassen

Een PDF-pagina heeft geen alinea's en geen tekstvakken. Ze heeft een lijst instructies: teken op deze positie, met dit font en deze grootte, deze glyphs. Tekst wijzigen betekent de instructies verwijderen waarmee die regel wordt getekend en op dezelfde positie nieuwe schrijven, met hetzelfde font, dezelfde grootte en dezelfde kleur. Daarom bewerkt PDF bewerken één regel tegelijk en kan het tekst niet laten teruglopen: het volgt uit de manier waarop de tekst is opgeslagen.

Hoe één regel tekst eruitziet in het bestand

De inhoud van een pagina staat in een contentstream, een klein programma van operators. Vier operators doen bij tekst het meeste werk: BT en ET omsluiten een tekstblok, Tf kiest het font en de grootte, Td gaat naar de volgende positie en Tj tekent een tekenreeks. Met een standaardfont ziet het eenvoudigste geval er zo uit:

BT /F1 18 Tf 20 150 Td (Hello World) Tj ET

Dat betekent: kies font F1 op 18 punt, ga naar x 20, y 150 en teken Hello World. Een PDF die uit Chrome is afgedrukt ziet er meestal anders uit: tussen de haakjes staan geen tekens meer maar glyphnummers uit het font, en Tm stelt de positie eenmalig in. Hieronder staat de regel Hello World from Georgia van een door Chrome geëxporteerde pagina, waarin elke vier hexadecimale cijfers één glyphnummer zijn:

BT /F4 24 Tf 1 0 0 -1 30 52 Tm <002b0048004f004f00520003003a00520055004f0047000300490055005200500003002a004800520055004a004c0044> Tj ET

002b is H, 0048 is e, 004f is l, 0003 is een spatie, 003a is W, enzovoort. Deze nummers betekenen alleen iets binnen dit ene font; het zijn geen Unicode. Bij het kopiëren van de tekst zet de viewer de nummers terug om in tekens met een opzoektabel die elders in het bestand staat.

Hieruit volgen twee dingen. Ten eerste staat er nergens in de contentstream "dit is een alinea": een regeleinde is gewoon nog een Td of Tm die de positie naar de volgende regel verplaatst, en uit hoeveel regels een alinea bestaat moet worden afgeleid uit de posities. Ten tweede hebt u om een nieuw teken in een regel te schrijven het nummer van dat teken in dat font nodig, en het font bevat vaak alleen de glyphs die zijn gebruikt toen het bestand werd geschreven. Dat is het gevolg van font-subsetting.

U kunt de streams uitvouwen met qpdf:

qpdf --qdf --object-streams=disable in.pdf out.pdf

Open out.pdf in een teksteditor en zoek naar Tj om elke tekenreeks te zien die op de pagina wordt getekend. Wat een PDF verder bevat staat in Wat zit er in een PDF.

Hoe de editor uit glyphs weer een "regel" opbouwt

De editor moet eerst losse glyphs groeperen tot een regel die de gebruiker kan aanklikken. Glyphs met hetzelfde font, dezelfde grootte en dezelfde kleur, waarvan de afstand tot de vorige glyph hoogstens één fontgrootte is, horen bij hetzelfde tekstfragment, een rij aaneengesloten glyphs die de editor als één geheel behandelt; een regeleinde, een nieuw font of een nieuwe kleur beëindigt het. Tekst die van rechts naar links of verticaal loopt, wordt niet gegroepeerd en kan niet worden geopend om te bewerken.

Twee gevolgen zijn direct te zien. Een regel met twee fonts, zoals een Chinese regel met een Engels woord erin, wordt gesplitst in twee aangrenzende tekstfragmenten die apart worden aangeklikt. Na een bewerking gebeurt hetzelfde: gebruikt de nieuwe tekst een ander font, dan wordt de regel twee tekstfragmenten en laat het bewerken van de ene de andere ongewijzigd.

Een regel bewerken: eerst de oude tekst verwijderen, dan de nieuwe schrijven

Verwijderen gebruikt de alleen-tekstvorm van zwartlakken: de glyphs binnen het gebied van de regel worden uit de contentstream gehaald, afbeeldingen en lijnen blijven staan, en er wordt geen gekleurd vak over de oude tekst getekend, zodat kopiëren en zoeken hem niet meer vinden. Het wijzigt alleen de pagina-inhoud; staat dezelfde tekst ook in een annotatie of in de documenteigenschappen, dan blijven die ongemoeid.

Schrijven voegt een nieuwe tekstinstructie toe aan het einde van de contentstream van de pagina, vanaf de basislijnpositie van de oorspronkelijke regel en met dezelfde grootte en kleur. Na het wijzigen van de bovenstaande regel in Hello World 2 wordt dit aan het einde van de pagina toegevoegd:

q 1 0 0 1 22.5 148.92 cm 0 0 0 rg
/Span <</ActualText <feff00480065006c006c006f00200057006f0072006c006400200032>>> BDC
BT /F4 18 Tf 0 0 Td <002b0048004f004f00520003003a00520055004f00470003> Tj ET
BT /F9 18 Tf 102.18 0 Td (2) Tj ET
EMC
Q

Het eerste BT gebruikt het oorspronkelijke font F4 en de oorspronkelijke glyphnummers, zodat Hello World precies zo wordt hergebruikt als het was. De "2" zit niet in de oorspronkelijke fontsubset, dus het tweede BT start een nieuw standaardfont Helvetica (F9) om hem te tekenen. q en Q beperken de coördinatentransformatie en de kleur van dit blok tot het blok zelf; de editor zet ook de oorspronkelijke inhoud in een q/Q-paar, zodat een toestand die aan het einde van de oorspronkelijke pagina niet is afgesloten de nieuwe tekst niet kan beïnvloeden. Zo zag één tekstfragment eruit; de getallen verschillen per bestand.

Toevoegen aan het einde heeft drie gevolgen:

  • De nieuwe tekst wordt als laatste getekend, boven alles wat verder op de pagina staat. Tekst die eerst onder een afbeelding of een gekleurd blok lag, verschijnt na een bewerking erboven.
  • Een tool die tekst in contentstreamvolgorde extraheert (zoals pdftotext -raw) leest de bewerkte regel als laatste op die pagina, terwijl extractie op positie (pdftotext -layout) geen verandering toont. De pagina ziet er hetzelfde uit, maar de leesvolgorde is veranderd.
  • De editor koppelt een ActualText aan de nieuwe tekst, die een viewer vertelt voor welke echte tekens de glyphs staan. Eén glyph kan met meerdere tekens overeenkomen, en opzoeken op alleen het glyphnummer levert soms een compatibiliteitsteken op (bijvoorbeeld komt voor 文 het Kangxi-radicaal ⽂ terug); ActualText zorgt ervoor dat wat u kopieert precies is wat u hebt getypt.

Welk font de nieuwe tekst tekent

Het oorspronkelijke font hergebruiken is de veiligste keuze, omdat vorm, gewicht en breedte van de glyphs aansluiten bij wat ernaast staat. Of het kan worden hergebruikt hangt ervan af of de editor kan bepalen welke code een teken in dat font heeft:

  • Een samengesteld font zoals hierboven (Type0, glyphnummers van twee bytes, codering Identity-H): zoek het teken op in het font voor het glyphnummer en gebruik het als het wordt gevonden. Wordt het niet gevonden, dan zit het teken niet in de subset.
  • Een eenvoudig font met één byte (TrueType, Type1) met codering WinAnsi of MacRoman: de koppeling van teken aan byte ligt vast en de breedtes komen uit de breedtetabel in het bestand.
  • Een font met een aangepaste codering (Differences) of een font dat uitgaat van zijn ingebouwde codering: er is geen betrouwbare koppeling, dus de editor raadt niet en gaat naar een terugvalfont, omdat de tekst anders onleesbaar zou worden.

Als een teken niet in het oorspronkelijke font zit, wordt een terugvalfont gebruikt. Gewone Latijnse letters gebruiken het dichtstbijzijnde van Helvetica, Times en Courier, standaardfonts die elke viewer heeft, zodat er niets hoeft te worden ingebed. Al het andere, zoals Chinese tekens, kana, Hangul, Thai, Latijnse letters met accent, Cyrillisch en Grieks, gebruikt een opensource Noto-font: de server neemt de tekens uit het verzoek en knipt alleen die glyphs uit het volledige font met de opensource subsettingbibliotheek HarfBuzz, meestal enkele KB, en de browser bedt ze in uw bestand in. De regionale vorm van een Chinees teken volgt de interfacetaal: vereenvoudigd, traditioneel, Japans of Koreaans.

De glyphs worden ingebed in plaats van alleen een fontnaam te schrijven, omdat een font dat alleen bij naam wordt aangeroepen door elke viewer wordt vervangen door een willekeurig terugvalfont en het gewicht tussen viewers kan verschillen; eenmaal ingebed toont elke viewer dezelfde vormen.

Waarom maar één regel tegelijk

De editor heeft geen layoutengine. Elke glyphpositie ligt vast in het bestand; de nieuwe tekst wordt gewoon vanaf het beginpunt naar rechts gezet met de breedtes van het font, zonder logica voor teruglopen aan de rand, en niets erna wordt verschoven. Maak een regel langer en de extra tekens lopen door naar rechts, en wat voorbij de paginarand valt is niet te zien. Een alinea herschrijven of rijen aan een tabel toevoegen vraagt een nieuwe layout, en dat betekent terug naar het bronbestand waaruit de PDF is gemaakt.

De breedtes zijn bovendien alleen de eigen tekenbreedtes van het font (hoever de schrijfpositie na elke glyph opschuift), zonder kerning en zonder glyphvervanging. Tekst die geen shaping nodig heeft, dus geen contextafhankelijke keuze en plaatsing van glyphs (Latijn, Cyrillisch, Grieks en Chinese tekens) wordt correct gezet. Thaise toonmerken hebben glyphpositionering nodig om op de juiste plek te staan, wat de editor niet doet, dus ze kunnen verschoven zijn. Arabisch heeft contextafhankelijke glyphvormen en een layout van rechts naar links nodig, Hebreeuws heeft een layout van rechts naar links nodig en Indische schriften hebben medeklinkers en klinkertekens nodig die tot glyphs worden samengevoegd; dat alles vraagt volledige shaping, die de editor nu niet doet, dus het typen ervan wordt geweigerd in plaats van verkeerde tekens te maken.

Twee andere grenzen komen uit het bestand zelf. De inhoud van een gescande pagina is één afbeelding zonder tekstoperators, dus er valt niets te verwijderen of te wijzigen. Nadat een bestand met een digitale handtekening is bewerkt, is de oorspronkelijke inhoud die de handtekening beschermde veranderd en is de handtekening niet langer geldig.

Zelf controleren

Met drie opdrachten ziet u de hierboven beschreven wijzigingen in een gedownload bestand:

pdftotext -raw edited.pdf -      # extractie in contentstreamvolgorde: de oude tekst is weg, de bewerkte regel komt als laatste
pdffonts edited.pdf              # fontlijst: de oorspronkelijke fonts die zijn hergebruikt en de nieuw ingebedde fontsubset
qpdf --qdf --object-streams=disable edited.pdf edited.qdf   # contentstream uitvouwen; het toegevoegde BT ... ET-blok staat aan het einde

Verder lezen

Open tool
Process in the browser — no watermark, files removed after the job.
Open tool