#lang racket (require rackunit racket/runtime-path fontland fontland/subset) #| approximates https://github.com/mbutterick/fontkit/blob/master/test/subset.js |# (define-runtime-path open-sans-ttf "data/OpenSans/OpenSans-Regular.ttf") (define font (open-font open-sans-ttf)) (test-case "should create a TTFSubset instance" (define subset (create-subset font)) (check-true (ttf-subset? subset))) (test-case "should produce a subset" (define subset (create-subset font)) (for ([glyph (in-vector (vector-map glyph-id (glyphrun-glyphs (layout font "hello"))))]) (subset-add-glyph! subset glyph)) (define f (encode-to-port subset)) f (void)) #| it('should produce a subset', function(done) { let subset = font.createSubset(); for (let glyph of font.glyphsForString('hello')) { subset.includeGlyph(glyph); } subset.encodeStream().pipe(concat(function(buf) { let f = fontkit.create(buf); assert.equal(f.numGlyphs, 5); assert.equal(f.getGlyph(1).path.toSVG(), font.glyphsForString('h')[0].path.toSVG()); done(); })); }); it('should re-encode variation glyphs', function(done) { if (!fs.existsSync('/Library/Fonts/Skia.ttf')) return done(); let font = fontkit.openSync('/Library/Fonts/Skia.ttf', 'Bold'); let subset = font.createSubset(); for (let glyph of font.glyphsForString('e')) { subset.includeGlyph(glyph); } subset.encodeStream().pipe(concat(function(buf) { let f = fontkit.create(buf); assert.equal(f.getGlyph(1).path.toSVG(), font.glyphsForString('e')[0].path.toSVG()); done(); })); }); it('should handle composite glyphs', function(done) { let subset = font.createSubset(); subset.includeGlyph(font.glyphsForString('é')[0]); subset.encodeStream().pipe(concat(function(buf) { let f = fontkit.create(buf); assert.equal(f.numGlyphs, 4); assert.equal(f.getGlyph(1).path.toSVG(), font.glyphsForString('é')[0].path.toSVG()); done(); })); }); it('should handle fonts with long index to location format (indexToLocFormat = 1)', function(done) { let font = fontkit.openSync(__dirname + '/data/FiraSans/FiraSans-Regular.ttf'); let subset = font.createSubset(); for (let glyph of font.glyphsForString('abcd')) { subset.includeGlyph(glyph); } subset.encodeStream().pipe(concat(function(buf) { let f = fontkit.create(buf); assert.equal(f.numGlyphs, 5); assert.equal(f.getGlyph(1).path.toSVG(), font.glyphsForString('a')[0].path.toSVG()); // must test also second glyph which has an odd loca index assert.equal(f.getGlyph(2).path.toSVG(), font.glyphsForString('b')[0].path.toSVG()); done(); })); }); }); describe('CFF subsetting', function() { let font = fontkit.openSync(__dirname + '/data/SourceSansPro/SourceSansPro-Regular.otf'); it('should create a CFFSubset instance', function() { let subset = font.createSubset(); return assert.equal(subset.constructor.name, 'CFFSubset'); }); it('should produce a subset', function(done) { let subset = font.createSubset(); let iterable = font.glyphsForString('hello'); for (let i = 0; i < iterable.length; i++) { let glyph = iterable[i]; subset.includeGlyph(glyph); } return subset.encodeStream().pipe(concat(function(buf) { let stream = new r.DecodeStream(buf); let cff = new CFFFont(stream); let glyph = new CFFGlyph(1, [], { stream, 'CFF ': cff }); assert.equal(glyph.path.toSVG(), font.glyphsForString('h')[0].path.toSVG()); return done(); })); }); it('should handle CID fonts', function(done) { let f = fontkit.openSync(__dirname + '/data/NotoSansCJK/NotoSansCJKkr-Regular.otf'); let subset = f.createSubset(); let iterable = f.glyphsForString('갈휸'); for (let i = 0; i < iterable.length; i++) { let glyph = iterable[i]; subset.includeGlyph(glyph); } return subset.encodeStream().pipe(concat(function(buf) { let stream = new r.DecodeStream(buf); let cff = new CFFFont(stream); let glyph = new CFFGlyph(1, [], { stream, 'CFF ': cff }); assert.equal(glyph.path.toSVG(), f.glyphsForString('갈')[0].path.toSVG()); assert.equal(cff.topDict.FDArray.length, 2); assert.deepEqual(cff.topDict.FDSelect.fds, [0, 1, 1]); return done(); })); }); }); }); |#