FK~

Moje odkazy

Ostatní odkazy

Close Windows
Nenajdete mě na Facebooku ani Twitteru
Rozpad EU
Jsem členem FSF
There Is No Cloud …just other people's computers.
Sane software manifesto / Manifest příčetného softwaru

Obsah článku:

Tisk v přesném měřítku (PDF, PPD, CUPS)

vydáno: 29. 6. 2020 01:15, aktualizováno: 14. 4. 2023 20:06

Problém s tiskárnami je, že… Nechci dnes mluvit o hardwarových závadách (jako že vám třeba zaschne náplň v inkoustové tiskárně), ale o těch softwarových. V dobách, kdy jsme běžně k počítačům připojovali jehličkové tiskárny pomocí paralelního portu, byla situace v lecčems jednodušší – s tiskárnou jsme komunikovali více napřímo a ta poslušně plnila naše příkazy (takže jsme si třeba potiskli místo papíru válec, když jsme zadali špatné rozměry). S tím, jak roste komplexita softwaru, přibývají v systému další mezičlánky – a ty občas kompenzují chyby uživatele a jindy mu přidělávají starosti. Potištěných válců ubylo, ale zmuchlaných papírů v koši je pořád dost.

tisk v přesném měřítku, tisknutelná oblast a okraje

To si třeba nastavíte v LaTeXu třícentimetrové okraje a vytisknete zkušební stránku. Je to lepší než výchozí nastavení (které oceníte, když píšete diplomku, protože vám rychleji přibývají stránky, ale jinak je dost nepraktické), ale pořád je to nějaké divné, tak vezmete do ruky pravítko a naměříte 3,5 cm. To není chyba omluvitelná nějakou mechanickou nepřesností tiskárny – tady je něco špatně.

Je chyba v TeXu? Nebo jsem špatně pochopil parametry příkazu \usepackage{geometry}? Rozbila mi to PDF knihovna nebo PDF prohlížeč, přes který jsem to posílal do tiskárny? Vstoupil do toho nějaký CUPS filtr? Nebo je chyba v tiskárně? Ta mrcha má dneska v sobě malý počítač s vlastním OS, byť se navenek tváří celkem nevinně se svým dvouřádkovým LCD displejem, pár tlačítky a retro webovým rozhraním.

Teď by se nabízela metoda půlení intervalu, ale nechce se mi psát ručně PostScript a zkoušet ho tam procpat od prostředka, abych zjistil, jestli je chyba spíš na té polovině cesty směrem k tiskárně nebo na té druhé směrem k uživateli. Tak to zkusím rovnou od druhého konce: dávám PDF soubory na USB flashku a nesu je k tiskárně – ta má USB port a nabízí tzv. přímý tisk. Ovládání přes ten malý displej a pár tlačítek je docela použitelné. Tiskárna tiskne… a další makulatura je na světě. Výsledek je o nějaký ten milimetr lepší, ale stále je to celé špatně. Až tak „přímý“ tisk to tedy nebude. Beznaděj. Moje tiskárna je zmetek, který neposlouchá a dělá si, co chce.

Pak si ale matně vzpomínám, že jsem na téhle tiskárně kdysi vytiskl podací lístek na poštu, který má mít přesné rozměry 133×90 mm, takže nějaká šance tu přeci jen je. Vracím se tedy k počítači. Program pdfTeX mám ve verzi 3.14159265 a jak známo, jeho verze konvergují k číslu Pi a tím k dokonalosti, takže tahle verze by měla být dost dobrá. Tady problém nebude. Přes uživatelské rozhraní CUPS – http://localhost:631/ – nic relevantního nastavit nejde (to jsem zkoušel hned na začátku). Tak jdu hledat konfigurační soubory pro moji tiskárnu a nacházím /etc/cups/ppd/*.ppd. Zaujaly mne řádky:

*ImageableArea A4/A4: "18 36 577 806"
*PaperDimension A4/A4: "595 842"

To první bude asi tisknutelná oblast a to druhé velikost stránky. Sice těm číslům nerozumím, ale vzhledem k tomu, že ImageableArea nezačíná na nule a nejde až k 595×842, značí to nějaké okraje – tady se rýsuje šance na rychlé řešení…

Zatímco 210×297 mm si normální člověk ještě občas pamatuje. Čísla 595×842 působí dost tajemně. V PostScriptu a tím pádem i PPD (PostScript Printer Description) se jako jednotka nepoužívá mm ale typografický bod – a to ve variantě z roku 1984 definované jako 1/72 palce, což je 0,3527 mm. A značí se jako pt, alespoň tedy v PostScriptu (zatímco v TeXu se značí bp, protože pt tam znamená 0,35145980).

