Files
ofdgo/ofdgo_renderer_stamp_canvas.go
T
2026-10-19 08:43:50 +08:00

169 lines
4.3 KiB
Go

// Copyright 2025-2026 肖其顿 (XIAO QI DUN)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ofdgo
import (
"bytes"
"context"
"image"
"github.com/tdewolff/canvas"
baseimage "github.com/xiaoqidun/ofdgo/internal/base/image"
)
// renderStamp 渲染印章
// 入参: ctx 画布上下文, s 印章对象, pageH 页面高度
func (r *Renderer) renderStamp(ctx *canvas.Context, s Stamp, pageH float64) {
if r.textOnly {
return
}
pageContext := r.pageContext
if pageContext == nil {
pageContext = context.Background()
}
defer func() {
if err := pageContext.Err(); err != nil {
r.renderError = err
}
}()
if err := pageContext.Err(); err != nil {
r.renderError = err
return
}
if s.Type == "ofd" && len(s.Data) > 0 {
if s.Clip != nil {
if img := r.renderOFDStampImage(s.Data); img != nil {
r.renderStampImage(ctx, img, s, pageH)
}
return
}
reader, err := NewReader(&Input{reader: bytes.NewReader(s.Data), size: int64(len(s.Data))})
if err == nil {
defer reader.Close()
doc, err := reader.DocContext(pageContext)
if err == nil {
renderer := r.childRenderer(reader)
for _, pageRef := range doc.Pages.Page {
content, err := reader.PageContentContext(pageContext, pageRef)
if err != nil {
if pageContext.Err() != nil {
return
}
r.renderError = err
return
}
sealBox, err := renderer.GetPageBox(content)
if err != nil {
r.renderError = err
return
}
ctx.Push()
ctx.Translate(s.Box.X, pageH-(s.Box.Y+s.Box.H))
ctx.Scale(s.Box.W/sealBox.W, s.Box.H/sealBox.H)
err = renderer.renderCanvasPageToContext(ctx, content, false)
ctx.Pop()
if err != nil {
r.renderError = err
return
}
}
return
}
r.renderError = err
return
}
r.renderError = err
return
}
if len(s.Data) > 0 {
img, _, err := baseimage.DecodeContext(pageContext, s.Data)
if err != nil {
r.renderError = err
return
}
r.renderStampImage(ctx, img, s, pageH)
}
}
// renderOFDStampImage 渲染OFD印章图像
// 入参: data OFD印章数据
// 返回: image.Image 印章图像
func (r *Renderer) renderOFDStampImage(data []byte) image.Image {
ctx := r.pageContext
if ctx == nil {
ctx = context.Background()
}
defer func() {
if err := ctx.Err(); err != nil {
r.renderError = err
}
}()
if err := ctx.Err(); err != nil {
r.renderError = err
return nil
}
reader, err := NewReader(&Input{reader: bytes.NewReader(data), size: int64(len(data))})
if err != nil {
r.renderError = err
return nil
}
defer reader.Close()
doc, err := reader.DocContext(ctx)
if err != nil {
r.renderError = err
return nil
}
renderer := r.childRenderer(reader)
renderer.decodeImages = true
renderer.TransparentBackground = true
for _, pageRef := range doc.Pages.Page {
content, err := reader.PageContentContext(ctx, pageRef)
if err != nil {
if ctx.Err() != nil {
return nil
}
r.renderError = err
return nil
}
img, err := renderer.RenderToImage(content)
if err != nil {
r.renderError = err
return nil
}
return img
}
return nil
}
// renderStampImage 渲染印章图像
// 入参: ctx 画布上下文, img 印章图像, s 印章对象, pageH 页面高度
func (r *Renderer) renderStampImage(ctx *canvas.Context, img image.Image, s Stamp, pageH float64) {
pixels, err := baseimage.PixelDataContext(r.pageContext, img)
if err != nil {
r.renderError = err
return
}
if r.decodeImages {
img = pixels
}
box := s.Box
var clip *canvas.Path
if s.Clip != nil {
clip = canvas.Rectangle(s.Clip.W, s.Clip.H).Translate(box.X+s.Clip.X, pageH-box.Y-s.Clip.Y-s.Clip.H)
}
matrix := canvas.Identity.Translate(box.X, pageH-box.Y-box.H).Scale(box.W/float64(img.Bounds().Dx()), box.H/float64(img.Bounds().Dy()))
r.drawClippedImage(ctx, img, clip, matrix)
}