Introducing bitlib-rs for Rust and Cairo

This article builds off my previous article, Intro to Cairo Graphics in Rust. In that, I briefly described how to install Rust and the Cairo graphics library and set up a Rust project using the cairo-rs bindings. With that article, and a bit of dedicated research on your own, you should have been able to start coding some drawings using the Rust programming language. In this article, I’m going to build on what I described there, and introduce my own library, bitlib-rs, that adds a bunch of new functionality on top of Cairo.

I used to do a lot of work in Flash. ActionScript. RIP. I had, at various times, built up libraries of additional drawing routines that made it easier to draw complex shapes, manipulate colors, etc. But for some reason I never got very organized with it back then.

Eventually, I switched over to JavaScript and started using Canvas to draw stuff. By that time, github was a thing, and I started creating libraries that actually stuck around. This culminated in my own bitlib JavaScript library that I personally used all the time. It’s got all kinds of advanced drawing routines, animation stuff, a bunch of math and geometry functions, a pseudo random number generator, and hard core color manipulation tools.

When I started working with Rust and Cairo, I wanted all that functionality to come over with me. So I got to work porting bitlib to bitlib-rs. This was a great way for me to learn Rust itself. 800-something lines of code I knew inside out, that had to be recreated in a totally different paradigm. With the added verbosity of the new language, pulling some other stuff in from some of my earlier JS libraries, and riffing on existing code with new functionality, I’m up to over 1,400 lines of Rust. It’s still very much a work in progress, and as of this writing, should be considered to be in a pre-alpha state. Functions might be broken. APIs might change. More stuff needs to be tested and documented. But there’s some good stuff in there.

Let’s start by adding bitlib-rs to a new project. Use cargo new to create a project. In the dependencies, add:

[dependencies]
bitlib = { git = "https://github.com/bit101/bitlib-rs.git" }

Normally, dependencies are added with a version number when they are registered with the crates dependency system. Since bitlib-rs is not there yet, you can just add it with the git url. Alternately, you could check out the project and add it via a path:

[dependencies]
bitlib = { path = "path/to/bitlib-rs" }

I use this method while I’m working on the library and want to see the latest changes in a test project.

Now, in your main.rs, add the following line at the top of the file:

extern crate bitlib;

Now you’re ready to use the various structs and methods in your code. But first, let’s get an idea of how bitlib-rs can make using Cairo easier. Let’s make a bare-bones application that draws a bunch of randomly sized, positioned and colored circles and saves it as a png.

extern crate cairo;
extern crate rand;

use cairo::{ Context, ImageSurface, Format };
use std::fs::File;
use std::f64::consts::PI;
use rand::random;

fn main() {
    let surface = ImageSurface::create(Format::ARgb32, 600, 600)
        .expect("couldn't create a surface, yo");
    let context = Context::new(&surface);    

    for _i in 0..1000 {
        let x = random::<f64>() * 600.0;
        let y = random::<f64>() * 600.0;
        let r = rand::random::<f64>() * 45.0 + 5.0;

        context.set_source_rgb(random::<f64>(),
                               random::<f64>(),
                               random::<f64>());
        context.arc(x, y, r, 0.0, PI * 2.0);
        context.fill();
    }

    let mut file = File::create("output.png").unwrap();
    surface.write_to_png(&mut file)
        .expect("Couldn't write to png");
}

It’s not too bad, but there are some points there that seem a bit painful to me to have to do over and over.

  • Creating the surface and context is wordy.
  • The random syntax is painful to do anything interesting with.
  • The color definition method is inadequate.
  • Shape definitions lacking.
  • Saving to png is wordy.

To contrast, here is the exact same program written using bitlib-rs:

extern crate bitlib;

use bitlib::canvas::{ Canvas, BitContext };
use bitlib::color::Color;
use bitlib::random::Random;
use bitlib::file::open;

fn main() {
    let canvas = Canvas::create(600.0, 600.0);
    let context = canvas.get_context();
    let mut rand = Random::new();

    for _i in 0..1000 {
        let x = rand.float(0.0, 600.0);
        let y = rand.float(0.0, 600.0);
        let r = rand.float(5.0, 50.0);
        context.set_source_color(&Color::random_rgb());
        context.fill_circle(x, y, r);
    }
    canvas.write("output.png");
    open("output.png");
}

Let’s go through it step by step. First, the creation of the surface and context. I always want to create both of these, in the exact same way. They are a pair. So I created a Canvas struct that encapsulates them. This now goes from:

let surface = ImageSurface::create(Format::ARgb32, 600, 600)
    .expect("couldn't create a surface, yo");
let context = Context::new(&surface);

to this:

let canvas = Canvas::create(600.0, 600.0);
let context = canvas.get_context();

You can count characters typed if you want. But for me, it’s just a lot less boilerplate to keep in my head. Canvas::create and get_context. Simple.

Next, the random syntax. The rand crate is very powerful, but can be a bit complex to use, especially if you want a seeded pseudo random number generator (PRNG). Using the simplest (non-seeded) version, you get this:

let x = random::<f64>() * 600.0;
let y = random::<f64>() * 600.0;
let r = random::<f64>() * 45.0 + 5.0;

I don’t really love having to specify the data type in angle brackets and doing the math to generate a range. So I encapsulated rand’s more complex PRNG functionality into bitlib::random::Random. You have to create the PRNG, and then you have various methods to get int ranges, float ranges, bools, etc.

let mut rand = Random::new();

and then…

let x = rand.float(0.0, 600.0);
let y = rand.float(0.0, 600.0);
let r = rand.float(5.0, 50.0);

Doesn’t save a whole lot of typing, but again, it’s much easier on the brain. At least on my brain.

Then there’s color management. Cairo-rs has two methods for setting color:

context.set_source_rgb(r, g, b);
context.set_source_rgba(r, g, b, a);

In these, each value is a normalized value (0.0 to 1.0). For those of us who are used to 0-255 integers and hex values for color, this can be hard to think with. So a large portion of bitlib-rs is devoted to powerful color methods. You create an instance of the Color struct with various methods such as:

Color::rgb(r, g, b);                 // values from 0.0 to 1.0
Color::rgba(r, g, b, a);             // values from 0.0 to 1.0
Color::rgb_int(r, g, b);             // values from 0 to 255
Color::rgba_int(r, g, b, a);         // values from 0 to 255
Color::from_int(0xffcc9966);         // single integer argb.
Color::from_string("#ffcc99");       // rgb with 100% opacity
Color::from_string("#80ffcc99");     // argb
Color::from_string("palevioletred"); // standard css color names
Color::grey(shade);                  // 0.0 to 1.0 shade
Color::grey_int(shade);              // 0 to 255 shade
Color::hsv(h, s, v);                 // h = 0.0 to 360.0. s, v = 0.0 to 1.0

