|
|
|
|
/*
|
|
|
|
|
** fontface -- Font Preparation for Web usage via CSS @font-face
|
|
|
|
|
** Copyright (c) 2010-2015 Ralf S. Engelschall <rse@engelschall.com>
|
|
|
|
|
** Licensed under GPL <http://www.gnu.org/licenses/gpl.txt>
|
|
|
|
|
** fontface.js: browser workarounds (language: JavaScript/1.5)
|
|
|
|
|
**
|
|
|
|
|
** Background:
|
|
|
|
|
** Opera (even until 11.60, appVersion 9.80) is known
|
|
|
|
|
** to be buggy when it comes to the @font-face rules.
|
|
|
|
|
** The bug is that is does only use the font-family
|
|
|
|
|
** as the unique name and not the combination of
|
|
|
|
|
** font-family+font-style+font-weight+font-stretch+font-variant.
|
|
|
|
|
** Additionally, the CSS3 font-stretch property is also not
|
|
|
|
|
** understood at all.
|
|
|
|
|
**
|
|
|
|
|
** Problem:
|
|
|
|
|
** The last @font-face rule for a particular font-family overrides
|
|
|
|
|
** all previous ones and as a result the wrong fonts are used.
|
|
|
|
|
**
|
|
|
|
|
** Workaround:
|
|
|
|
|
** We walk through all @font-face rules and make copies of
|
|
|
|
|
** them with a font-family property value including the
|
|
|
|
|
** font-weight+font-style+font-stretch+font-variant information.
|
|
|
|
|
** Additionally, we activate these generated @font-face rules
|
|
|
|
|
** and change the style on all DOM elements to those generated
|
|
|
|
|
** @font-face rules.
|
|
|
|
|
**
|
|
|
|
|
** See Also:
|
|
|
|
|
** http://dev.opera.com/articles/view/seven-web-fonts-showcases/
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
(function () {
|
|
|
|
|
var fixme = function () {
|
|
|
|
|
/* 1. determine all @font-face CSS rules, remember
|
|
|
|
|
their font-family attributes (for later substitution)
|
|
|
|
|
and assemble the substitution CSS rules */
|
|
|
|
|
|
|
|
|
|
/* iterate over all stylesheets */
|
|
|
|
|
var css_rules = "";
|
|
|
|
|
var font_families = {};
|
|
|
|
|
for (var i = 0; i < document.styleSheets.length; i++) {
|
|
|
|
|
/* iterate over all stylesheet rules */
|
|
|
|
|
var len = document.styleSheets[i].cssRules.length;
|
|
|
|
|
for (var j = 0; j < len; j++) {
|
|
|
|
|
/* act on @font-face rules only */
|
|
|
|
|
var m;
|
|
|
|
|
var cssText = document.styleSheets[i].cssRules[j].cssText;
|
|
|
|
|
if (m = cssText.match(/^@font-face\s+\{(.+)\}/)) {
|
|
|
|
|
var rules = m[1];
|
|
|
|
|
|
|
|
|
|
/* extract font related rules */
|
|
|
|
|
var font_family = "sans-serif";
|
|
|
|
|
var font_style = "normal";
|
|
|
|
|
var font_weight = "normal";
|
|
|
|
|
var font_stretch = "normal";
|
|
|
|
|
var font_variant = "normal";
|
|
|
|
|
if (m = rules.match(/font-family:\s*("([^""]+)"|'([^'']+)'|([^\s;}]+))/))
|
|
|
|
|
font_family = m[2] || m[3] || m[4];
|
|
|
|
|
if (m = rules.match(/font-style:\s*("([^""]+)"|'([^'']+)'|([^\s;}]+))/))
|
|
|
|
|
font_style = m[2] || m[3] || m[4];
|
|
|
|
|
if (m = rules.match(/font-weight:\s*("([^""]+)"|'([^'']+)'|([^\s;}]+))/))
|
|
|
|
|
font_weight = m[2] || m[3] || m[4];
|
|
|
|
|
if (m = rules.match(/font-stretch:\s*("([^""]+)"|'([^'']+)'|([^\s;}]+))/))
|
|
|
|
|
font_stretch = m[2] || m[3] || m[4];
|
|
|
|
|
if (m = rules.match(/font-variant:\s*("([^""]+)"|'([^'']+)'|([^\s;}]+))/))
|
|
|
|
|
font_variant = m[2] || m[3] || m[4];
|
|
|
|
|
|
|
|
|
|
/* special treatment for oblique style */
|
|
|
|
|
if (font_style == "oblique") {
|
|
|
|
|
font_style = "italic";
|
|
|
|
|
cssText = cssText.replace(/(font-style:\s*)[^\s;}]+/, "$1" + font_style);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* extend the font-family with the style-weight-stretch tag
|
|
|
|
|
and remember the original font-family */
|
|
|
|
|
var tag = font_style + "-" + font_weight + "-" + font_stretch + "-" + font_variant;
|
|
|
|
|
cssText = cssText.replace(/src:\s+url\('.+?\.eot'\);/, "");
|
|
|
|
|
cssText = cssText.replace(/src:\s+url\(.+?\.eot\);/, "");
|
|
|
|
|
cssText = cssText.replace(/url\('\S+?\.(eot|woff)'\) format\(.+?\),/g, "");
|
|
|
|
|
cssText = cssText.replace(/url\(\S+?\.(eot|woff)\) format\(.+?\),/g, "");
|
|
|
|
|
cssText = cssText.replace(/url\('\S+?\.svg#.+?'\) format\(.+?\);/, "");
|
|
|
|
|
cssText = cssText.replace(/url\(\S+?\.svg#.+?\) format\(.+?\);/, "");
|
|
|
|
|
cssText = cssText.replace(/,(\s+font-style:)/, ";$1");
|
|
|
|
|
cssText = cssText.replace(/local\('.+?'\),/g, "");
|
|
|
|
|
cssText = cssText.replace(/local\(.+?\),/g, "");
|
|
|
|
|
cssText = cssText.replace(/(font-family:\s*"[^""]+)(")/, "$1 "+tag+"$2");
|
|
|
|
|
cssText = cssText.replace(/(font-family:\s*'[^'']+)(')/, "$1 "+tag+"$2");
|
|
|
|
|
css_rules += cssText + "\n";
|
|
|
|
|
font_families[font_family] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 2. activate all generated @font-face CSS rules */
|
|
|
|
|
var sheet = document.createElement('style')
|
|
|
|
|
sheet.innerHTML = css_rules;
|
|
|
|
|
document.body.appendChild(sheet);
|
|
|
|
|
|
|
|
|
|
/* 3. walk over all elements in the whole DOM tree
|
|
|
|
|
and substitute font-family rules */
|
|
|
|
|
var walker = document.createTreeWalker(
|
|
|
|
|
document,
|
|
|
|
|
NodeFilter.SHOW_ELEMENT,
|
|
|
|
|
{ acceptNode: function(node) { return NodeFilter.FILTER_ACCEPT; } },
|
|
|
|
|
false
|
|
|
|
|
);
|
|
|
|
|
while (walker.nextNode()) {
|
|
|
|
|
var node = walker.currentNode;
|
|
|
|
|
|
|
|
|
|
/* determine the computed style of an element */
|
|
|
|
|
var style = window.getComputedStyle(node, null);
|
|
|
|
|
var font_family = style.getPropertyValue("font-family") || "sans-serif";
|
|
|
|
|
var font_style = style.getPropertyValue("font-style") || "normal";
|
|
|
|
|
var font_weight = style.getPropertyValue("font-weight") || "normal";
|
|
|
|
|
var font_stretch = style.getPropertyValue("font-stretch") || "normal";
|
|
|
|
|
var font_variant = style.getPropertyValue("font-variant") || "normal";
|
|
|
|
|
|
|
|
|
|
/* font-weight alias canonicalization */
|
|
|
|
|
if (font_weight == "normal") { font_weight = "400"; }
|
|
|
|
|
else if (font_weight == "bold") { font_weight = "700"; }
|
|
|
|
|
|
|
|
|
|
/* act on font-family styled elements for which a @font-face was seen */
|
|
|
|
|
font_family = font_family.replace(/^"(.+)"$/, "$1").replace(/^'(.+)'$/, "$1");
|
|
|
|
|
if (typeof font_families[font_family] !== "undefined" && font_families[font_family]) {
|
|
|
|
|
/* extend the font-family with the style-weight-stretch tag */
|
|
|
|
|
font_family += " " + font_style + "-" + font_weight + "-" + font_stretch + "-" + font_variant;
|
|
|
|
|
|
|
|
|
|
/* apply the font-family (but delay it a little bit to ensure
|
|
|
|
|
that Opera does not stumple over its feet because we are
|
|
|
|
|
currently walking through the elements) */
|
|
|
|
|
(function (el, font_family) {
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
el.style.fontFamily = font_family;
|
|
|
|
|
}, 20);
|
|
|
|
|
})(node, font_family);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* act for Opera only */
|
|
|
|
|
if (window.opera && navigator.userAgent.match(/Opera/)) {
|
|
|
|
|
var m = navigator.userAgent.match(/Version\/(\d+\.\d+)/)
|
|
|
|
|
var version = (m && m[1] ? parseFloat("" + m[1]) : 0.0);
|
|
|
|
|
if (version < 12.00) {
|
|
|
|
|
window.onload = function () {
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
fixme();
|
|
|
|
|
}, 1*1000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|