IE盒子

搜索
查看: 137|回复: 1

C语言显示数学公式-Latex格式

[复制链接]

2

主题

3

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2022-12-19 07:28:11 | 显示全部楼层 |阅读模式
缘起

最近学习计算机图形学,想做一些数学方面的简单动画。
发现一个问题:如何在电脑屏幕上显示数学公式(C语言,OpenGL编程)
比如下面这个表达式:
\int_a^b f(x)dx = F(b) - F(a)
输入字符串:\int_a^b f(x)dx = F(b) - F(a)
输出:在电脑屏幕上显示这个数学公式
在网上找了许久,都没有答案。
研究了几天,才知晓了答案,现在分享给大家。
代码

可以运行在Mac和windows
用Raylib库开发,底层是OpengGL
gentheaven/animation
网页显示数学公式

网页上可以显示数学公式,用的大多数是mathjax引擎,网站如下
http://www.mathjax.org
代码如下
https://github.com/mathjax/MathJax-src
这是用Javascript写的
C语言显示Latex公式

分为3步:

  • 解析Latex表达式
  • 合理的布局
  • 显示在屏幕上
解析Latex:parser

我在网上找了很久,没有找到C/C++的latext解析器
可以找到Python,Javascript 写的解析器
现在的demo版本中,我没有写解析器。
直接人工解析表达式,将来可能会用C语言写一个简单的。
比如:只解析单行表达式,只支持有限的Latex关键字
布局Layout

解析之后,还需要合理的布局
比如积分符号:


需要确定积分上限a和积分下限b的位置,和积分符号的大小关系等。
在我的实现中,积分符号的大小是积分上下限的3.5倍,和积分对象的大小是2倍。
积分对象需要放在积分符号的中间位置。
smallFont = floorf(fontSize / 3.5f); 积分符号的大小是积分上下限字母的3.5倍
smallFont = fontSize * 0.5f;  字号是积分符号的一半
其它字符也有类似的问题,所以需要合理的布局。
并且在字号缩放时,相对位置不变。
字库Font

其实电脑上显示的数学符号,来自于字库。现在都是矢量字库。
电脑上显示文字,本质上是一个矢量图。不过这个图形的画法是固定的,有规则的。
解析这套规则的库,叫做文字渲染引擎。
现在最常用的开源文字渲染引擎:freetype
但是一般的字库,不会显示所有的数学符号。需要寻找特定的字库。
如何找到显示数学符号的字库?
数学符号的编码是多少?
如何根据编码找到字库中对应的字形?
网上没有找到任何文章。
<hr/>matplotlib:找到字库

Matplotlib - Visualization with Python
我虽然不会Python,不妨碍我从网上下载python库,直接运行它的示例代码。
发现这个python库,可以显示latex公式。
python是开源的,所以找到相应的代码。虽然没学过python,但是可以直接读代码,猜。
Writing mathematical expressions
在这篇文章中,说道它内部集成了解析器,布局和字体:
Note that you do not need to have TeX installed, since Matplotlib ships its own
TeX expression parser, layout engine, and fonts.
所以最终在它的代码库中找到字体库。
数学符号的编码

matplotlib 在内部有一张表,记录了数学符号的名称和编码的关系。
我用的是iMac,安装包位置:/usr/local/lib/python3.9/site-packages/matplotlib
ls *math*,找到3个文件
_mathtext.py
_mathtext_data.py
mathtext.py
在文件_mathtext_data.py 中,发现一个数组:


比如解析 \int,就是积分符号,对应的编码就是8747
16进制编码是:222b
数学符号的英文名称

Math Symbols | All Mathematical Symbols


这个网站上,可以找到数字符号的英文名称。
如何确认编码

假设你想找积分符号,从上面的英文网站上,根据图形,找到对应的英文名称;
在文件_mathtext_data.py 中,可以找到对应的编码。
那么,如何确认这个编码就是你想要的。
Windows自带Character Map工具
可以输入Unicode码,直接查看对应的字形,还有名字


这样,最终确认,0x222b就是这个字库的积分符号
我们到哪了

现在,我们解析了Latex,做好了布局,并且找到合适的字库,还能在字库中找到对应的数学符号。
下一步,显示数学公式
显示数学公式

字库中已经有字形了,还需要做什么?
需要用freetype库才能显示。
freetype库可以根据字符编码,找到那个字形,
        int index = GetGlyphIndex(font, SYMBOL_INT);
        GlyphInfo gly = GetGlyphInfo(font, index);然后,缩放任意大小的,想要的字体:比如32号字体,或96号字体。
还可以旋转字体,做一些特效。
最终,把字体显示在电脑屏幕的特定位置。
raylib库

我用的是raylib库,一个图形库。
它自己写的字体引擎,没有用freetype。
发现它的引擎有3个问题:
加载字库非常慢。加载一个700KB的字库,需要5秒以上。
查找字形速度很慢。居然用循环查找,至少也应该是二分法查找。
不支持间断编码。很多字库的字形编码是连续的,但是也有很多是不连续的。
刚好我用的字库,编码不连续,然后raylib库就找不到,然后就显示不了某些字形。
所以,未来我会封装freetype,不用raylib的字体引擎。
最终的显示效果如本文的封面所示。
还有许多细节需要完善。
回复

使用道具 举报

1

主题

5

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 3 天前 | 显示全部楼层
沙发位出租,有意请联系电话:13838384381
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表