Piotr Szmyd
Piotr Szmyd

Reputation: 13366

Make Adobe fonts work with CSS3 @font-face in IE9

I'm in the process of building a small intranet application and try, with no luck, to use Adobe font I purchased lately. As I was informed, in our case it's not a license violation.

I converted the .ttf/.otf versions of font to .woff, .eot and .svg, so to target all major browsers. The @font-face syntax I used is basically the bulletproof one from Font Spring:

@font-face {
    font-family: 'MyFontFamily';
    src: url('myfont-webfont.eot');
    src: url('myfont-webfont.eot?#iehack') format('eot'), 
         url('myfont-webfont.woff') format('woff'), 
         url('myfont-webfont.ttf')  format('truetype'),
         url('myfont-webfont.svg#svgFontName') format('svg');
    }

I modified the HTTP headers (added Access-Control-Allow-Origin = "*") to allow cross-domain references. In FF and Chrome it works perfectly, but in IE9 I get:

CSS3111: @font-face encountered unknown error.  
myfont-webfont.woff
CSS3114: @font-face failed OpenType embedding permission check. Permission must be Installable. 
myfont-webfont.ttf

I noticed that when converting font from .ttf/.otf to .woff I also get an .afm file, but I don't have a clue whether it's important or not...

Any ideas how to work it out?

[Edit] - I host my websites (fonts too, but under separate directory and subdomain for static content) under IIS 7.5

Upvotes: 135

Views: 102230

Answers (19)

Mikhail Razgovorov
Mikhail Razgovorov

Reputation: 159

If you want to do this with a Python script instead of having to run C / PHP code, here's a Python3 function that you can use to remove the embedding permissions from the font:

def convert_restricted_font(filename):
with open(filename, 'rb+') as font:

    font.read(12)
    while True:
        _type = font.read(4)
        if not _type:
            raise Exception('Could not read the table definitions of the font.')
        try:
            _type = _type.decode()
        except UnicodeDecodeError:
            pass
        except Exception as err:
            pass
        if _type != 'OS/2':
            continue
        loc = font.tell()
        font.read(4)
        os2_table_pointer = int.from_bytes(font.read(4), byteorder='big')
        length = int.from_bytes(font.read(4), byteorder='big')
        font.seek(os2_table_pointer + 8)

        fs_type = int.from_bytes(font.read(2), byteorder='big')
        print(f'Installable Embedding: {fs_type == 0}')
        print(f'Restricted License: {fs_type & 2}')
        print(f'Preview & Print: {fs_type & 4}')
        print(f'Editable Embedding: {fs_type & 8}')

        print(f'No subsetting: {fs_type & 256}')
        print(f'Bitmap embedding only: {fs_type & 512}')

        font.seek(font.tell()-2)
        installable_embedding = 0 # True
        font.write(installable_embedding.to_bytes(2, 'big'))
        font.seek(os2_table_pointer)
        checksum = 0
        for i in range(length):
            checksum += ord(font.read(1))
        font.seek(loc)
        font.write(checksum.to_bytes(4, 'big'))
        break


if __name__ == '__main__':
    convert_restricted_font("19700-webfont.ttf")

it works, but I ended up solving the problem of loading fonts in IE by https like this this

thanks NobleUplift

Original source in C can be found here.

Upvotes: 0

Alena Kastsiukavets
Alena Kastsiukavets

Reputation: 812

This works for me:

@font-face {
  font-family: FontName;
  src: url('@{path-fonts}/FontName.eot?akitpd');
  src: url('@{path-fonts}/FontName.eot?akitpd#iefix') format('embedded-opentype'),
    url('@{path-fonts}/FontName.ttf?akitpd') format('truetype'),
    url('@{path-fonts}/FontName.woff?akitpd') format('woff'),
    url('@{path-fonts}/FontName.svg?akitpd#salvage') format('svg');
}

Upvotes: 0

bwigs
bwigs

Reputation: 96

