@@ -35,11 +35,11 @@ class SVGSkin extends Skin {
3535 /** @type {Array.<SVGMIPs> } */
3636 this . _scaledMIPs = [ ] ;
3737
38- /** @type {Number } */
38+ /**
39+ * Ratio of the size of the SVG and the max size of the WebGL texture
40+ * @type {Number }
41+ */
3942 this . _maxTextureScale = 1 ;
40-
41- /** @type {Number } */
42- this . _largestTextureScale = 1 ;
4343 }
4444
4545 /**
@@ -54,7 +54,6 @@ class SVGSkin extends Skin {
5454 }
5555 this . _texture = null ;
5656 this . _scaledMIPs . length = 0 ;
57- this . _largestTextureScale = 1 ;
5857 }
5958 super . dispose ( ) ;
6059 }
@@ -80,26 +79,22 @@ class SVGSkin extends Skin {
8079 * Create a MIP for a given scale and pass it a callback for updating
8180 * state when switching between scales and MIPs.
8281 * @param {number } scale - The relative size of the MIP
82+ * @param {function } resetCallback - this is a callback for doing a hard reset
83+ * of MIPs and a reset of the rotation center. Only passed in if the MIP scale is 1.
8384 * @return {SVGMIP } An object that handles creating and updating SVG textures.
8485 */
85- createMIP ( scale ) {
86- const callback = textureData => {
87- if ( scale > this . _largestTextureScale ) {
88- this . _largestTextureScale = scale ;
86+ createMIP ( scale , resetCallback ) {
87+ const textureCallback = textureData => {
88+ // Check if we have the largest MIP
89+ // eslint-disable-next-line no-use-before-define
90+ if ( this . _scaledMIPs [ this . _scaledMIPs . length - 1 ] === mip ) {
8991 // Currently silhouette only gets scaled up
9092 this . _silhouette . update ( textureData ) ;
9193 }
9294
93- if ( scale === 1 ) {
94- const maxDimension = Math . max ( textureData . width , textureData . height ) ;
95- let testScale = 2 ;
96- for ( testScale ; maxDimension * testScale <= MAX_TEXTURE_DIMENSION ; testScale *= 2 ) {
97- this . _maxTextureScale = testScale ;
98- }
99- this . _silhouette . update ( textureData ) ;
100- }
95+ if ( resetCallback ) resetCallback ( ) ;
10196 } ;
102- const mip = new SVGMIP ( this . _renderer , this . _svgRenderer , scale , callback ) ;
97+ const mip = new SVGMIP ( this . _renderer , this . _svgRenderer , scale , textureCallback ) ;
10398
10499 return mip ;
105100 }
@@ -108,7 +103,6 @@ class SVGSkin extends Skin {
108103 * @param {Array<number> } scale - The scaling factors to be used, each in the [0,100] range.
109104 * @return {WebGLTexture } The GL texture representation of this skin when drawing at the given scale.
110105 */
111- // eslint-disable-next-line no-unused-vars
112106 getTexture ( scale ) {
113107 // The texture only ever gets uniform scale. Take the larger of the two axes.
114108 const scaleMax = scale ? Math . max ( Math . abs ( scale [ 0 ] ) , Math . abs ( scale [ 1 ] ) ) : 100 ;
@@ -136,34 +130,44 @@ class SVGSkin extends Skin {
136130 }
137131
138132 /**
139- * Set the contents of this skin to a snapshot of the provided SVG data.
140- * @param {string } svgData - new SVG to use.
133+ * Do a hard reset of the existing MIPs by calling dispose(), setting a new
134+ * scale 1 MIP in this._scaledMIPs, and finally updating the rotationCenter.
135+ * @param {SVGMIPs } mip - An object that handles creating and updating SVG textures.
141136 * @param {Array<number> } [rotationCenter] - Optional rotation center for the SVG. If not supplied, it will be
142137 * calculated from the bounding box
143- * @fires Skin.event:WasAltered
138+ * @fires Skin.event:WasAltered
144139 */
145- setSVG ( svgData , rotationCenter ) {
146- this . _svgRenderer . loadString ( svgData ) ;
140+ resetMIPs ( mip , rotationCenter ) {
141+ this . _scaledMIPs . forEach ( oldMIP => oldMIP . dispose ( ) ) ;
142+ this . _scaledMIPs . length = 0 ;
147143
148- if ( this . _texture ) {
149- this . _texture = this . _scaledMIPs [ INDEX_OFFSET ] ;
150- this . _texture . draw ( ) ;
151-
152- for ( const index in this . _scaledMIPs ) {
153- if ( index !== INDEX_OFFSET ) {
154- this . _scaledMIPs [ index ] . dirty = true ;
155- }
156- }
157- } else {
158- const textureScale = 1 ;
159- this . _texture = this . _scaledMIPs [ INDEX_OFFSET ] = this . createMIP ( textureScale ) ;
160- }
144+ // Set new scale 1 MIP after outdated MIPs have been disposed
145+ this . _texture = this . _scaledMIPs [ INDEX_OFFSET ] = mip ;
161146
162147 if ( typeof rotationCenter === 'undefined' ) rotationCenter = this . calculateRotationCenter ( ) ;
163148 this . setRotationCenter . apply ( this , rotationCenter ) ;
164149 this . emit ( Skin . Events . WasAltered ) ;
165150 }
166151
152+ /**
153+ * Set the contents of this skin to a snapshot of the provided SVG data.
154+ * @param {string } svgData - new SVG to use.
155+ * @param {Array<number> } [rotationCenter] - Optional rotation center for the SVG.
156+ */
157+ setSVG ( svgData , rotationCenter ) {
158+ this . _svgRenderer . loadString ( svgData ) ;
159+
160+ const maxDimension = Math . ceil ( Math . max ( this . size [ 0 ] , this . size [ 1 ] ) ) ;
161+ let testScale = 2 ;
162+ for ( testScale ; maxDimension * testScale <= MAX_TEXTURE_DIMENSION ; testScale *= 2 ) {
163+ this . _maxTextureScale = testScale ;
164+ }
165+
166+ // Create the 1.0 scale MIP at INDEX_OFFSET.
167+ const textureScale = 1 ;
168+ const mip = this . createMIP ( textureScale , ( ) => this . resetMIPs ( mip , rotationCenter ) ) ;
169+ }
170+
167171}
168172
169173module . exports = SVGSkin ;
0 commit comments