Comparing version 1.5.8 to 1.6.0
{ | ||
"name": "fontkit", | ||
"version": "1.5.8", | ||
"version": "1.6.0", | ||
"description": "An advanced font engine for Node and the browser", | ||
@@ -17,3 +17,3 @@ "keywords": [ | ||
"prepublish": "make", | ||
"coverage": "babel-node ./node_modules/.bin/isparta cover ./node_modules/.bin/_mocha" | ||
"coverage": "BABEL_ENV=cover nyc mocha" | ||
}, | ||
@@ -48,2 +48,3 @@ "main": "index.js", | ||
"babel-cli": "^6.14.0", | ||
"babel-plugin-istanbul": "^4.1.3", | ||
"babel-plugin-transform-class-properties": "^6.16.0", | ||
@@ -59,4 +60,4 @@ "babel-plugin-transform-decorators-legacy": "^1.3.4", | ||
"iconv-lite": "^0.4.13", | ||
"isparta": "^3.5.3", | ||
"mocha": "^2.0.1", | ||
"nyc": "^10.3.2", | ||
"rollup": "^0.34.10", | ||
@@ -63,0 +64,0 @@ "rollup-plugin-babel": "^2.6.1", |
@@ -70,3 +70,3 @@ import isEqual from 'deep-equal'; | ||
let b = stream.readUInt8(); | ||
if (b <= 21) { | ||
if (b < 28) { | ||
if (b === 12) { | ||
@@ -73,0 +73,0 @@ b = (b << 8) | stream.readUInt8(); |
@@ -25,8 +25,11 @@ import r from 'restructure'; | ||
if (this.topDictIndex.length !== 1) { | ||
throw new Error("Only a single font is allowed in CFF"); | ||
if (this.version < 2) { | ||
if (this.topDictIndex.length !== 1) { | ||
throw new Error("Only a single font is allowed in CFF"); | ||
} | ||
this.topDict = this.topDictIndex[0]; | ||
} | ||
this.isCIDFont = (this.topDict.ROS != null); | ||
this.isCIDFont = this.topDict.ROS != null; | ||
return this; | ||
@@ -36,2 +39,6 @@ } | ||
string(sid) { | ||
if (this.version >= 2) { | ||
return null; | ||
} | ||
if (sid < standardStrings.length) { | ||
@@ -44,8 +51,8 @@ return standardStrings[sid]; | ||
get topDict() { | ||
return this.topDictIndex[0]; | ||
} | ||
get postscriptName() { | ||
if (this.version < 2) { | ||
return this.nameIndex[0]; | ||
} | ||
get postscriptName() { | ||
return this.nameIndex[0]; | ||
return null; | ||
} | ||
@@ -67,2 +74,7 @@ | ||
getGlyphName(gid) { | ||
// CFF2 glyph names are in the post table. | ||
if (this.version >= 2) { | ||
return null; | ||
} | ||
// CID-keyed fonts don't have glyph names | ||
@@ -103,3 +115,5 @@ if (this.isCIDFont) { | ||
fdForGlyph(gid) { | ||
if (!this.topDict.FDSelect) { return null; } | ||
if (!this.topDict.FDSelect) { | ||
return null; | ||
} | ||
@@ -111,2 +125,3 @@ switch (this.topDict.FDSelect.version) { | ||
case 3: | ||
case 4: | ||
let { ranges } = this.topDict.FDSelect; | ||
@@ -142,3 +157,7 @@ let low = 0; | ||
return this.topDict.Private; | ||
if (this.version < 2) { | ||
return this.topDict.Private; | ||
} | ||
return this.topDict.FDArray[0].Private; | ||
} | ||
@@ -145,0 +164,0 @@ } |
@@ -8,4 +8,16 @@ import r from 'restructure'; | ||
getCFFVersion(ctx) { | ||
while (ctx && !ctx.hdrSize) { | ||
ctx = ctx.parent; | ||
} | ||
return ctx ? ctx.version : -1; | ||
} | ||
decode(stream, parent) { | ||
let count = stream.readUInt16BE(); | ||
let version = this.getCFFVersion(parent); | ||
let count = version >= 2 | ||
? stream.readUInt32BE() | ||
: stream.readUInt16BE(); | ||
if (count === 0) { | ||
@@ -12,0 +24,0 @@ return []; |
@@ -5,2 +5,14 @@ import CFFDict from './CFFDict'; | ||
class CFFBlendOp { | ||
static decode(stream, parent, operands) { | ||
let numBlends = operands.pop(); | ||
// TODO: actually blend. For now just consume the deltas | ||
// since we don't use any of the values anyway. | ||
while (operands.length > numBlends) { | ||
operands.pop(); | ||
} | ||
} | ||
} | ||
export default new CFFDict([ | ||
@@ -25,3 +37,5 @@ // key name type default | ||
[21, 'nominalWidthX', 'number', 0], | ||
[22, 'vsindex', 'number', 0], | ||
[23, 'blend', CFFBlendOp, null], | ||
[19, 'Subrs', new CFFPointer(new CFFIndex, {type: 'local'}), null] | ||
]); |
@@ -10,2 +10,3 @@ import r from 'restructure'; | ||
import { ISOAdobeCharset, ExpertCharset, ExpertSubsetCharset } from './CFFCharsets'; | ||
import { ItemVariationStore } from '../tables/variations'; | ||
@@ -112,3 +113,3 @@ // Checks if an operand is an index of a predefined value, | ||
let FDRange = new r.Struct({ | ||
let FDRange3 = new r.Struct({ | ||
first: r.uint16, | ||
@@ -118,2 +119,7 @@ fd: r.uint8 | ||
let FDRange4 = new r.Struct({ | ||
first: r.uint32, | ||
fd: r.uint16 | ||
}); | ||
let FDSelect = new r.VersionedStruct(r.uint8, { | ||
@@ -126,4 +132,10 @@ 0: { | ||
nRanges: r.uint16, | ||
ranges: new r.Array(FDRange, 'nRanges'), | ||
ranges: new r.Array(FDRange3, 'nRanges'), | ||
sentinel: r.uint16 | ||
}, | ||
4: { | ||
nRanges: r.uint32, | ||
ranges: new r.Array(FDRange4, 'nRanges'), | ||
sentinel: r.uint32 | ||
} | ||
@@ -195,17 +207,34 @@ }); | ||
let CFFHeader = new r.Struct({ | ||
majorVersion: r.uint8, | ||
minorVersion: r.uint8, | ||
hdrSize: r.uint8, | ||
offSize: r.uint8 | ||
}); | ||
let VariationStore = new r.Struct({ | ||
length: r.uint16, | ||
itemVariationStore: ItemVariationStore | ||
}) | ||
let CFFTop = new r.Struct({ | ||
header: CFFHeader, | ||
nameIndex: new CFFIndex(new r.String('length')), | ||
topDictIndex: new CFFIndex(CFFTopDict), | ||
stringIndex: new CFFIndex(new r.String('length')), | ||
globalSubrIndex: new CFFIndex() | ||
let CFF2TopDict = new CFFDict([ | ||
[[12, 7], 'FontMatrix', 'array', [0.001, 0, 0, 0.001, 0, 0]], | ||
[17, 'CharStrings', new CFFPointer(new CFFIndex), null], | ||
[[12, 37], 'FDSelect', new CFFPointer(FDSelect), null], | ||
[[12, 36], 'FDArray', new CFFPointer(new CFFIndex(FontDict)), null], | ||
[24, 'vstore', new CFFPointer(VariationStore), null], | ||
[25, 'maxstack', 'number', 193] | ||
]); | ||
let CFFTop = new r.VersionedStruct(r.fixed16, { | ||
1: { | ||
hdrSize: r.uint8, | ||
offSize: r.uint8, | ||
nameIndex: new CFFIndex(new r.String('length')), | ||
topDictIndex: new CFFIndex(CFFTopDict), | ||
stringIndex: new CFFIndex(new r.String('length')), | ||
globalSubrIndex: new CFFIndex | ||
}, | ||
2: { | ||
hdrSize: r.uint8, | ||
length: r.uint16, | ||
topDict: CFF2TopDict, | ||
globalSubrIndex: new CFFIndex | ||
} | ||
}); | ||
export default CFFTop; |
@@ -9,2 +9,6 @@ import Glyph from './Glyph'; | ||
_getName() { | ||
if (this._font.CFF2) { | ||
return super._getName(); | ||
} | ||
return this._font['CFF '].getGlyphName(this.id); | ||
@@ -27,3 +31,3 @@ } | ||
let cff = this._font['CFF ']; | ||
let cff = this._font.CFF2 || this._font['CFF ']; | ||
let str = cff.topDict.CharStrings[this.id]; | ||
@@ -54,7 +58,15 @@ let end = str.offset + str.length; | ||
let vstore = cff.topDict.vstore && cff.topDict.vstore.itemVariationStore; | ||
let vsindex = privateDict.vsindex; | ||
let variationProcessor = this._font._variationProcessor; | ||
function checkWidth() { | ||
if (width == null) { | ||
width = stack.shift() + privateDict.nominalWidthX; | ||
} | ||
} | ||
function parseStems() { | ||
if (stack.length % 2 !== 0) { | ||
if (width === null) { | ||
width = stack.shift() + privateDict.nominalWidthX; | ||
} | ||
checkWidth(); | ||
} | ||
@@ -89,3 +101,3 @@ | ||
if (stack.length > 1) { | ||
if (typeof width === 'undefined' || width === null) { width = stack.shift() + privateDict.nominalWidthX; } | ||
checkWidth(); | ||
} | ||
@@ -148,7 +160,14 @@ | ||
case 11: // return | ||
if (cff.version >= 2) { | ||
break; | ||
} | ||
return; | ||
case 14: // endchar | ||
if (cff.version >= 2) { | ||
break; | ||
} | ||
if (stack.length > 0) { | ||
if (typeof width === 'undefined' || width === null) { width = stack.shift() + privateDict.nominalWidthX; } | ||
checkWidth(); | ||
} | ||
@@ -162,2 +181,42 @@ | ||
case 15: { // vsindex | ||
if (cff.version < 2) { | ||
throw new Error('vsindex operator not supported in CFF v1'); | ||
} | ||
vsindex = stack.pop(); | ||
break; | ||
} | ||
case 16: { // blend | ||
if (cff.version < 2) { | ||
throw new Error('blend operator not supported in CFF v1'); | ||
} | ||
if (!variationProcessor) { | ||
throw new Error('blend operator in non-variation font'); | ||
} | ||
let blendVector = variationProcessor.getBlendVector(vstore, vsindex); | ||
let numBlends = stack.pop(); | ||
let numOperands = numBlends * blendVector.length; | ||
let delta = stack.length - numOperands; | ||
let base = delta - numBlends; | ||
for (let i = 0; i < numBlends; i++) { | ||
let sum = stack[base + i]; | ||
for (let j = 0; j < blendVector.length; j++) { | ||
sum += blendVector[j] * stack[delta++]; | ||
} | ||
stack[base + i] = sum; | ||
} | ||
while (numOperands--) { | ||
stack.pop(); | ||
} | ||
break; | ||
} | ||
case 19: // hintmask | ||
@@ -171,4 +230,3 @@ case 20: // cntrmask | ||
if (stack.length > 2) { | ||
if (typeof width === 'undefined' || width === null) { width = stack.shift() + privateDict.nominalWidthX; } | ||
let haveWidth = true; | ||
checkWidth(); | ||
} | ||
@@ -183,3 +241,3 @@ | ||
if (stack.length > 1) { | ||
if (typeof width === 'undefined' || width === null) { width = stack.shift() + privateDict.nominalWidthX; } | ||
checkWidth(); | ||
} | ||
@@ -542,4 +600,9 @@ | ||
parse(); | ||
if (open) { | ||
path.closePath(); | ||
} | ||
return path; | ||
} | ||
} |
@@ -86,2 +86,6 @@ import { cache } from '../decorators'; | ||
if (this._font._variationProcessor && this._font.HVAR) { | ||
advanceWidth += this._font._variationProcessor.getAdvanceAdjustment(this.id, this._font.HVAR); | ||
} | ||
return this._metrics = { advanceWidth, advanceHeight, leftBearing, topBearing }; | ||
@@ -88,0 +92,0 @@ } |
@@ -28,2 +28,3 @@ const TUPLES_SHARE_POINT_NUMBERS = 0x8000; | ||
this.normalizedCoords = this.normalizeCoords(coords); | ||
this.blendVectors = new Map; | ||
} | ||
@@ -384,2 +385,96 @@ | ||
} | ||
getAdvanceAdjustment(gid, table) { | ||
let outerIndex, innerIndex; | ||
if (table.advanceWidthMapping) { | ||
let idx = gid; | ||
if (idx >= table.advanceWidthMapping.mapCount) { | ||
idx = table.advanceWidthMapping.mapCount - 1; | ||
} | ||
let entryFormat = table.advanceWidthMapping.entryFormat; | ||
({outerIndex, innerIndex} = table.advanceWidthMapping.mapData[idx]); | ||
} else { | ||
outerIndex = 0; | ||
innerIndex = gid; | ||
} | ||
return this.getMetricDelta(table.itemVariationStore, outerIndex, innerIndex); | ||
} | ||
// See pseudo code from `Font Variations Overview' | ||
// in the OpenType specification. | ||
getMetricDelta(itemStore, outerIndex, innerIndex) { | ||
let varData = itemStore.itemVariationData[outerIndex]; | ||
let deltaSet = varData.deltaSets[innerIndex]; | ||
let blendVector = this.getBlendVector(itemStore, outerIndex); | ||
let netAdjustment = 0; | ||
for (let master = 0; master < varData.regionIndexCount; master++) { | ||
netAdjustment += deltaSet.deltas[master] * blendVector[master]; | ||
} | ||
return netAdjustment; | ||
} | ||
getBlendVector(itemStore, outerIndex) { | ||
let varData = itemStore.itemVariationData[outerIndex]; | ||
if (this.blendVectors.has(varData)) { | ||
return this.blendVectors.get(varData); | ||
} | ||
let normalizedCoords = this.normalizedCoords; | ||
let blendVector = []; | ||
// outer loop steps through master designs to be blended | ||
for (let master = 0; master < varData.regionIndexCount; master++) { | ||
let scalar = 1; | ||
let regionIndex = varData.regionIndexes[master]; | ||
let axes = itemStore.variationRegionList.variationRegions[regionIndex]; | ||
// inner loop steps through axes in this region | ||
for (let j = 0; j < axes.length; j++) { | ||
let axis = axes[j]; | ||
let axisScalar; | ||
// compute the scalar contribution of this axis | ||
// ignore invalid ranges | ||
if (axis.startCoord > axis.peakCoord || axis.peakCoord > axis.endCoord) { | ||
axisScalar = 1; | ||
} else if (axis.startCoord < 0 && axis.endCoord > 0 && axis.peakCoord !== 0) { | ||
axisScalar = 1; | ||
// peak of 0 means ignore this axis | ||
} else if (axis.peakCoord === 0) { | ||
axisScalar = 1; | ||
// ignore this region if coords are out of range | ||
} else if (normalizedCoords[j] < axis.startCoord || normalizedCoords[j] > axis.endCoord) { | ||
axisScalar = 0; | ||
// calculate a proportional factor | ||
} else { | ||
if (normalizedCoords[j] === axis.peakCoord) { | ||
axisScalar = 1; | ||
} else if (normalizedCoords[j] < axis.peakCoord) { | ||
axisScalar = (normalizedCoords[j] - axis.startCoord + Number.EPSILON) / | ||
(axis.peakCoord - axis.startCoord + Number.EPSILON); | ||
} else { | ||
axisScalar = (axis.endCoord - normalizedCoords[j] + Number.EPSILON) / | ||
(axis.endCoord - axis.peakCoord + Number.EPSILON); | ||
} | ||
} | ||
// take product of all the axis scalars | ||
scalar *= axisScalar; | ||
} | ||
blendVector[master] = scalar; | ||
} | ||
this.blendVectors.set(varData, blendVector); | ||
return blendVector; | ||
} | ||
} |
@@ -281,4 +281,4 @@ import Glyph from './Glyph'; | ||
// Recompute and cache metrics if we performed variation processing | ||
if (glyph.phantomPoints) { | ||
// Recompute and cache metrics if we performed variation processing, and don't have an HVAR table | ||
if (glyph.phantomPoints && !this._font.directory.tables.HVAR) { | ||
this._metrics.advanceWidth = glyph.phantomPoints[1].x - glyph.phantomPoints[0].x; | ||
@@ -312,5 +312,4 @@ this._metrics.advanceHeight = glyph.phantomPoints[3].y - glyph.phantomPoints[2].y; | ||
if (this._font._variationProcessor) { | ||
// Decode the font data (and cache for later). | ||
// This triggers recomputation of metrics | ||
if (this._font._variationProcessor && !this._font.HVAR) { | ||
// No HVAR table, decode the glyph. This triggers recomputation of metrics. | ||
this.path; | ||
@@ -380,3 +379,3 @@ } | ||
} | ||
path.closePath(); | ||
@@ -383,0 +382,0 @@ } |
@@ -20,2 +20,7 @@ import GlyphIterator from './GlyphIterator'; | ||
// Setup variation substitutions | ||
this.variationsIndex = font._variationProcessor | ||
? this.findVariationsIndex(font._variationProcessor.normalizedCoords) | ||
: -1; | ||
// initialize to default script + language | ||
@@ -95,3 +100,4 @@ this.selectScript(); | ||
let record = this.table.featureList[featureIndex]; | ||
this.features[record.tag] = record.feature; | ||
let substituteFeature = this.substituteFeatureForVariations(featureIndex); | ||
this.features[record.tag] = substituteFeature || record.feature; | ||
} | ||
@@ -127,2 +133,42 @@ } | ||
substituteFeatureForVariations(featureIndex) { | ||
if (this.variationsIndex === -1) { | ||
return null; | ||
} | ||
let record = this.table.featureVariations.featureVariationRecords[this.variationsIndex]; | ||
let substitutions = record.featureTableSubstitution.substitutions; | ||
for (let substitution of substitutions) { | ||
if (substitution.featureIndex === featureIndex) { | ||
return substitution.alternateFeatureTable; | ||
} | ||
} | ||
return null; | ||
} | ||
findVariationsIndex(coords) { | ||
let variations = this.table.featureVariations; | ||
if (!variations) { | ||
return -1; | ||
} | ||
let records = variations.featureVariationRecords; | ||
for (let i = 0; i < records.length; i++) { | ||
let conditions = records[i].conditionSet.conditionTable; | ||
if (this.variationConditionsMatch(conditions, coords)) { | ||
return i; | ||
} | ||
} | ||
return -1; | ||
} | ||
variationConditionsMatch(conditions, coords) { | ||
return conditions.every(condition => { | ||
let coord = condition.axisIndex < coords.length ? coords[condition.axisIndex] : 0; | ||
return condition.filterRangeMinValue <= coord && coord <= condition.filterRangeMaxValue; | ||
}); | ||
} | ||
applyFeatures(userFeatures, glyphs, advances) { | ||
@@ -129,0 +175,0 @@ let lookups = this.lookupsForFeatures(userFeatures); |
import unicode from 'unicode-properties'; | ||
const VARIATION_FEATURES = ['rvrn']; | ||
const COMMON_FEATURES = ['ccmp', 'locl', 'rlig', 'mark', 'mkmk']; | ||
@@ -29,3 +30,3 @@ const FRACTIONAL_FEATURES = ['frac', 'numr', 'dnom']; | ||
plan.add({ | ||
global: DIRECTIONAL_FEATURES[plan.direction], | ||
global: [...VARIATION_FEATURES, ...DIRECTIONAL_FEATURES[plan.direction]], | ||
local: FRACTIONAL_FEATURES | ||
@@ -32,0 +33,0 @@ }); |
@@ -155,2 +155,5 @@ import Subset from './Subset'; | ||
let top = { | ||
version: 1, | ||
hdrSize: this.cff.hdrSize, | ||
offSize: this.cff.length, | ||
header: this.cff.header, | ||
@@ -157,0 +160,0 @@ nameIndex: [this.cff.postscriptName], |
import r from 'restructure'; | ||
import { ScriptList, FeatureList, LookupList, Coverage, ClassDef, Device } from './opentype'; | ||
import {ScriptList, FeatureList, LookupList, Coverage, ClassDef, Device} from './opentype'; | ||
import {ItemVariationStore} from './variations'; | ||
@@ -41,4 +42,4 @@ let AttachPoint = new r.Array(r.uint16, r.uint16); | ||
export default new r.VersionedStruct(r.uint32, { | ||
0x00010000: { | ||
glyphClassDef: new r.Pointer(r.uint16, ClassDef), // 1: base glyph, 2: ligature, 3: mark, 4: component | ||
header: { | ||
glyphClassDef: new r.Pointer(r.uint16, ClassDef), | ||
attachList: new r.Pointer(r.uint16, AttachList), | ||
@@ -48,9 +49,11 @@ ligCaretList: new r.Pointer(r.uint16, LigCaretList), | ||
}, | ||
0x00010000: {}, | ||
0x00010002: { | ||
glyphClassDef: new r.Pointer(r.uint16, ClassDef), | ||
attachList: new r.Pointer(r.uint16, AttachList), | ||
ligCaretList: new r.Pointer(r.uint16, LigCaretList), | ||
markAttachClassDef: new r.Pointer(r.uint16, ClassDef), | ||
markGlyphSetsDef: new r.Pointer(r.uint16, MarkGlyphSetsDef) | ||
}, | ||
0x00010003: { | ||
markGlyphSetsDef: new r.Pointer(r.uint16, MarkGlyphSetsDef), | ||
itemVariationStore: new r.Pointer(r.uint32, ItemVariationStore) | ||
} | ||
}); |
import r from 'restructure'; | ||
import { ScriptList, FeatureList, LookupList, Coverage, ClassDef, Device, Context, ChainingContext } from './opentype'; | ||
import {ScriptList, FeatureList, LookupList, Coverage, ClassDef, Device, Context, ChainingContext} from './opentype'; | ||
import {FeatureVariations} from './variations'; | ||
@@ -194,7 +195,13 @@ let ValueFormat = new r.Bitfield(r.uint16, [ | ||
export default new r.Struct({ | ||
version: r.int32, | ||
scriptList: new r.Pointer(r.uint16, ScriptList), | ||
featureList: new r.Pointer(r.uint16, FeatureList), | ||
lookupList: new r.Pointer(r.uint16, new LookupList(GPOSLookup)) | ||
export default new r.VersionedStruct(r.uint32, { | ||
header: { | ||
scriptList: new r.Pointer(r.uint16, ScriptList), | ||
featureList: new r.Pointer(r.uint16, FeatureList), | ||
lookupList: new r.Pointer(r.uint16, new LookupList(GPOSLookup)) | ||
}, | ||
0x00010000: {}, | ||
0x00010001: { | ||
featureVariations: new r.Pointer(r.uint32, FeatureVariations) | ||
} | ||
}); | ||
@@ -201,0 +208,0 @@ |
import r from 'restructure'; | ||
import { ScriptList, FeatureList, LookupList, Coverage, ClassDef, Device, Context, ChainingContext } from './opentype'; | ||
import {ScriptList, FeatureList, LookupList, Coverage, ClassDef, Device, Context, ChainingContext} from './opentype'; | ||
import {FeatureVariations} from './variations'; | ||
@@ -72,7 +73,13 @@ let Sequence = new r.Array(r.uint16, r.uint16); | ||
export default new r.Struct({ | ||
version: r.int32, | ||
scriptList: new r.Pointer(r.uint16, ScriptList), | ||
featureList: new r.Pointer(r.uint16, FeatureList), | ||
lookupList: new r.Pointer(r.uint16, new LookupList(GSUBLookup)) | ||
export default new r.VersionedStruct(r.uint32, { | ||
header: { | ||
scriptList: new r.Pointer(r.uint16, ScriptList), | ||
featureList: new r.Pointer(r.uint16, FeatureList), | ||
lookupList: new r.Pointer(r.uint16, new LookupList(GSUBLookup)) | ||
}, | ||
0x00010000: {}, | ||
0x00010001: { | ||
featureVariations: new r.Pointer(r.uint32, FeatureVariations) | ||
} | ||
}); |
@@ -43,2 +43,3 @@ let tables = {}; | ||
tables['CFF '] = CFFFont; | ||
tables['CFF2'] = CFFFont; | ||
tables.VORG = VORG; | ||
@@ -73,3 +74,7 @@ | ||
// OpenType variations tables | ||
import HVAR from './HVAR'; | ||
tables.HVAR = HVAR; | ||
// Other OpenType Tables | ||
@@ -76,0 +81,0 @@ import DSIG from './DSIG'; |
@@ -36,3 +36,3 @@ import r from 'restructure'; | ||
let Feature = new r.Struct({ | ||
export let Feature = new r.Struct({ | ||
featureParams: r.uint16, // pointer | ||
@@ -39,0 +39,0 @@ lookupCount: r.uint16, |
@@ -29,2 +29,4 @@ import r from 'restructure'; | ||
this.stream = stream; | ||
this.variationCoords = variationCoords; | ||
this._directoryPos = this.stream.pos; | ||
@@ -44,6 +46,2 @@ this._tables = {}; | ||
} | ||
if (variationCoords) { | ||
this._variationProcessor = new GlyphVariationProcessor(this, variationCoords); | ||
} | ||
} | ||
@@ -377,3 +375,3 @@ | ||
} else if (this.directory.tables['CFF ']) { | ||
} else if (this.directory.tables['CFF '] || this.directory.tables.CFF2) { | ||
this._glyphs[glyph] = new CFFGlyph(glyph, characters, this); | ||
@@ -430,2 +428,3 @@ } | ||
*/ | ||
@cache | ||
get variationAxes() { | ||
@@ -456,2 +455,3 @@ let res = {}; | ||
*/ | ||
@cache | ||
get namedVariations() { | ||
@@ -485,4 +485,4 @@ let res = {}; | ||
getVariation(settings) { | ||
if (!this.directory.tables.fvar || !this.directory.tables.gvar || !this.directory.tables.glyf) { | ||
throw new Error('Variations require a font with the fvar, gvar, and glyf tables.'); | ||
if (!(this.directory.tables.fvar && ((this.directory.tables.gvar && this.directory.tables.glyf) || this.directory.tables.CFF2))) { | ||
throw new Error('Variations require a font with the fvar, gvar and glyf, or CFF2 tables.'); | ||
} | ||
@@ -517,2 +517,22 @@ | ||
@cache | ||
get _variationProcessor() { | ||
if (!this.fvar) { | ||
return null; | ||
} | ||
let variationCoords = this.variationCoords; | ||
// Ignore if no variation coords and not CFF2 | ||
if (!variationCoords && !this.CFF2) { | ||
return null; | ||
} | ||
if (!variationCoords) { | ||
variationCoords = this.fvar.axis.map(axis => axis.defaultValue); | ||
} | ||
return new GlyphVariationProcessor(this, variationCoords); | ||
} | ||
// Standardized format plugin API | ||
@@ -519,0 +539,0 @@ getFont(name) { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1471331
121
21722
18