【问题标题】:detect bold and italic support检测粗体和斜体支持
【发布时间】:2013-01-07 12:02:39
【问题描述】:

某些字体不支持 CSS 斜体或粗体(例如 Zapfino 不支持斜体,因为它已经很像脚本了)。我想检测何时不支持字体样式,以便我可以在编辑器中禁用样式按钮。

我尝试了like this

that.checkFontData = function( fontList )
{   var test = $("<span style='font-size:24px;absolute;visibility:hidden;height:auto;width:auto;white-space:nowrap;'>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910</span>");
    $('body').append( test );
    for (var i= 0, iMax = fontList.length; i < iMax; ++i)
    {   test.css( 'fontFamily', fontList[i] );
        var normalWidth = test.outerWidth( true );
        var normalHeight = test.outerHeight( true );
        test.css( 'fontStyle', 'italic' );
        var italicWidth = test.outerWidth( true );
        var italicHeight = test.outerHeight( true );
        test.css( 'fontStyle', 'normal' );
        test.css( 'fontWeight', 'bold' );
        var boldWidth = test.outerWidth( true );
        var boldHeight = test.outerHeight( true );
        console.log( fontList[i]  + ", normal: " + normalWidth + ", bold: " + boldWidth + ", italic: " + italicWidth  );
    }
    test.remove( );
};

但它不起作用...许多提供斜体或粗体的字体报告相同的宽度。

接下来,我想用画布元素来检测这一点,但是,可惜的是,Firefox 甚至不会在画布中呈现斜体文本,所以这个想法搞砸了。

你有什么建议?

【问题讨论】:

  • OCR,如果真的很重要。想不出更好的了
  • 手动检查,然后对结果进行硬编码
  • 拥有像 P1nGu1n 这样的硬编码结果建议将是我认为最好的最合乎逻辑的解决方案。大概您可以控制自己的字体 - 这应该很容易。
  • 我应该看到以下链接 [test ccs][1] [1]:stackoverflow.com/a/2333865/1926761

标签: javascript css


【解决方案1】:

我已经在 jsFiddle 中测试了您的代码,它确实为 GeorgiaArial 等自然网络字体提供了不同的大小,但对于像 Snowburst One (Googlefont) 这样的外部加载字体则没有。

JS fiddle of your script

经过一些研究,我发现对于 @font-face 加载的字体没有 css 字体转换适用。人们加载@font-face 变体并像这样应用它们:

body { font-family:"DroidSerifRegular", Georgia, serif; }
h1 {
    font-family:"DroidSerifBold", Georgia, serif;
    font-weight:normal;
}
em {
    font-family:"DroidSerifItalic", Georgia, serif;
    font-weight:normal;
    font-style:normal;
}
strong em {
    font-family:"DroidSerifBoldItalic", Georgia, serif;
    font-weight:normal;
    font-style:normal;
}

如果您使用的@font-face 字体与上面的示例中一样,您可能会想出某种命名约定。然后,您可以通过检查与后备字体相比的宽度来检查这些字体是否存在。

test.css('fontFamily', 'sans-serif');
var defaultWidth = test.outerWidth( true );

for (var i= 0, iMax = fontList.length; i < iMax; ++i)
{   test.css( 'fontFamily', fontList[i] + ', sans-serif' );

    var normalWidth = test.outerWidth( true );
    var normalHeight = test.outerHeight( true );
    test.css( 'fontFamily', fontList[i] + 'Italic, sans-serif' );
    var italicWidth = test.outerWidth( true );
    var italicHeight = test.outerHeight( true );
    test.css( 'fontFamily', fontList[i] + 'Bold, sans-serif' );
    var boldWidth = test.outerWidth( true );
    var boldHeight = test.outerHeight( true );
    console.log( "default: "+ defaultWidth + ", " fontList[i]  + ", normal: " + normalWidth + ", bold: " + boldWidth + ", italic: " + italicWidth  );
}

