为WebFonts技术实现自动裁剪:帮助汉字从我们的时代幸存下去

第一章 我们应该承认,汉字是不适应网络时代的

只从两点来证明:
首先,从来没有过一个完整的汉字字体。
英语只包含26个字母,构成一篇文章、一个网页所需的全部字符都包含在ASCII码表内,每个字符在计算机中只需要一个字节表示。而反观汉字,甚至没有定论究竟有多少个字。目前我们可以使用的汉字(包括日语、韩语中的)大约有8万个,Unicode中定义了7万多个,在中国大陆地区广泛使用的GBK编码收录了2万个,GB2312编码收录了6千多个,在香港、台湾广泛使用的BIG5编码收录了1.3万个。一般情况下这些编码标准都能满足人们的需求,因为我们日常使用中的汉字大约只有3500个左右。
但是使用不完整的字体总归会引发问题。如果计算机中不包含某个字的字形,那么用到它时一般会被打印成方块乱码,在wikipedia社区被叫做豆腐问题。这种现象大家应该多多少少都遇到过,在软件界面上、在网页上、在命令行终端上等等。2014年习近平主席访问德国,当地人打出的横幅上就有很多“豆腐”,对于不会中文的人来说,“方块字”和“方块”确实很难区分……

其次,字体文件太大。
打开你计算机的字体文件目录,按大小排序,最大的几个一定是汉字字体(如果你装了汉字的话)。其它文字的字体文件一般都是几十到几百KB,而到了汉字,最小也是好几个MB,我Mac中的“楷体”更是高达70MB。它们的大小差异来自于所收录的字符集大小,考虑到前文所述,如果真的有一个“完整汉字字体”,那肯定是要上百MB的。也许你会觉得无所谓,现在的硬盘很大很便宜,但是其它一些场景下,这个大小是无法接受的,例如需要被打包进软件,或者需要随网页发布。2011年我为Blender实现国际化系统时,为了支持中文,需要将一个3MB的字体嵌入到软件中,被社区认为是不可接受的。因为软件本身只有27MB,他们一直致力于控制软件的大小,可能仅仅为了节省1MB空间就付出过很多努力,完全无法容忍从“二十多兆”突然飙升至“三十多兆”。而本文将要讲到的WebFonts技术也面临相同的问题。这一技术会在加载网页时从服务器取得字体,完成网页渲染。Google已经提供了这样的在线字体服务,但是至今仍不包含中文字体。因为不可能让用户在浏览一个小网页时额外还需要下载一个好几MB的字体。抛开带宽成本不讲,光是下载时间就足以严重损害用户体验了。

我们是否应该放弃汉字,或者像我以前的想法——废除生僻字,统一只使用3000个常用字?虽然在一定程度上解决了上述问题,但是终究是不可取的。汉字从甲骨文至今已有三千多年了,经史子集、诗词歌赋,承载了整个中华文明的历史。而计算机、互联网出现才区区五六十年,要为了它改造汉字,似乎还有点冒进。所以作为以“知识分子”自居的程序员,我们应该利用起自己手中的技术。传承数千年的汉字到了我们手里,我们就要让它从这个“互联网时代”好好地活下去。

第二章 言归正传,干货来袭