…zpět k přízemním starostem s tiskárnou. PPD soubor, který jsem si zkopíroval z /etc/cups/ppd/ tedy upravuji na:

*ImageableArea A4/A4: "0 0 595 842"

Tiskárna samozřejmě nějaká hardwarová omezení má a netiskne až do krajů, ale s tím se bude muset vypořádat sama. Mně jde teď o to, aby moje stránky nenarušoval software před ní – plán je prostý: software si bude myslet, že se dá tisknout všude, a bude tak stránky beze změn posílat rovnou do tiskárny. V CUPS si tedy konfiguruji novou tiskárnu (budu tam mít dvě směřující na stejné URL té jedné fyzické) a místo, abych vybral v nabídce výrobce a model, přikládám svůj upravený PPD soubor.

tisk v přesném měřítku, tisknutelná oblast a okraje

Plán vyšel! Když teď zvolím správnou tiskárnu a v dialogovém okně Vlastnosti tiskárny nastavím nulové okraje (což dřív samo o sobě nestačilo), tak se dokument vytiskne ve správném měřítku.

dialog Vlastnosti tiskárny – Okular, KDE

Pokud do tiskárny pošleme stránku, která má nějaký obsah i v netisknutelné oblasti, nedojde k žádné tragédii – tato část se pouze nevytiskne (viz první obrázek v tomto článku – čára v PDF vedla až k okraji stránky). Tzn. dokument se ořízne, ale nezmenší.

Závěr

Svým způsobem se dá pochopit, že procesy kolem tisku a výchozí nastavení budou optimalizované pro běžné uživatele, kteří dají spíš přednost tomu, aby se jim vytisklo všechno (i za cenu změny měřítka). Nicméně zmenšovat stránku i v případě, že se mimo tisknutelnou oblast nenachází žádný obsah, je přinejmenším nadbytečné. Byť samozřejmě chápu, že zjišťovat, zda nějaký obsah mimo tisknutelnou oblast existuje, je implementačně náročnější, než jen porovnat deklarovanou velikost papíru dokumentu s deklarovanou tisknutelnou oblastí tiskárny.

Tisk v přesném měřítku se hodí v mnoha situacích – pro vyplňování různých formulářů (třeba ty podací lístky na poštu), tisk šablon (air brush atd.) nebo třeba výrobu plošných spojů (metoda přenosu toneru nebo tisk na průhledné fólie). Ve výkresech by sice všechno mělo být okótované a neměly by se z nich rozměry odměřovat pravítkem, ale ani to není důvod tisknout vše o trochu menší. A i když tiskneme „jen“ text, je žádoucí zachovat měřítko – aby znaky a okraje měly ten rozměr, který jsme jim nastavili a ne nějaký náhodný.

P.S. (PostScriptum)

Výše uvedené řešení byla tak trochu střelba od boku, která náhodou vyšla. Specifikace formátu PPD má 240 stránek a otevřel jsem ji až po vyřešení problému. Zde se dozvíme různé další věci, jako že existuje parametr HWMargins.

tisk v přesném měřítku, tisknutelná oblast a okraje

Abychom lépe viděli, co se děje uvnitř tiskového subsystému, je dobré si zvýšit úroveň logování. To lze udělat příkazem cupsctl --debug-logging, ale ten nám ze souboru /etc/cups/cupsd.conf zároveň vymaže všechny komentáře, takže si úroveň raději nastavíme ručně:

LogLevel debug

A restartujeme CUPS, např.:

systemctl restart cups

Logovací soubor /var/log/cups/error_log se nám začne plnit spoustou zajímavých informací. Navzdory svému názvu neobsahuje jen chybové hlášky.

Z logu zjistíme, že náš dokument prochází přes foomatic-rip (raster image processor) a další filtry, konkrétně gstorasterpdftopdf nacházející se v adresáři /usr/lib/cups/filter/. A hlavně tu máme zaznamenané proměnné prodtředí a CLI parametry, kde vidíme mj. parametr fit-to-page. Pozorný čtenář už asi chápe, proč slova vyšlavyřešení výše byla psaná kurzívou… Příběh ještě nekončí a věc je, jako obvykle, složitější, než se na první pohled zdá.

