momente şi schiţe de informatică şi matematică
anti point—and—click

Caractere (vechi şi noi), cu PostScript (VIII)

PostScript
2020 jun

Corijări (programare vs. rescriere)

Asupra lui confCat.ps din [1], avem de observat nişte simplificări care ţin nu atât de o eventuală „optimizare”, cât direct de „bunul simţ”. Având în tabloul /Fonts nume de fonturi şi în variabila /key unul dintre cele 1004 nume de caracter, modelam scrierea unui rând de glife (din fiecare font, pentru valoarea curentă key) prin:

    id0  % idx:=0 (/idx servea pentru calculul abscisei glifei următoare celei curente)
    Fonts {  % scrie pe un rând glifele din cele 8 fonturi, pentru 'key'
        findfont 24 scalefont setfont
        key glyphshow
        nextpos id1  % avansează 'currentpoint' la abscisa 50*(idx+1) şi face idx:=idx+1
    } forall

/nextpos ne calcula aceleaşi valori (50, 100, 150, ..., 350 şi 400), fixând prin rmoveto poziţia de scriere pe rândul curent a următoarei glife – pentru fiecare dintre cele 1004 rânduri ale tabelului rezultat prin varierea lui key.

Calculul repetat al unor valori care de fapt sunt constante este fără îndoială, un defect de programare impardonabil; în cazul de faţă, scuza (sau poate, adevărata greşală) ar fi aceasta: n-am „programat” direct confCat.ps, ci mai degrabă am preluat şi „rescris” programul anterior glyphCat.ps (fără a sesiza că în noul context, chiar nu mai este cazul de a folosi indexarea prin /id0 şi /id1).

Pentru a evita defectul de programare semnalat mai sus, cel mai simplu este să definim de la bun început /Fonts ca „tablou de tablouri” – fiecare subtablou conţinând numele unui font şi abscisa coloanei pe care trebuie scrise glifele acestuia:

/tab {50 mul} bind def  % <n> tab (abscisa coloanei n este n*50)
/Fonts [[/AvantGarde-Book 0 tab] [/Bookman-Light 1 tab] [/Courier 2 tab] 
        [/Helvetica 3 tab] [/NewCenturySchlbk-Roman 4 tab] [/Palatino-Roman 5 tab]
        [/Times-Roman 6 tab] [/ZapfChancery-MediumItalic 7 tab]] def
/tab9 8 tab 10 sub def  % coloana numelor de caracter are abscisa 8*50-10

Obs. Întâlnind o definiţie de tablou care angajează şi anumite calcule de valori, interpretorul va face imediat calculele indicate şi va salva rezultatele acestora, drept componente ale tabloului; de exemplu, nu se va salva "[/Courier 2 tab]", ci "[/Courier 100]" – încât /tab nu va mai fi pusă în execuţie când se va invoca ulterior /Fonts.

Acum nu vom mai avea nevoie de /id0, /id1 şi nici de /nextpos (şi le putem elimina din confCat.ps); avem de modificat doar procedura /writeGlyphs:

/writeGlyphs {  % pe stivă: un nume de caracter din tabloul 'Keys'
    /key exch def
    18 newLine
    /ypos currentpoint exch pop def  % ordonata este constantă, pe rândul curent
    Fonts {  % scrie pe un rând glifele din cele 8 fonturi, pentru 'key'
        aload pop  % în stivă: numele de font şi abscisa coloanei asociate lui
        ypos moveto
        findfont 24 scalefont setfont
        key glyphshow  % scrie glifa la abscisa şi ordonata indicate
    } forall  % pentru toate sub-tablourile din 'Fonts'
    fontEntry setfont
    tab9 ypos moveto  % scrie pe ultima coloană, numele de caracter din 'key'
    key 20 string cvs show
    ypos neg 700 lt  % trece la un nou rând (dacă încape), sau la o nouă pagină
    {18 newLine} {showpage newPage} ifelse    
} bind def

De observat că acum currentpoint este invocat o singură dată (în /ypos), pentru a obţine ordonata rândului curent (pe când în [1], currentpoint se repeta – prin /nextpos – pentru fiecare glifă a rândului şi mai apărea explicit în final, pentru a decide trecerea la un nou rând de glife sau la o nouă pagină).

Obţinem fişierul PDF la fel ca în [1] (folosind ps2pdf cu opţiunile "-d" NOSAFER, PDFSETTINGS=/prepress şi EmbedAllFonts=true) şi îl redăm aici pentru motivul că acum avem în prima coloană /AvantGarde-Book (în [1] alesesem cam neinspirat, /AvantGarde-Demi):

Fişierul PDF obţinut măsoară ceva mai puţin şi rezultă în ceva mai puţin timp, faţă de [1] – ceea ce înseamnă că „reparaţia” defectului de programare semnalat aici la început este importantă.

docerpro | Prev |