Archive for the 'Ruby' Category

prototype.js and Textware QuickFIND BHO crashes IE

Wednesday, February 14th, 2007

You do hate when you get very obscure error reports from your clients? Atleast I do. Especially those screenshots of the very descriptive Microsoft “This program has encountered error and needs to be closed.”. Why the default crash dialog needs to be so general and all the interesting bits are hidden behind some “click here” link? Normal users usually just take screenshots of the first error dialog they see and assume we would know from that what’s wrong.

This time the problem was that IE was crashing instantly when visiting our web application’s first page. I asked our client to send some screenshots of his IE settings and I google around a bit. I instructed him to disable 3rd party extensions which did solve the problem. Further investigation revealed that the problem was Textware’s QuickFIND BHO which he no doubt gotten from Cambridge Learner’s Dictionary. I could find only one screenshot of this program in action. Looks quite useful application, but definetely very buggy. Unfortunately the Textware company is long gone as well. Their website just points to some very generic site. I doubt we will be getting any updates to QuickFIND.

The problem is the way this IE add-on works. It monitors your mouse movements in IE and displays info about the text your mouse is hovering. For some reason prototype.js makes the plugin to crash and take IE down with it. I really hope we don’t have to try to solve this issue, or are forced to strip prototype.js till it’s working. And to be honest, it would only solve the problems in our website. There are many Web2.0 applications in the web, and especially since Ruby on Rails relies heavily on the prototype.js and includes it by default, these QuickFIND users are going to experience more and more IE crashes. Even IE7 crashes just like that.

If we have to go down the harder road, I will definitely report back my success in debugging prototype.js. Right now, we’re waiting on customer’s opinion and hoping for the best.

I could find only couple of sources of the same problem:
Source 1,
Source 2

Ruby PDF::Writer doing text-transformations and font kerning

Friday, December 1st, 2006

Some time ago I wrote about the PDF::Writer changes to be able to use font embedding properly. I got one inquiry about this, which is cool. I haven’t yet had time to test the PDFs in Mac OSX (I don’t have Mac myself, only two of my colleagues).

However shortly after writing about the font problem and solution for it I needed some text-transformations and they appeared to be really troublesome. Ie. rotate, stretch, skew text or all at the same time. Especially with the in-place transformations got from SVG files. Same for embedded images.

This led me again back to the PDF specifications and I found solution about transformations for the text block itself. PDF::Writer did not support this except for the fixed angle parameter. What I did I extended the angle parameter also to accept 6 element transformation array. Similar transformation array is accepted by the add_image methods.

After I had “fixed” that the text still did not look correct. Adobe Illustrator was still showing the texts to be have less width. Just by accident I noticed the kerning information in Illustrator and I figured PDF::Writer is not really adding kerning to the text for some reason. And it turned out atleast Acrobat does not view text automatically with kerning even if the kerning data is embedded in the font data.

Once again the PDF specifications were the saviour. Solution was to pre-process the text strings into array strings with the kerning data in them prior writing the PDF data block (so modifications on the add_text were needed). Rather simple string processing (although I admit the code doing it might be a bit poorly written as-is) after fixing bug from fontmetrics.rb to get proper kerning data.

That’s about it. Here’s are the changed and added methods:

PDF::Writer.add_text(x, y, text, size = nil, angle = 0, word_space_adjust = 0, char_space_adjust = 0, text_kerning = 1)

I added support for char_space_adjust and text_kerning. Angle can also be transformation matrix which is in-place relative transformation only to the text’s x, y and own size. No more need to “manually” correct x, y for add_text if you just want to rotate the text.

PDF::Writer.kern(text)
Returns PDF string array with text kerning information of the current font. Mostly useful only internally by the add_text. Note that this requires fixes in the fontmetrics.rb (fixes in the package). In short pdf-writer 1.1.3 just has few bugs in the fontmetrics.rb preventing kerning information being loaded properly.

PDF::Writer.add_image(image, x, y, width = nil, height = nil, image_info = nil, link = nil, matrix = nil)
PDF::Writer.add_image_from_file(image, x, y, width = nil, height = nil, link = nil, matrix = nil)

Basically I added same functionality as with add_text in-place transformation matrix. However there’s small catch in this implementation about the corner of the x, y position when adding image. In 1.1.3 the x, y is the position of the bottom, left corner, but in SVG transformations the corner is top, left. It was easier for me to do it this way for the purpose I needed this change.

This time I provide full package of the PDF::Writer. It’s basically 1.1.3 with the changes I made. Most likely the demos won’t work, but I don’t want to bother myself with that ;)