I recently encountered this issue with .eot and .otf fonts producing the CSS3114 and CSS3111 errors in the console when loading. The solution that worked for me was to use only .woff and .woff2 formats with a .ttf format fallback. The .woff formats will be used before .ttf in most browsers and don't seem to trigger the font embedding permissions issue (css3114) and the font naming incorrect format issue (css3111). I found my solution in this extremely helpful article about the CSS3111 and CSS3114 issue, and also reading this article on using @font-face.

note: This solution does not require re-compiling, converting or editing any font files. It is a css-only solution. The font I tested with did have .eot, .otf, .woff, .woff2 and .svg versions generated for it, probably from the original .ttf source which did produce the 3114 error when i tried it, however the .woff and .woff2 files seemed to be immune to this issue.

This is what DID work for me with @font-face:

@font-face {
  font-family: "Your Font Name";
  font-weight: normal;
  src: url('your-font-name.woff2') format('woff2'),
       url('your-font-name.woff') format('woff'),
       url('your-font-name.ttf')  format('truetype');
}

This was what triggered the errors with @font-face in IE:

@font-face {
  font-family: 'Your Font Name';
  src: url('your-font-name.eot');
  src: url('your-font-name.eot?#iefix') format('embedded-opentype'),
       url('your-font-name.woff2') format('woff2'),
       url('your-font-name.woff') format('woff'),
       url('your-font-name.ttf')  format('truetype'),
       url('your-font-name.svg#svgFontName') format('svg');
}

Upvotes: 0

Mark O'Russa
Mark O'Russa

Reputation: 21

I tried the ttfpatch tool and it didn't work form me. Internet Exploder 9 and 10 still complained.

I found this nice Git gist and it solved my issues. https://gist.github.com/stefanmaric/a5043c0998d9fc35483d

Just copy and paste the code in your css.

Upvotes: 0

user22600
user22600

Reputation: 563

As Knu said, you can use this tool, however it's compiled only for MS-DOS. I compiled it for Win64. Download.

Usage:

  1. Place the .exe in the same folder as the font you need to modify

  2. Navigate to that directory in the command line

  3. type embed fontname.fonttype, replacing fontname with the filename and fonttype with the extension i.e. embed brokenFont.ttf

  4. All done! Your font should now work.

Upvotes: 39

Patrick Knott
Patrick Knott

Reputation: 1817

A Different Answer: Legal issues.

There's a couple of things to note before you do this. First, to get this error, in IE, inspect element, switch your tabs, and look for the errors, I believe "CSS3114" appears in the console.

What you need to understand is this is a licensing issue. I.E. (pun intended) if you are trying to load a font that causes this error, you don't have permissions on the file to use the font, and if you don't have permission, it is highly likely that you may lose a legal battle (which itself is highly unlikely) over using this font in this manner unless you are holding the license. So, you can, for the first time, thank IE for being the only browser to tell you "no", because it at least lets you know that you are doing something questionable.

That said, here is your answer:

First ensure you're using the best code in .css, see some of the other css answers for that.
IE 11 css example (works in all modern browsers may need to be tweaked for IE9):

@font-face {
font-family: "QuestionableLegalFont";
font-weight: bold;
src: url('../fonts/QuestionableLegalFont.ttf') format('truetype');
}

Then, ensure you have a working web-font (you probably already know this by seeing your font in other browsers). If you need an online font converter, check here: https://onlinefontconverter.com/

Finally, To get rid of the "CSS3114" error. For an online tool, click here: https://www.andrebacklund.com/fontfixer.html

Upvotes: 8

Knu
Knu

Reputation: 15136

I can only explain you how to fix the "CSS3114" error.
You have to change the embedding level of your TTF file.

Using the appropriate tool you can set it to installable embedding allowed.
For a 64-bit version, check @user22600's answer.

Upvotes: 98

shisaq
shisaq

Reputation: 63

I found eot file should be put beyond ttf. If it's under ttf, thought the font shows correctly, IE9 will still throw an error.

Recommend:

@font-face {
  font-family: 'Font-Name';
  src: url('../fonts/Font-Name.eot?#iefix') format('embedded-opentype');
  src: url('../fonts/Font-Name.ttf')  format('truetype');
}

