-
Notifications
You must be signed in to change notification settings - Fork 15
Adding VF extracting support #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
|
||
import time | ||
from fontTools.pens.boundsPen import ControlBoundsPen | ||
from fontTools.pens.hashPointPen import HashPointPen | ||
|
@@ -8,6 +9,7 @@ | |
USE_MY_METRICS, | ||
) | ||
from fontTools.ttLib.tables._h_e_a_d import mac_epoch_diff | ||
from fontTools.varLib.mutator import instantiateVariableFont | ||
from extractor.exceptions import ExtractorError | ||
from extractor.stream import InstructionStream | ||
from extractor.tools import RelaxedInfo, copyAttr | ||
|
@@ -32,6 +34,23 @@ def isOpenType(pathOrFile): | |
return False | ||
return True | ||
|
||
def isVarFont(pathOrFile): | ||
try: | ||
font = TTFont(pathOrFile) | ||
fvar = varFont["fvar"] | ||
del varFont | ||
except TTLibError: | ||
return False | ||
return True | ||
|
||
def locationToName(locDict): | ||
name = "" | ||
for tag,val in locDict.items(): | ||
name += f"{tag}_{val};" | ||
return name | ||
|
||
def getDefaultLocation(varFont): | ||
return {axis.axisTag:axis.defaultValue for axis in varFont["fvar"].axes} | ||
|
||
def extractFontFromOpenType( | ||
pathOrFile, | ||
|
@@ -48,6 +67,20 @@ def extractFontFromOpenType( | |
extractOpenTypeInfo(source, destination) | ||
if doGlyphs: | ||
extractOpenTypeGlyphs(source, destination) | ||
if isVarFont: | ||
''' | ||
Add Support for extracting Variable Instances as RLayer objects | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better separate UFOs or layers? Not sure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh good point, I had imagined a layer-based import just because I thought containing everything in one file was more "UFO-esque" but multiple files could be a better solution. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May be good to have the option to do either There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extractor works by providing a dest font object and a source binary file. ufo = defcon.Font()
extractor.extractUFO("/path/to/MyFont.ttf", ufo) Returning a list of ufo's is a big change. Adding arguments is also a big change. Im thinking that extracting variable fonts should be implicit, and maybe directly into a designspace object: extract axis, ranges, the relationships between sources, store font objects as sources in the designspace document object: extractVariableFont("path/to/varfont.ttf", designspaceDocumentObject)
# raise error when no fvar table is found Extractor is not build to round trip from binary to ufo and back, so parts can lost during extracting. But is would be cool to get as much data as possible back into scriptable objects. |
||
Currently this is pulling the VFs instances but I think using the Sources is a better solution? | ||
''' | ||
defLoc = getDefaultLocation(source) | ||
locations = [instance.coordinates for instance in source["fvar"].instances] | ||
# sourceFonts = [instantiateVariableFont(source,loc,True,True) for loc in locations] | ||
for varLoc in locations: | ||
if varLoc != defLoc: | ||
instanceFont = instantiateVariableFont(source,varLoc) | ||
layerName = locationToName(varLoc) | ||
extractOpenTypeGlyphs(instanceFont, destination, layerName) | ||
|
||
extractUnicodeVariationSequences(source, destination) | ||
if doGlyphOrder: | ||
extractGlyphOrder(source, destination) | ||
|
@@ -59,7 +92,11 @@ def extractFontFromOpenType( | |
for function in customFunctions: | ||
function(source, destination) | ||
if doInstructions: | ||
extractInstructions(source, destination) | ||
if not isVarFont: | ||
''' | ||
seems to run into issue with extracting VF component indentifier | ||
''' | ||
extractInstructions(source, destination) | ||
source.close() | ||
|
||
|
||
|
@@ -522,19 +559,23 @@ def binaryToIntList(value, start=0): | |
# -------- | ||
|
||
|
||
def extractOpenTypeGlyphs(source, destination): | ||
def extractOpenTypeGlyphs(source, destination, layerName="public.default"): | ||
# grab the cmap | ||
vmtx = source.get("vmtx") | ||
vorg = source.get("VORG") | ||
is_ttf = "glyf" in source | ||
reversedMapping = source.get("cmap").buildReversed() | ||
# add layers | ||
if layerName != destination.defaultLayerName: | ||
destination.newLayer(layerName) | ||
# grab the glyphs | ||
glyphSet = source.getGlyphSet() | ||
for glyphName in glyphSet.keys(): | ||
sourceGlyph = glyphSet[glyphName] | ||
# make the new glyph | ||
destination.newGlyph(glyphName) | ||
destinationGlyph = destination[glyphName] | ||
destinationLayer = destination.getLayer(layerName) | ||
destinationLayer.newGlyph(glyphName) | ||
destinationGlyph = destinationLayer[glyphName] | ||
# outlines | ||
if is_ttf: | ||
pen = destinationGlyph.getPointPen() | ||
|
Uh oh!
There was an error while loading. Please reload this page.