From 26d810dd65a0067bc7fcc17728c0bab409b5e79c Mon Sep 17 00:00:00 2001 From: Benoit KUGLER Date: Mon, 11 Dec 2023 16:58:54 +0100 Subject: [PATCH] [cff] properly skip blend arguments when no variations are set up by the user (#123) --- opentype/api/font/cff/charstring.go | 13 ++++++------- opentype/api/font/cff/parser_test.go | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/opentype/api/font/cff/charstring.go b/opentype/api/font/cff/charstring.go index 78229a8..de73879 100644 --- a/opentype/api/font/cff/charstring.go +++ b/opentype/api/font/cff/charstring.go @@ -186,13 +186,11 @@ type cff2CharstringHandler struct { func (cff2CharstringHandler) Context() ps.Context { return ps.Type2Charstring } -// returns true if variations are activated -func (met *cff2CharstringHandler) isVar() bool { - return len(met.coords) != 0 && len(met.vars.ItemVariationDatas) != 0 -} - func (met *cff2CharstringHandler) setVSIndex(index int) error { - if !met.isVar() { + // if the font has variations, always build the scalar + // slice, even if no variations are activated by the user: + // the blend operator needs to know how many args to skip. + if len(met.vars.ItemVariationDatas) == 0 { return nil } @@ -221,7 +219,8 @@ func (met *cff2CharstringHandler) blend(state *ps.Machine) error { return errors.New("missing arguments for blend operator") } - if met.isVar() { + // actually apply the deltas only if the user has activated variations + if len(met.coords) != 0 { args := state.ArgStack.Vals[state.ArgStack.Top-n*(k+1) : state.ArgStack.Top] // the first n values are the 'default' arguments for i := int32(0); i < n; i++ { diff --git a/opentype/api/font/cff/parser_test.go b/opentype/api/font/cff/parser_test.go index 8c72e1d..ae5de9d 100644 --- a/opentype/api/font/cff/parser_test.go +++ b/opentype/api/font/cff/parser_test.go @@ -136,3 +136,22 @@ func TestParseCFF2(t *testing.T) { tu.AssertNoErr(t, err) } } + +func TestIssue122(t *testing.T) { + b, err := td.Files.ReadFile("common/NotoSansCJKjp-VF.otf") + tu.AssertNoErr(t, err) + + ft, err := loader.NewLoader(bytes.NewReader(b)) + tu.AssertNoErr(t, err) + + table, err := ft.RawTable(loader.MustNewTag("CFF2")) + tu.AssertNoErr(t, err) + + out, err := ParseCFF2(table) + tu.AssertNoErr(t, err) + + // check that the correct number of segments are + // computed, even if the user has not activated variations + segments, _, _ := out.LoadGlyph(38, nil) + tu.Assert(t, len(segments) == 12) +}