Skip to content

Instantly share code, notes, and snippets.

@simoncozens
simoncozens / cmap-survey.py
Created Jul 10, 2020
Survey CMAP tables of installed fonts
View cmap-survey.py
from fontTools.ttLib import TTFont
import glob
from tabulate import tabulate
import os
import random
paths = [
os.path.expanduser("~/Library/Fonts"),
"/Library/Fonts",
View badkerndetector.py
from tensorfont.dataset import prepare_training_data
from tensorfont.generators import RandomPair
prepare_training_data()
def kern_generator():
rpg = RandomPair(196, 196, 76, "training")
gen = rpg.generator()
while True:
font, left, right = next(gen)
img1, perturbation = rpg.get_image(font, left, right, perturbation_range= [-100,100])
@simoncozens
simoncozens / interrofont.py
Created Apr 3, 2020
Interrofont: Show various data about a font from the command line
View interrofont.py
#!env python3
import sys
from fontTools.ttLib import TTFont
from argparse import ArgumentParser
import itertools
parser = ArgumentParser()
parser.add_argument("input",
help="font file to process", metavar="FILE")
parser.add_argument('-n', "--name", action='store_true',
View ncov2019.r
library(readr)
library(dplyr)
library(ggplot2)
library(tidyr)
logTicks <- function(n = 5, base = 10){
# Divisors of the logarithm base. E.g. for base 10: 1, 2, 5, 10.
divisors <- which((base / seq_len(base)) %% 1 == 0)
mkTcks <- function(min, max, base, divisor){
f <- seq(divisor, base, by = divisor)
View JSTFBuilder.py
#!/usr/bin/env python
# Builds a JSTF table from specially named features
# To use:
# First, set up the features in your font.
# You may add as many or as few features as you like, but they must conform
# to the following naming convention:
# exs1: First priority extension substitution.
# i.e. the first rules we try to substitute glyphs to make the line longer
# exp1: First priority extension positioning.
# i.e. the first rules we try to reposition glyphs to make the line longer
View IUP Optimizer Test
from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.ttLib import TTFont
from Lib.fontTools.varLib.iup import iup_delta_optimize, _iup_contour_bound_forced_set
font = TTFont("NotoSerifHebrew-GX.ttf")
gvar = font["gvar"]
glyf = font["glyf"]
total = 0
@simoncozens
simoncozens / HTKerner.py
Created Feb 1, 2019
HT LetterKerner, first draft
View HTKerner.py
#MenuTitle: HT LetterKerner
# Put this in your HTLetterSpacer script directory so it can find
# the library.
# Todo:
# Does not handle whole-font yet.
# Does not know or care about kerning groups.
# The reference glyph should be adjusted based on the letter pair
# - "n" works well for lowercase-lowercase
@simoncozens
simoncozens / SignalHandler.py
Created May 31, 2018
Keras callback for signal handing
View SignalHandler.py
# In your model:
# from SignalHandler import SignalHandler
# model.fit(... callbacks=[..., SignalHandler()])
# kill -USR1 $KERAS_PROCESS # Drop learning rate x0.1
# kill -USR2 $KERAS_PROCESS # Save model immediately
# kill $KERAS_PROCESS # Terminate at end of epoch
from keras import backend as K
from keras.callbacks import Callback
@simoncozens
simoncozens / otvar-instance.py
Created Sep 27, 2016
OpenType Variation Instance Generator
View otvar-instance.py
#!/usr/bin/python
from fontTools.misc.py23 import *
from fontTools.ttLib import TTFont
import sys
import argparse
parser = argparse.ArgumentParser(description="OpenType Variation Instance Generator")
parser.add_argument('font', help="font file")
parser.add_argument('-a', '--all', action="store_true", help="Generate all instances")
parser.add_argument('-o', '--output', help="Output directory", default = ".")
@simoncozens
simoncozens / harmonization.md
Last active Oct 7, 2020
Harmonizing two Bezier curves
View harmonization.md

To harmonize (with G2 curvature) two cubic Bézier curves a0,a1,a2,a3 and b0,b1,b2,b3 where a2, a3 = b0, and b1 are colinear:

  • First find d = intersection point of line a1--a2 and line b1--b2.
  • Now find ratios p0 = |a1, a2| / |a2, d| and p1 = |d1, b1| / |b1, b2|.
  • Determine ratio p = sqrt(p0 * p1)
  • Now set position of a3 = b0 such that |a2, a3| / |a3, b1| == p.
  • To do this, set t = p / (p+1).
  • Adjust the position of a3=b0 so that it sits t of the way between a2 and b1.

Of course, you may prefer to keep the position of a3 because it's the on-curve point. Fine. Instead, compute where a3 should go according to this algorithm, work out the delta between the new position and the current position, and apply that delta to the handles a2 and b1 instead.

You can’t perform that action at this time.