Current File : /home/tradevaly/www/node_modules/fontkit/src/subset/CFFSubset.js |
import Subset from './Subset';
import CFFTop from '../cff/CFFTop';
import CFFPrivateDict from '../cff/CFFPrivateDict';
import standardStrings from '../cff/CFFStandardStrings';
export default class CFFSubset extends Subset {
constructor(font) {
super(font);
this.cff = this.font['CFF '];
if (!this.cff) {
throw new Error('Not a CFF Font');
}
}
subsetCharstrings() {
this.charstrings = [];
let gsubrs = {};
for (let gid of this.glyphs) {
this.charstrings.push(this.cff.getCharString(gid));
let glyph = this.font.getGlyph(gid);
let path = glyph.path; // this causes the glyph to be parsed
for (let subr in glyph._usedGsubrs) {
gsubrs[subr] = true;
}
}
this.gsubrs = this.subsetSubrs(this.cff.globalSubrIndex, gsubrs);
}
subsetSubrs(subrs, used) {
let res = [];
for (let i = 0; i < subrs.length; i++) {
let subr = subrs[i];
if (used[i]) {
this.cff.stream.pos = subr.offset;
res.push(this.cff.stream.readBuffer(subr.length));
} else {
res.push(new Buffer([11])); // return
}
}
return res;
}
subsetFontdict(topDict) {
topDict.FDArray = [];
topDict.FDSelect = {
version: 0,
fds: []
};
let used_fds = {};
let used_subrs = [];
for (let gid of this.glyphs) {
let fd = this.cff.fdForGlyph(gid);
if (fd == null) {
continue;
}
if (!used_fds[fd]) {
topDict.FDArray.push(Object.assign({}, this.cff.topDict.FDArray[fd]));
used_subrs.push({});
}
used_fds[fd] = true;
topDict.FDSelect.fds.push(topDict.FDArray.length - 1);
let glyph = this.font.getGlyph(gid);
let path = glyph.path; // this causes the glyph to be parsed
for (let subr in glyph._usedSubrs) {
used_subrs[used_subrs.length - 1][subr] = true;
}
}
for (let i = 0; i < topDict.FDArray.length; i++) {
let dict = topDict.FDArray[i];
delete dict.FontName;
if (dict.Private && dict.Private.Subrs) {
dict.Private = Object.assign({}, dict.Private);
dict.Private.Subrs = this.subsetSubrs(dict.Private.Subrs, used_subrs[i]);
}
}
return;
}
createCIDFontdict(topDict) {
let used_subrs = {};
for (let gid of this.glyphs) {
let glyph = this.font.getGlyph(gid);
let path = glyph.path; // this causes the glyph to be parsed
for (let subr in glyph._usedSubrs) {
used_subrs[subr] = true;
}
}
let privateDict = Object.assign({}, this.cff.topDict.Private);
if (this.cff.topDict.Private && this.cff.topDict.Private.Subrs) {
privateDict.Subrs = this.subsetSubrs(this.cff.topDict.Private.Subrs, used_subrs);
}
topDict.FDArray = [{ Private: privateDict }];
return topDict.FDSelect = {
version: 3,
nRanges: 1,
ranges: [{ first: 0, fd: 0 }],
sentinel: this.charstrings.length
};
}
addString(string) {
if (!string) {
return null;
}
if (!this.strings) {
this.strings = [];
}
this.strings.push(string);
return standardStrings.length + this.strings.length - 1;
}
encode(stream) {
this.subsetCharstrings();
let charset = {
version: this.charstrings.length > 255 ? 2 : 1,
ranges: [{ first: 1, nLeft: this.charstrings.length - 2 }]
};
let topDict = Object.assign({}, this.cff.topDict);
topDict.Private = null;
topDict.charset = charset;
topDict.Encoding = null;
topDict.CharStrings = this.charstrings;
for (let key of ['version', 'Notice', 'Copyright', 'FullName', 'FamilyName', 'Weight', 'PostScript', 'BaseFontName', 'FontName']) {
topDict[key] = this.addString(this.cff.string(topDict[key]));
}
topDict.ROS = [this.addString('Adobe'), this.addString('Identity'), 0];
topDict.CIDCount = this.charstrings.length;
if (this.cff.isCIDFont) {
this.subsetFontdict(topDict);
} else {
this.createCIDFontdict(topDict);
}
let top = {
version: 1,
hdrSize: this.cff.hdrSize,
offSize: 4,
header: this.cff.header,
nameIndex: [this.cff.postscriptName],
topDictIndex: [topDict],
stringIndex: this.strings,
globalSubrIndex: this.gsubrs
};
CFFTop.encode(stream, top);
}
}