[Laszlo-checkins] r13642 - openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml

ptw@openlaszlo.org ptw at openlaszlo.org
Thu Apr 9 09:27:48 PDT 2009


Author: ptw
Date: 2009-04-09 09:27:46 -0700 (Thu, 09 Apr 2009)
New Revision: 13642

Modified:
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js
Log:
Change 20090408-ptw-e by ptw at dueling-banjos.home on 2009-04-08 14:03:38 EDT
    in /Users/ptw/OpenLaszlo/trunk-3
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: Reduce calls to LzTextSprite/getTextDimension

Bugs Fixed: LPP-8016 Performance differences between OL 4.0.x and 4.3.x

Technical Reviewer: hminsky (Message-ID: <8c61fad60904090922x488b493fl6ccb0a37aefff1e7 at mail.gmail.com>)
QA Reviewer: mkolenda (pending)

Details:
    Moved the quick cache check into the callers of getTextDimension,
    avoiding the call if the cached value is still valid.

Tests:
    smokecheck
    test/lztest/lztest-textheight.lzx?debug=true&lzr=dhtml&lzt=testboth



Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js	2009-04-09 10:30:06 UTC (rev 13641)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js	2009-04-09 16:27:46 UTC (rev 13642)
@@ -133,6 +133,7 @@
 
 LzTextSprite.prototype.setTextColor = LzSprite.prototype.setColor;
 
+LzTextSprite.prototype.lineHeight = null;
 LzTextSprite.prototype.scrollTop = null;
 LzTextSprite.prototype.scrollHeight = null;
 LzTextSprite.prototype.scrollLeft = null;
@@ -167,9 +168,15 @@
 }
 
 LzTextSprite.prototype.__updatefieldsize = function ( ){
-  var lzv = this.owner;
+  var lineHeight = this.getLineHeight();
   // Validate lineHeight
-  this.__updatelineheight();
+  if (this.lineHeight !== lineHeight) {
+    this.lineHeight = lineHeight;
+    // NOTE [2009-04-08 ptw] We always send lineHeight events, even if
+    // scrollevents are not requested.  scrollevent should probably be
+    // renamed to spriteevent or something
+    this.owner.scrollevent('lineHeight', lineHeight);
+  }
   // Measure the total height of the text, including any clipped
   // (scrollable) text
   // Debug.debug('scrollHeight %d, last char %w', scrolldiv.scrollHeight, scrolldiv['value'] && scrolldiv.value.charAt(scrolldiv.value.length - 1));
@@ -188,19 +195,6 @@
   }
 }
 