Poznámka: Kromě čtení logů můžeme pomocí Wiresharku odposlouchávat komunikaci mezi CUPS a tiskárnou (pokud jde o síťovou tiskárnu implementující protokol IPP). Wireshark tento protokol umí dekódovat (jde o nadstavbu nad HTTP) a díky tomu z něj můžeme vytáhnout .ps (PostScript) soubory, které odešly do tiskárny, a sledovat i další komunikaci s ní.

Po nahlédnutí do zdrojových kódů CUPS zjistíme, že řetězec fit-to-page se nachází jen v těchto souborech:

test/5.6-lpr.sh
test/5.5-lp.sh
filter/pstops.c
doc/help/options.html
cups/encode.c

A ani jeden z nich nenasvědčuje tomu, že by tuto volbu CUPS doplňoval automaticky. Podezření se tedy přesouvá na aplikaci, která tisk zadala, což je v našem případě Okular (PDF prohlížeč z KDE). Pro jistotu si ho spustíme přes strace, který nám zaloguje systémová volání:

strace -ttfo okular.strace.log -s 4096 okular test-2.pdf

Zadáme tisk a Okular ukončíme. Mimochodem, v CUPS můžeme tiskárnu pozastavit, abychom negenerovali další potištěné papíry (výsledek už známe). V logu okular.strace.log nás bude zajímat systémové volání exec*(), protože předpokládáme, že Okular spouští lpr (CLI rozhraní CUPS). Tohle volání zde skutečně najdeme včetně všech parametrů:

15558 20:49:02.126094 execve("/usr/bin/lpr", ["lpr", "-P", "tiskarna",
  "-#1", "-J", "test-2.pdf", "-o", "media=A4", 
  "-o", "portrait",
  "-o", "sides=one-sided", "-o", "outputorder=normal", "-o", "Collate=True",
  "-o", "page-left=18", "-o", "page-top=36", "-o", "page-right=18",
  "-o", "page-bottom=36", "-o", "fit-to-page", "-o", "number-up=1",
  "-o", "number-up-layout=lrtb", "-o", "job-billing", "-o", "job-priority=50",
  "-o", "job-sheets=none,none", "-r", "/tmp/okular_t21413.ps"],
  0x7ffeffad7e10 /* 63 vars */ <unfinished ...>

Jdeme se tedy podívat na zdrojové kódy Okularu. A hledáme:

$ grep -lr fit-to-page
core/fileprinter.cpp

To je ale nejnovější verze – tu téměř jistě nainstalovanou nemáme, takže nás zajímá spíš historie. V případě gitu ji můžeme prohledat takto:

$ git log --all --oneline -G "fit-to-page"

748884b4c PDF: Implement scaling options for non-rasterized printing
466eb7961 Use QStringLiteral
5a1afc51e Pass down to lpr the printer margins

Mimochodem, v Mercurialu slouží k podobnému prohledávání historie příkaz hg grep.

Nebo včetně časů a celých zpráv:

$ git log --all -G "fit-to-page"

commit 748884b4c74d6636accc29be96065114e42990ba
Author: Michael Weghorn <…>
Date:   Sun Apr 14 21:08:59 2019 -0600

    PDF: Implement scaling options for non-rasterized printing
    
    Summary:
    This adds another 'FilePrinter::printFile' method that
    accepts an additional parameter to specify whether or not to
    do scaling and passes the 'fit-to-page' to CUPS dependent
    on what is specified.
    
    If FilePrinter is used, The PDF generator now passes this
    option depending on the scaling mode that was selected in the
    custom print options widget, which is therefore now enabled
    for non-rasterized printing as well.
    
    Test Plan:
    1) open a PDF document in Okular and open the print dialog
    2) go to the "PDF Options" tab
    3) verify that "Force rasterisation" is disabled, but the
      "Scale mode" combobox is active.
    4) test all the three options available in the "Scale mode"
       combobox do what they say
    5) Make sure the three options still work as expected for
       the "Force rasterisation" case.
    
    Reviewers: #okular, ngraham, sander
    
    Reviewed By: ngraham
    
    Subscribers: aacid, fvogt, okular-devel
    
    Tags: #okular
    
    Differential Revision: https://phabricator.kde.org/D18179

commit 466eb79615ba313ff6ef418177a15a6961fbfb36
Author: Montel Laurent <…>
Date:   Thu Oct 29 13:37:11 2015 +0100

    Use QStringLiteral

