~raph/interp-toy

99dec86f10988f0b415899481d9652ae546f97f8 — Raph Levien 2 years ago 716b180
Start loading data from font

Loads a glyph from a font and populates a point cloud.
M Cargo.lock => Cargo.lock +97 -0
@@ 12,6 12,14 @@ dependencies = [
]

[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "approx"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 28,6 36,15 @@ dependencies = [
]

[[package]]
name = "atty"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "autocfg"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 114,6 131,20 @@ dependencies = [
]

[[package]]
name = "clap"
version = "2.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
 "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 337,8 368,10 @@ version = "0.1.0"
dependencies = [
 "druid 0.3.0 (git+https://github.com/xi-editor/druid?rev=cfbde68ca16c67b20268a5999da469ed76999b82)",
 "glyphstool 0.1.0",
 "kurbo 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "nalgebra 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "rbf-interp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "structopt 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]


@@ 620,6 653,16 @@ dependencies = [
]

[[package]]
name = "proc-macro-error"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "proc-macro-hack"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 854,6 897,32 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "structopt"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "structopt-derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "structopt-derive"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "syn"
version = "0.15.42"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 885,6 954,14 @@ dependencies = [
]

[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 940,6 1017,11 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "unicode-width"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 950,6 1032,11 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "vec_map"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1066,8 1153,10 @@ dependencies = [

[metadata]
"checksum alga 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d708cb68c7106ed1844de68f50f0157a7788c2909a6926fad5a87546ef6a4ff8"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b"
"checksum backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "88fb679bc9af8fa639198790a77f52d345fe13656c08b43afa9424c206b731c6"
"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"


@@ 1080,6 1169,7 @@ dependencies = [
"checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf79daa4e11e5def06e55306aa3601b87de6b5149671529318da048f67cdd77b"
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"


@@ 1133,6 1223,7 @@ dependencies = [
"checksum piet-direct2d 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ccea047f88a367ad86b2a972302070f0bf4183b51376ad840b9eb298f3bdafc1"
"checksum piet-web 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5f168f31a01eb3d0cc977258ae6b085f98d022f32b7e3edcdb4f565d912dcc60"
"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af"
"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097"
"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95"


@@ 1162,9 1253,13 @@ dependencies = [
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum structopt 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe8d3289b63ef2f196d89e7701f986583c0895e764b78f052a55b9b5d34d84a"
"checksum structopt-derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f3add731f5b4fb85931d362a3c92deb1ad7113649a8d51701fb257673705f122"
"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e"
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum unic-langid 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "33288471bc3e172fa79b2961474221b7d093b4f049e0408d65c898a6984a8497"


@@ 1172,8 1267,10 @@ dependencies = [
"checksum unic-langid-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "197eef46da6708b77f05bde40a2a10e5792676ef1012c4a1ca9d023a7fac4411"
"checksum unic-langid-macros-impl 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abb939907a0153c889d20f3ccc8eb38b54e21c018a0194a9a539114c0996322e"
"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "4de97fa1806bb1a99904216f6ac5e0c050dc4f8c676dc98775047c38e5c01b55"
"checksum wasm-bindgen-backend 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "5d82c170ef9f5b2c63ad4460dfcee93f3ec04a9a36a4cc20bc973c39e59ab8e3"

M Cargo.toml => Cargo.toml +2 -0
@@ 8,7 8,9 @@ edition = "2018"

[dependencies]
druid = {git = "https://github.com/xi-editor/druid", rev = "cfbde68ca16c67b20268a5999da469ed76999b82" }
kurbo = "0.5.1"
rbf-interp = "0.1.3"
nalgebra = "0.18"
structopt = "0.3.2"

glyphstool = { path = "glyphstool" }

M glyphstool/Cargo.toml => glyphstool/Cargo.toml +3 -0
@@ 7,6 7,9 @@ edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[[bin]]
name = "glyphstool"

[dependencies]
kurbo = "0.5.1"
plist_derive = { path = "plist_derive" }

M glyphstool/src/font.rs => glyphstool/src/font.rs +19 -0
@@ 15,6 15,7 @@ use crate::to_plist::ToPlist;
#[derive(Debug, FromPlist, ToPlist)]
pub struct Font {
    pub glyphs: Vec<Glyph>,
    pub font_master: Vec<FontMaster>,
    #[rest]
    pub other_stuff: HashMap<String, Plist>,
}


@@ 79,6 80,24 @@ pub struct GuideLine {
    pub position: Point,
}

#[derive(Debug, FromPlist, ToPlist)]
pub struct FontMaster {
    pub id: String,
    pub weight_value: i64,
}

impl Font {
    pub fn load(path: &std::path::Path) -> Result<Font, String> {
        let contents = std::fs::read_to_string(path).map_err(|e| format!("{:?}", e))?;
        let plist = Plist::parse(&contents).map_err(|e| format!("{:?}", e))?;
        Ok(FromPlist::from_plist(plist))
    }

    pub fn get_glyph(&self, glyphname: &str) -> Option<&Glyph> {
        self.glyphs.iter().find(|g| g.glyphname == glyphname)
    }
}

impl FromPlist for Node {
    fn from_plist(plist: Plist) -> Self {
        let mut spl = plist.as_str().unwrap().split(' ');

M glyphstool/src/main.rs => glyphstool/src/main.rs +1 -1
@@ 33,7 33,7 @@ fn main() {
    */
    let mut font: Font = FromPlist::from_plist(plist);
    //println!("{:?}", font);
    stretch::stretch(&mut font, 0.5, "051EFAE4-8BBE-4FBB-A016-4335C3E52F59");
    stretch(&mut font, 0.5, "051EFAE4-8BBE-4FBB-A016-4335C3E52F59");
    let plist = font.to_plist();
    println!("{}", plist.to_string());
}

M src/app_state.rs => src/app_state.rs +11 -2
@@ 58,9 58,9 @@ impl Data for Shared {
    }
}

#[derive(Clone)]
#[derive(Clone, Default)]
pub struct InterpPt {
    samples: Vec<InterpSample>,
    pub samples: Vec<InterpSample>,
}

/// This is data that's made available to individual master entries


@@ 205,6 205,15 @@ impl AppState {
            .iter()
            .any(|master| self.shared.width == master.width && self.shared.weight == master.weight)
    }

    pub fn add_weight(&mut self, weight: f64) {
        let master = Master { width: 0.0, weight };
        Arc::make_mut(&mut self.masters).push(master);
    }

    pub fn set_pts(&mut self, pts: Vec<InterpPt>) {
        *Arc::make_mut(&mut self.pts) = pts;
    }
}

impl InterpPt {

M src/interp_pane.rs => src/interp_pane.rs +2 -12
@@ 48,11 48,7 @@ impl Widget<AppState> for InterpPane {
            };
            let is_selected = data.sel == Some(i);
            let interp = pt.eval(width, weight, data.interp_type);
            let radius = if is_selected {
                6.0
            } else {
                5.0
            };
            let radius = if is_selected { 6.0 } else { 5.0 };
            let circle = Circle::new(interp, radius);
            paint_ctx.render_ctx.fill(circle, &fg_color);
        }


@@ 68,13 64,7 @@ impl Widget<AppState> for InterpPane {
        bc.constrain((100.0, 100.0))
    }

    fn event(
        &mut self,
        event: &Event,
        ctx: &mut EventCtx,
        data: &mut AppState,
        _env: &Env,
    ) {
    fn event(&mut self, event: &Event, ctx: &mut EventCtx, data: &mut AppState, _env: &Env) {
        let width = data.shared.width;
        let weight = data.shared.weight;
        match event {

M src/lens2.rs => src/lens2.rs +2 -9
@@ 20,8 20,7 @@ use std::marker::PhantomData;
use druid::kurbo::Size;

use druid::{
    BaseState, BoxConstraints, Data, Env, Event, EventCtx, LayoutCtx, PaintCtx, UpdateCtx,
    Widget,
    BaseState, BoxConstraints, Data, Env, Event, EventCtx, LayoutCtx, PaintCtx, UpdateCtx, Widget,
};

/// A lens is a datatype that gives access to a part of a larger


@@ 163,13 162,7 @@ where
        self.lens.get(data, |data| inner.layout(ctx, bc, data, env))
    }

    fn event(
        &mut self,
        event: &Event,
        ctx: &mut EventCtx,
        data: &mut T,
        env: &Env,
    ) {
    fn event(&mut self, event: &Event, ctx: &mut EventCtx, data: &mut T, env: &Env) {
        let inner = &mut self.inner;
        self.lens
            .with_mut(data, |data| inner.event(event, ctx, data, env));

M src/list.rs => src/list.rs +3 -9
@@ 5,8 5,8 @@ use std::sync::Arc;
use druid::kurbo::{Point, Rect, Size};

use druid::{
    BaseState, BoxConstraints, Data, Env, Event, EventCtx, LayoutCtx, PaintCtx, UpdateCtx,
    Widget, WidgetPod,
    BaseState, BoxConstraints, Data, Env, Event, EventCtx, LayoutCtx, PaintCtx, UpdateCtx, Widget,
    WidgetPod,
};

pub struct List<T: Data, F: FnMut() -> Box<dyn Widget<T>>> {


@@ 59,13 59,7 @@ impl<T: Data, F: FnMut() -> Box<dyn Widget<T>>> Widget<Arc<Vec<T>>> for List<T, 
        bc.constrain(Size::new(width, y))
    }

    fn event(
        &mut self,
        event: &Event,
        ctx: &mut EventCtx,
        data: &mut Arc<Vec<T>>,
        env: &Env,
    ) {
    fn event(&mut self, event: &Event, ctx: &mut EventCtx, data: &mut Arc<Vec<T>>, env: &Env) {
        let mut new_data = Vec::with_capacity(data.len());
        let mut any_changed = false;
        for (child, child_data) in self.children.iter_mut().zip(data.iter()) {

M src/main.rs => src/main.rs +75 -2
@@ 1,13 1,40 @@
use std::collections::HashMap;
use std::path::PathBuf;

use kurbo::Affine;

use druid::widget::{Button, Column, DynLabel, Padding, RadioGroup, Row, Scroll, Slider};
use druid::{AppLauncher, LensWrap, LocalizedString, Widget, WindowDesc};

use structopt::StructOpt;

#[derive(Debug, StructOpt)]
enum Cmd {
    /// Show a blank window, add points manually.
    Blank,
    /// Load a glyph from a font.
    Glyph(GlyphCmd),
}

#[derive(Debug, StructOpt)]
struct GlyphCmd {
    /// A font file in Glyphs format.
    #[structopt(parse(from_os_str))]
    input: PathBuf,

    /// The name of the glyph to read.
    glyph: String,
}

mod app_state;
mod interp_pane;
mod lens2;
mod list;
mod master;

use app_state::{lenses, AppState, InterpPt, InterpType};
use glyphstool::Font;

use app_state::{lenses, AppState, InterpPt, InterpSample, InterpType};
use interp_pane::InterpPane;
use lens2::{Lens2Wrap, Pair};
use list::List;


@@ 58,8 85,54 @@ fn build_ui() -> impl Widget<AppState> {
    row
}

fn set_app_state_for_glyph(app_state: &mut AppState, font: &Font, glyphname: &str) {
    let a = Affine::new([0.5, 0.0, 0.0, -0.5, 0.0, 500.0]);
    let mut weight_map = HashMap::new();
    for master in &font.font_master {
        let weight = (master.weight_value - 200) as f64 / 700.0;
        weight_map.insert(master.id.clone(), weight);
        app_state.add_weight(weight);
    }
    if let Some(glyph) = font.get_glyph(glyphname) {
        let mut pts = Vec::new();
        for layer in &glyph.layers {
            if let Some(&weight) = weight_map.get(&layer.layer_id) {
                let mut i = 0;
                for p in layer.paths.as_ref().unwrap() {
                    for n in &p.nodes {
                        if i == pts.len() {
                            pts.push(InterpPt::default());
                        }
                        let sample = InterpSample {
                            pt: a * n.pt,
                            weight,
                            width: 0.0,
                        };
                        pts[i].samples.push(sample);
                        i += 1;
                    }
                }
            }
        }
        app_state.set_pts(pts);
    }
}

fn main() {
    let app_state = AppState::default();
    let cmd = Cmd::from_args();

    let mut app_state = AppState::default();
    match cmd {
        Cmd::Glyph(g) => {
            println!("loading glyph {} from file {:?}", g.glyph, g.input);
            let font = Font::load(&g.input).unwrap();
            set_app_state_for_glyph(&mut app_state, &font, &g.glyph);
            println!("masters: {:?}", font.font_master);
        }
        Cmd::Blank => {
            println!("blank app");
        }
    }
    let title = LocalizedString::new("Interpolation toy");
    let window = WindowDesc::new(build_ui).title(title);
    AppLauncher::with_window(window)

M src/master.rs => src/master.rs +3 -9
@@ 3,8 3,8 @@
use druid::kurbo::{Point, Rect, Size};

use druid::{
    BaseState, BoxConstraints, BoxedWidget, Env, Event, EventCtx, LayoutCtx, PaintCtx,
    UpdateCtx, Widget, WidgetPod,
    BaseState, BoxConstraints, BoxedWidget, Env, Event, EventCtx, LayoutCtx, PaintCtx, UpdateCtx,
    Widget, WidgetPod,
};

use druid::widget::{DynLabel, Padding};


@@ 54,13 54,7 @@ impl Widget<(Shared, Master)> for MasterItem {
        size
    }

    fn event(
        &mut self,
        event: &Event,
        ctx: &mut EventCtx,
        data: &mut (Shared, Master),
        env: &Env,
    ) {
    fn event(&mut self, event: &Event, ctx: &mut EventCtx, data: &mut (Shared, Master), env: &Env) {
        match event {
            Event::MouseDown(_) => {
                data.0.weight = data.1.weight;