【问题标题】:Make Adobe fonts work with CSS3 @font-face in IE9使 Adob​​e 字体在 IE9 中与 CSS3 @font-face 一起使用
【发布时间】:2011-08-01 01:43:03
【问题描述】:

我正在构建一个小型 Intranet 应用程序并尝试使用我最近购买的 Adobe 字体,但没有成功。据我所知,在我们的案例中,这不是许可证违规。

我将 .ttf/.otf 版本的字体转换为 .woff、.eot 和 .svg,以便针对所有主流浏览器。 我使用的 @font-face 语法基本上是防弹的来自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');
    }

我修改了 HTTP 标头(添加了 Access-Control-Allow-Origin = "*")以允许跨域引用。 在 FF 和 Chrome 中完美运行,但在 IE9 中我得到:

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

我注意到在将字体从 .ttf/.otf 转换为 .woff 时,我还会得到一个 .afm 文件,但我不知道它是否重要...

有什么办法可以解决吗?

[编辑] - 我在 IIS 7.5

下托管我的网站(字体也是,但在静态内容的单独目录和子域下)

【问题讨论】:

  • +1 是一个很好、聪明、措辞恰当的问题,所有作业都完成了。这些天我们得到这些太少了!
  • 确实这是一个很好的问题,但遗憾的是,重复了。
  • 不,它肯定不是重复的,因为在非 Adob​​e 字体中,我发现的解决方案非常有效。不同的是,我猜跨域字体引用并非如此 - 我得到“@font-face 遇到未知错误”与 .woff 字体,而不是其他提到的“@font-face 跨域请求失败”案例。
  • 我在更改嵌入选项后遇到了这一行的问题:url('myfont-webfont.eot?#iehack') format('eot'), 删除它解决了最后一个错误(未知错误)。

标签: internet-explorer css internet-explorer-9 font-face


【解决方案1】:

我只能向您解释如何修复“CSS3114”错误。
您必须更改 TTF 文件的嵌入级别。

使用适当的tool,您可以将其设置为允许安装嵌入
对于 64 位版本,请查看 @user22600 的 answer

【讨论】:

  • 作为 ttfpatch 的注释,使用 fsType=0。
  • ttfpatch 对我不起作用。错误:tableversion 必须是 0、1 或者是 hex:003
  • 嵌入工作正常。只需下载源代码并编译...这是 StackOverflow,对吗?它只有一个文件。 :-) 对于 VS2010,您需要添加:#include <string.h>
  • @JonathanDeMarks:感谢您的鼓励 - ttfpatch 对我也不起作用,但为 64 位重新编译 embed.c 确实成功了。
  • 对于那些不熟悉在 Windows 上编译 C 程序的人来说,这非常简单。遵循 Microsoft 的指南:msdn.microsoft.com/en-us/library/bb384838.aspx
【解决方案2】:

正如 Knu 所说,您可以使用 this tool,但它仅针对 MS-DOS 编译。我为Win64编译它。 Download.

用法:

  1. 将.exe与需要修改的字体放在同一文件夹中

  2. 在命令行中导航到该目录

  3. 键入embed fontname.fonttype,将fontname 替换为文件名,将fonttype 替换为扩展名,即embed brokenFont.ttf

  4. 全部完成!您的字体现在应该可以使用了。

【讨论】:

  • 感谢您的报告。固定。
  • 真的帮了我很多。通过使用 Win64 位 exe。
  • 天哪,这太神奇了。并非全部:使用 windows 命令行而不是像 GIT BASH 这样的替代品,我通常更喜欢 bash,在这里不起作用。
  • 瞧!太棒了!
【解决方案3】:

您应该将 ie 字体的格式设置为 'embedded-opentype' 而不是 'eot'。 例如:

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

【讨论】:

  • 谢谢,但事实并非如此。这完全是关于在字体本身中嵌入权限。
  • 这适用于 Firefox 和 Chrome(IE 仍然可以使用)。谢谢!
【解决方案4】:

我收到以下错误:

CSS3114:@font-face 未能通过 OpenType 嵌入权限检查。权限必须是可安装的。
字体名称.ttf

使用下面的代码后,我的问题得到了解决....

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

谢谢你们帮助我!
干杯,
伦吉斯。

【讨论】:

  • 我认为您的解决方案适用于某些字体系列,但不适用于其他字体系列。这取决于字体的嵌入权限级别。例如,这不适用于 Abadi 字体
  • 是的,这对我的 .ttf 文件完全没有影响,我仍然得到“权限必须是可安装的”。错误。解决此问题的方法是运行 Christian 的 .exe(本页其他位置)来修改 .ttf 文件。完成此操作后,IE11 在我的网页上正确显示 .ttf 字体。
