我正在构建一个小型 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 下托管我的网站(字体也是,但在单独的目录和静态内容的子域下)
url('myfont-webfont.eot?#iehack') format('eot'),
删除它解决了最后一个错误(未知错误)。
正如 Knu 所说,您可以使用 this tool,但它仅针对 MS-DOS 编译。我为Win64编译它。 Download。
用法:
把.exe和你需要修改的字体放在同一个文件夹下导航到那个目录,在命令行输入embed fontname.fonttype,把fontname换成文件名,把fonttype换成扩展名,即embed brokenFont.ttf 全部搞定!你的字体现在应该可以工作了。
您应该将 ie 字体的格式设置为 'embedded-opentype' 而不是 'eot'。例如:
src: url('fontname.eot?#iefix') format('embedded-opentype')
我收到以下错误:
CSS3114:@font-face 未能通过 OpenType 嵌入权限检查。权限必须是可安装的。字体名称.ttf
使用下面的代码后,我的问题得到了解决....
src: url('fontname.ttf') format('embedded-opentype')
谢谢你们帮助我!干杯,伦吉斯。
试试这个,在 web.config 中添加这一行。
<system.webServer>
<staticContent>
<mimeMap fileExtension=".woff" mimeType="application/octet-stream" />
</staticContent>
</system.webServer>
application/font-woff
。
另一个答案:法律问题。
在您执行此操作之前,有几件事需要注意。首先,要得到这个错误,在 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
确实,IE9 要求 TTF 字体将嵌入位设置为可安装。生成器会自动执行此操作,但我们目前出于其他原因阻止了 Adobe 字体。我们可能会在不久的将来取消此限制。
因为这个问题,我浪费了很多时间。最后我自己找到了很好的解决方案。在我只使用 .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);
}
我希望这会对某人有所帮助。
作为 Mac 用户,我无法使用上面提到的 MS-DOS 和 Windows 命令行工具来修复字体嵌入权限。但是,我发现您可以使用 FontLab 将权限设置为“允许所有内容”来解决此问题。我希望这个关于如何set the font permission to Installable on Mac OS X的秘诀也对其他人有用。
如果您熟悉 nodejs/npm,ttembed-js 是一种在 TTF 字体上设置“可安装嵌入允许”标志的简单方法。这将修改指定的 .ttf 文件:
npm install -g ttembed-js
ttembed-js somefont.ttf
问题可能与您的服务器配置有关 - 它可能没有为字体文件发送正确的标题。查看问题 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>
如果你想用 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。
对于遇到错误的每个人:“tableversion 必须为 0、1 或并且是 hex:003”当使用 ttfpatch 时,我已经为 64 位编译了 embed。我没有改变任何东西,只是添加了需要的库并编译。使用风险自负。
用法:ConsoleApplication1 font.ttf
http://www.mediafire.com/download/8x1px8aqq18lcx8/ConsoleApplication1.exe
您可以通过以下代码解决它
@font-face {
font-family: 'Font-Name';
src: url('../fonts/Font-Name.ttf');
src: url('../fonts/Font-Name.eot?#iefix') format('embedded-opentype');
}
我发现 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');
}
我尝试了 ttfpatch 工具,但它对我不起作用。 Internet Exploder 9 和 10 仍然抱怨。
我找到了这个不错的 Git 要点,它解决了我的问题。 https://gist.github.com/stefanmaric/a5043c0998d9fc35483d
只需将代码复制并粘贴到您的 css 中即可。
我最近遇到了 .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');
}
这对我有用:
@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');
}
如果您想使用 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
可以在 here 中找到 C 中的原始源代码。
#include <string.h>