Bake all path transform attributes into path data instead

HTML

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   viewbox="0 0 100 100"
   id="expandSVG"
   version="1.1"
   inkscape:version="0.91 r13725"
   sodipodi:docname="shrink.svg">
  <metadata
     id="metadata15">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <defs
     id="defs13" />
  <sodipodi:namedview
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1"
     objecttolerance="10"
     gridtolerance="10"
     guidetolerance="10"
     inkscape:pageopacity="0"
     inkscape:pageshadow="2"
     inkscape:window-width="1286"
     inkscape:window-height="713"
     id="namedview11"
     showgrid="false"
     inkscape:zoom="2.36"
     inkscape:cx="50"
     inkscape:cy="50"
     inkscape:window-x="0"
     inkscape:window-y="0"
     inkscape:window-maximized="0"
     inkscape:current-layer="expandSVG" />
  <polygon
     points="75,0 100,0 100,25 90,15 69,37 64,30 84,10 "
     id="polygon3"
     transform="matrix(-1,0,0,-1,164,37)"
     style="fill:#000000" />
  <polygon
     points="75,100 100,100 100,75 90,85 69,63 64,70 84,90 "
     id="polygon5"
     transform="matrix(-1,0,0,-1,164,163)"
     style="fill:#000000" />
  <polygon
     points="25,0 0,0 0,25 10,15 31,37 36,30 16,10 "
     id="polygon7"
     transform="matrix(-1,0,0,-1,36,37)"
     style="fill:#000000" />
  <polygon
     points="25,100 0,100 0,75 10,85 31,63 36,70 16,90 "
     id="polygon9"
     transform="matrix(-1,0,0,-1,36,163)"
     style="fill:#000000" />
</svg>

JavaScript

// Helper tool to piece together Raphael's paths into strings again
Array.prototype.flatten || (Array.prototype.flatten = function() {
  return this.reduce(function(a, b) {
    return a.concat('function' === typeof b.flatten ? b.flatten() : b);
  }, []);
});

// Bake the transforms into all path nodes and remove the transform attributes
var paths = [].slice.call(document.querySelectorAll('path'), 0);
paths.forEach(function bake(p) {
  var before = p.getAttribute('d'), after = applyTransforms(p);
  console.log('before/after path #'+arguments[1]+':\n', before, '\n', after);
  p.setAttribute('d', after);
});
paths.forEach(function removeTransforms(p) {
  do {
    p.removeAttribute('transform');
    p = p.parentNode;
  } while (!/^svg$/i.test(p.nodeName)); // walk to the SVG root, to catch <g>s
});
// done!

// Uses Raphael.path2curve and Raphael.pathToRelative
//
// Calculates a new <path d> attribute relative to a given root (<svg>) element,
// folding in all the transforms into the path data itself so it can move there,
// and get rid of its transform attribute.
function applyTransforms(path, root) {
  function point(x, y) { var p = svg.createSVGPoint(); p.x=x; p.y=y; return p; }

  // add a copy of the path at the same level of the hierarchy to see transforms
  path = path.parentElement.appendChild(path.cloneNode(false));
  // turn all arc commands into splines so we can transform them even with skews
  path.setAttribute('d', path2curve(path));

  var svg    = path.ownerSVGElement
    , normal = (root||svg).getScreenCTM().inverse() // compensation for root
    , matrix = normal.multiply(path.getCTM()) // transform, relative to svg root

    , _      = ''
    , coords = [_, 1, 2] // main and optional handle 1 and 2 coordinates
    , segs   = path.pathSegList
    , len    = segs.numberOfItems
    , x      = { 0: 0, '': 0, 1: 0, 2: 0 }
    , y      = { 0: 0, '': 0, 1: 0, 2: 0 }
    , i      = -1
    , seg, cmd
    ;

  // simplify the logic by normalizing to...