Then the random color methods:

Color::random_rgb();                // what it sounds like
Color::random_grey();               // also what it sounds like
Color::random_grey_range(min, max); // min and max both 0.0 to 1.0
Color::random_hsv(hmin, hmax, smin, smax, vmin, vmax); // you get the idea

Finally, some hard-coded colors for black, white, red, green, blue, yellow, cyan, magenta:

Color::black();
Color::red(); // etc.

So, our randomly colored circles go from:

context.set_source_rgb(random::<f64>(),
                       random::<f64>(),
                       random::<f64>());

to:

context.set_source_color(&Color::random_rgb());

Two things to note here. One is that there’s a new method on context, set_source_color. I’ll get into how that happened in a moment. Also, this method takes a reference. So it’s &Color instead of just Color. This lets the context borrow colors rather than move them, so you can reuse a single color multiple times. It’s a Rust thing you need to understand early on.

Now, about that context. It’s got some drawing methods, sure. But they are pretty minimal. That’s fine. I’m a big fan of APIs being minimal but extendable. There are a lot of things I want to draw that are not simply lines, arcs, rectangles or bezier curves. But they can all be composed from those things.

One of the brilliant pieces of Rust is its trait system. You can think of a trait as an interface… kind of. It defines methods that should be on a struct that implements that trait. Just like an interface defines methods that should be on a class that implements that interface. But Rust allows you to implement the trait methods on other structs. Even structs you don’t own, like cairo::Context. With that, I was able to extend Context with a whole boatload of new methods that are indistinguishable from native methods. All you have to do is tell Rust that you want to use that trait. My trait is called BitContext, so you just have to say:

use bitlib::canvas::BitContext;

at the top of the file and you’re all set. This is why we now magically have a new method called context.set_source_color, when Context itself only has set_source_rgb and knows nothing at all about my custom Color module. I’ve also added a ton of custom shapes, so instead of using arc and fill:

context.arc(x, y, r, 0.0, PI * 2.0);
context.fill();

I can now just draw a filled circle:

context.fill_circle(x, y, r);

The BitContext trait has all kinds of other drawing methods on it. Methods to draw ellipses, rounded rectangles, various types of curves and paths, polygons, stars, heart shapes, grids, etc. They each have a simple version that creates a path, and fill as well as stroke variants where appropriate.

Finally, we get to the point of saving the drawing as a png. Normally, you need to create a file and set up error handling, and use that file in the surface.write_to_png method, again with more error handling.

let mut file = File::create("output.png").unwrap();
surface.write_to_png(&mut file)
    .expect("Couldn't write to png");

But with the Canvas struct, you can just call write, with the path.

canvas.write("output.png");
open("output.png");

Also notice the final line, which is a call to bitlib::file::open. This will open the file in whatever application is registered to open that kind of file. As of this writing, this is set up to work on Linux and MacOS. It’s a nice added touch that lets you create and display the image just by running the program.

In addition to all that, there are geometry and math modules that have a bunch of other useful functions in them. One thing to note is that almost all the methods in those modules work exclusively with f64 values – 64-bit floating point numbers. Many of them could be made generic, but because cairo-rs‘s drawing methods all take f64s, I decided to keep these methods using the same data type. That may change in the future.

You may have noticed that I kind of skimped on the error handling. In various places where errors need to be handled, I did the bare minimum of expect or unwrap, which will work fine when things work fine, but will crash the program (with a hopefully useful error message) if you, say, try to use a file you don’t have access to. For my purposes – writing programs that generate images – this is totally fine. To make it more robust, I’d probably want to pass those possible error conditions to the caller of the functions that are currently squashing those errors. That would make the whole system more complex to use and defeat the purposes of a lot of the shortcut methods I’ve created. If you plan on doing something more sensitive – writing an app that others are going to depend on, you’d want to not use these shortcuts, and actually handle the errors appropriately.

To recap, this whole library is in its very early stages. But I know that a lot of the people who follow me may be interested in learning something new like Rust and Cairo and if this code were to give someone a bit of a boost, and some sample code to get started, that would be great.

My Resolution Guidelines

So here’s the obligatory New Year’s Resolution post. I’m not going to tell you what my resolutions are, or what yours should be, but I have been mulling over some guiding principles for quite a while. These aren’t resolutions, per se. But they are guideposts I try to keep in mind personally when thinking about my resolutions, or in fact, whenever I’m taking any action.

So here you go, my four principles. These are all in the form of “X is greater than Y”. In each case, this does not mean that X is holy and Y is evil. It just means that when all else is equal, I would prefer to give preference to X over Y.

1. Creation is greater than Consumption.

If I have a chance to create something versus consume something that someone else has created, I like to focus on creating. Whether this means writing a blog post or tutorial, making a video, publishing some open source experiments, building an app or game, going down into the shop and doing some wood or metal working or even doing some home improvements, creating something either for myself or for someone else will always be priority for me.

This doesn’t mean that consumption is bad. Nothing wrong with some Netflix and chill. I do some casual gaming on Steam, etc. and I’m even thinking of getting a more decent gaming rig this year to try a few more serious games. But personally, I need to keep in mind that games and popular media can be traps.

Yeah, sometimes I find myself at the end of an evening, having done nothing more than surfing imgur, reddit, YouTube and my RSS feed all night. It doesn’t feel very good. Other nights, I pull myself away from the computer after working on some long post or open source library all evening, with my head full of plans on where to go with it next. The latter is far more fulfilling. To me. Personally.

2. Enlightenment is greater than Entertainment.

Whenever I create something that has nothing but entertainment value, I feel empty. I have a side site called Art From Code where I just post algorithmically generated images and occasionally animations. Every once in a while, I get back into it for a little bit. But it never lasts very long because it’s just me saying, “Look at this cool thing I made.” And maybe some other people come along and say, “Hey, I like that cool thing you made.” And it ends there. That’s really boring for me.

I guess that’s why artists like to go on and on about their visions and inspirations for various pieces. I’m convinced that a lot of that stuff is dreamed up after the pieces are complete, but I understand the sentiment to explain what’s behind a particular work. That’s why I prefer to do stuff with open source. Even with computer-generated art, I like to share the code that created the image. It’s not some pseudo-intellectual artist’s statement about a dream I had, it’s literally what I did that brought that image about.

