pyBlazon: Blazonry to SVG Converter
Links here are temporarily broken: Google code shut down, and the project has been moved to github; I'll update the links soon.
pyBlazon is a Python program that attempts to translate from Blazonry, the specialized terminology used for describing coats of arms (specifically shields) to Scalable Vector Graphics. In other words, this is an attempt at automatic emblazoning (drawing) of a blazon (description). pyBlazon was written by Mark Shoulson and Arnt Richard Johansen.
Blazonry has been called the first programming language, loosely speaking (maybe a markup language would be closer. Like HTML or something). But it never intended for the kind of precision required here, and was always meant to be read by readers with full Natural Language Processing abilities (i.e., people), not by a computer program trying to implement it as a proper subset of English. The line between blazonry and just plain English is not a sharp one, so be aware the program’s abilities are very limited compared to the liberties blazons commonly take.
The program uses PLY, which is a Python port of the venerable LEX/YACC combo. The grammar is thus subject to some limitations, but we'll see what can be done about that. As the blazon is parsed, various blazonry objects are created and called upon each other, representing tinctures, charges, ordinaries, and so forth. The other library used is SVGdraw, which does not seem to be supported anymore, so we will include it with the pyBlazon distribution (the license appears to permit this). SVGdraw is a fairly simple library that just makes building SVG files a bit easier.
The SVN log of the project will show the checkin messages as changes are made to the code, but more usefully...
- 1 May 2008
Merged a “branch” version I had been working on back into the trunk: I think I don't yet properly appreciate when I should really be dealing with branches. The new one, now uploaded to the server, uses a different method of lexing, which gives more flexibility, and also added a question-mark charge to be used whenever someone gives a charge that the program does not know about. This should lead to fewer unenlightening “error” pages.
Also, finally announcing the pyBlazon GoogleCode repository for all your pyBlazon needs. You can check out the source code from there (yay!), add your comments to the wiki, track issues that I'll ignore, etc.
- 14 March 2008
- Pursuant to bug report #422599 reported on Mozilla Firefox, which someone else filed after having trouble seeing the SVG code generated by pyBlazon, I’ve corrected all the SVG errors. I had run the output through a validator, but that was a while ago and also there are errors that validators don’t catch. I may backtrack on some that apparently did not need to be fixed, but things do seem to be working better on Opera, at any rate.
The full grammar understood by pyBlazon is in its plyyacc.py file, contained in the __doc__ strings of the functions, as required by the PLY package. Here is a link to a printout of the current grammar, and here is one for the lexical elements. But it is probably more helpful to have a simplified description. I am replacing the almost-formal informal grammar that used to be here with something much shorter and more example-oriented; maybe that will be helpful. Note that punctuation, in general, is stripped out and ignored, so don’t go worrying about where to put commas: they do not need to be anywhere.
- Essentially, you want «treatment» followed by one or more charges or charge-groups.
- The “treatment” is going to be a color, like argent or sable or azure and so on (I am assuming you know blazonry jargon; if not, follow a link somewhere below); or else it can be something more complicated like per pale argent and sable or gyronny of ten vert and azure or per bend sinister wavy purpure and or. You can do furs and lines of partition and all kinds of sneaky things like that.
- Charges and ordinaries currently sorta share grammatical space. And the usual ones work: bend, pale, fesse, chevron, bar, pallet, bend sinister, etc., and also roundel, lozenge, fusil, mullet [of x points], annulet, and so on. A charge has to have a treatment too, which follows it, as in sable a roundel or or per pale argent and sable a lozenge per saltire gules and azure or whatever excites you. These can get arbitrarily complex.
- You can also have a charge-group, which is a group of identical charges, like three lozenges sable or six roundels per cross argent and gules. These can also be given an arrangement, like two two and two or seven annulets argent, four one one and one or whatever, or else in cross, in bend, in annulo, etc. If you have more than one charge or charge-group, pyBlazon will try to arrange them in the “right” way, occasionally with success.
- Any charge can have other stuff on it, in which case you use the following syntax: on a roundel sable two mullets argent or on a bend or three billets azure.
- If you want charges on the elements of a chargegroup, you say things like three roundels azure each charged with a lozenge or or five lozenges sable each charged with as many mullets argent.
- For examples, see the blazonserver's list of examples, and also the Evil Blazons page on the pyBlazon wiki at GoogleCode.
Just from looking at the grammar you can see some potential problems with commonly-used constructions. This isn't an exhaustive list, though I'm working on it. I'm sure you'll find plenty of perfectly normal blazons that don't work: remember, blazons were intended for humans, whose English is much better than the program's.
This section prone to fast out-of-dateness.
- Directions like “in chief” come after the charge or group, so you have to say Argent two bars and three mullets in chief gules instead of Argent two bars and in chief three mullets gules. (George Washington’s arms)
- You have to say purpure within a bordure argent instead of purpure a bordure argent
- “Between” is a synonym for “and”. So “or a fess between two chevrons gules” doesn’t work: the fess overlies most of the chevrons. (Working on changing this, but progress is slight so far.)
- At the moment, certain treatments, like “per pale azure and gules” don’t work on some SVG-included symbols, like lions rampant.
- Stuff like “argent an escutcheon gules and eight escallops azure in orle” lumps the escutcheon and the escallops into one group, and then ignores the “in orle” instruction. Using between will (now) prevent the lumping together, but the sizes come out wrong still.
- Generally, the hack that combines different charges into groups is, well, a hack. And fairly badly-behaved in several situations. This hack is necessary for things like “per bend argent and sable a mullet and a roundel counterchanged”: they have to be joined into a group of charges so they can be distributed properly, on either side of the partition line. Misbehavior of this hack causes things like the above bug, and also the fact that you can't say “ermine a mullet and a lozenge gules in pale”. The “in pale” has to come after the first charge, which is just wrong. The hack will have to be re-hacked.
- The charges “cross couped” and “saltire couped”, etc, are not recognized and tend to be treated as just crosses and saltires.
- A chief sometimes squishes the rest of the field down, as it should, and sometimes does not, in which case it interferes with what is on the top of the regular field. I've tried to disambiguate a little: to make a “real” chief, that is, one that squishes the field down, use “with a chief...” instead of “and a chief”, and it has to be at the very end of the blazon. If there are charges on the chief, you have to say “with a chief azure charged with three bezants” or something like that (and not the “and on a ‹ordinary› two ‹charges›” like usual).
- Field colorations like barry and furs (usually) don't scale with the charge they are attached to. This is often the Right Thing, but it can make things like a fountain (a roundel barry wavy argent and azure) look funny because the stripes are too wide. You need to specify something like “a roundel barry wavy of twelve argent and azure” to make it a finer-grained barry. On the other hand, sometimes the treatments do scale, depending on the precise charge and how it is included, or when made into a semy.
- In general, only a few charges are known. Deal with it.
- Sometimes charges get positioned badly and overlie each other.
- In a similar vein, charges on top of other charges (e.g.
on a roundel or two mullets sable) work some of the time, particularly when the base charge is fairly large and open, like a roundel or an escutcheon. But since the program doesn't know the sizes of the open areas of charges, things like lozenges and mullets sometimes wind up too small for their contents.
- Obviously, you can’t specify complicated things like “argent a label sable each point charged with three bezants” or “azure three four-winged, six-headed seahorses in pall argent, their tails nowed in a right-handed three-way sheet bend”.
See also Hacks.