Cache image element in the SVG renderer.

This commit is contained in:
Paul Kaplan
2018-01-17 09:42:20 -05:00
parent 89b5ed32d0
commit 8a04fcd541
2 changed files with 40 additions and 24 deletions

View File

@@ -88,7 +88,6 @@ class SVGSkin extends Skin {
});
}
/** @todo re-render a scaled version if the requested scale is significantly larger than the current render */
return this._texture;
}
@@ -103,7 +102,6 @@ class SVGSkin extends Skin {
this._svgRenderer.fromString(svgData, 1, () => {
const gl = this._renderer.gl;
this._textureScale = this._maxTextureScale = 1;
this._svgRenderer.extraScale = 1;
if (this._texture) {
gl.bindTexture(gl.TEXTURE_2D, this._texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._svgRenderer.canvas);

View File

@@ -38,6 +38,7 @@ class SvgRenderer {
this._canvas = canvas || document.createElement('canvas');
this._context = this._canvas.getContext('2d');
this._measurements = {x: 0, y: 0, width: 0, height: 0};
this._cachedImage = null;
}
/**
@@ -89,6 +90,9 @@ class SvgRenderer {
* @param {string} svgString String of SVG data to draw in quirks-mode.
*/
_loadString (svgString) {
// New svg string invalidates the cached image
this._cachedImage = null;
// Parse string into SVG XML.
const parser = new DOMParser();
this._svgDom = parser.parseFromString(svgString, 'text/xml');
@@ -301,30 +305,44 @@ class SvgRenderer {
* @param {Function} [onFinish] - An optional callback to call when the draw operation is complete.
*/
_draw (scale, onFinish) {
// Convert the SVG text to an Image, and then draw it to the canvas.
if (this._cachedImage) {
this._drawFromImage(scale, onFinish);
} else {
const img = new Image();
img.onload = () => {
this._cachedImage = img;
this._drawFromImage(scale, onFinish);
};
const svgText = this._toString();
img.src = `data:image/svg+xml;utf8,${encodeURIComponent(svgText)}`;
}
}
/**
* Draw to the canvas from a loaded image element.
* @param {number} [scale] - Optionally, also scale the image by this factor (multiplied by `getDrawRatio()`).
* @param {Function} [onFinish] - An optional callback to call when the draw operation is complete.
**/
_drawFromImage (scale, onFinish) {
if (!this._cachedImage) return;
const ratio = this.getDrawRatio() * (Number.isFinite(scale) ? scale : 1);
const bbox = this._measurements;
// Convert the SVG text to an Image, and then draw it to the canvas.
const img = new Image();
img.onload = () => {
// Set up the canvas for drawing.
this._canvas.width = bbox.width * ratio;
this._canvas.height = bbox.height * ratio;
this._context.clearRect(0, 0, this._canvas.width, this._canvas.height);
this._context.scale(ratio, ratio);
this._context.drawImage(img, 0, 0);
// Reset the canvas transform after drawing.
this._context.setTransform(1, 0, 0, 1, 0, 0);
// Set the CSS style of the canvas to the actual measurements.
this._canvas.style.width = bbox.width;
this._canvas.style.height = bbox.height;
// All finished - call the callback if provided.
if (onFinish) {
onFinish();
}
};
const svgText = this._toString();
img.src = `data:image/svg+xml;utf8,${encodeURIComponent(svgText)}`;
this._canvas.width = bbox.width * ratio;
this._canvas.height = bbox.height * ratio;
this._context.clearRect(0, 0, this._canvas.width, this._canvas.height);
this._context.scale(ratio, ratio);
this._context.drawImage(this._cachedImage, 0, 0);
// Reset the canvas transform after drawing.
this._context.setTransform(1, 0, 0, 1, 0, 0);
// Set the CSS style of the canvas to the actual measurements.
this._canvas.style.width = bbox.width;
this._canvas.style.height = bbox.height;
// All finished - call the callback if provided.
if (onFinish) {
onFinish();
}
}
/**