| // Copyright 2014 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package driver |
| |
| import ( |
| "regexp" |
| "strings" |
| |
| "github.com/google/pprof/third_party/svgpan" |
| ) |
| |
| var ( |
| viewBox = regexp.MustCompile(`<svg\s*width="[^"]+"\s*height="[^"]+"\s*viewBox="[^"]+"`) |
| graphID = regexp.MustCompile(`<g id="graph\d"`) |
| svgClose = regexp.MustCompile(`</svg>`) |
| ) |
| |
| // massageSVG enhances the SVG output from DOT to provide better |
| // panning inside a web browser. It uses the svgpan library, which is |
| // embedded into the svgpan.JSSource variable. |
| func massageSVG(svg string) string { |
| // Work around for dot bug which misses quoting some ampersands, |
| // resulting on unparsable SVG. |
| svg = strings.Replace(svg, "&;", "&;", -1) |
| |
| // Dot's SVG output is |
| // |
| // <svg width="___" height="___" |
| // viewBox="___" xmlns=...> |
| // <g id="graph0" transform="..."> |
| // ... |
| // </g> |
| // </svg> |
| // |
| // Change it to |
| // |
| // <svg width="100%" height="100%" |
| // xmlns=...> |
| |
| // <script type="text/ecmascript"><![CDATA[` ..$(svgpan.JSSource)... `]]></script>` |
| // <g id="viewport" transform="translate(0,0)"> |
| // <g id="graph0" transform="..."> |
| // ... |
| // </g> |
| // </g> |
| // </svg> |
| |
| if loc := viewBox.FindStringIndex(svg); loc != nil { |
| svg = svg[:loc[0]] + |
| `<svg width="100%" height="100%"` + |
| svg[loc[1]:] |
| } |
| |
| if loc := graphID.FindStringIndex(svg); loc != nil { |
| svg = svg[:loc[0]] + |
| `<script type="text/ecmascript"><![CDATA[` + string(svgpan.JSSource) + `]]></script>` + |
| `<g id="viewport" transform="scale(0.5,0.5) translate(0,0)">` + |
| svg[loc[0]:] |
| } |
| |
| if loc := svgClose.FindStringIndex(svg); loc != nil { |
| svg = svg[:loc[0]] + |
| `</g>` + |
| svg[loc[0]:] |
| } |
| |
| return svg |
| } |