fogbound.net




Wed, 30 Jan 2013

Failures in Typographical Experimentation

— SjG @ 8:35 pm

This started with an idea.

Perhaps it would be interesting to create a family of type faces where the density of the characters was related to the frequency of their use. This font, to be called Densitas, would have variants based upon the text analyzed. For example, Densitas Shakespeare would use the collected works of Shakespeare for the character frequency corpus, while Densitas Brontë would use the works of the Brontë sisters for the corpus. For aesthetic purposes, perhaps the initial faces could be selected based on relevance to the source corpus as well.

What would this accomplish? It might reveal something interesting about the difference in usages between authors. It might end up being environmentally friendly by using less ink on more common characters. It might enhance readability. After all, it’s popularly understood that we tend to look at the shapes of words rather than the constituent letters. De-emphasizing the more common shapes may even make it easier to process text.

Any time I have an idea of this nature, I start thinking about code and design and try to avoid thinking about the end result. As my Father is wont to say, it is just as difficult to create something ugly as it is to create something beautiful. If I think too much on the end result, I will obsess over whether it will be worth the effort, and never get to the actual work. If I just dive in, I may find myself wasting a lot of time, but at least I will learn something.

This turns out to be one of those experiences. I thought it was an interesting idea. The end result is mediocre at best, dull perhaps, a waste of time. Still, I learned something in the process.

Step one was to write a character frequency analyzer. This code does a few things:

  • read a text file
  • compute the character frequencies
  • scale the results across the frequency range, so the least frequent character has a value of zero and the most frequent character has a value of one
  • map the characters to glyph names
  • write out a chunk of code to substitute into the next step

The next step is a FontLab Studio/RoboFab script, hence glyph names instead of raw character names. Since FontLab/RoboFab scripts are in Python, I figured I’d write this in Python as well (I don’t really know Python, but that kind of ignorance never stops me from writing code).

I ended up with this program: cf.py

I ran it against the plaintext
The Complete Works of William Shakespeare from Project Gutenberg
(after stripping out the Project Gutenberg-specific text, which I believe is permitted since I’m not redistributing the text, merely crunching it with code).

The FontLab/RoboFab script accepts two font sources, and interpolates each glyph according to the frequency computed in the previous step, where the less frequently used glyphs are darkest. For my test, I used the current state a sans-serif font I’ve been developing1. I have it in several weights, so I interpolated between the lightest and heaviest. The code to do this interpolation looks like shakespeare_weighter.py.

The results were unimpressive, to say the least:

(click to enlarge)

There are some of the obvious problems: distribution between is too stark; there seem to be only two or three densities. Similarly, kerning gets really disrupted by the different densities. But first things first. Why is the density contrast so extreme? Looking at the weighted frequency data answers that question:

For this chart, punctuation and other glyphs have been omitted.

So the next approach is to make the differences more gradual. Instead of doing by pure letter frequency, we use a gradient based on the ranking of frequency. In other words, the least common glyph is the darkest, the next least common glyph is one increment lighter, and so on, until the most common glyph is the lightest. This code to compute this looks like cf2.py, and the output distribution looks like this:

Looks more promising, does it not? We substitute the values into our FontLab/RoboFab script (like this: shakespeare_weighter2.py), and run it. Alas, the end results are still pretty dull:


(click to enlarge)

For the last try, we’ll do a few things differently. First, the thing that probably jumped out at you when you saw the first distribution graph: we’ll ignore all non-alphabetical characters when doing the frequency calculation. For the sake of readability, we’ll set all non-alphabetical characters to the median value. Secondly, we’ll take accented characters and consider them the same weight as their non-accented versions, so, for example, “á” and “ä” are the same density as “a.” Lastly — and this might be the big shift — we won’t interpolate between two weights of a font based on the frequency, but instead we will effectively halftone each glyph with a screen density based on the frequency.

To do this, we use the RoboFab halftoneGlyph() pen for inspiration. We do a much blunter approach: we impose a grid over the glyph, determine which points on the grid are inside, and replace those points with squares. The size of the squares is the same across a given glyph, and is based on the frequency. This process will then convert a nice, smooth glyph into a rougher, pixellated gray version of itself.

The revised frequency computation code is here (cf3.py), and the resulting frequency graph looks like this:

From this, we generate the final FontLab/RoboFab script (this one: shakespeare_weighter3.py), and run it.

And yet again, we look at the results, and sigh. All this work, and really nothing to show for it. There are a number of problems. The font stresses most rendering engines with its very high contour count, and either gets blurred into oblivion or converted into a plaid checkerboard nightmare when viewed on a display. The differences in shades are only apparent when the characters are enormous, even when printing. And, of course, aesthetically, it’s nothing to write home about.

(click to enlarge)

The lack of results are dispiriting enough to resort to quoting that reprobate Thomas Edison: “Results! Why, man, I have gotten a lot of results! I know several thousand things that won’t work.”

I can’t claim to know thousands of things that won’t work, but I do have another handful to add to the collection.

1 The font will be released as WL Hope Grotesque, when and if I ever complete it to my satisfaction.


Tue, 8 Jan 2013

iPhone 5 Wallpapers

— SjG @ 8:48 pm

