anchor.diff:                  match str with
                       | "black" -> Some C4f.Black
                       | "white" -> Some C4f.White
  +                    | "red" -> Some C4f.Red
  +                    | "green" -> Some C4f.Green
  +                    | "blue" -> Some C4f.Blue
                       | "none" -> Some (C4f(0.0, 0.0, 0.0, 0.0))
                       | _ ->
                           None
  +
  +
  +        let private whiteSpaceRx = System.Text.RegularExpressions.Regex @"[ \t\r\n]+"
  +        let private functionRx = System.Text.RegularExpressions.Regex @"(?<name>[a-zA-Z_]+)\((?<args>.*)\)"
  +        let private parseTrafo (str : string) : Option<M33d> =
  +            let str = whiteSpaceRx.Replace(str, "")
  +            let mutable m = functionRx.Match str
  +            let mutable trafo = M33d.Identity
  +            while m.Success do
  +                let f = m.Groups.["name"].Value
  +                let args = m.Groups.["args"].Value.Split(',') |> Array.map float
  +
  +                let mat = 
  +                    match f.ToLower() with
  +                        | "matrix" -> 
  +                            if args.Length >= 6 then
  +                                M33d(args.[0], args.[1], args.[2], args.[3], args.[4], args.[5], 0.0, 0.0, 1.0)
  +                            else
  +                                Log.warn "invalid matrix command: %A" m.Value
  +                                M33d.Identity
  +                        | "translate" ->
  +                            match args with
  +                                | [|x; y|] -> M33d.Translation(x,y)
  +                                | [|x|] -> M33d.Translation(x,0.0)
  +                                | _ ->
  +                                    Log.warn "invalid translate command: %A" m.Value
  +                                    M33d.Identity
  +                        | "scale" ->
  +                            match args with
  +                                | [|x; y|] -> M33d.Scale(x,y)
  +                                | [|x|] -> M33d.Scale(x)
  +                                | _ ->
  +                                    Log.warn "invalid scale command: %A" m.Value
  +                                    M33d.Identity
  +
  +                        | "rotate" ->
  +                            match args with
  +                                | [| angle |] -> 
  +                                    M33d.Rotation(-Constant.RadiansPerDegree * angle)
  +                                | [| angle; cx; cy|] ->
  +                                    let rot = M33d.Rotation(-Constant.RadiansPerDegree * angle)
  +                                    M33d.Translation(cx, cy) * rot * M33d.Translation(-cx, -cy)
  +                                | _ -> 
  +                                    Log.warn "invalid rotate command: %A" m.Value
  +                                    M33d.Identity
  +
  +                        | "skewx" ->
  +                            if args.Length > 0 then
  +                                M33d(1.0, tan (Constant.RadiansPerDegree * args.[0]), 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
  +                            else
  +                                Log.warn "invalid skewX command: %A" m.Value
  +                                M33d.Identity
  +
  +                        | "skewy" ->
  +                            if args.Length > 0 then
  +                                M33d(1.0, 0.0, 0.0, tan (Constant.RadiansPerDegree * args.[0]), 1.0, 0.0, 0.0, 0.0, 1.0)
  +                            else
  +                                Log.warn "invalid skewX command: %A" m.Value
  +                                M33d.Identity
  +                        | _ ->
  +                            Log.warn "unknown command: %A" m.Value
  +                            M33d.Identity
  +
  +                trafo <- mat * trafo
  +                m <- m.NextMatch()
  +            
  +
  +            if trafo.IsIdentity(Constant.PositiveTinyValue) then
  +                None
  +            else
  +                Some trafo
  +
   
   
           let private readers =
  
positive.code:                 | "path" ->
                      
                      let segments = n |> tryReadAttribute "d" |> withDefault ""
                      let width = n |> tryReadAttribute "stroke-width"
  
    
                      segments 
                          |> PathParser.parse
                          |> Primitive.Path
                          |> renderPrimitive
                          |> maybeApp Nvg.strokeWidth width
  
  
                  | "polyline" ->
                      let points = n |> tryReadAttribute "points" |> withDefault ""
                      let width = n |> tryReadAttribute "stroke-width"
  
                      let readPoint (str : string) =
                          let arr = str.Split ','
  
negative.code:                         commands 
                              |> Primitive.Path
                              |> renderPrimitive
                      else
                          Nvg.empty
  
                  | "polygon" ->
                      let points = n |> tryReadAttribute "points" |> withDefault ""
  
                      let readPoint (str : string) =
                          let arr = str.Split ','
  