Flashkard Printed Output
Hal Stanton's article on FlashKard made me abandon some primitive flashcard software I had been working on. What I wanted now was a way to print the data on, well, flashcards. I was going to write one of my typical hacks--most likely using awk and troff--to print the cards, but I decided to try to work with the XML.
What I mean by work with the XML is I decided to use standard XML tools to format the data for output. I had never done this before, but I knew XSLT was an important buzzword. XSLT stands for XML Stylesheet Language Transformations, and it is a language designed to define transformations from XML to other formats. So, I started reading. Typically, XSLT is used to transform XML into HTML, but there is no restriction on what you can do with it. So I decided to give it a try for my flashcard project.
Having decided to use XSLT, I still needed two more pieces of information before I could continue. First, I had to decide what to transform the XML into. Second, as there would be some program logic involved to place the cards on the page in the right positions, I needed to decide on a general-purpose programming language. After considering the various programming language alternatives--Python being the one that sounded best--I realized that if I simply generated PostScript, I could let the printer itself deal with the placement issues. It seemed strange, but I figured "Why not?".
Having picked PostScript, I sat down to decide how to place the cards on the page. Flashcards need to be double-sided. At first, I thought of printing one side and then running the card stock back through the printer to print the other side. This is a logical nightmare, however, as it is easy to get the paper in the printer incorrectly, have a registration problem or get out of order because of a printer jam.
I decided on an alternative approach that involves another high-tech device called a "glue stick". The idea is to print the front and back of each card on the front of one page, which you then fold in half, glue together and cut into the actual cards. The double layer of paper and the glue make the cards heavy enough to work with without falling apart.
Now, it's time for a confession: this is not a beautiful, finished production system. What it is, however, is something that works and a proof of concept. For a production environment, it is important to define card sizes and fonts in a configuration file. In addition, the message for each side currently is printed in a single line without consideration of size. Line folding needs to be implemented.
Okay, back to work. I picked a 1.5" x 2.5" card size, which makes it possible to get nine cards--both front and back--on one side of letter-sized paper. I set 1" top and bottom margins and .5" left and right margins. In order to make folding and cutting easy, I wanted to print a fold line down the middle of the page--between the front sides and the back sides--and cut marks for the edges of the cards. With this fold, the printing on the back is upside down from the printing on the front. After considering this for a minute, I decided it wasn't important--it simply defined which way to turn over the card when using them.
Everything, that is, the PostScript and the the XSL, is in one file that you can download here. You can ignore the XML stuff for now. Note that if you try to display this in your browser, it does not display correctly because of the XML. You can see the sample output below.
If you have never worked in PostScript, get ready. PostScript is an RPN (Reverse Polish Notation) language. If you have ever used an HP calculator, you know what I am talking about. If not, the quick explanation is that you do things by putting items on a stack and then operating on that stack. For example, to add two numbers, you place the numbers on the stack and then execute the add operator. The operator then fetches the numbers, adds them and puts the result back on the stack. Note: I hate RPN languages.
Disclaimer aside, PostScript actually is a very clean language and not a bad one to do the work we need to do. The way you work with PostScript is to describe everything you want to put on a page--characters, lines, filled-in areas and so on--and then tell it to print the page. That means we don't have to remember a lot of stuff and then work down the page sequentially; we simply move around and put what we want on the page.
In PostScript the basic unit of length is 1/72 of an inch. Personally, I an not very excited about working in such units, so I defined a function, called inch, that takes the current value on the stack, multiplies it by 72 and puts the value back on the stack.
/inch { 72 mul } def
This way, I add the word inch after a number and it is multiplied by 72.
If you look at the cutmarks function, you can see a whole bunch of moveto and lineto statements. As you might expect, these operators take two values off the stack--an x and a y coordinate, where the 0,0 is the lower left corner of the page and a positive move to the right or up--and either move the current location to the specified coordinates or draw a line from the current location to the specified location.
Going down to the startit function, you can see all the setup work for the page. I define three, nine-element arrays--x, yf and yb--that contain the x and y coordinates (yf for front, yb for back) of where to place the text for each of the nine cards. (Note that arrays in PostScript are indexed starting at 0.) The other two initialization steps are to define the font and font size to be used for the text and to set the card number counter cardno to 0.
Two other utility functions are defined, cardstep and pageout. pageout checks the current card number. If it is greater than 0, pageout draws the cutmarks--by calling the cutmarks function--and then prints the page using the showpage builtin. cardstep increments the card counter. Then, if the counter is greater than 8, cardstep calls pageout to print the page. It then resets cardno to 0 to prepare for the next page.
The last two functions are front and back. They move to the correct location on the page by indexing into the location arrays. They then print the top value on the stack using the show builtin. The back function calls cardstep to move along to the next position. Thus, the following two lines would print a card:
(Front Side) front (Back Side) back
I said two lines, but the spacing isn't important in PostScript. You would get the same result if this information was on one line. The parenthesis are used to delineate the string that is being placed on the stack.
All of the lines starting with a slash (/) have just-defined functions. The real program starts with the line startit, which calls the startit initialization function. Next, a series of calls to front and back must be entered, followed by a call to pageout to output the last page, if there are any cards on it.
Phil Hughes
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Designing Electronics with Linux | May 22, 2013 |
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
- Designing Electronics with Linux
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Dynamic DNS—an Object Lesson in Problem Solving
- Using Salt Stack and Vagrant for Drupal Development
- New Products
- Why Python?
- Build a Skype Server for Your Home Phone System
- A Topic for Discussion - Open Source Feature-Richness?
- Validate an E-Mail Address with PHP, the Right Way
- Tech Tip: Really Simple HTTP Server with Python
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




55 min 28 sec ago
3 hours 25 min ago
13 hours 27 min ago
17 hours 54 min ago
21 hours 30 min ago
22 hours 3 min ago
1 day 26 min ago
1 day 29 min ago
1 day 31 min ago
1 day 4 hours ago