1// Copyright 2014 Google Inc. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package driver 16 17import ( 18 "regexp" 19 "strings" 20 21 "github.com/google/pprof/third_party/svgpan" 22) 23 24var ( 25 viewBox = regexp.MustCompile(`<svg\s*width="[^"]+"\s*height="[^"]+"\s*viewBox="[^"]+"`) 26 graphID = regexp.MustCompile(`<g id="graph\d"`) 27 svgClose = regexp.MustCompile(`</svg>`) 28) 29 30// massageSVG enhances the SVG output from DOT to provide better 31// panning inside a web browser. It uses the svgpan library, which is 32// embedded into the svgpan.JSSource variable. 33func massageSVG(svg string) string { 34 // Work around for dot bug which misses quoting some ampersands, 35 // resulting on unparsable SVG. 36 svg = strings.Replace(svg, "&;", "&;", -1) 37 38 // Dot's SVG output is 39 // 40 // <svg width="___" height="___" 41 // viewBox="___" xmlns=...> 42 // <g id="graph0" transform="..."> 43 // ... 44 // </g> 45 // </svg> 46 // 47 // Change it to 48 // 49 // <svg width="100%" height="100%" 50 // xmlns=...> 51 52 // <script type="text/ecmascript"><![CDATA[` ..$(svgpan.JSSource)... `]]></script>` 53 // <g id="viewport" transform="translate(0,0)"> 54 // <g id="graph0" transform="..."> 55 // ... 56 // </g> 57 // </g> 58 // </svg> 59 60 if loc := viewBox.FindStringIndex(svg); loc != nil { 61 svg = svg[:loc[0]] + 62 `<svg width="100%" height="100%"` + 63 svg[loc[1]:] 64 } 65 66 if loc := graphID.FindStringIndex(svg); loc != nil { 67 svg = svg[:loc[0]] + 68 `<script type="text/ecmascript"><![CDATA[` + svgpan.JSSource + `]]></script>` + 69 `<g id="viewport" transform="scale(0.5,0.5) translate(0,0)">` + 70 svg[loc[0]:] 71 } 72 73 if loc := svgClose.FindStringIndex(svg); loc != nil { 74 svg = svg[:loc[0]] + 75 `</g>` + 76 svg[loc[0]:] 77 } 78 79 return svg 80} 81