# ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # File: iosevka-fonts-all-build-plan.pl # Copyright 🄯 2016—2023 Van de Bugger. # SPDX-License-Identifier: FSFAP # ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # Generates Iosevka private build plan. use v5.30.0; use warnings; use FindBin; use TOML; BEGIN { require "$FindBin::Bin/iosevka-fonts-all.pm" or die( $@ or $! ); Iosevka::Util->import; }; # ------------------------------------------------------------------------------------------------ # Functions # ------------------------------------------------------------------------------------------------ # Merge the second hash to the first one. sub _merge($$); sub _merge($$) { my ( $a, $b ) = @_; while ( my ( $k, $v ) = each( %$b ) ) { if ( defined( $v ) ) { if ( ref( $v ) eq 'HASH' ) { $a->{ $k } //= {}; _merge( $a->{ $k }, $v ); } else { $a->{ $k } = $v; }; }; }; }; # Merge hashes. sub merge { my $r = {}; for my $a ( @_ ) { if ( defined( $a ) ) { _merge( $r, $a ); }; }; return $r; }; # ------------------------------------------------------------------------------------------------ # Variables # ------------------------------------------------------------------------------------------------ my $output = "private-build-plans.toml"; my %spacings = ( # Uniform Iosevka spacing name # => Original Iosevka spacing name. prop => 'quasi-proportional', full => 'normal', term => 'term', mono => 'fontconfig-mono', hard => 'fixed', ); my %weights = ( map( { ( $Weights[ $_ ] => { shape => 100 * ( $_ + 1 ), menu => 100 * ( $_ + 1 ), css => 100 * ( $_ + 1 ), }, ) } 0 .. $#Weights ) ); my %widths = ( condensed => { shape => 500, menu => 3, css => "condensed", }, normal => { shape => 600, menu => 5, css => "normal", }, ); my %slopes = ( upright => { angle => 0.0, css => 'normal', }, oblique => { angle => 9.4 }, italic => { angle => 9.4 } ); for my $slope ( @Slopes ) { $slopes{ $slope }->{ $_ } //= $slope for qw( shape menu css ); }; # ------------------------------------------------------------------------------------------------ # Parse command line # ------------------------------------------------------------------------------------------------ sub parse_part($) { my ( $str ) = @_; $str =~ s/\A\{(.*)\}\z/$1/ or die "oops"; return hash( split( ',', $str ) ); }; my %opts; get_options( map( { ( "$_=s" => sub { my ( $opt, $arg ) = @_; my @parts = split( '-', $arg ); @parts == 3 or die "oops"; $opts{ $opt } = { weights => { parse_part( $parts[ 0 ] ) }, widths => { parse_part( $parts[ 1 ] ) }, slopes => { parse_part( $parts[ 2 ] ) }, }; }, ) } @Families ), ); my %common = ( 'zero' => "dotted-oval", 'two' => "straight-neck", 'four' => "closed-non-crossing", 'five' => "oblique-upper-left-bar", 'six' => "closed-contour", 'seven' => "bend-serifless", 'eight' => "crossing-asymmetric", 'nine' => "closed-contour", 'asterisk' => "penta-low", 'brace' => "straight", 'percent' => "rings-continuous-slash", ); my %variants = ( sans => { design => { 'f' => "flat-hook", 'g' => "double-storey", 'i' => "hooky", 'j' => "flat-hook-serifed", 'l' => "serifed-flat-tailed", 'r' => "compact", 't' => "flat-hook", 'w' => "straight-flat-top", 'y' => "straight-turn", 'capital-g' => "toothless-rounded-serifless-hooked", 'capital-j' => "flat-hook-serifed", 'lower-alpha' => "tailed-barred", 'lower-lambda' => "straight-turn", 'cyrl-capital-u' => "straight-turn", %common, }, italic => { 'a' => "single-storey-serifless", 'd' => "toothed-serifless", 'g' => "single-storey-flat-hook-serifless", 'i' => "serifed-flat-tailed", 'k' => "straight-serifless", 'u' => "toothed", 'cyrl-ef' => "serifless", 'cyrl-capital-u' => "straight-turn", }, }, slab => { design => { 'f' => "flat-hook-serifed", 'g' => "double-storey", 'j' => "flat-hook-serifed", 'r' => "corner-hooked-serifed", 't' => "flat-hook", 'w' => "straight-flat-top", 'capital-a' => "straight-tri-serifed", 'capital-j' => "flat-hook-serifed-symmetric", 'lower-alpha' => "tailed-barred", %common, 'three' => "flat-top", 'four' => "closed", 'seven' => "bend-serifed", }, italic => { 'a' => "single-storey-serifed", 'd' => "toothed-serifed", 'g' => "single-storey-flat-hook-serifed", 'h' => "straight", 'i' => "serifed-flat-tailed", 'k' => "straight-serifed", 'l' => "serifed-flat-tailed", 'u' => "motion-serifed", 'v' => "straight", 'x' => "straight-serifed", 'y' => "straight-turn", 'z' => "straight-serifed", 'capital-j' => "flat-hook-serifed-symmetric", 'cyrl-ka' => "symmetric-connected-serifed", 'cyrl-el' => "straight", 'cyrl-en' => "serifed", 'cyrl-ef' => "serifed", 'cyrl-che' => "standard", }, }, ); my %prop = ( sans => { design => { 'i' => "serifless", 'j' => "flat-hook-serifless", 'l' => "flat-tailed", }, }, slab => { }, ); my $plans = {}; for my $spacing ( @Spacings ) { for my $serif ( @Serifs ) { my $family = "$spacing-$serif"; $opts{ $family } or next; my $opt = $opts{ "$family" }; $plans->{ buildPlans }->{ "iosevka-$family" } = { 'family' => tc( cat( "Iosevka", $spacing, $serif ) ), 'spacing' => $spacings{ $spacing }, 'serifs' => $serif, 'no-cv-ss' => "false", 'variants' => merge( $variants{ $serif }, $spacing eq 'prop' ? $prop{ $serif } : {}, ), 'weights' => { map( { $opt->{ weights }->{ $_ } ? ( $_ => $weights{ $_ } ) : () } @Weights ) }, 'widths' => { map( { $opt->{ widths }->{ $_ } ? ( $_ => $widths{ $_ } ) : () } @Widths ) }, 'slopes' => { map( { $opt->{ slopes }->{ $_ } ? ( $_ => $slopes{ $_ } ) : () } @Slopes ) }, }; }; }; path( $output )->spew_utf8( to_toml( $plans ) ); # end of file #