commit 5a1afc51e3bbe78cf9af2870ae41bf2eb79e7a64
Author: Albert Astals Cid <…>
Date:   Tue Oct 29 20:44:48 2013 +0100

    Pass down to lpr the printer margins
    
    This makes automagically work the printing on printers with
    hard-margins since the QPrinter dialog margins are initialized to the printer
    hard-margins. If you still want the old and mostly unuseful
    behaviour of not having any margin (and thus your printer not printing things on the borders) you
    can always set the margins to 0 in the dialog
    
    BUGS: 319476
    FIXED-IN: 4.12.0

Změna z roku 2015 zjevně není zajímavá. Relevantní jsou změny z let 2013 a 2019. Verze Okularu, kterou používám, v sobě nezahrnuje změnu z roku 2019. V Kubuntu 20.04 LTS totiž dialog vypadá jinak:

Tiskový dialog v aplikaci Okular v Kubuntu 20.04

než v Kubuntu 18.04 LTS, kde jsem na problém narazil – tam totiž volba „Režim škálování“ vůbec není.

Dle zdrojových kódů se po té změně z roku 2019 volba fit-to-page nepřidává, když vybereme „None;print original size“, což jsem i ověřil pomocí strace v Kubuntu 20.04 LTS. Po změně z roku 2013 se ale volba fit-to-page nastavovala vždy. Dle toho, co píše Albert Astals Cid:

If you still want the old and mostly unuseful behaviour of not having any margin (and thus your printer not printing things on the borders) you can always set the margins to 0 in the dialog

to asi tehdy fungovalo a po nastavení nulových okrajů v dialogu se vytiskla nezmenšená stránka. To by znamenalo, že mezitím došlo k nekompatibilní změně rozhraní CUPS a jeho filtrů (tzn. možná se při nastavení nulových okrajů změna měřítka neaplikovala, zatímco teď ano).

Další možné vysvětlení by bylo, že se v PPD souboru (ovšem to by muselo být jak v tom mém, tak v tom, se kterým to testoval Albert Astals Cid) změnila hodnota ImageableArea případně HWMargins (pokud na to má vliv). Ale dle historie foomatic-db je PPD soubor pro moji tiskárnu stále stejný už od roku 2010. Mimochodem, pokud byste třeba v Debianu nebo Ubuntu hledali PPD soubory pro nenainstalované tiskárny, tak je nenajdete. Místo nich tam máte /usr/lib/cups/driver/openprinting-ppds, což je skript v Pythonu, který v sobě má textovou proměnnou s velmi dlouhým řetězcem (celý ten skript má přes 5 MB) ve formátu Base64, uvnitř kterého jsou zkomprimované všechny PPD soubory. Tohle raději nebudu komentovat. PPD soubory si můžeme vypsat pomocí openprinting list a jeden konkrétní získat pomocí openprinting-ppds cat URI (kde URI začíná openprinting-ppds: a jde o první sloupec z výpisu). Získání jednoho PPD souboru na mém ne úplně pomalém počítači s SSD diskem trvá dva a půl vteřiny. Tím se vysvětluje, proč přidávání nové tiskány přes CUPS není zrovna dvakrát rychlé.

Jaké z toho plyne ponaučení?

  • Části systému by měly být propojené pomocí dobře definovaných rozhranísémanticky verzované.
  • V rámci vývojového procesu je potřeba správně evidovat, které změny jsou opravou chyb a které jsou přidáním nových funkcí. Jen na základě toho pak lze opravy portovat do všech podporovaných verzí.
  • Testování je důležité. Test ověřuje shodu implementace se zadáním (z čehož jaksi plyne, že potřebujeme to zadání… ale o tom zase někdy příště).
  • Opatrně s tzv. automagickým chováním.

Toto patří mezi základní dobré praktiky. A ty jsou nezávislé na programovacím jazyku, paradigmatu či metodice. Dokud si je neosvojíme, nemá smysl doufat, že změna technologie nebo čehokoli jiného za nás vyřeší naše problémy.

Přílohy:

  • test-2.pdf – jednoduchý obrazec pro otestování měřítka tisku (22 422 bajtů) [1589]

Témata: [GNU/Linux] [hardware]

Komentáře čtenářů

Tento článek zatím nikdo nekomentoval

Přidat komentář

reagujete na jiný komentář (zrušit)
jméno nebo přezdívka
název příspěvku
webová stránka, blog
e-mailová adresa
nápověda: možnosti formátování
ochrana proti spamu a špatným trollům

Náhled komentáře