如果样式版本的宽度与默认版本相比有所改变,那么它就是“Bingo”!

注意:这不适用于等宽字体,因为所有字符的宽度始终相同。

【讨论】:

  • 在你的jsfiddle中,你只测试Georgia,而不是Arial。尝试用var fontlist = ["Georgia", "Arial"]; 替换第一行,您会看到Arial 的正常和斜体尺寸相同。
  • 我修复了数组的问题。相同的维度是因为加载数组的新项时没有清除样式。我已经更新了我的示例来解决这个问题。
  • 啊,我明白我在哪里感到困惑了。您的 Arial 方法会根据不同的浏览器/操作系统组合提供不同的大小。 Windows Firefox 和 Chrome 报告 Arial Italic 的不同尺寸,但 IE 以及 Linux 上的所有浏览器为 Arial Italic 和 Arial 提供相同的尺寸。所以,它有点碰碰运气……
【解决方案2】:

要检测 bolditalic 支持,您可以将文本转换为图像并进行比较。

方法是:

  1. 创建一个canvas见下文(无需将其附加到 DOM)
  2. canvas中绘制文字
  3. 将画布转换为图像(这里我使用png
  4. 比较图片的base64字符串

关于canvas

接下来,我想用画布元素来检测这一点,但是,可惜的是,Firefox 甚至不会在画布中呈现斜体文本,所以这个想法搞砸了。

某些字体在 Firefox 的画布中没有斜体,因为本机斜体字体不存在。其他浏览器会尝试对字体进行伪斜体化(倾斜)。

View on jsFiddle(此演示还测试了 Google 字体 Snowburst One

function detectBoldItalic(fonts) {
    // Create canvas
    var canvas = document.createElement('canvas');
    canvas.width = 1000;
    canvas.height = 30;
    var context = canvas.getContext("2d");
    var test = {}, results = {};
    // Default
    context.font = "normal 16px a base case font";
    context.fillText("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910", 10, 20);
    var standard = canvas.toDataURL("image/png");
    context.setTransform(1, 0, 0, 1, 0, 0);
    context.clearRect(0, 0, canvas.width, canvas.height);
    // Start test
    for (var i = 0; i < fonts.length; i++) {
        var styles = ["normal", "bold", "italic"];
        test[fonts[i]] = {};
        results[fonts[i]] = {};
        for (var j = 0; j < styles.length; j++) {
            // Draw text in canvas
            context.font = styles[j] + " 16px " + fonts[i];
            context.fillText("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910", 10, 20);
            // Convert canvas to png
            test[fonts[i]][styles[j]] = canvas.toDataURL("image/png");
            // Clear canvas
            context.setTransform(1, 0, 0, 1, 0, 0);
            context.clearRect(0, 0, canvas.width, canvas.height);
        }
        if (test[fonts[i]]["normal"] !== standard) {
            results[fonts[i]]["bold"] = test[fonts[i]]["normal"] !== test[fonts[i]]["bold"] ? true:false; // Support bold
            results[fonts[i]]["italic"] = test[fonts[i]]["normal"] !== test[fonts[i]]["italic"] ? true:false; // Support italic
        } else {
            results[fonts[i]] = false; // Font does not exist
        }
    }
    return results;
}
console.log(detectBoldItalic(["Arial","Zapfino"]));

【讨论】:

  • 我相信没有办法在画布元素上指定font-stretch: condensed。所以我相信没有办法使用你的方法检测对斜体/粗体Arial Narrow字体的支持。尽管有其他优点,但您的答案仍然是最好的 - 特别是因为它能够更精确地区分不同的字体样式。
【解决方案3】:

使用 Font.js,您可以更可靠地访问字体指标以进行计算。 http://pomax.nihongoresources.com/pages/Font.js

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    • 2011-07-18
    • 1970-01-01
    • 2016-01-02
    • 2012-12-10
    • 2012-12-31
    • 2011-06-14
    相关资源
    最近更新 更多