Skip to content

Commit

Permalink
Implemented png export (#4427)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-rifkin authored and mattgodbolt committed Jan 24, 2023
1 parent cfaafa7 commit a827a21
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 7 deletions.
49 changes: 46 additions & 3 deletions static/panes/cfg-view.ts
Expand Up @@ -83,7 +83,8 @@ export class Cfg extends Pane<CfgState> {
graphContainer: HTMLElement;
graphElement: HTMLElement;
infoElement: HTMLElement;
exportButton: JQuery;
exportPNGButton: JQuery;
exportSVGButton: JQuery;
currentPosition: Coordinate = {x: 0, y: 0};
dragging = false;
dragStart: Coordinate = {x: 0, y: 0};
Expand Down Expand Up @@ -156,7 +157,8 @@ export class Cfg extends Pane<CfgState> {
this.graphContainer = this.domRoot.find('.graph-container')[0];
this.graphElement = this.domRoot.find('.graph')[0];
this.infoElement = this.domRoot.find('.cfg-info')[0];
this.exportButton = this.domRoot.find('.export').first();
this.exportPNGButton = this.domRoot.find('.export-png').first();
this.exportSVGButton = this.domRoot.find('.export-svg').first();
}

override registerCallbacks() {
Expand Down Expand Up @@ -201,11 +203,18 @@ export class Cfg extends Pane<CfgState> {
this.state.zoom = MINZOOM;
}
});
this.exportButton.on('click', () => {
this.exportPNGButton.on('click', () => {
this.exportPNG();
});
this.exportSVGButton.on('click', () => {
this.exportSVG();
});
}

async exportPNG() {
fileSaver.saveAs(await this.createPNG(), 'cfg.png');
}

exportSVG() {
fileSaver.saveAs(new Blob([this.createSVG()], {type: 'text/plain;charset=utf-8'}), 'cfg.svg');
}
Expand Down Expand Up @@ -436,6 +445,40 @@ export class Cfg extends Pane<CfgState> {
return doc;
}

async createPNG() {
const svg_blob = new Blob([this.createSVG()], {type: 'image/svg+xml;charset=utf-8'});
const svg_url = URL.createObjectURL(svg_blob);
const image = new Image();
const width = this.layout.getWidth();
const height = this.layout.getHeight();
image.width = width;
image.height = height;
const canvas = await new Promise<HTMLCanvasElement>((resolve, reject) => {
image.onerror = reject;
image.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('Null ctx');
}
ctx.drawImage(image, 0, 0, width, height);
resolve(canvas);
};
image.src = svg_url;
});
return await new Promise<Blob>((resolve, reject) => {
canvas.toBlob(blob => {
if (blob) {
resolve(blob);
} else {
reject(blob);
}
}, 'image/png');
});
}

override resize() {
_.defer(() => {
const topBarHeight = utils.updateAndCalcTopBarHeight(this.domRoot, this.topBar, this.hideable);
Expand Down
15 changes: 11 additions & 4 deletions views/templates/panes/cfg.pug
Expand Up @@ -2,10 +2,17 @@
.top-bar.btn-toolbar.bg-light.cfg-toolbar(role="toolbar")
.btn-group.btn-group-sm(role="group")
select.function-selector
.btn-group.btn-group-sm(role="group" aria-label="Cfg actions")
button.btn.btn-sm.btn-light.export(title="Export graph" aria-label="Export graph as an image")
span.fas.fa-file-arrow-down
span.dp-text.hideable Export
.btn-group.btn-group-sm(role="group" aria-label="CFG Export")
button.btn.btn-sm.btn-light.dropdown-toggle(type="button" title="LLVM Opt Pass Options" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" aria-label="Set output options")
span.fas.fa-arrow-down
span.hideable Export
.dropdown-menu
button.btn.btn-sm.btn-light.dropdown-item.export-png(title="Export graph" aria-label="Export graph as an image")
span.fas.fa-image
span.hideable Export PNG
button.btn.btn-sm.btn-light.dropdown-item.export-svg(title="Export graph" aria-label="Export graph as an image")
span.fas.fa-vector-square
span.hideable Export SVG
.graph-container
span.cfg-info
.graph
Expand Down

0 comments on commit a827a21

Please sign in to comment.