mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-08-30 12:12:40 +08:00
+100
-22
@@ -148,10 +148,11 @@ func (fsys *FontFS) matchStyle(pattern string, bold, italic bool) []string {
|
|||||||
func (fsys *FontFS) matchPatternsStyle(patterns []string, bold, italic bool) []string {
|
func (fsys *FontFS) matchPatternsStyle(patterns []string, bold, italic bool) []string {
|
||||||
var matches []fontFileMatch
|
var matches []fontFileMatch
|
||||||
seen := make(map[string]int)
|
seen := make(map[string]int)
|
||||||
for _, pattern := range patterns {
|
files := fontFileCandidates(fsys.names, path.Base)
|
||||||
for _, name := range fsys.names {
|
for _, matcher := range newFontPatternMatchers(patterns) {
|
||||||
rank := matchFontPatternRank(pattern, name)
|
for _, file := range files {
|
||||||
appendFontFileMatch(&matches, seen, pattern, name, rank, bold, italic)
|
rank := matcher.rank(file.base)
|
||||||
|
appendFontFileMatch(&matches, seen, matcher.pattern, file.name, rank, bold, italic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sortFontFileMatches(matches, bold, italic)
|
sortFontFileMatches(matches, bold, italic)
|
||||||
@@ -205,51 +206,128 @@ func cleanFontName(name string) string {
|
|||||||
// 入参: pattern 匹配模式, name 字体文件名
|
// 入参: pattern 匹配模式, name 字体文件名
|
||||||
// 返回: int 匹配等级
|
// 返回: int 匹配等级
|
||||||
func matchFontPatternRank(pattern, name string) int {
|
func matchFontPatternRank(pattern, name string) int {
|
||||||
|
return newFontPatternMatcher(pattern).rank(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fontFileCandidate struct {
|
||||||
|
name string
|
||||||
|
base string
|
||||||
|
}
|
||||||
|
|
||||||
|
// fontFileCandidates 筛选字体文件候选
|
||||||
|
// 入参: names 文件名列表, base 文件名提取函数
|
||||||
|
// 返回: []fontFileCandidate 字体文件候选列表
|
||||||
|
func fontFileCandidates(names []string, base func(string) string) []fontFileCandidate {
|
||||||
|
files := make([]fontFileCandidate, 0, len(names))
|
||||||
|
for _, name := range names {
|
||||||
|
if isFontFileName(name) {
|
||||||
|
files = append(files, fontFileCandidate{name: name, base: base(name)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
|
type fontPatternMatcher struct {
|
||||||
|
pattern string
|
||||||
|
lowerPattern string
|
||||||
|
stem string
|
||||||
|
aliases []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// newFontPatternMatcher 创建字体文件匹配器
|
||||||
|
// 入参: pattern 匹配模式
|
||||||
|
// 返回: fontPatternMatcher 字体文件匹配器
|
||||||
|
func newFontPatternMatcher(pattern string) fontPatternMatcher {
|
||||||
|
matcher := fontPatternMatcher{
|
||||||
|
pattern: pattern,
|
||||||
|
lowerPattern: strings.ToLower(pattern),
|
||||||
|
stem: fontPatternStem(pattern),
|
||||||
|
}
|
||||||
|
if matcher.stem != "" {
|
||||||
|
for _, alias := range fontExactCandidateNames(matcher.stem) {
|
||||||
|
alias = fontNormalizeName(alias)
|
||||||
|
if alias != "" {
|
||||||
|
matcher.aliases = append(matcher.aliases, alias)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matcher
|
||||||
|
}
|
||||||
|
|
||||||
|
// newFontPatternMatchers 创建字体文件匹配器列表
|
||||||
|
// 入参: patterns 匹配模式列表
|
||||||
|
// 返回: []fontPatternMatcher 字体文件匹配器列表
|
||||||
|
func newFontPatternMatchers(patterns []string) []fontPatternMatcher {
|
||||||
|
matchers := make([]fontPatternMatcher, 0, len(patterns))
|
||||||
|
for _, pattern := range patterns {
|
||||||
|
matchers = append(matchers, newFontPatternMatcher(pattern))
|
||||||
|
}
|
||||||
|
return matchers
|
||||||
|
}
|
||||||
|
|
||||||
|
// rank 获取字体文件匹配等级
|
||||||
|
// 入参: name 字体文件名
|
||||||
|
// 返回: int 匹配等级
|
||||||
|
func (m fontPatternMatcher) rank(name string) int {
|
||||||
rawName := name
|
rawName := name
|
||||||
exactPath, _ := path.Match(pattern, name)
|
exactPath, _ := path.Match(m.pattern, name)
|
||||||
lowerPath, _ := path.Match(strings.ToLower(pattern), strings.ToLower(name))
|
lowerPath, _ := path.Match(m.lowerPattern, strings.ToLower(name))
|
||||||
stem := fontPatternStem(pattern)
|
if m.stem == "" {
|
||||||
if stem == "" {
|
|
||||||
if exactPath || lowerPath {
|
if exactPath || lowerPath {
|
||||||
return fontMatchFuzzy
|
return fontMatchFuzzy
|
||||||
}
|
}
|
||||||
return fontMatchNone
|
return fontMatchNone
|
||||||
}
|
}
|
||||||
name = fontNormalizeName(name)
|
name = fontNormalizeName(name)
|
||||||
if name == stem {
|
if name == m.stem {
|
||||||
return fontMatchExact
|
return fontMatchExact
|
||||||
}
|
}
|
||||||
aliases := fontExactCandidateNames(stem)
|
for _, alias := range m.aliases {
|
||||||
for _, alias := range aliases {
|
if name == alias {
|
||||||
alias = fontNormalizeName(alias)
|
|
||||||
if alias != "" && name == alias {
|
|
||||||
return fontMatchExact
|
return fontMatchExact
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fontFileKnownStyleSuffix(fontFileStyleSuffix(pattern, rawName)) {
|
if fontFileKnownStyleSuffix(m.styleSuffix(rawName)) {
|
||||||
return fontMatchExact
|
return fontMatchExact
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(name, stem) {
|
if strings.HasPrefix(name, m.stem) {
|
||||||
return fontMatchPartial
|
return fontMatchPartial
|
||||||
}
|
}
|
||||||
for _, alias := range aliases {
|
for _, alias := range m.aliases {
|
||||||
alias = fontNormalizeName(alias)
|
if strings.HasPrefix(name, alias) {
|
||||||
if alias != "" && strings.HasPrefix(name, alias) {
|
|
||||||
return fontMatchPartial
|
return fontMatchPartial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if exactPath || lowerPath || strings.Contains(name, stem) {
|
if exactPath || lowerPath || strings.Contains(name, m.stem) {
|
||||||
return fontMatchFuzzy
|
return fontMatchFuzzy
|
||||||
}
|
}
|
||||||
for _, alias := range aliases {
|
for _, alias := range m.aliases {
|
||||||
alias = fontNormalizeName(alias)
|
if strings.Contains(name, alias) {
|
||||||
if alias != "" && strings.Contains(name, alias) {
|
|
||||||
return fontMatchFuzzy
|
return fontMatchFuzzy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fontMatchNone
|
return fontMatchNone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// styleSuffix 获取字体文件样式后缀
|
||||||
|
// 入参: name 字体文件名
|
||||||
|
// 返回: string 样式后缀
|
||||||
|
func (m fontPatternMatcher) styleSuffix(name string) string {
|
||||||
|
key := fontNormalizeName(name)
|
||||||
|
if m.stem == "" || key == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(key, m.stem) {
|
||||||
|
return strings.TrimPrefix(key, m.stem)
|
||||||
|
}
|
||||||
|
for _, alias := range m.aliases {
|
||||||
|
if strings.HasPrefix(key, alias) {
|
||||||
|
return strings.TrimPrefix(key, alias)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type fontFileMatch struct {
|
type fontFileMatch struct {
|
||||||
name string
|
name string
|
||||||
pattern string
|
pattern string
|
||||||
|
|||||||
+5
-9
@@ -227,16 +227,12 @@ func fontFSMatches(fsys fs.FS, patterns []string) []string {
|
|||||||
func fontFSMatchesStyle(fsys fs.FS, patterns []string, bold, italic bool) []string {
|
func fontFSMatchesStyle(fsys fs.FS, patterns []string, bold, italic bool) []string {
|
||||||
var matches []fontFileMatch
|
var matches []fontFileMatch
|
||||||
seen := make(map[string]int)
|
seen := make(map[string]int)
|
||||||
add := func(pattern, name string, rank int) {
|
|
||||||
if !isFontFileName(name) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
appendFontFileMatch(&matches, seen, pattern, name, rank, bold, italic)
|
|
||||||
}
|
|
||||||
names, _ := fs.Glob(fsys, "*")
|
names, _ := fs.Glob(fsys, "*")
|
||||||
for _, pattern := range patterns {
|
candidates := fontFileCandidates(names, path.Base)
|
||||||
for _, name := range names {
|
for _, matcher := range newFontPatternMatchers(patterns) {
|
||||||
add(pattern, name, matchFontPatternRank(pattern, path.Base(name)))
|
for _, file := range candidates {
|
||||||
|
rank := matcher.rank(file.base)
|
||||||
|
appendFontFileMatch(&matches, seen, matcher.pattern, file.name, rank, bold, italic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sortFontFileMatches(matches, bold, italic)
|
sortFontFileMatches(matches, bold, italic)
|
||||||
|
|||||||
@@ -161,16 +161,12 @@ func (r *Renderer) loadFont(fontID string) *canvas.FontFamily {
|
|||||||
func (r *Renderer) matchFontFiles(dir string, patterns []string, bold, italic bool) []string {
|
func (r *Renderer) matchFontFiles(dir string, patterns []string, bold, italic bool) []string {
|
||||||
var matches []fontFileMatch
|
var matches []fontFileMatch
|
||||||
index := make(map[string]int)
|
index := make(map[string]int)
|
||||||
add := func(pattern, name string, rank int) {
|
|
||||||
if !isFontFileName(name) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
appendFontFileMatch(&matches, index, pattern, name, rank, bold, italic)
|
|
||||||
}
|
|
||||||
files, _ := filepath.Glob(filepath.Join(dir, "*"))
|
files, _ := filepath.Glob(filepath.Join(dir, "*"))
|
||||||
for _, pattern := range patterns {
|
candidates := fontFileCandidates(files, filepath.Base)
|
||||||
for _, name := range files {
|
for _, matcher := range newFontPatternMatchers(patterns) {
|
||||||
add(pattern, name, matchFontPatternRank(pattern, filepath.Base(name)))
|
for _, file := range candidates {
|
||||||
|
rank := matcher.rank(file.base)
|
||||||
|
appendFontFileMatch(&matches, index, matcher.pattern, file.name, rank, bold, italic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sortFontFileMatches(matches, bold, italic)
|
sortFontFileMatches(matches, bold, italic)
|
||||||
|
|||||||
@@ -85,6 +85,9 @@ func imageWithAlpha(img image.Image, alpha *int) image.Image {
|
|||||||
return img
|
return img
|
||||||
}
|
}
|
||||||
a := clampColor(*alpha)
|
a := clampColor(*alpha)
|
||||||
|
if a == 255 {
|
||||||
|
return img
|
||||||
|
}
|
||||||
bounds := img.Bounds()
|
bounds := img.Bounds()
|
||||||
out := image.NewNRGBA(bounds)
|
out := image.NewNRGBA(bounds)
|
||||||
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
||||||
@@ -109,6 +112,9 @@ func imageWithTransparentEdge(img image.Image) (image.Image, int) {
|
|||||||
if w == 0 || h == 0 {
|
if w == 0 || h == 0 {
|
||||||
return img, 0
|
return img, 0
|
||||||
}
|
}
|
||||||
|
if opaque, ok := img.(interface{ Opaque() bool }); ok && opaque.Opaque() {
|
||||||
|
return img, 0
|
||||||
|
}
|
||||||
src := image.NewNRGBA(image.Rect(0, 0, w, h))
|
src := image.NewNRGBA(image.Rect(0, 0, w, h))
|
||||||
hasZero, hasVisible := false, false
|
hasZero, hasVisible := false, false
|
||||||
for y := 0; y < h; y++ {
|
for y := 0; y < h; y++ {
|
||||||
|
|||||||
@@ -1014,6 +1014,9 @@ func (r *Renderer) renderStamp(ctx *canvas.Context, s Stamp, pageH float64) {
|
|||||||
// 入参: img 印章图片对象
|
// 入参: img 印章图片对象
|
||||||
// 返回: image.Image 处理后的印章图片对象
|
// 返回: image.Image 处理后的印章图片对象
|
||||||
func stampImageWithTransparentWhite(img image.Image) image.Image {
|
func stampImageWithTransparentWhite(img image.Image) image.Image {
|
||||||
|
if opaque, ok := img.(interface{ Opaque() bool }); ok && !opaque.Opaque() {
|
||||||
|
return img
|
||||||
|
}
|
||||||
bounds := img.Bounds()
|
bounds := img.Bounds()
|
||||||
out := image.NewNRGBA(bounds)
|
out := image.NewNRGBA(bounds)
|
||||||
hasAlpha := false
|
hasAlpha := false
|
||||||
|
|||||||
Reference in New Issue
Block a user