I needed to change my iPhone lock screen image. With no further aesthetic commentary, here are three Retina-ready, iPhone 5-sized images you can use. They’ll also work on non-Retina or lower-resolution iPhone screens, you’ll just have to select a portion of the image (or scale it down). If you don’t know how to install Wallpaper images on your iPhone, the first page I Googled gave a pretty good step-by-step.

(Click on the thumbnail to see the full-size versions; right-click to download them)

Enjoy!


Fri, 12 Oct 2012

Resizing LVM partitions

— SjG @ 10:30 am

I ran into a problem where the default installer for RHEL had configured a server’s partitions in a way that was really suboptimal for how the server was being used. It looks like the default was intended for workstation use or one in which a lot of users would keep their stuff in home directories, but this system is being used as a web application server. The root partition filled up, and the database (with its files in /var) got quite unhappy.

[root@epicwin]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_epicwin-lv_root
50G 47G 0 100% /
tmpfs 1.9G 76K 1.9G 1% /dev/shm
/dev/sde1 485M 80M 380M 18% /boot
/dev/mapper/vg_epicwin-lv_home
532G 198M 505G 1% /home

So I had to learn some LVM basics, and move the space around. I found various instructions out there, but many of them were missing steps or glossed over whether or not I’d suffer data loss. Here’s how I solved my problem (without data loss!) and got the system back on its feet.

  • Boot into “rescue” mode.
  • Decline to mount the existing system or filesystem for repair, instead go straight to a root shell.
  • Activate the LVM system:
    lvm vgchange -a y
  • Make sure the filesystems are clean:
    e2fsck -f /dev/mapper/vg_epicwin-lv_home
    e2fsck -f /dev/mapper/vg_epicwin-lv_root
  • Reduce the size of the lv_home logical volume from 540G to 40G:
    resize2fs /dev/mapper/vg_epicwin-lv_home 40g
    lvreduce -L 40g /dev/mapper/vg_epicwin-lv_home
  • Expand the size of the lv_root logical volume from 50G to 550G:

    lvextend -L +500g /dev/mapper/vg_epicwin-lv_root

  • Expand the filesystem on the root logical volume:

    resize2fs /dev/mapper/vg_epicwin-lv_root

  • Exit shell / reboot.
  • Watch SELinux freak out on next boot:

    *** Warning -- SELinux targeted policy relabel is required. ***
    *** Relabeling could take a very long time, depending on file ***
    *** system size and speed of hard drives. ***

  • Watch SELinux print asterisks and then the system reboot unexpectedly in a way that looks quite disturbingly bad.
  • System comes up clean!

A few notes:
If /home had a lot of stuff in it, this would obviously be a lot more complicated. This approach works because I had the space and it wasn’t being utilized. if /home had been closer to full, the approach would have been to add a new physical drive, and it to the logical volume set, and then do something similar to the above.


Mon, 17 Sep 2012

Cambot’s First Campaign

— SjG @ 10:30 pm

Cambot is a project based on the Teensy development board. Cambot creates an infra-red “trip beam” that triggers a pre-focused Nikon D90.

To create an IR beam and detector that work in direct sunlight, Cambot pulses the IR source every 10ms, and compares detected signal between the on and off states. If it’s greater than a threshold, it’s considered a valid signal. The sensor also has a vary small aperture which is additionally shielded with a filter to reduce the ambient IR. When powered on, Cambot goes into calibration mode, which lights up an LED when it detects a good signal. This is critical for lining up the IR sources and detector — once a good signal is sustained for 3 seconds, Cambot goes into “armed” mode. When armed, breaking the beam will turn off the IR source, half-press the camera’s shutter for 10ms so the camera can compute exposure, and then fires off a burst of pictures before re-arming itself.

While there’s nothing in Cambot that couldn’t have been implemented with, say, 555 timers, counters, and gates, having the ability to drive digital logic with C code makes things much more flexible. When trying to determine the proper threshold values for arming and triggering, the ability to output hex data over the USB connector to a host computer was invaluable.

Here’s Cambot’s first run, when the trip-beam was positioned over a tempting milkweed blossom in the back yard.

If there’s any interest, I’ll post a circuit diagram and source code.


Mon, 6 Aug 2012

Sneaky, sneaky SELinux

— SjG @ 4:38 pm

I was getting a web site up and running on Centos 6.3, and PHP was refusing to talk to the SMTP server on the same box. This, in and of itself, is not unusual. There’s a checklist:

  • Verify SMTP’s running
  • Check that the SMTP server is configured to accept connections from localhost
  • Check the firewall rules
  • Really check the firewall rules by generating an email using telnet localhost 25 or nc localhost 25 from the command line
  • Check that PHP is trying to talk to the SMTP server you think it is
  • Look in the system log for SELinux being a bully and preventing communication

In this case, all of the above checked out cleanly. I was perplexed. But it turns out that, in what is as shocking and surprising as my cat wanting to be fed,
SELinux was indeed the culprit. It just wasn’t logging the problem anywhere.

A quick
setsebool -P httpd_can_network_connect=1

as root solved the problem.

Moral(s) of the Story: The cat is always hungry. SELinux is always fuckin’ shit up.