【解决方案5】:

试试这个,在 web.config 中添加这一行。

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

【讨论】:

  • 我认为这与他报告的错误不同,但如果您从 IIS 提供 .woffs,则需要这样做,是的。或者,您可以在 HKLM\Software\Classes 下为 .woff 添加一个注册表项,并在其中设置“内容类型”值。但是维基百科说the correct type is application/font-woff
  • 确实,这是另一回事。我有这个条目 - 问题在于 已经下载 字体,由于嵌入的权限而无法在 IE 中打开。
  • 我在 Apache 环境中进行开发,当我将字体文件移动到 Windows IIS 服务器时,这解决了我的问题。
【解决方案6】:

不同的答案:法律问题。

在执行此操作之前,有几件事需要注意。首先,要得到这个错误,在 IE 中,检查元素,切换标签,然后查找错误,我相信“CSS3114”会出现在控制台中。

您需要了解的是,这是一个许可问题。 IE。 (双关语)如果您尝试加载导致此错误的字体,则您没有使用该字体的文件的权限,如果您没有权限,您很可能会丢失合法的除非您持有许可证,否则以这种方式使用这种字体进行战斗(这本身是极不可能的)。所以,你可以第一次感谢 IE 是唯一一个告诉你“不”的浏览器,因为它至少让你知道你在做一些有问题的事情。

也就是说,这是你的答案:

首先确保您使用的是 .css 中的最佳代码,请参阅其他一些 css 答案。
IE 11 css 示例(适用于所有现代浏览器可能需要针对 IE9 进行调整):

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

然后,确保您有一个有效的网络字体(您可能已经通过在其他浏览器中查看您的字体知道这一点)。如果您需要在线字体转换器,请点击此处:https://onlinefontconverter.com/

最后,摆脱“CSS3114”错误。如需在线工具,请点击此处:https://www.andrebacklund.com/fontfixer.html

【讨论】:

  • 在线工具为我修复了它。谢谢!
【解决方案7】:

确实,IE9 要求 TTF 字体将嵌入位设置为可安装。生成器会自动执行此操作,但我们目前出于其他原因阻止了 Adob​​e 字体。我们可能会在不久的将来取消此限制。

