From 88878eae2f50cc23faeffab130e1c1c28d87d031 Mon Sep 17 00:00:00 2001 From: Ross Baquir Date: Sat, 11 Nov 2023 11:57:31 -0800 Subject: [PATCH] fix setting preferred subfamily (#635) * fix setting preferred subfamily * add test file for sfnt.js and default tests * add tests for name table and small changes to tests * test font.toTables --- src/tables/sfnt.js | 6 +- test/font.js | 8 +++ test/tables/sfnt.js | 153 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 test/tables/sfnt.js diff --git a/src/tables/sfnt.js b/src/tables/sfnt.js index fe2e1f74..71ef148a 100644 --- a/src/tables/sfnt.js +++ b/src/tables/sfnt.js @@ -316,15 +316,15 @@ function fontToSfntTable(font) { } if (!names.unicode.preferredSubfamily) { - names.unicode.preferredSubfamily = fontNamesUnicode.fontSubFamily || fontNamesMacintosh.fontSubFamily || fontNamesWindows.fontSubFamily; + names.unicode.preferredSubfamily = fontNamesUnicode.fontSubfamily || fontNamesMacintosh.fontSubfamily || fontNamesWindows.fontSubfamily; } if (!names.macintosh.preferredSubfamily) { - names.macintosh.preferredSubfamily = fontNamesMacintosh.fontSubFamily || fontNamesUnicode.fontSubFamily || fontNamesWindows.fontSubFamily; + names.macintosh.preferredSubfamily = fontNamesMacintosh.fontSubfamily || fontNamesUnicode.fontSubfamily || fontNamesWindows.fontSubfamily; } if (!names.windows.preferredSubfamily) { - names.windows.preferredSubfamily = fontNamesWindows.fontSubFamily || fontNamesUnicode.fontSubFamily || fontNamesMacintosh.fontSubFamily; + names.windows.preferredSubfamily = fontNamesWindows.fontSubfamily || fontNamesUnicode.fontSubfamily || fontNamesMacintosh.fontSubfamily; } // we have to handle fvar before name, because it may modify name IDs diff --git a/test/font.js b/test/font.js index d3ac06af..383b7280 100644 --- a/test/font.js +++ b/test/font.js @@ -164,4 +164,12 @@ describe('font.js', function() { assert.equal(cmapFont.hasChar('≩'), true); }); }); + + describe('toTables', function() { + it('returns an sfnt font table', function() { + const tables = font.toTables(); + assert.ok(tables); + assert.equal(tables.tableName, 'sfnt'); + }); + }); }); diff --git a/test/tables/sfnt.js b/test/tables/sfnt.js new file mode 100644 index 00000000..b0bf61f8 --- /dev/null +++ b/test/tables/sfnt.js @@ -0,0 +1,153 @@ +import assert from 'assert'; +import Font from '../../src/font.js'; +import sfnt from '../../src/tables/sfnt.js'; +import name from '../../src/tables/name.js'; +import { encode } from '../../src/types.js'; + +function encodeAndParseTable(table, parser) { + const bytes = encode.TABLE(table); + const data = new DataView(new ArrayBuffer(bytes.length), 0); + for (let k = 0; k < bytes.length; k++) { + data.setUint8(k, bytes[k]); + } + + return parser(data, 0); +} + +describe('tables/sfnt.js', ()=>{ + let font; + const defaultFont = { + familyName: 'MyFont', + styleName: 'Medium', + unitsPerEm: 1000, + ascender: 800, + descender: 0, + }; + + describe('fontToSfntTable', () => { + beforeEach(function() { + font = new Font({...defaultFont}); + }); + + it('should create an sfnt table object', ()=>{ + const sfnt_table = sfnt.fontToTable(font); + assert.ok(sfnt_table); + assert.equal(sfnt_table.tableName, 'sfnt'); + }); + + it('should set default values when no name values are set', ()=>{ + const sfnt_table = sfnt.fontToTable(font); + const name_table = sfnt_table.tables.find((table)=>table.tableName == 'name'); + + assert.ok(name_table); + + const parsedNameTable = encodeAndParseTable(name_table, name.parse); + + assert.deepEqual(parsedNameTable, { + macintosh: { + copyright: { en: ' ' }, + fontFamily: { en: defaultFont.familyName }, // 'MyFont' + fontSubfamily: { en: defaultFont.styleName }, // 'Medium' + fullName: { en: `${defaultFont.familyName} ${defaultFont.styleName}` }, // 'MyFont Medium' + version: { en: 'Version 0.1' }, + postScriptName: { en: `${defaultFont.familyName}${defaultFont.styleName}` }, // 'MyFontMedium' + trademark: { en: ' ' }, + manufacturer: { en: ' ' }, + designer: { en: ' ' }, + description: { en: ' ' }, + manufacturerURL: { en: ' ' }, + designerURL: { en: ' ' }, + license: { en: ' ' }, + licenseURL: { en: ' ' }, + preferredFamily: { en: defaultFont.familyName }, // 'MyFont' + preferredSubfamily: { en: defaultFont.styleName } // 'Medium' + }, + windows: { + copyright: { en: ' ' }, + fontFamily: { en: defaultFont.familyName }, // 'MyFont' + fontSubfamily: { en: defaultFont.styleName }, // 'Medium' + fullName: { en: `${defaultFont.familyName} ${defaultFont.styleName}` }, // 'MyFont Medium' + version: { en: 'Version 0.1' }, + postScriptName: { en: `${defaultFont.familyName}${defaultFont.styleName}` }, // 'MyFontMedium' + trademark: { en: ' ' }, + manufacturer: { en: ' ' }, + designer: { en: ' ' }, + description: { en: ' ' }, + manufacturerURL: { en: ' ' }, + designerURL: { en: ' ' }, + license: { en: ' ' }, + licenseURL: { en: ' ' }, + preferredFamily: { en: defaultFont.familyName }, // 'MyFont' + preferredSubfamily: { en: defaultFont.styleName } // 'Medium' + } + }); + }); + + it('should set values in the names table with the values of the font object\'s names property', ()=>{ + const fontFamily = 'Original Name'; + const fontSubfamily = 'Bold Italic'; + const fullName = 'Original Name Bold Italic'; + const version = 'Version 24'; + const preferredFamily = 'Custom Name'; + const preferredSubfamily = '700 Italic'; + + font.names = { + macintosh: { + fontFamily: { en: fontFamily }, + fontSubfamily: { en: fontSubfamily}, + fullName: { en: fullName }, + version: { en: version }, + preferredFamily: { en: preferredFamily }, + preferredSubfamily: { en: preferredSubfamily} + }, + windows: { + fontFamily: { en: fontFamily }, + fontSubfamily: { en: fontSubfamily}, + fullName: { en: fullName }, + version: { en: version }, + preferredFamily: { en: preferredFamily }, + preferredSubfamily: { en: preferredSubfamily} + } + }; + + const sfnt_table = sfnt.fontToTable(font); + const name_table = sfnt_table.tables.find((table)=>table.tableName == 'name'); + const parsedNameTable = encodeAndParseTable(name_table, name.parse); + + assert.deepEqual(parsedNameTable, { + macintosh: { + fontFamily: { en: fontFamily }, + fontSubfamily: { en: fontSubfamily}, + fullName: { en: fullName }, + version: { en: version }, + preferredFamily: { en: preferredFamily }, + preferredSubfamily: { en: preferredSubfamily} + }, + windows: { + fontFamily: { en: fontFamily }, + fontSubfamily: { en: fontSubfamily}, + fullName: { en: fullName }, + version: { en: version }, + preferredFamily: { en: preferredFamily }, + preferredSubfamily: { en: preferredSubfamily} + } + }); + }); + + it('should set preferredSubfamily as value of fontSubfamily, if not explicitly set', ()=>{ + const preferredSubfamily = 'Custom Subfamily'; + font.names = { macintosh: { + fontFamily: {en: defaultFont.familyName }, + fontSubfamily: { en: preferredSubfamily } + }}; + + const sfnt_table = sfnt.fontToTable(font); + const name_table = sfnt_table.tables.find((table)=>table.tableName == 'name'); + const parsedNameTable = encodeAndParseTable(name_table, name.parse); + + assert.deepEqual(parsedNameTable.macintosh.preferredSubfamily, { en: preferredSubfamily }); + assert.deepEqual(parsedNameTable.windows.preferredSubfamily, { en: preferredSubfamily }); + }); + }); +}); +