June 7, 2011 11 Comments
This library has been laying around in an unusable state on my harddrive for a long time, but now it is finally good enough to be used. In contrast to a lot of graphics libraries on Hackage it is not a binding. That means there were a lot of algorithms that had to be implemented. Although Haskell is often propagated as a language to write correct programs, algorithmic errors are as common as in other languages, because they cannot be catched by the type system. Debug.Trace, debugging with ghci is no alternative because they have no visual output and a list of hundred of floats is not helpful. In the future I plan to have a visual debugger for this.
But it works now. The interface should be easy to integrate into other libraries. Take a look at the following example:
main = do args <- getArgs let str = if null args then "Haskell" else head args resolution = (300, 300) -- mode: INSIDE_V1_V2: the string is inside v1 v2 boundaries (height/length-relation not kept) -- mode: INSIDE_V1: stay inside v1 boundary, size of v2 adjusted to height/length-relation -- mode: INSIDE_V2: stay inside v2 boundary, size of v1 adjusted to height/length-relation mode = INSIDE_V2 -- spacing: MONO: Use mono spacing between glyphs -- HADV: Every glyph has a unique constant horiz. advance -- KERN: Same as HADV but sometimes overridden by kerning: i.e. the horizontal advance -- in "VV" is bigger than in "VA" spacing = HADV gaw = makeOutlMap "../../../src/Test/GirlsareWeird.svg" resolution lin = makeOutlMap "../../../src/Test/LinLibertine.svg" resolution o = (0,0,1.1) -- origin v1 = (5,0,0) -- direction of char-advance v2 = (0,0,-1) -- height direction v3 = (0,0.2,0) -- extrusion f :: String -> [String] -- assigning a property to every character by a unique string f str = replicate (length str) "p" -- data CharProp = Prop (FontData, OutlineMap) String Textured prop :: Map.Map String CharProp prop = Map.fromList [("p", Prop lin "to3d" False)] -- transformation of a Geoemtry Node (i.e. triangulation) transf :: Map.Map String (Geometry -> Geometry) transf = Map.fromList [("to3d", to3d)] -- to3d: not the perfect solution since some points are generated twice to3d geom = ( ((extrude (0,0.1,0)).deleteHoles) geom ) `atop` ( tri (translate (0,0.1,0) geom) ) tri = (triangulate ketTri).deleteHoles tex = makeTexMap resolution prop transf node = displayString str "node" resolution prop transf mode spacing o v1 v2 f tex genCollada (lightedScene node) emptyAnim putStrLn "Collada File generated"
Line 30 shows that a integration into a drawing combinator library seems to be reasonable. I am a little bit proud that this library is lot smaller than freetype2 (something around 100KB against 4000KB)
and the only things that it cannot do (yet!) is Rastered Images, Autohinting, Unicode, and the big amount of file formats supported by freetype2.
Another difference is that the library consists of several small parts that can be used in many other places while a lot of C-libraries tend to be monolithic (like freetype2).
I have to admit that parsing ttf and the other formats is maybe more work then the what has been done so far.
Thanks to the developers of Blender who fixed a bug I described it is possible to load this file into Blender to generate a raytraced picture: