mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-08-30 12:12:40 +08:00
@@ -73,7 +73,9 @@ func NewRenderer(reader *Reader, opts ...RendererOption) *Renderer {
|
|||||||
FontMap: make(map[string]*canvas.FontFamily),
|
FontMap: make(map[string]*canvas.FontFamily),
|
||||||
FontGIDMap: make(map[string]map[uint16]rune),
|
FontGIDMap: make(map[string]map[uint16]rune),
|
||||||
FontCIDMap: make(map[string]map[uint16]rune),
|
FontCIDMap: make(map[string]map[uint16]rune),
|
||||||
fontFSCache: make(map[fontFSKey]*canvas.FontFamily),
|
fontCache: make(map[fontCacheKey]*canvas.FontFamily),
|
||||||
|
fontSourceCache: make(map[string][]fontSource),
|
||||||
|
fontSourceUsed: make(map[string]fontSource),
|
||||||
textGlyphPathCache: make(map[textGlyphPathCacheKey]textGlyphPathCacheValue),
|
textGlyphPathCache: make(map[textGlyphPathCacheKey]textGlyphPathCacheValue),
|
||||||
templatePageCache: make(map[string]*PageContent),
|
templatePageCache: make(map[string]*PageContent),
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-71
@@ -168,9 +168,9 @@ func (r *Renderer) fontInfo(font Font) FontInfo {
|
|||||||
}
|
}
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
if matched, exact := r.matchFont(font.FontName, font.FamilyName); matched != "" {
|
if source, ok := r.fontSourceMatch(font.ID, &font); ok {
|
||||||
info.Matched = matched
|
info.Matched = source.name
|
||||||
if exact {
|
if source.exact {
|
||||||
info.Status = FontStatusMatched
|
info.Status = FontStatusMatched
|
||||||
info.Detail = "使用外部字体文件"
|
info.Detail = "使用外部字体文件"
|
||||||
} else {
|
} else {
|
||||||
@@ -184,74 +184,6 @@ func (r *Renderer) fontInfo(font Font) FontInfo {
|
|||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
// matchFont 匹配外部字体
|
|
||||||
// 入参: names 字体名称列表
|
|
||||||
// 返回: string 匹配字体文件, bool 是否为名称匹配
|
|
||||||
func (r *Renderer) matchFont(names ...string) (string, bool) {
|
|
||||||
patterns := fontFilePatterns(names...)
|
|
||||||
for _, dir := range r.fontDirs {
|
|
||||||
if matches := r.matchFontFiles(dir, patterns, false, false); len(matches) > 0 {
|
|
||||||
return matches[0], true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, fsys := range r.fontFS {
|
|
||||||
if matcher, ok := fsys.(interface {
|
|
||||||
Match(...string) (string, bool)
|
|
||||||
}); ok {
|
|
||||||
if matched, exact := matcher.Match(names...); matched != "" {
|
|
||||||
return matched, exact
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if matched := matchFontFS(fsys, names...); matched != "" {
|
|
||||||
return matched, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !canLoadSystemFonts() {
|
|
||||||
for _, fsys := range r.fontFS {
|
|
||||||
if matched := fallbackFontFS(fsys); matched != "" {
|
|
||||||
return matched, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
// matchFontFS 从字体文件系统匹配字体
|
|
||||||
// 入参: fsys 字体文件系统, names 字体名称列表
|
|
||||||
// 返回: string 匹配字体文件
|
|
||||||
func matchFontFS(fsys fs.FS, names ...string) string {
|
|
||||||
if matches := fontFSMatches(fsys, fontFilePatterns(names...)); len(matches) > 0 {
|
|
||||||
return matches[0]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallbackFontFS 从字体文件系统获取回退字体
|
|
||||||
// 入参: fsys 字体文件系统
|
|
||||||
// 返回: string 回退字体文件
|
|
||||||
func fallbackFontFS(fsys fs.FS) string {
|
|
||||||
for _, pattern := range fontFallbackFiles {
|
|
||||||
if matches := fontFSMatches(fsys, []string{pattern}); len(matches) > 0 {
|
|
||||||
return matches[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
all, _ := fs.Glob(fsys, "*")
|
|
||||||
for _, name := range all {
|
|
||||||
if isFontFileName(name) {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// fontFSMatches 匹配字体文件系统中的字体文件
|
|
||||||
// 入参: fsys 字体文件系统, patterns 匹配模式列表
|
|
||||||
// 返回: []string 字体文件列表
|
|
||||||
func fontFSMatches(fsys fs.FS, patterns []string) []string {
|
|
||||||
return fontFSMatchesStyle(fsys, patterns, false, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fontFSMatchesStyle 匹配字体文件系统中的指定样式字体文件
|
// fontFSMatchesStyle 匹配字体文件系统中的指定样式字体文件
|
||||||
// 入参: fsys 字体文件系统, patterns 匹配模式列表, bold 是否粗体, italic 是否斜体
|
// 入参: fsys 字体文件系统, patterns 匹配模式列表, bold 是否粗体, italic 是否斜体
|
||||||
// 返回: []string 字体文件列表
|
// 返回: []string 字体文件列表
|
||||||
|
|||||||
+151
-78
@@ -22,10 +22,33 @@ import (
|
|||||||
"github.com/tdewolff/canvas"
|
"github.com/tdewolff/canvas"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fontFSKey 字体文件系统缓存键
|
// fontSourceKind 字体来源类型
|
||||||
type fontFSKey struct {
|
type fontSourceKind uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
fontSourceFile fontSourceKind = iota
|
||||||
|
fontSourceFS
|
||||||
|
fontSourceSystem
|
||||||
|
)
|
||||||
|
|
||||||
|
// fontSource 字体来源
|
||||||
|
type fontSource struct {
|
||||||
|
kind fontSourceKind
|
||||||
index int
|
index int
|
||||||
name string
|
name string
|
||||||
|
exact bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// fontSourceKey 字体来源去重键
|
||||||
|
type fontSourceKey struct {
|
||||||
|
kind fontSourceKind
|
||||||
|
index int
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// fontCacheKey 字体加载缓存键
|
||||||
|
type fontCacheKey struct {
|
||||||
|
fontSourceKey
|
||||||
style canvas.FontStyle
|
style canvas.FontStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +67,7 @@ func (r *Renderer) loadFont(fontID string) *canvas.FontFamily {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return defaultFont
|
return defaultFont
|
||||||
}
|
}
|
||||||
|
fontStyle := canvasFontStyle(of)
|
||||||
ff := canvas.NewFontFamily(of.FontName)
|
ff := canvas.NewFontFamily(of.FontName)
|
||||||
if of.FontFile != "" {
|
if of.FontFile != "" {
|
||||||
if fontData, err := r.Reader.ResData(of.FontFile); err == nil {
|
if fontData, err := r.Reader.ResData(of.FontFile); err == nil {
|
||||||
@@ -73,13 +97,6 @@ func (r *Renderer) loadFont(fontID string) *canvas.FontFamily {
|
|||||||
r.FontGIDMap[fontID] = inv
|
r.FontGIDMap[fontID] = inv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var fontStyle canvas.FontStyle
|
|
||||||
if of.Bold {
|
|
||||||
fontStyle |= canvas.FontBold
|
|
||||||
}
|
|
||||||
if of.Italic {
|
|
||||||
fontStyle |= canvas.FontItalic
|
|
||||||
}
|
|
||||||
if err := ff.LoadFont(fontData, 0, fontStyle); err == nil {
|
if err := ff.LoadFont(fontData, 0, fontStyle); err == nil {
|
||||||
r.FontMap[fontID] = ff
|
r.FontMap[fontID] = ff
|
||||||
return ff
|
return ff
|
||||||
@@ -88,87 +105,143 @@ func (r *Renderer) loadFont(fontID string) *canvas.FontFamily {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var fontStyle canvas.FontStyle
|
for _, source := range r.fontSources(fontID, of, fontStyle) {
|
||||||
if of.Bold {
|
if loaded := r.loadFontSource(ff, source, fontStyle); loaded != nil {
|
||||||
fontStyle |= canvas.FontBold
|
r.FontMap[fontID] = loaded
|
||||||
}
|
r.fontSourceUsed[fontID] = source
|
||||||
if of.Italic {
|
|
||||||
fontStyle |= canvas.FontItalic
|
|
||||||
}
|
|
||||||
boldStyle := fontStyle&canvas.FontBold != 0
|
|
||||||
italicStyle := fontStyle&canvas.FontItalic != 0
|
|
||||||
patterns := fontFilePatterns(of.FontName, of.FamilyName)
|
|
||||||
for _, dir := range r.fontDirs {
|
|
||||||
for _, m := range r.matchFontFiles(dir, patterns, boldStyle, italicStyle) {
|
|
||||||
if err := ff.LoadFontFile(m, fontStyle); err == nil {
|
|
||||||
r.FontMap[fontID] = ff
|
|
||||||
return ff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for index, fsys := range r.fontFS {
|
|
||||||
for _, m := range fontFSMatchesStyle(fsys, patterns, boldStyle, italicStyle) {
|
|
||||||
if loaded := r.loadFontFromFS(fontID, ff, index, fsys, m, fontStyle); loaded != nil {
|
|
||||||
return loaded
|
return loaded
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if !canLoadSystemFonts() {
|
|
||||||
for index, fsys := range r.fontFS {
|
|
||||||
if matches, err := fs.Glob(fsys, "*"); err == nil {
|
|
||||||
for _, m := range matches {
|
|
||||||
if loaded := r.loadFontFromFS(fontID, ff, index, fsys, m, fontStyle); loaded != nil {
|
|
||||||
return loaded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.FontMap[fontID] = defaultFont
|
|
||||||
return defaultFont
|
|
||||||
}
|
|
||||||
names := []string{of.FamilyName, of.FontName}
|
|
||||||
for _, name := range names {
|
|
||||||
if name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, targetName := range fontSystemNames(name) {
|
|
||||||
for _, m := range r.matchFontFiles(systemFontDir(), fontFilePatterns(targetName), boldStyle, italicStyle) {
|
|
||||||
if err := ff.LoadFontFile(m, fontStyle); err == nil {
|
|
||||||
r.FontMap[fontID] = ff
|
|
||||||
return ff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := ff.LoadSystemFont(targetName, fontStyle); err == nil {
|
|
||||||
r.FontMap[fontID] = ff
|
|
||||||
return ff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, m := range r.matchFontFiles(systemFontDir(), fontFilePatterns(name), boldStyle, italicStyle) {
|
|
||||||
if err := ff.LoadFontFile(m, fontStyle); err == nil {
|
|
||||||
r.FontMap[fontID] = ff
|
|
||||||
return ff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.FontMap[fontID] = defaultFont
|
r.FontMap[fontID] = defaultFont
|
||||||
return defaultFont
|
return defaultFont
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadFontFromFS 从字体文件系统加载字体
|
// canvasFontStyle 获取Canvas字体样式
|
||||||
// 入参: fontID 字体ID, family 字体族, index 文件系统索引, fsys 字体文件系统, name 字体文件名, style 字体样式
|
// 入参: font OFD字体定义
|
||||||
|
// 返回: canvas.FontStyle Canvas字体样式
|
||||||
|
func canvasFontStyle(font *Font) canvas.FontStyle {
|
||||||
|
var style canvas.FontStyle
|
||||||
|
if font.Bold {
|
||||||
|
style |= canvas.FontBold
|
||||||
|
}
|
||||||
|
if font.Italic {
|
||||||
|
style |= canvas.FontItalic
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
|
||||||
|
// fontSources 获取字体来源列表
|
||||||
|
// 入参: fontID 字体ID, font OFD字体定义, style Canvas字体样式
|
||||||
|
// 返回: []fontSource 字体来源列表
|
||||||
|
func (r *Renderer) fontSources(fontID string, font *Font, style canvas.FontStyle) []fontSource {
|
||||||
|
if sources, ok := r.fontSourceCache[fontID]; ok {
|
||||||
|
return sources
|
||||||
|
}
|
||||||
|
bold := style&canvas.FontBold != 0
|
||||||
|
italic := style&canvas.FontItalic != 0
|
||||||
|
patterns := fontFilePatterns(font.FontName, font.FamilyName)
|
||||||
|
sources := make([]fontSource, 0)
|
||||||
|
seen := make(map[fontSourceKey]bool)
|
||||||
|
for _, dir := range r.fontDirs {
|
||||||
|
for _, name := range r.matchFontFiles(dir, patterns, bold, italic) {
|
||||||
|
sources = appendFontSource(sources, seen, fontSource{kind: fontSourceFile, name: name, exact: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for index, fsys := range r.fontFS {
|
||||||
|
for _, name := range fontFSMatchesStyle(fsys, patterns, bold, italic) {
|
||||||
|
sources = appendFontSource(sources, seen, fontSource{kind: fontSourceFS, index: index, name: name, exact: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !canLoadSystemFonts() {
|
||||||
|
for index, fsys := range r.fontFS {
|
||||||
|
names, _ := fs.Glob(fsys, "*")
|
||||||
|
for _, name := range names {
|
||||||
|
sources = appendFontSource(sources, seen, fontSource{kind: fontSourceFS, index: index, name: name})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.fontSourceCache[fontID] = sources
|
||||||
|
return sources
|
||||||
|
}
|
||||||
|
for _, name := range []string{font.FamilyName, font.FontName} {
|
||||||
|
for _, systemName := range fontSystemNames(name) {
|
||||||
|
for _, match := range r.matchFontFiles(systemFontDir(), fontFilePatterns(systemName), bold, italic) {
|
||||||
|
sources = appendFontSource(sources, seen, fontSource{kind: fontSourceFile, name: match, exact: true})
|
||||||
|
}
|
||||||
|
sources = appendFontSource(sources, seen, fontSource{kind: fontSourceSystem, name: systemName, exact: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.fontSourceCache[fontID] = sources
|
||||||
|
return sources
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendFontSource 追加字体来源
|
||||||
|
// 入参: sources 字体来源列表, seen 去重映射, source 字体来源
|
||||||
|
// 返回: []fontSource 字体来源列表
|
||||||
|
func appendFontSource(sources []fontSource, seen map[fontSourceKey]bool, source fontSource) []fontSource {
|
||||||
|
if source.name == "" {
|
||||||
|
return sources
|
||||||
|
}
|
||||||
|
key := fontSourceKey{kind: source.kind, index: source.index, name: source.name}
|
||||||
|
if seen[key] {
|
||||||
|
return sources
|
||||||
|
}
|
||||||
|
seen[key] = true
|
||||||
|
return append(sources, source)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fontSourceMatch 获取匹配的字体来源
|
||||||
|
// 入参: fontID 字体ID, font OFD字体定义
|
||||||
|
// 返回: fontSource 字体来源, bool 是否匹配
|
||||||
|
func (r *Renderer) fontSourceMatch(fontID string, font *Font) (fontSource, bool) {
|
||||||
|
if source, ok := r.fontSourceUsed[fontID]; ok {
|
||||||
|
return source, true
|
||||||
|
}
|
||||||
|
style := canvasFontStyle(font)
|
||||||
|
for _, source := range r.fontSources(fontID, font, style) {
|
||||||
|
key := fontCacheKey{fontSourceKey: fontSourceKey{kind: source.kind, index: source.index, name: source.name}, style: style}
|
||||||
|
if cached, ok := r.fontCache[key]; ok {
|
||||||
|
if cached != nil {
|
||||||
|
return source, true
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if source.kind != fontSourceSystem {
|
||||||
|
return source, true
|
||||||
|
}
|
||||||
|
family := canvas.NewFontFamily(font.FontName)
|
||||||
|
if r.loadFontSource(family, source, style) != nil {
|
||||||
|
return source, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fontSource{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadFontSource 加载字体来源
|
||||||
|
// 入参: family 字体族, source 字体来源, style Canvas字体样式
|
||||||
// 返回: *canvas.FontFamily 字体族
|
// 返回: *canvas.FontFamily 字体族
|
||||||
func (r *Renderer) loadFontFromFS(fontID string, family *canvas.FontFamily, index int, fsys fs.FS, name string, style canvas.FontStyle) *canvas.FontFamily {
|
func (r *Renderer) loadFontSource(family *canvas.FontFamily, source fontSource, style canvas.FontStyle) *canvas.FontFamily {
|
||||||
key := fontFSKey{index: index, name: name, style: style}
|
key := fontCacheKey{fontSourceKey: fontSourceKey{kind: source.kind, index: source.index, name: source.name}, style: style}
|
||||||
if cached := r.fontFSCache[key]; cached != nil {
|
if cached, ok := r.fontCache[key]; ok {
|
||||||
r.FontMap[fontID] = cached
|
|
||||||
return cached
|
return cached
|
||||||
}
|
}
|
||||||
data, err := readFontData(fsys, name)
|
var err error
|
||||||
if err != nil || family.LoadFont(data, 0, style) != nil {
|
switch source.kind {
|
||||||
|
case fontSourceFile:
|
||||||
|
err = family.LoadFontFile(source.name, style)
|
||||||
|
case fontSourceFS:
|
||||||
|
var data []byte
|
||||||
|
data, err = readFontData(r.fontFS[source.index], source.name)
|
||||||
|
if err == nil {
|
||||||
|
err = family.LoadFont(data, 0, style)
|
||||||
|
}
|
||||||
|
case fontSourceSystem:
|
||||||
|
err = family.LoadSystemFont(source.name, style)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
r.fontCache[key] = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
r.fontFSCache[key] = family
|
r.fontCache[key] = family
|
||||||
r.FontMap[fontID] = family
|
|
||||||
return family
|
return family
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-7
@@ -15,6 +15,7 @@
|
|||||||
package ofdgo
|
package ofdgo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -30,14 +31,18 @@ type Box struct {
|
|||||||
// 返回: Box 矩形对象, error 错误信息
|
// 返回: Box 矩形对象, error 错误信息
|
||||||
func ParseBox(s string) (Box, error) {
|
func ParseBox(s string) (Box, error) {
|
||||||
parts := strings.Fields(s)
|
parts := strings.Fields(s)
|
||||||
if len(parts) < 4 {
|
if len(parts) != 4 {
|
||||||
return Box{}, nil
|
return Box{}, fmt.Errorf("invalid box: %s", s)
|
||||||
}
|
}
|
||||||
x, _ := strconv.ParseFloat(parts[0], 64)
|
var values [4]float64
|
||||||
y, _ := strconv.ParseFloat(parts[1], 64)
|
for i, part := range parts {
|
||||||
w, _ := strconv.ParseFloat(parts[2], 64)
|
value, err := strconv.ParseFloat(part, 64)
|
||||||
h, _ := strconv.ParseFloat(parts[3], 64)
|
if err != nil {
|
||||||
return Box{X: x, Y: y, W: w, H: h}, nil
|
return Box{}, fmt.Errorf("invalid box: %s", s)
|
||||||
|
}
|
||||||
|
values[i] = value
|
||||||
|
}
|
||||||
|
return Box{X: values[0], Y: values[1], W: values[2], H: values[3]}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matrix 2D仿射变换矩阵
|
// Matrix 2D仿射变换矩阵
|
||||||
|
|||||||
+3
-1
@@ -33,7 +33,9 @@ type Renderer struct {
|
|||||||
FontMap map[string]*canvas.FontFamily
|
FontMap map[string]*canvas.FontFamily
|
||||||
FontGIDMap map[string]map[uint16]rune
|
FontGIDMap map[string]map[uint16]rune
|
||||||
FontCIDMap map[string]map[uint16]rune
|
FontCIDMap map[string]map[uint16]rune
|
||||||
fontFSCache map[fontFSKey]*canvas.FontFamily
|
fontCache map[fontCacheKey]*canvas.FontFamily
|
||||||
|
fontSourceCache map[string][]fontSource
|
||||||
|
fontSourceUsed map[string]fontSource
|
||||||
textGlyphPathCache map[textGlyphPathCacheKey]textGlyphPathCacheValue
|
textGlyphPathCache map[textGlyphPathCacheKey]textGlyphPathCacheValue
|
||||||
templatePageCache map[string]*PageContent
|
templatePageCache map[string]*PageContent
|
||||||
fontDirs []string
|
fontDirs []string
|
||||||
|
|||||||
+4
-19
@@ -20,7 +20,6 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,7 +27,9 @@ import (
|
|||||||
type SignType string
|
type SignType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// SignTypeSeal 印章签名
|
||||||
SignTypeSeal SignType = "Seal"
|
SignTypeSeal SignType = "Seal"
|
||||||
|
// SignTypeSign 数字签名
|
||||||
SignTypeSign SignType = "Sign"
|
SignTypeSign SignType = "Sign"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -150,27 +151,11 @@ func (r *Reader) SignatureStampPositions(stamps []SignatureStamp) ([]SignatureSt
|
|||||||
// 入参: s 区域字符串
|
// 入参: s 区域字符串
|
||||||
// 返回: Box 矩形对象, error 错误信息
|
// 返回: Box 矩形对象, error 错误信息
|
||||||
func parseSignatureStampBox(s string) (Box, error) {
|
func parseSignatureStampBox(s string) (Box, error) {
|
||||||
parts := strings.Fields(s)
|
box, err := ParseBox(s)
|
||||||
if len(parts) != 4 {
|
|
||||||
return Box{}, fmt.Errorf("invalid signature stamp box: %s", s)
|
|
||||||
}
|
|
||||||
x, err := strconv.ParseFloat(parts[0], 64)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Box{}, fmt.Errorf("invalid signature stamp box: %s", s)
|
return Box{}, fmt.Errorf("invalid signature stamp box: %s", s)
|
||||||
}
|
}
|
||||||
y, err := strconv.ParseFloat(parts[1], 64)
|
return box, nil
|
||||||
if err != nil {
|
|
||||||
return Box{}, fmt.Errorf("invalid signature stamp box: %s", s)
|
|
||||||
}
|
|
||||||
w, err := strconv.ParseFloat(parts[2], 64)
|
|
||||||
if err != nil {
|
|
||||||
return Box{}, fmt.Errorf("invalid signature stamp box: %s", s)
|
|
||||||
}
|
|
||||||
h, err := strconv.ParseFloat(parts[3], 64)
|
|
||||||
if err != nil {
|
|
||||||
return Box{}, fmt.Errorf("invalid signature stamp box: %s", s)
|
|
||||||
}
|
|
||||||
return Box{X: x, Y: y, W: w, H: h}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseSignatures 解析签名文件
|
// parseSignatures 解析签名文件
|
||||||
|
|||||||
Reference in New Issue
Block a user