mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-08-30 12:12:40 +08:00
feat(印章渲染): 优化印章渲染
This commit is contained in:
+42
-3
@@ -650,7 +650,8 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
if obj.VScale != 0 {
|
if obj.VScale != 0 {
|
||||||
sizeMM *= obj.VScale
|
sizeMM *= obj.VScale
|
||||||
}
|
}
|
||||||
if scale := ctm.YScale(); scale > 0 {
|
useTextMatrix := hasTextMatrix(ctm)
|
||||||
|
if scale := ctm.YScale(); scale > 0 && !useTextMatrix {
|
||||||
sizeMM *= scale
|
sizeMM *= scale
|
||||||
}
|
}
|
||||||
sizePt := sizeMM * 2.83465
|
sizePt := sizeMM * 2.83465
|
||||||
@@ -754,19 +755,39 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
}
|
}
|
||||||
if glyphFillPaint != nil {
|
if glyphFillPaint != nil {
|
||||||
ctx.SetFill(glyphFillPaint)
|
ctx.SetFill(glyphFillPaint)
|
||||||
|
drawGlyph := func(x, y float64) {
|
||||||
if embeddedFont {
|
if embeddedFont {
|
||||||
path, width := face.ToPath(str)
|
path, width := face.ToPath(str)
|
||||||
textWidth = width
|
textWidth = width
|
||||||
ctx.DrawPath(canvasX, canvasY, path)
|
ctx.DrawPath(x, y, path)
|
||||||
} else {
|
} else {
|
||||||
textFace := face
|
textFace := face
|
||||||
if fillColorNode != nil && fillColorNode.AxialShd != nil {
|
if fillColorNode != nil && fillColorNode.AxialShd != nil {
|
||||||
textFace = ff.Face(sizePt, glyphFillPaint, fontStyle, canvas.FontNormal)
|
textFace = ff.Face(sizePt, glyphFillPaint, fontStyle, canvas.FontNormal)
|
||||||
}
|
}
|
||||||
text := canvas.NewTextLine(textFace, str, canvas.Left)
|
text := canvas.NewTextLine(textFace, str, canvas.Left)
|
||||||
ctx.DrawText(canvasX, canvasY, text)
|
ctx.DrawText(x, y, text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if useTextMatrix {
|
||||||
|
ctx.Push()
|
||||||
|
ctx.Translate(canvasX, canvasY)
|
||||||
|
ctx.ComposeView(textMatrix(ctm))
|
||||||
|
drawGlyph(0, 0)
|
||||||
|
if strings.Contains(obj.Decoration, "Underline") {
|
||||||
|
uw := sizeMM * 0.05
|
||||||
|
ctx.SetStrokeWidth(uw)
|
||||||
|
ctx.SetStrokeColor(fillColor)
|
||||||
|
off := sizeMM * 0.1
|
||||||
|
ctx.MoveTo(0, -off)
|
||||||
|
ctx.LineTo(textWidth, -off)
|
||||||
|
ctx.Stroke()
|
||||||
|
}
|
||||||
|
ctx.Pop()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
drawGlyph(canvasX, canvasY)
|
||||||
|
}
|
||||||
if strings.Contains(obj.Decoration, "Underline") {
|
if strings.Contains(obj.Decoration, "Underline") {
|
||||||
uw := sizeMM * 0.05
|
uw := sizeMM * 0.05
|
||||||
ctx.SetStrokeWidth(uw)
|
ctx.SetStrokeWidth(uw)
|
||||||
@@ -782,6 +803,24 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
ctx.Pop()
|
ctx.Pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hasTextMatrix 判断文本是否需要应用字形变换
|
||||||
|
// 入参: ctm 变换矩阵
|
||||||
|
// 返回: bool 是否需要变换
|
||||||
|
func hasTextMatrix(ctm Matrix) bool {
|
||||||
|
const eps = 1e-9
|
||||||
|
return math.Abs(ctm.a-1) > eps || math.Abs(ctm.b) > eps || math.Abs(ctm.c) > eps || math.Abs(ctm.d-1) > eps
|
||||||
|
}
|
||||||
|
|
||||||
|
// textMatrix 获取文本字形变换矩阵
|
||||||
|
// 入参: ctm OFD变换矩阵
|
||||||
|
// 返回: canvas.Matrix 画布变换矩阵
|
||||||
|
func textMatrix(ctm Matrix) canvas.Matrix {
|
||||||
|
return canvas.Matrix{
|
||||||
|
{ctm.a, -ctm.c, 0},
|
||||||
|
{-ctm.b, ctm.d, 0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// loadFont 加载字体
|
// loadFont 加载字体
|
||||||
// 入参: fontID 字体ID
|
// 入参: fontID 字体ID
|
||||||
// 返回: *canvas.FontFamily 字体族
|
// 返回: *canvas.FontFamily 字体族
|
||||||
|
|||||||
+30
-3
@@ -138,9 +138,10 @@ func extractSeal(data []byte) (string, []byte) {
|
|||||||
if node.IsCompound {
|
if node.IsCompound {
|
||||||
if elements, ok := asn1Children(node.Bytes); ok {
|
if elements, ok := asn1Children(node.Bytes); ok {
|
||||||
if len(elements) >= 2 && elements[1].Tag == 4 {
|
if len(elements) >= 2 && elements[1].Tag == 4 {
|
||||||
sealType := sealString(elements[0])
|
sealType := normalizeSealType(sealString(elements[0]))
|
||||||
if sealType == "es" {
|
if isSealMediaType(sealType) {
|
||||||
sealType = "png"
|
foundType, foundData = sealType, elements[1].Bytes
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
if imgType, sealData := extractImageData(elements[1].Bytes); len(sealData) > 0 {
|
if imgType, sealData := extractImageData(elements[1].Bytes); len(sealData) > 0 {
|
||||||
if sealType == "" {
|
if sealType == "" {
|
||||||
@@ -197,6 +198,32 @@ func sealString(raw asn1.RawValue) string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// normalizeSealType 标准化印章媒体类型
|
||||||
|
// 入参: s 原始媒体类型
|
||||||
|
// 返回: string 标准媒体类型
|
||||||
|
func normalizeSealType(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "jpg":
|
||||||
|
return "jpeg"
|
||||||
|
case "jb2", "gbig2":
|
||||||
|
return "jbig2"
|
||||||
|
default:
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// isSealMediaType 判断是否为可渲染印章媒体类型
|
||||||
|
// 入参: s 媒体类型
|
||||||
|
// 返回: bool 是否可渲染
|
||||||
|
func isSealMediaType(s string) bool {
|
||||||
|
switch s {
|
||||||
|
case "png", "jpeg", "jbig2", "ofd":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// extractImageData 提取图片数据
|
// extractImageData 提取图片数据
|
||||||
// 入参: data 原始数据
|
// 入参: data 原始数据
|
||||||
// 返回: string 图片类型, []byte 图片数据
|
// 返回: string 图片类型, []byte 图片数据
|
||||||
|
|||||||
Reference in New Issue
Block a user