Hopefully, by sharing that, someone else will have some similar idea pop into their head and they can go riff on it and do some creation of their own.

Of course, I often go further than just sharing the code, and wind up writing tutorials or books or doing videos or talks on how I did things. And nothing beats the feeling of someone emailing to thank me for some bit of info I passed on, with a link to some project they were able to do because of that. It always makes my day.

3. Advice is greater than Authority.

So many articles and tutorials are designed, I think, not so much to teach, but to build up the egos of the authors. You know the ones I’m talking about:

“Everything you know about ____ is wrong!”

“The right way to ____.”

“10 things you should be doing in ____.”

“You’re doing ____ all wrong.”

A lot of these are outright clickbait, designed to create controversy. Others are from people who have learned some stuff about some stuff and have taken it upon themselves to instruct the world on the right way to do that stuff. Apparently, by speaking like an authority, you become an authority. At least in your own mind. And often in the minds of those coming newly to a subject.

I’m not perfect, but I intentionally try to avoid such a tone whenever I’m writing an article or tutorial. I actually do word searches for words like “should” before publishing an article. It’s a word that often indicates that I’ve slipped into authoritarian mode. I’m not saying I forbid the use of the word in my writing, I just look extra close when I do find myself using it.

Now, obviously, there are times when you are explaining some process to an audience and there is a common pitfall you want to warn them about. Say there’s a situation where strategy A is going to cause them a big headache and strategy B is a much better solution. You could write:

“Don’t use strategy A! It’s wrong. Strategy B is the right way to do this.”

But now you’ve just stuck the reader with a fixed idea that strategy A is bad and strategy B is good, with no real understanding of why. They’ll probably go off and repeat this to others, with just as much authority. And just as little explanation. Alternately, you might want to write:

“You could use strategy A here, but if you do that, here’s what you’re going to run into… [explain the pitfalls] Instead, you might want to look at strategy B, which has these advantages in this situation… [explain the benefits]”

There are no stone tablets with right and wrong coding practices written on them. Or design practices, or really any other practices in any field. There are different ways of doing just about anything that can be done. Each of those ways will have its benefits and its disadvantages. What we call the “right” way is usually one of the ways where the benefits greatly outweigh the disadvantages. Rather than just dictating “right and wrong”, why not explain the details and let them decide? It’s more work, but I find it much more valuable.

4. Commendation is greater than Condemnation.

Everything I’ve talked about so far has mostly to do with things you create yourself. This last one has more to do with responding to things others are doing or have created.

Another easy way to stroke one’s own ego is to put down something that someone else has done. Apparently, some people feel that if they are able to criticize something, they must be better than that thing they are criticizing. They are able to see the flaws in the product that the author could not see. So we get movie and book reviewers who have never written anything other than movie and book reviews. Software and hardware reviewers who have never built anything real or virtual. And of course, political experts who have never been in charge of anything other than their own life (and have often failed miserably at that).

If you use some software or hardware that has a bug, it’s way too easy to write some scathing review about how the developers are a bunch of idiots. You feel justified. I used to do this all the time. I’m trying to get out of that. I’ve actually found that directly communicating to the developer or company and explaining the issue usually works far better. Not always, but often enough to be a much better first attempt. If I do wind up posting a bad review about anything, I try really hard to not let my emotions get too involved. And I try to remember that there are real people behind the product – developers or creators like me, who are not perfect, but generally aren’t idiots.

Along with this, I’ve made a real effort to commend those things I really like. If I use some software or device or service that I like, I’ll tweet about it, tell people about it, leave a positive review about it. Usually we are only driven to give feedback when something goes wrong and we get pissed off. If something just works the way we expected it to, we go on our happy way without another thought. So I’ve been trying to go back through my purchase histories now and then and do positive reviews for all the things I bought. Particularly for smaller companies, individuals, eBay sellers, etc., whose livelihood depends on positive word of mouth.

I’ll even sometimes send a personal note to the seller/creator if I particularly liked something I bought or used. I know the effect this has because people often do the same for my books, videos, tutorials, etc. and it always puts me in a good mood when I get one of those notes.

Rewarding positive behavior can be just as powerful as punishing bad. Sometimes a bit of both is needed. But if I had to focus on one, it would be the former.

Summary

There is a lot of negativity in the world. It’s tempting to fight back at bad things with more negativity. But if we do that we just have negative on top of negative. Someone somewhere needs to do something positive once in a while. All of the above are focused on adding some positivity back into the world, lifting others up in the hopes that they’ll do the same for me now and then.

Have a great new year!

2017 in Review

It’s that time of year when we look back to see how things have gone in the last year, what we accomplished, how well we stuck to our goals, any major changes – good or bad, and start making plans for the next year. All arbitrarily based on a calendar system someone made up centuries ago, but so be it. If there’s no natural origin point, make one up.

2017 was a year of massive change for me. I changed companies once and changed jobs twice. And to a large degree, I actually changed careers once. I abandoned one coding platform, ramped up on another one and started learning an entirely new one.

My Job and Career

When the year started, I was working at a company called Dreamsocket, doing mostly Android work, with some web work and helping out now and then on iOS. I’d been there nearly three years and learned a whole lot. It’s a small company that does way more work than you would imagine possible. Award-winning, high profile work. It was an honor to be part of a lot of those projects. But I was feeling the urge to move on. It was just a feeling. I hadn’t gotten to the point of actually looking for another job. But then Steff, a friend and former coworker at two different companies reached out and asked if I’d be interested in coming to have a chat where he was working.

The company was Notarize. They do on-line notarizations. Not too exciting, I thought. But sure, worth a chat. As it turned out, I wound up being impressed enough with the people and technology that I wound up accepting an offer and became part of the web team. It’s all React, with Relay and GraphQL. Rails backend. In other words, a whole bunch of technology I knew almost nothing about. The first couple of months were a struggle. Although I came on as a senior engineer, I felt like a total noob. But I eventually found my feet and got productive and feel like I’ve been doing pretty well in terms of helping shape the team’s best practices, improving processes, improving the build, etc.

The company has been growing fast. There were 6 developers before me. Now there are close to 30. A month or so after I started there, Steff became the Engineering Manager. As we continued to grow, we needed additional managers. In just about every company I’ve worked for in my career as a developer, I’ve had some kind of manager role offered to me. I’ve never been interested. I just wanted to code. At Notarize, it was different. I really liked the way Steff was defining the role. It aligned with what I really wanted to do – help other developers be successful. So I volunteered. It’s very different. Much less coding, but I’m really enjoying getting to know all the engineers more and helping align what they want to do with what the company needs to get done. I have 8 developers I’m working with. Soon to be more. Working with Steff has been great. We see most things eye to eye and have a lot of agreement on where we should be headed. So that’s my job and the start of my budding new career.

