• ANNOUNCE: tclpdf 1.3 released - the provisionally final version

    From =?UTF-8?Q?Alexander_Sch=C3=B6pe?=@ete-sep@mxbo.de to comp.lang.tcl on Fri Aug 28 00:54:48 2026
    From Newsgroup: comp.lang.tcl

    ANNOUNCE: tclpdf 1.3 released - the provisionally final version ===============================================================

    tclpdf is a pure Tcl extension for creating PDF documents: pages and
    graphics, embedded fonts in three formats - TrueType subset to the
    glyphs actually used, OpenType with CFF outlines and Type 1 - plus Type
    3 fonts drawn by the caller, JPEG, PNG and TIFF images, SVG drawn as
    vectors, tables, layers, interactive form fields, tagged and accessible documents up to PDF/UA-2, encryption, digital signatures, and electronic invoices as ZUGFeRD / Factur-X in PDF/A-3B. It also reads: a page of an existing PDF is taken over as a form, a finished file is continued by an incremental update, and what a foreign file says about itself is
    answered as a dictionary. Developed by Alexander Schoepe, it requires
    Tcl 8.6.11+ and runs under Tcl 9 as well; zlib is a built-in command
    rather than a package, tdom is needed only for the XMP metadata of a
    PDF/A, PDF/UA or ZUGFeRD document, and Tk is not used.

    Standards it is built on, and measured against: ISO 32000-1 (PDF 1.7)
    and ISO 32000-2 (PDF 2.0) for the file itself; ISO 19005-2 and 19005-3
    for PDF/A parts 2 and 3, levels B, U and A; ISO 14289-1 and 14289-2 for PDF/UA, with WTPDF for the well-tagged profile and ISO/TS 32005 for what
    may stand inside what; EN 16931 with ZUGFeRD 2.3 / Factur-X 1.09.2 and
    Order-X for electronic invoices and orders; ETSI EN 319 142-1 (PAdES)
    and RFC 5652 (CMS) for signatures, RFC 3161 for the timestamps inside
    them; ISO/IEC 14496-22 (OpenType, the sfnt tables, GSUB and GPOS, COLR)
    for fonts, beside it Adobe's own specifications for what OpenType does
    not cover - the Type 1 Font Format, Technical Note #5176 (CFF), #5902 (PostScript name generation), the Adobe Font Metrics of the fourteen
    standard faces and the Adobe Glyph List - with UAX #9 for right-to-left
    text and UTR #53 for the order of Arabic marks; TIFF 6.0 with Technote
    2, JFIF and Exif for pictures. What claims a profile is checked against
    it on every run: veraPDF for PDF/A and PDF/UA, Mustangproject for the invoices, qpdf and pdfsig over every document.

    How much of it is tested: 4462 tests across 85 test files, green under
    Tcl 8.6.18 and Tcl 9.0.4 alike, and 81 example scripts writing 90
    documents - every command, option and value the manual names has a test
    of its own, and every example is run, validated and looked at.

    1.3 follows 1.2 and is a release about correctness rather than reach: a seventh norm review read the whole package against the standards it
    claims - twelve reviewers, each on one topic, each with the standard
    open beside the code - and found twenty-nine places where the file was
    valid and wrong at once: a gradient turned by 180 degrees, an overprint
    that switched the wrong side, an integer a reader throws the page away
    over, a table whose structure said eight columns where the page shows
    four. Every one of them is built, each with a test that a single
    reverted line turns red. An eighth review followed on its heels -
    fourteen reviewers, with two lenses the seventh had not used: what two
    claims do when they are combined, and what the reader makes of a file
    whose numbers lie - and found seventy-four more places, among them a
    metadata packet that carried its extension schemas twice and so lost
    both its PDF/A and its PDF/UA identification, an object generation the
    reader threw away and a signature that lost an annotation over it, a
    rotation about the wrong corner, an SVG transform turned the wrong way
    round, and two loops that never returned. Those are built the same way,
    and the review's own probes were run unchanged against the built tree.
    Beside the repairs, what the review asked for and what it took to prove
    the repairs is new: cursive attachment and chained positioning in GPOS, reverse chaining in GSUB, the axis variation of vertical metrics,
    two-level hyphenation dictionaries read as their author meant them, a
    table that breaks across the width of the page as one table, a table of contents that PDF/UA-2 accepts, and a pagination that is linear in the
    length of the text. Seven behaviours changed and are listed under
    "Changed since 1.2"; the API grew and nothing was withdrawn.

    Four tech notes go with this release, three of them new:
    Soft masks inside a Type 3 glyph - seven readers, two of them wrong,
    twice: https://fossil.sowaswie.de/tclpdf/technote/4dd7f8f558
    Why tclpdf does not claim PDF/X conformance: https://fossil.sowaswie.de/tclpdf/technote/4c0fac9bd3
    What 1.3 does, and what it deliberately does not: https://fossil.sowaswie.de/tclpdf/technote/09a0e91552
    Why tclpdf exists, and what it shows about working with AI: https://fossil.sowaswie.de/tclpdf/technote/d647175afa

    Download / Repository: https://fossil.sowaswie.de/tclpdf
    Author: Alexander Schoepe <alx.tcl@sowaswie.de> - bug reports, patches
    and questions are welcome by mail as well as through the repository.


    English
    -------

    New since 1.2:

    * GPOS in full for the horizontal line: beside pair kerning the kern
    path now reads and applies single adjustment, cursive attachment and
    chained contextual positioning (lookup types 1, 3, 7 and 8, extension included), so a Nastaliq face steps down its word the way its designer
    drew it and an Arabic face kerns its pairs under its own script rather
    than under Latin. The contextual matching is the one GSUB uses; a face
    with a cursive lookup over letters is set as HarfBuzz sets it, measured
    word for word against hb-shape over five Arabic faces.
    * GSUB reverse chaining (lookup type 8) is applied, backwards over the
    run as the standard says; "calt" and "rclt" run in the closing stage
    with "liga" and "clig", and "rlig" runs for every script, as HarfBuzz
    runs them - under Latin in the same stage, under Arabic before it, both measured on faces built for the purpose. A cyclic lookup graph no longer
    costs exponential time: the shaper carries a work budget and hands the
    run back unchanged when it runs out.
    * Arabic marks in the order a shaper expects: a shadda and the hamza
    marks are set before the vowel signs whatever order the text arrives in
    (UTR #53), so the composed and the decomposed spelling draw the same
    word. Everything else keeps the order it was written in.
    * Variable fonts: the MVAR table is applied, so the cap height,
    x-height, ascent and descent written for an instance are the instance's
    own and not the default's. The cmap is chosen as HarfBuzz chooses it, a Unicode full-repertoire table before a BMP-only one, which gives a face
    like Noto Sans all its characters instead of the first plane; a face
    that forbids subsetting in its fsType is embedded whole, and "font info"
    says so.
    * Hyphenation dictionaries with two levels - the German one among them -
    are read as two levels, the rule libhyphen documents for them: the first
    table finds the joints of a compound, the second hyphenates each part.
    Before, the second table ran over the whole word and offered a break at
    one letter in a fifth of all compounds; now every joint the dictionary
    names is offered and the parts break as the patterns say. "Betriebskostenabrechnung" comes out as Be-triebs-kos-ten-ab-rech-nung.
    A one-level dictionary is unchanged.
    * "structure -ref" names the element an entry points at, which PDF 2.0
    writes as /Ref and which PDF/UA-2 demands of every table-of-contents
    item; "structureResume" reopens a closed element so that later children
    - the cells of a table row that continues on the next page - become its children rather than a repetition of it. A table broken across the width
    of the page ("-horizontalBreak") is one Table with one TR per logical
    row, and the columns "-repeatColumns" carries over are pagination
    artifacts, as are repeated heads and feet.
    * A standard face in a PDF 2.0 document carries FirstChar, LastChar,
    Widths and a FontDescriptor, which ISO 32000-2 no longer exempts the
    fourteen from; under 1.7 not a byte changes.
    * "pdf info" reports a certification signature and its permission level
    as "certified", leaves the content-derived keys empty for an encrypted
    file instead of guessing them, and looks for "startxref" in the last
    1024 bytes of the file rather than at its very end, so the line or two a
    mail gateway appends does not make it unreadable - measured on a small document, 1004 appended bytes are still read. A second import of the
    same file shares its font programs and streams with the first, so a
    letterhead placed on twenty pages costs one copy. "image info" reports
    the Exif orientation of a JPEG; the picture is not turned, since the
    package decodes no pixels, but the caller can.
    * Bitmap colour fonts: "colorFont" reads an sbix face - Apple Color
    Emoji is one - and builds a Type 3 font whose glyphs are the face's own
    PNG pictures, one image XObject per glyph with the alpha channel as its
    soft mask, the largest strike unless "-strike" names a size; a face that
    joins its sequences through "morx" rather than GSUB - the AAT chain of
    finite state machines, all five subtable kinds - is shaped as HarfBuzz
    shapes it, measured against hb-shape over 3196 sequences. A TrueType collection is read by face ("-face"), and a 192 MB file costs 0.06
    seconds and 28 MB, because the picture tables stay on disk and are read
    by offset. Example 02.18 writes the same three pages in Apple Color
    Emoji beside Noto Color Emoji on a Mac that has the face.
    * A colour font reports what each of its glyphs was built from - bands,
    clips, constant opacity or a soft mask - under "font info masks", so a
    caller who needs a document free of soft masks for a particular reader
    can count them.
    * Pagination is linear in the length of the text: a paragraph that runs
    over ninety pages in two balanced columns took more than ten minutes and
    now takes six seconds, because the lines are broken once and carried
    forward rather than measured again on every page.
    * "encrypt -metadata 0" writes the Identity crypt filter on the metadata stream as ISO 32000-2 7.6.6 shows it, so a reader that decrypts every
    stream by default - poppler is one - still reads the packet in the
    clear. A date is written in the spelling of the version the file is
    written in, whichever version it was handed in under; "sign add" refuses
    a document whose certification forbids any change; a name tree keeps one encoding for all its keys; "zugferd" refuses an XML that declares
    another encoding than UTF-8.
    * Every refusal the review found missing is there, and each names its
    reason: an open arc under a fill in force, a pattern used in another
    stream than the one it was set up in, a save without a restore at the
    end of a stream, a nesting depth past the limit of Annex C, a name
    longer than 127 bytes, a structure element where ISO/TS 32005 forbids
    it, a field value the field's font cannot set, a value outside what a
    PDF number holds - checked at the call, before a byte of the stream is written, with the one bound kept in one place.
    * GPOS mark attachment to the ligature component a mark belongs to and
    to a mark on a mark (lookup types 5 and 6, with the component index
    HarfBuzz carries), the Nastaliq cluster held together across a glyph
    without a code point, and a ToUnicode map that gives a character its own
    CID where two letters share one skeleton glyph - measured from the
    written stream against hb-shape and read back with pdftotext, so a word extracts as the word that was set.
    * Apple Color Emoji: a sequence the face builds from two glyphs with a
    GPOS mark attachment - most multi-person sequences - is drawn as one
    picture of one width, the attached glyph folded into the Type 3 glyph of
    its base, so "textWidth" of a kiss is one em, as HarfBuzz measures it;
    and the vertical metrics of a variable instance come out of the face's variations, not out of the default vmtx.
    * The reader keeps the generation number of every object through
    parsing, resolution, copying and update, treats a reference to a
    generation the file does not have as the null object, checks the header
    of an object stream against the cross-reference table, reads literal
    strings as ISO 32000 says - end-of-line as LF, an octal escape capped at
    a byte - refuses ASCII85 and ASCIIHex data with characters the encoding
    does not allow, keeps the last of two equal dictionary keys and never
    writes both, reads a leading zero the same under Tcl 8.6 and 9, writes
    an integer beyond 2^31 as a real, and bounds what a Flate stream may
    unpack to.
    * One pdfaExtension:schemas container for every contributor: PDF/UA,
    ZUGFeRD and a caller's own extension schema go into one bag, so "ua 1"
    beside "zugferd" passes veraPDF for PDF/A-3B and PDF/UA-1 alike; a
    caller's whole metadata packet beside a claim that needs schemas of its
    own is refused rather than silently replaced; an XRECHNUNG profile is
    embedded as xrechnung.xml, the name Factur-X 1.09.2 reserves for it, and
    the reserved names cannot be taken by a second attachment.
    * "structure -script" is transactional: a script that fails before it
    marked anything leaves no element behind, and a form field's label and a
    table row behave the same; PDF/UA-2 refuses a Link element with two
    targets, a FENote without its /Ref pair, a page destination where a
    structure destination is required and a second Caption in any element; a
    -tag inside an open LI is what it says rather than silently LBody, and
    an imported layer that only an XObject refers to reaches /OCProperties
    with its OFF state.
    * A fillable text or choice field embeds its face whole, so a reader can
    type what the writer never wrote; seven annotation and field keys check
    the PDF version they need; an annotation or a link inside a form script
    is refused, because its rectangle would be in the wrong space; and NaN
    or Inf in a field's geometry is refused at the call.
    * SVG: transforms turn the way SVG 1.1 says, switch, visibility and display:none are honoured, currentColor, stroke-width 0, nested
    viewports, stop-opacity, the dash offset, the miter limit, the mask's
    own grey coefficients, units from em to mm, tspan in document order and collapsed whitespace are read; what a drawing loses is reported under
    "svg info", a use cycle or an entity expansion is refused before
    anything is drawn, and a refused drawing leaves the page untouched.
    * The Figure /BBox of a placed form, picture or drawing takes the transformation in force into account; a value that would round to a
    forbidden zero in the file - a stop, a dash, a pattern step, a box - is refused on the value the file would carry, not on the value given; a
    scale that makes the placement matrix singular is refused; two pictures
    of the same length and hash are two pictures; an RGB JPEG without an
    Adobe marker gets its ColorTransform entry; a PNG with a bit depth the
    format does not allow, and a mask that would be refused, are stopped
    before an object is written.
    * Tagged text extracts whole across a break hyphen; "-avoid", "leader
    -width", "pageLabels -start", "-typeArea", "table -at" and a colSpan
    across a -horizontalBreak group are checked at the call, so nothing
    loops for ever and nothing dies in arithmetic; every public command
    works as the first call of a fresh document, and a test proves it for
    all of them.

    Changed since 1.2:

    * "-fit" refuses a box that would need a size below one point; before,
    it fitted down to a size that rounds to nothing.
    * A face whose glyphs are boxes without contours - an sbix, CBDT or SVG
    colour font without a COLR table - is refused as drawing nothing,
    instead of being embedded and setting blank text that extracts fine; a
    face with real outlines beside its colour table is embedded as before.
    * "overprint -stroke" governs stroking alone: the entry is written with
    the fill side stated, because ISO 32000 makes /OP without /op set both. Before, "overprint -stroke 0" switched the fill overprint off with it.
    * "-rotate" on a form or a picture turns about the point -at names - the
    top left corner of the unturned placement, as the manual always said;
    before, it turned about the bottom left corner, and the Figure /BBox of
    a turned placement now moves with it.
    * "pdf import" refuses a page from a file whose version is newer than
    the document's, naming the version needed; before, PDF 1.5 constructs
    went into a PDF 1.4 file unremarked.
    * The /Artifact brackets of an imported page are stripped together with
    its marked content, under -artifact 1 as well; before, they stayed, and
    a tagged foreign page placed as a described Figure failed PDF/UA.
    * A fillable text or choice field that uses an embedded face embeds it
    whole instead of the subset - measured, a document with one such field
    grows from 5 kB to 384 kB; a read-only field keeps the subset.

    Fixed since 1.2:

    * Twenty-nine violations no validator sees, found by a seventh norm
    review over the whole package and all built: every COLR v1 sweep
    gradient was turned by 180 degrees (the angle bias of the format was not applied); an integer beyond 2^31 went into the file as an integer token,
    which makes qpdf discard the content stream that holds it; a shading
    angle under a pattern matrix was mapped twice; a pattern anchored in one stream was accepted in another; a justified paragraph under a horizontal scaling ended beside its column; a Type 3 family with a fallback chain
    lost its word spacing in the fallback segments; a tagged right-to-left paragraph stood one space to the right; a text path that failed left its structure mark open; a number beyond the PDF range was refused after q
    and BT were written; an sfnt without glyf and loca was embedded;
    xmpSchema accepted a prefix of xml or an empty URI; a name tree mixed
    two key encodings; a signature field could be declared over a text field
    of the same name; the import kept object numbers reserved when a later
    object was refused; a horizontally broken table was tagged as eight rows
    of four columns; a PDF/UA-2 table of contents could never conform; and
    the position a refusal names counted UTF-16 units under Tcl 8.6.
    * The forty-odd grey areas the same review named are built as well,
    among them srcAtop and xor compositions of a colour font drawn exactly
    where the masking side allows it and refused where it does not, a fully transparent gradient refused as empty, colour operators stripped from a
    d1 glyph so that Quartz and poppler draw it alike, the Ascent and
    CapHeight of a Type 1 or bare CFF face read from its own glyphs, the
    subset tag derived from the font program so two programs of one name
    never share it, a positive descender negated, a kerning list that gives
    a right-to-left line the width textWidth measured, a unit that never
    breaks before a variation selector or a combining mark, and repeated
    table heads written as pagination artifacts rather than as new rows.
    * Seventy-four findings of the eighth norm review, twenty-four of them
    in the SVG module, all built with the same test-and-revert proof and
    each re-run with the review's own probe on the built tree: violations of
    a standard the file claims, breaches of the manual's own contract, and
    two loops that never returned.

    Notes:

    * Tested against Tcl 8.6.18 and Tcl 9.0.4 on macOS: 4462 tests green
    under both over 85 test files, 81 examples writing 90 documents, every
    one of them accepted by "qpdf --check" and, where it claims PDF/A or
    PDF/UA, by veraPDF against the profile it claims; a document with a
    hybrid attachment is read by Mustangproject as well. Every command,
    option and value the manual names has a test of its own; "make check"
    runs the whole acceptance - suite under every interpreter, examples,
    qpdf, veraPDF, Mustangproject, pdfinfo, the reference snippets of the assistant skill under both interpreters, whether the error code table in
    the manual is the one the source makes, and whether the manual is newer
    than its source.
    * The package is 103 modules and loads only what a script actually uses: "package require tclpdf" registers all 103 and loads one, creating a
    document loads nine, a document with a line of text sixteen, and one
    with shapes and a table twenty-one - a script that never touches an
    image, an SVG, an invoice, a signature or a foreign file never reads the
    other eighty-two.
    * Installing: the release archives tclpdf1.3.zip and tclpdf1.3.tar.gz
    hold one directory tclpdf1.3 with the modules, pkgIndex.tcl and the ICC profiles - nothing to build; extract it into a directory on your
    auto_path and "package require tclpdf" finds it. The source archive
    builds the TEA way in the source directory: ./configure, make test, make install. A separate build directory configures cleanly but cannot run
    the tests, because the generated pkgIndex.tcl locates the modules
    through $dir while the sources stay where they are.
    * tdom is required for the XMP metadata packet, so every document that declares PDF/A, PDF/UA or ZUGFeRD needs it; a document with no such
    claim runs without it. The SVG module uses it as well when present: it
    parses 27 to 48 times faster than the parser tclpdf brings along and
    refuses an entity expansion bomb, and without it SVG still works through
    the built-in element tree parser. tzint is optional and only for
    barcodes. Nothing else is used - the encryption and the signatures are
    pure Tcl.
    * Loading a two-level hyphenation dictionary costs more than it did: the German one takes about 0.7 seconds and 120 megabytes where it took 60 milliseconds and 5, because the compound table is held as a trie.
    Hyphenating is as fast as before, and a one-level dictionary costs
    nothing extra. The price was measured against the breaks it buys and the module says so in its head.
    * No font is part of the package. The faces under examples/assets/fonts
    exist so that the tests and examples have something to embed and travel
    in the source archive alone; "make install" installs none. Whether you
    may embed a font into a PDF that tclpdf writes is a question for that
    font's licence, not for this one.
    * Some things are refused with a message naming the reason and the way
    out rather than written wrong: a progressive JPEG and an interlaced
    (Adam7) PNG, a BigTIFF and a tiled or planar TIFF and one with an alpha channel, an encrypted file handed to "pdf import" or "update open" -
    this package carries no decryption -, a line that mixes writing
    directions in one call, and a colour font composition PDF cannot draw
    exactly.
    * What tclpdf covers is roughly a third of ISO 32000-1, weighted by the
    page count of its chapters. Of the rest, what a writer would need is
    small: multimedia and 3D, JBIG2 and JPX, linearisation, and object and cross-reference streams to write - reading them has been there since the import.

    Planned:

    * Nothing, at present. 1.3 is the version this package settles on: every finding of both norm reviews is built, what is knowingly left as it is
    stands in the manual beside the feature it limits, and no extension is planned.
    * Deliberately not coming, each for a measured reason: mixed writing directions in one call, PDF/X-3 and X-4 (no tool here could check the
    claim - the tech note says why), document timestamps (the same reason),
    RC4 and the older encryption revisions, EPS as a template, GIF and BMP.

    Thanks to everyone who reported findings on the mailing list, and to
    those who wrote to me directly - several of the corrections in this
    release came out of private mail rather than a public thread.


    Deutsch
    -------

    tclpdf ist eine Erweiterung in reinem Tcl zum Erzeugen von
    PDF-Dokumenten: Seiten und Grafik, eingebettete Schriften in drei
    Formaten - TrueType auf die tatsaechlich benutzten Glyphen verkleinert, OpenType mit CFF-Konturen und Type 1 - dazu vom Aufrufer gezeichnete Type-3-Schriften, JPEG-, PNG- und TIFF-Bilder, SVG als Vektoren,
    Tabellen, Ebenen, interaktive Formularfelder, getaggte und barrierefreie Dokumente bis PDF/UA-2, Verschluesselung, digitale Signaturen und elektronische Rechnungen als ZUGFeRD / Factur-X in PDF/A-3B. Es liest
    auch: eine Seite eines vorhandenen PDF wird als Form uebernommen, eine
    fertige Datei wird durch eine Fortschreibung ergaenzt, und was eine
    fremde Datei ueber sich selbst sagt, kommt als Woerterbuch zurueck.
    Entwickelt von Alexander Schoepe, verlangt es Tcl 8.6.11+ und laeuft
    ebenso unter Tcl 9; zlib ist ein eingebauter Befehl und kein Paket, tdom
    wird nur fuer die XMP-Metadaten eines PDF/A-, PDF/UA- oder
    ZUGFeRD-Dokuments gebraucht, und Tk wird nicht benutzt.

    Normen, auf denen das Paket aufsetzt und gegen die es geprueft wird: ISO 32000-1 (PDF 1.7) und ISO 32000-2 (PDF 2.0) fuer die Datei selbst; ISO
    19005-2 und 19005-3 fuer PDF/A Teil 2 und 3 in den Stufen B, U und A;
    ISO 14289-1 und 14289-2 fuer PDF/UA, dazu WTPDF fuer das gut getaggte
    Profil und ISO/TS 32005 dafuer, was worin stehen darf; EN 16931 mit
    ZUGFeRD 2.3 / Factur-X 1.09.2 und Order-X fuer elektronische Rechnungen
    und Bestellungen; ETSI EN 319 142-1 (PAdES) und RFC 5652 (CMS) fuer Signaturen, RFC 3161 fuer die Zeitstempel darin; ISO/IEC 14496-22
    (OpenType, die sfnt-Tabellen, GSUB und GPOS, COLR) fuer Schriften,
    daneben Adobes eigene Spezifikationen fuer das, was OpenType nicht
    abdeckt - das Type 1 Font Format, Technical Note #5176 (CFF), #5902 (PostScript-Namensbildung), die Adobe Font Metrics der vierzehn Standardschriften und die Adobe Glyph List - mit UAX #9 fuer
    linkslaeufigen Text und UTR #53 fuer die Reihenfolge arabischer Marken;
    TIFF 6.0 samt Technote 2, JFIF und Exif fuer Bilder. Was ein Profil beansprucht, wird bei jedem Lauf dagegen geprueft: veraPDF fuer PDF/A
    und PDF/UA, Mustangproject fuer die Rechnungen, qpdf und pdfsig ueber
    jedes Dokument.

    Wie viel davon geprueft wird: 4462 Tests in 85 Testdateien, gruen unter
    Tcl 8.6.18 und Tcl 9.0.4, und 81 Beispielskripte, die 90 Dokumente
    schreiben - jeder Befehl, jede Option und jeder Wert, den das Handbuch
    nennt, hat einen eigenen Test, und jedes Beispiel wird ausgefuehrt,
    validiert und angesehen.

    1.3 folgt auf 1.2 und ist eine Fassung fuer die Richtigkeit, nicht fuer
    den Umfang: eine siebte Normpruefung hat das ganze Paket gegen die
    Normen gelesen, die es beansprucht - zwoelf Pruefer, jeder auf einem
    Thema, jeder mit der Norm neben dem Code - und neunundzwanzig Stellen gefunden, an denen die Datei gueltig und falsch zugleich war: ein um 180
    Grad gedrehter Verlauf, ein Ueberdruck, der die falsche Seite schaltete,
    eine Ganzzahl, ueber die ein Leser die Seite wegwirft, eine Tabelle,
    deren Struktur acht Spalten sagte, wo die Seite vier zeigt. Jede davon
    ist gebaut, jede mit einem Test, den eine einzige zurueckgenommene Zeile
    rot macht. Eine achte Pruefung folgte ihr auf dem Fuss - vierzehn
    Pruefer, mit zwei Blickwinkeln, die die siebte nicht hatte: was zwei
    Zusagen tun, wenn man sie kombiniert, und was der Leser aus einer Datei
    macht, deren Zahlen luegen - und fand vierundsiebzig weitere Stellen,
    darunter ein Metadatenpaket, das seine Erweiterungsschemata zweimal trug
    und damit seine PDF/A- und seine PDF/UA-Kennung zugleich verlor, eine Objektgeneration, die der Leser wegwarf, und eine Signatur, die darueber
    eine Annotation verlor, eine Drehung um die falsche Ecke, eine SVG-Transformation in die falsche Richtung und zwei Schleifen, die nie zurueckkamen. Die sind auf dieselbe Weise gebaut, und die Proben der
    Pruefung liefen unveraendert gegen den gebauten Baum. Neben den
    Reparaturen ist neu, was die Pruefung verlangt hat und was es brauchte,
    die Reparaturen zu belegen: Cursive Attachment und verkettete
    Positionierung in GPOS, Reverse Chaining in GSUB, die Achsenvariation
    der vertikalen Metriken, zweistufige Silbentrenn-Woerterbuecher so
    gelesen, wie ihr Autor sie meinte, eine ueber die Seitenbreite
    umbrochene Tabelle als eine Tabelle, ein Inhaltsverzeichnis, das
    PDF/UA-2 annimmt, und eine Paginierung, die linear in der Laenge des
    Textes ist. Sieben Verhalten haben sich geaendert und stehen unter
    "Geaendert seit 1.2"; die Schnittstelle ist gewachsen, und nichts wurde zurueckgezogen.

    Vier Technotes gehoeren zu dieser Ausgabe, drei davon neu:
    Weichmasken in einem Type-3-Glyph - sieben Leser, zwei davon falsch,
    zweimal: https://fossil.sowaswie.de/tclpdf/technote/4dd7f8f558
    Warum tclpdf keine PDF/X-Konformitaet beansprucht: https://fossil.sowaswie.de/tclpdf/technote/4c0fac9bd3
    Was 1.3 kann und was bewusst fehlt: https://fossil.sowaswie.de/tclpdf/technote/09a0e91552
    Warum es tclpdf gibt und was das ueber die Arbeit mit KI zeigt: https://fossil.sowaswie.de/tclpdf/technote/d647175afa

    Bezug / Repository: https://fossil.sowaswie.de/tclpdf
    Autor: Alexander Schoepe <alx.tcl@sowaswie.de> - Fehlermeldungen,
    Patches und Fragen gern auch per Mail, nicht nur ueber das Repository.

    Neu seit 1.2:

    * GPOS vollstaendig fuer die waagerechte Zeile: neben dem Paar-Kerning
    liest und wendet der Kerning-Weg jetzt Einzelanpassung, Cursive
    Attachment und verkettete kontextuelle Positionierung an (Lookuptypen 1,
    3, 7 und 8, Extension eingeschlossen), sodass eine Nastaliq-Schrift ihr
    Wort so hinabsteigt, wie ihr Gestalter es gezeichnet hat, und eine
    arabische Schrift ihre Paare unter ihrem eigenen Schriftsystem kernt
    statt unter dem lateinischen. Der Kontextabgleich ist derselbe wie bei
    GSUB; eine Schrift mit einer Cursive-Lookup ueber Buchstaben wird so
    gesetzt, wie HarfBuzz sie setzt, Wort fuer Wort gegen hb-shape ueber
    fuenf arabische Schriften gemessen.
    * GSUB Reverse Chaining (Lookuptyp 8) wird angewendet, rueckwaerts ueber
    den Lauf, wie die Norm es sagt; "calt" und "rclt" laufen in der
    Schlussstufe mit "liga" und "clig", und "rlig" laeuft fuer jedes Schriftsystem, so wie HarfBuzz es tut - unter Latein in derselben Stufe,
    unter Arabisch davor, beides an eigens gebauten Schriften gemessen. Ein zyklischer Lookup-Graph kostet keine exponentielle Zeit mehr: der Shaper traegt ein Arbeitsbudget und gibt den Lauf unveraendert zurueck, wenn es erschoepft ist.
    * Arabische Marken in der Reihenfolge, die ein Shaper erwartet: ein
    Schadda und die Hamza-Marken werden vor die Vokalzeichen gesetzt, in
    welcher Reihenfolge der Text auch ankommt (UTR #53), sodass die
    komponierte und die zerlegte Schreibweise dasselbe Wort zeichnen. Alles
    andere behaelt die Reihenfolge, in der es geschrieben wurde.
    * Variable Schriften: die MVAR-Tabelle wird angewendet, sodass
    Versalhoehe, x-Hoehe, Ascent und Descent einer Instanz die der Instanz
    sind und nicht die der Vorgabe. Die cmap wird gewaehlt, wie HarfBuzz sie waehlt, eine Unicode-Tabelle ueber alle Ebenen vor einer, die nur die
    BMP kennt, was einer Schrift wie Noto Sans alle ihre Zeichen gibt statt
    der ersten Ebene; eine Schrift, die in ihrem fsType das Verkleinern
    verbietet, wird ganz eingebettet, und "font info" sagt es.
    * Silbentrenn-Woerterbuecher mit zwei Stufen - das deutsche gehoert dazu
    - werden als zwei Stufen gelesen, nach der Regel, die libhyphen fuer sie dokumentiert: die erste Tabelle findet die Fugen eines Kompositums, die
    zweite trennt jeden Teil. Vorher lief die zweite Tabelle ueber das ganze
    Wort und bot in einem Fuenftel aller Komposita eine Trennung an einem einzelnen Buchstaben an; jetzt wird jede Fuge angeboten, die das
    Woerterbuch nennt, und die Teile trennen so, wie die Muster es sagen. "Betriebskostenabrechnung" kommt als Be-triebs-kos-ten-ab-rech-nung
    heraus. Ein einstufiges Woerterbuch ist unveraendert.
    * "structure -ref" nennt das Element, auf das ein Eintrag zeigt, was PDF
    2.0 als /Ref schreibt und PDF/UA-2 von jedem Eintrag eines Inhaltsverzeichnisses verlangt; "structureResume" oeffnet ein
    geschlossenes Element wieder, sodass spaetere Kinder - die Zellen einer Tabellenzeile, die auf der naechsten Seite weitergeht - seine Kinder
    werden statt einer Wiederholung. Eine ueber die Seitenbreite umbrochene Tabelle ("-horizontalBreak") ist EINE Tabelle mit einem TR je logischer
    Zeile, und die Spalten, die "-repeatColumns" mitnimmt, sind Paginierungsartefakte, ebenso wiederholte Kopf- und Fusszeilen.
    * Eine Standardschrift in einem PDF-2.0-Dokument traegt FirstChar,
    LastChar, Widths und einen FontDescriptor, von denen ISO 32000-2 die
    vierzehn nicht mehr ausnimmt; unter 1.7 aendert sich kein Byte.
    * "pdf info" meldet eine Zertifizierungssignatur samt Berechtigungsstufe
    als "certified", laesst die inhaltsabgeleiteten Schluessel bei einer verschluesselten Datei leer statt sie zu raten und sucht "startxref" in
    den letzten 1024 Byte der Datei statt an ihrem Ende, so dass die eine
    oder zwei Zeilen, die ein Mail-Gateway anhaengt, sie nicht unlesbar
    machen - an einem kleinen Dokument gemessen werden 1004 angehaengte Byte
    noch gelesen. Ein zweiter Import derselben Datei teilt sich
    Schriftprogramme und Stroeme mit dem ersten, ein auf zwanzig Seiten
    gesetzter Briefbogen kostet also eine Kopie. "image info" meldet die Exif-Orientierung eines JPEG; das Bild wird nicht gedreht, weil das
    Paket keine Pixel dekodiert, der Aufrufer kann es.
    * Bitmap-Farbschriften: "colorFont" liest eine sbix-Schrift - Apple
    Color Emoji ist eine - und baut eine Type-3-Schrift, deren Glyphen die PNG-Bilder der Schrift selbst sind, ein Image-XObject je Glyphe mit dem Alphakanal als Weichmaske, der groesste Strike, sofern "-strike" keine
    Groesse nennt; eine Schrift, die ihre Sequenzen ueber "morx" statt GSUB
    bildet - die AAT-Kette endlicher Automaten, alle fuenf Subtabellenarten
    -, wird geformt, wie HarfBuzz sie formt, gemessen gegen hb-shape ueber
    3196 Sequenzen. Eine TrueType-Sammlung wird je Face gelesen ("-face"),
    und eine 192-MB-Datei kostet 0,06 Sekunden und 28 MB, weil die
    Bildtabellen auf der Platte bleiben und ueber Offsets gelesen werden.
    Beispiel 02.18 schreibt auf einem Mac mit der Schrift dieselben drei
    Seiten in Apple Color Emoji neben Noto Color Emoji.
    * Eine Farbschrift sagt, woraus jede ihrer Glyphen gebaut wurde -
    Baender, Clips, konstante Deckkraft oder eine Weichmaske - unter "font
    info masks", sodass ein Aufrufer, der fuer einen bestimmten Leser ein
    Dokument ohne Weichmasken braucht, sie zaehlen kann.
    * Die Paginierung ist linear in der Laenge des Textes: ein Absatz ueber neunzig Seiten in zwei ausgeglichenen Spalten brauchte mehr als zehn
    Minuten und braucht jetzt sechs Sekunden, weil die Zeilen einmal
    umbrochen und weitergereicht werden statt auf jeder Seite neu gemessen.
    * "encrypt -metadata 0" schreibt den Identity-Crypt-Filter am
    Metadatenstrom, wie ISO 32000-2 7.6.6 es zeigt, sodass ein Leser, der
    von sich aus jeden Strom entschluesselt - poppler ist einer -, das Paket weiter im Klartext liest. Ein Datum wird in der Schreibweise der Version geschrieben, in der die Datei geschrieben wird, unter welcher Version es
    auch uebergeben wurde; "sign add" lehnt ein Dokument ab, dessen
    Zertifizierung jede Aenderung verbietet; ein Namensbaum haelt eine
    Kodierung fuer alle seine Schluessel; "zugferd" lehnt ein XML ab, das
    eine andere Kodierung als UTF-8 erklaert.
    * Jede Ablehnung, die die Pruefung vermisst hat, ist da, und jede nennt
    ihren Grund: ein offener Bogen unter einer geltenden Fuellung, ein
    Muster in einem anderen Strom als dem, in dem es eingerichtet wurde, ein
    save ohne restore am Ende eines Stroms, eine Schachtelungstiefe jenseits
    der Grenze aus Annex C, ein Name laenger als 127 Byte, ein
    Strukturelement, wo ISO/TS 32005 es verbietet, ein Feldwert, den die
    Schrift des Feldes nicht setzen kann, ein Wert ausserhalb dessen, was
    eine PDF-Zahl haelt - geprueft am Aufruf, bevor ein Byte des Stroms geschrieben ist, mit der einen Grenze an einer Stelle.
    * GPOS-Markenanbindung an die Komponente einer Ligatur, zu der die Marke gehoert, und an eine Marke auf einer Marke (Lookuptypen 5 und 6, mit dem Komponentenindex, den HarfBuzz fuehrt), der Nastaliq-Cluster ueber eine
    Glyphe ohne Codepunkt hinweg zusammengehalten, und eine
    ToUnicode-Abbildung, die einem Zeichen eine eigene CID gibt, wo zwei Buchstaben eine Skelettglyphe teilen - aus dem geschriebenen Strom gegen hb-shape gemessen und mit pdftotext zurueckgelesen, sodass ein Wort als
    das Wort extrahiert, das gesetzt wurde.
    * Apple Color Emoji: eine Sequenz, die der Schnitt aus zwei Glyphen mit
    einer GPOS-Markenanbindung baut - die meisten Mehrpersonen-Sequenzen -,
    wird als ein Bild mit einer Breite gezeichnet, die angebundene Glyphe in
    die Type-3-Glyphe ihrer Basis gefaltet, sodass "textWidth" eines Kusses
    ein Geviert ist, wie HarfBuzz es misst; und die vertikalen Metriken
    einer variablen Instanz kommen aus den Variationen des Schnitts, nicht
    aus dem Default-vmtx.
    * Der Leser fuehrt die Generationsnummer jedes Objekts durch Parsen, Aufloesen, Kopieren und Update, behandelt einen Verweis auf eine
    Generation, die die Datei nicht hat, als Nullobjekt, haelt den Kopf
    eines Objektstroms gegen die Querverweistabelle, liest Literal-Strings,
    wie ISO 32000 es sagt - Zeilenende als LF, ein Oktal-Escape auf ein Byte gekappt -, lehnt ASCII85- und ASCIIHex-Daten mit Zeichen ab, die die
    Kodierung nicht erlaubt, behaelt den letzten von zwei gleichen Dictionary-Schluesseln und schreibt nie beide, liest eine fuehrende Null
    unter Tcl 8.6 und 9 gleich, schreibt eine Ganzzahl jenseits 2^31 als
    Real und begrenzt, worauf ein Flate-Strom sich entpacken darf.
    * Ein pdfaExtension:schemas-Container fuer jeden Beitrag: PDF/UA,
    ZUGFeRD und das eigene Erweiterungsschema eines Aufrufers kommen in
    einen Bag, sodass "ua 1" neben "zugferd" veraPDF fuer PDF/A-3B und
    PDF/UA-1 gleichermassen besteht; ein ganzes Metadatenpaket des Aufrufers
    neben einem Anspruch, der eigene Schemata braucht, wird abgelehnt statt
    still ersetzt; ein XRECHNUNG-Profil wird als xrechnung.xml eingebettet,
    der Name, den Factur-X 1.09.2 dafuer reserviert, und die reservierten
    Namen kann kein zweiter Anhang nehmen.
    * "structure -script" ist transaktional: ein Skript, das scheitert,
    bevor es etwas markiert hat, laesst kein Element zurueck, und die
    Beschriftung eines Formularfelds und eine Tabellenzeile verhalten sich
    ebenso; PDF/UA-2 lehnt ein Link-Element mit zwei Zielen ab, eine FENote
    ohne ihr /Ref-Paar, eine Seitendestination, wo eine Strukturdestination verlangt ist, und eine zweite Caption in jedem Element; ein -tag in
    einem offenen LI ist, was es sagt, statt still LBody, und eine
    importierte Ebene, auf die nur ein XObject verweist, erreicht
    /OCProperties mit ihrem OFF-Zustand.
    * Ein ausfuellbares Text- oder Auswahlfeld bettet seinen Schnitt ganz
    ein, sodass ein Leser tippen kann, was der Schreiber nie geschrieben
    hat; sieben Annotations- und Feldschluessel pruefen die PDF-Version, die
    sie brauchen; eine Annotation oder ein Link in einem Formular-Skript
    wird abgelehnt, weil ihr Rechteck im falschen Raum laege; und NaN oder
    Inf in der Geometrie eines Feldes wird am Aufruf abgelehnt.
    * SVG: Transformationen drehen so, wie SVG 1.1 es sagt, switch,
    visibility und display:none werden beachtet, currentColor, stroke-width
    0, verschachtelte Viewports, stop-opacity, der Strichversatz, die Gehrungsgrenze, die eigenen Graukoeffizienten der Maske, Einheiten von
    em bis mm, tspan in Dokumentreihenfolge und zusammengefasster Leerraum
    werden gelesen; was einer Zeichnung verlorengeht, meldet "svg info", ein use-Zyklus oder eine Entity-Expansion wird abgelehnt, bevor etwas
    gezeichnet ist, und eine abgelehnte Zeichnung laesst die Seite unberuehrt.
    * Die Figure-/BBox einer platzierten Form, eines Bildes oder einer
    Zeichnung beruecksichtigt die geltende Transformation; ein Wert, der in
    der Datei auf eine verbotene Null runden wuerde - ein Stopp, ein Strich,
    ein Musterschritt, eine Box -, wird an dem Wert abgelehnt, den die Datei truege, nicht am uebergebenen; ein Massstab, der die Platzierungsmatrix singulaer macht, wird abgelehnt; zwei Bilder gleicher Laenge und
    gleichen Hashes sind zwei Bilder; ein RGB-JPEG ohne Adobe-Marker bekommt seinen ColorTransform-Eintrag; ein PNG mit einer Bittiefe, die das
    Format nicht erlaubt, und eine Maske, die abgelehnt wuerde, werden
    gestoppt, bevor ein Objekt geschrieben ist.
    * Getaggter Text extrahiert ueber einen Trennstrich hinweg ganz;
    "-avoid", "leader -width", "pageLabels -start", "-typeArea", "table -at"
    und ein colSpan ueber eine -horizontalBreak-Gruppe werden am Aufruf
    geprueft, sodass nichts endlos laeuft und nichts in der Arithmetik
    stirbt; jeder oeffentliche Befehl funktioniert als erster Aufruf eines frischen Dokuments, und ein Test belegt es fuer alle.

    Geaendert seit 1.2:

    * "-fit" lehnt eine Box ab, die eine Groesse unter einem Punkt
    braeuchte; vorher passte es bis zu einer Groesse ein, die auf nichts rundet.
    * Eine Schrift, deren Glyphen Kaesten ohne Konturen sind - eine sbix-,
    CBDT- oder SVG-Farbschrift ohne COLR-Tabelle -, wird abgelehnt, weil sie nichts zeichnet, statt eingebettet zu werden und leeren Text zu setzen,
    der sich tadellos extrahiert; eine Schrift mit echten Konturen neben
    ihrer Farbtabelle wird eingebettet wie bisher.
    * "overprint -stroke" regelt allein den Strich: der Eintrag wird mit
    benannter Fuellseite geschrieben, weil ISO 32000 ein /OP ohne /op beide
    Seiten setzen laesst. Vorher schaltete "overprint -stroke 0" den
    Ueberdruck der Fuellung mit ab.
    * "-rotate" an einer Form oder einem Bild dreht um den Punkt, den -at
    nennt - die obere linke Ecke der ungedrehten Platzierung, wie das
    Handbuch es immer gesagt hat; vorher drehte es um die untere linke Ecke,
    und die Figure-/BBox einer gedrehten Platzierung wandert jetzt mit.
    * "pdf import" lehnt eine Seite aus einer Datei ab, deren Version
    juenger ist als die des Dokuments, und nennt die noetige Version; vorher gingen PDF-1.5-Konstrukte unbemerkt in eine PDF-1.4-Datei.
    * Die /Artifact-Klammern einer importierten Seite werden mit ihrem
    markierten Inhalt entfernt, auch unter -artifact 1; vorher blieben sie
    stehen, und eine getaggte Fremdseite, als beschriebene Figure platziert,
    fiel bei PDF/UA durch.
    * Ein ausfuellbares Text- oder Auswahlfeld mit einem eingebetteten
    Schnitt bettet ihn ganz ein statt als Subset - gemessen waechst ein
    Dokument mit einem solchen Feld von 5 kB auf 384 kB; ein
    schreibgeschuetztes Feld behaelt das Subset.

    Behoben seit 1.2:

    * Neunundzwanzig Verstoesse, die kein Validator sieht, gefunden von
    einer siebten Normpruefung ueber das ganze Paket und alle gebaut: jeder COLR-v1-Sweep-Verlauf war um 180 Grad gedreht (der Winkelversatz des
    Formats wurde nicht angewendet); eine Ganzzahl jenseits von 2^31 ging
    als Ganzzahl-Token in die Datei, worauf qpdf den Inhaltsstrom verwirft,
    der sie traegt; ein Verlaufswinkel unter einer Mustermatrix wurde
    zweimal abgebildet; ein in einem Strom verankertes Muster wurde in einem anderen angenommen; ein Blocksatzabsatz unter einer waagerechten
    Skalierung endete neben seiner Spalte; eine Type-3-Familie mit Ersatzschrift-Kette verlor in den Ersatzabschnitten ihren Wortabstand;
    ein getaggter linkslaeufiger Absatz stand ein Leerzeichen zu weit
    rechts; ein Textpfad, der scheiterte, liess seine Strukturmarke offen;
    eine Zahl jenseits des PDF-Bereichs wurde erst nach geschriebenem q und
    BT abgelehnt; ein sfnt ohne glyf und loca wurde eingebettet; xmpSchema
    nahm ein Praefix xml oder eine leere URI an; ein Namensbaum mischte zwei Schluesselkodierungen; ein Signaturfeld liess sich ueber einem
    gleichnamigen Textfeld erklaeren; der Import hielt Objektnummern
    reserviert, wenn ein spaeteres Objekt abgelehnt wurde; eine waagerecht umbrochene Tabelle war als acht Zeilen zu vier Spalten getaggt; ein PDF/UA-2-Inhaltsverzeichnis konnte nie konform sein; und die Position,
    die eine Ablehnung nennt, zaehlte unter Tcl 8.6 UTF-16-Einheiten.
    * Die rund vierzig Grauzonen, die dieselbe Pruefung benannt hat, sind ebenfalls gebaut, darunter srcAtop- und xor-Kompositionen einer
    Farbschrift, exakt gezeichnet, wo die Maskenseite es zulaesst, und
    abgelehnt, wo nicht, ein vollstaendig durchsichtiger Verlauf als leer abgelehnt, Farboperatoren aus einer d1-Glyphe gestrichen, sodass Quartz
    und poppler sie gleich zeichnen, Ascent und CapHeight einer Type-1- oder nackten CFF-Schrift aus ihren eigenen Glyphen gelesen, das
    Subset-Kennzeichen aus dem Schriftprogramm abgeleitet, sodass zwei
    Programme eines Namens es nie teilen, ein positiver Descender negiert,
    eine Kerning-Liste, die einer linkslaeufigen Zeile die Breite gibt, die textWidth gemessen hat, eine Einheit, die nie vor einem
    Variantenselektor oder einer kombinierenden Marke bricht, und
    wiederholte Tabellenkoepfe als Paginierungsartefakte geschrieben statt
    als neue Zeilen.
    * Vierundsiebzig Befunde der achten Normpruefung, vierundzwanzig davon
    im SVG-Modul, alle mit demselben Test-und-Ruecknahme-Beleg gebaut und
    jeder mit der eigenen Probe der Pruefung auf dem gebauten Baum
    wiederholt: Verstoesse gegen eine Norm, die die Datei beansprucht,
    Brueche des eigenen Handbuchvertrags und zwei Schleifen, die nie
    zurueckkamen.

    Hinweise:

    * Geprueft gegen Tcl 8.6.18 und Tcl 9.0.4 unter macOS: 4462 Tests gruen
    unter beiden ueber 85 Testdateien, 81 Beispiele mit 90 Dokumenten, jedes
    davon von "qpdf --check" angenommen und, wo es PDF/A oder PDF/UA
    beansprucht, von veraPDF gegen das beanspruchte Profil; ein Dokument mit Hybridanhang wird ausserdem von Mustangproject gelesen. Jeder Befehl,
    jede Option und jeder Wert, den das Handbuch nennt, hat einen eigenen
    Test; "make check" faehrt die ganze Abnahme - Suite unter jedem
    Interpreter, Beispiele, qpdf, veraPDF, Mustangproject, pdfinfo, die Referenz-Schnipsel des Assistenten-Skills unter beiden Interpretern, ob
    die Fehlercodetabelle im Handbuch die ist, die die Quelle erzeugt, und
    ob das Handbuch neuer ist als seine Quelle.
    * Das Paket besteht aus 103 Modulen und laedt nur, was ein Skript
    wirklich benutzt: "package require tclpdf" meldet alle 103 an und laedt
    eines, ein Dokument anzulegen laedt neun, ein Dokument mit einer
    Textzeile sechzehn und eines mit Formen und einer Tabelle einundzwanzig
    - wer nie ein Bild, kein SVG, keine Rechnung, keine Signatur und keine
    fremde Datei anfasst, liest die anderen zweiundachtzig nie.
    * Installation: die Release-Archive tclpdf1.3.zip und tclpdf1.3.tar.gz enthalten ein Verzeichnis tclpdf1.3 mit den Modulen, pkgIndex.tcl und
    den ICC-Profilen - nichts zu bauen; in ein Verzeichnis auf dem auto_path entpacken, und "package require tclpdf" findet es. Das Quellarchiv baut
    auf TEA-Art im Quellverzeichnis: ./configure, make test, make install.
    Ein eigenes Bauverzeichnis konfiguriert sauber, kann die Tests aber
    nicht ausfuehren, weil die erzeugte pkgIndex.tcl die Module ueber $dir
    sucht, waehrend die Quellen liegen bleiben.
    * tdom wird fuer das XMP-Metadatenpaket gebraucht, also von jedem
    Dokument, das PDF/A, PDF/UA oder ZUGFeRD erklaert; ein Dokument ohne
    solche Erklaerung laeuft ohne. Das SVG-Modul benutzt es ausserdem, wenn
    es vorhanden ist: es parst 27- bis 48-mal schneller als der
    mitgelieferte Parser und wehrt eine Entity-Bombe ab, und ohne tdom
    laeuft SVG weiter, ueber den eingebauten Elementbaum-Parser. tzint ist optional und nur fuer Barcodes. Sonst wird nichts benutzt - die Verschluesselung und die Signaturen sind reines Tcl.
    * Ein zweistufiges Silbentrenn-Woerterbuch zu laden kostet mehr als
    bisher: das deutsche braucht etwa 0,7 Sekunden und 120 Megabyte, wo es
    60 Millisekunden und 5 brauchte, weil die Kompositumstabelle als Trie
    gehalten wird. Das Trennen selbst ist so schnell wie vorher, und ein einstufiges Woerterbuch kostet nichts zusaetzlich. Der Preis ist gegen
    die Trennungen gemessen, die er kauft, und der Modulkopf sagt es.
    * Keine Schrift gehoert zum Paket. Die Schnitte unter
    examples/assets/fonts sind da, damit Tests und Beispiele etwas zum
    Einbetten haben, und reisen allein im Quellarchiv mit; "make install" installiert keine. Ob eine Schrift in ein von tclpdf geschriebenes PDF eingebettet werden darf, entscheidet die Lizenz jener Schrift, nicht
    diese hier.
    * Manches wird mit einer Meldung abgelehnt, die Grund und Ausweg nennt,
    statt falsch geschrieben zu werden: ein progressives JPEG und ein verschraenktes (Adam7) PNG, ein BigTIFF und ein gekacheltes oder ebenengetrenntes TIFF und eines mit Alphakanal, eine verschluesselte
    Datei an "pdf import" oder "update open" - dieses Paket bringt keine Entschluesselung mit -, eine Zeile, die in einem Aufruf die
    Schreibrichtungen mischt, und eine Farbschrift-Komposition, die PDF
    nicht exakt zeichnen kann.
    * Was tclpdf abdeckt, ist rund ein Drittel von ISO 32000-1, gewichtet
    nach dem Seitenumfang der Kapitel. Vom Rest ist das, was ein Schreiber braeuchte, wenig: Multimedia und 3D, JBIG2 und JPX, Linearisierung sowie Objekt- und Querverweisstroeme zum Schreiben - gelesen werden sie seit
    dem Import.

    Geplant:

    * Zur Zeit nichts. 1.3 ist die Fassung, auf der dieses Paket ruht: jeder Befund beider Normpruefungen ist gebaut, was wissentlich bleibt, wie es
    ist, steht im Handbuch neben dem Merkmal, das es begrenzt, und keine Erweiterung ist geplant.
    * Ausdruecklich nicht geplant, jedes aus einem gemessenen Grund:
    gemischte Schreibrichtungen in einem Aufruf, PDF/X-3 und X-4 (kein
    Werkzeug hier koennte die Zusage pruefen - die Technote sagt, warum), Dokument-Zeitstempel (derselbe Grund), RC4 und die aelteren Verschluesselungsrevisionen, EPS als Vorlage, GIF und BMP.

    Dank an alle, die auf der Mailingliste Befunde gemeldet haben, und an
    die, die mir direkt geschrieben haben - mehrere Korrekturen dieser
    Ausgabe kamen aus persoenlicher Post und nicht aus einem oeffentlichen
    Thread.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Arjen@user153@newsgrouper.org.invalid to comp.lang.tcl on Wed Sep 2 06:20:35 2026
    From Newsgroup: comp.lang.tcl


    I tried to read the technote on what tclpdf can and cannot do - https://fossil.sowaswie.de/tclpdf/technote/09a0e91552
    - but I got the response that that note cannot be found.

    I am in the very short term interested in adding a bit of text (and two lines to cross out a word ;)) to an existing PDF document. Can that be done?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From =?UTF-8?Q?Alexander_Sch=C3=B6pe?=@ete-sep@mxbo.de to comp.lang.tcl on Thu Sep 3 16:51:43 2026
    From Newsgroup: comp.lang.tcl

    Hi Arjen,

    I reorganized a few things, and unfortunately some of the IDs got lost
    in the process. Just have a look at the overview of the technotes: https://fossil.sowaswie.de/tclpdf/timeline?y=e

    I could imagine that the following might work: import the existing PDF
    and then draw on top of it. I haven't tried it myself yet, though.

    Alex

    Am 02.09.26 um 08:20 schrieb Arjen:

    I tried to read the technote on what tclpdf can and cannot do - https://fossil.sowaswie.de/tclpdf/technote/09a0e91552
    - but I got the response that that note cannot be found.

    I am in the very short term interested in adding a bit of text (and two lines to cross out a word ;)) to an existing PDF document. Can that be done?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Christian Gollwitzer@auriocus@gmx.de to comp.lang.tcl on Thu Sep 3 19:31:48 2026
    From Newsgroup: comp.lang.tcl

    Am 02.09.26 um 08:20 schrieb Arjen:

    I tried to read the technote on what tclpdf can and cannot do - https://fossil.sowaswie.de/tclpdf/technote/09a0e91552
    - but I got the response that that note cannot be found.

    I am in the very short term interested in adding a bit of text (and two lines to cross out a word ;)) to an existing PDF document. Can that be done?

    is it for a one-off thing? Then you could use some GUI editor. For
    example, okular (the KDE/Linux viewer) can add annotations, which can be crossing out and adding text. Not great at formatting the text, and if
    you need the annotations burned in, you need to process the PDF again.

    You can also import the PDF into inkscape, I believe this decomposes / recreates the whole PDF.

    I think the Foxit PDF reader can also do annotations and simple edits,
    haven't used it myself, though. And then there is pdflatex which can do
    a lot, but with a steep learning curve.

    Christian
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From =?UTF-8?Q?Alexander_Sch=C3=B6pe?=@ete-sep@mxbo.de to comp.lang.tcl on Thu Sep 3 21:10:12 2026
    From Newsgroup: comp.lang.tcl

    Am 03.09.26 um 19:31 schrieb Christian Gollwitzer:
    Am 02.09.26 um 08:20 schrieb Arjen:

    I tried to read the technote on what tclpdf can and cannot do -
    https://fossil.sowaswie.de/tclpdf/technote/09a0e91552
    - but I got the response that that note cannot be found.

    I am in the very short term interested in adding a bit of text (and
    two lines
    to cross out a word ;)) to an existing PDF document. Can that be done?

    is it for a one-off thing? Then you could use some GUI editor. For
    example, okular (the KDE/Linux viewer) can add annotations, which can be crossing out and adding text. Not great at formatting the text, and if
    you need the annotations burned in, you need to process the PDF again.

    You can also import the PDF into inkscape, I believe this decomposes / recreates the whole PDF.

    I think the Foxit PDF reader can also do annotations and simple edits, haven't used it myself, though. And then there is pdflatex which can do
    a lot, but with a steep learning curve.

    Christian

    Yes, I use PDFgear, which runs on macOS and Windows (for free).

    Alex
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Arjen@user153@newsgrouper.org.invalid to comp.lang.tcl on Fri Sep 4 06:23:45 2026
    From Newsgroup: comp.lang.tcl


    Thanks for the suggestions. It was a one-off thing, indeed, and after a
    quick look at some examples I decided to go the more pedestrian way ;). Just a copy of the image, then the infamous Paint program on Windows. It worked, not very
    elegant, I am afraid, but I will definitely keep this package in mind.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Christian Gollwitzer@auriocus@gmx.de to comp.lang.tcl on Fri Sep 4 09:11:51 2026
    From Newsgroup: comp.lang.tcl

    Am 04.09.26 um 08:23 schrieb Arjen:

    Thanks for the suggestions. It was a one-off thing, indeed, and after a
    quick look at some examples I decided to go the more pedestrian way ;). Just a
    copy of the image, then the infamous Paint program on Windows. It worked, not very
    elegant, I am afraid, but I will definitely keep this package in mind.

    One more, the newest LIbreoffice can also edit PDF, and it's not that
    bad. You can easily drag around objects, change text etc. As usual, the
    layout is not preserved, i.e. each line is a single object etc.

    Christian
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Fri Sep 4 17:53:51 2026
    From Newsgroup: comp.lang.tcl

    Christian Gollwitzer <auriocus@gmx.de> wrote:
    Am 04.09.26 um 08:23 schrieb Arjen:

    Thanks for the suggestions. It was a one-off thing, indeed, and
    after a quick look at some examples I decided to go the more
    pedestrian way ;). Just a copy of the image, then the infamous
    Paint program on Windows. It worked, not very elegant, I am afraid,
    but I will definitely keep this package in mind.

    One more, the newest LIbreoffice can also edit PDF, and it's not that
    bad. You can easily drag around objects, change text etc. As usual,
    the layout is not preserved, i.e. each line is a single object etc.

    That is likely because the PDF is laying out each line as a single "pdf object".

    The internal commands of a PDF for text layout are basically raw
    instructions for a virtual 2D typesetter (i.e., goto x,y position,
    place text at the last goto position, etc). So what you are seeing
    when opening one in LibreOffice is how the creator app for that PDF
    broke apart the document to "position" each piece on the virtual 2D typesetters output bitmap.

    You could, if you wanted to obsfuscate things, position each letter on
    the page in a completely random ordering within the PDF. Once the page
    is rendered, it would look the same as one created top down, left to
    right, but internally trying to follow what was happening would be
    quite a confusing nightmare (plus the display rendering would likely
    take a bit longer to finish).

    --- Synchronet 3.22a-Linux NewsLink 1.2