The computer images series has covered pixels, lines and polygons. Some drawing functions are very simple. Circles and ellipses can be drawn with some basic math and setting individual pixels. A fill algorithm is also simple, and not worth discussing. Curves, however, are far more interesting.
Curves are made with splines. Spline is a term long used in ship building. To make a spline, use a flexible but stiff material, like a strip of wood or metal. Attach it to pegs then trace the curve it makes. You can also tie weights to it, to shape the curve. Starting in the last century, they used math to solve splines. The equations are very similar to real splines but are less prone to errors. (Caused by flaws in the wood or metal spline.)
Making your own spline is simple enough, it just requires some math. First, decide on the spline properties. For example, we want a spline that passes through the points, is continuous and smooth. For it to pass through the points, it needs those points. For it to be smooth, the derivative must also be continuous. You could add additional characteristics, such as second derivative continuous, but we won’t bother for this one.
Points: `P_1, P_2, P_3, P_4`
Slope: `M_2, M_3`
We can pick an arbitrary condition for the slopes. For example:
`M_2 = P_3 – P_1`
`M_3 = P_4 – P_1`
Now we can write the input variables as: `P_2, P_3, M_2, M_3` and t. The variable t is a value between 0 and 1. Next, write out the conditions.
A weighting factor (k) is nice to add, to tweak it later. The initial equation is:
`f(t) = [P_2, P_3, M_2, M_3][[M_00, M_01, M_02, M_03],[M_10, M_11, M_12, M_13],[M_20, M_21, M_22, M_23],[M_30, M_31, M_32, M_33]][[t^3],[t^2],[t^1],]`
To calculate the slope we take the derivative:
`f'(t) = [P_2, P_3, M_2, M_3][[M_00, M_01, M_02, M_03],[M_10, M_11, M_12, M_13],[M_20, M_21, M_22, M_23],[M_30, M_31, M_32, M_33]][[3t^2],[2t],,]`
The first condition gives:
`f(0) = [P_2, P_3, M_2, M_3][[M_00, M_01, M_02, M_03],[M_10, M_11, M_12, M_13],[M_20, M_21, M_22, M_23],[M_30, M_31, M_32, M_33]][,,,] = P_2`
`[P_2, P_3, M_2, M_3][[M_03],[M_13],[M_23],[M_33]] = P_2`
`:.M_03 = 1, M_13 = 0, M_23 = 0, M_33 = 0`
The third condition gives:
`f'(0) = [P_2, P_3, M_2, M_3][[M_00, M_01, M_02, 1],[M_10, M_11, M_12, 0],[M_20, M_21, M_22, 0],[M_30, M_31, M_32, 0]][,,,] = kM_2`
`[P_2, P_3, M_2, M_3][[M_02],[M_12],[M_22],[M_32]] = kM_2`
`:.M_02 = 0, M_12 = 0, M_22 = k, M_32 = 0`
The second condition gives:
`f(1) = [P_2, P_3, M_2, M_3][[M_00, M_01, 0, 1],[M_10, M_11, 0, 0],[M_20, M_21, k, 0],[M_30, M_31, 0, 0]][,,,] = P_3`
`[P_2, P_3, M_2, M_3][[M_00+M_01+1],[M_10+M_11],[M_20+M_21+k],[M_30+M_31]] = P_3`
The fourth condition gives:
`f'(1) = [P_2, P_3, M_2, M_3][[M_00, M_01, 0, 1],[M_10, M_11, 0, 0],[M_20, M_21, k, 0],[M_30, M_31, 0, 0]][,,,] = M_3`
`[P_2, P_3, M_2, M_3][[3M_00+2M_01],[3M_10+2M_11],[3M_20+2M_21+k],[3M_30+2M_31]] = M_3`
Now we solve for the remaining constants:
This gives the final equation:
`f(t) = [P_2, P_3, M_2, M_3][[2, -3, 0, 1],[-2, 3, 0, 0],[k, -2k, k, 0],[k, -k, 0, 0]][[t^3],[t^2],[t^1],]`
This is our spline equation. So, how does it look in practice? For k = 1:
For k = 0.5:
As you can see, k could be called a tension constant. After creating a few splines you’ll quickly learn where additional constants are needed and how to best utilize them.
So now we can draw a curve. Or almost. No doubt, the inquisitive minds have already looked at the HTML source for this page. The SVG images are made with a series of line segments, not curves. To make a curve, just draw a series of straight line segments. This is important because of the parametric approximation. We’ve reduced a span of any length into a variable t that goes between 0 and 1. This means there is no direct relationship between t and pixel coordinates. Most programmers would just use a small increment of t when calculating the curve. This works, until the space between points grows beyond the t resolution. So it mostly works but sometimes makes dotted lines. A simpler algorithm is to calculate a set number of points along the curve then draw lines between them. The result will still look like a curve but takes far less time to draw.
This seems like an awful lot of work for simple curves, but without them you can not see text. That’s right, a spline is essential for drawing text. To explain why, understand the difference between vectored images and pixeled images.
A pixeled image is what we’ve covered so far. Vectored images don’t contain pixel level information. Instead, they contain drawing commands. These drawing commands can be applied to any size of image. For example, the SVGs in this webpage contain vectored data. The previous image contains circles and a path containing points. It’s similar to a program written in an image creating language. When the browser has to display it, it renders those commands into a pixeled image then displays the pixeled image. Vectored images can often be clearer than pixeled images, because it can be resized cleanly and the browser or operating system can change the antialias algorithm to match the monitor type. That will be covered in the antialias blog post.
Fonts have various sizes. With all the characters they contain, including all unicode characters, storing every size of every character would take a huge amount of memory. So instead, fonts have a list of drawing commands similar to SVG. When the operating system loads a font, it loads those drawing commands. If you need text rendered in a different size then it creates those images at the correct size and uses those. The operating system you use might not have a way to draw into your image. If you want text in your image library then you may have to make your own font libraries. For that, you will need splines to help draw the text.
Splines are an often overlooked part of an image library, but are most often essential.