Personal Projects

In the last few years, I’ve done a lot of physical making of stuff. Woodworking, knife making, leather work, blacksmithing. It’s been great, but it’s taken a back seat this year. Mostly due to the new job, which has required learning a whole lot of new stuff. There’s also the commute factor. For the previous four years, I was working at home. At the end of the day, I’d just pop downstairs into the shop and do an hour’s work before dinner. Or even get something done in the morning before work. I’m starting to feel the urge to build something these days though. I’m planning to at least get down into the workshop and do some cleaning up and organizing before New Years, and hopefully get a few projects done in the coming year.

As for personal coding projects, at the beginning of 2017, I started a new BIT-101 Lab. This was kind of a revival of my earliest BIT-101 Flash-based experiments lab. I had hoped to continue the experiment-a-day for the full year, but the new job did impact that. I’d be coming home and learning about React and Relay and Ruby and Rails. I had a backlog of daily pieces which acted as a buffer for a while, but when those ran out, I didn’t have the time to continue doing more.

Eventually, as I stabilized in the new job, I started being a bit more relaxed after work and had the urge to learn something new. I’ve been coding graphics and animation in JavaScript and Canvas for years. I really felt it was time to learn a new language though. Two that I was really interested in were Rust and Go. I somewhat randomly chose Rust, and for the last couple of months, that has been consuming me. It at once feels very familiar, but is also so fundamentally different than any other language I’ve worked in. It’s been a real challenge, but not in any overwhelming sense. I’ve been able to get productive in Rust while I continue to learn its weird nuances. I’ve been porting over a lot of my JavaScript graphics libraries. I’ve discovered that porting code you are really familiar with is a great way to learn a new language. You know exactly what you are trying to do. You just need to know how to express that in the new language’s constructs. I’ve already published one article on what I’m doing, and have plans for more to come.

I haven’t gone deep into animation with Rust. I’ve been using Cairo graphics, which really just generates image files which I save to disk. I have got a setup going where I can very easily generate an image sequence and convert it into an animated gif. Eventually, I want to explore the Piston game engine. More for its interactive animation capabilities than actually creating games. But who knows where that will go.

Personal Life

Not a whole lot to report here. I’m a year older than I was last year, slowly working my way through my sixth decade on this planet. (No, that doesn’t mean I’m in my 60s. Do the math!) There’s a lot to be said for getting older though. As your own mortality becomes more real to you, a lot of BS falls away. A lot of things you used to fret over now seem silly. You start to focus on what’s really important. And you realize that what is important is an individual thing that nobody can define for you, and you can’t define for anyone else.

I guess I’ll just end on that existentially inspirational note. I’m honestly excited for what 2018 will bring!

Intro to Cairo Graphics in Rust

In the past few weeks, I’ve been itching to learn some new stuff. Those who know me even just a little bit know that “new stuff” is generally going include “new ways of creating graphics and/or animations”. And so it does this time.

I’ve been creating graphics in HTML5 Canvas for quite a few years now, and that’s cool. But there are a few pain points with its workflow:

1. It sometimes seems silly to pipe everything through the browser all the time. I’d like to just be able to run a program and have it create a file and display that file.

2. Running in the browser via the file system introduces various security issues, so you need to run some kind of local server, and even then you run into issues with saving files to disk automatically, so you need to right click and save or set up some kind of button to save an image.

3. At work, I’m using React with Webpack and Babel, so I get to use the latest and greatest ECMAScript with classes and all the other syntactic sugar. It’s really nice, but setting all of that up is not trivial. For a one-time large project, it’s not a huge deal to spend some time on creating all that config. But if you’re going to be doing random experiments all the time, it’s a ton of overhead. I get stuck with whatever the current browsers implement.

So I’ve been looking for some other language / drawing api I could learn.

After a short amount of searching, I came across Cairo Graphics.

https://cairographics.org/

