s-fonts-shapes.lua /size: 10 Kb    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules['s-fonts-shapes'] = {
2    version   = 1.001,
3    comment   = "companion to s-fonts-shapes.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9moduledata.fonts        = moduledata.fonts        or { }
10moduledata.fonts.shapes = moduledata.fonts.shapes or { }
11
12local fontdata = fonts.hashes.identifiers
13
14local context = context
15local NC, NR = context.NC, context.NR
16local space, dontleavehmode, glyph, getvalue = context.space, context.dontleavehmode, context.glyph, context.getvalue
17local formatters = string.formatters
18
19function char(id,k)
20    dontleavehmode()
21    glyph(id,k)
22end
23
24local function special(id,specials)
25    if specials and #specials > 1 then
26        context("%s:",specials[1])
27        if #specials > 5 then
28            space() char(id,specials[2])
29            space() char(id,specials[3])
30            space() context("...")
31            space() char(id,specials[#specials-1])
32            space() char(id,specials[#specials])
33        else
34            for i=2,#specials do
35                space() char(id,specials[i])
36            end
37        end
38    end
39end
40
41function moduledata.fonts.shapes.showlist(specification) -- todo: ranges
42    specification = interfaces.checkedspecification(specification)
43    local id, cs = fonts.definers.internal(specification,"<module:fonts:shapes:font>")
44    local chrs = fontdata[id].characters
45    context.begingroup()
46    context.tt()
47    context.starttabulate { "|l|c|c|c|c|l|l|" }
48        context.FL()
49            NC() context.bold("unicode")
50            NC() context.bold("glyph")
51            NC() context.bold("shape")
52            NC() context.bold("lower")
53            NC() context.bold("upper")
54            NC() context.bold("specials")
55            NC() context.bold("description")
56            NC() NR()
57        context.TL()
58        for k, v in next, characters.data do
59            if chrs[k] then
60                NC() context("0x%05X",k)
61                NC() char(id,k)
62                NC() char(id,v.shcode)
63                NC() char(id,v.lccode or k)
64                NC() char(id,v.uccode or k)
65                NC() special(id,v.specials)
66                NC() context.tx(v.description)
67                NC() NR()
68            end
69        end
70    context.stoptabulate()
71    context.endgroup()
72end
73
74local descriptions = nil
75local characters   = nil
76
77
78local function showglyphshape(specification)
79    --
80    local specification = interfaces.checkedspecification(specification)
81    local id, cs        = fonts.definers.internal(specification,"<module:fonts:shapes:font>")
82    local tfmdata       = fontdata[id]
83    local characters    = tfmdata.characters
84    local descriptions  = tfmdata.descriptions
85    local parameters    = tfmdata.parameters
86    local anchors       = fonts.helpers.collectanchors(tfmdata)
87
88    local function showonecharacter(unicode)
89        local c = characters  [unicode]
90        local d = descriptions[unicode]
91        if c and d then
92            local factor = (parameters.size/parameters.units)*((7200/7227)/65536)
93            local llx, lly, urx, ury = unpack(d.boundingbox)
94            llx, lly, urx, ury = llx*factor, lly*factor, urx*factor, ury*factor
95            local width = (d.width or 0)*factor
96            context.start()
97            context.dontleavehmode()
98            context.obeyMPboxdepth()
99            context.startMPcode()
100            context("numeric lw ; lw := .125bp ;")
101            context("pickup pencircle scaled lw ;")
102            if width < 0.01 then
103                -- catches zero width marks
104                context('picture p ; p := textext.drt("\\hskip5sp\\getuvalue{%s}\\gray\\char%s"); draw p ;',cs,unicode)
105            else
106                context('picture p ; p := textext.drt("\\getuvalue{%s}\\gray\\char%s"); draw p ;',cs,unicode)
107            end
108            context('draw (%s,%s)--(%s,%s)--(%s,%s)--(%s,%s)--cycle withcolor green ;',llx,lly,urx,lly,urx,ury,llx,ury)
109            context('draw (%s,%s)--(%s,%s) withcolor green ;',llx,0,urx,0)
110            context('draw boundingbox p withcolor .2white withpen pencircle scaled .065bp ;')
111            context("defaultscale := 0.05 ; ")
112            -- inefficient but non critical
113            local slant = {
114                function(v,dx,dy,txt,xsign,ysign,loc,labloc)
115                    local n = #v
116                    if n > 0 then
117                        local l = { }
118                        for i=1,n do
119                            local c = v[i]
120                            local h = c.height or 0
121                            local k = c.kern or 0
122                            l[i] = formatters["((%s,%s) shifted (%s,%s))"](xsign*k*factor,ysign*h*factor,dx,dy)
123                        end
124                        context("draw ((%s,%s) shifted (%s,%s))--%s dashed (evenly scaled 1/16) withcolor .5white;", xsign*v[1].kern*factor,lly,dx,dy,l[1])
125                        context("draw laddered (%..t) withcolor .5white ;",l) -- why not "--"
126                        context("draw ((%s,%s) shifted (%s,%s))--%s dashed (evenly scaled 1/16) withcolor .5white;", xsign*v[#v].kern*factor,ury,dx,dy,l[#l])
127                        for i=1,n do
128                            context("draw %s withcolor blue withpen pencircle scaled 2lw ;",l[i])
129                        end
130                    end
131                end,
132                function(v,dx,dy,txt,xsign,ysign,loc,labloc)
133                    local n = #v
134                    if n > 0 then
135                        local l = { }
136                        for i=1,n do
137                            local c = v[i]
138                            local h = c.height or 0
139                            local k = c.kern or 0
140                            l[i] = formatters["((%s,%s) shifted (%s,%s))"](xsign*k*factor,ysign*h*factor,dx,dy)
141                        end
142                        if loc == "top" then
143                            context('label.%s("\\type{%s}",%s shifted (0,-1bp)) ;',loc,txt,l[n])
144                        else
145                            context('label.%s("\\type{%s}",%s shifted (0,2bp)) ;',loc,txt,l[1])
146                        end
147                        for i=1,n do
148                            local c = v[i]
149                            local h = c.height or 0
150                            local k = c.kern or 0
151                            context('label.top("(%s,%s)",%s shifted (0,-2bp));',k,h,l[i])
152                        end
153                    end
154                end,
155            }
156            --
157            local math = d.math
158            if math then
159                local kerns = math.kerns
160                if kerns then
161                    for i=1,#slant do
162                        local s = slant[i]
163                        for k, v in next, kerns do
164                            if k == "topright" then
165                             -- s(v,width+italic,0,k,1,1,"top","ulft")
166                                s(v,width,0,k,1,1,"top","ulft")
167                            elseif k == "bottomright" then
168                                s(v,width,0,k,1,1,"bot","lrt")
169                            elseif k == "topleft" then
170                                s(v,0,0,k,-1,1,"top","ulft")
171                            elseif k == "bottomleft" then
172                                s(v,0,0,k,-1,1,"bot","lrt")
173                            end
174                        end
175                    end
176                end
177                local accent = math.accent
178                if accent and accent ~= 0 then
179                    local a = accent * factor
180                    context('draw (%s,%s+1bp)--(%s,%s-1bp) withcolor blue;',a,ury,a,ury)
181                    context('label.bot("\\type{%s}",(%s,%s+1bp));',"accent",a,ury)
182                    context('label.top("%s",(%s,%s-1bp));',math.accent,a,ury)
183                end
184            end
185            --
186            local anchordata = anchors[unicode]
187            if anchordata then
188                local function show(txt,list)
189                    if list then
190                        for i=1,#list do
191                            local li = list[i]
192                            local x, y = li[1], li[2]
193                            local xx, yy = x*factor, y*factor
194                            context("draw (%s,%s) withcolor blue withpen pencircle scaled 2lw ;",xx,yy)
195                            context('label.top("\\infofont %s",(%s,%s-2.75bp)) ;',txt .. i,xx,yy)
196                            context('label.bot("\\infofont (%s,%s)",(%s,%s+2.75bp)) ;',x,y,xx,yy)
197                        end
198                    end
199                end
200                --
201                show("b",anchordata.base)
202                show("m",anchordata.mark)
203                show("l",anchordata.ligature)
204                show("e",anchordata.entry)
205                show("x",anchordata.exit)
206            end
207            --
208            local italic = d.italic
209            if italic and italic ~= 0 then
210                local i = italic * factor
211                context('draw (%s,%s-1bp)--(%s,%s-0.5bp) withcolor blue ;',width,ury,width,ury)
212                context('draw (%s,%s-1bp)--(%s,%s-0.5bp) withcolor blue ;',width+i,ury,width+i,ury)
213                context('draw (%s,%s-1bp)--(%s,%s-1bp) withcolor blue ;',width,ury,width+i,ury)
214                context('label.lft("\\type{%s}",(%s+2bp,%s-1bp));',"italic",width,ury)
215                context('label.rt("%s",(%s-2bp,%s-1bp));',italic,width+i,ury)
216            end
217            context('draw origin withcolor red withpen pencircle scaled 2lw;')
218            context("setbounds currentpicture to boundingbox currentpicture enlarged 1bp ;")
219            context("currentpicture := currentpicture scaled 8 ;")
220            context.stopMPcode()
221            context.stop()
222        end
223    end
224
225    local unicode = tonumber(specification.character) or
226                    fonts.helpers.nametoslot(specification.character)
227
228    if unicode then
229        showonecharacter(unicode)
230    else
231        context.modulefontsstartshowglyphshapes()
232        for unicode, description in fonts.iterators.descriptions(tfmdata) do
233            if unicode >= 0x110000 then
234                break
235            end
236            context.modulefontsstartshowglyphshape(unicode,description.name or "",description.index or 0)
237                showonecharacter(unicode)
238            context.modulefontsstopshowglyphshape()
239        end
240        context.modulefontsstopshowglyphshapes()
241    end
242
243end
244
245moduledata.fonts.shapes.showglyphshape    = showglyphshape
246moduledata.fonts.shapes.showallglypshapes = showglyphshape
247
248function moduledata.fonts.shapes.showlastglyphshapefield(unicode,name)
249    if not descriptions then
250        -- bad news
251    elseif name == "unicode" then
252        context("U+%05X",descriptions.unicode)
253    else
254        local d = descriptions[name]
255        if d then
256            context(d)
257        end
258    end
259end
260