From ba2769ce487c0fbd9fd1853fced50f7ac33b1880 Mon Sep 17 00:00:00 2001 From: Dylan Box Date: Fri, 16 Apr 2021 15:52:32 -0400 Subject: [PATCH 1/2] Update: Add custom string for load checking --- src/modules/google/googlefontapi.js | 3 ++- webfontloader.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/google/googlefontapi.js b/src/modules/google/googlefontapi.js index 8f3e5a43..9d0c38fe 100644 --- a/src/modules/google/googlefontapi.js +++ b/src/modules/google/googlefontapi.js @@ -41,6 +41,7 @@ goog.scope(function () { this.configuration_['text'] ); var fontFamilies = this.configuration_['families']; + var fontTestStrings = this.configuration_['text'] fontApiUrlBuilder.setFontFamilies(fontFamilies); var fontApiParser = new FontApiParser(fontFamilies); @@ -48,7 +49,7 @@ goog.scope(function () { domHelper.loadStylesheet(fontApiUrlBuilder.build(), waiter.startWaitingLoad()); waiter.waitWhileNeededThen(function() { - onReady(fontApiParser.getFonts(), fontApiParser.getFontTestStrings(), GoogleFontApi.METRICS_COMPATIBLE_FONTS); + onReady(fontApiParser.getFonts(), fontTestStrings || fontApiParser.getFontTestStrings(), GoogleFontApi.METRICS_COMPATIBLE_FONTS); }); }; }); diff --git a/webfontloader.js b/webfontloader.js index 5590abbb..d8d806d0 100644 --- a/webfontloader.js +++ b/webfontloader.js @@ -15,4 +15,4 @@ function wa(a){if(0==a.a.length)throw Error("No fonts to load!");if(-1!=a.c.inde var za={latin:"BESbswy","latin-ext":"\u00e7\u00f6\u00fc\u011f\u015f",cyrillic:"\u0439\u044f\u0416",greek:"\u03b1\u03b2\u03a3",khmer:"\u1780\u1781\u1782",Hanuman:"\u1780\u1781\u1782"},Aa={thin:"1",extralight:"2","extra-light":"2",ultralight:"2","ultra-light":"2",light:"3",regular:"4",book:"4",medium:"5","semi-bold":"6",semibold:"6","demi-bold":"6",demibold:"6",bold:"7","extra-bold":"8",extrabold:"8","ultra-bold":"8",ultrabold:"8",black:"9",heavy:"9",l:"3",r:"4",b:"7"},Ba={i:"i",italic:"i",n:"n",normal:"n"}, Ca=/^(thin|(?:(?:extra|ultra)-?)?light|regular|book|medium|(?:(?:semi|demi|extra|ultra)-?)?bold|black|heavy|l|r|b|[1-9]00)?(n|i|normal|italic)?$/; function Da(a){for(var b=a.f.length,d=0;d Date: Tue, 27 Apr 2021 13:18:25 -0400 Subject: [PATCH 2/2] Update: Test out every character in test strings --- src/core/fontwatchrunner.js | 116 +++++++++++++++++++++++------------- webfontloader.js | 37 ++++++------ 2 files changed, 92 insertions(+), 61 deletions(-) diff --git a/src/core/fontwatchrunner.js b/src/core/fontwatchrunner.js index c00a696b..5efcbe31 100644 --- a/src/core/fontwatchrunner.js +++ b/src/core/fontwatchrunner.js @@ -25,10 +25,10 @@ webfont.FontWatchRunner = function(activeCallback, inactiveCallback, domHelper, this.metricCompatibleFonts_ = opt_metricCompatibleFonts || null; - this.fontRulerA_ = null; - this.fontRulerB_ = null; - this.lastResortRulerA_ = null; - this.lastResortRulerB_ = null; + this.fontRulersA_ = []; + this.fontRulersB_ = []; + this.lastResortRulersA_ = []; + this.lastResortRulersB_ = []; this.setupRulers_(); }; @@ -90,25 +90,38 @@ goog.scope(function () { * @private */ FontWatchRunner.prototype.setupRulers_ = function() { - this.fontRulerA_ = new FontRuler(this.domHelper_, this.fontTestString_); - this.fontRulerB_ = new FontRuler(this.domHelper_, this.fontTestString_); - this.lastResortRulerA_ = new FontRuler(this.domHelper_, this.fontTestString_); - this.lastResortRulerB_ = new FontRuler(this.domHelper_, this.fontTestString_); + // Make a ruler for each character in the test string + const testChars = this.fontTestString_.split('') - this.fontRulerA_.setFont(new Font(this.font_.getName() + ',' + FontWatchRunner.LastResortFonts.SERIF, this.font_.getVariation())); - this.fontRulerB_.setFont(new Font(this.font_.getName() + ',' + FontWatchRunner.LastResortFonts.SANS_SERIF, this.font_.getVariation())); - this.lastResortRulerA_.setFont(new Font(FontWatchRunner.LastResortFonts.SERIF, this.font_.getVariation())); - this.lastResortRulerB_.setFont(new Font(FontWatchRunner.LastResortFonts.SANS_SERIF, this.font_.getVariation())); - - this.fontRulerA_.insert(); - this.fontRulerB_.insert(); - this.lastResortRulerA_.insert(); - this.lastResortRulerB_.insert(); + this.fontRulersA_ = testChars.map((char) => { + const ruler = new FontRuler(this.domHelper_, char) + ruler.setFont(new Font(this.font_.getName() + ',' + FontWatchRunner.LastResortFonts.SERIF, this.font_.getVariation())); + ruler.insert(); + return ruler + }) + this.fontRulersB_ = testChars.map((char) => { + const ruler = new FontRuler(this.domHelper_, char) + ruler.setFont(new Font(this.font_.getName() + ',' + FontWatchRunner.LastResortFonts.SANS_SERIF, this.font_.getVariation())); + ruler.insert(); + return ruler + }) + this.lastResortRulersA_ = testChars.map((char) => { + const ruler = new FontRuler(this.domHelper_, char) + ruler.setFont(new Font(FontWatchRunner.LastResortFonts.SERIF, this.font_.getVariation())); + ruler.insert(); + return ruler + }) + this.lastResortRulersB_ = testChars.map((char) => { + const ruler = new FontRuler(this.domHelper_, char) + ruler.setFont(new Font(FontWatchRunner.LastResortFonts.SANS_SERIF, this.font_.getVariation())); + ruler.insert(); + return ruler + }) }; FontWatchRunner.prototype.start = function() { - this.lastResortWidths_[FontWatchRunner.LastResortFonts.SERIF] = this.lastResortRulerA_.getWidth(); - this.lastResortWidths_[FontWatchRunner.LastResortFonts.SANS_SERIF] = this.lastResortRulerB_.getWidth(); + this.lastResortWidths_[FontWatchRunner.LastResortFonts.SERIF] = this.lastResortRulersA_.map((ruler) => (ruler.getWidth())); + this.lastResortWidths_[FontWatchRunner.LastResortFonts.SANS_SERIF] = this.lastResortRulersB_.map((ruler) => (ruler.getWidth())); this.started_ = goog.now(); @@ -120,11 +133,12 @@ goog.scope(function () { * * @private * @param {number} width + * @param {number} index The character's index in the test string * @param {string} lastResortFont * @return {boolean} */ - FontWatchRunner.prototype.widthMatches_ = function(width, lastResortFont) { - return width === this.lastResortWidths_[lastResortFont]; + FontWatchRunner.prototype.widthMatches_ = function(width, index, lastResortFont) { + return width === this.lastResortWidths_[lastResortFont][index]; }; /** @@ -134,13 +148,14 @@ goog.scope(function () { * @private * @param {number} a * @param {number} b + * @param {number} index The character's index in the test string * @return {boolean} */ - FontWatchRunner.prototype.widthsMatchLastResortWidths_ = function(a, b) { + FontWatchRunner.prototype.widthsMatchLastResortWidths_ = function(a, b, index) { for (var font in FontWatchRunner.LastResortFonts) { if (FontWatchRunner.LastResortFonts.hasOwnProperty(font)) { - if (this.widthMatches_(a, FontWatchRunner.LastResortFonts[font]) && - this.widthMatches_(b, FontWatchRunner.LastResortFonts[font])) { + if (this.widthMatches_(a, index, FontWatchRunner.LastResortFonts[font]) && + this.widthMatches_(b, index, FontWatchRunner.LastResortFonts[font])) { return true; } } @@ -163,11 +178,12 @@ goog.scope(function () { * @private * @param {number} a * @param {number} b + * @param {number} index The character's index in the test string * @return {boolean} */ - FontWatchRunner.prototype.isFallbackFont_ = function (a, b) { - return this.widthMatches_(a, FontWatchRunner.LastResortFonts.SERIF) && - this.widthMatches_(b, FontWatchRunner.LastResortFonts.SANS_SERIF); + FontWatchRunner.prototype.isFallbackFont_ = function (a, b, index) { + return this.widthMatches_(a, index, FontWatchRunner.LastResortFonts.SERIF) && + this.widthMatches_(b, index, FontWatchRunner.LastResortFonts.SANS_SERIF); }; /** @@ -189,10 +205,11 @@ goog.scope(function () { * @private * @param {number} a * @param {number} b + * @param {number} index The character's index in the test string * @return {boolean} */ - FontWatchRunner.prototype.isLastResortFont_ = function (a, b) { - return FontWatchRunner.hasWebKitFallbackBug() && this.widthsMatchLastResortWidths_(a, b); + FontWatchRunner.prototype.isLastResortFont_ = function (a, b, index) { + return FontWatchRunner.hasWebKitFallbackBug() && this.widthsMatchLastResortWidths_(a, b, index); }; /** @@ -216,21 +233,34 @@ goog.scope(function () { * @private */ FontWatchRunner.prototype.check_ = function() { - var widthA = this.fontRulerA_.getWidth(); - var widthB = this.fontRulerB_.getWidth(); + let isFontLoaded = true + + for (let index = 0; index < this.fontRulersA_.length; index += 1) { + var widthA = this.fontRulersA_[index].getWidth(); + var widthB = this.fontRulersB_[index].getWidth(); - if (this.isFallbackFont_(widthA, widthB) || this.isLastResortFont_(widthA, widthB) || this.isInvalidFont_(widthA, widthB)) { - if (this.hasTimedOut_()) { - if (this.isLastResortFont_(widthA, widthB) && this.isMetricCompatibleFont_()) { - this.finish_(this.activeCallback_); + if (this.isFallbackFont_(widthA, widthB, index) || this.isLastResortFont_(widthA, widthB, index) || this.isInvalidFont_(widthA, widthB)) { + if (this.hasTimedOut_()) { + if (this.isLastResortFont_(widthA, widthB, index) && this.isMetricCompatibleFont_()) { + // Only count as true if none of the previous characters were false + isFontLoaded = isFontLoaded && true + } } else { - this.finish_(this.inactiveCallback_); + // If any character comes back false, it isn't loaded + isFontLoaded = false } - } else { - this.asyncCheck_(); + } else { + // Only count as true if none of the previous characters were false + isFontLoaded = isFontLoaded && true } - } else { + } + + if (isFontLoaded && !this.hasTimedOut_()) { this.finish_(this.activeCallback_); + } else if (this.hasTimedOut_()) { + this.finish_(this.inactiveCallback_); + } else { + this.asyncCheck_(); } }; @@ -251,10 +281,10 @@ goog.scope(function () { // Remove elements and trigger callback (which adds active/inactive class) asynchronously to avoid reflow chain if // several fonts are finished loading right after each other setTimeout(goog.bind(function () { - this.fontRulerA_.remove(); - this.fontRulerB_.remove(); - this.lastResortRulerA_.remove(); - this.lastResortRulerB_.remove(); + this.fontRulersA_.forEach((ruler) => {ruler.remove()}); + this.fontRulersB_.forEach((ruler) => {ruler.remove()}); + this.lastResortRulersA_.forEach((ruler) => {ruler.remove()}); + this.lastResortRulersB_.forEach((ruler) => {ruler.remove()}); callback(this.font_); }, this), 0); }; diff --git a/webfontloader.js b/webfontloader.js index d8d806d0..77512b41 100644 --- a/webfontloader.js +++ b/webfontloader.js @@ -1,18 +1,19 @@ -/* Web Font Loader v1.6.28 - (c) Adobe Systems, Google. License: Apache 2.0 */(function(){function aa(a,b,d){return a.call.apply(a.bind,arguments)}function ba(a,b,d){if(!a)throw Error();if(2=b.f?e():a.fonts.load(fa(b.a),b.h).then(function(a){1<=a.length?c():setTimeout(f,25)},function(){e()})}f()}),e=null,f=new Promise(function(a,c){e=setTimeout(c,b.f)});Promise.race([f,c]).then(function(){e&&(clearTimeout(e),e=null);b.g(b.a)},function(){b.j(b.a)})};function Q(a,b,d,c,e,f,g){this.v=a;this.B=b;this.c=d;this.a=c;this.s=g||"BESbswy";this.f={};this.w=e||3E3;this.u=f||null;this.m=this.j=this.h=this.g=null;this.g=new M(this.c,this.s);this.h=new M(this.c,this.s);this.j=new M(this.c,this.s);this.m=new M(this.c,this.s);a=new G(this.a.c+",serif",J(this.a));a=O(a);this.g.a.style.cssText=a;a=new G(this.a.c+",sans-serif",J(this.a));a=O(a);this.h.a.style.cssText=a;a=new G("serif",J(this.a));a=O(a);this.j.a.style.cssText=a;a=new G("sans-serif",J(this.a));a= -O(a);this.m.a.style.cssText=a;N(this.g);N(this.h);N(this.j);N(this.m)}var R={D:"serif",C:"sans-serif"},S=null;function T(){if(null===S){var a=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent);S=!!a&&(536>parseInt(a[1],10)||536===parseInt(a[1],10)&&11>=parseInt(a[2],10))}return S}Q.prototype.start=function(){this.f.serif=this.j.a.offsetWidth;this.f["sans-serif"]=this.m.a.offsetWidth;this.A=q();U(this)}; -function la(a,b,d){for(var c in R)if(R.hasOwnProperty(c)&&b===a.f[R[c]]&&d===a.f[R[c]])return!0;return!1}function U(a){var b=a.g.a.offsetWidth,d=a.h.a.offsetWidth,c;(c=b===a.f.serif&&d===a.f["sans-serif"])||(c=T()&&la(a,b,d));c||(c=[2410,2411,2412],c=-1!==c.indexOf(b)||-1!==c.indexOf(d));c?q()-a.A>=a.w?T()&&la(a,b,d)&&(null===a.u||a.u.hasOwnProperty(a.a.c))?V(a,a.v):V(a,a.B):ma(a):V(a,a.v)}function ma(a){setTimeout(p(function(){U(this)},a),50)} -function V(a,b){setTimeout(p(function(){v(this.g.a);v(this.h.a);v(this.j.a);v(this.m.a);b(this.a)},a),0)};function W(a,b,d){this.c=a;this.a=b;this.f=0;this.m=this.j=!1;this.s=d}var X=null;W.prototype.g=function(a){var b=this.a;b.g&&w(b.f,[b.a.c("wf",a.c,J(a).toString(),"active")],[b.a.c("wf",a.c,J(a).toString(),"loading"),b.a.c("wf",a.c,J(a).toString(),"inactive")]);K(b,"fontactive",a);this.m=!0;na(this)}; -W.prototype.h=function(a){var b=this.a;if(b.g){var d=y(b.f,b.a.c("wf",a.c,J(a).toString(),"active")),c=[],e=[b.a.c("wf",a.c,J(a).toString(),"loading")];d||c.push(b.a.c("wf",a.c,J(a).toString(),"inactive"));w(b.f,c,e)}K(b,"fontinactive",a);na(this)};function na(a){0==--a.f&&a.j&&(a.m?(a=a.a,a.g&&w(a.f,[a.a.c("wf","active")],[a.a.c("wf","loading"),a.a.c("wf","inactive")]),K(a,"active")):L(a.a))};function oa(a){this.j=a;this.a=new ja;this.h=0;this.f=this.g=!0}oa.prototype.load=function(a){this.c=new ca(this.j,a.context||this.j);this.g=!1!==a.events;this.f=!1!==a.classes;pa(this,new ha(this.c,a),a)}; -function qa(a,b,d,c,e){var f=0==--a.h;(a.f||a.g)&&setTimeout(function(){var a=e||null,m=c||null||{};if(0===d.length&&f)L(b.a);else{b.f+=d.length;f&&(b.j=f);var h,l=[];for(h=0;h=b.f?e():a.fonts.load(fa(b.c),b.h).then(function(a){1<=a.length?c():setTimeout(f,25)},function(){e()})}f()}),e=null,f=new Promise(function(a,d){e=setTimeout(d,b.f)});Promise.race([f,c]).then(function(){e&&(clearTimeout(e),e=null);b.g(b.c)},function(){b.j(b.c)})};function P(a,b,d,c,e,f,g){this.A=a;this.C=b;this.a=d;this.c=c;this.B=g||"BESbswy";this.f={};this.v=e||3E3;this.u=f||null;this.g=[];this.h=[];this.j=[];this.s=[];la(this)}var Q={F:"serif",D:"sans-serif"},R=null;function S(){if(null===R){var a=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent);R=!!a&&(536>parseInt(a[1],10)||536===parseInt(a[1],10)&&11>=parseInt(a[2],10))}return R} +function la(a){var b=a.B.split("");a.g=b.map(function(b){b=new L(a.a,b);var c=new F(a.c.a+",serif",I(a.c)),c=N(c);b.m.style.cssText=c;M(b);return b});a.h=b.map(function(b){b=new L(a.a,b);var c=new F(a.c.a+",sans-serif",I(a.c)),c=N(c);b.m.style.cssText=c;M(b);return b});a.j=b.map(function(b){b=new L(a.a,b);var c=new F("serif",I(a.c)),c=N(c);b.m.style.cssText=c;M(b);return b});a.s=b.map(function(b){b=new L(a.a,b);var c=new F("sans-serif",I(a.c)),c=N(c);b.m.style.cssText=c;M(b);return b})} +P.prototype.start=function(){this.f.serif=this.j.map(function(a){return a.m.offsetWidth});this.f["sans-serif"]=this.s.map(function(a){return a.m.offsetWidth});this.w=q();T(this)};function U(a,b,d,c){for(var e in Q)if(Q.hasOwnProperty(e)&&b===a.f[Q[e]][c]&&d===a.f[Q[e]][c])return!0;return!1}function V(a){return q()-a.w>=a.v} +function T(a){for(var b=!0,d=0;d