Обнаруживать жирную и курсивную поддержку

Некоторые шрифты не поддерживают CSS курсивом или полужирным шрифтом (например, Zapfino не поддерживает курсив, так как он уже выглядит довольно scripty-look). Я хочу определить, когда стиль шрифта не поддерживается, поэтому я могу отключить кнопки стилизации в редакторе.

Я пробовал что-то как это:

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( );
};

но он не работает... многие шрифты, которые предоставляют курсив или полужирный, сообщают о том же ширине.

Далее, я решил обнаружить это с помощью элемента canvas, но, увы, firefox даже не делает курсивный текст в холсте, так что это означает, что эта идея.

Что бы вы предложили?

Ответ 1

Чтобы обнаружить жирный и курсивную поддержку, вы можете преобразовать текст в изображение и сравнить его.

Способ сделать это:

  • создать canvas См. ниже (нет необходимости добавлять его в DOM)
  • нарисуйте текст в canvas
  • преобразовать холст в изображение (здесь я использую png)
  • сравнить строку base64 изображения

Относительно canvas:

Далее, я решил обнаружить это с помощью элемента canvas, но, увы, firefox даже не делает курсивный текст в холсте, так что это означает, что эта идея.

Некоторые шрифты не выделены курсивом в холсте в Firefox, потому что родной курсивный шрифт не существует. Другие браузеры будут пытаться использовать псевдоним (наклон) шрифта.

Просмотр в 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"]));

Ответ 2

Я тестировал ваш код в jsFiddle, и он дает разные размеры для естественных веб-сайтов, таких как Georgia и Arial, но не для внешнего загружаемого шрифта, такого как Snowburst One (Googlefont).

JS скрипт вашего 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  );
}

Если стилизованные версии имеют измененную ширину по сравнению со значением по умолчанию, то это "Бинго"!

Примечание: это не будет работать для моноширинных шрифтов, так как ширина всех символов всегда одинакова.