It’s a 2D graphics library, written in C, but has bindings for several other languages. Well, that sounds pretty cool. Looking over the tutorials and api documents (https://cairographics.org/manual/), I see that you create a surface, then get a context from that surface, then call various commands on the context such as move_to and line_to, and then follow up with stroke and/or fill. Well that sounds awfully familiar. In fact, I’m going to guess that HTML5’s Canvas is either backed up by Cairo at some level, or is at the very least inspired by Cairo’s api. At any rate, it sounded worth looking into.

I wasn’t about to dive into C programming, but as I mentioned, there are bindings for several other languages. The first I tried was Python, and that worked great. I’ll probably do another tutorial on pyCairo at some point, but I wanted to take it a little further and really dive into something new. I’ve had my eye on a couple of languages – Rust and Go. Both have Cairo bindings, so I flipped a coin and decided to try out Rust.

https://www.rust-lang.org/en-US/

Rust is a pretty interesting programming language. It’s built around speed and safety – preventing you from doing bad things. As such, it has some programming paradigms that seem really strange at first. But there’s a lot of logic behind those decisions. I’m not going to do a Rust tutorial here. But the documentation on how to learn the language is some of the best learning material I’ve seen on any site for any language or system.

Just start reading “The Book”:

https://doc.rust-lang.org/book/

I’m going through the Second edition, which is still listed as “under construction”, but I haven’t run into any flaws or incompleteness as of yet.

What I do want to cover in this tutorial is using Cairo in Rust. There’s a lot resources on how to use Cairo, lots of stuff on how to use Rust. But the center part of the Venn diagram is rather thin.

So, here’s what you need to do:

1. Install Rust and learn how to program in it. At least the basics. I had to read maybe 1/3 of “The Book” before I felt I was ready to start trying to pull in the Cairo bindings and create some graphics.

2. Install Cairo. This is the C library itself. It needs to be on your system so that the Rust bindings for Cairo have something to bind to.

https://cairographics.org/download/

I’m on Ubuntu, so this was really easy, just:

sudo apt install libcairo2-dev

On MacOS, it seems you’re supposed to use MacPorts, which I’m not really familiar with, or fink, which I’ve never heard of.

On Windows, it looks like you just have to add a few dlls to your path.

OK, we’ll carry on, assuming you got Cairo installed.

3. Create a project and set up the dependencies.

Again, this is not a Rust tutorial, but to create a Rust project, you can use cargo new.

cargo new cairo_stuff --bin

This creates a new project named cairo_stuff, which will be a binary executable, (bin) as opposed to a library project.

You’ll see a new folder with the project name. Inside that will be a src folder and a .toml file. It also sets up the project to use git by default, so you get a .git folder and .gitignore file. The .toml file is the project configuration file. It should look something like this:

[package]
name = "cairo_stuff"
version = "0.1.0"
authors = ["Your Name <you@domain.com>"]

[dependencies]

The authors data is taken from your .gitconfig file if you have one. We need to add our Cairo binding as dependencies for this project. To do that, we list them under dependencies. We’ll need two packages or “crates” as they are called in Rust.

We’ll need the png crate so we can save images, and the cairo-rs crate which contains the actual Cairo bindings. We also need to add png as a feature to cairo-rs, so that cairo-rs itself knows how to save pngs.

Whenever you’re doing dependency configuration in any language, it’s important to have a way to know what versions of different dependencies are available. In Rust, you can go to https://crates.io and search for the package you want to add, in this case, “png”.

The first match tells us that we want version 0.11.0.

And for cairo-rs, it’s 0.2.0.

Note, these will definitely and continuously change, so actually go to the site and check the numbers.

For png, we can just add a line in the dependencies section that says

[dependencies]
png = "0.11.0"

Simple.

But the cairo-rs line is a bit more complicated because we need to pass png into it as a feature. So we say

[dependencies]
png = "0.11.0"
cairo-rs = { version = "0.2.0", features = ["png"] }

Again, read “The Book” to fully understand all the syntax here. But this will get you up and running.

Now, if you look at the main source file in the project, it’s src/main.rs and it looks like this:

fn main() {
    println!("Hello, world!");
}

If you’ve done any kind of programming, all that should be pretty self-explanatory. You have a function called main. Rust follows the pattern of many other languages where main is the function that is called when the program is executed.

In main, we call println, passing a string. Other than the exclamation point there, it should be straightforward. (The ! indicates that println is implemented as a macro, not a function, but … whatever.)

At this point you can call cargo run from the main project directory. This will satisfy all your dependencies, build the executable, and run it. It should print out the message “Hello, world!”. Great! It probably took a while to download everything it needed. But if you run it again, it should complete almost instantly.

If you now look in your project folder, you’ll see you have a Cargo.lock file and a target folder. The target is where your final executable and all the build artifacts are. The lock file lists all the other dependencies that got pulled in when you added png and cairo-rs. For me, this file wound up at 171 lines, so there were quite a few other libraries it needed to pull down to satisfy those two that we added.

Let’s Draw Some Stuff

Now that we’ve set things up, let’s draw something.

Here are the basic steps:

1. Create an image surface.

2. Create a 2D drawing context that references that surface.

3. Draw things.

4. Create a file.

5. Write the surface to the file as a png.

For most of your projects, steps 1, 2, 4 and 5 are going to be boilerplate. The meat is going to be step 3 where you draw the actual content you want to draw.

First, we’re going to need to import the cairo-rs bindings. That’s an external crate that we downloaded in our dependencies. So up at the top of the file we say

extern crate cairo;

Note that although the crate name was cairo-rs, we just link to it as cairo.

We’ll be using three modules from the cairo library: ImageSurface, Format, and Context. We could access these like so:

cairo::ImageSurface
cairo::Format
cairo::Context

But repeating that leading cairo:: every time is unnecessary. Instead we can say:

use cairo::{ ImageSurface, Format, Context };

This would be equivalent to something like the following in the latest versions of JavaScript:

import { ImageSurface, Format, Context } from "cairo";

Now we can use those modules directly. Next, let’s make our surface. Delete the println line inside of main and add this instead:

let surface = ImageSurface::create(Format::ARgb32, 600, 600);

So ImageSurface has a method named create which gets a format, width and height and creates a new surface. The format will have four channels – a, r, g, b – each 32 bits.

But actually, this is not quite right as it stands. The ImageSurface::create method does not directly return a surface, it returns a result because this call may fail. Maybe you don’t have enough memory to make a surface the size that you requested for example. So you need to check the result to make sure that it’s valid before proceeding.

There are a few ways to handle that result and get at the surface. Rust provides a quick shortcut to let us do this in one step: just call expect, passing in a message string. If the call succeeds, it will pass through the newly created surface. If it fails, the program will crash, displaying your message.

let surface = ImageSurface::create(Format::ARgb32, 600, 600)
    .expect("Couldn't create a surface!");

Now, obviously, this is not great error handling for a program you’re going to release into the world, but it’s good enough for a first pass of something you’re testing out.

Now we create a context based on this surface, assuming it gets created.

let context = Context::new(&surface);

Context has a new method which takes a reference to a surface, hence the ampersand. (Read “The Book”!)

Now we have a context to draw stuff on! Let’s start by painting it red.

context.set_source_rgb(1.0, 0.0, 0.0);
context.paint();

set_source_rgb takes three normalized floating point values. paint fills the context with the current source value.

Where is My Image?

So how do we see this thing? The program we are creating has no UI. It just runs on the command line. We can’t just display the image in a window, because we have no window. We can save it to a file though.

First we need to create a file object. That would be std::fs::File. We can use use up at the top to shorten that in our code.

use std::fs::File;

After the context.paint() line, create the file:

let mut file = File::create("output.png")
    .expect("Couldn't create file.");

The mut there means this is a mutable variable. It can be changed. By default, variables are immutable in Rust. Our next line will require a mutable reference though, so we make file mutable. Again, this call may fail, so we tack on expect with a message string so that we get a file not a result, and we’ll crash if this fails.

Now we can write the surface as a png to this file:

surface.write_to_png(&mut file)
    .expect("Couldn't write to png");

The write_to_png method needs a mutable reference to a file object. &mut file is how we specify that (see “The Book”). And once again, we check the result.

And that’s that. Here’s the whole program:

extern crate cairo;
use cairo::{ ImageSurface, Format, Context };
use std::fs::File;

fn main() {
    let surface = ImageSurface::create(Format::ARgb32, 600, 600)
        .expect("Couldn't create surface");
    let context = Context::new(&surface);
    context.set_source_rgb(1.0, 0.0, 0.0);
    context.paint();
    let mut file = File::create("output.png")
        .expect("Couldn't create file");
    surface.write_to_png(&mut file)
        .expect("Couldn't write to png");
}

When you run that, you should wind up with a file called ouput.png in the main project directory. It should be a 600×600 red square.

Wait, That’s Not Drawing!

OK, OK, filling a png with a single color is not really drawing. Let’s get a taste of the drawing api itself. I’m just going to throw the whole file at you and let you figure it out.

extern crate cairo;
extern crate rand;

use cairo::{ ImageSurface, Format, Context };
use std::fs::File;

fn main() {
    let surface = ImageSurface::create(Format::ARgb32, 600, 600)
        .expect("Couldn't create surface");
    let context = Context::new(&surface);

    // paint canvas white
    context.set_source_rgb(1.0, 1.0, 1.0);
    context.paint();

    // draw 100 random black lines
    context.set_source_rgb(0.0, 0.0, 0.0);
    for _i in 0..100 {
        let x = rand::random::<f64>() * 600.0;
        let y = rand::random::<f64>() * 600.0;
        context.line_to(x, y);
    }
    context.stroke();

    let mut file = File::create("output.png")
        .expect("Couldn't create file");
    surface.write_to_png(&mut file)
        .expect("Couldn't write to png");
}

Again, the top and bottom of this file is mostly boilerplate. After we create the surface and context, we paint the surface white this time, and use a for loop to draw 100 lines. This is done with context.line_to.

Note that we’re using a random number generator here. That’s another crate. Up top I’ve imported that with extern crate rand; I’ll leave it up to you to search https://crates.io to find the current version and add it to your .toml file.

Now the random functionality gets a bit wordy here, with specifying the type each time (f64 = 64-bit floating point number). But you’re probably going to want to create your own random range function anyway, so you can say random(min, max) and get a result in that range. When you do that, you can just abstract the actual random call within that function.

What Next?

I’ve already said it enough, but read “The Book” if you want to learn more about Rust. It’s really that good.

In terms of cairo-rs, all the api docs are here: http://gtk-rs.org/docs/cairo/

And all the actual drawing commands are on the context object here: http://gtk-rs.org/docs/cairo/

A lot of those will look really familiar if you’ve been working in HTML5 Canvas. move_to, line_to, curve_to, arc, rectangle, etc.

And once you’re familiar with Rust and cairo-rs, you should be able to go to any C-specific Cairo documentation and figure out how that can be translated over to Rust.

One point I want to address briefly is that I said in the beginning that setting up a Webpack/Babel project in order to use the latest and greatest JavaScript features is cumbersome. After reading this article, you might be thinking that setting up a Rust project is just as cumbersome, maybe more so.

But it’s not really. Installing Rust and Cairo itself may have taken a bit, but those are one time actions. Once they’re on your system, you’re done. From there, a new project is as simple as running cargo new and adding two lines for the dependencies. For the source file, you can create some kind of snippet or template for all that boilerplate stuff and you’re off to the races, writing drawing commands in under a minute.

Anyway, hopefully this starts you on some kind of journey of learning something new.

Flow Fields, Part II

In Flow Fields, Part I, we covered what a flow field is and looked at a few different formulas to create them. And we rendered flow fields in a various ways. We even animated particles being influenced by fields. In this article we’ll cover a couple more ways to generate flow fields and some new ways to render them. As I said in the first part, the possibilities are endless. I’m just pointing you in a few directions to get started.

Perlin Noise

Using simple math and minimal trigonometry gave us some pretty interesting patterns, but they wound up being very regular and repeating. The more complex function we used (the strange attractor) made for a fairly uninteresting field by itself, but was beautiful with particles tracing lines across it.

What would be nice is something complex but non-repeating. Perlin noise fits the bill, which is why it is used so often to create flow fields. Perlin noise was invented by Ken Perlin and was initially used to generate natural looking textures for computer generated special effects in movies and video games. It gives you random values across a two- or three-dimensional field, and ensures that there is a nice, smooth gradient between the various values. With different settings, scaling and colors applied, you can get textures that look like smoke, fire, liquid, wood grain, rusty metal, etc.

We can tap into Perlin noise to create a flow field that varies all over the place and never repeats. And we can animate it as well by creating a 3D Perlin noise field and moving through slices of it on the z-axis. More on that soon.

If you’re using Processing or some other platform, you may have a Perlin noise function built in. If you’re just using plain vanilla JavaScript like me, however, you’ll need a Perlin noise library to generate the values. There are a few out there. I’m going to use one by Seph Gentle (josephg on github) at https://github.com/josephg/noisejs. I’ve downloaded that into my project folder.

I’m going to start with the same basic HTML file as last time, and add the perlin.js library in the script tag.

And here’s the first script file:

The first block is the same as before. Then we seed the Perlin noise library with a random number so we’ll get a new image each time, and call render.

The render function loops through the canvas in a grid-like fashion as before, getting a value and drawing a line there. All pretty much the same as last time.

It’s the getValue function that changes. Now we’re going to get the value directly from the Perlin noise function. This noise library has a few different functions. We’ll use the 2d Perlin noise function, perlin2, for now. This just takes an x and a y. We’ll scale it down somewhat to make a more interesting pattern. The result of this is a number from -1 to +1. So we can multiply that by 2 PI to get a direction in radians. That’s all, folks. And here’s what it gives us:

Pretty cool, eh? Let’s change the res variable to 2. This makes a much tighter grid:

And now we can see what happens if we change the scale, to maybe 0.004.

It’s like zooming in.

Now, consider 3d Perlin noise as a stack of these 2d Perlin flow fields layered on top of each other, each one varying just a bit. If we could flip through them, one by one, we could see them animating. That’s exactly what our next file does, using the noise.perlin3 function:

Here, we add a z variable set to zero. Then we clear the canvas at the start of render so we can redraw each time. Finally, we increase z by a very small amount and call requestAnimationFrame(render) to set up the next frame of the animation.

The getValue function calls noise.perlin3, passing in the current z. No other changes. A still image would look about the same as the first image in this article, but if you actually run this one, you’ll see a lovely, flowing animation, reminiscent of seaweed, or amber waves of grain.

OK, what’s next? Well, last time we moved on to having the flow field influence the movement of some particles. We’ll do the same thing here, using the Perlin-based flow field.

Again, we create a column of particles on the left edge of the screen, and on each frame, update each particle’s position and draw a line from its last position to where it currently is. This gives us a trail of its movement. The major change here is, again, that we’re using Perlin noise to calculate the flow field. Here’s what we get:

And of course, this looks even cooler as you watch it animate and build up.

One last Perlin example. We’ll use 3d Perlin noise again. This time, on each frame, we’ll create a column of particles down the center of the canvas and iterate each one’s path 500 times. That will create a bunch of flowing lines. Then we’ll update z and draw the next frame. Now, the path of each particle is altered a bit differently on each frame, so you get an eerie, undulating flow going on. The further out from their source each particle gets, the more its path differs from the last frame. Sometimes it jumps off in a totally different direction, giving it a weird, glitchy feeling. The code:

And a single frame of the animation, which you’ll want to see in motion:

What else?

Well, we’ve created flow fields with simple and complex formulas and used third party libraries to create them. You might want to play with the simplex noise contained in that noise library we were using. It’s similar to Perlin noise, also created by Ken Perlin, but has a bit of a different feel to it.

But really we can use anything we want to create a flow field. All we need is something that maps an x, y coordinate to a value. So where could we get a source of values that are mapped to x, y coordinates? Like a map of different… bits of information… like a bit… map. OK, I guess you see where I’m going here. So yeah, any image is simply a 2d map of values. If we can take an image and pass in x and y to some function to get the value at that location, we are golden. And in HTML canvas, we can. And it’s likely you can do the same thing if you are using some other system.

I’ve created a Bitmap module. I’m not going to show it or go into it much here, but you can check out the source at the repo I’ll post at the end of the article. The module takes a url and an onComplete callback that gets called when it’s ready. It then has a getValue method that takes x, y parameters and returns a value between 0 and 255. This is an average of the red, green and blue values of that pixel and basically equates the brightness of the image at that point.

Here’s how we use it:

We create the initial canvas, but we don’t size it full screen like we did before. Then we create the bitmap and wait for it to complete. When it does, we set the canvas to be the same size as the bitmap, create 1000 random points, and call render.

Most of render should look pretty familiar. Get the value at the current location and use that to influence the particle’s velocity. Note that I extracted a couple of values, force and friction. Playing with these can give you very different behaviors. Try out different values. The other main difference here is that if a particle goes off the canvas, we set it back to a random location again.

Finally, the getValue function calls bitmap.getValue. Remember, that will return a value from 0 to 255. So we convert that to be in the range of 2 PI. And that’s it.

All you have to do is supply it an image. Note that for security reasons, you’re not going to just be able to link to any image from anywhere on the web, and you’re probably not going to be able to run this example from the file system. I just set up a simple node.js based server using the http-server package and serve the app and image from there as localhost:8080.

Supplying a random cat image (because this is the Internet, after all), we get the following:

You might even be able to see a hint of the cat there. But if you uncomment line 12 in the code, it will draw the original image before starting to animate the particles. With that, you see the following:

So, there’s a few more ideas. Different images, different settings, different ways of rendering or animating, all make for infinite possibilities. Now you can go explore some of them. Have fun.

The code for all of this can be found at: https://github.com/bit101/tutorials . Note that the code here is not necessarily super clean or ruggedly tested. I’m just having fun here and pretty much just stopped when things looked good.

Useful, or at least fun?

I plan to use the money I make from these posts to finance my presidential campaign. Or at least pay my Netflix bill for a month or two. If you’re down for helping me with either of those two things…

Flow Fields, Part I

Maybe you’ve heard the term “flow field” and maybe you’ve seen some neat pictures or animations with the term attached. In this article, I’ll cover what a flow field is, show how to create one, and give a few examples of experimenting with them. Flow fields are also known as vector fields.

The Pre-Game Show

I’ll be using HTML5, JavaScript and Canvas for this article, but the concepts will apply to Processing, p5js, WebGL, or just about any other graphics programming platform. That being the case, I’m going to try to focus less on the canvas specific stuff and more on the core concepts.

But, to just lay the foundations, I’m going to go over the files we’re using. It’s all going to be super basic. An HTML file and a JavaScript file. Here’s the HTML:

A bit of CSS, my QuickSettings Panel, which might come in handy eventually, a canvas element and a link to the main script. The script is going to start out like this:

All we’re doing here is getting a reference to the canvas and its context, then resizing the canvas so it fills the browser window, saving the width and height values for later use. Some of the CSS in the HTML file aids in all this being fully possible.

The Main Event: Flow Fields

So, what is a flow field? Well, you can think of a field as just a two-dimensional area. Of course, you could have a 3D flow field, but let’s save that for another day. You can also think of a magnetic field.

In this image of iron filings revealing a magnetic field, you see various lines and loops. The strength and orientation of the magnetic force is different in different areas of the field. You can imagine that an object moving through this field would be influenced by it and tend to move along those visible lines.

Basically, that’s what we want to do – create a two-dimensional area where each point has a different value. But these aren’t just random values. A particular point has a particular value and as you move out from that point to neighboring points, you get similar, but gradually changing values. In flow fields, these values are usually interpreted as directions. So if you map your values so they are between 0 and 360, they can be directly used as degrees of direction. Of course, we’ll probably map them between 0 and 2PI radians because the computer likes that better.

Once we have values for each point, we can graphically render each one based on it value. For example, we can draw a line pointing in the direction associated with that value.

So that brings us to two different tasks – how to come up with the different values for the field, and how to render the different values on the field. The great thing is, there are no correct answers for either one of those questions. In fact, there are nearly infinite ways of doing either one, so you can explore this technique for quite a while.

Let’s start out really simple, to get the idea of what’s going on. I’m just going to loop through from left to right and top to bottom, every 10 pixels. The value for that point on the grid will simply be (x + y) * 0.01 % Math.PI * 2. Just adding x and y together, scaling it down and modding it by 360 degrees (Math.PI * 2 radians). Then we render that value by translating to that point, rotating by the value and drawing a short line at the point.

Simple as that all is, we already have the start of something interesting going on.

You might now see why this is starting to be something you’d call a “flow field”. As you follow the directions of the lines, you start to see some very directional motion going on.

We can start cleaning this up a bit by extracting the two things that we’ve already determined are going to change a lot – the calculation of the value and how each value point is rendered. We’ll put each one of those into its own function and call them where appropriate.

No change in behavior, but we’ve isolated the things that we now want to change. Furthermore, we don’t necessarily always want this to be in a strict grid. Instead we can grab any number of random points on the grid and render those.

I’ve arbitrarily defined a value of 20,000 for number of points to render. Just looping through that many times, getting a random point and finding its value and rendering it. I’ve changed a few other values as well, such as the length of the line and the scale value that (x + y) is multiplied by. Now we’re getting something a bit more natural looking.

At this point, we can just start messing with the formula we use to get the value. Generally, you’re going to want to use the x and y inputs somehow, but really, just do whatever you want here. Here’s a somewhat interesting one I came up with.

Just taking the sine of x and y and adding them together. Some rendering changes too: reduced the line width and varied the line length at each point. But with just those few small changes, we’re onto something really hairy looking.

Now I could spend all day iterating on this – different formulas, different parameters for the lines it’s drawing etc. I know I could spend all day on it because I have spent whole days doing just that in the past. But let’s move on to something else.

Earlier I mentioned the idea that you could possibly imagine an object moving through a flow field and being influenced by those flows. Let’s simulate that. I’ll start with a single random point. Call it a particle. This particle will actually be an object with not only position, but velocity on the x and y axes. Initially these will be set to zero. On each iteration, wherever the particle is, we’ll get the value at that location – which is a direction, remember – and use that value to influence the particle’s velocity. Then we’ll add that velocity to the position to get a new position. And repeat.

Hopefully the comments explain a bit more what’s going on here. This gives us the following:

What’s interesting in this case is that we no longer actually see the field. We only see the result that the field has on the motion of the particle.

Do run this one on your own. It’s pretty neat to watch the drawing build up over time. You can see that the flow field is influencing the way the particle moves. You can change some of those hard-coded values to see what they do to the motion. Even in just our fifth iteration here, we have a ton of things to experiment with.

Let’s do one more for this article. Where one particle was fun, more particles is… more fun.

Here, I just made an array of particles and arranged them down the left side of the screen. For the algorithm, I used a strange attractor called the “Clifford Attractor”, published by Paul Bourke and attributed to Clifford Pickover. You can see the code for that here: http://paulbourke.net/fractals/clifford/ This gives you a very complex field. The parameters, a-d, are randomized at the top of the file, so you’ll get a different pattern every time.

Again, this is one you want to run on your own and play around with. It’s really quite beautiful to see in action. If you’re curious what the flow field actually looks like for one of these attractors, it’s something like this:

OK, that’s enough for one article. In part two, we’ll look at some other ways to create fields and other ways to render them. If you want to play around with the code itself, you can either grab the gists I’ve embedded here, or just check out the full tutorial repo itself at https://github.com/bit101/tutorials.

Pay(pal) it Forward?

If you’ve found this post useful or at least entertaining and want to contribute in some way, I will gladly accept your kindness.

It’s not my plan to make any kind of premium, subscriber-only content. And the Patreon model doesn’t really cut it for me. I just want to write tutorials for a while. If I make a few bucks here and there, I will probably want to write tutorials even more.

REBOOT!

History

I’ve been coding – as a hobbyist – since the 1980’s. But I’d say my programming career actually started around 1998, when I first accepted money for writing code. Make no mistake – the money I received at that time was worth a hell of a lot more than the code I was writing. But I like to think I’ve improved over the years and that my value as a coder is a considerably more commensurate with my current compensation.

I continued coding as a part time second job for a year or two until that late 90’s bubble finally burst. But I was hooked and had learned a lot. I knew coding was in my future in spite of the state of technology jobs at the time. So I continued to study and eventually learned enough that I was writing my own tutorials. This was back in the early days of Flash. My first tutorial was on coding physics and motion graphics. I called it the “Gravity Tutorial” but it covered stuff like velocity, acceleration, gravity, bouncing, friction and mouse interaction (dragging, throwing, catching). I promoted the tutorial on sites like Flashkit and before long it had thousands of views and had been translated into a half dozen different languages. That tutorial was followed up with several others, which led to book deals and speaking engagements and a full time employment as a programmer with a series of increasingly better jobs.

Throughout my career as a programmer, I’ve always taken a two-pronged approach. One is whatever job I happen to have a the time – writing code for a pay check. And the other is education – sharing whatever I’ve learned with other aspiring programmers. It’s been a successful combination and I’ve explored a number of different ways of doing the education part: tutorials, blog posts, open source experiments, books, conference talks, seminars and workshops, and in the last few years, videos.

Actually, over the last six months or so, I’ve really been slacking on the education stuff. I started a new job working with several technologies that I was really not up to snuff on. So I’ve been focusing far more on catching up on that stuff. But by now I’ve gotten to a pretty stable place and I’m feeling the urge to get back into teaching some stuff again.

Videos

While I’ve had a lot of fun making videos, they are a ton of work. First you come up with a subject and write a script. Then you record the audio, record the screencast, edit the audio, edit the video, sync everything up along with any other graphics you might want to add in, prepare the transcript, the title, upload it, prepare all the links and everything else that go on and around the videos, and promote it here and there. A single 15 minute video takes many hours of work. I guess other people can just sit down, hit record, start talking and typing away, finish up and publish. For me, though, a lot more goes into it than that.

Writing

So, in my next phase, I’m going to try going back to plain old writing, making some tutorial-type blog posts right here. I’m still working out some of the technical details, such as code embedding. I was initially thinking of using either codepen or jsbin for embedding interactive examples, but I think I’ve decided to stick with github gists for code only, and screenshots for results. I think my tutorials will wind up with multiple iterations of a single file and having an interactive example for each iteration is going to be heavy and overkill.

$$$?

I’m also trying to come up with some kind of idea of monetization. I don’t want to force people to pay in order to get the content, but in my experience, if you deliver regular doses of quality material, a lot of people are more than happy to voluntarily give something back. And who am I to deny them that opportunity? I’m not really happy with the Patreon model that I used for my Coding Math video series. I got paid once each time I published a video. All of those videos are still getting tons of views on YouTube, and likely will for years to come. But I won’t see another penny from Patreon on any of those views. Advertising is meh. I guess I can just throw up a “tip jar” link and make it really obvious. So that part will just most likely evolve over time. In the end, it’s not about the money, but it’s not NOT about the money, either.

Another idea I’m thinking of is cross publishing on other platforms. Medium is the one that comes to mind initially. I’ve never put anything on Medium. I kind of have mixed feelings about the platform, but it could wind up being a good thing. More eyes on the content, more clicks on the tip jar. One more idea I’ve kicked around is eventually compiling a bunch of articles into a self-published book. My Playing With Chaos book still gets a few sales per month. Enough to keep my Paypal account from bottoming out. 🙂 In fact, I have been planning a follow up book to PWC for quite a while now, but never seem to get around to it. So a lot of the articles I’m thinking of publishing here come from that project’s table of contents.

In closing…

Anyway, I’ve decided to just wipe out the old blog and start fresh here. I may put an archived version of the old blog up eventually. It’s quite old and really needed some severe maintenance anyway. But look forward to seeing some new content around here soon. Hopefully at the pace of an article a week? Maybe more, maybe less. And if you have any ideas or requests, feel fee to comment or otherwise shout at me via some random social network.