I recently stumbled upon John Siracusa’s legendary Mac OS X reviews for the first time.
If you’re not in the loop, these were astonishingly detailed technical reviews of Apple’s major Mac OS X releases between 1999 and 2014. According to Ars Technica, where these were published, “a new OS X release started with Steve Jobs and ended with John Siracusa.” I voraciously delved into these reviews with a handy reading list as my tour guide.
What I found most fascinating — and what really inspired me to write this — was the piece on Core Animation from 2007. As a Swift baby, who barely remembers the Grand Renaming of Swift 3.0, Core Animation feels as fundamental as iOS itself, underpinning both UIKit and SwiftUI.
Learning of the existence of a world before Core Animation is like finding out that Santa isn’t real. What? You mean the pixels didn’t move around my screen by magic? It’s like learning that before the fire, we cooked food by rearranging its atoms by hand. Which, incidentally, is more or less what you had to do with pixels on first-generation GUIs.
In this article, I’m going to guide you on a journey through time to discover what was available to the Apple devs of each era, explain the problems solved by each successive generation of animation APIs, and even give you the opportunity to play with some real-life old-school animation code in this GitHub project.
Timeline
1989 — NeXTSTEP Generation: Display PostScript
2001 — Apple’s Renaissance: Quartz & OpenGL
2007 — The Modern Era: Core Animation
2014 — The Performance Age: Metal
2019 — The Declarative Revolution: SwiftUI
1989 — NeXTSTEP Generation: Display PostScript
Let’s first jump way back in history to understand the context of today’s Apple software. After being ousted from Apple in 1985, Steve Jobs founded NeXT, a rival computer company.
NeXT was hugely influential in object-oriented programming and graphical user interfaces and was eventually acquired by Apple. Their own NeXTSTEP operating system was merged with the Mac OS to become Mac OS X.
I didn’t want to shell out for a NeXTcube — or go down a huge rabbit hole to emulate 40-year-old hardware — therefore this section will show some code, but we won’t be able to run it. For everything else, there are real-life examples in the GitHub project that you can try out in Xcode!
The NeXTSTEP OS used a computer graphics engine developed by Adobe called Display PostScript. This introduced substantial advances over previous-generation display layers: it allowed text and graphics to be treated the same and introduced device-agnosticism through its higher-level API and page description language.
To give you a flavour of what this was like to work with, I bring you a charming snippet from the NeXT Computer Programming Manual:
# In the Application Kit, rectangles are specified as C structures of type NXRect. Since all coordinate values must be specified by floating-point numbers, it defines NXCoord as a float:
typedef float NXCoord;
# A pair of NXCoord variables--one for the x coordinate and one for the y coordinate--designate a point:
typedef struct _NXPoint {
NXCoord x;
NXCoord y;
} NXPoint;
# A pair of NXCoord variables also designate the size of a rectangle:
typedef struct _NXSize {
NXCoord width;
NXCoord height;
} NXSize;
# The NeXT header file graphics.h (in the appkit subdirectory) combines NXPoint and NXSize structures to define the rectangle itself:
typedef struct _NXRect {
NXPoint origin;
NXSize size;
} NXRect;
The manual also offers some simple code examples and PostScript APIs, such as…
Instantiating a rectangle:
NXRect rect = {{10.0, 10.0}, {50.0, 50.0}};
Highlighting a rectangle on-screen:
NXHighlightRect(&rect);
Checking whether two rectangles overlap:
BOOL overlap;
overlap = NXIntersectRect(&rect1, &rect2);
Creating a new rectangle for the intersection of overlapping rectangles:
NXRect *smallrect;
smallrect = NXIntersectionRect(&rect1, &rect2);
Creating a new rectangle for the union of both rectangles, i.e., the rectangle containing both:
NXRect *bigrect;
bigrect = NXUnionRect(&rect1, &rect2);
While these commands were exceptionally low-level compared to what we are used to, they could compose together to create some pretty clean-looking systems, considering the constraints of 1989 hardware.
While code archaeology is good fun, I am starting to get dust in my butterfly keyboard. Before I cannot type, I will move on to some APIs that you can run on today’s hardware!