bug 485612. Avoid causing extra non-interruptible reflows the document when zooming to width during page load. r=taras
authorStuart Parmenter <pavlov@pavlov.net>
Thu, 26 Mar 2009 08:38:27 -0700
changeset 65148 b49f9223b34da650d6bcec68d246a537a3b2d7e0
parent 65147 0f69339ffe7213771ba99af4d47ca640288bc4ac
child 65149 3461f4972ed18f9ea3b53800d4936f25965a0146
push idunknown
push userunknown
push dateunknown
reviewerstaras
bugs485612
bug 485612. Avoid causing extra non-interruptible reflows the document when zooming to width during page load. r=taras
mobile/chrome/content/CanvasBrowser.js
--- a/mobile/chrome/content/CanvasBrowser.js
+++ b/mobile/chrome/content/CanvasBrowser.js
@@ -52,35 +52,36 @@ CanvasBrowser.prototype = {
   _zoomLevel: 1,
   _browser: null,
   _pageBounds: null,
   _screenX: 0,
   _screenY: 0,
   _visibleBounds: null,
 
   // during pageload: controls whether we poll document for size changing
-  _maybeZoomToPage: false,
+  _lazyWidthChanged: false,
+  _lazyHeightChanged: false,
 
   // if true, the page is currently loading
   _pageLoading: true,
 
   // 0,0 to contentW, contentH..is a list of dirty rectangles
   _rgnPage: null,
 
   // used to force paints to not be delayed during panning, otherwise things
   // some things seem to get drawn at the wrong offset, not sure why
   _isPanning: false,
 
   // if we have an outstanding paint timeout, its value is stored here
   // for cancelling when we end page loads
   _drawTimeout: 0,
 
-  // the max right/bottom coords we saw from paint events
+  // the max right coordinate we've seen from paint events
   // while we were loading a page.  If we see something that's bigger than
-  // either, we'll trigger a page zoom.
+  // our width, we'll trigger a page zoom.
   _maxRight: 0,
   _maxBottom: 0,
   
   // Tells us to pan to top before first draw 
   _needToPanToTop: false,
 
   get canvasDimensions() {
     if (!this._canvasRect) {
@@ -244,17 +245,18 @@ CanvasBrowser.prototype = {
     this._maxRight = 0;
     this._maxBottom = 0;
     this._pageLoading = true;
     this._needToPanToTop = true;
   },
 
   endLoading: function() {
     this._pageLoading = false;
-    this._maybeZoomToPage = false;
+    this._lazyWidthChanged = false;
+    this._lazyHeightChanged = false;
     this.zoomToPage();
     // flush the region, to reduce startPanning delay
     // and to avoid getting a black border in tab thumbnail
     this.flushRegion();
 
     if (this._drawTimeout) {
       clearTimeout(this._drawTimeout);
       this._drawTimeout = 0;
@@ -392,25 +394,25 @@ CanvasBrowser.prototype = {
     let zeroPageBounds = this._pageBounds.clone();
     zeroPageBounds.left = Math.max(zeroPageBounds.left, 0);
     zeroPageBounds.top = Math.max(zeroPageBounds.top, 0);
 
     // Go through each rect, checking whether it intersects the
     // visible part of the page bounds.  If it doesn't, skip it.
     for each (var rect in rects) {
       if (this._pageLoading)  {
-        // if this rect would push us beyond our known size to the bottom or right,
-        if (rect.bottom > this._maxBottom) {
-          this._maybeZoomToPage = true;
-          this._maxBottom = rect.bottom;
+        // if this rect would push us beyond our known size to the right
+        // (since we zoom to page we don't care about bottom/height)
+        if (rect.right > this._maxRight) {
+          this._lazyWidthChanged = true;
+          this._maxRight = rect.right;
         }
-
-        if (rect.right > this._maxRight) {
-          this._maybeZoomToPage = true;
-          this._maxRight = rect.right;
+        if (rect.bottom > this._maxBottom) {
+          this._lazyHeightChanged = true;
+          this._maxBottom = rect.bottom;
         }
       }
 
       rect = rect.intersect(zeroPageBounds);
 
       if (!rect)
         continue;
 
@@ -423,20 +425,37 @@ CanvasBrowser.prototype = {
 
     // did we end up with anything to do?
     if (realRectCount == 0)
       return;
 
     // a little helper function; we might decide to call it right away,
     // or we might decide to delay it if the page is still loading.
     function resizeAndPaint(self) {
-      if (self._maybeZoomToPage) {
-        self.zoomToPage();
-        self._maybeZoomToPage = false;
+      if (self._lazyWidthChanged) {
+        // XXX rather than calling zoomToPage, which can trigger a browser reflow
+        // just zoom to the max width we've seen so far.
+        // we'll make sure to use the real page's bounds when the page finishes loading
+        // but this should work fine for now.
+        //self.zoomToPage();
+        let contentW = self._maxRight;
+        let [canvasW, ] = self.canvasDimensions;
+
+        if (contentW > canvasW)
+          this.zoomLevel = canvasW / contentW;
+
+        self._lazyWidthChanged = false;
+      } else if (self._lazyHeightChanged) {
+
+        // Setting the zoomLevel will call updateViewportSize.
+        // We need to handle height changes seperately.
+        Browser.updateViewportSize();
+        self._lazyHeightChanged = false;
       }
+
       // draw visible area..freeze during pans
       if (!self._isPanning)
         self.flushRegion(true);
 
       if (self._pageLoading) {
         // kick ourselves off 2s later while we're still loading
         self._drawTimeout = setTimeout(resizeAndPaint, 2000, self);
       } else {
@@ -446,17 +465,17 @@ CanvasBrowser.prototype = {
 
     let flushNow = !this._pageLoading;
 
     // page is loading, and we don't have an existing draw here.  Note that
     // setTimeout is used (and reset in resizeAndPaint)
     if (this._pageLoading && !this._drawTimeout) {
       //always flush the first draw
       flushNow = true;
-      this._maybeZoomToPage = true;
+      this._lazyWidthChanged = true;
       this._drawTimeout = setTimeout(resizeAndPaint, 2000, this);
     }
 
     if (flushNow) {
       resizeAndPaint(this);
     }
   },