@@ -4,10 +4,58 @@ local icu = require("justenoughicu")
44
55local lastshaper
66
7+ local bits = require (" core.parserbits" )
8+ local lpeg = require (" lpeg" )
9+ local Ct , Cg , P = lpeg .Ct , lpeg .Cg , lpeg .P
10+ local adjust_metric = P (" ex-height" ) + P (" cap-height" )
11+ local adjustment = Ct (Cg (bits .number , " amount" )^- 1 * bits .ws * Cg (adjust_metric , " unit" ))
12+
13+ local function measureFontAdjustment (metric )
14+ if metric == " ex-height" then
15+ -- Uses the height of lowercase letters.
16+ -- This is used to normalize lowercase letters across fonts.
17+ -- The height of the lowercase letter "x" is used as the reference.
18+ -- Another option would be to use the OS/2 font table sxHeight value when available.
19+ return SILE .shaper :measureChar (" x" ).height
20+ end
21+ if metric == " cap-height" then
22+ -- Uses the the height of uppercase letters.
23+ -- This is used to normalize uppercase letters across fonts.
24+ -- The height of the uppercase letter "H" is used as the reference.
25+ -- Another option would be to use the OS/2 font table sCapHeight value when available.
26+ return SILE .shaper :measureChar (" H" ).height
27+ end
28+ SU .error (" Unknown font adjust metric " .. metric )
29+ end
30+
31+ local function adjustedFontSize (options )
32+ local adjust = options .adjust
33+ local parsed = adjustment :match (adjust )
34+ if not parsed then
35+ SU .error (" Couldn't parse font adjust value " .. adjust )
36+ end
37+ local baseOpts = pl .tablex .copy (options ) -- shallow copy
38+ baseOpts .adjust = nil -- cancel for target font size calculation
39+ local currentMeasure = measureFontAdjustment (parsed .unit )
40+ local ratio = parsed .amount or 1
41+ local newMeasure
42+ -- Apply the target font size to measure the new font
43+ SILE .call (" font" , baseOpts , function ()
44+ newMeasure = measureFontAdjustment (parsed .unit )
45+ end )
46+ return SILE .settings :get (" font.size" ) * ratio * (currentMeasure / newMeasure )
47+ end
48+
749SILE .registerCommand (" font" , function (options , content )
850 if SU .ast .hasContent (content ) then
951 SILE .settings :pushState ()
1052 end
53+ if options .adjust then
54+ if options .size then
55+ SU .error (" Can't specify both 'size' and 'adjust' in a \\ font command" )
56+ end
57+ SILE .settings :set (" font.size" , adjustedFontSize (options ))
58+ end
1159 if options .filename then
1260 SILE .settings :set (" font.filename" , options .filename )
1361 end
0 commit comments