WebFonts是一种新兴的解决网页上字体缺失问题的技术。目前主流的浏览器都支持以下CSS语法:
@font-face {
     font-family: 宋体;
     src: url(‘http://path.com/songti.ttf‘) format(‘ttf‘);
}
如果网页中用到了该字体,浏览器就会根据src去加载。Google已经提供了这样的在线字体服务[1],Wikipedia的运营者WMF(维基媒体基金会)也建立了自己的字体库。当然,由于上面提到的这些原因,它们都还没有提供中文字体支持。为了解决这一问题,在今年的Google Summer of Code项目中,我为mediawiki(也就是Wikipedia所使用的wiki系统)实现了“自动字体裁剪”,项目主页见[2]。该解决方案分为三个部分:
1.在服务器端通过钩子(Hook),在页面被输出前预先根据内容裁剪出字体文件,这些字体只包含了将要被输出的文字,因此非常小。具体的裁剪是使用一个第三方开源库php-font-lib[3],其裁剪出的字体在格式上还有些问题,于是又调用fontforge导出一次,进行修正。这是本项目一大需要改进之处。
2.页面被客户端加载后,css中对WebFonts的定义被修改为了类似:
@font-face {
    font-family: 宋体;
    src: url(‘http://path.com/FontRequest.php?font=songti‘) format(‘ttf‘);
}
注意其url部分,已经不再是静态的ttf文件,而是一个php脚本,我称其为“动态字体技术”
3.在服务器端,“动态字体请求”需要被返回正确的、裁剪后的文件。根据实验,通过重定向到一个静态字体文件:
<?php
    header(“Location:$path_to_tailored_font”);
?>
或者通过修改MIME Type来返回二进制数据:
<?php
    header( ‘Content-Type: application/octet-stream‘ );
    header( ‘Content-Disposition: attachment; filename=songti.ttf‘ );
    readfile( $path_to_tailored_font );
?>
都可以达到目的。在本项目中采用的是第二种方法,以避免多余的HTTP请求。

第三章 眼见为实

在完成了上述项目之后,我在基金会的Labs服务器群上搭建了一个测试站点[4],在首页大家可以看到,第二行字采用了“文泉驿微米黑”字体,该字体的完整文件有4.5MB,但是通过Debug工具发现该页面只需要加载20KB。而另一个测试页面[5],含有一首完整的《最炫民族风》,也只需要加载40KB左右。至此,WebFonts技术终于可以运用于中文!你可以放心地在页面上包含特殊的字体,包括自定义的艺术字,而不必担心用户没有安装这个字体、或者下载开销太大、或者需要导出为图片嵌在网页里。
作为验证,你也可以新建wiki页面(请勿修改供展示用的页面),写下这样的代码:
<p style="font-family:WenQuanYi Micro Hei”>SOMETHING YOU WANT</p>
就可以看到页面加载了经裁剪的、仅包含了你所使用的文字的字体。当然,裁剪操作有一定耗时,所以第一次访问时有延迟量。

第四章 通用化,另一种实现

给Wikipedia的项目业已完工,但是我认为这个功能是通用的,可以解决一些大难题。因此我把这项工作总结并迁移到了Github上[6],并且采用了更简洁的实现。即在客户端用JavaScript收集字体信息,用AJAX向服务器端发出请求。服务器端进行裁剪操作(如果没有命中缓存),然后返回各个裁剪后的字体的URL。客户端收到后,生成CSS代码附加到<head>末尾。WebFonts随后生效。
这个实现非常简洁,易于部署。项目中附有示例代码,演示网页见[7].

结束语
欢迎大家为自己的网站部署这套系统,我愿意提供力所能及的协助。希望有朝一日能够有一个一站式的、带自动字体裁剪功能的中文字体在线服务,为中文网络世界提供统一解决方案。
我的微博:@甜菜萧
我的LinkedIn: linkedin.com/in/xiaoxiangquan

[1] https://www.google.com/fonts
[2] https://www.mediawiki.org/wiki/Extension:UniversalLanguageSelector/Fonts_for_Chinese_wikis
[3] https://github.com/PhenX/php-font-lib
[4] http://fonttailor.wmflabs.org
[5] http://fonttailor.wmflabs.org/index.php/Test
[6] https://github.com/xiaoxq/webfonts-subsetting
[7] http://fonttailor.wmflabs.org/webfonts-subsetting

时间: 2024-10-10 01:46:39

为WebFonts技术实现自动裁剪:帮助汉字从我们的时代幸存下去的相关文章

最新 IOS应用开发Icon规格自动裁剪器(C#)

老早之前做IOS APP开发,为折腾一个IOS应用的Icon,用C#写了一个简单的IOS应用开发Icon规格自动裁剪器,但时过境迁,目前IOS设备屏幕规格也是越来越多,一个版本就要生成好几种规格分辨率的Icon,用PS什么的一个一个生成费劲,如果Icon有变动又得重新生成一次,所以还是整个程序来干这活比较轻松. 思路很简单,先导入一张大图(注意:这张图必须大于等于1024*1024,因为[email protected]的规格是1024*1024),然后生成对应像素的小图,最后保存出来. 首先来

IVI 技术在自动测试系统中的应用研究

最近在做一个项目,关于TR组件自动测试系统,其中对测试系统仪器的设置,想底层用IVI 来实现,新的仪器大多支持lan口,厂家都自带IVI 驱动程序,只要按指定步骤就能实现多个厂家的IVI 仪器设置,实现同类仪器的可互换性. 本项目中用到示波器.频谱仪.宽带信号源.微波信号源等仪器.下面讲一下开发IVI 步骤: 1.首先要对IVI 有所了解,IVI 相关信息可从下面网址获得:http://www.ivifoundation.org/default.aspx overview 中大家可以学习IVI

cookie技术实现自动登录+cookie中写入中文+记住用户名

结合上次写的cookie技术实现自动登录添加部分功能<tr> <td colspan="2"> <input type="checkbox" name="usernamelogin" id="usernamelogin" value="usernameOk" >记住用户名 <input type="checkbox" name="aut

WordPress自动裁剪768w像素缩略图的解决办法

最新观赏鱼在折腾一个新的WordPress站点,即使通过后台把多媒体裁剪的宽高都设置为0时,移除主题可能存在的自动裁剪大小,WordPress依然会在上传图片的时候自动裁剪一个宽为768像素的图片.并且网上的禁用WordPress自动裁剪图片的解决全部失效. 经过一番研究和查找,WordPress 4.4版本以后增加了响应式图片的功能,目的是让图片能适应手机.平板等不同屏幕,所以WordPress是把这个参数直接在WordPress安装的时候写入数据库的,但是在后台又没有地方改,改代码也没有用,

使用nginx+lua+GraphicsMagick实现图片自动 裁剪

在做网站尤其是以内容为主的过程中,常常会遇到一张图片各种地方都要引用,且每个引用的地方要求的图片尺寸都不一样的.一般中大型的网站都会对这一类的图片做自动裁剪功能.本文介绍在centos6操作系统上,采用nginx.lua和GraphicsMagick工具简单实现图片的自动裁剪功能.其中nginx负责展示图片和调度lua脚本,GraphicsMagick负责对原图进行裁剪. 一.基础软件包安装groupadd wwwuseradd -g www www -s /bin/falseyum -y in

《淘宝技术这十年》读书笔记 (四). 分布式时代和中间件

前面两篇文章介绍了淘宝的发展历程.Java时代的变迁和淘宝开始创新技术: <淘宝技术这十年>读书笔记 (一).淘宝网技术简介及来源 <淘宝技术这十年>读书笔记 (二).Java时代的脱胎换骨和坚若磐石 <淘宝技术这十年>读书笔记 (三).创造技术TFS和Tair 这篇文章主要讲述分布式时代和中间件相关知识,包括服务化.HSF.Notify和TDDL.同时里面有我们经常遇见的编码错误等相关问题,希望文章对你有所帮助! 一. 分布式时代 1.服务化 在系统发展的过程中,架构

cookie技术实现自动登录+验证用户名输入是否正确

login页面 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+requ

.net图片自动裁剪白边函数案例

1.项目要求上传白底的图片要进行裁剪白边,于是同事谢了个函数感觉很好用. 2. #region 剪切白边 /// <summary> /// 剪切白边 /// </summary> /// <param name="p"></param> /// <returns></returns> public static Image Crop(Image p) { int x, y ;//for use of X,Y Co

用深度学习技术FCN自动生成口红

1 这个是什么? ???????基于全卷积神经网络(FCN)的自动生成口红Python程序. 图1 FCN生成口红的效果(注:此两张人脸图来自人脸公开数据库LFW) 2 怎么使用了? ???????首先能从这个Github (https://github.com/Kalafinaian/ai_lips_makeup) 中下载这个python项目.下载解压后你得到这样一个程序. 图2 口红Python程序 ???????本项目的运行环境为Python3.6,需要的深度学习包tensorflow ,