本文来告诉大家,在 OpenXML 里面的 Geometry 的如 gdLst 和 ahLst 和 pathLst 等里面参数的公式的参数含义
这部分内容放在 ECMA-376 的 20.1.10.55 章文档里面,本文只是将文档里面的内容翻译一下
在使用 OpenXML 读取形状时,会看到有些形状的定义内容如下
或者是采用预设形状,定义如下
对于预设形状来说,需要通过预设形状的文档,也就是 ECMA-376 的 ECMA-376, Third Edition, Part 1 - Fundamentals And Markup Language Reference
的 PresetShapeDefinitions.xml
文档里面,获取到预设形状的定义。展开的结果也和上文相同,预设的定义允许被具体的元素的定义覆盖,规则和 WPF 的资源优先级相同
我将本文的计算规则逻辑放到 DocumentFormat.OpenXml.Flatten 库里面,在 GitHub 上完全开源: https://github.com/dotnet-campus/DocumentFormat.OpenXml.Extensions
如果想要绘制形状的 Path 几何图形,就需要计算此形状里面的 Path 的各个值。如上面代码,可以看到都采用的是公式的方式进行计算,如 gd 的内容如下
以上表示了在 avLst 也就是 AdjustValueList 调整点的参数,以上的 gd 也就是 OpenXML SDK 的 ShapeGuide 类型,这里面的 name 就是 adj1 换句话说就是变量名为 adj1 的值。此 adj1 变量将会在接下来的公式里面使用。而 fmla 就是 ShapeGuide 的 Formula 公式内容,通过如下代码可以获取到公式
可以看到以上的 val 50000
字符串就是公式的内容,以上的 val 表示常量,也就是相当于 adj1 = val 50000
也就是 adj1 变量的值就是 50000 的常量
而后续在 gdLst 也就是 ShapeGuideList 类型里面,将会在如下代码使用到 adj1 变量
此时在 gd name="x2" fmla="*/ w adj1 100000"
里面通过计算,拿到 x2 变量的值,以上使用了 */
这个符号,其实在 OpenXML 里面的公式用的是逆波兰表达的公式,大概的意思就是 */
运算符要求后续传入三个参数,假定这三个参数是 a b c 三个,那么计算的方法是 (a * b) / c
拿到值
通过不断代入公式可以拿到对应的变量,从而计算出 Path 里面的内容。但以上有一部分公式使用了常量,如下面代码
上面代码的 pt x="l" y="t"
的 l 和 t 都是常量,在文档里面都有定义
下面将告诉大家计算的符号的含义,以及常量的值
3cd4
表示三分之四的圆,以上的 c 就是 Circle 圆的意思,而 d 就是除法的意思, 相当于 3 * 圆 / 4
的值
以上的圆使用的是 180° 的表示,也就是以上常量的值等于 3cd4 = 3 x 360° / 4 = 270°
通过 Office Open XML 的测量单位 可以拿到角度对应的值是 16200000.0 的常量值。在 OpenXML 里面使用 60000 表示 360° 的圆
以此可以了解到以下的对圆的计算值
t
也就是 Shape Top Edge 的含义,表示上边缘,等价于常量 0 的值。原因是 OpenXML 的形状采用的坐标系和 DirectX 的坐标系相同,左上角是 0,0 点,从上到下 y 的值不断加大。从左到右 x 的值加大
b
也就是 Shape Bottom Edge 的含义,等价于常量 h 的值
这是形状的下边缘,因为形状的上边缘被认为是 0 点,因此下边缘就是形状的高度
关于常量 h 的值,请看下文
h
也就是 Shape Height 的含义,表示形状的高度,需要通过形状的属性拿到形状的高度才能了解此值
hd2
表示的是高度除以 2 的值,以上的 h 是 高度 而 d 表示的是除以,相当于如下公式
以上代码的 */
公式内容请参阅下文,而 h 表示的是宽度
以此可以了解如下的几个常量的计算
vc
也就是 Vertical Center of Shape 的含义,表示垂直的中心,相当于高度的一半,使用如下公式
以上代码的 */
公式内容请参阅下文,而 h 表示的是宽度
l
也就是 Shape Left Edge 的含义,表示左边缘的值,等价于常量 0 的值。原因是 OpenXML 的形状采用的坐标系和 DirectX 的坐标系相同,左上角是 0,0 点,从上到下 y 的值不断加大。从左到右 x 的值加大
r
也就是 Shape Right Edge 的含义,表示右边缘的值,等价于常量 w 的值。也就是右边缘的值和形状的宽度相同,因为形状的左边缘是 0 的值,因此形状的右边的值就和形状的宽度相同
关于 w 请看下文
w
也就是 Shape Width 形状宽度的含义,需要通过形状的属性拿到形状的高度才能了解此值
wd2
表示形状宽度的一半,以上的 w 是 宽度 而 d 表示的是除以,相当于如下公式
以此可以了解如下的几个常量的计算
hc
也就是 Horizontal Center 的含义,表示水平的中心点,相当于宽度的一半,计算的公式如下
以上代码的 */
公式内容请参阅下文,而 w 表示的是宽度
ls
也就是 Longest Side of Shape 的含义,表示宽度或高度里面最长的一边,等价以下公式
也就是返回宽度或高度的最大值
ss
也就是 Shortest Side of Shape 的含义,表示宽度或高度里面最短的一边,等价以下公式
也就是返回宽度或高度的最小值
ssd2
表示的是 ss 除以 2 的值,也就是获取宽度或高度的最小值除以 2 的值,以上 d 表示的是除以,使用如下公式
以此可以了解如下的几个常量的计算
符号
而形状的计算符号定义在 ECMA 376 的 20.1.9.11 章文档
含义如下,以下的 x 和 y 和 z 表示传入的三个参数的值,如 fmla="*/ x y z"
的实际文档的值是 fmla="*/ 1 2 3"
也就是表示 x = 1 ,y = 2 ,z = 3 的值
Multiply Divide Formula
乘除公式使用 */
表示,要求传入三个参数
Add Subtract Formula
加减公式使用 +-
表示,要求传入三个参数
Add Divide Formula
加除公式使用 +/
表示,要求传入三个参数
If Else Formula
条件判断使用 ?:
符号表示,和 C# 里面的 ?:
逻辑相同,需要传入三个参数,假定参数是 x y z 三个参数,判断是如果传入的 x 大于 0 那么则是 true 代码如下
Absolute Value Formula
绝对值公式使用 abs
表示,需要传入一个参数,计算方法如下
ArcTan Formula
表示三角函数的 arctan2
公式,计算方法如下
而 Atan2 等的定义如下
Cosine ArcTan Formula
表示三角函数的两次计算 cat2
公式,计算方法如下
Cosine Formula
表示三角函数的 cos
公式,计算方法如下
Sine ArcTan Formula
表示三角函数的 sat2
公式,计算方法如下
Sine Formula
表示三角函数的 sin
公式,计算方法如下
Tangent Formula
表示三角函数的 tan
公式,计算方法如下
Maximum Value Formula
表示两个数里面最大的一个值,使用 max
公式,计算方法如下
Minimum Value Formula
表示两个数里面最小的一个值,使用 min
公式,计算方法如下
Modulo Formula
表示 mod
公式,计算方法如下
Pin To Formula
表示 pin
公式,计算方法如下
Square Root Formula
表示 sqrt
公式,计算方法如下
Literal Value Formula
表示一个常量的值,相当于 var
的定义,表示的是 val
公式,将会返回对应的值
如 val x
就是返回 x 的值
如需要转换为 SVG 的字符串,请看 dotnet OpenXML 让 PathLst 自定义形状转 SVG 路径格式的 Geometry 内容
更多请看 Office 使用 OpenXML SDK 解析文档博客目录
感谢
感谢 Ryzen 提供的公式和代码
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。 欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。