Download: PDF::Writer 1.1.4

Ruby pdf-writer 1.1.3 and embedding fonts

Tuesday, October 17th, 2006

I’ve been working with some interesting stuff with Ruby and PDF generating lately at work. This includes Ruby code reading one standard file format (used ie. for printing invoices by print houses here in Finland) and then converting that file format into similar looking PDF with pdf-writer Ruby library. we already had invoice generating in that file format and those print houses aren’t too good in providing services for PDF invoices if you want to archive or send PDF invoices, so we ended up using the same file and that makes invoice layout maintaining a lot easier.

Only problem with that above is that print houses provide standard and custom made layout templates which contain static graphical elements for the printed pages. Only the content text with few control codes are in the file format itself. Due this I also created small application for reading SVG files with Ruby REXML, converting the SVG files into structured arrays and hashes. From there the application writes it into Ruby code file which contains code lines for reproducing the SVG graphics in PDF with pdf-writer. So it’s sort of svg to pdf-writer rb converter. This static approach was decided for better performance. There’s no point parsing and converting the svg each time we need the static graphical elements.

The SVG converter supports about 70-80% of SVG specifications, which is all the basic stuff including the path curves for more complex graphics. This makes it possible to use other PDF files (when converted into SVG) or Adobe Illustrator (application I use here at work for vector graphics) to create invoice layouts.

Unfortunately I cannot share any of that, even if I wanted to, because that has been made during my work time.

However there’s something I can share to contribute something for all pdf-writer users. That is some help on embedding TrueType/OpenType and Type1 fonts. I had lots of troubles doing that and I did some debugging with Adobe Illustrator written PDF files and other PDF files. I had to dig the pdf-writer source code as well to see what’s going on. Not to mention the requirement for the AFM files. When I got some PDF files out I was just getting the famous “The font contains a bad /BBox” error message and it was so frusturating when the pdf-writer manual was incomplete on this matter.

Today I’m much wiser on those issues. I even had to do some changes for the pdf-writer source code to get the font-embedding to work properly. In addition to the changes I found perfect OpenSource tool called TTF2PT1 for creating the AFM/PFB files of TrueType fonts. There’s also link for downloading Windows binaries, which was great time saver for me.

First apply the patch to your pdf-writer. The patch includes replacements for the two changed files and diff files if you want to use patch instead of just replacing the files. What I changed is how the font files are handled. There even was a syntax error in the pdf-writer preventing the font embedding from working. In addition the TrueType license checking code was not working properly, atleast on the fonts I tried, so I removed that check from the code. Just make sure you’re using fonts which you are allowed to embed into your PDF files.

What the pdf-writer manual did not mention is the fact that the font files need to be renamed to same name as the FontName data in the AFM file. It just does not work unless you do that. Also the select_font() call takes the file name as parameter. My pdf-writer patch fixes select_font() a bit so you don’t have to give the .afm extension of the file name when using select_font(). That was also something the pdf-writer manual decided not to tell us.

The pdf-writer manual does tell that you need the AFM files (the PDF specification requires that information and pdf-writer doesn’t know how to extract this info by itself). You can use the TTF2PT1 program to convert TTF file into pair of AFM and PFB files. pdf-writer does prefer the PFB over TTF file if you have both in the fonts directory. To setup the fonts directories you can use the following code:

PDF::Writer::FONT_PATH << "./fonts"
PDF::Writer::FontMetrics::METRICS_PATH << "./fonts"

I prefer this, so I can have application specific font files. Copy your TTF font file(s) into that directory and use the following command to convert the font into AFM and PFB file pair:

ttf2pt1 -GFA -b -p ttf myfontfile.ttf

The open the AFM file into text editor and see the line starting with “FontName”. Take the font name and rename the 3 files with that name. For example if you had font “SF Movie Poster.ttf” you’d get files “SFMoviePoster.ttf”, “SFMoviePoster.pfb” and “SFMoviePoster.afm” because the AFM file has line “FontName SFMoviePoster”. As far I as I know the FontName should never contain spaces.

Now in pdf-writer you use this font name with select_font() method. For example:

pdf = PDF::Writer.new(:paper => "A4")
pdf.fill_color Color::RGB::Black
pdf.stroke_color Color::RGB::Black
pdf.select_font "SFMoviePoster"
pdf.add_text 10, 200, "Text with embedded font."
pdf.save_as "test.pdf"

And that’s about it. The generated PDF should open in Acrobat Reader without any error messages and the text is written with the given font. Also the font is shown as embedded font in the Acrobat document properties.