精华内容
下载资源
问答
  • win7 DOS 中文乱码

    千次阅读 2013-12-10 14:10:17
    在window dos下,经常出现中文乱码的问题,我是这样解决的,也许能帮到大家: 打开cmd: 敲入更改编码命令:chcp 936 点击dos框的属性,选择如下: 点击确定,ok,解决。 MS-DOS为以下国家语言...

    在window dos下,经常出现中文乱码的问题,我是这样解决的,也许能帮到大家:

    打开cmd:

    敲入更改编码命令:chcp 936

    点击dos框的属性,选择如下:

    点击确定,ok,解决。


    MS-DOS为以下国家和语言提供字符集:

       代码页描述   1258 越南语   1257 波罗的语   1256 阿拉伯语   1255 希伯来语   1254 土耳其语   1253 希腊语   1252 拉丁 1 字符 (ANSI)   1251 西里尔语   1250 中欧语言   950 繁体中文   949 朝鲜语   936 简体中文(默认)   932 日语   874 泰国语   850 多语种 (MS-DOS Latin1)   437 MS-DOS 美国英语

    展开全文
  • 中文转码问题总结

    2015-02-12 10:34:00
    因此只能表示一些数字,英文字母西欧语言、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号单字节,即一个字节对应一个编码,不能编码汉字 GBK 1) 能编码汉字,一个汉字用2个字节编码2) 编码的汉字比GB2312更多...

    编码基础知识

    ISO-8859-1

    ISO-8859-1 的较低部分(从 1 到 127 之间的代码)。
    ISO-8859-1 的较高部分(从 160 到 255 之间的代码)。
    因此只能表示一些数字,英文字母和西欧语言、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号
    单字节,即一个字节对应一个编码,不能编码汉字


    GBK

    1) 能编码汉字,一个汉字用2个字节编码
    2) 编码的汉字比GB2312更多


    GB2312

    能编码汉字,一个汉字用2个字节编码

    UTF-8

    英文字母用一个字节表示,一个汉字用3个字节表示
    字符集范围包括:汉字、字母、符号

    编码和解码
    原理

    我们平时看到的“美女”是字符,是一种逻辑展示,计算机不会直接存储一个这样的字符串,
    考虑重用,计算机存储的基本单位是字节,然后由字节来表示字符,比如a用[97]表示
    这种映射关系就叫做编码,因此一个字符串要被编码成字节之后才能被计算机存储,网络传输
    也是如此,都是以字节的形式传输。
    将字节还原成字符的过程叫做解码。
    那么就要规定编码和解码的规则要相同,否则就会造成乱码


    servlet容器中遇到的编码问题

    接收浏览器POST请求

    客户端是浏览器
    服务端是servlet容器
    那么首先,客户端要指定编码的方式,以html为例:
    html4:<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    html5:<meta charset="utf-8"/>
    此标签的作用不是浏览器展示时用的,而是浏览发起post请求时,按此编码将
    发送的内容编码为字节。

    servlet服务端解码方式:
    request.setCharacterEncoding("utf-8");
    String name = request.getParameter("name");


    接收浏览器GET请求

    如:
    http://localhost:8888/webtest/EncodeServlet?name=你好
    浏览器将会对url进行urlEncode,编码方式为UTF-8
    服务端解码方式:
    String name = new String(request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8");
    此处用request.setCharacterEncoding("UTF-8");来设置解码,不能奏效,原因是get请求将参数拼在url后面进行url encode,而web容器对url的解码是在调用servlet之前,且默认解码方式是iso-8859-1
    当然这个uri encode的可以修改的,其实中国人开发的程序,就应该讲uri的编码也设置成utf-8而不是iso-8859-1
    如果是tomcat,则修改位置如下:
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

     响应给浏览器

    Response设置编码:
    Response是指响应给客户端时,字节的编码方式,默认为ISO-8859-1
    可用如下方法查看:
    response.getCharacterEncoding();
    设置响应流的编码方式:
    response.setCharacterEncoding("UTF-8");
    设置浏览器的解码方式:
    response.setContentType("text/html;charset=UTF-8");
    此设置是告知客户端按此编码来解码


    Struts2 和Spring 设置编码问题

    Struts2

    Struts.xml中做如下配置:
    <constant name="struts.i18n.encoding" value="utf-8"></constant>


    Spring

    Web.xml中配置如下:
    <filter>
    <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter
    </filter-class>
    <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
    </init-param>
    <init-param>

    <param-name>forceEncoding</param-name>
    <param-value>true</param-value>
    </init-param>
    </filter>
    其中encoding设置服务端编码和解码的方式
    forceEncoding表示强制编码的方式


    字符串转字节转码

    String s = "s汉";
    byte[] bytes1 = s.getBytes("ISO-8859-1");//丢失字符
    byte[] bytes2 = s.getBytes("GBK");
    byte[] bytes3 = s.getBytes("UTF-8");


    字节转字符串

    String s1 = new String(bytes1,"utf-8");//丢失
    String s2 = new String(bytes2,"GBK");
    String s3 = new String(bytes3,"utf-8");

    转载于:https://www.cnblogs.com/tangyanbo/p/4287468.html

    展开全文
  • Readiris 还可以识别阿拉伯语、波斯语和希伯来语以及四种亚洲语言:日语、简体中文、繁体中文和韩语。除了文本识别,得益于 I.R.I.S. 的压缩技术 iHQC,Readiris 还提供 PDF 和 XPS 文件的强大压缩功能。新...
  • 2014 在英语, 德国的, 西班牙的, 法国人, 意大利的, 葡萄牙, 荷兰人, 丹麦的, 瑞典, 芬兰, 挪威, 捷克的, 波兰语, 匈牙利, 土耳其, 俄, 希腊的, 阿拉伯语, 希伯来文, 日本, 中国传统, 简体中国韩国. 支持的操作...
  • 通过Pango库(例如处理希伯来文、阿拉伯文、泰文等文字)可支持使用任何的描述语言及编程语言。 字母上下突出端(Kerning)、字母间隔(letterspacing)、列间隔等的调整。 路径上可走文字(无论文字或路径都可持续...
  • ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍点击左上方蓝字关注我们01修图动口不动手,有人把StyleGANCLIP组了个CP,能听懂修图指令那种在最近的一篇论文中,来自希伯来大学、特拉维夫大学...

    ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍点击左上方蓝字关注我们

    01

    修图动口不动手,有人把StyleGAN和CLIP组了个CP,能听懂修图指令那种

    在最近的一篇论文中,来自希伯来大学、特拉维夫大学、Adobe 等机构的研究者提出了一种名为「StyleCLIP」的模型,几乎可以让你动动嘴皮子就把图修了。

    这里用「几乎」是因为研究者给出的接口其实还是文字版的。如下图所示,如果你想让一只猫看起来可爱一点,只需要输入「cute cat」,模型就能够把猫的眼睛放大,同时改变其他影响其可爱值的特征。

    StyleGAN+CLIP=StyleCLIP

    GAN 模型的出现颠覆了图像生成领域,StyleGAN 更是其中的翘楚,可以生成极其逼真的图像。此外,研究者发现,StyleGAN 学到的中间隐空间拥有解耦特性,这使得利用预训练模型对合成图像以及真实图像执行各种各样的图像操作成为可能。

    但对于用户来说,利用 StyleGAN 的强大表达能力来实现自己的意图并不容易。他们需要一个简单、直观的接口。现有的语义控制发现方法要么涉及手动检查,要么涉及大量带注释的数据,要么需要预训练的分类器。此外,后续操作通常是使用一个参数模型(如 StyleRig 中的 3DMM),通过在一个隐空间中沿着一个方向移动来执行。

    在这篇论文中,研究者利用 OpenAI 最近推出的 CLIP(Contrastive Language-Image Pre-training)模型来支持基于文本的直观语义图像操作,既不限于预设的操作方向,也不需要额外的手工工作来发现新的 control。

    • 论文链接:

      https://arxiv.org/pdf/2103.17249.pdf

    • 项目链接:

      https://github.com/orpatashnik/StyleCLIP

    信息来源:机器之心

    02

    CVPR2021 | 国防科大:基于几何稳定性分析的物体位姿估计方法

    物体6D姿态估计是机器人抓取、虚拟现实等任务中的核心研究问题。近些年来,随着深度学习技术和图像卷积神经网络的快速发展,在提取物体的几何特征方面出现了许多需要改善的问题。国防科技大学的研究人员致力于通过将几何稳定性概念引入物体 6D 姿态估计的方法来解决问题。

    近些年来,随着深度传感技术的快速发展,以 PPF 特征匹配算法为代表非学习方法和以 3DMatch 为代表的深度学习几何特征提取方法逐渐在位姿估计问题中崭露头角。这些方法虽然在多个公开数据集中取得了不错的效果,但是没有显式地约束几何特征提取和物体位姿的关系,因此制约了方法的可解释性和泛化性。

    针对这一问题,国防科技大学的研究人员将几何稳定性概念引入了物体 6D 姿态估计,并提出了利用物体表面几何稳定(Geometrically stable)的面片组合(Patch group)预测物体姿态的方法 StablePose。StablePose 物体位姿估计模块的输入只有物体的深度信息,不包括 RGB 图像,能够有效处理无纹理、弱纹理物体的位姿估计问题。实验表明,StablePose 在多个实例位姿估计和类别位姿估计数据集上取得了最佳性能,能够处理物体间遮挡,具有良好的泛化性。论文的主要创新点包括:

    • 将几何稳定性概念引入到物体 6D 姿态估计问题;

    • 提出了基于几何稳定面块组合回归物体位姿的深度网络;

    • 提出了用于处理对称物体、有遮挡的物体以及新颖物体的机制,增强了方法的稳定性。

    论文地址: https://arxiv.org/abs/2102.09334

    信息来源:机器之心

    03

    BERT和GAN咋压缩,且看咱PaddleSlim新利器——OFA

    目前在深度学习领域,一方面需要追求更高的性能,采用强大、复杂的模型网络和实验方法;另一方面又需要关注如何将算法更稳定、高效地在硬件平台上落。复杂的模型固然展现更好的性能,但过高的存储空间需求和计算资源消耗,是影响在各硬件平台上的落地的重要原因之一。尤其在NLP领域,以BERT、GPT为代表的预训练模型规模越来越大。

    针对部署难题,可以使用剪枝、量化、蒸馏等传统的模型压缩技术,但是这些模型压缩技术整体的流程较长,直接串行结合的效果不佳。而OFA(Once For All)[1]技术巧妙地结合了剪枝、蒸馏和结构搜索策略,不仅提升了压缩效果,还简化了压缩流程。

    百度飞桨模型压缩工具PaddleSlim新增支持OFA这一实用功能,并在BERT和GAN模型上做了验证:对于BERT模型实现了近2倍的加速;而对GAN模型则实现了33倍的体积压缩。除此以外,PaddleSlim还为用户提供了简单易用且低侵入的轻量级接口,用户无需修改模型训练代码,即可完成OFA压缩。

    图 PaddleSlim OFA接口示意图

    如上图所示,OFA涉及多个复杂的操作,包括按重要性对权重重排、剪枝、蒸馏、子模型搜索等,PaddleSlim将这些操作隐藏到底层,提供给用户简单的适用接口。更重要的是,PaddleSlim提供的接口对用户代码是低侵入的,用户不用修改现有的模型训练代码,通过调用PaddleSlim的转换接口即可将原有模型自动转换为超网络。

    项目链接:

    https://github.com/PaddlePaddle/PaddleSlim

    信息来源:飞桨PaddlePaddle

    04

    C和C++不安全?谷歌宣布Android加入对Rust语言支持

    Android 系统涉及很多组件,开发者会根据正在开发的 Android 部分而选择不同的编程语言。对于应用开发者来说,Java 和 Kotlin 是比较流行的选择;而对于从事操作系统以及内部底层的开发人员来说,C 和 C++ 是比较好的选择。

    近日,谷歌为操作系统开发者增加了第 3 个选择 Rust。谷歌发布博客称 AOSP (Android Open Source Project) 现已支持使用 Rust 开发 Android 操作系统。

    谷歌表示,用 Rust 重写数千万行的 C 和 c++ Android 代码根本不可行,而重写旧的 Android 不会有太大影响,因为到目前为止旧代码已经清除了大部分 bug。由于 Android 源代码是一个拥有数十亿用户的开源项目,很多人都在关注它。大部分内存 bug 都发生在新的或最近修改过的代码中,大约 50% 的错误发生在不到一年的时间里。必要时,Rust 将用于新组件,这将有助于减少谷歌可能引入的新内存 bug。

    Android 内存 bug 图表。旧代码有很多 bug,现在已经修复了。

    比较罕见的旧内存 bug 可能会让人感到惊讶,但谷歌表示旧代码并不是最迫切需要改进的地方。随着时间的推移,软件 bug 会被逐渐发现和修复,因此我们可以预期还在维护但未处于活跃开发状态的代码中的错误量会逐渐减少。

    无论如何,向 Android 平台添加新的开发语言支持是一项大工程。谷歌表示:「在过去的 18 个月里,我们一直在为 Android 开源项目添加 Rust 支持,在接下来的几个月里,我们将分享一些早期采用 Rust 的项目。将 Rust 扩展到更多的 OS 是一个长期项目。」

    信息来源:机器之心

    05

    黑客用GitHub服务器挖矿,三天跑了3万个任务,代码惊现中文

    加密货币价格一路高涨,显卡又买不起,怎么才能“廉价”挖矿?

    黑客们动起了歪心思——“白嫖”服务器。

    给PC植入挖矿木马,已经无法满足黑客日益增长的算力需求,如果能用上GitHub的服务器,还不花钱,那当然是极好的。

    原理也很简单,利用GitHub Action的自动执行工作流功能,轻松将挖矿程序运行在GitHub的服务器上。

    Github Actions的免费服务器可以提供英特尔E5 2673v4的两个核心,7GB内存。

    大致估算单台运行一天只能获利几美分,而且黑客的挖矿程序通常只能在被发现之前运行几个小时。比如Docker Hub就把自动build的运行时间限制在2个小时。

    不过蚊子再小也是肉,黑客通过寻找更多接受公开Action的仓库以及反复打开关闭Pull Request就能执行更多的挖矿程序。

    △同一黑客账号至少攻击了95个GitHub仓库

    正如Twitter用户Dave Walker所说的,如果你提供免费的计算资源,就要做好会被攻击和滥用的觉悟。挖矿有利可图的情况下这是不可避免的。

    据报道,受害的不止GitHub,还有Docker Hub、Travis CI以及Circle CI等提供类似服务的持续集成平台。

    这一乱象不知何时才能结束,唯一的好消息可能就是,挖矿的黑客似乎只是针对GitHub提供的服务器资源,而不会破坏你的代码。

    但是GitHub Action的漏洞不止这一个。还有方法能使黑客读写开发者的仓库,甚至可以读取加密的机密文件。

    去年7月,Google Project Zero团队就已向GitHub通报漏洞。但在给出的90天修复期限+延长14天后,GitHub仍未能有效解决。

    对此,我们的建议是,不要轻易相信GitHub市场里的Action作者,不要交出你的密匙。

    信息来源:量子位

    飞桨(PaddlePaddle)以百度多年的深度学习技术研究和业务应用为基础,是中国首个开源开放、技术领先、功能完备的产业级深度学习平台,包括飞桨开源平台和飞桨企业版。飞桨开源平台包含核心框架、基础模型库、端到端开发套件与工具组件,持续开源核心能力,为产业、学术、科研创新提供基础底座。飞桨企业版基于飞桨开源平台,针对企业级需求增强了相应特性,包含零门槛AI开发平台EasyDL和全功能AI开发平台BML。EasyDL主要面向中小企业,提供零门槛、预置丰富网络和模型、便捷高效的开发平台;BML是为大型企业提供的功能全面、可灵活定制和被深度集成的开发平台。

    END

    展开全文
  • 从右向左的语言,比如希伯来阿拉伯语。 Passolo 非常易于使用易于优化本地化过程。使用者既不需要大量的时间也不需要昂贵的 培训费用,更加不需要任何的编程经验。软件本地化工作可以在不接触源代码情况下...
  • 能翻译为任何人类语言,包括阿拉伯语,中文,希腊语,希伯来语,日语,韩语以及任何用户自定义语言。 可翻译为可视化文本(所见即所得)。所以所有用户都可对之进行翻译,包括您,您的翻译,或者身在其他国家的合作...
  • 免费翻译超过50种不同的语言!...免费翻译是一个高级翻译扩展产品,能够轻松翻译超过55种语言(包括英文,德文,意大利文,法文,日文,中文,西班牙文,俄文,阿拉伯文,葡萄牙文和希伯来文)。 支持语言:English
  • FreeType 管理字形

    千次阅读 2017-03-07 11:10:50
    1.字形度量 ... 通常一个字形有两个度量集:用来排版水平文本排列的字形(拉丁文、西里尔文、阿拉伯文、希伯来文等等)用来排版垂直文本排列的字形(中文、日文、韩文等等)。  要注意的是

    转自:http://blog.csdn.net/hgl868/article/details/7254687

    1.字形度量


         顾名思义,字形度量是对应每一个字形的特定距离,以此描述如何对文本排版。
         通常一个字形有两个度量集:用来排版水平文本排列的字形(拉丁文、西里尔文、阿拉伯文、希伯来文等等)和用来排版垂直文本排列的字形(中文、日文、韩文等等)。
         要注意的是只有很少的字体格式提供了垂直度量。你可以使用宏FT_HAS_VERTICAL测试某个给出的face对象是否包含垂直度量,当结果为真时表示包含垂直度量。
         每个的字形度量都可以先装载字形到face的字形槽,然后通过face->glyph->metrics结构访问,其类型为FT_Glyph_Metrics。我们将在下面详细讨论它,现在,我们只关注该结构包含如下的字段:

        Width
        这是字形图像的边框的宽度。它与排列方向无关。
        Height
        这是字形图像的边框的高度。它与排列方向无关。千万不要把它和FT_Size_Metrics的height字段混淆。
        horiBearingX
        用于水平文本排列,这是从当前光标位置到字形图像最左边的边界的水平距离。
        horiBearingY
        用于水平文本排列,这是从当前光标位置(位于基线)到字形图像最上边的边界的水平距离。 horiAdvance
        用于水平文本排列,当字形作为字符串的一部分被绘制时,这用来增加笔位置的水平距离。
        vertBearingX
        用于垂直文本排列,这是从当前光标位置到字形图像最左边的边框的垂直距离。
        vertBearingY
        用于垂直文本排列,这是从当前光标位置(位于基线)到字形图像最上边的边框的垂直距离。 vertAdvance
        用于垂直文本排列,当字形作为字符串的一部分被绘制时,这用来增加笔位置的垂直距离。
        注意:因为不是所有的字体都包含垂直度量,当FT_HAS_VERTICAL为假时,vertBearingX,vertBearingY和vertAdvance的值是不可靠的。

         下面的图形更清楚地图解了度量。第一个图解了水平度量,其基线为水平轴:

    对于垂直文本排列,基线是垂直的,与垂直轴一致:

    Face->glyph->metrics中的度量通常以26.6象素格式(例如1/64象素)表示,除非你在调用FT_Load_Glyph或FT_Load_Char时使用了FT_LOAD_NO_SCALE标志,这样的话度量会用原始字体单位表示。
         字形槽(glyph slot)对象也有一些其他有趣的字段可以减轻开发者的工作。你可以通过face->glyph->xxx访问它们,其中xxx是下面字段之一:

        Advance
        这个字段是一个FT_Vector,保存字形的经变换步长。当你通过FT_Set_Transform使用变换时,这是很有用的,这在第一部分的循环文本例子中已经展示过了。这个值是默认的(metrics.horiAdvance,0),除非你在装载字形图像时指定FT_LOAD_VERTICAL,那么它将会为(0,metrics.vertAdvance),这点与第一部分的例子不同。
        linearHoriAdvance
        这个字段包含字形水平推进宽度的线性刻度值。实际上,字形槽返回的metrics.horiAdvance值通常四舍五入为整数象素坐标(例如,它是64的倍数),字体驱动器用它装载字形图像。linearHoriAdvance是一个16.16固定浮点数,提供了以1/65536象素为单位的原始字形推进宽度的值。它可以用来完成伪设备无关文字排版。
        linearVertAdvance
        这与linearHoriAdvance类似,但它用于字形的垂直推进高度。只有当字体face包含垂直度量时这个值才是可靠的。

    2.管理字形图像

         装载到字形槽的字形可以转换到一幅字形位图中,这可以在装载时使用FT_LOAD_RENDER标志或者调用FT_Render_Glyph函数实现。每一次你装载一个新的字形到字形槽,前面装载的字形将会从字形槽中抹去。
         但是,你可能需要从字形槽中提取这个字形,并在你的应用程序中缓存它,或者进行附加的变换,或者在转换成位图前测量它。
         FreeType 2 API有一个特殊的扩展能够以一种灵活和普通的方式处理字形图像。要使用它,你首先需要包含FT_GLYPH_H头文件,如下:

    #include FT_GLYPH_H

         现在我们将解释如何使用这个文件定义的这个函数。

    a.提取字形图像

         你可以很简单地提取一个字形图像。这里有一向代码向你展示如何去做:

    FT_Glyph glyph; /* 字形图像的句柄 */

    ...
    error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NORMAL );
    if ( error ) { ... }

    error = FT_Get_Glyph( face->glyph, &glyph );
    if ( error ) { ... }

         显而易见,我们:

        * 创建一个类型为FT_Glyph,名为glyph的变量。这是一个字形图像的句柄(即指针)。

        * 装载字形图像(通常情况下)到face的字形槽中。我们不使用FT_LOAD_RENDER因为我们想抓取一个可缩放的字形图像,以便后面对其进行变换。

        * 通过调用FT_Get_Glyph,把字形图像从字形槽复制到新的FT_Glyph对象glyph中。这个函数返回一个错误码并且设置glyph。

         要非常留意,被取出的字形跟字形槽中的原始字形的格式是一样的。例如,如果我们从TrueType字体文件中装载一个字形,字形图像将是可伸缩的矢量轮廓。

         如果你想知道字形是如何建模和存储的,你可以访问flyph->format字段。一个字形对象可以通过调用FT_Done_Glyph来销毁。

         字形对象正好包含一个字形图像和一个2D矢量,2D矢量以16.16固定浮点坐标的形式表示字形的推进步长。后者可以直接通过glyph->advance访问它。

         注意,不同于其他TrueType对象,库不保存全部分配了的字形对象的列表。这意味着你必须自己销毁它们,而不是依靠FT_Done_FreeType完成全部的清除。

    b.变换和复制字形图像

         如果字形图像是可伸缩的(glyph->format不等于FT_GLYPH_FORMAT_BITMAP),那么就可以随时通过调用FT_Glyph_Transform来变换该图像。

         你也可以通过FT_Glyph_Copy复制一个字形图像。这里是一些例子代码:

    FT_Glyph glyph, glyph2;
    FT_Matrix matrix;
    FT_Vector delta;

    ... 装载字形图像到 `glyph' ...

    /* 复制 glyph 到 glyph2 */
    error = FT_Glyph_Copy( glyph, &glyph2 );
    if ( error ) { ... 无法复制(内存不足) ... }

    /* 平移 `glyph' */
    delta.x = -100 * 64; /* 坐标是 26.6 象素格式的 */
    delta.y = 50 * 64;
    FT_Glyph_Transform( glyph, 0, &delta );

    /* 变换 glyph2 (水平剪切) */
    matrix.xx = 0x10000L;
    matrix.xy = 0.12 * 0x10000L;
    matrix.yx = 0;
    matrix.yy = 0x10000L;
    FT_Glyph_Transform( glyph2, &matrix, 0 );

         注意,2×2矩阵变换总是适用于字形的16.16推进步长矢量,所以你不需要重修计算它。

    c.测量字形图像

         你也可以通过FT_Glyph_Get_CBox函数检索任意字形图像(无论是可伸缩或者不可伸缩的)的控制(约束)框,如下:

    FT_BBox bbox;
    ...
    FT_Glyph_Get_CBox( glyph, bbox_mode, &bbox );

         坐标是跟字形的原点(0, 0)相关的,使用y向上的约定。这个函数取一个特殊的参数:bbox_mode来指出如何表示框坐标。

         如果字形装载时使用了FT_LOAD_NO_SCALE标志,bbox_mode必须设置为FT_GLYPH_BBOX_UNSCALED,以此来获得以26.6象素格式为单位表示的不可缩放字体。值FT_GLYPH_BBOX_SUBPIXELS是这个常量的另一个名字。

         要注意,框(box)的最大坐标是唯一的,这意味着你总是可以以整数或26.6象素的形式计算字形图像的宽度和高度,公式如下:

    width = bbox.xMax - bbox.xMin;
    height = bbox.yMax - bbox.yMin;

         同时要注意,对于26.6坐标,如果FT_GLYPH_BBOX_GRIDFIT被用作为bbox_mode,坐标也将网格对齐,符合如下公式:

    bbox.xMin = FLOOR( bbox.xMin )
    bbox.yMin = FLOOR( bbox.yMin )
    bbox.xMax = CEILING( bbox.xMax )
    bbox.yMax = CEILING( bbox.yMax )

         要把bbox以整数象素坐标的形式表示,把bbox_mode设置为FT_GLYPH_BBOX_TRUNCATE。

         最后,要把约束框以网格对齐象素坐标的形式表示,把bbox_mode设置为FT_GLYPH_BBOX_PIXELS。

    d.转换字形图像为位图

         当你已经把字形对象缓存或者变换后,你可能需要转换它到一个位图。这可以通过FT_Glyph_To_Bitmap函数简单得实现。它负责转换任何字形对象到位图,如下:

    FT_Vector origin;

    origin.x = 32; /* 26.6格式的1/2象素 */
    origin.y = 0;
    error = FT_Glyph_To_Bitmap(
        &glyph,
        render_mode,
        &origin,
        1 ); /* 销毁原始图像 == true */

         一些注解:

        * 第一个参数是源字形句柄的地址。当这个函数被调用时,它读取该参数来访问源字形对象。调用结束后,这个句柄将指向一个新的包含渲染后的位图的字形对象。

        * 第二个参数时一个标准渲染模式,用来指定我们想要哪种位图。它取FT_RENDER_MODE_DEFAULT时表示8位颜色深度的抗锯齿位图;它取FT_RENDER_MODE_MONO时表示1位颜色深度的黑白位图。

        * 第三个参数是二维矢量的指针。该二维矢量是用来在转换前平移源字形图像的。要注意,函数调用后源图像将被平移回它的原始位置(这样源图像便不会有变化)。如果你在渲染前不需要平移源字形,设置这个指针为0。

        * 最后一个参数是一个布尔值,用来指示该函数是否要销毁源字形对象。如果为false,源字形对象不会被销毁,但是它的句柄丢失了(客户应用程序需要自己保留句柄)。

         如果没返回错误,新的字形对象总是包含一个位图。并且你必须把它的句柄进行强制类型转换,转换为FT_BitmapGlyph类型,以此访问它的内容。这个类型是FT_Glyph的一种“子类”,它包含下面的附加字段(看FT_BitmapGlyphRec):

        Left

        类似于字形槽的bitmap_left字段。这是字形原点(0,0)到字形位图最左边象素的水平距离。它以整数象素的形式表示。

        Top

        类似于字形槽的bitmap_top字段。它是字形原点(0,0)到字形位图最高象素之间的垂直距离(更精确来说,到位图最上面的象素)。这个距离以整数象素的形式表示,并且y轴向上为正。

        Bitmap

        这是一个字形对象的位图描述符,就像字形槽的bitmap字段。

    3.全局字形度量

         不同于字形度量,全局度量是用来描述整个字体face的距离和轮廓的。他们可以用26.6象素格式或者可缩放格式的“字体单位”来表示。

    a.预设全局度量

         对于可缩放格式,全部全局度量都是以字体单位的格式表示的,这可以用来在稍后依照本教程本部分的最后一章描述的规则来缩放到设备空间。你可以通过FT_Face句柄的字段直接访问它们。

         然而,你需要在使用它们前检查字体face的格式是否可缩放。你可以使用宏FT_IS_SCALEABLE来实现,当该字体是可缩放时它返回正。

    如果是这样,你就可以访问全局预设度量了,如下:

        units_per_EM

        这是字体face的EM正方形的大小。它是可缩放格式用来缩放预设坐标到设备象素的,我们在这部分的最后一章叙述它。通常这个值为2048(对于TrueType)或者1000(对于Type 1),但是其他值也是可能的。对于固定尺寸格式,如FNT/FON/PCF/BDF,它的值为1。

        global_bbox

        全局约束框被定义为最大矩形,该矩形可以包围字体face的所有字形。它只为水平排版而定义。

        ascender

        Ascender是从水平基线到字体face最高“字符”的坐标之间的垂直距离。不幸地,不同的字体格式对ascender的定义是不同的。对于某些来说,它代表了全部大写拉丁字符(重音符合除外)的上沿值(ascent);对于其他,它代表了最高的重音符号的上沿值(ascent);最后,其他格式把它定义为跟global_bbox.yMax相同。

        descender

        Descender是从水平基线到字体face最低“字符”的坐标之间的垂直距离。不幸地,不同的字体格式对descender的定义是不同的。对于某些来说,它代表了全部大写拉丁字符(重音符合除外)的下沿值(descent);对于其他,它代表了最高的重音符号的下沿值(descent);最后,其他格式把它定义为跟global_bbox.yMin相同。这个字段的值是负数。

        text_height

        这个字段是在使用这个字体书写文本时用来计算默认的行距的(例如,基线到基线之间的距离)。注意,通常它都比ascender和descent的绝对值之和还要大。另外,不保证使用这个距离后面就没有字形高于或低于基线。

        max_advance_width

        这个字段指出了字体中所有字形得最大的水平光标推进宽度。它可以用来快速计算字符串得最大推进宽度。它不等于最大字形图像宽度!

        max_advance_height

        跟max_advance_width一样,但是用在垂直文本排版。它只在字体提供垂直字形度量时才可用。

        underline_position

        当显示或者渲染下划线文本时,这个值等于下划线到基线的垂直距离。当下划线低于基线时这个值为负数。

        underline_thickness

        当显示或者渲染下划线文本时,这个值等于下划线的垂直宽度。

         现在注意,很不幸的,由于字体格式多种多样,ascender和descender的值是不可靠的。

    b.伸缩的全局度量

         每一个size对象同时包含了上面描述的某些全局度量的伸缩版本。它们可以通过face->size->metrics结构直接访问。

    注意这些值等于预设全局变量的伸缩版本,但没有做舍入或网格对齐。它们也完全独立于任何hinting处理。换句话说,不要依靠它们来获取象素级别的精确度量。它们以26.6象素格式表示。

        ascender

        原始预设ascender的伸缩版本。

        descender

        原始预设ascender的伸缩版本。

        height

        原始预设文本高度(text_height)的伸缩版本。这可能是这个结构中你真正会用到的字段。

        max_advance

        原始预设最大推进的伸缩版本。

         注意,face->size->metrics结构还包含其他字段,用来伸缩预设坐标到设备空间。它们会在最后一章描述。

    c.字距调整

         字距调整是调整字符串中两个并排的字形图像位置的过程,它可以改善文本的整体外观。基本上,这意味着当‘A’的跟着‘V’时,它们之间的间距可以稍微减少,以此避免额外的“对角线空白”。

         注意,理论上字距调整适用于水平和垂直方向的两个字形,但是,除了非常极端的情况外,几乎在所有情况下,它只会发生在水平方向。

         不是所有的字体格式包含字距调整信息。有时候它们依赖于一个附加的文件来保存不同的字形度量,包括字距调整,但该文件不包含字形图像。一个显著的例子就是Type1格式。它的字形图像保存在一个扩展名为.pfa或.pfb的文件中,字距调整度量存放在一个附加的扩展名为.afm或.pfm的文件中。

         FreeType 2提供了FT_Attach_File和FT_Attach_Stream API来让你处理这种情况。两个函数都是用来装载附加的度量到一个face对象中,它通过从附加的特定格式文件中读取字距调整度量来实现。例如,你可以象下面那样打开一个Type1字体:

    error = FT_New_Face( library, "/usr/shared/fonts/cour.pfb",
        0, &face );
    if ( error ) { ... }

    error = FT_Attach_File( face, "/usr/shared/fonts/cour.afm" );
    if ( error )
    { ... 没能读取字距调整和附加的度量 ... }

         注意,FT_Attach_Stream跟FT_Attach_File是类似的,不同的是它不是以C字符串指定附加文件,而是以一个FT_Stream句柄。另外,读取一个度量文件不是强制性的。

    最后,文件附加API是非常通用的,可以用来从指定的face中装载不同类型的附加信息。附加内容的种类完全是因字体格式而异的。

         FreeType 2允许你通过FT_Get_Kerning函数获取两个字形的字距调整信息,该函数界面如下:

    FT_Vector kerning;
    ...
    error = FT_Get_Kerning( face, /* face对象的句柄 */
        left, /* 左边字形索引 */
        right, /* 右边字形索引 */
        kerning_mode, /* 字距调整模式 */
        &kerning ); /* 目标矢量 */

         正如你所见到的,这个函数的参数有一个face对象的句柄、字距调整值所要求的左边和右边字形索引,以及一个称为字距调整模式的整数,和目标矢量的指针。目标矢量返回适合的距离值。

         字距调整模式跟前一章描述的bbox模式(bbox mode)是很类似的。这是一个枚举值,指示了目标矢量如何表示字距调整距离。

         默认值是FT_KERNING_DEFAULT,其数值为0。它指示字距调整距离以26.6网格对齐象素(这意味着该值是64的倍数)的形式表示。对于可伸缩格式,这意味着返回值是把预设字距调整距离先伸缩,然后舍入。

         值FT_KERNING_UNFITTED指示了字距调整距离以26.6非对齐象素(也就是,那不符合整数坐标)的形式表示。返回值是把预设字距调整伸缩,但不舍入。

         最后,值FT_KERNING_UNSCALED是用来返回预设字距调整距离,它以字体单位的格式表示。你可以在稍后用本部分的最后一章描述的算式把它拉伸到设备空间。

         注意,“左”和“右”位置是指字符串字形的可视顺序。这对双向或由右到左的文本来说是很重要的。

    4.简单的文本渲染:字距调整+居中

         为了显示我们刚刚学到的知识,现在我们将示范如何修改第一部分给出的代码以渲染一个字符串,并且增强它,使它支持字距调整和延迟渲染。

    a.字距调整支持

         要是我们只考虑处理从左到右的文字,如拉丁文,那在我们的代码上添加字距调整是很容易办到的。我们只要获取两个字形之间的字距调整距离,然后适当地改变笔位置。代码如下:

    FT_GlyphSlot slot = face->glyph; /* 一个小捷径 */
    FT_UInt glyph_index;
    FT_Bool use_kerning;
    FT_UInt previous;
    int pen_x, pen_y, n;

    ... 初始化库 ...
    ... 创建face对象 ...
    ... 设置字符尺寸 ...

    pen_x = 300;
    pen_y = 200;
    use_kerning = FT_HAS_KERNING( face );
    previous = 0;

    for ( n = 0; n < num_chars; n++ )
    {
        /* 把字符码转换为字形索引 */
        glyph_index = FT_Get_Char_Index( face, text[n] );

        /* 获取字距调整距离,并且移动笔位置 */
        if ( use_kerning && previous && glyph_index )
        {
            FT_Vector delta;
            FT_Get_Kerning( face, previous, glyph_index,
                ft_kerning_mode_default, &delta );

            pen_x += delta.x >> 6;
        }

        /* 装载字形图像到字形槽(擦除之前的字形图像) */
        Error = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER);

        if ( error )
            continue; /* 忽略错误 */

        /* 现在绘制到我们的目标表面(surface) */
        my_draw_bitmap( &slot->bitmap,

        pen_x + slot->bitmap_left,
        pen_y - slot->bitmap_top );

        /* 增加笔位置 */
        pen_x += slot->advance.x >> 6;

        /* 记录当前字形索引 */
        previous = glyph_index;
    }

    若干注解:

        * 因为字距调整是由字形索引决定的,我们需要显式转换我们的字符代码到字形索引,然后调用FT_Load_Glyph而不是FT_Load_Char。

        * 我们使用一个名为use_kerning的变量,它的值为宏FT_HAS_KERNING的结果。当我们知道字体face不含有字距调整信息,不调用FT_Get_kerning程序将执行得更快。

        * 我们在绘制一个新字形前移动笔位置。

        * 我们以值0初始化变量previous,这表示“字形缺失(missing glyph)”(在Postscript中,这用.notdef表示)。该字形也没有字距调整距离。

        * 我们不检查FT_Get_kerning返回得错误码。这是因为这个函数在错误发生时总是把delta置为(0,0)。

    b.居中

         我们的代码开始变得有趣了,但对普通应用来说仍然有点太简单了。例如,笔的位置在我们渲染前就决定了。通常,你要在计算文本的最终位置(居中,等)前布局它和测量它,或者执行自动换行。

         现在让我们把文字渲染函数分解为两个截然不同但连续的两部分:第一部分将在基线上定位每一个字形图像,第二部分将渲染字形。我们将看到,这有很多好处。

         我们先保存每一个独立的字形图像,以及它们在基线上面的位置。这可以通过如下的代码完成:

    FT_GlyphSlot slot = face->glyph; /* 一个小捷径 */
    FT_UInt glyph_index;
    FT_Bool use_kerning;
    FT_UInt previous;
    int pen_x, pen_y, n;
    FT_Glyph glyphs[MAX_GLYPHS]; /* 字形图像 */
    FT_Vector pos [MAX_GLYPHS]; /* 字形位置 */
    FT_UInt num_glyphs; 

    ... 初始化库 ...
    ... 创建face对象 ...
    ... 设置字符尺寸 ... 

    pen_x = 0; /* 以 (0,0) 开始 */
    pen_y = 0;
    num_glyphs = 0;
    use_kerning = FT_HAS_KERNING( face );
    previous = 0;
    for ( n = 0; n < num_chars; n++ )
    {
        /* 把字符码转换为字形索引 */
        glyph_index = FT_Get_Char_Index( face, text[n] ); 

        /* 获取字距调整距离,并且移动笔位置 */
        if ( use_kerning && previous && glyph_index )
        {
        FT_Vector delta;
        FT_Get_Kerning( face, previous, glyph_index,
            FT_KERNING_DEFAULT, &delta );
            pen_x += delta.x >> 6;
            } 

        /* 保存当前笔位置 */
        pos[num_glyphs].x = pen_x;
        pos[num_glyphs].y = pen_y; 

        /* 装载字形图像到字形槽,不渲染它 */
        error=FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); 

        if ( error )
            continue; /* 忽略错误,跳到下一个字形 */ 

        /* 提取字形图像并把它保存在我们的表中 */
        error = FT_Get_Glyph( face->glyph, &glyphs[num_glyphs] );
        if ( error )
            continue; /* 忽略错误,跳到下一个字形 */ 

        /* 增加笔位置 */
        pen_x += slot->advance.x >> 6; 

        /* 记录当前字形索引 */
        previous = glyph_index; 

        /* 增加字形数量 */
        num_glyphs++;


         相对于我们之前的代码,这有轻微的变化:我们从字形槽中提取每一个字形图像,保存每一个字形图像和它对应的位置在我们的表中。

         注意pen_x包含字符串的整体前移值。现在我们可以用一个很简单的函数计算字符串的边界框(bounding box),如下:

    void compute_string_bbox( FT_BBox *abbox )
    {
        FT_BBox bbox;
        /* 初始化字符串bbox为“空”值 */
        bbox.xMin = bbox.yMin = 32000;
        bbox.xMax = bbox.yMax = -32000; 

        /* 对于每一个字形图像,计算它的边界框,平移它,并且增加字符串bbox */
        for ( n = 0; n < num_glyphs; n++ )
        {
            FT_BBox glyph_bbox;
            FT_Glyph_Get_CBox( glyphs[n], ft_glyph_bbox_pixels,
                &glyph_bbox ); 

            glyph_bbox.xMin += pos[n].x;
            glyph_bbox.xMax += pos[n].x;
            glyph_bbox.yMin += pos[n].y;
            glyph_bbox.yMax += pos[n].y; 

            if ( glyph_bbox.xMin < bbox.xMin )
                bbox.xMin = glyph_bbox.xMin; 

            if ( glyph_bbox.yMin < bbox.yMin )
                bbox.yMin = glyph_bbox.yMin; 

            if ( glyph_bbox.xMax > bbox.xMax )
                bbox.xMax = glyph_bbox.xMax; 

            if ( glyph_bbox.yMax > bbox.yMax )
                bbox.yMax = glyph_bbox.yMax;
        } 

        /* 检查我们是否真的增加了字符串bbox */
        if ( bbox.xMin > bbox.xMax )
        {
            bbox.xMin = 0;
            bbox.yMin = 0;
            bbox.xMax = 0;
            bbox.yMax = 0;
        } 

        /* 返回字符串bbox */
        *abbox = bbox;


         最终得到的边界框尺寸以整数象素的格式表示,并且可以随后在渲染字符串前用来计算最终的笔位置,如下:

    /* 计算整数象素表示的字符串尺度 */
    string_width = string_bbox.xMax - string_bbox.xMin;
    string_height = string_bbox.yMax - string_bbox.yMin; 

    /* 计算以26.6笛卡儿象素表示的笔起始位置*/
    start_x = ( ( my_target_width - string_width ) / 2 ) * 64;
    start_y = ( ( my_target_height - string_height ) / 2 ) * 64;
    for ( n = 0; n < num_glyphs; n++ )
    {
        FT_Glyph image;
        FT_Vector pen;
        image = glyphs[n]; 

        pen.x = start_x + pos[n].x;
        pen.y = start_y + pos[n].y;
        error = FT_Glyph_To_Bitmap(&image, FT_RENDER_MODE_NORMAL,
            &pen, 0 );
        if ( !error )
        {
            FT_BitmapGlyph bit = (FT_BitmapGlyph)image;
            my_draw_bitmap( bit->bitmap,
                bit->left,
                my_target_height - bit->top );
            FT_Done_Glyph( image );
        }


        一些说明:

        * 笔位置以笛卡儿空间(例如,y向上)的形式表示。

        * 我们调用FT_Glyph_To_Bitmap时destroy参数设置为0(false),这是为了避免破坏原始字形图像。在执行该调用后,新的字形位图通过image访问,并且它的类型转变为FT_BitmapGlyph。

        * 当调用FT_Glyph_To_Bitmap时,我们使用了平移。这可以确保位图字形对象的左区域和上区域已经被设置为笛卡儿空间中的正确的象素坐标。

        * 当然,在渲染前我们仍然需要把象素坐标从笛卡儿空间转换到设备空间。因此在调用my_draw_bitmap前要先计算my_target_height – bitmap->top。

         相同的循环可以用来把字符串渲染到我们的显示面(surface)任意位置,而不需要每一次都重新装载我们的字形图像。我们也可以决定实现自动换行或者只是绘制。

    5.高级文本渲染:变换 + 居中 + 字距调整

         现在我们将修改我们的代码,以便可以容易地变换已渲染的字符串,例如旋转它。我们将以实行少许小改进开始:

    a.打包然后平移字形

         我们先把与一个字形图像相关的信息打包到一个结构体,而不是并行的数组。因此我们定义下面的结构体类型:

    typedef struct TGlyph_
    {
        FT_UInt index; /* 字形索引 */
        FT_Vector pos; /* 基线上面的字形原点 */
        FT_Glyph image; /* 字形图像 */
    } TGlyph, *PGlyph; 

         我们在装载每一个字形图像过程中,在把它装载它在基线所在位置后便直接平移它。我们将看到,这有若干好处。我们的字形序列装载其因而变成:

    FT_GlyphSlot slot = face->glyph; /* 一个小捷径 */
    FT_UInt glyph_index;
    FT_Bool use_kerning;
    FT_UInt previous;
    int pen_x, pen_y, n;
    TGlyph glyphs[MAX_GLYPHS]; /* 字形表 */
    PGlyph glyph; /* 表中的当前字形*/
    FT_UInt num_glyphs; 

    ... 初始化库 ...
    ... 创建face对象 ...
    ... 设置字符尺寸 ... 

    pen_x = 0; /* 以 (0,0) 开始 */
    pen_y = 0;
    num_glyphs = 0;
    use_kerning = FT_HAS_KERNING( face );
    previous = 0;
    glyph = glyphs;
    for ( n = 0; n < num_chars; n++ )
    {
        glyph->index = FT_Get_Char_Index( face, text[n] );
        if ( use_kerning && previous && glyph->index )
        {
            FT_Vector delta;
            FT_Get_Kerning( face, previous, glyph->index,
                FT_KERNING_MODE_DEFAULT, &delta ); 

            pen_x += delta.x >> 6;
        } 

        /* 保存当前笔位置 */
        glyph->pos.x = pen_x;
        glyph->pos.y = pen_y;
        error = FT_Load_Glyph(face,glyph_index,FT_LOAD_DEFAULT);
        if ( error ) continue; 

        error = FT_Get_Glyph( face->glyph, &glyph->image );
        if ( error ) continue; 

        /* 现在平移字形图像 */
        FT_Glyph_Transform( glyph->image, 0, &glyph->pos );
        pen_x += slot->advance.x >> 6;
        previous = glyph->index; 

        /* 增加字形的数量 */
        glyph++;


    /* 计算已装载的字形的数量 */
    num_glyphs = glyph - glyphs;

         注意,这个时候平移字形有若干好处。第一是当我们计算字符串的边界框时不需要平移字形bbox。代码将会变成这样:

    void compute_string_bbox( FT_BBox *abbox )
    {
        FT_BBox bbox;
        bbox.xMin = bbox.yMin = 32000;
        bbox.xMax = bbox.yMax = -32000;
        for ( n = 0; n < num_glyphs; n++ )
        {
            FT_BBox glyph_bbox;
            FT_Glyph_Get_CBox( glyphs[n], &glyph_bbox );
            if (glyph_bbox.xMin < bbox.xMin)
                bbox.xMin = glyph_bbox.xMin; 

            if (glyph_bbox.yMin < bbox.yMin)
                bbox.yMin = glyph_bbox.yMin; 

            if (glyph_bbox.xMax > bbox.xMax)
                bbox.xMax = glyph_bbox.xMax; 

            if (glyph_bbox.yMax > bbox.yMax)
                bbox.yMax = glyph_bbox.yMax;
        } 

        if ( bbox.xMin > bbox.xMax )
        {
            bbox.xMin = 0;
            bbox.yMin = 0;
            bbox.xMax = 0;
            bbox.yMax = 0;
        } 

        *abbox = bbox;


         更详细描述:compute_string_bbox函数现在可以计算一个已转换的字形字符串的边界框。例如,我们可以做如下的事情:

    FT_BBox bbox;
    FT_Matrix matrix;
    FT_Vector delta; 

    ... 装载字形序列 ...
    ... 设置 "matrix" 和 "delta" ... 

    /* 变换字形 */
    for ( n = 0; n < num_glyphs; n++ )
        FT_Glyph_Transform( glyphs[n].image, &matrix, &delta ); 

    /* 计算已变换字形的边界框 */
    compute_string_bbox( &bbox ); 

    b.渲染一个已变换的字形序列

         无论如何,如果我们想重用字形来以不同的角度或变换方式绘制字符串,直接变换序列中的字形都不是一个好主意。更好的方法是在字形被渲染前执行放射变换,如下面的代码所示:

    FT_Vector start;
    FT_Matrix transform; 

    /* 获取原始字形序列的 bbox */
    compute_string_bbox( &string_bbox ); 

    /* 计算整数象素表示的字符串尺度 */
    string_width = (string_bbox.xMax - string_bbox.xMin) / 64;
    string_height = (string_bbox.yMax - string_bbox.yMin) / 64; 

    /* 设置26.6笛卡儿空间表示的笔起始位置 */
    start.x = ( ( my_target_width - string_width ) / 2 ) * 64;
    start.y = ( ( my_target_height - string_height ) / 2 ) * 64; 

    /* 设置变换(旋转) */
    matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
    matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
    matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
    matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L ); 

    for ( n = 0; n < num_glyphs; n++ )
    {
        FT_Glyph image;
        FT_Vector pen;
        FT_BBox bbox; 

        /* 创建原始字形的副本 */
        error = FT_Glyph_Copy( glyphs[n].image, &image );
        if ( error ) continue; 

        /* 变换副本(这将平移它到正确的位置) */
        FT_Glyph_Transform( image, &matrix, &start ); 

        /* 检查边界框;如果已变换的字形图像不在*/
        /* 我们的目标表面中,我们可以避免渲染它 */
        FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
        if ( bbox.xMax <= 0 || bbox.xMin >= my_target_width ||
            bbox.yMax <= 0 || bbox.yMin >= my_target_height )
            continue; 

        /* 把字形图像转换为位图(销毁字形的副本!) */
        error = FT_Glyph_To_Bitmap(
            &image,
            FT_RENDER_MODE_NORMAL,
            0, /* 没有附加的平移*/
            1 ); /* 销毁 "image" 指向的副本 */
        if ( !error )
        {
            FT_BitmapGlyph bit = (FT_BitmapGlyph)image;
            my_draw_bitmap( bitmap->bitmap,
            bitmap->left,
            my_target_height - bitmap->top );
            FT_Done_Glyph( image );
        }


         这份代码相对于原始版本有少许改变:

        * 我们没改变原始的字形图像,而是变换该字形图像的拷贝。

        * 我们执行“剪取”操作以处理渲染和绘制的字形不在我们的目标表面(surface)的情况。

        * 当调用FT_Glyhp_To_Bitmap时,我们总是销毁字形图像的拷贝,这是为了销毁已变换的图像。注意,即使当这个函数返回错误码,该图像依然会被销毁(这就是为什么FT_Done_Glyph只在复合语句中被调用的原因)。

        * 平移字形序列到起始笔位置集成到FT_Glyph_Transform函数,而不是FT_Glyph_To_Bitmap函数。

         可以多次调用这个函数以渲染字符串到不同角度的,或者甚至改变计算start的方法以移动它到另外的地方。

         这份代码是FreeType 2示范程序ftstring.c的基础。它可以被简单地扩展,在第一部发完成高级文本布局或自动换行,而第二部分不需改变。

         无论如何,要注意通常的实现会使用一个字形缓冲以减少内存消耗。据个例子,让我们假定我们的字符串是“FreeType”。我们将在我们的表中保存字母‘e’的三个相同的字形图像,这不是最佳的(特别是当你遇到更长的字符串或整个页面时)。

    6.以预设字体单位的格式访问度量,并且伸缩它们

         可伸缩的字体格式通常会为字体face中的每一个字形保存一份矢量图像,该矢量图像称为轮廓。每一个轮廓都定义在一个抽象的网格中,该网格被称为预设空间(design space),其坐标以名义上(nominal)的字体单位(font unit)表示。当装载一个字形图像时,字体驱动器通常会依照FT_Size对象所指定的当前字符象素尺寸把轮廓伸缩到设备空间。字体驱动器也能修改伸缩过的轮廓以大大地改善它在基于象素的表面(surface)中显示的效果。修改动作通常称为hinting或网格对齐。

         这一章描述了如何把预设坐标伸缩到设备空间,以及如何读取字形轮廓和如何获取以预设字体单位格式表示的度量。这对许多事情来说都是重要的:

        * 真正的所见即所得文字排版

        * 为了字体转换或者分析的目的而访问字体内容

    a.伸缩距离到设备空间

         我们使用一个简单的伸缩变换把预设坐标伸缩到设备空间。变换系数借助字符象素尺寸来计算:

    Device_x = design_x * x_scale
    Device_y = design_y * y_scale
    X_scale = pixel_size_x / EM_size
    Y_scale = pixel_size_y / EM_size

         这里,值EM_Size是因字体而异的,并且对应预设空间的一个抽象矩形(称为EM)的大小。字体设计者使用该矩形创建字形图像。EM_Size以字体单元的形式表示。对于可伸缩字体格式,可以通过face->unix_per_EM直接访问。你应该使用FT_IS_SCALABLE宏检查某个字体face是否包含可伸缩字形图像,当包含时该宏返回true。

         当你调用函数FT_Set_Pixel_Sizes,你便指定了pixel_size_x和pixel_size_y的值。FreeType库将会立即使用该值计算x_scale和y_scale的值。

         当你调用函数FT_Set_Char_Size,你便以物理点的形式指定了字符尺寸。FreeType库将会使用该值和设备的解析度来计算字符象素尺寸和相应的比例因子。

         注意,在调用上面提及的两个函数后,你可以通过访问face->size->metrices结构的字段得到字符象素尺寸和比例因子的值。这些字段是:

        X_ppem

        这个字段代表了“每一个EM的x方向象素”,这是以整数象素表示EM矩形的水平尺寸,也是字符水平象素尺寸,即上面例子所称的pixel_size_x。

        y_ppem

        这个字段代表了“每一个EM的y方向象素”,这是以整数象素表示EM矩形的垂直尺寸,也是字符垂直象素尺寸,即上面例子所称的pixel_size_y。

        X_scale

        这是一个16.16固定浮点比例,用来把水平距离从预设空间直接伸缩到1/64设备象素。

        y_scale

        这是一个16.16固定浮点比例,用来把垂直距离从预设空间直接伸缩到1/64设备象素。

         你可以借助FT_MulFix函数直接伸缩一个以26.6象素格式表示的距离,如下所示:

    /* 把预设距离转换到1/64象素 */
    pixels_x=FT_MulFix(design_x,face->size->metrics.x_scale);
    pixels_y=FT_MulFix(design_y,face->size->metrics.y_scale); 

    当然,你也可以使用双精度浮点数更精确地伸缩该值:
    FT_Size_Metrics* metrics = &face->size->metrics; /* 捷径 */ 

    double pixels_x, pixels_y;
    double em_size, x_scale, y_scale; 

    /* 计算浮点比例因子 */
    em_size = 1.0 * face->units_per_EM;
    x_scale = metrics->x_ppem / em_size;
    y_scale = metrics->y_ppem / em_size; 

    /* 把预设距离转换为浮点象素 */
    pixels_x = design_x * x_scale;
    pixels_y = design_y * y_scale; 

    b.访问预设度量(字形的和全局的)

         你可以以字体单位的格式访问字形度量,只要在调用FT_Load_Glyph或FT_Load_Char时简单地指定FT_LOAD_NO_SCALE位标志便可以了。度量返回在face->glyph_metrics,并且全部都以字体单位的格式表示。

         你可以使用FT_KERNING_MODE_UNSCALED模式访问未伸缩的字距调整数据。

    展开全文
  • 能翻译为任何人类语言,包括阿拉伯语,中文,希腊语,希伯来语,日语,韩语以及任何用户自定义语言。 可翻译为可视化文本(所见即所得)。所以所有用户都可对之进行翻译,包括您,您的翻译,或者身在其他国家的合作...
  • 文本可以被翻译为多种语言,包括亚洲语系(Unicode 码)以及书写方式为从右向左的语言,比如希伯来阿拉伯语。 Passolo 的使用非常容易,因此优化了软件的本地化过程。使用者既不需要进行耗时昂贵的培训,也不...
  • Qt 多语化--国际化

    千次阅读 2013-08-23 10:06:29
    QT除了采用英语和许多欧洲语系中的拉丁字母之外,它还提供了许多其他的位子系统。QT的整个应用程序编程的接口及其内部都是用的Unicode,...QT布局引擎--可以为从右到左的文本布局提供支持,比如阿拉伯文和希伯来文
  • CSS 文本方向 direction属性

    千次阅读 2018-02-13 22:23:25
    然而,并非所有语言都是如此,还有许多从右向左阅读的语言,如阿拉伯语和希伯来语等。于是,CSS2.1引入了 direction属性,用来定义文本流的书写方向,可选值有 ltr | rtl,默认值为 ltr。ltr(left-to-right)表示...
  • 史上最全的女生英文名字相应的意义来自 薄雾倾城 溺水的小舟发表 收录于昨天 72分享 来自: 鲜果网英文 中文 来源 涵意 Abigail 艾比盖 希伯来 父亲很高兴;得意的父亲 Ada 艾达 英国 增光;快乐的;美丽 Adela ...
  • JSP页面乱码问题的解决

    千次阅读 多人点赞 2012-03-25 21:19:58
    你新建一个JSP页面的话,就会发现默认编码为“ISO-8859-1”, ...汉字当然没有了,汉字的字符集为GBK(有繁体)GB2312(中文简体),GBK编码标准兼容GB2312。所以JSP页面一般有下面三条语句,基本
  • 设计为使用UNICODE的地址和联系人管理器,并链接NLSO-WEB系统以共享非个人地址数据。这将使创建可以打印英语和希伯来语(例如英语和中文)地址的应用程序成为可能
  • 该辞库包括由Babylon的语言学专家队伍分别以英文、法文、德文、西班牙文、意大利文、葡萄牙文、日文、希伯来文、繁体中文、简体中文、荷兰语、俄语、韩语以及瑞典语等十四种语言文字共同研发的25个专业辞典。...
  • 使用简单的CSS进行漂亮的打印。 ... ... HTML无缝转换为可以打印,下载存档的文档。...Prince使您可以排版,格式化打印HTML内容,因此您可以成为自己的发布者。...页眉页脚 ...阿拉伯文,希伯来文,北印度文等
  • 土耳其中文(繁体)、中文(简体)、丹麦、巴斯克、日文、加里西亚、加泰罗尼亚、卡纳达、布尔、白俄罗斯语、立陶宛、冰岛、匈牙利、印尼、印度、印度古哈拉地语、西班牙、克罗埃西亚、...
  • ABBYY FineReader是一款图文识别(OCR)软件,使用ABBYY FineReader可以识别阿拉伯语、希伯来语、意第绪语、泰国语、中文、日语韩语文档,处理中文、日语或韩语文档,以及混合使用中日韩 (CJK)语言欧洲语言的文档...
  • OpenHub 一个**开源*的GitHub Android客户端,MD风格,支持主题、主颜色、语言切换,SO COOL的语法高亮。支持Android5.0及以上系统。...支持英文、简体中文和希伯来语 支持离线模式 支持32种语言的最热版本库查看...
  • 编码转换CodeTrans v2.2

    2019-11-01 13:56:36
    在不同字符集间转换编码的转码工具,支持GBK和BIG5之间和GBK内的简繁转换,简繁转换支持可由用户修改的词汇对应表支持多种字符集(UNICODE,泰,日,简,韩,繁,捷克,俄,英,希腊... 界面可在简体中文、繁体中文和英文间切换。
  • 77 javaIO_3 _编码方式

    2020-07-23 10:04:16
    ISO- 8859-1收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。 UTF-8:针对Unicode码表的可变长度字符编码 GB2312:简体中文 GBK:简体中文、扩充 BIG5台湾,繁体中文 当编码方式...
  • 支持英语,简体中文希伯来语,德语,印地语,葡萄牙语,韩国,西班牙语,繁体中文,俄语,波兰语,格鲁吉亚语,意大利语,荷兰语,捷克语葡萄牙语(巴西) 离线模式 支持所有语言的趋势库页面 支持多账户切换 ...
  • ABBYY FineReader是一款OCR文字识别软件,使用ABBYY FineReader可以识别阿拉伯语、希伯来语、意第绪语、泰国语、中文、日语韩语文档,处理中文、日语或韩语文档,以及混合使用中日韩 (CJK)语言欧洲语言的文档时...
  • 使用简单的CSS进行漂亮的打印。 ... HTML无缝转换为可以打印,下载存档的文档。 Prince使您可以排版,格式化打印HTML内容,因此您可以成为自己的发布者。... 阿拉伯文,希伯来文,北印度文等
  • Big5,GB2312,EUC-TW,HZ-GB-2312,ISO-2022-CN(繁体中文和简体中文) EUC-JP,SHIFT_JIS,CP932,ISO-2022-JP(日语) EUC-KR,ISO-2022-KR,Johab(韩文) KOI8-R,MacCyrillic,IBM855,IBM866,ISO-8859-5...

空空如也

空空如也

1 2 3 4
收藏数 75
精华内容 30
关键字:

中文和希伯来文