UNPKG

fonteditor-core

Version:

fonts (ttf, woff, woff2, eot, svg, otf) parse, write, transform, glyph adjust.

155 lines (132 loc) 5.39 kB
/** * @file post 表 * @author mengke01(kekee000@gmail.com) * * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html */ import table from './table'; import struct from './struct'; import string from '../util/string'; import unicodeName from '../enum/unicodeName'; const Posthead = table.create( 'posthead', [ ['format', struct.Fixed], ['italicAngle', struct.Fixed], ['underlinePosition', struct.Int16], ['underlineThickness', struct.Int16], ['isFixedPitch', struct.Uint32], ['minMemType42', struct.Uint32], ['maxMemType42', struct.Uint32], ['minMemType1', struct.Uint32], ['maxMemType1', struct.Uint32] ] ); export default table.create( 'post', [], { read(reader, ttf) { const format = reader.readFixed(this.offset); // 读取表头 const tbl = new Posthead(this.offset).read(reader, ttf); // format2 if (format === 2) { const numberOfGlyphs = reader.readUint16(); const glyphNameIndex = []; for (let i = 0; i < numberOfGlyphs; ++i) { glyphNameIndex.push(reader.readUint16()); } const pascalStringOffset = reader.offset; const pascalStringLength = ttf.tables.post.length - (pascalStringOffset - this.offset); const pascalStringBytes = reader.readBytes(reader.offset, pascalStringLength); tbl.nameIndex = glyphNameIndex; // 设置glyf名字索引 tbl.names = string.getPascalString(pascalStringBytes); // glyf名字数组 } // deprecated else if (format === 2.5) { tbl.format = 3; } return tbl; }, write(writer, ttf) { const post = ttf.post || { format: 3 }; // write header writer.writeFixed(post.format); // format writer.writeFixed(post.italicAngle || 0); // italicAngle writer.writeInt16(post.underlinePosition || 0); // underlinePosition writer.writeInt16(post.underlineThickness || 0); // underlineThickness writer.writeUint32(post.isFixedPitch || 0); // isFixedPitch writer.writeUint32(post.minMemType42 || 0); // minMemType42 writer.writeUint32(post.maxMemType42 || 0); // maxMemType42 writer.writeUint32(post.minMemType1 || 0); // minMemType1 writer.writeUint32(post.maxMemType1 || 0); // maxMemType1 // version 3 不设置post信息 if (post.format === 2) { const numberOfGlyphs = ttf.glyf.length; writer.writeUint16(numberOfGlyphs); // numberOfGlyphs // write glyphNameIndex const nameIndex = ttf.support.post.nameIndex; for (let i = 0, l = nameIndex.length; i < l; i++) { writer.writeUint16(nameIndex[i]); } // write names ttf.support.post.names.forEach((name) => { writer.writeBytes(name); }); } }, size(ttf) { const numberOfGlyphs = ttf.glyf.length; ttf.post = ttf.post || {}; ttf.post.format = ttf.post.format || 3; ttf.post.maxMemType1 = numberOfGlyphs; // version 3 不设置post信息 if (ttf.post.format === 3 || ttf.post.format === 1) { return 32; } // version 2 let size = 34 + numberOfGlyphs * 2; // header + numberOfGlyphs + numberOfGlyphs * 2 const glyphNames = []; const nameIndexArr = []; let nameIndex = 0; // 获取 name的大小 for (let i = 0; i < numberOfGlyphs; i++) { // .notdef if (i === 0) { nameIndexArr.push(0); } else { const glyf = ttf.glyf[i]; const unicode = glyf.unicode ? glyf.unicode[0] : 0; const unicodeNameIndex = unicodeName[unicode]; if (undefined !== unicodeNameIndex) { nameIndexArr.push(unicodeNameIndex); } else { // 这里需要注意,"" 有可能是"\3" length不为0,但是是空字符串 const name = glyf.name; if (!name || name.charCodeAt(0) < 32) { nameIndexArr.push(258 + nameIndex++); glyphNames.push([0]); size++; } else { nameIndexArr.push(258 + nameIndex++); const bytes = string.toPascalStringBytes(name); // pascal string bytes glyphNames.push(bytes); size += bytes.length; } } } } ttf.support.post = { nameIndex: nameIndexArr, names: glyphNames }; return size; } } );