【讨论】:

    【解决方案8】:

    因为这个问题,我浪费了很多时间。 最后我自己找到了很好的解决方案。在我只使用 .ttf 字体之前。但我添加了一种额外的字体格式 .eot,它开始在 IE 中工作。

    我使用了以下代码,它在所有浏览器中都像魅力一样工作。

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

    我希望这会对某人有所帮助。

    【讨论】:

      【解决方案9】:

      作为 Mac 用户,我无法使用之前提到的 MS-DOS 和 Windows 命令行工具来修复字体嵌入权限。但是,我发现您可以使用 FontLab 将权限设置为“允许所有内容”来解决此问题。我希望这个关于如何set the font permission to Installable on Mac OS X 的秘诀也对其他人有用。

      【讨论】:

      • “我无法使用 MS-DOS 和 Windows 命令行工具”:虽然提供了源代码 - 我希望它只能在 Mac 上编译?
      • 对不起,我的意思是:作为一个被宠坏的 OS X Finder 用户。
      【解决方案10】:

      如果您熟悉 nodejs/npm,ttembed-js 是一种在 TTF 字体上设置“允许可安装嵌入”标志的简单方法。这将修改指定的 .ttf 文件:

      npm install -g ttembed-js
      
      ttembed-js somefont.ttf
      

      【讨论】:

      • 谢谢 - 这对于在 IE11 中导致我出现问题的 .otf 字体非常有用。
      【解决方案11】:

      问题可能与您的服务器配置有关 - 它可能没有为字体文件发送正确的标题。看看IE9 blocks download of cross-origin web font这个问题给出的答案。

      EricLaw 建议将以下内容添加到您的 Apache 配置中

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

      【讨论】:

      • 但情况并非如此。我已阅读该帖子并已尝试过您提供的解决方案。问题出在 Adob​​e 字体上。我尝试使用 Font Squirrel 的字体工具包,这些工具包在所有浏览器(IE9 也一样)中都能正常工作。当我尝试以相同的方式使用 Adob​​e 字体(转换为适当的格式)时 - IE9 出现错误...
      • 还有 - 我忘了说(我会编辑我的问题) - 我在 IIS 7.5 下运行我的网站。
      • 他们是否偶然输入了 1 个字体?
      • 这些都是单文件 .ttf (TrueType) 字体。但不知何故,当我通过 onlinefontconverter.com 转换为 .woff 格式时,我得到了一个 .afm(Adobe Font Metrics)文件。我不知道该怎么办?
      【解决方案12】:

      如果您想使用 PHP 脚本而不是运行 C 代码来执行此操作(或者您像我一样在 Mac 上,并且您不会因为只等待一年才能打开 Xcode 而感到羞耻) , 这是一个 PHP 函数,您可以使用它来从字体中删除嵌入权限:

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

      确保在运行此代码之前备份您的字体文件,如果它损坏了不要怪我。

      C 源代码可以在here找到。

      【讨论】:

      • 这行得通,现在应该是第一答案。到目前为止,它一直在爬升以超越旧的答案,这是一种耻辱。
      • 非常感谢@Goose!我最初是为我的工作编写的,但是代码被丢弃并替换了,所以它仍然存在于 Stack Overflow 中。为 Web 应用程序问题提供 C 代码绝对不理想。
      • @Goose 我更喜欢 C 代码。总是。所以这是一个品味问题,这就是为什么这个答案等同于答案。仅供参考,您还可以使用 CGI 在您的网站中实现 C 代码。
      【解决方案13】:

      对于遇到错误的每个人:“tableversion 必须是 0、1 或并且是 hex:003”当使用 ttfpatch 时,我已经为 64 位编译了 embed。我没有改变任何东西,只是添加了需要的库并编译。使用风险自负。

      用法:ConsoleApplication1 font.ttf

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

      【讨论】:

        【解决方案14】:

        可以通过以下代码解决

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

        【讨论】:

        • 不,这行不通。我的案例完全是关于不允许嵌入设计的字体(但有允许它的许可证)。所以这与我如何嵌入它无关。使用明确禁止网络嵌入的 TTF 字体检查它,您就会明白我的问题。
        【解决方案15】:

        我发现eot 文件应该放在ttf 之外。如果在ttf下,认为字体显示正确,IE9还是会报错。

        推荐:

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

        推荐:

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

        【讨论】:

          【解决方案16】:

          我尝试了 ttfpatch 工具,但它对我不起作用。 Internet Exploder 9 和 10 仍在抱怨。

          我发现了这个不错的 Git 要点,它解决了我的问题。 https://gist.github.com/stefanmaric/a5043c0998d9fc35483d

          只需将代码复制并粘贴到您的 css 中即可。

          【讨论】:

            【解决方案17】:

            我最近遇到了 .eot 和 .otf 字体在加载时在控制台中产生 CSS3114 和 CSS3111 错误的问题。对我有用的解决方案是仅使用带有 .ttf 格式后备的 .woff 和 .woff2 格式。在大多数浏览器中,.woff 格式将在 .ttf 之前使用,并且似乎不会触发字体嵌入权限问题 (css3114) 和字体命名错误格式问题 (css3111)。我在this extremely helpful article about the CSS3111 and CSS3114 issue 中找到了我的解决方案,并且还阅读了this article on using @font-face

            注意:此解决方案不需要重新编译、转换或编辑任何字体文件。这是一个纯 CSS 的解决方案。我测试的字体确实有为其生成的 .eot、.otf、.woff、.woff2 和 .svg 版本,可能来自原始的 .ttf 源,当我尝试它时确实产生了 3114 错误,但是 .woff 和 . woff2 文件似乎不受此问题的影响。

            这就是我使用@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');
            }
            

            这是在 IE 中触发 @font-face 错误的原因:

            @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');
            }
            

            【讨论】:

              【解决方案18】:

              这对我有用:

              @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');
              }
              

              【讨论】:

                【解决方案19】:

                如果您想使用 Python 脚本而不是运行 C/PHP 代码来执行此操作,这里有一个 Python3 函数,您可以使用它来从字体中删除嵌入权限:

                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")
                

                它有效,但我最终解决了通过 https 在 IE 中加载字体的问题,例如 this

                thanks NobleUplift

                C 中的原始源代码可以在here 找到。

                【讨论】:

                  猜你喜欢
                  • 2022-12-04
                  • 1970-01-01
                  • 2011-12-28
                  • 2011-09-11
                  • 2013-08-10
                  • 1970-01-01
                  • 2013-05-18
                  • 2012-09-21
                  • 2012-11-18
                  相关资源
                  最近更新 更多