
Dear Haskell-Cafe list, Since I am learning Haskell, I decided to try to do a real program, to practice and give me some experience. I choose to do a basic typesetting program (like TeX/LaTeX). Now, obviously, such a program needs to manipulate font objects, and in particular, font metrics. Basically, I would like some function like this : stringWidth :: Font -> String -> Double charWidth :: Font -> Char -> Double which take some appropriate font type, string or char, and gives me a width (also height) in some given unit. I'd like it to take into account appropriate kerning. Question 1 : Now, I may be missing something, but a quick search on Google/Hackage didn't yield anything. Is there an existing package, or any nice and simple way to deal with that problem? Question 2 : In case the answer to the previous question is negative, I guess I will need to do it myself, the old-fashioned way. Now, this is where I have a design question. The thing is that font metrics information are encoded into some file (either .tfm or .pl files, for TeX fonts), so my function stringWidth will need to read a file, which is, gasp, an IO operation. Therefore, its type will be something like stringWidth :: Font -> String -> IO Double and it will "infect" pretty much everything else. It doesn't sound really appealing, so I'd like your opinions on this subject. To start the conversation, here are the solutions that I have in mind, so far : 1. well, do nothing, and let IO infect everything. 2. use unsafePerformIO to get rid of IO. (I am weary to do this, since I am a newbie, and I don't really want to start using that function everywhere... However, in this case, it looks kinda legitimate...) 3. Perform a reading of the font metrics file in the main program, put the results into some FontMetrics object, and give that to stringWidth :: FontMetrics -> Font -> String -> Double. Pros : allow me to avoid problems of solution 1 and 2, cons : it doesn't sound right for the main program to have to do this, it should be confined into a Font module. Any other ideas, suggestions? Gery D.

On Tue, Jun 1, 2010 at 10:30 AM, Gery Debongnie
3. Perform a reading of the font metrics file in the main program, put the results into some FontMetrics object, and give that to stringWidth :: FontMetrics -> Font -> String -> Double. Pros : allow me to avoid problems of solution 1 and 2, cons : it doesn't sound right for the main program to have to do this, it should be confined into a Font module.
Ultimately all your IO is driven from main, so don't be afraid to add more IO dependencies to it. You can let IO "infect" a module for dealing with font files (e.g. a FontMetrics module with a function getMetrics :: [String] -> Map String Double), then drive that module from main and feed its results into your pure code. Anthony

Hi Gery There probably isn't a library to help - I've looked at extracting TrueType font metrics myself but abandoned it - TrueType fonts have a very complicated file format, and the spec is inadequate to code an implementation. TeX font metrics are probably simpler but obviously tied to TeX. Reading from file and being in IO is probably not so bad for a TeX like program - as TeX is essentially a 'compiler' a function from Tex to Dvi, i.e. compileFile :: TeX -> Dvi. For any significant compiler you are likely to have the work inside a monad made of a stack of monad transformers, so you can cleanly and fairly trivially add IO as the bottom layer of the monad stack - CompilerM - e.g. compileFile :: TeX -> CompilerM Dvi. Best wishes Stephen

On Jun 1, 2010, at 10:53 , Stephen Tetley wrote:
There probably isn't a library to help - I've looked at extracting TrueType font metrics myself but abandoned it - TrueType fonts have a very complicated file format, and the spec is inadequate to code an
The saner way to do this is to write a binding to freetype2. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Hi Brandon
Even that's not simple - freetype is essentially a framework for
writing font processors rather than a conventional C library[*]. Saner
perhaps is to write a C program using freetype to do the exact job you
have in mind, then bind to your C program.
Best wishes
Stephen
[*} Probably why several people Including me have attempted a binding,
but no-one has delivered one.
On 1 June 2010 17:18, Brandon S. Allbery KF8NH
The saner way to do this is to write a binding to freetype2.

Maybe you could check out the FTGL package for inspiration on using
the freetype as a conventional C library. I was going to try to write
a Hackage package but realised I know nothing about typography and had
to start reading the intro. on Freetype's homepage (which is pretty
good, actually). Maybe I'll try it on the weekend. I needed something
to measure the size in pixels of some text for a given font and point
size, so I used libgd and manually analysed the pixels. It wasn't fast
but it worked perfectly. So, Gery, if you don't really need speed all
that much, that's a quick route to success. Otherwise maybe we could
work on something with the Freetype library.
On 1 June 2010 18:22, Stephen Tetley
Hi Brandon
Even that's not simple - freetype is essentially a framework for writing font processors rather than a conventional C library[*]. Saner perhaps is to write a C program using freetype to do the exact job you have in mind, then bind to your C program.
Best wishes
Stephen
[*} Probably why several people Including me have attempted a binding, but no-one has delivered one.
On 1 June 2010 17:18, Brandon S. Allbery KF8NH
wrote: The saner way to do this is to write a binding to freetype2.
Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (5)
-
Anthony Cowley
-
Brandon S. Allbery KF8NH
-
Christopher Done
-
Gery Debongnie
-
Stephen Tetley