[NTG-context] CFF2 based variable fonts with SubRS

2020-08-26 Thread Marcel Fabian Krüger
Hi,

I was playing with the variable font support of ConTeXt's font loader
and noticed some issues.

  1. While parsing the LocalSubRS and GlobalSubRS Indices, ConTeXt tries
 to use 16bit count fields as in CFF(1) instead of 32bit fields as in
 CFF2, reducing the number of found subroutines by a factor of 65536.
 Effectivly this suppressed all subroutines in the fonts I tested.

  2. For fonts where the Top DICT does not contain an FDSelect entry,
 ConTeXt tries to read the Private dictionary offset from the Top
 dictionary as in name-keyed CFF1 fonts. This is not the expected
 behavior for CFF2, where the Top dictionary never contains the Privte
 offset.
 Instead, a missing FDSelect means that exactly one entry exists in
 FDArray which should be used for all CIDs. This caused problems
 when ConTeXt tried to find the Private directory in order to find
 local subroutines.

A test font demonstrating both issues is "SourceCode Variable"
https://github.com/adobe-fonts/source-code-pro/releases:

The document

\definefontfeature
  [light]
  [default]
  [axis={weight=200}]

\definefont
  [sourcelight]
  [file:SourceCodeVariable-Roman.otf*light]

\starttext
\sourcelight Hallo
\stoptext

generates

[...]
otf reader  > cff > unknown local call 14, case 2 : [] n=0
otf reader  > cff > unknown local call 11, case 2 : [] n=0
otf reader  > cff > unknown local call 138, case 2 : [] n=0
otf reader  > cff > unknown local call 314, case 2 : [300 -12] n=2
otf reader  > cff > unknown local call 607, case 2 : [-99 -66 99 174] 
n=4
otf reader  > fatal error in file 'SourceCodeVariable-Roman.otf': 
...e0dde776fb1556f32e/formats/luametatex/font-cff-macro.lua:1517: attempt to 
perform arithmetic on a nil value (local 'v')
stack traceback:
...e0dde776fb1556f32e/formats/luametatex/font-otr-macro.lua:2339: in 
metamethod 'add'
...e0dde776fb1556f32e/formats/luametatex/font-cff-macro.lua:1517: in 
local 'a'
...e0dde776fb1556f32e/formats/luametatex/font-cff-macro.lua:1980: in 
upvalue 'process'
[...]


A possible fix for both issues would be


diff --git a/tex/context/base/mkiv/font-cff.lua 
b/tex/context/base/mkiv/font-cff.lua
index c2cf0e699..d00637b8e 100644
--- a/tex/context/base/mkiv/font-cff.lua
+++ b/tex/context/base/mkiv/font-cff.lua
@@ -2265,8 +2265,8 @@ do
 
 end
 
-local function readglobals(f,data)
-local routines = readlengths(f)
+local function readglobals(f,data,version)
+local routines = readlengths(f,version == "cff2")
 for i=1,#routines do
 routines[i] = readbytetable(f,routines[i])
 end
@@ -2324,14 +2324,14 @@ local function readprivates(f,data)
 end
 end
 
-local function readlocals(f,data,dictionary)
+local function readlocals(f,data,dictionary,version)
 local header  = data.header
 local private = dictionary.private
 if private then
 local subroutineoffset = private.data.subroutines
 if subroutineoffset ~= 0 then
 setposition(f,header.offset+private.offset+subroutineoffset)
-local subroutines = readlengths(f)
+local subroutines = readlengths(f,version=="cff2")
 for i=1,#subroutines do
 subroutines[i] = readbytetable(f,subroutines[i])
 end
@@ -2394,7 +2394,7 @@ readers.parsecharstrings = parsecharstrings -- used in 
font-onr.lua (type 1)
 local function readnoselect(f,fontdata,data,glyphs,doshapes,version,streams)
 local dictionaries = data.dictionaries
 local dictionary   = dictionaries[1]
-readglobals(f,data)
+readglobals(f,data,version)
 readcharstrings(f,data,version)
 if version == "cff2" then
 dictionary.charset = nil
@@ -2402,9 +2402,19 @@ local function 
readnoselect(f,fontdata,data,glyphs,doshapes,version,streams)
 readencodings(f,data)
 readcharsets(f,data,dictionary)
 end
+local cid  = dictionary.cid
+local fdarray  = cid and cid.fdarray
+if fdarray and not dictionary.private then
+setposition(f,data.header.offset+fdarray)
+local dictionaries = readlengths(f,version=="cff2")
+assert(#dictionaries == 1)
+dictionaries[1] = readstring(f,dictionaries[1])
+parsedictionaries(data,dictionaries)
+dictionary.private = dictionaries[1].private
+end
 readprivates(f,data)
 parseprivates(data,data.dictionaries)
-readlocals(f,data,dictionary)
+readlocals(f,data,dictionary,version)
 startparsing(fontdata,data,streams)
 parsecharstrings(fontdata,data,glyphs,doshapes,version,streams)
 stopparsing(fontdata,data)
@@ -2416,7 +2426,7 @@ local function 
readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)
 local dictionary   = dictionaries[1]
 local cid  = dictionary.cid
 local cidselect= cid and cid.fdselect
-readglobals(f,data)
+readglobals(f,data,version)
 readcharstrings(f,data,version)
 

Re: [NTG-context] CFF2 based variable fonts with SubRS

2020-08-26 Thread Hans Hagen

On 8/26/2020 11:01 AM, Marcel Fabian Krüger wrote:

Hi,

I was playing with the variable font support of ConTeXt's font loader
and noticed some issues.

   1. While parsing the LocalSubRS and GlobalSubRS Indices, ConTeXt tries
  to use 16bit count fields as in CFF(1) instead of 32bit fields as in
  CFF2, reducing the number of found subroutines by a factor of 65536.
  Effectivly this suppressed all subroutines in the fonts I tested.

   2. For fonts where the Top DICT does not contain an FDSelect entry,
  ConTeXt tries to read the Private dictionary offset from the Top
  dictionary as in name-keyed CFF1 fonts. This is not the expected
  behavior for CFF2, where the Top dictionary never contains the Privte
  offset.
  Instead, a missing FDSelect means that exactly one entry exists in
  FDArray which should be used for all CIDs. This caused problems
  when ConTeXt tried to find the Private directory in order to find
  local subroutines.

A test font demonstrating both issues is "SourceCode Variable"
https://github.com/adobe-fonts/source-code-pro/releases:

The document

\definefontfeature
   [light]
   [default]
   [axis={weight=200}]

\definefont
   [sourcelight]
   [file:SourceCodeVariable-Roman.otf*light]

\starttext
\sourcelight Hallo
\stoptext


Thanks. I'll check it. (Reminds me to check another issue in a variable 
font that I observed recently, something with accuracy, but of could 
also be a border case in a viewer as acrobat views ok.) I would not be 
surprised of there are more issues because at the time I wrote that code 
there were hardly any valid variable fonts and the specs were just 
showing up. (Most of those variable fonts were showcases.)


Hans



-
  Hans Hagen | PRAGMA ADE
  Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
   tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-
___
If your question is of interest to others as well, please add an entry to the 
Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki : http://contextgarden.net
___