font-cft.lua /size: 16 Kb    last modification: 2023-12-21 09:44
1if not modules then modules = { } end modules ['font-cft'] = {
2    version   = 1.001,
3    comment   = "companion to font-ini.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
9-- context font tables (needs updating, only okay for mkiv)
10--
11-- todo: extra:
12--
13-- extra_space       => space.extra
14-- space             => space.width
15-- space_stretch     => space.stretch
16-- space_shrink      => space.shrink
17--
18-- We do keep the x-height, extra_space, space_shrink and space_stretch
19-- around as these are low level official names.
20--
21-- Needs to be checked and updated.
22
23local type, tonumber = type, tonumber
24
25local fonts  = fonts or { }
26local tables = fonts.tables or { }
27fonts.tables = tables
28
29local data   = utilities.storage.allocate()
30tables.data  = data
31
32do
33
34    local t_units     = "<units>"
35    local t_unicode   = "<unicode>"
36    local t_unispec   = "<unispec>"      -- t_unicode | { t_unicode }
37    local t_index     = "<index>"
38    local t_cardinal  = "<cardinal>"
39    local t_integer   = "<integer>"
40    local t_float     = "<float>"
41    local t_boolean   = "<boolean>"
42    local t_string    = "<string>"
43    local t_array     = "<array>"
44    local t_hash      = "<hash>"
45    local t_scaled    = "<scaled>"
46    local t_keyword   = "<keyword>"
47    local t_scale     = "<scale>"       -- 1000 based tex scale
48    local t_value     = "<value>"       -- number, string, boolean
49    local t_function  = "<function>"
50
51    data.types = {
52        ["units"]     = "<units>",
53        ["unicode"]   = "<unicode>",
54        ["unispec"]   = "<unispec>" ,     -- t_unicode | { t_unicode }
55        ["index"]     = "<index>",
56        ["cardinal"]  = "<cardinal>",
57        ["integer"]   = "<integer>",
58        ["float"]     = "<float>",
59        ["boolean"]   = "<boolean>",
60        ["string"]    = "<string>",
61        ["array"]     = "<array>",
62        ["hash"]      = "<hash>",
63        ["scaled"]    = "<scaled>",
64        ["keyword"]   = "<keyword>",
65        ["scale"]     = "<scale>",       -- 1000 based tex scale
66        ["value"]     = "<value>",       -- number, string, boolean
67        ["function"]  = "<function>",
68    }
69
70    local boundingbox = {
71        t_units,
72        t_units,
73        t_units,
74        t_units
75    }
76
77    local mathvariants = {
78        t_array
79    }
80
81    local mathparts = {
82        {
83            advance  = t_units,
84            ["end"]  = t_units,
85            extender = t_units,
86            glyph    = t_unicode,
87            start    = t_units,
88        }
89    }
90
91    local mathkerns = {
92        {
93            height = t_units,
94            kern   = t_units,
95        },
96    }
97
98    local mathparts = {
99        {
100            advance  = t_scaled,
101            ["end"]  = t_scaled,
102            extender = t_scaled,
103            glyph    = t_unicode,
104            start    = t_scaled,
105        }
106    }
107
108    local mathkerns = {
109        {
110            height = t_scaled,
111            kern   = t_scaled,
112        },
113    }
114
115    local vfcommands = {
116        { t_keyword, t_value },
117    }
118
119    local description = {
120        width       = t_units,
121        height      = t_units,
122        depth       = t_units,
123        italic      = t_units,
124        index       = t_index,
125        boundingbox = boundingbox,
126        unicode     = t_unispec,
127        math        = {
128            accent    = t_units,
129            hvariants = mathvariants,
130            vvariants = mathvariants,
131            hparts    = mathparts,
132            vparts    = mathparts,
133            kerns     = {
134                bottomright = mathkerns,
135                bottomleft  = mathkerns,
136                topright    = mathkerns,
137                topleft     = mathkerns,
138            }
139        },
140    }
141
142    local character = {
143        width            = t_scaled,
144        height           = t_scaled,
145        depth            = t_scaled,
146        italic           = t_scaled,
147        index            = t_index,
148        expansion_factor = t_scaled,
149        left_protruding  = t_scaled,
150        right_protruding = t_scaled,
151        tounicode        = t_string,
152        unicode          = t_unispec,
153        commands         = vfcommands,
154        accent           = t_scaled,
155        hvariants        = mathvariants,
156        vvariants        = mathvariants,
157        hparts           = math_parts,
158        vparts           = math_parts,
159        kerns            = {
160            bottomright = math_kerns,
161            bottomleft  = math_kerns,
162            topright    = math_kerns,
163            topleft     = math_kerns,
164        },
165        ligatures        = t_hash,
166        kerns            = t_hash,
167        next             = t_array,
168    }
169
170    data.original = {
171        cache_uuid     =  t_string,
172        cache_version  =  t_float,
173        compacted      =  t_boolean,
174        creator        =  t_string,
175        descriptions   =  { description },
176        format         =  t_string,
177        goodies        =  t_hash,
178        metadata       =  {
179            ascender      = t_units,
180            averagewidth  = t_units,
181            capheight     = t_units,
182            descender     = t_units,
183            family        = t_string,
184            familyname    = t_string,
185            fontname      = t_string,
186            fullname      = t_string,
187            italicangle   = t_float,
188            monospaced    = t_boolean,
189            panoseweight  = t_string,
190            panosewidth   = t_string,
191            pfmweight     = t_units,
192            pfmwidth      = t_units,
193            subfamily     = t_string,
194            subfamilyname = t_string,
195            subfontindex  = t_index,
196            units         = t_cardinal,
197            version       = t_string,
198            weight        = t_string,
199            width         = t_string,
200            xheight       = t_units,
201        },
202        private        = t_unicode,
203        properties     = {
204            hascolor      = t_boolean,
205            hasitalics    = t_boolean,
206            hasspacekerns = t_boolean,
207        },
208        resources      = {
209            duplicates    = t_hash,
210            features      = {
211                gpos = t_hash,
212                gsub = t_hash,
213            },
214            filename      = t_string,
215            markclasses   = t_hash,
216            marks         = t_hash,
217            marksets      = t_hash,
218            mathconstants = t_hash,
219            private       = t_cardinal,
220            sequences     = t_array,
221         -- unicodes      = t_hash,
222            version       = t_string,
223        },
224        size         = t_cardinal,
225     -- tables       = t_array,
226        tableversion = t_float,
227        time         = t_cardinal,
228    }
229
230    data.scaled = {
231        properties = {
232            encodingbytes    = t_cardinal, -- not in lmtx
233            embedding        = t_cardinal, -- ?
234            cidinfo          = t_hash,
235            format           = t_string,
236            fontname         = t_string,
237            fullname         = t_string,
238            filename         = t_string,
239            psname           = t_string,
240            name             = t_string,
241            virtualized      = t_boolean, -- not in lmtx
242            hasitalics       = t_boolean,
243            autoitalicamount = t_float,
244            nostackmath      = t_boolean,
245            mode             = t_string,
246            hasmath          = t_boolean,
247            mathitalics      = t_boolean,
248            textitalics      = t_boolean,
249            finalized        = t_boolean,
250            effect = {
251                effect  = t_cardinal,
252                width   = t_float,
253                factor  = t_float,
254                hfactor = t_float,
255                vfactor = t_float,
256                wdelta  = t_float,
257                hdelta  = t_float,
258                ddelta  = t_float,
259            }
260        },
261        parameters = {
262            mathsize               = t_cardinal,
263            scriptpercentage       = t_float,
264            scriptscriptpercentage = t_float,
265            units                  = t_cardinal,
266            designsize             = t_scaled,
267            expansion              = {
268                stretch = t_scale,
269                shrink  = t_scale,
270                step    = t_scale,
271                auto    = t_boolean,
272            },
273            protrusion             = {
274                auto = t_boolean,
275            },
276            slantfactor   = t_float,
277            extendfactor  = t_float,
278            mode          = t_cardinal,
279            width         = t_scale,
280            factor        = t_float,
281            hfactor       = t_float,
282            vfactor       = t_float,
283            size          = t_scaled,
284            units         = t_scaled,
285            scaledpoints  = t_scaled,
286            slantperpoint = t_scaled,
287            xheight       = t_scaled,
288            quad          = t_scaled,
289            ascender      = t_scaled,
290            descender     = t_scaled,
291            spacing       = {
292                width   = t_scaled,
293                stretch = t_scaled,
294                shrink  = t_scaled,
295                extra   = t_scaled,
296            },
297         -- synonyms      = {
298         --     space         = "spacing.width",
299         --     spacestretch  = "spacing.stretch",
300         --     spaceshrink   = "spacing.shrink",
301         --     extraspace    = "spacing.extra",
302         --     x_height      = "xheight",
303         --     space_stretch = "spacing.stretch",
304         --     space_shrink  = "spacing.shrink",
305         --     extra_space   = "spacing.extra",
306         --     em            = "quad",
307         --     ex            = "xheight",
308         --     slant         = "slantperpoint",
309         -- },
310        },
311        descriptions   =  { description },
312        characters     =  { character },
313    }
314
315    data.goodies = {
316        -- preamble
317        name      = t_string,
318        version   = t_string,
319        comment   = t_string,
320        author    = t_string,
321        copyright = t_string,
322        --
323        remapping = {
324            tounicode = t_boolean,
325            unicodes = {
326                [t_string] = t_index,
327            },
328        },
329        mathematics = {
330            mapfiles = {
331                t_string,
332            },
333            virtuals = {
334                [t_string] = {
335                    {
336                        name       = t_string,
337                        features   = t_hash,
338                        main       = t_boolean,
339                        extension  = t_boolean,
340                        vector     = t_string,
341                        skewchar   = t_unicode,
342                        parameters = t_boolean,
343                    },
344                },
345            },
346            italics = {
347                [t_string] = {
348                    defaultfactor = t_float,
349                    disableengine = t_boolean,
350                    corrections   = {
351                        [t_unicode] = t_float,
352                    }
353                },
354            },
355            kerns = {
356                [t_unicode] = {
357                    bottomright = math_kerns,
358                    topright    = math_kerns,
359                    bottomleft  = math_kerns,
360                    topleft     = math_kerns,
361                },
362            },
363            alternates = {
364                [t_string] = {
365                    feature = t_hash,
366                    value   = t_float,
367                    comment = t_string,
368                },
369            },
370            variables = {
371                [t_string] = t_value,
372            },
373            parameters = {
374                [t_string] = t_value,
375                [t_string] = t_function,
376            },
377            dimensions = {
378                [t_string] = {
379                    [t_unicode] = {
380                        width   = t_units,
381                        height  = t_units,
382                        depth   = t_units,
383                        xoffset = t_units,
384                        yoffset = t_units,
385                    },
386                },
387            },
388        },
389        filenames = {
390            [t_string] = {
391                t_string,
392            },
393        },
394        compositions = {
395            [t_string] = {
396                dy          = t_unit,
397                dx          = t_unit,
398                [t_unicode] = {
399                    dy = t_unit
400                },
401                [t_unicode] = {
402                    anchors = {
403                        top = {
404                            x = t_unit,
405                            y = t_unit,
406                        },
407                        bottom = {
408                            x = t_unit,
409                            y = t_unit,
410                        },
411                    },
412                },
413            },
414        },
415        postprocessors = {
416            [t_string] = t_function,
417        },
418        designsizes = {
419            [t_string] = {
420                [t_string] = t_string,
421                default    = t_string
422            },
423        },
424        featuresets = {
425            [t_string] = {
426                t_string,
427                [t_keyword] = t_value
428            },
429        },
430        solutions = {
431            experimental = {
432                less = { t_string },
433                more = { t_string },
434            },
435        },
436        stylistics = {
437            [t_string] = t_string,
438            [t_string] = t_string,
439        },
440        colorschemes = {
441            default = {
442                { t_string },
443            }
444        },
445        files = {
446            name = t_string,
447            list = {
448                [t_string] = {
449                    name   = t_string,
450                    weight = t_string,
451                    style  = t_string,
452                    width  = t_string,
453                },
454            },
455        },
456        typefaces = {
457            [t_string] = {
458                shortcut     = t_string,
459                shape        = t_string,
460                fontname     = t_string,
461                normalweight = t_string,
462                boldweight   = t_string,
463                width        = t_string,
464                size         = t_string,
465                features     = t_string,
466            },
467        },
468    }
469
470end
471
472-- compatibility (for now)
473
474if fonts.constructors then
475    fonts.constructors.keys = data.scaled
476end
477
478-- handy helpers
479
480local report = logs.reporter("fonts")
481
482function tables.savefont(specification)
483    local method   = specification.method
484    local filename = specification.filename
485    local fontname = specification.fontname
486    if not method or method ~= "original" then
487        method = "scaled"
488    end
489    if not filename or filename == "" then
490        filename = "temp-font-" .. method .. ".lua"
491    else
492        filename = file.addsuffix(filename,"lua")
493    end
494    if not fontname or fontname == "" then
495        fontname = true
496    end
497    if fontname == true then
498        report("saving current font in %a",filename)
499    elseif tonumber(fontname) then
500        report("saving font id %a in %a",fontname,filename)
501        fontname = tonumber(fontname)
502    else
503        report("saving font %a in %a",fontname,filename)
504        tfmdata = fonts.definers.define {
505            name = fontname
506        }
507    end
508    if tfmdata then
509        tfmdata = fonts.hashes.identifiers[tfmdata]
510    end
511    if not tfmdata then
512        -- bad news
513    elseif method == "original" then
514        tfmdata = tfmdata.shared and tfmdata.shared.rawdata
515    else
516        tfmdata = {
517            characters    = tfmdata.characters,
518            parameters    = tfmdata.parameters,
519            properties    = tfmdata.properties,
520            specification = tfmdata.specification,
521        }
522    end
523    if tfmdata then
524        table.save(filename,tfmdata)
525    else
526     -- os.remove(filename)
527        report("saving font failed")
528    end
529end
530
531function tables.saveoriginal(filename,specification)
532    local tfmdata = get(specification)
533    if tfmdata then
534        local rawdata = tfmdata.shared and tfmdata.shared.rawdata
535        if rawdata then
536            table.save(filename,rawdata)
537        end
538    end
539end
540
541if context then
542
543    interfaces.implement {
544        name      = "savefont",
545        actions   = tables.savefont,
546        arguments = {
547            {
548                { "filename" },
549                { "fontname" },
550                { "method" },
551            }
552        },
553    }
554
555end
556
557