From 00ac320063ff016aea9f997948aa104d31bc95ff Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Fri, 2 Apr 2010 17:14:01 +0200 Subject: Support 'opbd' (OpenType protrusion) feature Code scrapped from ConTeXt, AFAIK, no font implements OpenType optical bounds (on of Linux Libertine font has traces of it), but I plan to use it in my fonts. The committed feature file is prepared for Pagella, we can later have font specific feature files like this. --- otfl-font-dum.lua | 121 ++++++++++++++++++++++++--- tests/opbd.fea | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/opbd.tex | 9 ++ 3 files changed, 363 insertions(+), 11 deletions(-) create mode 100644 tests/opbd.fea create mode 100644 tests/opbd.tex diff --git a/otfl-font-dum.lua b/otfl-font-dum.lua index 8e13b5b..1d79ab1 100644 --- a/otfl-font-dum.lua +++ b/otfl-font-dum.lua @@ -155,20 +155,119 @@ fonts.protrusions.setups = fonts.protrusions.setups or { } local setups = fonts.protrusions.setups +-- As this is experimental code, users should not depend on it. The +-- implications are still discussed on the ConTeXt Dev List and we're +-- not sure yet what exactly the spec is (the next code is tested with +-- a gyre font patched by / fea file made by Khaled Hosny). The double +-- trick should not be needed it proper hanging punctuation is used in +-- which case values < 1 can be used. +-- +-- preferred (in context, usine vectors): +-- +-- \definefontfeature[whatever][default][mode=node,protrusion=quality] +-- +-- using lfbd and rtbd, with possibibility to enable only one side : +-- +-- \definefontfeature[whocares][default][mode=node,protrusion=yes, opbd=yes,script=latn] +-- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn] +-- +-- idem, using multiplier +-- +-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn] +-- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn] +-- +-- idem, using named feature file (less frozen): +-- +-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea] + +local function map_opbd_onto_protrusion(tfmdata,value,opbd) + local characters, descriptions = tfmdata.characters, tfmdata.descriptions + local otfdata = tfmdata.shared.otfdata + local singles = otfdata.shared.featuredata.gpos_single + local script, language = tfmdata.script, tfmdata.language + local done, factor, left, right = false, 1, 1, 1 + local setup = setups[value] + if setup then + factor = setup.factor or 1 + left = setup.left or 1 + right = setup.right or 1 + else + factor = tonumber(value) or 1 + end + if opbd ~= "right" then + local validlookups, lookuplist = fonts.otf.collect_lookups(otfdata,"lfbd",script,language) + if validlookups then + for i=1,#lookuplist do + local lookup = lookuplist[i] + local data = singles[lookup] + if data then + if trace_protrusion then + logs.report("fonts","set left protrusion using lfbd lookup '%s'",lookup) + end + for k, v in next, data do + -- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same + local p = - (v[1] / 1000) * factor * left + characters[k].left_protruding = p + if trace_protrusion then + logs.report("opbd","lfbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," ")) + end + end + done = true + end + end + end + end + if opbd ~= "left" then + local validlookups, lookuplist = fonts.otf.collect_lookups(otfdata,"rtbd",script,language) + if validlookups then + for i=1,#lookuplist do + local lookup = lookuplist[i] + local data = singles[lookup] + if data then + if trace_protrusion then + logs.report("fonts","set right protrusion using rtbd lookup '%s'",lookup) + end + for k, v in next, data do + -- local p = v[3] / descriptions[k].width -- or 3 + local p = (v[1] / 1000) * factor * right + characters[k].right_protruding = p + if trace_protrusion then + logs.report("opbd","rtbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," ")) + end + end + end + done = true + end + end + end + tfmdata.auto_protrude = done +end + +-- The opbd test is just there because it was discussed on the +-- context development list. However, the mentioned fxlbi.otf font +-- only has some kerns for digits. So, consider this feature not +-- supported till we have a proper test font. + function fonts.initializers.common.protrusion(tfmdata,value) if value then - local setup = setups[value] - if setup then - local factor, left, right = setup.factor or 1, setup.left or 1, setup.right or 1 - local emwidth = tfmdata.parameters.quad - tfmdata.auto_protrude = true - for i, chr in next, tfmdata.characters do - local v, pl, pr = setup[i], nil, nil - if v then - pl, pr = v[1], v[2] + local opbd = tfmdata.shared.features.opbd + if opbd then + -- possible values: left right both yes no (experimental) + map_opbd_onto_protrusion(tfmdata,value,opbd) + elseif value then + local setup = setups[value] + if setup then + local factor, left, right = setup.factor or 1, setup.left or 1, setup.right or 1 + local emwidth = tfmdata.parameters.quad + tfmdata.auto_protrude = true + for i, chr in next, tfmdata.characters do + local v, pl, pr = setup[i], nil, nil + if v then + pl, pr = v[1], v[2] + end + if pl and pl ~= 0 then chr.left_protruding = left *pl*factor end + if pr and pr ~= 0 then chr.right_protruding = right*pr*factor end end - if pl and pl ~= 0 then chr.left_protruding = left *pl*factor end - if pr and pr ~= 0 then chr.right_protruding = right*pr*factor end end end end diff --git a/tests/opbd.fea b/tests/opbd.fea new file mode 100644 index 0000000..affc3c5 --- /dev/null +++ b/tests/opbd.fea @@ -0,0 +1,244 @@ + +lookup RightBounds { + lookupflag 0; + pos \exclam <100 0 0 0>; + pos \percent <100 0 0 0>; + pos \ampersand <100 0 0 0>; + pos \parenright <300 0 0 0>; + pos \asterisk <200 0 0 0>; + pos \plus <250 0 0 0>; + pos \comma <500 0 0 0>; + pos \hyphen <500 0 0 0>; + pos \period <700 0 0 0>; + pos \slash <300 0 0 0>; + pos \one <100 0 0 0>; + pos \seven <50 0 0 0>; + pos \colon <500 0 0 0>; + pos \semicolon <500 0 0 0>; + pos \question <200 0 0 0>; + pos \at <50 0 0 0>; + pos \A <50 0 0 0>; + pos \K <50 0 0 0>; + pos \L <50 0 0 0>; + pos \T <50 0 0 0>; + pos \V <50 0 0 0>; + pos \W <50 0 0 0>; + pos \X <50 0 0 0>; + pos \Y <50 0 0 0>; + pos \k <50 0 0 0>; + pos \p <50 0 0 0>; + pos \r <50 0 0 0>; + pos \v <50 0 0 0>; + pos \w <50 0 0 0>; + pos \x <50 0 0 0>; + pos \y <70 0 0 0>; + pos \asciitilde <250 0 0 0>; + pos \Agrave <50 0 0 0>; + pos \Aacute <50 0 0 0>; + pos \Acircumflex <50 0 0 0>; + pos \Atilde <50 0 0 0>; + pos \Adieresis <50 0 0 0>; + pos \Aring <50 0 0 0>; + pos \Amacron <50 0 0 0>; + pos \Abreve <50 0 0 0>; + pos \Aogonek <50 0 0 0>; + pos \Kcommaaccent <50 0 0 0>; + pos \kcommaaccent <50 0 0 0>; + pos \Lacute <50 0 0 0>; + pos \Lcommaaccent <50 0 0 0>; + pos \Lcaron <50 0 0 0>; + pos \Ldot <50 0 0 0>; + pos \Lslash <50 0 0 0>; + pos \racute <50 0 0 0>; + pos \rcommaaccent <50 0 0 0>; + pos \rcaron <50 0 0 0>; + pos \wcircumflex <50 0 0 0>; + pos \ycircumflex <70 0 0 0>; + pos \Acaron <50 0 0 0>; + pos \Aringacute <50 0 0 0>; + pos \Adblgrave <50 0 0 0>; + pos \rdblgrave <50 0 0 0>; + pos \uni021A <50 0 0 0>; + pos \Alpha <50 0 0 0>; + pos \Kappa <50 0 0 0>; + pos \Lambda <50 0 0 0>; + pos \Tau <50 0 0 0>; + pos \Ldotbelow <50 0 0 0>; + pos \Ldotbelowmacron <50 0 0 0>; + pos \rdotaccent <50 0 0 0>; + pos \rdotbelow <50 0 0 0>; + pos \rdotbelowmacron <50 0 0 0>; + pos \Tdotbelow <50 0 0 0>; + pos \Tlinebelow <50 0 0 0>; + pos \wgrave <50 0 0 0>; + pos \wacute <50 0 0 0>; + pos \wdieresis <50 0 0 0>; + pos \Ahookabove <50 0 0 0>; + pos \Acircumflexacute <50 0 0 0>; + pos \Acircumflexgrave <50 0 0 0>; + pos \Acircumflexhookabove <50 0 0 0>; + pos \Acircumflextilde <50 0 0 0>; + pos \Acircumflexdotbelow <50 0 0 0>; + pos \Abreveacute <50 0 0 0>; + pos \Abrevegrave <50 0 0 0>; + pos \Abrevehookabove <50 0 0 0>; + pos \Abrevetilde <50 0 0 0>; + pos \Abrevedotbelow <50 0 0 0>; + pos \ygrave <70 0 0 0>; + pos \ydotbelow <70 0 0 0>; + pos \yhookabove <70 0 0 0>; + pos \ytilde <70 0 0 0>; + pos \endash <300 0 0 0>; + pos \emdash <200 0 0 0>; + pos \quoteleft <700 0 0 0>; + pos \quoteright <700 0 0 0>; + pos \quotedblleft <400 0 0 0>; + pos \quotedblright <400 0 0 0>; + pos \Aogonekacute <50 0 0 0>; + pos \L_uni0303 <50 0 0 0>; + pos \T_uni0303 <50 0 0 0>; + pos \T_uni0308 <50 0 0 0>; +} RightBounds; + +lookup LeftBounds { + lookupflag 0; + pos \percent <-100 0 -100 0>; + pos \ampersand <-50 0 -50 0>; + pos \parenleft <-100 0 -100 0>; + pos \asterisk <-200 0 -200 0>; + pos \plus <-250 0 -250 0>; + pos \hyphen <-400 0 -400 0>; + pos \slash <-200 0 -200 0>; + pos \one <-100 0 -100 0>; + pos \at <-50 0 -50 0>; + pos \A <-50 0 -50 0>; + pos \J <-50 0 -50 0>; + pos \T <-50 0 -50 0>; + pos \V <-50 0 -50 0>; + pos \W <-50 0 -50 0>; + pos \X <-50 0 -50 0>; + pos \Y <-50 0 -50 0>; + pos \p <-50 0 -50 0>; + pos \q <-50 0 -50 0>; + pos \v <-50 0 -50 0>; + pos \w <-50 0 -50 0>; + pos \x <-50 0 -50 0>; + pos \y <-50 0 -50 0>; + pos \asciitilde <-200 0 -200 0>; + pos \Agrave <-50 0 -50 0>; + pos \Aacute <-50 0 -50 0>; + pos \Acircumflex <-50 0 -50 0>; + pos \Atilde <-50 0 -50 0>; + pos \Adieresis <-50 0 -50 0>; + pos \Aring <-50 0 -50 0>; + pos \Amacron <-50 0 -50 0>; + pos \Abreve <-50 0 -50 0>; + pos \Aogonek <-50 0 -50 0>; + pos \Jcircumflex <-50 0 -50 0>; + pos \wcircumflex <-50 0 -50 0>; + pos \ycircumflex <-50 0 -50 0>; + pos \Acaron <-50 0 -50 0>; + pos \Aringacute <-50 0 -50 0>; + pos \Adblgrave <-50 0 -50 0>; + pos \uni021A <-50 0 -50 0>; + pos \Alpha <-50 0 -50 0>; + pos \Lambda <-50 0 -50 0>; + pos \Tau <-50 0 -50 0>; + pos \Tdotbelow <-50 0 -50 0>; + pos \Tlinebelow <-50 0 -50 0>; + pos \wgrave <-50 0 -50 0>; + pos \wacute <-50 0 -50 0>; + pos \wdieresis <-50 0 -50 0>; + pos \Ahookabove <-50 0 -50 0>; + pos \Acircumflexacute <-50 0 -50 0>; + pos \Acircumflexgrave <-50 0 -50 0>; + pos \Acircumflexhookabove <-50 0 -50 0>; + pos \Acircumflextilde <-50 0 -50 0>; + pos \Acircumflexdotbelow <-50 0 -50 0>; + pos \Abreveacute <-50 0 -50 0>; + pos \Abrevegrave <-50 0 -50 0>; + pos \Abrevehookabove <-50 0 -50 0>; + pos \Abrevetilde <-50 0 -50 0>; + pos \Abrevedotbelow <-50 0 -50 0>; + pos \ygrave <-50 0 -50 0>; + pos \ydotbelow <-50 0 -50 0>; + pos \yhookabove <-50 0 -50 0>; + pos \ytilde <-50 0 -50 0>; + pos \endash <-300 0 -300 0>; + pos \emdash <-200 0 -200 0>; + pos \quoteleft <-500 0 -500 0>; + pos \quoteright <-500 0 -500 0>; + pos \quotedblleft <-300 0 -300 0>; + pos \quotedblright <-300 0 -300 0>; + pos \Aogonekacute <-50 0 -50 0>; + pos \J_uni030C.cap <-50 0 -50 0>; + pos \T_uni0303 <-50 0 -50 0>; + pos \T_uni0308 <-50 0 -50 0>; +} LeftBounds; + +feature rtbd { + + script DFLT; + language dflt ; + lookup RightBounds; + + script grek; + language dflt ; + lookup RightBounds; + + script latn; + language dflt ; + lookup RightBounds; + language AZE exclude_dflt; + lookup RightBounds; + language CRT exclude_dflt; + lookup RightBounds; + language MOL exclude_dflt; + lookup RightBounds; + language NLD exclude_dflt; + lookup RightBounds; + language PLK exclude_dflt; + lookup RightBounds; + language ROM exclude_dflt; + lookup RightBounds; + language TRK exclude_dflt; + lookup RightBounds; + + script thai; + language dflt ; + lookup RightBounds; +} rtbd; + +feature lfbd { + + script DFLT; + language dflt ; + lookup LeftBounds; + + script grek; + language dflt ; + lookup LeftBounds; + + script latn; + language dflt ; + lookup LeftBounds; + language AZE exclude_dflt; + lookup LeftBounds; + language CRT exclude_dflt; + lookup LeftBounds; + language MOL exclude_dflt; + lookup LeftBounds; + language NLD exclude_dflt; + lookup LeftBounds; + language PLK exclude_dflt; + lookup LeftBounds; + language ROM exclude_dflt; + lookup LeftBounds; + language TRK exclude_dflt; + lookup LeftBounds; + + script thai; + language dflt ; + lookup LeftBounds; +} lfbd; + diff --git a/tests/opbd.tex b/tests/opbd.tex new file mode 100644 index 0000000..4c45781 --- /dev/null +++ b/tests/opbd.tex @@ -0,0 +1,9 @@ +\input luaotfload.sty + +\pdfprotrudechars2 \pdfadjustspacing2 + +\font\testa=file:texgyrepagella-regular:script=latn at 12pt +\font\testb=file:texgyrepagella-regular:mode=node;script=latn;protrusion=yes;featurefile=opbd.fea;+opbd at 12pt +\testa \input tufte \par +\testb \input tufte \par +\bye -- cgit v1.2.3