pk:如何计算给定字形的前进

pk:如何计算给定字形的前进

我正在开发一个可以读取.dvi文件并生成文件的 Go 库。我已经有了 find+parse和files.png包:我有和等价的可执行文件,它们可以生成与 中文件一致的位对位输出。.tfm.pkpk2bmtfm2pldvitypetex-live

现在,我希望能够dvipng在 Go 中复制的功能(并且我想远离源代码dvipng以保持我的软件包在 BSD-3 下获得许可。)

从第一原理来看,我认为我成功地从文件中提取了位图数据.pk并显示每个字形,但我不确定:

  • 我已经正确缩放它们
  • 我有一个正确缩放的边界框
  • 我有一个正确缩放的水平前进值。

这是我得到的,尝试显示字符串VA(在dvi“机械”之外,仅获取VA字形,获取它们的边界框,绘制每个字形的位图,然后使用字形前进移动“点”(我还没有包括字距调整)):

在此处输入图片描述

显然,我对每个字形的宽度的处理不够标准。

假设我有以下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.otfpk

$> 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按照上述说明生成的文件:

在此处输入图片描述

存在一些差异。但我会将此视为一次胜利。

相关内容