Not Recommend:

@font-face {
  font-family: 'Font-Name';
  src: url('../fonts/Font-Name.ttf')  format('truetype');
  src: url('../fonts/Font-Name.eot?#iefix') format('embedded-opentype');
  }

Upvotes: 0

bendytree
bendytree

Reputation: 13589

If you are familiar with nodejs/npm, ttembed-js is an easy way to set the "installable embedding allowed" flag on a TTF font. This will modify the specified .ttf file:

npm install -g ttembed-js

ttembed-js somefont.ttf

Upvotes: 4

NobleUplift
NobleUplift

Reputation: 6005

If you want to do this with a PHP script instead of having to run C code (or you're on a Mac like me and you can't be arsed compiling with Xcode only to wait a year for it to open), here's a PHP function that you can use to remove the embedding permissions from the font:

function convertRestrictedFont($filename) {
    $font = fopen($filename,'r+');
    if ($font === false) {
        throw new Exception('Could not open font file.');
    }

    fseek($font, 12, 0);

    while (!feof($font)) {
        $type = '';
        for ($i = 0; $i < 4; $i++) {
            $type .= fgetc($font);
            if (feof($font)) {
                fclose($font);
                throw new Exception('Could not read the table definitions of the font.');
            }
        }
        if ($type == 'OS/2') {
            // Save the location of the table definition
            // containing the checksum and pointer to the data
            $os2TableDefinition = ftell($font);
            $checksum = 0;

            for ($i = 0; $i < 4; $i++) {
                fgetc($font);
                if (feof($font)) {
                    fclose($font);
                    throw new Exception('Could not read the OS/2 table header of the font.');
                }
            }

            // Get the pointer to the OS/2 table data
            $os2TablePointer = ord(fgetc($font)) << 24;
            $os2TablePointer |= ord(fgetc($font)) << 16;
            $os2TablePointer |= ord(fgetc($font)) << 8;
            $os2TablePointer |= ord(fgetc($font));

            $length = ord(fgetc($font)) << 24;
            $length |= ord(fgetc($font)) << 16;
            $length |= ord(fgetc($font)) << 8;
            $length |= ord(fgetc($font));

            if (fseek($font, $os2TablePointer + 8, 0) !== 0) {
                fclose($font);
                throw new Exception('Could not read the embeddable type of the font.');
            }

            // Read the fsType before overriding it
            $fsType = ord(fgetc($font)) << 8;
            $fsType |= ord(fgetc($font));

            error_log('Installable Embedding: ' . ($fsType == 0));
            error_log('Reserved: ' . ($fsType & 1));
            error_log('Restricted License: ' . ($fsType & 2));
            error_log('Preview & Print: ' . ($fsType & 4));
            error_log('Editable Embedding: ' . ($fsType & 8));
            error_log('Reserved: ' . ($fsType & 16)); 
            error_log('Reserved: ' . ($fsType & 32));
            error_log('Reserved: ' . ($fsType & 64));
            error_log('Reserved: ' . ($fsType & 128));
            error_log('No subsetting: ' . ($fsType & 256));
            error_log('Bitmap embedding only: ' . ($fsType & 512));                         
            error_log('Reserved: ' . ($fsType & 1024));
            error_log('Reserved: ' . ($fsType & 2048));
            error_log('Reserved: ' . ($fsType & 4096));
            error_log('Reserved: ' . ($fsType & 8192));
            error_log('Reserved: ' . ($fsType & 16384));
            error_log('Reserved: ' . ($fsType & 32768));

            fseek($font, ftell($font) - 2);

            // Set the two bytes of fsType to 0
            fputs($font, chr(0), 1);
            fputs($font, chr(0), 1);

            // Go to the beginning of the OS/2 table data
            fseek($font, $os2TablePointer, 0);

            // Generate a new checksum based on the changed 
            for ($i = 0; $i < $length; $i++) {
                $checksum += ord(fgetc($font));
            }
            fseek($font, $os2TableDefinition, 0);
            fputs($font, chr($checksum >> 24), 1);
            fputs($font, chr(255 & ($checksum >> 16)), 1);
            fputs($font, chr(255 & ($checksum >> 8)), 1);
            fputs($font, chr(255 & $checksum), 1);

            fclose($font);

            return true;
        }
        for ($i = 0; $i < 12; $i++) {
            fgetc($font);
            if (feof($font)) {
                fclose($font);
                throw new Exception('Could not skip a table definition of the font.');
            }
        }
    }

    fclose($font);

    return false;
}

