forked from enviPath/enviPy
Current Dev State
This commit is contained in:
304
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/cmap.js
generated
vendored
Normal file
304
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/cmap.js
generated
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/cmap.htm
|
||||
|
||||
var _ = require('lodash');
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
function getIDByUnicode(font, unicode) {
|
||||
return font.codePoints[unicode] ? font.codePoints[unicode].id : 0;
|
||||
}
|
||||
|
||||
// Calculate character segments with non-interruptable chains of unicodes
|
||||
function getSegments(font, bounds) {
|
||||
bounds = bounds || Number.MAX_VALUE;
|
||||
|
||||
var result = [];
|
||||
var segment;
|
||||
|
||||
// prevEndCode only changes when a segment closes
|
||||
_.forEach(font.codePoints, function (glyph, unicode) {
|
||||
unicode = parseInt(unicode, 10);
|
||||
if (unicode >= bounds) {
|
||||
return false;
|
||||
}
|
||||
// Initialize first segment or add new segment if code "hole" is found
|
||||
if (!segment || unicode !== (segment.end + 1)) {
|
||||
if (segment) {
|
||||
result.push(segment);
|
||||
}
|
||||
segment = {
|
||||
start: unicode
|
||||
};
|
||||
}
|
||||
segment.end = unicode;
|
||||
});
|
||||
|
||||
// Need to finish the last segment
|
||||
if (segment) {
|
||||
result.push(segment);
|
||||
}
|
||||
|
||||
_.forEach(result, function (segment) {
|
||||
segment.length = segment.end - segment.start + 1;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns an array of {unicode, glyph} sets for all valid code points up to bounds
|
||||
function getCodePoints(codePoints, bounds) {
|
||||
bounds = bounds || Number.MAX_VALUE;
|
||||
|
||||
var result = [];
|
||||
|
||||
_.forEach(codePoints, function (glyph, unicode) {
|
||||
unicode = parseInt(unicode, 10);
|
||||
// Since this is a sparse array, iterating will only yield the valid code points
|
||||
if (unicode > bounds) {
|
||||
return false;
|
||||
}
|
||||
result.push({
|
||||
unicode: unicode,
|
||||
glyph: glyph
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function bufferForTable(format, length) {
|
||||
var fieldWidth = format === 8 || format === 10 || format === 12 || format === 13 ? 4 : 2;
|
||||
|
||||
length += (0
|
||||
+ fieldWidth // Format
|
||||
+ fieldWidth // Length
|
||||
+ fieldWidth // Language
|
||||
);
|
||||
|
||||
var LANGUAGE = 0;
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
var writer = fieldWidth === 4 ? buffer.writeUint32 : buffer.writeUint16;
|
||||
|
||||
// Format specifier
|
||||
buffer.writeUint16(format);
|
||||
if (fieldWidth === 4) {
|
||||
// In case of formats 8.…, 10.…, 12.… and 13.…, this is the decimal part of the format number
|
||||
// But since have not been any point releases, this can be zero in that case as well
|
||||
buffer.writeUint16(0);
|
||||
}
|
||||
// Length
|
||||
writer.call(buffer, length);
|
||||
// Language code (0, only used for legacy quickdraw tables)
|
||||
writer.call(buffer, LANGUAGE);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createFormat0Table(font) {
|
||||
var FORMAT = 0;
|
||||
|
||||
var i;
|
||||
|
||||
var length = 0xff + 1; //Format 0 maps only single-byte code points
|
||||
|
||||
var buffer = bufferForTable(FORMAT, length);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
buffer.writeUint8(getIDByUnicode(font, i)); // existing char in table 0..255
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createFormat4Table(font) {
|
||||
var FORMAT = 4;
|
||||
|
||||
var i;
|
||||
|
||||
var segments = getSegments(font, 0xFFFF);
|
||||
var glyphIndexArrays = [];
|
||||
|
||||
_.forEach(segments, function (segment) {
|
||||
var glyphIndexArray = [];
|
||||
|
||||
for (var unicode = segment.start; unicode <= segment.end; unicode++) {
|
||||
glyphIndexArray.push(getIDByUnicode(font, unicode));
|
||||
}
|
||||
glyphIndexArrays.push(glyphIndexArray);
|
||||
});
|
||||
|
||||
var segCount = segments.length + 1; // + 1 for the 0xFFFF section
|
||||
var glyphIndexArrayLength = _.reduce(_.map(glyphIndexArrays, 'length'), function (result, count) { return result + count; }, 0);
|
||||
|
||||
var length = (0
|
||||
+ 2 // segCountX2
|
||||
+ 2 // searchRange
|
||||
+ 2 // entrySelector
|
||||
+ 2 // rangeShift
|
||||
+ 2 * segCount // endCodes
|
||||
+ 2 // Padding
|
||||
+ 2 * segCount //startCodes
|
||||
+ 2 * segCount //idDeltas
|
||||
+ 2 * segCount //idRangeOffsets
|
||||
+ 2 * glyphIndexArrayLength
|
||||
);
|
||||
|
||||
var buffer = bufferForTable(FORMAT, length);
|
||||
|
||||
buffer.writeUint16(segCount * 2); // segCountX2
|
||||
var maxExponent = Math.floor(Math.log(segCount) / Math.LN2);
|
||||
var searchRange = 2 * Math.pow(2, maxExponent);
|
||||
|
||||
buffer.writeUint16(searchRange); // searchRange
|
||||
buffer.writeUint16(maxExponent); // entrySelector
|
||||
buffer.writeUint16(2 * segCount - searchRange); // rangeShift
|
||||
|
||||
// Array of end counts
|
||||
_.forEach(segments, function (segment) {
|
||||
buffer.writeUint16(segment.end);
|
||||
});
|
||||
buffer.writeUint16(0xFFFF); // endCountArray should be finished with 0xFFFF
|
||||
|
||||
buffer.writeUint16(0); // reservedPad
|
||||
|
||||
// Array of start counts
|
||||
_.forEach(segments, function (segment) {
|
||||
buffer.writeUint16(segment.start); //startCountArray
|
||||
});
|
||||
buffer.writeUint16(0xFFFF); // startCountArray should be finished with 0xFFFF
|
||||
|
||||
// Array of deltas. Leave it zero to not complicate things when using the glyph index array
|
||||
for (i = 0; i < segments.length; i++) {
|
||||
buffer.writeUint16(0); // delta is always zero because we use the glyph array
|
||||
}
|
||||
buffer.writeUint16(1); // idDeltaArray should be finished with 1
|
||||
|
||||
// Array of range offsets
|
||||
var offset = 0;
|
||||
|
||||
for (i = 0; i < segments.length; i++) {
|
||||
buffer.writeUint16(2 * ((segments.length - i + 1) + offset));
|
||||
offset += glyphIndexArrays[i].length;
|
||||
}
|
||||
buffer.writeUint16(0); // rangeOffsetArray should be finished with 0
|
||||
|
||||
_.forEach(glyphIndexArrays, function (glyphIndexArray) {
|
||||
_.forEach(glyphIndexArray, function (glyphId) {
|
||||
buffer.writeUint16(glyphId);
|
||||
});
|
||||
});
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createFormat12Table(font) {
|
||||
var FORMAT = 12;
|
||||
|
||||
var codePoints = getCodePoints(font.codePoints);
|
||||
|
||||
var length = (0
|
||||
+ 4 // nGroups
|
||||
+ 4 * codePoints.length // startCharCode
|
||||
+ 4 * codePoints.length // endCharCode
|
||||
+ 4 * codePoints.length // startGlyphCode
|
||||
);
|
||||
|
||||
var buffer = bufferForTable(FORMAT, length);
|
||||
|
||||
buffer.writeUint32(codePoints.length); // nGroups
|
||||
_.forEach(codePoints, function (codePoint) {
|
||||
buffer.writeUint32(codePoint.unicode); // startCharCode
|
||||
buffer.writeUint32(codePoint.unicode); // endCharCode
|
||||
buffer.writeUint32(codePoint.glyph.id); // startGlyphCode
|
||||
});
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createCMapTable(font) {
|
||||
var TABLE_HEAD = (0
|
||||
+ 2 // platform
|
||||
+ 2 // encoding
|
||||
+ 4 // offset
|
||||
);
|
||||
|
||||
var singleByteTable = createFormat0Table(font);
|
||||
var twoByteTable = createFormat4Table(font);
|
||||
var fourByteTable = createFormat12Table(font);
|
||||
|
||||
// Subtable headers must be sorted by platformID, encodingID
|
||||
var tableHeaders = [
|
||||
// subtable 4, unicode
|
||||
{
|
||||
platformID: 0,
|
||||
encodingID: 3,
|
||||
table: twoByteTable
|
||||
},
|
||||
// subtable 12, unicode
|
||||
{
|
||||
platformID: 0,
|
||||
encodingID: 4,
|
||||
table: fourByteTable
|
||||
},
|
||||
// subtable 0, mac standard
|
||||
{
|
||||
platformID: 1,
|
||||
encodingID: 0,
|
||||
table: singleByteTable
|
||||
},
|
||||
// subtable 4, windows standard, identical to the unicode table
|
||||
{
|
||||
platformID: 3,
|
||||
encodingID: 1,
|
||||
table: twoByteTable
|
||||
},
|
||||
// subtable 12, windows ucs4
|
||||
{
|
||||
platformID: 3,
|
||||
encodingID: 10,
|
||||
table: fourByteTable
|
||||
}
|
||||
];
|
||||
|
||||
var tables = [
|
||||
twoByteTable,
|
||||
singleByteTable,
|
||||
fourByteTable
|
||||
];
|
||||
|
||||
var tableOffset = (0
|
||||
+ 2 // version
|
||||
+ 2 // number of subtable headers
|
||||
+ tableHeaders.length * TABLE_HEAD
|
||||
);
|
||||
|
||||
// Calculate offsets for each table
|
||||
_.forEach(tables, function (table) {
|
||||
table._tableOffset = tableOffset;
|
||||
tableOffset += table.length;
|
||||
});
|
||||
|
||||
var length = tableOffset;
|
||||
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// Write table header.
|
||||
buffer.writeUint16(0); // version
|
||||
buffer.writeUint16(tableHeaders.length); // count
|
||||
|
||||
// Write subtable headers
|
||||
_.forEach(tableHeaders, function (header) {
|
||||
buffer.writeUint16(header.platformID); // platform
|
||||
buffer.writeUint16(header.encodingID); // encoding
|
||||
buffer.writeUint32(header.table._tableOffset); // offset
|
||||
});
|
||||
|
||||
// Write subtables
|
||||
_.forEach(tables, function (table) {
|
||||
buffer.writeBytes(table.buffer);
|
||||
});
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
module.exports = createCMapTable;
|
||||
195
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/glyf.js
generated
vendored
Normal file
195
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/glyf.js
generated
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/glyf.htm
|
||||
|
||||
var _ = require('lodash');
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
function getFlags(glyph) {
|
||||
var result = [];
|
||||
|
||||
_.forEach(glyph.ttfContours, function (contour) {
|
||||
_.forEach(contour, function (point) {
|
||||
var flag = point.onCurve ? 1 : 0;
|
||||
|
||||
if (point.x === 0) {
|
||||
flag += 16;
|
||||
} else {
|
||||
if (-0xFF <= point.x && point.x <= 0xFF) {
|
||||
flag += 2; // the corresponding x-coordinate is 1 byte long
|
||||
}
|
||||
if (point.x > 0 && point.x <= 0xFF) {
|
||||
flag += 16; // If x-Short Vector is set, this bit describes the sign of the value, with 1 equalling positive and 0 negative
|
||||
}
|
||||
}
|
||||
if (point.y === 0) {
|
||||
flag += 32;
|
||||
} else {
|
||||
if (-0xFF <= point.y && point.y <= 0xFF) {
|
||||
flag += 4; // the corresponding y-coordinate is 1 byte long
|
||||
}
|
||||
if (point.y > 0 && point.y <= 0xFF) {
|
||||
flag += 32; // If y-Short Vector is set, this bit describes the sign of the value, with 1 equalling positive and 0 negative.
|
||||
}
|
||||
}
|
||||
result.push(flag);
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
//repeating flags can be packed
|
||||
function compactFlags(flags) {
|
||||
var result = [];
|
||||
var prevFlag = -1;
|
||||
var firstRepeat = false;
|
||||
|
||||
_.forEach(flags, function (flag) {
|
||||
if (prevFlag === flag) {
|
||||
if (firstRepeat) {
|
||||
result[result.length - 1] += 8; //current flag repeats previous one, need to set 3rd bit of previous flag and set 1 to the current one
|
||||
result.push(1);
|
||||
firstRepeat = false;
|
||||
} else {
|
||||
result[result.length - 1]++; //when flag is repeating second or more times, we need to increase the last flag value
|
||||
}
|
||||
} else {
|
||||
firstRepeat = true;
|
||||
prevFlag = flag;
|
||||
result.push(flag);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function getCoords(glyph, coordName) {
|
||||
var result = [];
|
||||
|
||||
_.forEach(glyph.ttfContours, function (contour) {
|
||||
result.push.apply(result, _.map(contour, coordName));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function compactCoords(coords) {
|
||||
return _.filter(coords, function (coord) {
|
||||
return coord !== 0;
|
||||
});
|
||||
}
|
||||
|
||||
//calculates length of glyph data in GLYF table
|
||||
function glyphDataSize(glyph) {
|
||||
// Ignore glyphs without outlines. These will get a length of zero in the “loca” table
|
||||
if (!glyph.contours.length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var result = 12; //glyph fixed properties
|
||||
|
||||
result += glyph.contours.length * 2; //add contours
|
||||
|
||||
_.forEach(glyph.ttf_x, function (x) {
|
||||
//add 1 or 2 bytes for each coordinate depending of its size
|
||||
result += ((-0xFF <= x && x <= 0xFF)) ? 1 : 2;
|
||||
});
|
||||
|
||||
_.forEach(glyph.ttf_y, function (y) {
|
||||
//add 1 or 2 bytes for each coordinate depending of its size
|
||||
result += ((-0xFF <= y && y <= 0xFF)) ? 1 : 2;
|
||||
});
|
||||
|
||||
// Add flags length to glyph size.
|
||||
result += glyph.ttf_flags.length;
|
||||
|
||||
if (result % 4 !== 0) { // glyph size must be divisible by 4.
|
||||
result += 4 - result % 4;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function tableSize(font) {
|
||||
var result = 0;
|
||||
|
||||
_.forEach(font.glyphs, function (glyph) {
|
||||
glyph.ttf_size = glyphDataSize(glyph);
|
||||
result += glyph.ttf_size;
|
||||
});
|
||||
font.ttf_glyph_size = result; //sum of all glyph lengths
|
||||
return result;
|
||||
}
|
||||
|
||||
function createGlyfTable(font) {
|
||||
|
||||
_.forEach(font.glyphs, function (glyph) {
|
||||
glyph.ttf_flags = getFlags(glyph);
|
||||
glyph.ttf_flags = compactFlags(glyph.ttf_flags);
|
||||
glyph.ttf_x = getCoords(glyph, 'x');
|
||||
glyph.ttf_x = compactCoords(glyph.ttf_x);
|
||||
glyph.ttf_y = getCoords(glyph, 'y');
|
||||
glyph.ttf_y = compactCoords(glyph.ttf_y);
|
||||
});
|
||||
|
||||
var buf = new ByteBuffer(tableSize(font));
|
||||
|
||||
_.forEach(font.glyphs, function (glyph) {
|
||||
|
||||
// Ignore glyphs without outlines. These will get a length of zero in the “loca” table
|
||||
if (!glyph.contours.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var offset = buf.tell();
|
||||
|
||||
buf.writeInt16(glyph.contours.length); // numberOfContours
|
||||
buf.writeInt16(glyph.xMin); // xMin
|
||||
buf.writeInt16(glyph.yMin); // yMin
|
||||
buf.writeInt16(glyph.xMax); // xMax
|
||||
buf.writeInt16(glyph.yMax); // yMax
|
||||
|
||||
// Array of end points
|
||||
var endPtsOfContours = -1;
|
||||
|
||||
var ttfContours = glyph.ttfContours;
|
||||
|
||||
_.forEach(ttfContours, function (contour) {
|
||||
endPtsOfContours += contour.length;
|
||||
buf.writeInt16(endPtsOfContours);
|
||||
});
|
||||
|
||||
buf.writeInt16(0); // instructionLength, is not used here
|
||||
|
||||
// Array of flags
|
||||
_.forEach(glyph.ttf_flags, function (flag) {
|
||||
buf.writeInt8(flag);
|
||||
});
|
||||
|
||||
// Array of X relative coordinates
|
||||
_.forEach(glyph.ttf_x, function (x) {
|
||||
if (-0xFF <= x && x <= 0xFF) {
|
||||
buf.writeUint8(Math.abs(x));
|
||||
} else {
|
||||
buf.writeInt16(x);
|
||||
}
|
||||
});
|
||||
|
||||
// Array of Y relative coordinates
|
||||
_.forEach(glyph.ttf_y, function (y) {
|
||||
if (-0xFF <= y && y <= 0xFF) {
|
||||
buf.writeUint8(Math.abs(y));
|
||||
} else {
|
||||
buf.writeInt16(y);
|
||||
}
|
||||
});
|
||||
|
||||
var tail = (buf.tell() - offset) % 4;
|
||||
|
||||
if (tail !== 0) { // glyph size must be divisible by 4.
|
||||
for (; tail < 4; tail++) {
|
||||
buf.writeUint8(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
return buf;
|
||||
}
|
||||
|
||||
module.exports = createGlyfTable;
|
||||
407
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/gsub.js
generated
vendored
Normal file
407
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/gsub.js
generated
vendored
Normal file
@ -0,0 +1,407 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/GSUB.htm
|
||||
|
||||
var _ = require('lodash');
|
||||
var identifier = require('../utils.js').identifier;
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
function createScript() {
|
||||
var scriptRecord = (0
|
||||
+ 2 // Script DefaultLangSys Offset
|
||||
+ 2 // Script[0] LangSysCount (0)
|
||||
);
|
||||
|
||||
var langSys = (0
|
||||
+ 2 // Script DefaultLangSys LookupOrder
|
||||
+ 2 // Script DefaultLangSys ReqFeatureIndex
|
||||
+ 2 // Script DefaultLangSys FeatureCount (0?)
|
||||
+ 2 // Script Optional Feature Index[0]
|
||||
);
|
||||
|
||||
var length = (0
|
||||
+ scriptRecord
|
||||
+ langSys
|
||||
);
|
||||
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// Script Record
|
||||
// Offset to the start of langSys from the start of scriptRecord
|
||||
buffer.writeUint16(scriptRecord); // DefaultLangSys
|
||||
|
||||
// Number of LangSys entries other than the default (none)
|
||||
buffer.writeUint16(0);
|
||||
|
||||
// LangSys record (DefaultLangSys)
|
||||
// LookupOrder
|
||||
buffer.writeUint16(0);
|
||||
// ReqFeatureIndex -> only one required feature: all ligatures
|
||||
buffer.writeUint16(0);
|
||||
// Number of FeatureIndex values for this language system (excludes the required feature)
|
||||
buffer.writeUint16(1);
|
||||
// FeatureIndex for the first optional feature
|
||||
// Note: Adding the same feature to both the optional
|
||||
// and the required features is a clear violation of the spec
|
||||
// but it fixes IE not displaying the ligatures.
|
||||
// See http://partners.adobe.com/public/developer/opentype/index_table_formats.html, Section “Language System Table”
|
||||
// “FeatureCount: Number of FeatureIndex values for this language system-*excludes the required feature*” (emphasis added)
|
||||
buffer.writeUint16(0);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createScriptList() {
|
||||
var scriptSize = (0
|
||||
+ 4 // Tag
|
||||
+ 2 // Offset
|
||||
);
|
||||
|
||||
// tags should be arranged alphabetically
|
||||
var scripts = [
|
||||
[ 'DFLT', createScript() ],
|
||||
[ 'latn', createScript() ]
|
||||
];
|
||||
|
||||
var header = (0
|
||||
+ 2 // Script count
|
||||
+ scripts.length * scriptSize
|
||||
);
|
||||
|
||||
var tableLengths = _.reduce(_.map(scripts, function (script) { return script[1].length; }), function (result, count) { return result + count; }, 0);
|
||||
|
||||
var length = (0
|
||||
+ header
|
||||
+ tableLengths
|
||||
);
|
||||
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// Script count
|
||||
buffer.writeUint16(scripts.length);
|
||||
|
||||
// Write all ScriptRecords
|
||||
var offset = header;
|
||||
|
||||
_.forEach(scripts, function (script) {
|
||||
var name = script[0], table = script[1];
|
||||
|
||||
// Script identifier (DFLT/latn)
|
||||
buffer.writeUint32(identifier(name));
|
||||
// Offset to the ScriptRecord from start of the script list
|
||||
buffer.writeUint16(offset);
|
||||
// Increment offset by script table length
|
||||
offset += table.length;
|
||||
});
|
||||
|
||||
// Write all ScriptTables
|
||||
_.forEach(scripts, function (script) {
|
||||
var table = script[1];
|
||||
|
||||
buffer.writeBytes(table.buffer);
|
||||
});
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Write one feature containing all ligatures
|
||||
function createFeatureList() {
|
||||
var header = (0
|
||||
+ 2 // FeatureCount
|
||||
+ 4 // FeatureTag[0]
|
||||
+ 2 // Feature Offset[0]
|
||||
);
|
||||
|
||||
var length = (0
|
||||
+ header
|
||||
+ 2 // FeatureParams[0]
|
||||
+ 2 // LookupCount[0]
|
||||
+ 2 // Lookup[0] LookupListIndex[0]
|
||||
);
|
||||
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// FeatureCount
|
||||
buffer.writeUint16(1);
|
||||
// FeatureTag[0]
|
||||
buffer.writeUint32(identifier('liga'));
|
||||
// Feature Offset[0]
|
||||
buffer.writeUint16(header);
|
||||
// FeatureParams[0]
|
||||
buffer.writeUint16(0);
|
||||
// LookupCount[0]
|
||||
buffer.writeUint16(1);
|
||||
// Index into lookup table. Since we only have ligatures, the index is always 0
|
||||
buffer.writeUint16(0);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createLigatureCoverage(font, ligatureGroups) {
|
||||
var glyphCount = ligatureGroups.length;
|
||||
|
||||
var length = (0
|
||||
+ 2 // CoverageFormat
|
||||
+ 2 // GlyphCount
|
||||
+ 2 * glyphCount // GlyphID[i]
|
||||
);
|
||||
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// CoverageFormat
|
||||
buffer.writeUint16(1);
|
||||
|
||||
// Length
|
||||
buffer.writeUint16(glyphCount);
|
||||
|
||||
|
||||
_.forEach(ligatureGroups, function (group) {
|
||||
buffer.writeUint16(group.startGlyph.id);
|
||||
});
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createLigatureTable(font, ligature) {
|
||||
var allCodePoints = font.codePoints;
|
||||
|
||||
var unicode = ligature.unicode;
|
||||
|
||||
var length = (0
|
||||
+ 2 // LigGlyph
|
||||
+ 2 // CompCount
|
||||
+ 2 * (unicode.length - 1)
|
||||
);
|
||||
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// LigGlyph
|
||||
var glyph = ligature.glyph;
|
||||
|
||||
buffer.writeUint16(glyph.id);
|
||||
|
||||
// CompCount
|
||||
buffer.writeUint16(unicode.length);
|
||||
|
||||
// Compound glyphs (excluding first as it’s already in the coverage table)
|
||||
for (var i = 1; i < unicode.length; i++) {
|
||||
glyph = allCodePoints[unicode[i]];
|
||||
buffer.writeUint16(glyph.id);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createLigatureSet(font, codePoint, ligatures) {
|
||||
var ligatureTables = [];
|
||||
|
||||
_.forEach(ligatures, function (ligature) {
|
||||
ligatureTables.push(createLigatureTable(font, ligature));
|
||||
});
|
||||
|
||||
var tableLengths = _.reduce(_.map(ligatureTables, 'length'), function (result, count) { return result + count; }, 0);
|
||||
|
||||
var offset = (0
|
||||
+ 2 // LigatureCount
|
||||
+ 2 * ligatures.length
|
||||
);
|
||||
|
||||
var length = (0
|
||||
+ offset
|
||||
+ tableLengths
|
||||
);
|
||||
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// LigatureCount
|
||||
buffer.writeUint16(ligatures.length);
|
||||
|
||||
// Ligature offsets
|
||||
_.forEach(ligatureTables, function (table) {
|
||||
// The offset to the current set, from SubstFormat
|
||||
buffer.writeUint16(offset);
|
||||
offset += table.length;
|
||||
});
|
||||
|
||||
// Ligatures
|
||||
_.forEach(ligatureTables, function (table) {
|
||||
buffer.writeBytes(table.buffer);
|
||||
});
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createLigatureList(font, ligatureGroups) {
|
||||
var sets = [];
|
||||
|
||||
_.forEach(ligatureGroups, function (group) {
|
||||
var set = createLigatureSet(font, group.codePoint, group.ligatures);
|
||||
|
||||
sets.push(set);
|
||||
});
|
||||
|
||||
var setLengths = _.reduce(_.map(sets, 'length'), function (result, count) { return result + count; }, 0);
|
||||
|
||||
var coverage = createLigatureCoverage(font, ligatureGroups);
|
||||
|
||||
var tableOffset = (0
|
||||
+ 2 // Lookup type
|
||||
+ 2 // Lokup flag
|
||||
+ 2 // SubTableCount
|
||||
+ 2 // SubTable[0] Offset
|
||||
);
|
||||
|
||||
var setOffset = (0
|
||||
+ 2 // SubstFormat
|
||||
+ 2 // Coverage offset
|
||||
+ 2 // LigSetCount
|
||||
+ 2 * sets.length // LigSet Offsets
|
||||
);
|
||||
|
||||
var coverageOffset = setOffset + setLengths;
|
||||
|
||||
var length = (0
|
||||
+ tableOffset
|
||||
+ coverageOffset
|
||||
+ coverage.length
|
||||
);
|
||||
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// Lookup type 4 – ligatures
|
||||
buffer.writeUint16(4);
|
||||
|
||||
// Lookup flag – empty
|
||||
buffer.writeUint16(0);
|
||||
|
||||
// Subtable count
|
||||
buffer.writeUint16(1);
|
||||
|
||||
// Subtable[0] offset
|
||||
buffer.writeUint16(tableOffset);
|
||||
|
||||
// SubstFormat
|
||||
buffer.writeUint16(1);
|
||||
|
||||
// Coverage
|
||||
buffer.writeUint16(coverageOffset);
|
||||
|
||||
// LigSetCount
|
||||
buffer.writeUint16(sets.length);
|
||||
|
||||
_.forEach(sets, function (set) {
|
||||
// The offset to the current set, from SubstFormat
|
||||
buffer.writeUint16(setOffset);
|
||||
setOffset += set.length;
|
||||
});
|
||||
|
||||
_.forEach(sets, function (set) {
|
||||
buffer.writeBytes(set.buffer);
|
||||
});
|
||||
|
||||
buffer.writeBytes(coverage.buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Add a lookup for each ligature
|
||||
function createLookupList(font) {
|
||||
var ligatures = font.ligatures;
|
||||
|
||||
var groupedLigatures = {};
|
||||
|
||||
// Group ligatures by first code point
|
||||
_.forEach(ligatures, function (ligature) {
|
||||
var first = ligature.unicode[0];
|
||||
|
||||
if (!_.has(groupedLigatures, first)) {
|
||||
groupedLigatures[first] = [];
|
||||
}
|
||||
groupedLigatures[first].push(ligature);
|
||||
});
|
||||
|
||||
var ligatureGroups = [];
|
||||
|
||||
_.forEach(groupedLigatures, function (ligatures, codePoint) {
|
||||
codePoint = parseInt(codePoint, 10);
|
||||
// Order ligatures by length, descending
|
||||
// “Ligatures with more components must be stored ahead of those with fewer components in order to be found”
|
||||
// From: http://partners.adobe.com/public/developer/opentype/index_tag7.html#liga
|
||||
ligatures.sort(function (ligA, ligB) {
|
||||
return ligB.unicode.length - ligA.unicode.length;
|
||||
});
|
||||
ligatureGroups.push({
|
||||
codePoint: codePoint,
|
||||
ligatures: ligatures,
|
||||
startGlyph: font.codePoints[codePoint]
|
||||
});
|
||||
});
|
||||
|
||||
ligatureGroups.sort(function (a, b) {
|
||||
return a.startGlyph.id - b.startGlyph.id;
|
||||
});
|
||||
|
||||
var offset = (0
|
||||
+ 2 // Lookup count
|
||||
+ 2 // Lookup[0] offset
|
||||
);
|
||||
|
||||
var set = createLigatureList(font, ligatureGroups);
|
||||
|
||||
var length = (0
|
||||
+ offset
|
||||
+ set.length
|
||||
);
|
||||
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// Lookup count
|
||||
buffer.writeUint16(1);
|
||||
|
||||
// Lookup[0] offset
|
||||
buffer.writeUint16(offset);
|
||||
|
||||
// Lookup[0]
|
||||
buffer.writeBytes(set.buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createGSUB(font) {
|
||||
var scriptList = createScriptList();
|
||||
var featureList = createFeatureList();
|
||||
var lookupList = createLookupList(font);
|
||||
|
||||
var lists = [ scriptList, featureList, lookupList ];
|
||||
|
||||
var offset = (0
|
||||
+ 4 // Version
|
||||
+ 2 * lists.length // List offsets
|
||||
);
|
||||
|
||||
// Calculate offsets
|
||||
_.forEach(lists, function (list) {
|
||||
list._listOffset = offset;
|
||||
offset += list.length;
|
||||
});
|
||||
|
||||
var length = offset;
|
||||
var buffer = new ByteBuffer(length);
|
||||
|
||||
// Version
|
||||
buffer.writeUint32(0x00010000);
|
||||
|
||||
// Offsets
|
||||
_.forEach(lists, function (list) {
|
||||
buffer.writeUint16(list._listOffset);
|
||||
});
|
||||
|
||||
// List contents
|
||||
_.forEach(lists, function (list) {
|
||||
buffer.writeBytes(list.buffer);
|
||||
});
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
module.exports = createGSUB;
|
||||
42
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/head.js
generated
vendored
Normal file
42
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/head.js
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/head.htm
|
||||
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
function dateToUInt64(date) {
|
||||
var startDate = new Date('1904-01-01T00:00:00.000Z');
|
||||
|
||||
return Math.floor((date - startDate) / 1000);
|
||||
}
|
||||
|
||||
function createHeadTable(font) {
|
||||
|
||||
var buf = new ByteBuffer(54); // fixed table length
|
||||
|
||||
buf.writeInt32(0x10000); // version
|
||||
buf.writeInt32(font.revision * 0x10000); // fontRevision
|
||||
buf.writeUint32(0); // checkSumAdjustment
|
||||
buf.writeUint32(0x5F0F3CF5); // magicNumber
|
||||
// FLag meanings:
|
||||
// Bit 0: Baseline for font at y=0;
|
||||
// Bit 1: Left sidebearing point at x=0;
|
||||
// Bit 3: Force ppem to integer values for all internal scaler math; may use fractional ppem sizes if this bit is clear;
|
||||
buf.writeUint16(0x000B); // flags
|
||||
buf.writeUint16(font.unitsPerEm); // unitsPerEm
|
||||
buf.writeUint64(dateToUInt64(font.createdDate)); // created
|
||||
buf.writeUint64(dateToUInt64(font.modifiedDate)); // modified
|
||||
buf.writeInt16(font.xMin); // xMin
|
||||
buf.writeInt16(font.yMin); // yMin
|
||||
buf.writeInt16(font.xMax); // xMax
|
||||
buf.writeInt16(font.yMax); // yMax
|
||||
buf.writeUint16(font.macStyle); //macStyle
|
||||
buf.writeUint16(font.lowestRecPPEM); // lowestRecPPEM
|
||||
buf.writeInt16(2); // fontDirectionHint
|
||||
buf.writeInt16(font.ttf_glyph_size < 0x20000 ? 0 : 1); // indexToLocFormat, 0 for short offsets, 1 for long offsets
|
||||
buf.writeInt16(0); // glyphDataFormat
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
module.exports = createHeadTable;
|
||||
31
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/hhea.js
generated
vendored
Normal file
31
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/hhea.js
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/hhea.htm
|
||||
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
function createHHeadTable(font) {
|
||||
|
||||
var buf = new ByteBuffer(36); // fixed table length
|
||||
|
||||
buf.writeInt32(0x10000); // version
|
||||
buf.writeInt16(font.ascent); // ascent
|
||||
buf.writeInt16(font.descent); // descend
|
||||
// Non zero lineGap causes offset in IE, https://github.com/fontello/svg2ttf/issues/37
|
||||
buf.writeInt16(0); // lineGap
|
||||
buf.writeUint16(font.maxWidth); // advanceWidthMax
|
||||
buf.writeInt16(font.minLsb); // minLeftSideBearing
|
||||
buf.writeInt16(font.minRsb); // minRightSideBearing
|
||||
buf.writeInt16(font.maxExtent); // xMaxExtent
|
||||
buf.writeInt16(1); // caretSlopeRise
|
||||
buf.writeInt16(0); // caretSlopeRun
|
||||
buf.writeUint32(0); // reserved1
|
||||
buf.writeUint32(0); // reserved2
|
||||
buf.writeUint16(0); // reserved3
|
||||
buf.writeInt16(0); // metricDataFormat
|
||||
buf.writeUint16(font.glyphs.length); // numberOfHMetrics
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
module.exports = createHHeadTable;
|
||||
19
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/hmtx.js
generated
vendored
Normal file
19
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/hmtx.js
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/hmtx.htm
|
||||
|
||||
var _ = require('lodash');
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
function createHtmxTable(font) {
|
||||
|
||||
var buf = new ByteBuffer(font.glyphs.length * 4);
|
||||
|
||||
_.forEach(font.glyphs, function (glyph) {
|
||||
buf.writeUint16(glyph.width); //advanceWidth
|
||||
buf.writeInt16(glyph.xMin); //lsb
|
||||
});
|
||||
return buf;
|
||||
}
|
||||
|
||||
module.exports = createHtmxTable;
|
||||
43
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/loca.js
generated
vendored
Normal file
43
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/loca.js
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/loca.htm
|
||||
|
||||
var _ = require('lodash');
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
function tableSize(font, isShortFormat) {
|
||||
var result = (font.glyphs.length + 1) * (isShortFormat ? 2 : 4); // by glyph count + tail
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function createLocaTable(font) {
|
||||
|
||||
var isShortFormat = font.ttf_glyph_size < 0x20000;
|
||||
|
||||
var buf = new ByteBuffer(tableSize(font, isShortFormat));
|
||||
|
||||
var location = 0;
|
||||
|
||||
// Array of offsets in GLYF table for each glyph
|
||||
_.forEach(font.glyphs, function (glyph) {
|
||||
if (isShortFormat) {
|
||||
buf.writeUint16(location);
|
||||
location += glyph.ttf_size / 2; // actual location must be divided to 2 in short format
|
||||
} else {
|
||||
buf.writeUint32(location);
|
||||
location += glyph.ttf_size; //actual location is stored as is in long format
|
||||
}
|
||||
});
|
||||
|
||||
// The last glyph location is stored to get last glyph length
|
||||
if (isShortFormat) {
|
||||
buf.writeUint16(location);
|
||||
} else {
|
||||
buf.writeUint32(location);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
module.exports = createLocaTable;
|
||||
46
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/maxp.js
generated
vendored
Normal file
46
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/maxp.js
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/maxp.htm
|
||||
|
||||
var _ = require('lodash');
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
// Find max points in glyph TTF contours.
|
||||
function getMaxPoints(font) {
|
||||
return _.max(_.map(font.glyphs, function (glyph) {
|
||||
return _.reduce(glyph.ttfContours, function (sum, ctr) { return sum + ctr.length; }, 0);
|
||||
}));
|
||||
}
|
||||
|
||||
function getMaxContours(font) {
|
||||
return _.max(_.map(font.glyphs, function (glyph) {
|
||||
return glyph.ttfContours.length;
|
||||
}));
|
||||
}
|
||||
|
||||
function createMaxpTable(font) {
|
||||
|
||||
var buf = new ByteBuffer(32);
|
||||
|
||||
buf.writeInt32(0x10000); // version
|
||||
buf.writeUint16(font.glyphs.length); // numGlyphs
|
||||
buf.writeUint16(getMaxPoints(font)); // maxPoints
|
||||
buf.writeUint16(getMaxContours(font)); // maxContours
|
||||
buf.writeUint16(0); // maxCompositePoints
|
||||
buf.writeUint16(0); // maxCompositeContours
|
||||
buf.writeUint16(2); // maxZones
|
||||
buf.writeUint16(0); // maxTwilightPoints
|
||||
// It is unclear how to calculate maxStorage, maxFunctionDefs and maxInstructionDefs.
|
||||
// These are magic constants now, with values exceeding values from FontForge
|
||||
buf.writeUint16(10); // maxStorage
|
||||
buf.writeUint16(10); // maxFunctionDefs
|
||||
buf.writeUint16(0); // maxInstructionDefs
|
||||
buf.writeUint16(255); // maxStackElements
|
||||
buf.writeUint16(0); // maxSizeOfInstructions
|
||||
buf.writeUint16(0); // maxComponentElements
|
||||
buf.writeUint16(0); // maxComponentDepth
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
module.exports = createMaxpTable;
|
||||
106
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/name.js
generated
vendored
Normal file
106
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/name.js
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/name.htm
|
||||
|
||||
var _ = require('lodash');
|
||||
var ByteBuffer = require('microbuffer');
|
||||
var Str = require('../../str');
|
||||
|
||||
var TTF_NAMES = {
|
||||
COPYRIGHT: 0,
|
||||
FONT_FAMILY: 1,
|
||||
ID: 3,
|
||||
DESCRIPTION: 10,
|
||||
URL_VENDOR: 11
|
||||
};
|
||||
|
||||
function tableSize(names) {
|
||||
var result = 6; // table header
|
||||
|
||||
_.forEach(names, function (name) {
|
||||
result += 12 + name.data.length; //name header and data
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function getStrings(name, id) {
|
||||
var result = [];
|
||||
var str = new Str(name);
|
||||
|
||||
result.push({ data: str.toUTF8Bytes(), id: id, platformID : 1, encodingID : 0, languageID : 0 }); //mac standard
|
||||
result.push({ data: str.toUCS2Bytes(), id: id, platformID : 3, encodingID : 1, languageID : 0x409 }); //windows standard
|
||||
return result;
|
||||
}
|
||||
|
||||
// Collect font names
|
||||
function getNames(font) {
|
||||
var result = [];
|
||||
|
||||
if (font.copyright) {
|
||||
result.push.apply(result, getStrings(font.copyright, TTF_NAMES.COPYRIGHT));
|
||||
}
|
||||
if (font.familyName) {
|
||||
result.push.apply(result, getStrings(font.familyName, TTF_NAMES.FONT_FAMILY));
|
||||
}
|
||||
if (font.id) {
|
||||
result.push.apply(result, getStrings(font.id, TTF_NAMES.ID));
|
||||
}
|
||||
result.push.apply(result, getStrings('Generated by svg2ttf from Fontello project.', TTF_NAMES.DESCRIPTION));
|
||||
result.push.apply(result, getStrings('http://fontello.com', TTF_NAMES.URL_VENDOR));
|
||||
|
||||
_.forEach(font.sfntNames, function (sfntName) {
|
||||
result.push.apply(result, getStrings(sfntName.value, sfntName.id));
|
||||
});
|
||||
|
||||
result.sort(function (a, b) {
|
||||
var orderFields = [ 'platformID', 'encodingID', 'languageID', 'id' ];
|
||||
var i;
|
||||
|
||||
for (i = 0; i < orderFields.length; i++) {
|
||||
if (a[orderFields[i]] !== b[orderFields[i]]) {
|
||||
return a[orderFields[i]] < b[orderFields[i]] ? -1 : 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function createNameTable(font) {
|
||||
|
||||
var names = getNames(font);
|
||||
|
||||
var buf = new ByteBuffer(tableSize(names));
|
||||
|
||||
buf.writeUint16(0); // formatSelector
|
||||
buf.writeUint16(names.length); // nameRecordsCount
|
||||
var offsetPosition = buf.tell();
|
||||
|
||||
buf.writeUint16(0); // offset, will be filled later
|
||||
var nameOffset = 0;
|
||||
|
||||
_.forEach(names, function (name) {
|
||||
buf.writeUint16(name.platformID); // platformID
|
||||
buf.writeUint16(name.encodingID); // platEncID
|
||||
buf.writeUint16(name.languageID); // languageID, English (USA)
|
||||
buf.writeUint16(name.id); // nameID
|
||||
buf.writeUint16(name.data.length); // reclength
|
||||
buf.writeUint16(nameOffset); // offset
|
||||
nameOffset += name.data.length;
|
||||
});
|
||||
var actualStringDataOffset = buf.tell();
|
||||
|
||||
//Array of bytes with actual string data
|
||||
_.forEach(names, function (name) {
|
||||
buf.writeBytes(name.data);
|
||||
});
|
||||
|
||||
//write actual string data offset
|
||||
buf.seek(offsetPosition);
|
||||
buf.writeUint16(actualStringDataOffset); // offset
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
module.exports = createNameTable;
|
||||
74
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/os2.js
generated
vendored
Normal file
74
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/os2.js
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/os2.htm
|
||||
|
||||
var _ = require('lodash');
|
||||
var identifier = require('../utils.js').identifier;
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
//get first glyph unicode
|
||||
function getFirstCharIndex(font) {
|
||||
return Math.max(0, Math.min(0xffff, Math.abs(_.minBy(Object.keys(font.codePoints), function (point) {
|
||||
return parseInt(point, 10);
|
||||
}))));
|
||||
}
|
||||
|
||||
//get last glyph unicode
|
||||
function getLastCharIndex(font) {
|
||||
return Math.max(0, Math.min(0xffff, Math.abs(_.maxBy(Object.keys(font.codePoints), function (point) {
|
||||
return parseInt(point, 10);
|
||||
}))));
|
||||
}
|
||||
|
||||
function createOS2Table(font) {
|
||||
|
||||
var buf = new ByteBuffer(86);
|
||||
|
||||
buf.writeUint16(1); //version
|
||||
buf.writeInt16(font.avgWidth); // xAvgCharWidth
|
||||
buf.writeUint16(font.weightClass); // usWeightClass
|
||||
buf.writeUint16(font.widthClass); // usWidthClass
|
||||
buf.writeInt16(font.fsType); // fsType
|
||||
buf.writeInt16(font.ySubscriptXSize); // ySubscriptXSize
|
||||
buf.writeInt16(font.ySubscriptYSize); //ySubscriptYSize
|
||||
buf.writeInt16(font.ySubscriptXOffset); // ySubscriptXOffset
|
||||
buf.writeInt16(font.ySubscriptYOffset); // ySubscriptYOffset
|
||||
buf.writeInt16(font.ySuperscriptXSize); // ySuperscriptXSize
|
||||
buf.writeInt16(font.ySuperscriptYSize); // ySuperscriptYSize
|
||||
buf.writeInt16(font.ySuperscriptXOffset); // ySuperscriptXOffset
|
||||
buf.writeInt16(font.ySuperscriptYOffset); // ySuperscriptYOffset
|
||||
buf.writeInt16(font.yStrikeoutSize); // yStrikeoutSize
|
||||
buf.writeInt16(font.yStrikeoutPosition); // yStrikeoutPosition
|
||||
buf.writeInt16(font.familyClass); // sFamilyClass
|
||||
buf.writeUint8(font.panose.familyType); // panose.bFamilyType
|
||||
buf.writeUint8(font.panose.serifStyle); // panose.bSerifStyle
|
||||
buf.writeUint8(font.panose.weight); // panose.bWeight
|
||||
buf.writeUint8(font.panose.proportion); // panose.bProportion
|
||||
buf.writeUint8(font.panose.contrast); // panose.bContrast
|
||||
buf.writeUint8(font.panose.strokeVariation); // panose.bStrokeVariation
|
||||
buf.writeUint8(font.panose.armStyle); // panose.bArmStyle
|
||||
buf.writeUint8(font.panose.letterform); // panose.bLetterform
|
||||
buf.writeUint8(font.panose.midline); // panose.bMidline
|
||||
buf.writeUint8(font.panose.xHeight); // panose.bXHeight
|
||||
// TODO: This field is used to specify the Unicode blocks or ranges based on the 'cmap' table.
|
||||
buf.writeUint32(0); // ulUnicodeRange1
|
||||
buf.writeUint32(0); // ulUnicodeRange2
|
||||
buf.writeUint32(0); // ulUnicodeRange3
|
||||
buf.writeUint32(0); // ulUnicodeRange4
|
||||
buf.writeUint32(identifier('PfEd')); // achVendID, equal to PfEd
|
||||
buf.writeUint16(font.fsSelection); // fsSelection
|
||||
buf.writeUint16(getFirstCharIndex(font)); // usFirstCharIndex
|
||||
buf.writeUint16(getLastCharIndex(font)); // usLastCharIndex
|
||||
buf.writeInt16(font.ascent); // sTypoAscender
|
||||
buf.writeInt16(font.descent); // sTypoDescender
|
||||
buf.writeInt16(font.lineGap); // lineGap
|
||||
// Enlarge win acscent/descent to avoid clipping
|
||||
buf.writeInt16(Math.max(font.yMax, font.ascent)); // usWinAscent
|
||||
buf.writeInt16(-Math.min(font.yMin, font.descent)); // usWinDescent
|
||||
buf.writeInt32(1); // ulCodePageRange1, Latin 1
|
||||
buf.writeInt32(0); // ulCodePageRange2
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
module.exports = createOS2Table;
|
||||
73
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/post.js
generated
vendored
Normal file
73
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/tables/post.js
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
// See documentation here: http://www.microsoft.com/typography/otspec/post.htm
|
||||
|
||||
var _ = require('lodash');
|
||||
var ByteBuffer = require('microbuffer');
|
||||
|
||||
function tableSize(font, names) {
|
||||
var result = 36; // table header
|
||||
|
||||
result += font.glyphs.length * 2; // name declarations
|
||||
_.forEach(names, function (name) {
|
||||
result += name.length;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function pascalString(str) {
|
||||
var bytes = [];
|
||||
var len = str ? (str.length < 256 ? str.length : 255) : 0; //length in Pascal string is limited with 255
|
||||
|
||||
bytes.push(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
var char = str.charCodeAt(i);
|
||||
|
||||
bytes.push(char < 128 ? char : 95); //non-ASCII characters are substituted with '_'
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function createPostTable(font) {
|
||||
|
||||
var names = [];
|
||||
|
||||
_.forEach(font.glyphs, function (glyph) {
|
||||
if (glyph.unicode !== 0) {
|
||||
names.push(pascalString(glyph.name));
|
||||
}
|
||||
});
|
||||
|
||||
var buf = new ByteBuffer(tableSize(font, names));
|
||||
|
||||
buf.writeInt32(0x20000); // formatType, version 2.0
|
||||
buf.writeInt32(font.italicAngle); // italicAngle
|
||||
buf.writeInt16(font.underlinePosition); // underlinePosition
|
||||
buf.writeInt16(font.underlineThickness); // underlineThickness
|
||||
buf.writeUint32(font.isFixedPitch); // isFixedPitch
|
||||
buf.writeUint32(0); // minMemType42
|
||||
buf.writeUint32(0); // maxMemType42
|
||||
buf.writeUint32(0); // minMemType1
|
||||
buf.writeUint32(0); // maxMemType1
|
||||
buf.writeUint16(font.glyphs.length); // numberOfGlyphs
|
||||
|
||||
// Array of glyph name indexes
|
||||
var index = 258; // first index of custom glyph name, it is calculated as glyph name index + 258
|
||||
|
||||
_.forEach(font.glyphs, function (glyph) {
|
||||
if (glyph.unicode === 0) {
|
||||
buf.writeUint16(0);// missed element should have .notDef name in the Macintosh standard order.
|
||||
} else {
|
||||
buf.writeUint16(index++);
|
||||
}
|
||||
});
|
||||
|
||||
// Array of glyph name indexes
|
||||
_.forEach(names, function (name) {
|
||||
buf.writeBytes(name);
|
||||
});
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
module.exports = createPostTable;
|
||||
129
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/utils.js
generated
vendored
Normal file
129
static/js/ketcher2/node_modules/svg2ttf/lib/ttf/utils.js
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var math = require('../math');
|
||||
|
||||
// Remove points, that looks like straight line
|
||||
function simplify(contours, accuracy) {
|
||||
return _.map(contours, function (contour) {
|
||||
var i, curr, prev, next;
|
||||
var p, pPrev, pNext;
|
||||
|
||||
// run from the end, to simplify array elements removal
|
||||
for (i = contour.length - 2; i > 1; i--) {
|
||||
prev = contour[i - 1];
|
||||
next = contour[i + 1];
|
||||
curr = contour[i];
|
||||
|
||||
// skip point (both oncurve & offcurve),
|
||||
// if [prev,next] is straight line
|
||||
if (prev.onCurve && next.onCurve) {
|
||||
p = new math.Point(curr.x, curr.y);
|
||||
pPrev = new math.Point(prev.x, prev.y);
|
||||
pNext = new math.Point(next.x, next.y);
|
||||
if (math.isInLine(pPrev, p, pNext, accuracy)) {
|
||||
contour.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return contour;
|
||||
});
|
||||
}
|
||||
|
||||
// Remove interpolateable oncurve points
|
||||
// Those should be in the middle of nebor offcurve points
|
||||
function interpolate(contours, accuracy) {
|
||||
return _.map(contours, function (contour) {
|
||||
var resContour = [];
|
||||
|
||||
_.forEach(contour, function (point, idx) {
|
||||
// Never skip first and last points
|
||||
if (idx === 0 || idx === (contour.length - 1)) {
|
||||
resContour.push(point);
|
||||
return;
|
||||
}
|
||||
|
||||
var prev = contour[idx - 1];
|
||||
var next = contour[idx + 1];
|
||||
|
||||
var p, pPrev, pNext;
|
||||
|
||||
// skip interpolateable oncurve points (if exactly between previous and next offcurves)
|
||||
if (!prev.onCurve && point.onCurve && !next.onCurve) {
|
||||
p = new math.Point(point.x, point.y);
|
||||
pPrev = new math.Point(prev.x, prev.y);
|
||||
pNext = new math.Point(next.x, next.y);
|
||||
if (pPrev.add(pNext).div(2).sub(p).dist() < accuracy) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// keep the rest
|
||||
resContour.push(point);
|
||||
});
|
||||
return resContour;
|
||||
});
|
||||
}
|
||||
|
||||
function roundPoints(contours) {
|
||||
return _.map(contours, function (contour) {
|
||||
return _.map(contour, function (point) {
|
||||
return { x: Math.round(point.x), y: Math.round(point.y), onCurve: point.onCurve };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Remove closing point if it is the same as first point of contour.
|
||||
// TTF doesn't need this point when drawing contours.
|
||||
function removeClosingReturnPoints(contours) {
|
||||
return _.map(contours, function (contour) {
|
||||
var length = contour.length;
|
||||
|
||||
if (length > 1 &&
|
||||
contour[0].x === contour[length - 1].x &&
|
||||
contour[0].y === contour[length - 1].y) {
|
||||
contour.splice(length - 1);
|
||||
}
|
||||
return contour;
|
||||
});
|
||||
}
|
||||
|
||||
function toRelative(contours) {
|
||||
var prevPoint = { x: 0, y: 0 };
|
||||
var resContours = [];
|
||||
var resContour;
|
||||
|
||||
_.forEach(contours, function (contour) {
|
||||
resContour = [];
|
||||
resContours.push(resContour);
|
||||
_.forEach(contour, function (point) {
|
||||
resContour.push({
|
||||
x: point.x - prevPoint.x,
|
||||
y: point.y - prevPoint.y,
|
||||
onCurve: point.onCurve
|
||||
});
|
||||
prevPoint = point;
|
||||
});
|
||||
});
|
||||
return resContours;
|
||||
}
|
||||
|
||||
function identifier(string, littleEndian) {
|
||||
var result = 0;
|
||||
|
||||
for (var i = 0; i < string.length; i++) {
|
||||
result = result << 8;
|
||||
var index = littleEndian ? string.length - i - 1 : i;
|
||||
|
||||
result += string.charCodeAt(index);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports.interpolate = interpolate;
|
||||
module.exports.simplify = simplify;
|
||||
module.exports.roundPoints = roundPoints;
|
||||
module.exports.removeClosingReturnPoints = removeClosingReturnPoints;
|
||||
module.exports.toRelative = toRelative;
|
||||
module.exports.identifier = identifier;
|
||||
|
||||
Reference in New Issue
Block a user