1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
if not modules then modules = { } end modules ['font-phb-imp-binary'] = {
version = 1.000, -- 2016.10.10,
comment = "companion to font-txt.mkiv",
author = "Hans Hagen",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files",
}
-- The hb library comes in versions and the one I tested in 2016 was part of the inkscape
-- suite. In principle one can have incompatibilities due to updates but that is the nature
-- of a library. When a library ie expected one has better use the system version, if only
-- to make sure that different programs behave the same.
--
-- The main reason for testing this approach was that when Idris was working on his fonts,
-- we wanted to know how different shapers deal with it and the hb command line program
-- could provide uniscribe output. For the context shaper uniscribe is the reference, also
-- because Idris started out with Volt a decade ago.
--
-- This file uses the indirect approach by calling the executable. This file uses context
-- features and is not generic.
local next, tonumber, pcall = next, tonumber, pcall
local concat = table.concat
local reverse = table.reverse
local formatters = string.formatters
local removefile = os.remove
local resultof = os.resultof
local savedata = io.savedata
local report = utilities.hb.report or print
local packtoutf8 = utilities.hb.helpers.packtoutf8
-- output : [index=cluster@x_offset,y_offset+x_advance,y_advance|...]
-- result : { index, cluster, x_offset, y_offset, x_advance, y_advance }
local P, Ct, Cc = lpeg.P, lpeg.Ct, lpeg.Cc
local lpegmatch = lpeg.match
local zero = Cc(0)
local number = lpeg.patterns.integer / tonumber + zero
local index = lpeg.patterns.cardinal / tonumber
local cluster = index
local offset = (P("@") * number * (P(",") * number + zero)) + zero * zero
local advance = (P("+") * number * (P(",") * number + zero)) + zero * zero
local glyph = Ct(index * P("=") * cluster * offset * advance)
local pattern = Ct(P("[") * (glyph * P("|")^-1)^0 * P("]"))
local shapers = {
native = "ot,uniscribe,fallback",
uniscribe = "uniscribe,ot,fallback",
fallback = "fallback"
}
local runner = sandbox.registerrunner {
method = "resultof",
name = "harfbuzz",
-- program = {
-- windows = "hb-shape.exe",
-- unix = "hb-shape"
-- },
program = "hb-shape",
checkers = {
shaper = "string",
features = "string",
script = "string",
language = "string",
direction = "string",
textfile = "writable",
fontfile = "readable",
},
template = string.longtostring [[
--shaper=%shaper%
--output-format=text
--no-glyph-names
--features="%features%"
--script=%script%
--language=%language%
--direction=%direction%
--text-file=%textfile%
--font-file=%fontfile%
]],
}
local tempfile = "font-phb.tmp"
local reported = false
function utilities.hb.methods.binary(font,data,rlmode,text,leading,trailing)
if runner then
savedata(tempfile,packtoutf8(text,leading,trailing))
local result = runner {
shaper = shapers[data.shaper] or shapers.native,
features = data.features,
script = data.script or "dflt",
language = data.language or "dflt",
direction = rlmode < 0 and "rtl" or "ltr",
textfile = tempfile,
fontfile = data.filename,
}
removefile(tempfile)
if result then
-- return jsontolua(result)
result = lpegmatch(pattern,result) -- { index cluster xo yo xa ya }
if rlmode < 0 then
return reverse(result) -- we can avoid this
else
return result
end
end
elseif reported then
report("no runner available")
reported = true
end
end
|