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

19

135

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

Jin answered 7/4, 2011 at 21:35 Comment(4)
+1 for a fine, intelligent, well worded question with all the homework done. We get these much too rarely these days!Keratinize
Indeed it is a well put question, but sadly, a duplicate.Synthiasyntonic
No, it's surely not a duplicate, as in non-Adobe fonts the solutions I found work perfectly. What differs is that it is not the case with cross-domain font referencing I guess - I get "@font-face encountered unknown error" with .woff font as opposed to "@font-face failed cross-origin request" in other mentioned cases.Jin
I had problems with this line after changing the embedding options: url('myfont-webfont.eot?#iehack') format('eot'), Removing it solved the last error (unknown error).Gratianna
C
98

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.

Carboniferous answered 10/4, 2011 at 7:41 Comment(12)
Thanks for the tool, I'll try that later today. In the meantime I've read about that and I guess you're right! It looks like the problem is caused with embedded DRM info. I'll keep you posted.Jin
Unfortunately the tool you provided cannot be easily ran under x64 systems (it's 16-bit). I found another tool that serves the same purpose and it worked like a charm! I'll mark your answer as accepted, as you pointed me in the right direction - thanks!Jin
As a note for ttfpatch, use fsType=0.Sennet
works beautifully. now I can use custom fonts to design my webpages! thanks for the tip.Favrot
ttfpatch did not work for me. Error: tableversion must be 0, 1 or and is hex:003Ula
embed works fine. Just download the source and compile... this is StackOverflow, right? It's only one file. :-) For VS2010 you need to add: #include <string.h>Gratianna
@JonathanDeMarks: Thanks for the encouragement - ttfpatch didn't work for me either, but recompiling embed.c for 64 bit definitely did the trick.Cymbre
Anyway to run the above program on a mac? Or know of any other programs like these made for mac?Linville
For those not au fait with compiling C programs on Windows, it's very straightforward. Follow this guide from Microsoft: msdn.microsoft.com/en-us/library/bb384838.aspxExergue
@Nam-G-VU Your link for the 64bit version has died.Bedclothes
So... what are you supposed to do if you can't edit the font files? Mine are coming from Google Fonts.Foreshadow
this program opens the CLI for a flash and then it disappears :/Micron
M
39

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.

Monogenesis answered 11/4, 2015 at 16:54 Comment(4)
Thank's for report. Fixed.Monogenesis
Really help me a lot. by using Win64 bit exe.Jannery
My god that's amazing. Side not to all: use windows command line and not a replacement like GIT BASH, I usually prefer bash, doesn't work here.Suki
voila! brilliant!!Micron
D
33

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')
Domash answered 27/3, 2012 at 8:27 Comment(2)
Thanks, but that was not the case. It was all about embedding permissions in the font itself.Jin
This worked for Firefox and Chrome (IE was working anyway). Thank you!Credits
U
12

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.

Upturned answered 20/4, 2012 at 7:19 Comment(2)
I think your solution works for some font families but not others. It depends on the font's embedding permission level. For example, this won't work for Abadi fontBailment
Yup, this made absolutely no difference with my .ttf files, I was still getting the "Permission must be Installable." error. What did fix this problem was running Christian's .exe (elsewhere on this page) to modify the .ttf files. After doing this, IE11 would display the .ttf fonts on my webpage correctly.Raouf
Z
9

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

<system.webServer>
  <staticContent>
     <mimeMap fileExtension=".woff" mimeType="application/octet-stream" />
  </staticContent>
</system.webServer>
Zoolatry answered 29/1, 2013 at 23:14 Comment(3)
I don't think that's the same error he's reported but that will be required if you're serving .woffs from IIS, yes. Alternatively you could add a registry key for .woff under HKLM\Software\Classes and set the "Content Type" value in that. However Wikipedia says the correct type is application/font-woff.Censor
Indeed, it's a different thing. I had this entry - the problem was with an already downloaded font that could not get opened in IE due to embedded permissions.Jin
I was doing development in an Apache environment, and when i moved my font files to a Windows IIS server, this fixed my issue.Takamatsu
E
8

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

Epicureanism answered 13/1, 2017 at 19:21 Comment(1)
The online tool fixed it for me. Thanks!Cubiculum
Y
7

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.

Yearlong answered 14/4, 2011 at 0:45 Comment(0)
D
7

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.

Dariodariole answered 6/10, 2015 at 11:15 Comment(0)
R
4

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.

Rollerskate answered 16/11, 2014 at 1:6 Comment(2)
"I was unable to use the MS-DOS and Windows command line tools": The source code is provided though - I'd expect it'd just compile on Mac?Censor
Sorry, I meant to say: Being a spoiled OS X Finder user.Rollerskate
P
4

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
Pocked answered 28/10, 2015 at 16:4 Comment(1)
Thanks - this worked great for the .otf fonts that were causing me problems in IE11.Recumbent
S
3

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>
Synthiasyntonic answered 8/4, 2011 at 13:35 Comment(4)
But this is not the same case though. I've read that post and already tried the solution you provided. The problem is specifically with Adobe fonts. I tried using font kits from Font Squirrel and those work perfectly fine in all browsers (IE9 too). When I try to use Adobe fonts (converted to appropriate formats) the same way - IE9 shouts with errors...Jin
And - what I forgot to say (I'll edit my question) - I'm running my websites under IIS 7.5.Jin
Are they type 1 fonts by any chance?Synthiasyntonic
These are all single-file .ttf (TrueType) fonts. But somehow I get an .afm (Adobe Font Metrics) file when converting to .woff format via onlinefontconverter.com. I don't have a clue what to do with that?Jin
C
3

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.

Catinacation answered 10/12, 2015 at 18:31 Comment(3)
This works and should now be the number 1 answer. It is a shame it has so far to climb to overtake the older answers.Unwarranted
Thanks a lot @Goose! I originally wrote this for my job, but the code got thrown away and replaced, so it lives on in Stack Overflow. Providing C code for a web application issue is definitely not ideal.Catinacation
@Unwarranted I perfer C code. Always. So it is a matter of taste and this is why this answer is equivalent to the answer. FYI you can also use CGI to implement C code in your website.Inly
R
2

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

Ritenuto answered 3/6, 2014 at 8:40 Comment(0)
B
0

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');
}
Bema answered 14/8, 2015 at 17:6 Comment(1)
No, it won't work. My case was strictly about fonts that didn't allow embedding by design (but with license that allows it). So it's not about how I embed it. Check it with a TTF font that explicitly prohibits web-embedding and you'll understand my issue.Jin
A
0

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');
  }
Approval answered 29/8, 2016 at 2:0 Comment(0)
B
0

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.

Bonin answered 20/7, 2017 at 8:11 Comment(0)
S
0

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');
}
Sociolinguistics answered 26/10, 2017 at 20:6 Comment(0)
D
0

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');
}
Deni answered 9/2, 2018 at 12:23 Comment(0)
M
0

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.

Moneybags answered 4/8, 2020 at 7:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.