-LzTextSprite.prototype.lineHeight = null;
-
-LzTextSprite.prototype.__updatelineheight = function ( ){
-  var lzv = this.owner;
-  var scrolldiv = this.scrolldiv;
-  var lineHeight = this.getTextDimension('lineheight');
-  if (this.lineHeight !== lineHeight) {
-    this.lineHeight = lineHeight;
-    lzv.scrollevent('lineHeight', lineHeight);
-  }
-}
-
-
 LzTextSprite.prototype.setText = function(t, force) {
     // For SWF compatibility, we preserve newlines in text.  We'd
     // like to use pre-line, but that appears not to work for any
@@ -276,17 +270,47 @@
 LzTextSprite.prototype.getTextWidth = function () {
   //Debug.write('LzTextSprite.getTextWidth', this.text, this._textsizecache[this.text]);
   //if (this.text == '') return 0;
-  var w = this.getTextDimension('width');
-  if (w != 0 && this.quirks['emulate_flash_font_metrics']) {
-    w += this.__wpadding;
+  var width;
+  ////
+  // NOTE: Quick cache check, inlined from getTextDimension
+  ////
+  var scrolldiv = this.scrolldiv;
+  var className = scrolldiv.className;
+  var style = scrolldiv.style.cssText;
+  var styleKey = className + "/" + style;
+  var cv = this._cachevalue;
+  if ((this._cacheStyleKey == styleKey) &&
+      (this._cacheTextKey == this.text) &&
+      ('width' in cv)) {
+    width = cv.width;
+  } else {
+    width = this.getTextDimension('width');
   }
-  return w;
+  if (width != 0 && this.quirks['emulate_flash_font_metrics']) {
+    width += this.__wpadding;
+  }
+  return width;
 }
 
-// TODO [2009-02-27 ptw] (LPP-7832) Rename to get LineHeight
-LzTextSprite.prototype.getTextHeight = function () {
+// TODO [2009-02-27 ptw] (LPP-7832) Deprecate getTextHeight
+LzTextSprite.prototype.getTextHeight = LzTextSprite.prototype.getLineHeight = function () {
   // Line height does _not_ include padding
-  return this.getTextDimension('lineheight');
+  ////
+  // NOTE: Quick cache check, inlined from getTextDimension
+  ////
+  var scrolldiv = this.scrolldiv;
+  var className = scrolldiv.className;
+  var style = scrolldiv.style.cssText;
+  var styleKey = className + "/" + style;
+  var cv = this._cachevalue;
+  if ((this._cacheStyleKey == styleKey) &&
+      // lineheight does not depend on the contents
+      ('lineheight' in cv)) {
+    lineheight = cv.lineheight;
+  } else {
+    lineheight = this.getTextDimension('lineheight');
+  }
+  return lineheight;
 }
 
 LzTextSprite.prototype.getTextfieldHeight = function () {
@@ -298,10 +322,24 @@
       // the div to be re-laid out).  Note, the actual text in the
       // scrolldiv may not be eq to this.text because of quirks, but
       // that is what we want to measure.
-      fieldHeight = this.getTextDimension('height');
+      ////
+      // NOTE: Quick cache check, inlined from getTextDimension
+      ////
+      var scrolldiv = this.scrolldiv;
+      var className = scrolldiv.className;
+      var style = scrolldiv.style.cssText;
+      var styleKey = className + "/" + style;
+      var cv = this._cachevalue;
+      if ((this._cacheStyleKey == styleKey) &&
+          (this._cacheTextKey == this.text) &&
+          ('height' in cv)) {
+        fieldHeight = cv.height;
+      } else {
+        fieldHeight = this.getTextDimension('height');
+      }
       if (this.quirks['safari_textarea_subtract_scrollbar_height']) { fieldHeight += 24 };
     } else {
-      fieldHeight = this.getTextDimension('lineheight');
+      fieldHeight = this.getLineHeight();
     }
     if (this.quirks['emulate_flash_font_metrics']) {
       // NOTE [2009-01-29 ptw] You might think you could just read
@@ -320,8 +358,10 @@
 }
 
 // key is the div class plus local style
-LzTextSprite.prototype._cachevalid = null;
-// values are height for the test string or widths for specific strings
+LzTextSprite.prototype._cacheStyleKey = null;
+// key is the text that was measured (only for height and width)
+LzTextSprite.prototype._cacheTextKey = null;
+// height, width, lineheight values corresponding to _cacheStyleKey and _cacheTextKey
 LzTextSprite.prototype._cachevalue = null;
 // We do all our measurement 'off screen'.  For some reason, this
 // seems to work without having to wait for a redisplay.  We are
@@ -350,17 +390,22 @@
         Debug.error("Unknown dimesion: %w", dimension);
       }
   }
-  // Quick check
+  ////
+  // NOTE: Quick check inlined at getTextWidth, getLineHeight,
+  // getTextfieldHeight
+  ////
   var className = scrolldiv.className;
   var style = scrolldiv.style.cssText;
-  var quickKey = className + "/" + style + "{" + string + "}";
+  var styleKey = className + "/" + style;
   var cv = this._cachevalue;
-  if ((this._cachevalid == quickKey &&
-       (dimension in cv))) {
+  if ((this._cacheStyleKey == styleKey) &&
+      (this._cacheTextKey == string) &&
+      (dimension in cv)) {
     return cv[dimension];
   }
-  // Update quick key
-  this._cachevalid = quickKey;
+  // Update quick keys
+  this._cacheStyleKey = styleKey;
+  this._cacheTextKey = string;
   // Now create a cache key limited to the styles that can affect the
   // height/width
   // Turn off `overflow: scroll; width: 100%; height:100%` so that does not interfere with measurements
@@ -372,10 +417,10 @@
            ((sds.lineHeight) ? ("line-height: " + sds.lineHeight + "; ") : "") +
            ((sds.letterSpacing) ? ("letter-spacing: " + sds.letterSpacing + "; ") : "") +
            ((sds.whiteSpace) ? ("white-space: " + sds.whiteSpace + "; ") : ""));
-  var cacheKey = className + "/" + style + "{" + string + "}";
+  var cacheFullKey = className + "/" + style + "{" + string + "}";
   var ltsp = LzTextSprite.prototype;
   var _sizecache = ltsp._sizecache;
-  var cv = this._cachevalue = _sizecache[cacheKey];
+  var cv = this._cachevalue = _sizecache[cacheFullKey];
   if (cv && (dimension in cv)) {
     return cv[dimension];
   }
@@ -393,7 +438,7 @@
     if (root) { root.innerHTML = ''; }
   }
   if (! cv) {
-    cv = this._cachevalue = _sizecache[cacheKey] = {};
+    cv = this._cachevalue = _sizecache[cacheFullKey] = {};
   }
   if (! root) {
     root = document.createElement('div');
@@ -442,7 +487,7 @@
     root.appendChild(mdiv);
   } 
   if (this.quirks.ie_leak_prevention) {
-    ltsp._sizedomcache['lzdiv~~~' + cacheKey] = mdiv;
+    ltsp._sizedomcache['lzdiv~~~' + cacheFullKey] = mdiv;
   }
   // inline to measure width
   mdiv.style.display = 'inline';
@@ -450,7 +495,7 @@
   cv[dimension] = (dimension == 'width') ? mdiv.clientWidth : mdiv.clientHeight;
   mdiv.style.display = 'none';
   LzTextSprite.prototype._sizecache.counter++;
-//   Debug.debug("%w %w %d", this, cacheKey, lineHeight);
+//   Debug.debug("%w %w %d", this, cacheFullKey, lineHeight);
   return cv[dimension];
 }
 



More information about the Laszlo-checkins mailing list