mirror of
https://github.com/kiliman/operator-mono-lig.git
synced 2026-08-12 02:10:52 +02:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3813319b42 | |||
| f2a61c74ad | |||
| 1fce61fe50 | |||
| 1028c96291 | |||
| 043c160546 | |||
| 445828c8bf | |||
| 66fd3f94a1 | |||
| 9bf5f6197c | |||
| bd48389313 | |||
| 30a6c098e7 | |||
| 42e64f84b8 | |||
| 124d893fe5 | |||
| e692fcfbf8 | |||
| 321486d19e | |||
| 6f3d00ae6d | |||
| 420eeefe59 | |||
| a5c360bf30 |
+1
-1
@@ -1,5 +1,5 @@
|
||||
build
|
||||
node_modules
|
||||
.idea
|
||||
.vscode/launch.json
|
||||
.vscode
|
||||
.DS_Store
|
||||
|
||||
@@ -3,19 +3,25 @@ setlocal
|
||||
|
||||
if not exist .\build\* mkdir build
|
||||
|
||||
set flags=
|
||||
if "%1"=="--italics-hack-off" (
|
||||
set flags=%1
|
||||
shift
|
||||
)
|
||||
rem only build passed in font
|
||||
if not "%1%"=="" (
|
||||
call :build_font %1
|
||||
if not "%1"=="" (
|
||||
call :build_font %1 %flags%
|
||||
exit /b
|
||||
)
|
||||
|
||||
rem build all fonts
|
||||
for /d %%d in (.\ligature\*) do call :build_font %%~nd
|
||||
for /d %%d in (.\ligature\*) do call :build_font %%~nd %flags%
|
||||
exit /b
|
||||
|
||||
|
||||
:build_font
|
||||
set lig=%1
|
||||
set flags=%2
|
||||
set otf=%lig:Lig-=-%
|
||||
|
||||
if not exist .\original\%otf%.otf exit /b
|
||||
@@ -23,6 +29,8 @@ if not exist .\ligature\%lig%\glyphs\* exit /b
|
||||
|
||||
@echo Building %lig%
|
||||
ttx -f .\original\%otf%.otf
|
||||
node index.js %otf%
|
||||
for %%f in (.\build\%lig%*.ttx) do ttx -f %%f
|
||||
node index.js %otf% %flags%
|
||||
ttx -f .\build\%lig%.ttx
|
||||
fonttools feaLib -v -o ".\build\%lig%.otf" .\features\default.fea ".\build\%lig%.otf"
|
||||
|
||||
exit /b
|
||||
|
||||
@@ -4,6 +4,7 @@ mkdir -p build
|
||||
|
||||
build_font() {
|
||||
lig="$1"
|
||||
flags="$2"
|
||||
otf=${lig/Lig-/-}
|
||||
|
||||
if [ ! -e "./original/$otf.otf" ]
|
||||
@@ -15,22 +16,28 @@ build_font() {
|
||||
return
|
||||
fi
|
||||
|
||||
echo Building $1
|
||||
echo Building "$1"
|
||||
ttx -f "./original/$otf.otf"
|
||||
node index.js $otf
|
||||
node index.js "$otf" "$flags"
|
||||
|
||||
for f in ./build/$1*.ttx ; do
|
||||
ttx -f $f
|
||||
done
|
||||
ttx -f "./build/$1.ttx"
|
||||
|
||||
fonttools feaLib -v -o "./build/$1.otf" ./features/default.fea "./build/$1.otf"
|
||||
}
|
||||
|
||||
flags=
|
||||
if [ "$1" = "--italics-hack-off" ]
|
||||
then
|
||||
flags=$1
|
||||
shift
|
||||
fi
|
||||
if [ -n "$1" ]
|
||||
then
|
||||
# build specified font
|
||||
build_font $1
|
||||
build_font "$1" "$flags"
|
||||
else
|
||||
# build all available fonts
|
||||
for d in ./ligature/*/ ; do
|
||||
build_font $(basename $d)
|
||||
build_font "$(basename "$d")" "$flags"
|
||||
done
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const rules = [
|
||||
,
|
||||
`
|
||||
lookup 1 {
|
||||
sub 1 by glyph;
|
||||
} 1;`,
|
||||
`
|
||||
lookup 1_2 {
|
||||
ignore sub 1 1' 2;
|
||||
ignore sub 1' 2 2;
|
||||
sub 1.spacer 2' by glyph;
|
||||
sub 1' 2 by 1.spacer;
|
||||
} 1_2;`,
|
||||
`
|
||||
lookup 1_2_3 {
|
||||
ignore sub 1 1' 2 3;
|
||||
ignore sub 1' 2 3 3;
|
||||
sub 1.spacer 2.spacer 3' by glyph;
|
||||
sub 1.spacer 2' 3 by 2.spacer;
|
||||
sub 1' 2 3 by 1.spacer;
|
||||
} 1_2_3;`,
|
||||
`
|
||||
lookup 1_2_3_4 {
|
||||
ignore sub 1 1' 2 3 4;
|
||||
ignore sub 1' 2 3 4 4;
|
||||
sub 1.spacer 2.spacer 3.spacer 4' by glyph;
|
||||
sub 1.spacer 2.spacer 3' 4 by 3.spacer;
|
||||
sub 1.spacer 2' 3 4 by 2.spacer;
|
||||
sub 1' 2 3 4 by 1.spacer;
|
||||
} 1_2_3_4;`,
|
||||
];
|
||||
|
||||
const gencalt = (ligatures) => {
|
||||
let calt = 'feature calt {\n';
|
||||
const ligs = {};
|
||||
console.log(ligatures);
|
||||
|
||||
ligatures
|
||||
.filter((l) => !!l.name.match(/\.liga$/) || l.name !== l.glyph)
|
||||
.map((l) => l.glyph)
|
||||
.sort((a, b) => {
|
||||
const length = b.split('_').length - a.split('_').length;
|
||||
if (length !== 0) return length;
|
||||
return a < b ? -1 : 1;
|
||||
})
|
||||
.forEach((g) => {
|
||||
g.split('.')
|
||||
.slice(0, 1)
|
||||
.forEach((l) => {
|
||||
if (ligs[l]) return;
|
||||
ligs[l] = true;
|
||||
const c = l.split('_');
|
||||
let rule = rules[c.length];
|
||||
rule = rule
|
||||
.replace(/\d/g, (m) => c[parseInt(m) - 1])
|
||||
.replace(/glyph/g, g);
|
||||
calt += rule + '\n';
|
||||
});
|
||||
});
|
||||
|
||||
return calt + '\n} calt;\n';
|
||||
};
|
||||
|
||||
exports.gencalt = gencalt;
|
||||
@@ -0,0 +1 @@
|
||||
calt.fea
|
||||
@@ -0,0 +1,212 @@
|
||||
languagesystem DFLT dflt;
|
||||
languagesystem latn dflt;
|
||||
|
||||
lookup lookup_0 {
|
||||
sub zero by zero.num;
|
||||
sub one by one.num;
|
||||
sub two by two.num;
|
||||
sub three by three.num;
|
||||
sub four by four.num;
|
||||
sub five by five.num;
|
||||
sub six by six.num;
|
||||
sub seven by seven.num;
|
||||
sub eight by eight.num;
|
||||
sub nine by nine.num;
|
||||
sub slash by fraction;
|
||||
sub fraction by fraction.afrc;
|
||||
} lookup_0;
|
||||
|
||||
lookup lookup_1 {
|
||||
sub zero by zero.den;
|
||||
sub one by one.den;
|
||||
sub two by two.den;
|
||||
sub three by three.den;
|
||||
sub four by four.den;
|
||||
sub five by five.den;
|
||||
sub six by six.den;
|
||||
sub seven by seven.den;
|
||||
sub eight by eight.den;
|
||||
sub nine by nine.den;
|
||||
sub slash by fraction;
|
||||
} lookup_1;
|
||||
|
||||
lookup lookup_2 {
|
||||
sub L periodcentered by Ldot;
|
||||
sub l periodcentered by ldot;
|
||||
} lookup_2;
|
||||
|
||||
|
||||
feature case {
|
||||
sub guillemotleft by guillemotleft.cap;
|
||||
sub guillemotright by guillemotright.cap;
|
||||
sub guilsinglleft by guilsinglleft.cap;
|
||||
sub guilsinglright by guilsinglright.cap;
|
||||
sub parenleft by parenleft.cap;
|
||||
sub parenright by parenright.cap;
|
||||
sub bracketleft by bracketleft.cap;
|
||||
sub bracketright by bracketright.cap;
|
||||
sub braceleft by braceleft.cap;
|
||||
sub braceright by braceright.cap;
|
||||
} case;
|
||||
|
||||
feature dnom {
|
||||
sub zero by zero.den;
|
||||
sub one by one.den;
|
||||
sub two by two.den;
|
||||
sub three by three.den;
|
||||
sub four by four.den;
|
||||
sub five by five.den;
|
||||
sub six by six.den;
|
||||
sub seven by seven.den;
|
||||
sub eight by eight.den;
|
||||
sub nine by nine.den;
|
||||
} dnom;
|
||||
|
||||
feature frac {
|
||||
lookup frac0 {
|
||||
sub [zero one two three four five six seven eight nine] slash' lookup lookup_0 [zero one two three four five six seven eight nine] ;
|
||||
} frac0;
|
||||
lookup frac1 {
|
||||
ignore sub [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] fraction' ;
|
||||
ignore sub fraction' [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] ;
|
||||
sub [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] fraction' lookup lookup_0 [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] ;
|
||||
} frac1;
|
||||
lookup frac2 {
|
||||
sub [zero one two three four five six seven eight nine]' lookup lookup_0 fraction.afrc ;
|
||||
sub fraction.afrc [zero one two three four five six seven eight nine]' lookup lookup_1 ;
|
||||
} frac2;
|
||||
lookup frac3 {
|
||||
sub one.num fraction.afrc two.den by onehalf;
|
||||
sub one.num fraction.afrc three.den by onethird;
|
||||
sub one.num fraction.afrc four.den by onequarter;
|
||||
sub one.num fraction.afrc five.den by onefifth;
|
||||
sub one.num fraction.afrc six.den by onesixth;
|
||||
sub one.num fraction.afrc eight.den by oneeighth;
|
||||
sub two.num fraction.afrc three.den by twothirds;
|
||||
sub two.num fraction.afrc five.den by twofifths;
|
||||
sub three.num fraction.afrc four.den by threequarters;
|
||||
sub three.num fraction.afrc five.den by threefifths;
|
||||
sub three.num fraction.afrc eight.den by threeeighths;
|
||||
sub four.num fraction.afrc five.den by fourfifths;
|
||||
sub five.num fraction.afrc six.den by fivesixths;
|
||||
sub five.num fraction.afrc eight.den by fiveeighths;
|
||||
sub seven.num fraction.afrc eight.den by seveneighths;
|
||||
} frac3;
|
||||
} frac;
|
||||
|
||||
feature locl {
|
||||
script latn;
|
||||
language CAT ;
|
||||
sub l' lookup lookup_2 periodcentered' lookup lookup_2 l ;
|
||||
sub L' lookup lookup_2 periodcentered' lookup lookup_2 L ;
|
||||
} locl;
|
||||
|
||||
feature numr {
|
||||
sub zero by zero.num;
|
||||
sub one by one.num;
|
||||
sub two by two.num;
|
||||
sub three by three.num;
|
||||
sub four by four.num;
|
||||
sub five by five.num;
|
||||
sub six by six.num;
|
||||
sub seven by seven.num;
|
||||
sub eight by eight.num;
|
||||
sub nine by nine.num;
|
||||
} numr;
|
||||
|
||||
feature rupa {
|
||||
sub R p by R_p;
|
||||
} rupa;
|
||||
|
||||
feature ss01 {
|
||||
sub registered by registered.alt;
|
||||
} ss01;
|
||||
|
||||
feature salt {
|
||||
lookup salt0 {
|
||||
sub registered by registered.alt;
|
||||
} salt0;
|
||||
lookup salt1 {
|
||||
sub colon by colon.alt;
|
||||
} salt1;
|
||||
lookup salt2 {
|
||||
sub bullet by bullet.alt;
|
||||
} salt2;
|
||||
lookup salt3 {
|
||||
sub asterisk by asterisk.alt;
|
||||
} salt3;
|
||||
lookup salt4 {
|
||||
sub zero by zero.alt;
|
||||
} salt4;
|
||||
lookup salt5 {
|
||||
sub underscore by underscore.alt;
|
||||
} salt5;
|
||||
lookup salt6 {
|
||||
sub [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] slash' lookup lookup_1 [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] ;
|
||||
} salt6;
|
||||
} salt;
|
||||
|
||||
feature sinf {
|
||||
sub zero by zero.inf;
|
||||
sub one by one.inf;
|
||||
sub two by two.inf;
|
||||
sub three by three.inf;
|
||||
sub four by four.inf;
|
||||
sub five by five.inf;
|
||||
sub six by six.inf;
|
||||
sub seven by seven.inf;
|
||||
sub eight by eight.inf;
|
||||
sub nine by nine.inf;
|
||||
} sinf;
|
||||
|
||||
feature ss03 {
|
||||
sub colon by colon.alt;
|
||||
} ss03;
|
||||
|
||||
feature ss04 {
|
||||
sub bullet by bullet.alt;
|
||||
} ss04;
|
||||
|
||||
feature ss05 {
|
||||
sub asterisk by asterisk.alt;
|
||||
} ss05;
|
||||
|
||||
feature ss07 {
|
||||
sub zero by zero.alt;
|
||||
} ss07;
|
||||
|
||||
feature ss08 {
|
||||
sub underscore by underscore.alt;
|
||||
} ss08;
|
||||
|
||||
feature ss09 {
|
||||
sub [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] slash' lookup lookup_1 [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den] ;
|
||||
} ss09;
|
||||
|
||||
feature subs {
|
||||
sub zero by zero.inf;
|
||||
sub one by one.inf;
|
||||
sub two by two.inf;
|
||||
sub three by three.inf;
|
||||
sub four by four.inf;
|
||||
sub five by five.inf;
|
||||
sub six by six.inf;
|
||||
sub seven by seven.inf;
|
||||
sub eight by eight.inf;
|
||||
sub nine by nine.inf;
|
||||
} subs;
|
||||
|
||||
feature subs {
|
||||
sub zero by zero.sup;
|
||||
sub one by one.sup;
|
||||
sub two by two.sup;
|
||||
sub three by three.sup;
|
||||
sub four by four.sup;
|
||||
sub five by five.sup;
|
||||
sub six by six.sup;
|
||||
sub seven by seven.sup;
|
||||
sub eight by eight.sup;
|
||||
sub nine by nine.sup;
|
||||
} subs;
|
||||
|
||||
include(calt.fea);
|
||||
@@ -0,0 +1,36 @@
|
||||
const fs = require('fs');
|
||||
const lig = `<Glyph name="LIG" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>`;
|
||||
|
||||
fs.readdirSync('./ligature')
|
||||
.filter((f) => !!f.match(/^OperatorMono/))
|
||||
.forEach((f) => {
|
||||
console.log(f);
|
||||
fs.readdirSync(`./ligature/${f}/glyphs`)
|
||||
.filter((g) => !!g.match(/\.liga\.xml$/))
|
||||
.forEach((g) => {
|
||||
console.log(g);
|
||||
g.split('.')
|
||||
.slice(0, 1)
|
||||
.forEach((l) => {
|
||||
l.split('_').forEach((c) => {
|
||||
const path = `./ligature/${f}/glyphs/${c}.spacer.xml`;
|
||||
const exists = fs.existsSync(path);
|
||||
console.log(path, exists);
|
||||
if (exists) return;
|
||||
|
||||
const width = !!f.match(/SSm/) ? 625 : 600;
|
||||
const spacer = lig
|
||||
.replace('LIG', `${c}.spacer`)
|
||||
.replace('625', width);
|
||||
console.log(f, c, width);
|
||||
fs.writeFileSync(path, spacer);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,288 +0,0 @@
|
||||
const xpath = require('xpath');
|
||||
const NodeType = {};
|
||||
NodeType.TEXT_NODE = 3;
|
||||
|
||||
let dom;
|
||||
let gsubDom;
|
||||
let scriptListDom;
|
||||
let featureListDom;
|
||||
let lookupListDom;
|
||||
let featureDom;
|
||||
let lookupIndex = 0;
|
||||
let chainIndex = 0;
|
||||
const substLookupMap = {};
|
||||
|
||||
const buildGsubTables = (_dom, ligature) => {
|
||||
dom = _dom;
|
||||
|
||||
if (/_/.test(ligature.glyph) === false) {
|
||||
// not a ligature, so see if glyph exists in font (as substitute)
|
||||
const glyphNode = xpath.select(
|
||||
`ttFont/GlyphOrder/GlyphID[@name="${ligature.name}"]`,
|
||||
dom,
|
||||
true
|
||||
);
|
||||
if (!glyphNode) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const glyphs = ligature.name.replace(/\.liga$/, '').split('_');
|
||||
const isSingleGlyph = glyphs.length == 1;
|
||||
|
||||
gsubDom = xpath.select('ttFont/GSUB', dom, true);
|
||||
|
||||
// look for 'calt' feature
|
||||
featureListDom = xpath.select('FeatureList', gsubDom, true);
|
||||
|
||||
let featureRecord;
|
||||
const featureTag = xpath.select(
|
||||
'FeatureRecord/FeatureTag[@value="calt"]',
|
||||
featureListDom,
|
||||
true
|
||||
);
|
||||
if (!featureTag) {
|
||||
const featureListCount = xpath.select(
|
||||
'count(FeatureRecord)',
|
||||
featureListDom,
|
||||
true
|
||||
);
|
||||
featureRecord = createElementWithAttributes('FeatureRecord', {
|
||||
index: featureListCount
|
||||
});
|
||||
featureRecord.appendChild(
|
||||
createElementWithAttributes('FeatureTag', { value: 'calt' })
|
||||
);
|
||||
featureRecord.appendChild(dom.createElement('Feature'));
|
||||
featureListDom.appendChild(featureRecord);
|
||||
} else {
|
||||
featureRecord = featureTag.parentNode;
|
||||
}
|
||||
featureDom = xpath.select('Feature', featureRecord, true);
|
||||
|
||||
const featureIndex = featureRecord.getAttribute('index');
|
||||
|
||||
// add feature to scriptlist for DFLT and latn if not present
|
||||
addFeatureToScriptList('DFLT', featureIndex);
|
||||
addFeatureToScriptList('latn', featureIndex);
|
||||
|
||||
lookupListDom = xpath.select('LookupList', gsubDom, true);
|
||||
lookupIndex = xpath.select('count(Lookup)', lookupListDom, true);
|
||||
|
||||
const lookupDom = createElementWithAttributes('Lookup', {
|
||||
index: lookupIndex++
|
||||
});
|
||||
appendChildren(
|
||||
lookupDom,
|
||||
createElementWithAttributes('LookupType', { value: isSingleGlyph ? 1 : 6 }),
|
||||
createElementWithAttributes('LookupFlag', { value: 0 })
|
||||
);
|
||||
|
||||
// add contextual lookup to feature
|
||||
const featureLookupCount = xpath.select(
|
||||
'count(LookupListIndex)',
|
||||
featureDom,
|
||||
true
|
||||
);
|
||||
featureDom.appendChild(
|
||||
createElementWithAttributes('LookupListIndex', {
|
||||
index: featureLookupCount,
|
||||
value: lookupDom.getAttribute('index')
|
||||
})
|
||||
);
|
||||
|
||||
if (isSingleGlyph) {
|
||||
lookupDom.appendChild(
|
||||
getSubstLookup(ligature.name, ligature.glyph, lookupDom)
|
||||
);
|
||||
} else {
|
||||
lookupDom.appendChild(buildBacktrackFirst(glyphs));
|
||||
lookupDom.appendChild(buildLookAheadLast(glyphs));
|
||||
lookupDom.appendChild(buildLigatureSubst(glyphs, ligature.glyph));
|
||||
// remaining context
|
||||
for (let n = glyphs.length - 2; n >= 0; n--) {
|
||||
lookupDom.appendChild(
|
||||
buildChainContext(getLIGs(n), [glyphs[n]], glyphs.slice(n + 1), 'LIG')
|
||||
);
|
||||
}
|
||||
}
|
||||
lookupListDom.appendChild(lookupDom);
|
||||
};
|
||||
|
||||
const finalizeGsubTables = () => {
|
||||
// get current LookupList count
|
||||
let newIndex = xpath.select('count(Lookup)', lookupListDom, true);
|
||||
|
||||
// append added lookups
|
||||
Object.entries(substLookupMap).forEach(([, lookup]) => {
|
||||
// fixup existing lookups with new index
|
||||
const oldIndex = lookup.getAttribute('index');
|
||||
const substLookups = xpath.select(
|
||||
`//ChainContextSubst/SubstLookupRecord/LookupListIndex[@value="${oldIndex}"]`,
|
||||
lookupListDom,
|
||||
false
|
||||
);
|
||||
substLookups.forEach(substLookup => {
|
||||
substLookup.setAttribute('value', newIndex);
|
||||
});
|
||||
lookup.setAttribute('index', newIndex++);
|
||||
lookupListDom.appendChild(lookup);
|
||||
lookupListDom.appendChild(lookup);
|
||||
});
|
||||
};
|
||||
|
||||
//const dump = dom => console.log(format(serialize(dom)));
|
||||
|
||||
const addFeatureToScriptList = (tag, featureIndex) => {
|
||||
scriptListDom = xpath.select('ScriptList', gsubDom, true);
|
||||
const defaultLangSys = xpath.select(
|
||||
`ScriptRecord/ScriptTag[@value="${tag}"]/../Script/DefaultLangSys`,
|
||||
scriptListDom,
|
||||
true
|
||||
);
|
||||
const featureIndexNode = xpath.select(
|
||||
`FeatureIndex[@value=${featureIndex}]`,
|
||||
defaultLangSys,
|
||||
true
|
||||
);
|
||||
if (!featureIndexNode) {
|
||||
const count = xpath.select('count(FeatureIndex)', defaultLangSys, true);
|
||||
defaultLangSys.appendChild(
|
||||
createElementWithAttributes('FeatureIndex', {
|
||||
index: count,
|
||||
value: featureIndex
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const buildBacktrackFirst = glyphs => {
|
||||
// backtrack = first glyph
|
||||
// input = first glphy
|
||||
// lookAhead = [1..n]
|
||||
return buildChainContext([glyphs[0]], [glyphs[0]], glyphs.slice(1));
|
||||
};
|
||||
|
||||
const buildLookAheadLast = glyphs => {
|
||||
// backtrack = none
|
||||
// input = first glyph
|
||||
// lookAhead = [1..n] + [n]
|
||||
return buildChainContext(
|
||||
[],
|
||||
[glyphs[0]],
|
||||
[...glyphs.slice(1), glyphs.slice(-1)]
|
||||
);
|
||||
};
|
||||
|
||||
const buildLigatureSubst = (glyphs, lookup) => {
|
||||
// backtrack = LIG * n-1
|
||||
// input = last glyph
|
||||
// lookAhead = none
|
||||
return buildChainContext(
|
||||
getLIGs(glyphs.length - 1),
|
||||
glyphs.slice(-1),
|
||||
[],
|
||||
lookup
|
||||
);
|
||||
};
|
||||
|
||||
const getLIGs = length => new Array(length).fill('LIG', 0, length);
|
||||
|
||||
const buildChainContext = (backtrack, input, lookAhead, substitute) => {
|
||||
const chainDom = createElementWithAttributes('ChainContextSubst', {
|
||||
index: chainIndex++,
|
||||
Format: 3
|
||||
});
|
||||
|
||||
buildCoverage(chainDom, 'BacktrackCoverage', backtrack);
|
||||
buildCoverage(chainDom, 'InputCoverage', input);
|
||||
buildCoverage(chainDom, 'LookAheadCoverage', lookAhead);
|
||||
|
||||
if (substitute) {
|
||||
const lookup = getSubstLookup(input[0], substitute);
|
||||
const listIndex = lookup.getAttribute('index');
|
||||
const substLookupRecordDom = chainDom.appendChild(
|
||||
createElementWithAttributes('SubstLookupRecord', { index: 0 })
|
||||
);
|
||||
appendChildren(
|
||||
substLookupRecordDom,
|
||||
createElementWithAttributes('SequenceIndex', { value: 0 }),
|
||||
createElementWithAttributes('LookupListIndex', { value: listIndex })
|
||||
);
|
||||
}
|
||||
return chainDom;
|
||||
};
|
||||
|
||||
const buildCoverage = (chainDom, tagName, coverage) => {
|
||||
if (coverage) {
|
||||
coverage.forEach((glyph, i) => {
|
||||
const coverageDom = createElementWithAttributes(tagName, {
|
||||
index: i++,
|
||||
Format: 1
|
||||
});
|
||||
coverageDom.appendChild(
|
||||
createElementWithAttributes('Glyph', { value: glyph })
|
||||
);
|
||||
chainDom.appendChild(coverageDom);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const getSubstLookup = (input, output, lookupDom) => {
|
||||
if (!lookupDom) {
|
||||
lookupDom = substLookupMap[output];
|
||||
}
|
||||
|
||||
if (!lookupDom) {
|
||||
lookupDom = createElementWithAttributes('Lookup', {
|
||||
index: Object.keys(substLookupMap).length + 1
|
||||
});
|
||||
lookupDom.appendChild(
|
||||
createElementWithAttributes('LookupType', { value: 1 })
|
||||
);
|
||||
lookupDom.appendChild(
|
||||
createElementWithAttributes('LookupFlag', { value: 0 })
|
||||
);
|
||||
substLookupMap[output] = lookupDom;
|
||||
}
|
||||
|
||||
let singleSubstDom = xpath.select('SingleSubst', lookupDom, true);
|
||||
|
||||
if (!singleSubstDom) {
|
||||
singleSubstDom = createElementWithAttributes('SingleSubst', {
|
||||
index: 0,
|
||||
Format: 2
|
||||
});
|
||||
lookupDom.appendChild(singleSubstDom);
|
||||
}
|
||||
|
||||
// look for input subst
|
||||
const substitionDom = xpath.select(
|
||||
`Substitution[@in="${input}"]`,
|
||||
singleSubstDom,
|
||||
true
|
||||
);
|
||||
if (!substitionDom) {
|
||||
singleSubstDom.appendChild(
|
||||
createElementWithAttributes('Substitution', { in: input, out: output })
|
||||
);
|
||||
}
|
||||
return lookupDom;
|
||||
};
|
||||
|
||||
const createElementWithAttributes = (tagName, attributes) => {
|
||||
const element = dom.createElement(tagName);
|
||||
Object.entries(attributes).forEach(attribute => {
|
||||
element.setAttribute(attribute[0], attribute[1]);
|
||||
});
|
||||
return element;
|
||||
};
|
||||
|
||||
const appendChildren = (node, ...children) => {
|
||||
children.forEach(child => node.appendChild(child));
|
||||
};
|
||||
|
||||
//const serialize = dom => new XMLSerializer().serializeToString(dom);
|
||||
|
||||
exports.buildGsubTables = buildGsubTables;
|
||||
exports.finalizeGsubTables = finalizeGsubTables;
|
||||
@@ -1,10 +1,11 @@
|
||||
// @ts-nocheck
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
if (!os.EOL) {
|
||||
os.EOL = process.platform === 'win32' ? '\r\n' : '\n';
|
||||
}
|
||||
|
||||
const gsub = require('./gsub');
|
||||
const calt = require('./calt');
|
||||
|
||||
const xpath = require('xpath');
|
||||
const { DOMParser, XMLSerializer } = require('xmldom');
|
||||
@@ -17,8 +18,12 @@ const NodeType = {};
|
||||
NodeType.TEXT_NODE = 3;
|
||||
|
||||
let dom;
|
||||
let italicsHack = false;
|
||||
function main() {
|
||||
fontName = process.argv[2];
|
||||
italicsHack =
|
||||
fontName.includes('Italic') && process.argv[3] !== '--italics-hack-off';
|
||||
|
||||
ligFontName = fontName.split('-').join('Lig-');
|
||||
|
||||
const srcFileName = `./original/${fontName}.ttx`;
|
||||
@@ -29,12 +34,12 @@ function main() {
|
||||
const profiles = getProfiles();
|
||||
|
||||
// process settings (there may be more than one font to build)
|
||||
profiles.forEach(profile => buildFont(profile));
|
||||
profiles.forEach((profile) => buildFont(profile, { italicsHack }));
|
||||
|
||||
console.log('Done');
|
||||
}
|
||||
|
||||
const buildFont = profile => {
|
||||
const buildFont = (profile, options) => {
|
||||
// add suffix to dstFileName if present
|
||||
const dstFileName = `./build/${ligFontName}${profile.suffixWithLeadingHyphen}.ttx`;
|
||||
console.log(
|
||||
@@ -44,23 +49,25 @@ const buildFont = profile => {
|
||||
const ligatures = sortLigatures(
|
||||
fs
|
||||
.readdirSync(`./ligature/${ligFontName}/glyphs`)
|
||||
.filter(file => /\.xml$/.test(file))
|
||||
.map(file => file.replace('.xml', ''))
|
||||
.filter((file) => /\.xml$/.test(file))
|
||||
.map((file) => file.replace('.xml', ''))
|
||||
)
|
||||
.filter(name => !/\d+\.liga$/.test(name)) // skip alternates (ends with .#)
|
||||
.filter(name => filterLigatures(name, profile.ligatures))
|
||||
.map(name => mapLigatures(name, profile.ligatures))
|
||||
.filter(entry => filterGlyphsExists(entry));
|
||||
.filter((name) => !/\d+\.liga$/.test(name)) // skip alternates (ends with .#)
|
||||
.filter((name) => filterLigatures(name, profile.ligatures))
|
||||
.map((name) => mapLigatures(name, profile.ligatures))
|
||||
.filter((entry) => filterGlyphsExists(entry));
|
||||
|
||||
const ligaturesWithLIG = ligatures;
|
||||
//[...ligatures, { name: 'LIG', glyph: 'LIG' }];
|
||||
|
||||
processPatch('names', patchNames, dom, ligatures, profile);
|
||||
processPatch('gsub', patchGsub, dom, ligatures);
|
||||
processPatch('charstrings', patchCharStrings, dom, ligaturesWithLIG);
|
||||
processPatch('glyphs', patchGlyphs, dom, ligaturesWithLIG);
|
||||
processPatch('hmtx', patchHmtx, dom);
|
||||
|
||||
const feature = calt.gencalt(ligatures);
|
||||
fs.writeFileSync('./features/calt.fea', feature);
|
||||
|
||||
console.log(`Writing ligature font file ${dstFileName}`);
|
||||
fs.writeFileSync(dstFileName, format(serialize(dom)));
|
||||
};
|
||||
@@ -75,8 +82,8 @@ const getProfiles = () => {
|
||||
suffix: '',
|
||||
suffixWithLeadingSpace: '',
|
||||
suffixWithLeadingHyphen: '',
|
||||
ligatures: []
|
||||
}
|
||||
ligatures: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -86,8 +93,8 @@ const getProfiles = () => {
|
||||
const content = fs.readFileSync(profilePath, 'utf-8');
|
||||
content
|
||||
.split(/\r|\r\n|\n/g)
|
||||
.filter(line => /^[#]/.test(line) === false && line.length > 0)
|
||||
.forEach(line => {
|
||||
.filter((line) => /^[#]/.test(line) === false && line.length > 0)
|
||||
.forEach((line) => {
|
||||
const ch = line.trim()[0];
|
||||
if (ch === '[') {
|
||||
let name = line.substr(1, line.indexOf(']') - 1);
|
||||
@@ -96,7 +103,7 @@ const getProfiles = () => {
|
||||
suffix: name === 'default' ? '' : name,
|
||||
suffixWithLeadingSpace: name === 'default' ? '' : ' ' + name,
|
||||
suffixWithLeadingHyphen: name === 'default' ? '' : '-' + name,
|
||||
ligatures: []
|
||||
ligatures: [],
|
||||
};
|
||||
profiles.push(profile);
|
||||
} else {
|
||||
@@ -113,12 +120,12 @@ const getProfiles = () => {
|
||||
const filterLigatures = (name, mappings) => {
|
||||
// loop through mappings and return if name applies or not
|
||||
// skip if setting is !name
|
||||
return mappings.filter(entry => entry === '!' + name).length === 0;
|
||||
return mappings.filter((entry) => entry === '!' + name).length === 0;
|
||||
};
|
||||
|
||||
const mapLigatures = (name, mappings) => {
|
||||
let mapping = { name, glyph: name };
|
||||
mappings.forEach(entry => {
|
||||
mappings.forEach((entry) => {
|
||||
const [val1, val2] = entry.split('=');
|
||||
// handle lig=altliga
|
||||
if (val1 === name) {
|
||||
@@ -135,10 +142,10 @@ const filterGlyphsExists = ({ glyph }) => {
|
||||
return exists;
|
||||
};
|
||||
|
||||
const sortLigatures = ligatures => {
|
||||
const sortLigatures = (ligatures) => {
|
||||
// sort by most glyphs then alphabetically
|
||||
const sorted = ligatures
|
||||
.map(ligature => {
|
||||
.map((ligature) => {
|
||||
return { count: ligature.split('_').length + 1, ligature: ligature };
|
||||
})
|
||||
.sort(
|
||||
@@ -146,7 +153,7 @@ const sortLigatures = ligatures => {
|
||||
-compareProperty(a.count, b.count) || // sort by count descending
|
||||
compareProperty(a.ligature, b.ligature) // then by ligature alphabetically
|
||||
)
|
||||
.map(entry => entry.ligature);
|
||||
.map((entry) => entry.ligature);
|
||||
return sorted;
|
||||
};
|
||||
|
||||
@@ -158,20 +165,20 @@ const compareProperty = (a, b) => {
|
||||
}
|
||||
};
|
||||
|
||||
const loadXml = name => {
|
||||
const loadXml = (name) => {
|
||||
const fileName = `./ligature/${ligFontName}/${name}.xml`;
|
||||
const xml = fs.readFileSync(fileName, 'utf-8');
|
||||
return new DOMParser().parseFromString(xml);
|
||||
};
|
||||
|
||||
const processPatch = (name, patchFunc, dom, ligatures, profile) => {
|
||||
const processPatch = (name, patchFunc, dom, ligatures, profile, options) => {
|
||||
console.log(`Patching ${name}`);
|
||||
patchFunc(dom, ligatures, profile);
|
||||
patchFunc(dom, ligatures, profile, options);
|
||||
};
|
||||
|
||||
const PlatformId = {
|
||||
mac: 1,
|
||||
win: 3
|
||||
win: 3,
|
||||
};
|
||||
|
||||
const NameId = {
|
||||
@@ -182,7 +189,7 @@ const NameId = {
|
||||
version: 5,
|
||||
postscriptName: 6,
|
||||
windowsFamilyName: 16,
|
||||
fontStyleName: 17
|
||||
fontStyleName: 17,
|
||||
};
|
||||
|
||||
const patchNames = (dom, ligatures, profile) => {
|
||||
@@ -253,7 +260,7 @@ const patchGlyphs = (dom, ligatures) => {
|
||||
// only import glyphs specified
|
||||
let n = glyphsCount;
|
||||
// get ligature glyphs
|
||||
ligatures.forEach(ligature => {
|
||||
ligatures.forEach((ligature) => {
|
||||
targetGlyphs.appendChild(
|
||||
createElementWithAttributes('GlyphID', { id: n++, name: ligature.glyph })
|
||||
);
|
||||
@@ -262,18 +269,19 @@ const patchGlyphs = (dom, ligatures) => {
|
||||
setAttribute(dom, '/ttFont/maxp/numGlyphs', 'value', n);
|
||||
};
|
||||
|
||||
const patchGsub = (dom, ligatures) => {
|
||||
const patchGsub = (dom, ligatures, options) => {
|
||||
// don't patch if no ligatures other than LIG
|
||||
if (ligatures.length <= 1) return;
|
||||
gsub.initGsubTables(dom, options);
|
||||
|
||||
ligatures.forEach(ligature => {
|
||||
ligatures.forEach((ligature) => {
|
||||
// build gsub tables
|
||||
gsub.buildGsubTables(dom, ligature);
|
||||
gsub.buildGsubTables(dom, ligature, options);
|
||||
});
|
||||
gsub.finalizeGsubTables();
|
||||
};
|
||||
|
||||
const patchHmtx = dom => {
|
||||
const patchHmtx = (dom) => {
|
||||
const mtxCount = xpath.select('count(/ttFont/hmtx/mtx)', dom, true);
|
||||
setAttribute(dom, '/ttFont/hhea/numberOfHMetrics', 'value', mtxCount);
|
||||
|
||||
@@ -306,7 +314,7 @@ const patchCharStrings = (dom, ligatures) => {
|
||||
);
|
||||
const targetGsubrs = xpath.select('/ttFont/CFF/GlobalSubrs', dom, true);
|
||||
const fingerprints = {};
|
||||
ligatures.forEach(ligature => {
|
||||
ligatures.forEach((ligature) => {
|
||||
console.log(
|
||||
`* ${ligature.name}${
|
||||
ligature.name === ligature.glyph ? '' : ' => ' + ligature.glyph
|
||||
@@ -318,11 +326,11 @@ const patchCharStrings = (dom, ligatures) => {
|
||||
|
||||
const subrs = {
|
||||
sourcePath: '/Glyph/Subrs',
|
||||
target: targetSubrs
|
||||
target: targetSubrs,
|
||||
};
|
||||
const gsubrs = {
|
||||
sourcePath: '/Glyph/GlobalSubrs',
|
||||
target: targetGsubrs
|
||||
target: targetGsubrs,
|
||||
};
|
||||
|
||||
patchCharStringSubrs(glyphDom, node, fingerprints, subrs, gsubrs);
|
||||
@@ -332,16 +340,16 @@ const patchCharStrings = (dom, ligatures) => {
|
||||
createElementWithAttributes('mtx', {
|
||||
name: ligature.glyph,
|
||||
width: glyphDom.getAttribute('width'),
|
||||
lsb: glyphDom.getAttribute('lsb')
|
||||
lsb: glyphDom.getAttribute('lsb'),
|
||||
})
|
||||
);
|
||||
const code = glyphDom.getAttribute('code');
|
||||
if (code) {
|
||||
Array.from(targetCmaps).forEach(node => {
|
||||
Array.from(targetCmaps).forEach((node) => {
|
||||
node.appendChild(
|
||||
createElementWithAttributes('map', {
|
||||
code,
|
||||
name: ligature.glyph
|
||||
name: ligature.glyph,
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -354,7 +362,7 @@ const patchCharStringSubrs = (glyphDom, node, fingerprints, subrs, gsubrs) => {
|
||||
|
||||
const lines = node.childNodes[0].textContent.split(/\r|\r\n|\n/g);
|
||||
const newLines = [];
|
||||
lines.forEach(line => {
|
||||
lines.forEach((line) => {
|
||||
if (line.trim().length === 0) return;
|
||||
const matches = line.match(/(.*?)\{([0-9a-z]+)\} (callsubr|callgsubr)$/);
|
||||
if (matches != null) {
|
||||
@@ -403,21 +411,21 @@ const copyConfigAttribute = (dom, configDom, path, name) => {
|
||||
|
||||
const createElementWithAttributes = (tagName, attributes) => {
|
||||
const element = dom.createElement(tagName);
|
||||
Object.entries(attributes).forEach(attribute => {
|
||||
Object.entries(attributes).forEach((attribute) => {
|
||||
element.setAttribute(attribute[0], attribute[1]);
|
||||
});
|
||||
return element;
|
||||
};
|
||||
|
||||
//const dump = dom => console.log(serialize(dom));
|
||||
const serialize = dom =>
|
||||
new XMLSerializer().serializeToString(dom, false, node => {
|
||||
const serialize = (dom) =>
|
||||
new XMLSerializer().serializeToString(dom, false, (node) => {
|
||||
if (node.nodeType === NodeType.TEXT_NODE) {
|
||||
if (regExWhitespace.test(node.data)) return null;
|
||||
const data = node.data
|
||||
.split(/\r|\r\n|\n/g)
|
||||
.filter(s => /\S+/.test(s))
|
||||
.map(s => s.replace(/^\s+/g, ''))
|
||||
.filter((s) => /\S+/.test(s))
|
||||
.map((s) => s.replace(/^\s+/g, ''))
|
||||
.join(os.EOL);
|
||||
|
||||
return node.ownerDocument.createTextNode(data);
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="ampersand.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="bar.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="colon.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="equal.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="exclam.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="greater.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="hyphen.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="less.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="plus.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="question.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="slash.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="underscore.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="ampersand.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="bar.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="colon.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="equal.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="exclam.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="greater.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="hyphen.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="less.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="plus.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="question.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="slash.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="underscore.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="ampersand.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="bar.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="colon.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="equal.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="exclam.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="greater.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="hyphen.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="less.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="plus.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="question.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="slash.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="underscore.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="ampersand.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="bar.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="colon.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="equal.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="exclam.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="greater.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="hyphen.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="less.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="plus.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="question.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="slash.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="underscore.spacer" lsb="0" width="600">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="ampersand.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="bar.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="colon.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="equal.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="exclam.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="greater.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="hyphen.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="less.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="plus.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="question.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="slash.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="underscore.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="ampersand.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="bar.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="colon.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="equal.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="exclam.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="greater.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="hyphen.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="less.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="plus.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="question.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="slash.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="underscore.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="ampersand.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="bar.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="colon.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -1,21 +1,23 @@
|
||||
<Glyph name="colon_equal.liga" lsb="-401" width="625">
|
||||
<Glyph name="colon_equal.liga" lsb="-407" width="625">
|
||||
<CharString>
|
||||
0 129 39 77 169 77 hstem
|
||||
-553 134 512 438 vstem
|
||||
-401 388 rmoveto
|
||||
82 129 -43 77 169 77 -44 130 hstemhm
|
||||
-553 134 23 133 356 438 hintmask 01011110
|
||||
-397 447 rmoveto
|
||||
133 hlineto
|
||||
2 130 rlineto
|
||||
-133 hlineto
|
||||
779 -104 rmoveto
|
||||
hintmask 01101110
|
||||
775 -163 rmoveto
|
||||
1 77 rlineto
|
||||
-538 -77 hlineto
|
||||
-244 -278 rmoveto
|
||||
537 -246 rmoveto
|
||||
1 77 rlineto
|
||||
-538 -77 hlineto
|
||||
hintmask 10101110
|
||||
-250 -86 rmoveto
|
||||
133 hlineto
|
||||
2 130 rlineto
|
||||
-133 hlineto
|
||||
779 -98 rmoveto
|
||||
1 77 rlineto
|
||||
-538 -77 hlineto
|
||||
6 129 rlineto
|
||||
-134 hlineto
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="equal.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="exclam.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="greater.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="hyphen.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="less.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="plus.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,19 @@
|
||||
<Glyph name="plus_equal.liga" lsb="-470" width="625">
|
||||
<CharString>
|
||||
168 77 42 77 50 77 hstem
|
||||
-273 81 205 438 vstem
|
||||
-192 287 rmoveto
|
||||
196 hlineto
|
||||
1 77 rlineto
|
||||
-197 207 -81 -207 -197 -77 197 -208 81 hlineto
|
||||
642 335 rmoveto
|
||||
1 77 rlineto
|
||||
-438 -77 hlineto
|
||||
437 -246 rmoveto
|
||||
1 77 rlineto
|
||||
-438 -77 hlineto
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="question.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="slash.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="underscore.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="w.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="ampersand.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="bar.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="colon.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
@@ -0,0 +1,7 @@
|
||||
<Glyph name="equal.spacer" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user