@@ -610,19 +610,18 @@ drawing.makeTester = function() {
610610// in a reference frame where it isn't translated and its anchor
611611// point is at (0,0)
612612// always returns a copy of the bbox, so the caller can modify it safely
613- var savedBBoxes = [ ] ;
613+ var savedBBoxes = { } ;
614+ var savedBBoxesCount = 0 ;
614615var maxSavedBBoxes = 10000 ;
615616
616617drawing . bBox = function ( node ) {
617618 // cache elements we've already measured so we don't have to
618619 // remeasure the same thing many times
619- var saveNum = node . attributes [ 'data-bb' ] ;
620- if ( saveNum && saveNum . value ) {
621- return Lib . extendFlat ( { } , savedBBoxes [ saveNum . value ] ) ;
622- }
620+ var hash = nodeHash ( node ) ;
621+ var out = savedBBoxes [ hash ] ;
622+ if ( out ) return Lib . extendFlat ( { } , out ) ;
623623
624- var tester3 = drawing . tester ;
625- var tester = tester3 . node ( ) ;
624+ var tester = drawing . tester . node ( ) ;
626625
627626 // copy the node to test into the tester
628627 var testNode = node . cloneNode ( true ) ;
@@ -654,18 +653,41 @@ drawing.bBox = function(node) {
654653 // make sure we don't have too many saved boxes,
655654 // or a long session could overload on memory
656655 // by saving boxes for long-gone elements
657- if ( savedBBoxes . length >= maxSavedBBoxes ) {
658- d3 . selectAll ( '[data-bb]' ) . attr ( 'data-bb' , null ) ;
659- savedBBoxes = [ ] ;
656+ if ( savedBBoxesCount >= maxSavedBBoxes ) {
657+ savedBBoxes = { } ;
658+ maxSavedBBoxes = 0 ;
660659 }
661660
662661 // cache this bbox
663- node . setAttribute ( 'data-bb' , savedBBoxes . length ) ;
664- savedBBoxes . push ( bb ) ;
662+ savedBBoxes [ hash ] = bb ;
663+ savedBBoxesCount ++ ;
665664
666665 return Lib . extendFlat ( { } , bb ) ;
667666} ;
668667
668+ // capture everything about a node (at least in our usage) that
669+ // impacts its bounding box, given that bBox clears x, y, and transform
670+ // TODO: is this really everything? Is it worth taking only parts of style,
671+ // so we can share across more changes (like colors)? I guess we can't strip
672+ // colors and stuff from inside innerHTML so maybe not worth bothering outside.
673+ // TODO # 2: this can be long, so could take a lot of memory, do we want to
674+ // hash it? But that can be slow...
675+ // extracting this string from a typical element takes ~3 microsec, where
676+ // doing a simple hash ala https://stackoverflow.com/questions/7616461
677+ // adds ~15 microsec (nearly all of this is spent in charCodeAt)
678+ // function hash(s) {
679+ // var h = 0;
680+ // for (var i = 0; i < s.length; i++) {
681+ // h = (((h << 5) - h) + s.charCodeAt(i)) | 0; // codePointAt?
682+ // }
683+ // return h;
684+ // }
685+ function nodeHash ( node ) {
686+ return node . innerHTML +
687+ node . getAttribute ( 'text-anchor' ) +
688+ node . getAttribute ( 'style' ) ;
689+ }
690+
669691/*
670692 * make a robust clipPath url from a local id
671693 * note! We'd better not be exporting from a page
0 commit comments