* \[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`.
|
||||
* 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).
|
||||
* \[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 [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 [Transform] from"../../support/geometry/transform.mjs"
|
||||
extern Map
|
||||
|
@ -693,6 +693,68 @@ glyph-block Autobuild-Transformed : begin
|
|||
|
||||
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-import CommonShapes
|
||||
glyph-block-import Common-Derivatives
|
||||
|
|
|
@ -137,4 +137,6 @@ export : define [buildCVSS gsub para glyphStore] : begin
|
|||
|
||||
gsub.endBlock rec
|
||||
|
||||
return cvs
|
||||
|
||||
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 [buildLOCL] from"./gsub-locl.mjs"
|
||||
import [buildGsubThousands] from"./gsub-thousands.mjs"
|
||||
import [buildGsubTexture] from"./gsub-texture.mjs"
|
||||
import [buildMarkMkmk] from"./gpos-mark-mkmk.mjs"
|
||||
|
||||
define GDEF_SIMPLE 1
|
||||
|
@ -60,8 +61,9 @@ define [buildGSUB para glyphStore markGlyphs] : begin
|
|||
buildGsubThousands gsub para glyphStore
|
||||
|
||||
# cv##, ss##
|
||||
local cvs nothing
|
||||
if para.enableCvSs : begin
|
||||
buildCVSS gsub para glyphStore
|
||||
set cvs : buildCVSS gsub para glyphStore
|
||||
|
||||
# ccmp post cv/ss (for Ogonek shape transform)
|
||||
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
|
||||
buildLOCL gsub para glyphStore
|
||||
|
||||
# TXTR, "texture" feature
|
||||
if (para.buildTexture && !para.isQuasiProportional) : begin
|
||||
buildGsubTexture gsub glyphStore markGlyphs cvs
|
||||
|
||||
gsub.finalize
|
||||
return gsub
|
||||
|
||||
|
|
|
@ -23,8 +23,19 @@ export const VS01 = LinkedGlyphProp("VS01");
|
|||
export const TieMark = LinkedGlyphProp("TieMark");
|
||||
export const LeaningMark = LinkedGlyphProp("LeaningMark");
|
||||
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) {
|
||||
return {
|
||||
key,
|
||||
get(glyph) {
|
||||
if (glyph && glyph.related) return glyph.related[key];
|
||||
else return null;
|
||||
|
|
|
@ -11,6 +11,7 @@ export function init(data, argv) {
|
|||
applyAlternatesParam(argv, para, data, "slope", "slope");
|
||||
if (argv.featureControl.noCvSs) para.enableCvSs = false;
|
||||
if (argv.featureControl.noLigation) para.enableLigation = false;
|
||||
if (argv.featureControl.buildTexture) para.buildTexture = true;
|
||||
return para;
|
||||
}
|
||||
function applyBlendingParam(argv, para, data, key, keyArgv) {
|
||||
|
|
|
@ -3,7 +3,8 @@ import UnicodeDataIndex from "@unicode/unicode-15.0.0";
|
|||
export async function collectBlockData() {
|
||||
const BlockData = [
|
||||
[[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) {
|
||||
|
|
|
@ -230,6 +230,7 @@ const CompositesFromBuildPlan = computed(`metadata:composites-from-build-plan`,
|
|||
return data;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
const FontInfoOf = computed.group("metadata:font-info-of", async (target, fileName) => {
|
||||
const [{ fileNameToBpMap, buildPlans }] = await target.need(BuildPlans);
|
||||
const [version] = await target.need(Version);
|
||||
|
@ -261,7 +262,8 @@ const FontInfoOf = computed.group("metadata:font-info-of", async (target, fileNa
|
|||
featureControl: {
|
||||
noCvSs: bp["no-cv-ss"] || 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: bp.ligations || null,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue