@@ -610,19 +610,18 @@ drawing.makeTester = function() {
610
610
// in a reference frame where it isn't translated and its anchor
611
611
// point is at (0,0)
612
612
// always returns a copy of the bbox, so the caller can modify it safely
613
- var savedBBoxes = [ ] ;
613
+ var savedBBoxes = { } ;
614
+ var savedBBoxesCount = 0 ;
614
615
var maxSavedBBoxes = 10000 ;
615
616
616
617
drawing . bBox = function ( node ) {
617
618
// cache elements we've already measured so we don't have to
618
619
// 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 ) ;
623
623
624
- var tester3 = drawing . tester ;
625
- var tester = tester3 . node ( ) ;
624
+ var tester = drawing . tester . node ( ) ;
626
625
627
626
// copy the node to test into the tester
628
627
var testNode = node . cloneNode ( true ) ;
@@ -654,18 +653,41 @@ drawing.bBox = function(node) {
654
653
// make sure we don't have too many saved boxes,
655
654
// or a long session could overload on memory
656
655
// 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 ;
660
659
}
661
660
662
661
// cache this bbox
663
- node . setAttribute ( 'data-bb' , savedBBoxes . length ) ;
664
- savedBBoxes . push ( bb ) ;
662
+ savedBBoxes [ hash ] = bb ;
663
+ savedBBoxesCount ++ ;
665
664
666
665
return Lib . extendFlat ( { } , bb ) ;
667
666
} ;
668
667
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
+
669
691
/*
670
692
* make a robust clipPath url from a local id
671
693
* note! We'd better not be exporting from a page
0 commit comments