我正在开发一个可以读取.dvi
文件并生成文件的 Go 库。我已经有了 find+parse和files.png
包:我有和等价的可执行文件,它们可以生成与 中文件一致的位对位输出。.tfm
.pk
pk2bm
tfm2pl
dvitype
tex-live
现在,我希望能够dvipng
在 Go 中复制的功能(并且我想远离源代码dvipng
以保持我的软件包在 BSD-3 下获得许可。)
从第一原理来看,我认为我成功地从文件中提取了位图数据.pk
并显示每个字形,但我不确定:
- 我已经正确缩放它们
- 我有一个正确缩放的边界框
- 我有一个正确缩放的水平前进值。
这是我得到的,尝试显示字符串VA
(在dvi
“机械”之外,仅获取V
和A
字形,获取它们的边界框,绘制每个字形的位图,然后使用字形前进移动“点”(我还没有包括字距调整)):
显然,我对每个字形的宽度的处理不够标准。
假设我有以下tfm
包:
package tfm
type fileBody struct {
header header
glyphs []glyphInfo
width []fixed.Int12_20
height []fixed.Int12_20
depth []fixed.Int12_20
italic []fixed.Int12_20
ligKern []ligKernCmd
kern []fixed.Int12_20
exten []extensible
param []fixed.Int12_20
}
type header struct {
chksum uint32
designSize fixed.Int12_20
codingScheme string
fontID string
sevenBitSafe bool
face byte
extra []fixed.Int12_20
}
type glyphInfo struct {
raw [4]uint8
}
以及以下pk
字体包:
package pkf
// Font is a Packed Font.
type Font struct {
hdr CmdPre
glyphs []Glyph
}
type CmdPre struct {
Version uint8
Msg string
Design uint32
Checksum uint32
Hppp uint32
Vppp uint32
}
// Glyph represents a glyph contained in a PK font file.
type Glyph struct {
flag uint8
code uint32 // character code
wtfm uint32 // TFM width
dx uint32 // horizontal escapement
dy uint32 // vertical escapement
width uint32 // width in pixels of the minimum bounding box
height uint32 // height in pixels of the minimum bounding box
hoff int32 // horizontal offset from the upper left pixel
voff int32 // vertical offset from the upper left pixel
bitmap []byte // decoded bitmap data
}
"pk/ljfour/public/cm/dpi600/cmr10.pk"
当我以和"tfm/public/cm/cmr10.tfm"
作为输入开始并尝试绘制VAp
成PNG 图像时,我应该如何缩放所有这些((0,0) , (500, 250))
?(在 处有一个“点” (0, 100)
)
(我想将其缩放为 10pt + 600DPI 图像。)
答案1
好吧...有进展了。这并不完全令人满意,但是 - 除非有人有更多的见解 - 我会尝试这样做。
我已转换lmroman10-regular.otf
为pk
:
$> ttf2tfm lmroman10-regular.otf -q -T T1-WGL4.enc \
-v lmroman10-regular.vpl \
lmroman10-regular.tfm >> ./ttfonts.map
$> ttf2pk lmroman10-regular 600
确保我是在进行同类比较。
然后,经过反复试验,并查看文件A
中的 advance+glyph-bounds.otf
应该是什么样子,我得到了:
i := tfmFile.indexOf('A') // retrieve the glyph index for 'A'
w := tfmFile.width[i] + tfmFile.italic[i] // take into account italic correction
advance := int26_6_From_Int12_20(w) // Go fonts work with 26.6 fixed point ints
advance *= pkFont.UnitsPerEm() // 1000 for most (all?) PK fonts
advance /= 1<<6 // some more 26.6 fiddling?
advance = rescale(pkFont.scale * advance, pkFont.UnitsPerEm())
在哪里:
// rescale returns x divided by unitsPerEm, rounded to the nearest fixed.Int26_6
// value (1/64th of a pixel).
func rescale(x fixed.Int26_6, unitsPerEm int32) fixed.Int26_6 {
if x >= 0 {
x += fixed.Int26_6(unitsPerEm) / 2
} else {
x -= fixed.Int26_6(unitsPerEm) / 2
}
return x / fixed.Int26_6(unitsPerEm)
}
并且pkFont.scale
是:
opts.Size = tfmFile.DesignSize().AsFloat64()
opts.DPI = 600.0
pkFont.scale = fixed.Int26_6(0.5 + (opts.Size * opts.DPI * 64 / 72))
最后,我得到了lmroman10-regular.otf
(每个字形周围绘制有边界框):
对于lmroman10-regular.600pk
按照上述说明生成的文件:
存在一些差异。但我会将此视为一次胜利。