The joy of quiet coding
I never planned to code up a text layout engine from scratch. When I set out to fix some niggling annoyances in my canvas library's text handling code (aka: the Phrase entity) my main objective was to get the damn thing to display Arabic fonts on the canvas without looking like a drunken mess.
That work took me the best part of four months to complete. It started over Christmas when, instead of carousing, I sat in corners and thought about how graphic designers might want to add text to a poster, how data explorers might like to label their graphs and infographics. Where does text appear in a video game? When does it need to break over lines?
By the turn of the year these idle questions were piling up: how do we give different letters different colours, or sizes, or even fonts? How do we underline text? More fundamentally, how do we make sure screen readers can read the text in a way that makes sense?
... Too many questions! Given the whirl of thoughts in my head I took the decision to park work on this issue and go tinker with other shiny trinkets like getting a canvas element to play nicely with the new Popover API thing. This is something I regularly do across all my interests; shunting a knotty problem to the back of my head for a few weeks (or months) will often lead to much of the problem unknotting itself while I'm not staring at it.
I returned to the text problem at the start of February. The solution my subconscious had brewed for me seemed extreme: scrap all of the existing text-related code in the library and start again, replacing my beloved Phrase entity with two completely new ones. The first replacement would be a simple Label entity which would handle single lines of text and act like every other entity in the system for positioning, rotation, scaling, etc.
The other new thing - which I came to call the EnhancedLabel entity - was a completely different concept. Instead of laying text out in boxes, why not lay it out in shapes? Any shape! And for bonus points, track the text along bendy paths. Also: don't forget animation, because ... fun!
I know. This isn't a new idea. You can do it in Adobe's Photoshop software. And their Illustrator. Also in various other designery tools - like this one. You can even (sort of) do it in MS Word documents if you enjoy that sort of torture!
But you can't do any of that, today, in a web page.
We do have the CSS shape-outside property which we can use to push text from its boxy edges in interesting ways ... but it's a lot of work to implement for what is, in the end, just not the same thing.
As I started implementing my ideas I knew, if I managed to deliver even 10% of the vision I had for this new text handling functionality, it would mean introducing a major breaking change to my library's code. It would lead to much work, serious inconvenience (and probably some novel swearwords) to any downstream developer whose product used my library as a dependency.
... Which is the point of this post. I was very happy to embark on this intense voyage of discovery with no care whatsoever for the hurt it could cause fellow developers. Which is not the sort of attitude a caring, conscientious maintainer of an open source JavaScript library should have. Why no forewarning or consultation? Why no consideration of backwards compatibility?
What sort of idiot coder would consider damaging the reputation of his prize library in such a thoughtless, cavalier way?
Evolution and the Selfish Coder
My name is Rik and I am not a normal person.
I've known for a long time that I don't fit comfortably in the world around me. For a start, I don't understand why everybody else seems to care so much about the profit-and-loss of life. The whole celebrity-influencer-industrial complex leaves me cold. I've never felt the need to measure my worth by the wage I earn or the job title on my (virtual) office door. When I failed at the 'make it big before you're 30' thing I felt ... well, nada. I was too busy whoring my way through the London gay scene to notice (because: fun!)
Several times in my life I've been accused of "lacking self-confidence". It's fake news. A bad conclusion based on shaky assumptions. Because I know I have plenty of self-confidence; I just demonstrate it in ways people who think they have the right to criticise me choose not to see.
Take hierarchies, for instance. I don't like them. In my view too many people spend too much of their time worrying about their place in the scheme of things - especially when it comes to how they slot into them. Me? I prefer to get on with stuff - preferably stuff I enjoy doing, hopefully alongside good friends who are happy to tolerate my company.
This distrust of hierarchies is not confined to my social life. It infects the way I think about many subjects. When I look at a new codebase my first thoughts tend to focus on 'what does this do' rather than 'how is this built'. I can stare at a website's building blocks - the stacks of components used to construct the page - for ages, clueless; only when I start to untangle the user journeys the page offers, the play of data between front and back, across the page as microseconds pass, does my mind gather insights and glimmers of comprehension.
So, what made me this way? Perhaps I was born different?
According to the (thoroughly discredited) Myers-Briggs system, I have an INTJ personality type. As horoscopes go, it aligns more accurately with the model-of-self I carry around in my head than most such personality descriptions I've encountered over the years. Though it doesn't compare well to the glamour of my Chinese horoscope sign: the Wood Dragon is the best stereotype I've ever tried to imitate!
Whatever. I don't believe I was born different. I was (in my view) given a reasonable set of genes from both parents which then got shaped by circumstances. One genetic influence was my inherited face blindness (from my mother); another was dodging the dyslexia genes my Dad bequeathed to my siblings. But my aggressive self-reliance? That probably arose due to me being born a long time after the rest of the brood. Having parents who fed me and shod me and let me just get on with life was more blessing than curse.
One of the most important childhood lessons I picked up was that there are no Knights In Shining Armour, especially not in the real world. If I wanted a given outcome then I would have to get it, or make it, myself. Good things do not come to those who wait.
Another lesson came from the English class-based society that surrounded me. Know your place, I was told; you're not as good as you think you are. Do as we say. Respect your betters ... the lesson I took from that societal pressure was: fuck you!
My family taught me how to deal with that crap: don't let the bastards know you're scared! Maybe I took their advice too close to my heart?
Because if there's an originating cause to my antipathy towards hierarchies, then it's the slow-burning hatred I developed towards people who thought it was their God-given right to slap me down, denigrate and belittle me, push me back into my cage. When I learned to harness that anger, to use the passions it generated in ways that benefitted me rather than damage the world around me, I discovered a superpower that's kept me sane and productive for much of my adult life!
Life shapes us in wondrous ways!
The great open source popularity contest
For a wage, I develop and maintain web-based tools and web components in a corporate environment. I rarely have to innovate new approaches to the products I churn out but, when the opportunity arises, I do the sensible frontend engineering thing and go search the InterWebs to see if someone, somewhere, has already published a solution to the Node Package Manager (NPM) - a holy place in the Clouds which serves peace and harmony to all who seek its beneficence.
I think of NPM as the Cerberus that guards the Gates to GitHub, where all code goes to die. As a responsible engineer it is my job to pass those hallowed portals to inspect potential code solutions - for in many cases many people will have published packages that could solve my requirements ... but not all solutions are equal.
When it comes to evaluating GitHub code repos, I use three criteria:
How many contributors worked on the repo in the past year?
How often does the code get updated?
How healthy is the issues backlog?
I need to ask these questions because when I add a new NPM dependency to a company project, I'm actually pushing yet another sharp knife against the business's throat. Should the package break or fail for any reason, it has the potential to impact on the company's operations or revenue streams (and potentially my continued employment).
The one metric I do not check is how many GitHub stars the repo has. Like poems, GitHub stars are Lies. Sadly most engineers refuse to believe this. Decisions get made on that sole criterion and much anguish generated in due course. Need to choose a JavaScript framework for your next project? SvelteKit has 17.9k stars. Yet Backbone has 28.1k; Angular.js 58.9k ... which one is the best?
Now my canvas library lives in GitHub (where code goes to die) and has a presence in NPM (praise be!). Any frontend developer in the world can add my code to their project - I mean, who doesn't want their canvas-based interactive video to be as responsive and accessible as possible?
So obviously I should make all good effort to build a healthy community around the library. Many hands make light work, etc. Every sinew needs to be torn to promote the library to designers, product managers and developers so they can use my Genious solutions [tm pending] to generate profits and promotions. Stars must be gathered!
... I have tried. (Cynics will say I'm trying right now). I've smuggled links into blog post comments; I've mentioned it in passing in relevant Reddit communities. I've spammed Hacker News too often to count. I've built a promotional website; written reams of documentation; devised tutorials and coded up many (many!) demos. And I've been doing this work for the best part of ten years.
Heck: I even started a Discord channel - if you're searching for some online peace-and-quiet then it's the perfect place to visit!
It's usually at this point of the rant that I start making excuses: my marketing skills are laughable; my networking skills shite. My luck runs in other directions ... but who am I kidding here? Not you, dear reader, and certainly not me.
The joy of quiet coding
The scene graph concept has been around for decades. Used initially with 3D graphics, the scene graph sorts everything to be displayed into hierarchies of nodes (groups, layers, etc) and leaves (the pretty stuff). It's a really powerful way of laying out a graphic representation, and offers many efficiencies for animating the graphic and making it interactive.
I would argue that Flash was responsible for popularising the scene graph to websites across the globe, but it was by no means the only game in town. It can be argued that SVG, and even HTML itself, are forms of scene graphs. Because they all have one thing in common: they all model their displays using hierarchies.
After Flash died (or got murdered by Steve Jobs - note I have no dog in that fight), space opened up for intrepid code warriors to write libraries for the HTML <canvas> element, which had finally been standardised for implementation in web browsers in the late 2000s. Most of those libraries used a scene graph for their foundational functionality - partly because "Flash used it", but mainly because it's an excellent, battle hardened approach to sticking colours and shapes onto a computer screen.
Writing a canvas library is really, really hard work. Building your library on industry standards just makes sense!
... Have I mentioned how much I hate hierarchies?
I think the main reason why people don't use Scrawl-canvas is because it's too different to what they expect a canvas library to be, and do.
Take positioning. Most canvas libraries use the scene graph to stamp a red box on a black background. Traversals get run and matrices multiplied and everything falls into place. Scrawl-canvas takes a different approach: instead of assigning the box to a layer, and the layer to the root, a Scrawl-canvas Block has start coordinates which position it relative to the canvas - or we pivot it to another entity which determines where the box gets painted - or maybe we lock the box to a path, or a DOM element's corner, or a particle, or even a word in a block of text. Because Scrawl-canvas doesn't do hierarchies, and when they do creep in we try our best to ignore them.
That's how much I hate hierarchies!
So people don't use my awesome library and ... I kinda like it that way! Where other library maintainers have stress - GitHub complaints, GitHub demands, GitHub flame wars - I have serenity. I have the space to experiment with outlandish ideas and nobody gives me grief about it. Because nobody knows.
I built my own tween system and added it to the library. I could have instead written code to allow proven solutions like GSAP to do all the tweening work for me - but where's the fun in that?
I love the SVG approach to creating graphical filters but hate the hierarchical way SVG handles everything ... so I replicated the best bits of the SVG methodology and added it to the library. I did it because I could do it; people have a right to moan about the big increase in the library’s size, but nobody has complained to me yet.
Talking about filters, one Christmas I became obsessed with the idea of building a reduced palette filter. Did I make use of the latest research around building an effective reduced palette filter? Of course not! The results of the work please me and, at the end of the day, that’s all that matters.
Enough! I've written too much already. There's no moral to this story, no tidy wrap-up - except perhaps "don't do what Rik does if you want fame and glory".
YMMV.