SVG-Fonts-0.4 released on Hackage

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:

Example Rendering with Blender


11 Responses to SVG-Fonts-0.4 released on Hackage

  1. If you want a somewhat more efficient triangulation algorithm, you can check out my implementation in Sloth2D:

    The algorithm can actually deal with polygons that contain holes, but there is currently no way to specify such input. Nevertheless, this could be easily changed.

    • tillmannvogt says:

      That is interesting. I have looked quite intensively into triangulation algorithms and chose this one because it works. I deal with holes by cutting them open. I can use your library only if it is on Hackage. It would be also nice to know the names of the inventors of the triangulation algorithm. the fastest practical one is maybe from Seidel.

      • I’m not sure if my algorithm has a name, it’s just a simple sweep-based method, and that’s also why it can deal with holes directly. My implementation doesn’t guarantee O(nlogn) execution time (it could by changing the data structure that keeps track of the open cross sections), but it should be pretty much linear in the typical case like font outlines.

  2. Felipe says:

    The example is b0rked =(.

  3. pr.ranjan says:

    oh wow that is nice…i’m evaluating haskell and would like to know how is the state of svg library in general in haskell

  4. Ivan Miljenovic says:

    Is the do-block for main correct? Should it be a) getting the args from somewhere and b) doing “length args > 0” rather than just “args > 0” (and even then, “null args” makes more sense) ?

    • Ketil says:

      Maybe there’s some weird definition of ‘args’ somewhere? Normally I’d expect ‘args <- getArgs', but… The code in the blog post differs from what I see in Google reader, where both the 'if' and the '<' are missing (but perhaps it was modified?)

    • tillmannvogt says:

      you are right… corrected

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: