* \[Experimental\] Add a font feature for texture control (#2081).
- Currently only available through custom builds with `build-texture-feature = true`.
This commit is contained in:
parent
d91cbeca6c
commit
cfb3826680
9 changed files with 179 additions and 4 deletions
|
@ -3,3 +3,5 @@
|
||||||
* Fix serifs of GREEK LETTER DIGAMMA (`U+03DC`) under `ss12`.
|
* Fix serifs of GREEK LETTER DIGAMMA (`U+03DC`) under `ss12`.
|
||||||
* Improve crossbar position of GREEK SMALL LETTER DIGAMMA (`U+03DD`) and add a middle serif under slab.
|
* Improve crossbar position of GREEK SMALL LETTER DIGAMMA (`U+03DD`) and add a middle serif under slab.
|
||||||
* Refine Greek Capital Sho (U+03F7) glyph (#2079).
|
* Refine Greek Capital Sho (U+03F7) glyph (#2079).
|
||||||
|
* \[Experimental\] Add a font feature for texture control (#2081).
|
||||||
|
- Currently only available through custom builds with `build-texture-feature = true`.
|
||||||
|
|
|
@ -3,7 +3,7 @@ $$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [linreg clamp mix fallback] from"../../support/utils.mjs"
|
import [linreg clamp mix fallback] from"../../support/utils.mjs"
|
||||||
import [getGrTree IsSuperscript IsSubscript] from"../../support/gr.mjs"
|
import [getGrTree IsSuperscript IsSubscript] from"../../support/gr.mjs"
|
||||||
import [AnyCv DotlessOrNot CvDecompose MathSansSerif] from"../../support/gr.mjs"
|
import [AnyCv DotlessOrNot CvDecompose MathSansSerif Texture] from"../../support/gr.mjs"
|
||||||
import [NumeratorForm DenominatorForm] from"../../support/gr.mjs"
|
import [NumeratorForm DenominatorForm] from"../../support/gr.mjs"
|
||||||
import [Transform] from"../../support/geometry/transform.mjs"
|
import [Transform] from"../../support/geometry/transform.mjs"
|
||||||
extern Map
|
extern Map
|
||||||
|
@ -693,6 +693,68 @@ glyph-block Autobuild-Transformed : begin
|
||||||
|
|
||||||
link-relations relSets
|
link-relations relSets
|
||||||
|
|
||||||
|
glyph-block Autobuild-Transformed-Texture : begin
|
||||||
|
if (!(para.buildTexture && !para.isQuasiProportional)) : return nothing
|
||||||
|
|
||||||
|
glyph-block-import CommonShapes
|
||||||
|
glyph-block-import Common-Derivatives
|
||||||
|
glyph-block-import Recursive-Build : Fork
|
||||||
|
glyph-block-import Autobuild-Transformed-Shared : extendRelatedGlyphs link-relations wrapName
|
||||||
|
|
||||||
|
define [createTextureDerivatives gr extL extR _records] : begin
|
||||||
|
local { records relSets targetNameMap } : extendRelatedGlyphs gr.key _records
|
||||||
|
local pendingGlyphs : records.map : [record] => record.1
|
||||||
|
|
||||||
|
local forkedPara : Object.assign {.} para
|
||||||
|
if (extL + extR > 0)
|
||||||
|
: then : forkedPara.diversityM = 1 + extL + extR
|
||||||
|
: else : begin
|
||||||
|
forkedPara.diversityF = 1 + extL + extR
|
||||||
|
forkedPara.diversityI = 1 + extL + extR
|
||||||
|
forkedPara.diversityII = 1 + extL + extR
|
||||||
|
|
||||||
|
local forked : Fork pendingGlyphs forkedPara
|
||||||
|
foreach {unicode glyphid} [items-of records] : begin
|
||||||
|
if [not : query-glyph targetNameMap.(glyphid)] : begin
|
||||||
|
define glyphT : forked.queryByName glyphid
|
||||||
|
define glyphO : glyphStore.queryByName glyphid
|
||||||
|
if (glyphT && glyphO) : begin
|
||||||
|
if (glyphT.advanceWidth != glyphO.advanceWidth) : begin
|
||||||
|
gr.set glyphO targetNameMap.(glyphid)
|
||||||
|
create-glyph targetNameMap.(glyphid) unicode : glyph-proc
|
||||||
|
include glyphT AS_BASE ALSO_METRICS
|
||||||
|
set-width Width
|
||||||
|
if extL : currentGlyph.applyTransform [Translate (-extL * Width) 0] true
|
||||||
|
|
||||||
|
link-relations relSets
|
||||||
|
|
||||||
|
define ranges : list
|
||||||
|
list 0x41 0x5A
|
||||||
|
list 0x61 0x7A
|
||||||
|
list 0xC0 0xFF
|
||||||
|
list 0x100 0x2AF
|
||||||
|
list 0x370 0x3FF
|
||||||
|
list 0x400 0x4FF
|
||||||
|
list 0x500 0x52F
|
||||||
|
|
||||||
|
define [jobs base] : list
|
||||||
|
local results {}
|
||||||
|
foreach {low high} [items-of ranges] : begin
|
||||||
|
foreach lch [range low till high] : begin
|
||||||
|
local source : glyphStore.queryNameByUnicode lch
|
||||||
|
if source : results.push { null source }
|
||||||
|
return results
|
||||||
|
|
||||||
|
define EXTENSION : 1 / 12
|
||||||
|
define SHRINK : -1 / 12
|
||||||
|
createTextureDerivatives Texture.ExtL EXTENSION 0 [jobs 0xF000]
|
||||||
|
createTextureDerivatives Texture.ExtR 0 EXTENSION [jobs 0xF100]
|
||||||
|
createTextureDerivatives Texture.ExtLR EXTENSION EXTENSION [jobs 0xF200]
|
||||||
|
createTextureDerivatives Texture.ShrL SHRINK 0 [jobs 0xF300]
|
||||||
|
createTextureDerivatives Texture.ShrR 0 SHRINK [jobs 0xF400]
|
||||||
|
createTextureDerivatives Texture.ShrLR SHRINK SHRINK [jobs 0xF500]
|
||||||
|
|
||||||
|
|
||||||
glyph-block Autobuild-Transformed-Mathematical : begin
|
glyph-block Autobuild-Transformed-Mathematical : begin
|
||||||
glyph-block-import CommonShapes
|
glyph-block-import CommonShapes
|
||||||
glyph-block-import Common-Derivatives
|
glyph-block-import Common-Derivatives
|
||||||
|
|
|
@ -137,4 +137,6 @@ export : define [buildCVSS gsub para glyphStore] : begin
|
||||||
|
|
||||||
gsub.endBlock rec
|
gsub.endBlock rec
|
||||||
|
|
||||||
|
return cvs
|
||||||
|
|
||||||
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
||||||
|
|
88
font-src/otl/gsub-texture.ptl
Normal file
88
font-src/otl/gsub-texture.ptl
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
$$include '../meta/macros.ptl'
|
||||||
|
|
||||||
|
extern Set
|
||||||
|
|
||||||
|
import [Texture CvDecompose] from"../support/gr.mjs"
|
||||||
|
|
||||||
|
# Name-driven feature pairs
|
||||||
|
export : define [buildGsubTexture gsub glyphStore markGlyphs cvs] : begin
|
||||||
|
local anyMark : Array.from markGlyphs.all
|
||||||
|
local rec : gsub.beginBlock
|
||||||
|
|
||||||
|
define txtr : gsub.addCommonFeature : gsub.createFeature 'TXTR'
|
||||||
|
define { chain-rule reverse-rule } : gsub.ChainRuleBuilder
|
||||||
|
|
||||||
|
local extRFrom { }
|
||||||
|
local extRTo { }
|
||||||
|
local extLFrom { }
|
||||||
|
local extLTo { }
|
||||||
|
local shrLFrom { }
|
||||||
|
local shrLTo { }
|
||||||
|
local shrRFrom { }
|
||||||
|
local shrRTo { }
|
||||||
|
|
||||||
|
local anyInfluence : new Set
|
||||||
|
|
||||||
|
foreach { gid g } [glyphStore.namedEntries] : if (gid.(0) !== ".") : begin
|
||||||
|
local extL : Texture.ExtL.get g
|
||||||
|
local extR : Texture.ExtR.get g
|
||||||
|
local extLR : Texture.ExtLR.get g
|
||||||
|
local shrL : Texture.ShrL.get g
|
||||||
|
local shrR : Texture.ShrR.get g
|
||||||
|
local shrLR : Texture.ShrLR.get g
|
||||||
|
|
||||||
|
if extR : begin [extRFrom.push gid] [extRTo.push extR]
|
||||||
|
if extL : begin [extLFrom.push gid] [extLTo.push extL]
|
||||||
|
if (extR && extLR) : begin [extLFrom.push extR] [extLTo.push extLR]
|
||||||
|
|
||||||
|
if shrL : begin [shrLFrom.push gid] [shrLTo.push shrL]
|
||||||
|
if shrR : begin [shrRFrom.push gid] [shrRTo.push shrR]
|
||||||
|
if (shrL && shrLR) : begin [shrRFrom.push shrL] [shrRTo.push shrLR]
|
||||||
|
|
||||||
|
if (extL || extR || shrL || shrR) : anyInfluence.add gid
|
||||||
|
|
||||||
|
define subExtR : gsub.createLookup
|
||||||
|
.type 'gsub_chaining'
|
||||||
|
.ignoreGlyphs anyMark
|
||||||
|
.rules : list
|
||||||
|
chain-rule
|
||||||
|
extRFrom ~> extRTo
|
||||||
|
shrLFrom ~> shrLTo
|
||||||
|
|
||||||
|
define subExtL : gsub.createLookup
|
||||||
|
.type 'gsub_chaining'
|
||||||
|
.ignoreGlyphs anyMark
|
||||||
|
.rules : list
|
||||||
|
chain-rule
|
||||||
|
shrRFrom ~> shrRTo
|
||||||
|
extLFrom ~> extLTo
|
||||||
|
|
||||||
|
txtr.addLookup subExtR
|
||||||
|
txtr.addLookup subExtL
|
||||||
|
gsub.setDependency subExtR subExtL
|
||||||
|
|
||||||
|
# Decompose everything if we enable TXTR
|
||||||
|
if cvs
|
||||||
|
: then : begin
|
||||||
|
# Reuse existing Cvdecompose data
|
||||||
|
foreach cv [cvs.values] : begin
|
||||||
|
if cv.decompositionLookup : begin
|
||||||
|
txtr.addLookup cv.decompositionLookup
|
||||||
|
gsub.setDependency cv.decompositionLookup subExtR
|
||||||
|
: else : begin
|
||||||
|
# Built it from scratch
|
||||||
|
local decompose : gsub.createLookup
|
||||||
|
.type 'gsub_multiple'
|
||||||
|
.substitutions {.}
|
||||||
|
|
||||||
|
foreach { gn glyph } [glyphStore.namedEntries] : begin
|
||||||
|
local parts : CvDecompose.get glyph
|
||||||
|
if parts : begin
|
||||||
|
local influenced : anyInfluence.has gn
|
||||||
|
foreach part [items-of parts] : if [anyInfluence.has part] : set influenced true
|
||||||
|
if influenced : set decompose.substitutions.(gn) parts
|
||||||
|
|
||||||
|
txtr.addLookup decompose
|
||||||
|
gsub.setDependency decompose subExtR
|
||||||
|
|
||||||
|
gsub.endBlock rec
|
|
@ -10,6 +10,7 @@ import [buildFrac] from"./gsub-frac.mjs"
|
||||||
import [buildCVSS] from"./gsub-cv-ss.mjs"
|
import [buildCVSS] from"./gsub-cv-ss.mjs"
|
||||||
import [buildLOCL] from"./gsub-locl.mjs"
|
import [buildLOCL] from"./gsub-locl.mjs"
|
||||||
import [buildGsubThousands] from"./gsub-thousands.mjs"
|
import [buildGsubThousands] from"./gsub-thousands.mjs"
|
||||||
|
import [buildGsubTexture] from"./gsub-texture.mjs"
|
||||||
import [buildMarkMkmk] from"./gpos-mark-mkmk.mjs"
|
import [buildMarkMkmk] from"./gpos-mark-mkmk.mjs"
|
||||||
|
|
||||||
define GDEF_SIMPLE 1
|
define GDEF_SIMPLE 1
|
||||||
|
@ -60,8 +61,9 @@ define [buildGSUB para glyphStore markGlyphs] : begin
|
||||||
buildGsubThousands gsub para glyphStore
|
buildGsubThousands gsub para glyphStore
|
||||||
|
|
||||||
# cv##, ss##
|
# cv##, ss##
|
||||||
|
local cvs nothing
|
||||||
if para.enableCvSs : begin
|
if para.enableCvSs : begin
|
||||||
buildCVSS gsub para glyphStore
|
set cvs : buildCVSS gsub para glyphStore
|
||||||
|
|
||||||
# ccmp post cv/ss (for Ogonek shape transform)
|
# ccmp post cv/ss (for Ogonek shape transform)
|
||||||
buildCCMPPostCvSs gsub ccmp glyphStore markGlyphs
|
buildCCMPPostCvSs gsub ccmp glyphStore markGlyphs
|
||||||
|
@ -70,6 +72,10 @@ define [buildGSUB para glyphStore markGlyphs] : begin
|
||||||
# Builds last, but the lookups are added into the beginning of the lookup list
|
# Builds last, but the lookups are added into the beginning of the lookup list
|
||||||
buildLOCL gsub para glyphStore
|
buildLOCL gsub para glyphStore
|
||||||
|
|
||||||
|
# TXTR, "texture" feature
|
||||||
|
if (para.buildTexture && !para.isQuasiProportional) : begin
|
||||||
|
buildGsubTexture gsub glyphStore markGlyphs cvs
|
||||||
|
|
||||||
gsub.finalize
|
gsub.finalize
|
||||||
return gsub
|
return gsub
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,19 @@ export const VS01 = LinkedGlyphProp("VS01");
|
||||||
export const TieMark = LinkedGlyphProp("TieMark");
|
export const TieMark = LinkedGlyphProp("TieMark");
|
||||||
export const LeaningMark = LinkedGlyphProp("LeaningMark");
|
export const LeaningMark = LinkedGlyphProp("LeaningMark");
|
||||||
export const LeaningMarkSpacer = LinkedGlyphProp("LeaningMarkSpacer");
|
export const LeaningMarkSpacer = LinkedGlyphProp("LeaningMarkSpacer");
|
||||||
|
|
||||||
|
export const Texture = {
|
||||||
|
ExtL: LinkedGlyphProp("TextureExtL"),
|
||||||
|
ExtR: LinkedGlyphProp("TextureExtR"),
|
||||||
|
ExtLR: LinkedGlyphProp("TextureExtLR"),
|
||||||
|
ShrL: LinkedGlyphProp("TextureShrL"),
|
||||||
|
ShrR: LinkedGlyphProp("TextureShrR"),
|
||||||
|
ShrLR: LinkedGlyphProp("TextureShrLR")
|
||||||
|
};
|
||||||
|
|
||||||
function LinkedGlyphProp(key) {
|
function LinkedGlyphProp(key) {
|
||||||
return {
|
return {
|
||||||
|
key,
|
||||||
get(glyph) {
|
get(glyph) {
|
||||||
if (glyph && glyph.related) return glyph.related[key];
|
if (glyph && glyph.related) return glyph.related[key];
|
||||||
else return null;
|
else return null;
|
||||||
|
|
|
@ -11,6 +11,7 @@ export function init(data, argv) {
|
||||||
applyAlternatesParam(argv, para, data, "slope", "slope");
|
applyAlternatesParam(argv, para, data, "slope", "slope");
|
||||||
if (argv.featureControl.noCvSs) para.enableCvSs = false;
|
if (argv.featureControl.noCvSs) para.enableCvSs = false;
|
||||||
if (argv.featureControl.noLigation) para.enableLigation = false;
|
if (argv.featureControl.noLigation) para.enableLigation = false;
|
||||||
|
if (argv.featureControl.buildTexture) para.buildTexture = true;
|
||||||
return para;
|
return para;
|
||||||
}
|
}
|
||||||
function applyBlendingParam(argv, para, data, key, keyArgv) {
|
function applyBlendingParam(argv, para, data, key, keyArgv) {
|
||||||
|
|
|
@ -3,7 +3,8 @@ import UnicodeDataIndex from "@unicode/unicode-15.0.0";
|
||||||
export async function collectBlockData() {
|
export async function collectBlockData() {
|
||||||
const BlockData = [
|
const BlockData = [
|
||||||
[[0xe0a0, 0xe0df], "Private Use Area — Powerline"],
|
[[0xe0a0, 0xe0df], "Private Use Area — Powerline"],
|
||||||
[[0xee00, 0xee3f], "Private Use Area — Progress Bar"]
|
[[0xee00, 0xee3f], "Private Use Area — Progress Bar"],
|
||||||
|
[[0xf000, 0xf8ff], "Private Use Area — Texture"]
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const id of UnicodeDataIndex.Block) {
|
for (const id of UnicodeDataIndex.Block) {
|
||||||
|
|
|
@ -230,6 +230,7 @@ const CompositesFromBuildPlan = computed(`metadata:composites-from-build-plan`,
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// eslint-disable-next-line complexity
|
||||||
const FontInfoOf = computed.group("metadata:font-info-of", async (target, fileName) => {
|
const FontInfoOf = computed.group("metadata:font-info-of", async (target, fileName) => {
|
||||||
const [{ fileNameToBpMap, buildPlans }] = await target.need(BuildPlans);
|
const [{ fileNameToBpMap, buildPlans }] = await target.need(BuildPlans);
|
||||||
const [version] = await target.need(Version);
|
const [version] = await target.need(Version);
|
||||||
|
@ -261,7 +262,8 @@ const FontInfoOf = computed.group("metadata:font-info-of", async (target, fileNa
|
||||||
featureControl: {
|
featureControl: {
|
||||||
noCvSs: bp["no-cv-ss"] || false,
|
noCvSs: bp["no-cv-ss"] || false,
|
||||||
noLigation: bp["no-ligation"] || false,
|
noLigation: bp["no-ligation"] || false,
|
||||||
exportGlyphNames: bp["export-glyph-names"] || false
|
exportGlyphNames: bp["export-glyph-names"] || false,
|
||||||
|
buildTexture: bp["build-texture-feature"] || false
|
||||||
},
|
},
|
||||||
// Ligations
|
// Ligations
|
||||||
ligations: bp.ligations || null,
|
ligations: bp.ligations || null,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue