@@ -941,6 +941,102 @@ fonts.constructors.features.otf.register {
941941 },
942942}
943943
944+ -- Protrusion for HarfBuzz fonts, based on the `node` feature in fonts-ext
945+ local protrusion_setups = fonts .protrusions .setups
946+
947+ local function initializeprotrusion (tfmdata , value )
948+ local setup = protrusion_setups [value ]
949+ if not setup then
950+ if value then
951+ texio .write_nl (' term and log' , string.format (' unknown protrusion setup %q ignored' , value ))
952+ end
953+ return
954+ end
955+ local lookup = {}
956+ local name_to_index = tfmdata .resources .unicodes
957+ for k , v in next , setup do
958+ local ktype = type (k )
959+ if ktype == ' number' then
960+ lookup [k ] = v
961+ elseif ktype == ' string' then
962+ local index = name_to_index [k ]
963+ if index then
964+ lookup [index ] = v
965+ end
966+ end
967+ end
968+ local quad = tfmdata .parameters .quad
969+ local factor = setup .factor or 1
970+ if quad ~= 0 then
971+ factor = factor * 1000 / quad
972+ end
973+ local left = factor * (setup .left or 1 )
974+ local right = factor * (setup .right or 1 )
975+ for i , chr in next , tfmdata .characters do
976+ local width = chr .width or 0
977+ local v , pl , pr = lookup [i ], nil , nil
978+ if v then
979+ pl , pr = v [1 ], v [2 ]
980+ end
981+ if pl and pl ~= 0 then chr .left_protruding = left * pl * width end
982+ if pr and pr ~= 0 then chr .right_protruding = right * pr * width end
983+ end
984+ end
985+
986+ fonts .constructors .features .otf .register {
987+ name = " protrusion" ,
988+ description = " shift characters into the left and or right margin" ,
989+ initializers = {
990+ plug = initializeprotrusion ,
991+ }
992+ }
993+
994+ -- Expansion for HarfBuzz fonts, based on the `node` feature in fonts-ext
995+ local expansion_setups = fonts .expansions .setups
996+
997+ local function initializeexpansion (tfmdata , value )
998+ local setup = expansion_setups [value ]
999+ if not setup then
1000+ if value then
1001+ texio .write_nl (' term and log' , string.format (' unknown expansion setup %q ignored' , value ))
1002+ end
1003+ return
1004+ end
1005+ local lookup = {}
1006+ local name_to_index = tfmdata .resources .unicodes
1007+ for k , v in next , setup do
1008+ local ktype = type (k )
1009+ if ktype == ' number' then
1010+ lookup [k ] = v
1011+ elseif ktype == ' string' then
1012+ local index = name_to_index [k ]
1013+ if index then
1014+ lookup [index ] = v
1015+ end
1016+ end
1017+ end
1018+ local factor = 1000 * (setup .factor or 1 )
1019+ tfmdata .stretch = 10 * (setup .stretch or 0 )
1020+ tfmdata .shrink = 10 * (setup .shrink or 0 )
1021+ tfmdata .step = 10 * (setup .step or 0 )
1022+ for i , chr in next , tfmdata .characters do
1023+ local v = lookup [i ]
1024+ if v and v ~= 0 then
1025+ chr .expansion_factor = v * factor
1026+ elseif factor ~= 1000 then
1027+ chr .expansion_factor = factor
1028+ end
1029+ end
1030+ end
1031+
1032+ fonts .constructors .features .otf .register {
1033+ name = " expansion" ,
1034+ description = " apply hz optimization" ,
1035+ initializers = {
1036+ plug = initializeexpansion ,
1037+ }
1038+ }
1039+
9441040return function ()
9451041 if not fonts and fonts .handlers then
9461042 report (" log" , 0 , " features" ,
0 commit comments