Make sure to backup your font file before running this code and don't blame me if it corrupts.

Original source in C can be found here.

Upvotes: 3

Stack Developer
Stack Developer

Reputation: 133

I wasted a lot of time because of this issue. Finally I found great solution myself. Before I was using .ttf font only. But I added one extra font format .eot that started to work in IE.

I used following code and it worked like charm in all browsers.

@font-face {
font-family: OpenSans;
src: url(assets/fonts/OpenSans/OpenSans-Regular.ttf), 
url(assets/fonts/OpenSans/OpenSans-Regular.eot);
}

@font-face {
font-family: OpenSans Bold;
src: url(assets/fonts/OpenSans/OpenSans-Bold.ttf),
url(assets/fonts/OpenSans/OpenSans-Bold.eot);
}

I hope this will help someone.

Upvotes: 7

Wajid Ali Siddiqui
Wajid Ali Siddiqui

Reputation: 1

You can solve it by following code

@font-face {
  font-family: 'Font-Name';
  src: url('../fonts/Font-Name.ttf');
  src: url('../fonts/Font-Name.eot?#iefix') format('embedded-opentype');
}

Upvotes: 0

buijs
buijs

Reputation: 43

As a Mac user, I was unable to use the MS-DOS and Windows command line tools that were mentioned to fix the font embedding permission. However, I found out that you can fix this using FontLab to set the permission to 'Everything is allowed'. I hope this recipe on how to set the font permission to Installable on Mac OS X is useful for others as well.

Upvotes: 4

Christian
Christian

Reputation: 69

For everyone who gets the error: "tableversion must be 0, 1 or and is hex:003" when using ttfpatch, i've compiled embed for 64bit. I have not changed anything, just added need libs and compiled. Use at own risk.

Usage: ConsoleApplication1 font.ttf

http://www.mediafire.com/download/8x1px8aqq18lcx8/ConsoleApplication1.exe

Upvotes: 2

Dan
Dan

Reputation: 91

Try this, add this lines in the web.config.

<system.webServer>
  <staticContent>
     <mimeMap fileExtension=".woff" mimeType="application/octet-stream" />
  </staticContent>
</system.webServer>

Upvotes: 9

Renjith
Renjith

Reputation: 129

I was getting the following error:

CSS3114: @font-face failed OpenType embedding permission check. Permission must be Installable.
fontname.ttf

After using the below code my issue got resolved....

src: url('fontname.ttf') format('embedded-opentype')

Thank you guys for helping me!
Cheers,
Renjith.

Upvotes: 12

stefannh
stefannh

Reputation: 391

You should set the format of the ie font to 'embedded-opentype' and not 'eot'. For example:

src: url('fontname.eot?#iefix') format('embedded-opentype')

Upvotes: 33

Font Squirrel
Font Squirrel

Reputation: 1571

It is true that IE9 requires TTF fonts to have the embedding bits set to Installable. The Generator does this automatically, but we are currently blocking Adobe fonts for other reasons. We may lift this restriction in the near future.

Upvotes: 7

Joseph Earl
Joseph Earl

Reputation: 23432

The issue might be to do with your server configuration - it may not be sending the right headers for the font files. Take a look at the answer given for the question IE9 blocks download of cross-origin web font.

EricLaw suggests adding the following to your Apache config

<FilesMatch "\.(ttf|otf|eot|woff)$">
    <IfModule mod_headers.c>
        Header set Access-Control-Allow-Origin "http://mydomain.com"
    </IfModule>
</FilesMatch>

Upvotes: 3

Related Questions