ChatGPT解决这个技术问题 Extra ChatGPT

使 Adobe 字体在 IE9 中与 CSS3 @font-face 一起使用

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

我将 .ttf/.otf 版本的字体转换为 .woff、.eot 和 .svg,以便针对所有主流浏览器。我使用的 @font-face 语法基本上是来自 { 1}:

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

C
Community

我只能向您解释如何修复“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
O
Our_Benefactors

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

用法:

把.exe和你需要修改的字体放在同一个文件夹下导航到那个目录,在命令行输入embed fontname.fonttype,把fontname换成文件名,把fonttype换成扩展名,即embed brokenFont.ttf 全部搞定!你的字体现在应该可以工作了。


谢谢你的报告。固定的。
真的帮了我很多。通过使用 Win64 位 exe。
我的天,这太神奇了。并非全部:使用 windows 命令行而不是像 GIT BASH 这样的替代品,我通常更喜欢 bash,在这里不起作用。
瞧!杰出的!!
s
stefannh

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

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

谢谢,但事实并非如此。这完全是关于在字体本身中嵌入权限。
这适用于 Firefox 和 Chrome(IE 仍然有效)。谢谢!
R
Rup

我收到以下错误:

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

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

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

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


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

试试这个,在 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 服务器时,这解决了我的问题。
P
Patrick Knott

另一个答案:法律问题。

在您执行此操作之前,有几件事需要注意。首先,要得到这个错误,在 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


在线工具为我修复了它。谢谢!
F
Font Squirrel

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


S
Stack Developer

因为这个问题,我浪费了很多时间。最后我自己找到了很好的解决方案。在我只使用 .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);
}

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


b
buijs

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


“我无法使用 MS-DOS 和 Windows 命令行工具”:虽然提供了源代码 - 我希望它只能在 Mac 上编译?
抱歉,我的意思是:作为一个被宠坏的 OS X Finder 用户。
b
bendytree

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

npm install -g ttembed-js

ttembed-js somefont.ttf

谢谢 - 这对于在 IE11 中导致我出现问题的 .otf 字体非常有用。
C
Community

问题可能与您的服务器配置有关 - 它可能没有为字体文件发送正确的标题。查看问题 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>

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

如果你想用 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 代码。
C
Christian

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

用法:ConsoleApplication1 font.ttf

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


W
Wajid Ali Siddiqui

您可以通过以下代码解决它

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

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

我发现 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');
  }

M
Mark O'Russa

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

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

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


b
bwigs

我最近遇到了 .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');
}

A
Alena Kastsiukavets

这对我有用:

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

M
Mikhail Razgovorov

如果您想使用 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

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


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