mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-08-30 12:12:40 +08:00
feat(渲染注释): 渲染注释,可配置不渲染
This commit is contained in:
@@ -67,6 +67,7 @@ func NewRenderer(reader *Reader, opts ...RendererOption) *Renderer {
|
|||||||
r := &Renderer{
|
r := &Renderer{
|
||||||
Reader: reader,
|
Reader: reader,
|
||||||
DPI: 300.0,
|
DPI: 300.0,
|
||||||
|
RenderAnnotations: true,
|
||||||
DrawParams: reader.drawParamCache,
|
DrawParams: reader.drawParamCache,
|
||||||
CompositeGraphicUnits: reader.compositeGraphicUnitCache,
|
CompositeGraphicUnits: reader.compositeGraphicUnitCache,
|
||||||
FontMap: make(map[string]*canvas.FontFamily),
|
FontMap: make(map[string]*canvas.FontFamily),
|
||||||
@@ -87,6 +88,15 @@ func WithDPI(dpi float64) RendererOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithAnnotations 设置是否渲染注释外观
|
||||||
|
// 入参: enable 是否渲染
|
||||||
|
// 返回: RendererOption 渲染选项
|
||||||
|
func WithAnnotations(enable bool) RendererOption {
|
||||||
|
return func(r *Renderer) {
|
||||||
|
r.RenderAnnotations = enable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithFontDirs 设置外部字体查找目录
|
// WithFontDirs 设置外部字体查找目录
|
||||||
// 入参: dirs 字体目录列表
|
// 入参: dirs 字体目录列表
|
||||||
// 返回: RendererOption 渲染选项
|
// 返回: RendererOption 渲染选项
|
||||||
|
|||||||
+58
-4
@@ -38,15 +38,69 @@ type Annotations struct {
|
|||||||
|
|
||||||
// AnnPage 页面注释引用
|
// AnnPage 页面注释引用
|
||||||
type AnnPage struct {
|
type AnnPage struct {
|
||||||
PageID string `xml:"PageID,attr"`
|
PageID string `xml:"PageID,attr"`
|
||||||
Annotation []Annotation `xml:"Annotation"`
|
FileLoc string `xml:"FileLoc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Annotation 注释定义
|
// PageAnnot 页面注释集合
|
||||||
|
type PageAnnot struct {
|
||||||
|
XMLName xml.Name `xml:"PageAnnot"`
|
||||||
|
Annot []Annotation `xml:"Annot"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotation 页面注释
|
||||||
type Annotation struct {
|
type Annotation struct {
|
||||||
ID string `xml:"ID,attr"`
|
ID string `xml:"ID,attr"`
|
||||||
Type string `xml:"Type,attr"`
|
Type string `xml:"Type,attr"`
|
||||||
|
Subtype string `xml:"Subtype,attr"`
|
||||||
Creator string `xml:"Creator,attr"`
|
Creator string `xml:"Creator,attr"`
|
||||||
LastModDate string `xml:"LastModDate,attr"`
|
LastModDate string `xml:"LastModDate,attr"`
|
||||||
Loc string `xml:"Loc,attr"`
|
Appearance Appearance
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appearance 注释外观
|
||||||
|
type Appearance struct {
|
||||||
|
Boundary string `xml:"Boundary,attr"`
|
||||||
|
Objects []GraphicObject `xml:"-"`
|
||||||
|
TextObject []TextObject `xml:"TextObject"`
|
||||||
|
PathObject []PathObject `xml:"PathObject"`
|
||||||
|
ImageObject []ImageObject `xml:"ImageObject"`
|
||||||
|
CompositeGraphicUnit []CompositeGraphicUnit `xml:"CompositeGraphicUnit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseAnnotations 解析注释文件
|
||||||
|
// 入参: doc 文档结构
|
||||||
|
// 返回: error 错误信息
|
||||||
|
func (r *Reader) parseAnnotations(doc *Document) error {
|
||||||
|
if doc.Annotations == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
annPath := r.ResPath(doc.Annotations)
|
||||||
|
f, err := r.openFile(annPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
var annotations Annotations
|
||||||
|
if err := xml.NewDecoder(f).Decode(&annotations); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if r.Annots == nil {
|
||||||
|
r.Annots = make(map[string][]Annotation)
|
||||||
|
}
|
||||||
|
for _, page := range annotations.Page {
|
||||||
|
annotPath := resolveResourcePath(annPath, "", page.FileLoc)
|
||||||
|
af, err := r.openFile(annotPath)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var pageAnnot PageAnnot
|
||||||
|
err = xml.NewDecoder(af).Decode(&pageAnnot)
|
||||||
|
_ = af.Close()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r.Annots[page.PageID] = append(r.Annots[page.PageID], pageAnnot.Annot...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,6 +123,11 @@ func (c *CompositeGraphicUnit) UnmarshalXML(d *xml.Decoder, start xml.StartEleme
|
|||||||
c.Alpha = &alpha
|
c.Alpha = &alpha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if value := attrValue(start, "Visible"); value != "" {
|
||||||
|
if visible, err := strconv.ParseBool(value); err == nil {
|
||||||
|
c.Visible = &visible
|
||||||
|
}
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
tok, err := d.Token()
|
tok, err := d.Token()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -210,6 +215,93 @@ func (c *CompositeGraphicUnit) decodePageBlock(d *xml.Decoder, start xml.StartEl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析注释外观并保留对象顺序
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 错误信息
|
||||||
|
func (a *Appearance) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
*a = Appearance{}
|
||||||
|
a.Boundary = attrValue(start, "Boundary")
|
||||||
|
for {
|
||||||
|
tok, err := d.Token()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch node := tok.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
if err := a.decodeObject(d, node); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case xml.EndElement:
|
||||||
|
if node.Name.Local == start.Name.Local {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeObject 解析注释外观子对象
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 错误信息
|
||||||
|
func (a *Appearance) decodeObject(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
switch start.Name.Local {
|
||||||
|
case "TextObject":
|
||||||
|
var obj TextObject
|
||||||
|
if err := d.DecodeElement(&obj, &start); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.TextObject = append(a.TextObject, obj)
|
||||||
|
a.Objects = append(a.Objects, GraphicObject{Type: start.Name.Local, TextObject: obj})
|
||||||
|
case "PathObject":
|
||||||
|
var obj PathObject
|
||||||
|
if err := d.DecodeElement(&obj, &start); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.PathObject = append(a.PathObject, obj)
|
||||||
|
a.Objects = append(a.Objects, GraphicObject{Type: start.Name.Local, PathObject: obj})
|
||||||
|
case "ImageObject":
|
||||||
|
var obj ImageObject
|
||||||
|
if err := d.DecodeElement(&obj, &start); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.ImageObject = append(a.ImageObject, obj)
|
||||||
|
a.Objects = append(a.Objects, GraphicObject{Type: start.Name.Local, ImageObject: obj})
|
||||||
|
case "CompositeGraphicUnit", "CompositeObject":
|
||||||
|
var obj CompositeGraphicUnit
|
||||||
|
if err := d.DecodeElement(&obj, &start); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.CompositeGraphicUnit = append(a.CompositeGraphicUnit, obj)
|
||||||
|
a.Objects = append(a.Objects, GraphicObject{Type: start.Name.Local, CompositeGraphicUnit: obj})
|
||||||
|
case "PageBlock":
|
||||||
|
return a.decodePageBlock(d, start)
|
||||||
|
default:
|
||||||
|
return d.Skip()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodePageBlock 解析注释外观页块子对象
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 错误信息
|
||||||
|
func (a *Appearance) decodePageBlock(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
for {
|
||||||
|
tok, err := d.Token()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch node := tok.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
if err := a.decodeObject(d, node); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case xml.EndElement:
|
||||||
|
if node.Name.Local == start.Name.Local {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// attrValue 获取XML属性值
|
// attrValue 获取XML属性值
|
||||||
// 入参: start 起始节点, name 属性名
|
// 入参: start 起始节点, name 属性名
|
||||||
// 返回: string 属性值
|
// 返回: string 属性值
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ type TextObject struct {
|
|||||||
HScale float64 `xml:"HScale,attr"`
|
HScale float64 `xml:"HScale,attr"`
|
||||||
VScale float64 `xml:"VScale,attr"`
|
VScale float64 `xml:"VScale,attr"`
|
||||||
CTM string `xml:"CTM,attr"`
|
CTM string `xml:"CTM,attr"`
|
||||||
|
Alpha *int `xml:"Alpha,attr"`
|
||||||
|
Visible *bool `xml:"Visible,attr"`
|
||||||
Fill *bool `xml:"Fill,attr"`
|
Fill *bool `xml:"Fill,attr"`
|
||||||
Stroke *bool `xml:"Stroke,attr"`
|
Stroke *bool `xml:"Stroke,attr"`
|
||||||
StrokeColor *StrokeColor `xml:"StrokeColor"`
|
StrokeColor *StrokeColor `xml:"StrokeColor"`
|
||||||
@@ -135,6 +137,8 @@ type PathObject struct {
|
|||||||
DashPattern string `xml:"DashPattern,attr"`
|
DashPattern string `xml:"DashPattern,attr"`
|
||||||
MiterLimit float64 `xml:"MiterLimit,attr"`
|
MiterLimit float64 `xml:"MiterLimit,attr"`
|
||||||
CTM string `xml:"CTM,attr"`
|
CTM string `xml:"CTM,attr"`
|
||||||
|
Alpha *int `xml:"Alpha,attr"`
|
||||||
|
Visible *bool `xml:"Visible,attr"`
|
||||||
Stroke *bool `xml:"Stroke,attr"`
|
Stroke *bool `xml:"Stroke,attr"`
|
||||||
Fill *bool `xml:"Fill,attr"`
|
Fill *bool `xml:"Fill,attr"`
|
||||||
StrokeColor *StrokeColor `xml:"StrokeColor"`
|
StrokeColor *StrokeColor `xml:"StrokeColor"`
|
||||||
@@ -187,5 +191,7 @@ type ImageObject struct {
|
|||||||
Boundary string `xml:"Boundary,attr"`
|
Boundary string `xml:"Boundary,attr"`
|
||||||
ResourceID string `xml:"ResourceID,attr"`
|
ResourceID string `xml:"ResourceID,attr"`
|
||||||
CTM string `xml:"CTM,attr"`
|
CTM string `xml:"CTM,attr"`
|
||||||
|
Alpha *int `xml:"Alpha,attr"`
|
||||||
|
Visible *bool `xml:"Visible,attr"`
|
||||||
Clips *Clips `xml:"Clips"`
|
Clips *Clips `xml:"Clips"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ type Reader struct {
|
|||||||
compositeGraphicUnitCache map[string]*CompositeGraphicUnit
|
compositeGraphicUnitCache map[string]*CompositeGraphicUnit
|
||||||
doc *Document
|
doc *Document
|
||||||
Stamps map[string][]Stamp
|
Stamps map[string][]Stamp
|
||||||
|
Annots map[string][]Annotation
|
||||||
fileIndex map[string]*zip.File
|
fileIndex map[string]*zip.File
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,6 +139,7 @@ func (r *Reader) Doc() (*Document, error) {
|
|||||||
r.loadRes(doc.CommonData.PublicRes)
|
r.loadRes(doc.CommonData.PublicRes)
|
||||||
}
|
}
|
||||||
r.doc = &doc
|
r.doc = &doc
|
||||||
|
_ = r.parseAnnotations(&doc)
|
||||||
_ = r.parseSignatures(&doc)
|
_ = r.parseSignatures(&doc)
|
||||||
return r.doc, nil
|
return r.doc, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-14
@@ -38,6 +38,7 @@ import (
|
|||||||
type Renderer struct {
|
type Renderer struct {
|
||||||
Reader *Reader
|
Reader *Reader
|
||||||
DPI float64
|
DPI float64
|
||||||
|
RenderAnnotations bool
|
||||||
fontFamily *canvas.FontFamily
|
fontFamily *canvas.FontFamily
|
||||||
DrawParams map[string]*DrawParam
|
DrawParams map[string]*DrawParam
|
||||||
CompositeGraphicUnits map[string]*CompositeGraphicUnit
|
CompositeGraphicUnits map[string]*CompositeGraphicUnit
|
||||||
@@ -127,6 +128,9 @@ func (r *Renderer) renderPageToContext(ctx *canvas.Context, page *PageContent, d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if r.RenderAnnotations {
|
||||||
|
r.renderAnnotations(ctx, page.ID, pageH)
|
||||||
|
}
|
||||||
if stamps, ok := r.Reader.Stamps[page.ID]; ok {
|
if stamps, ok := r.Reader.Stamps[page.ID]; ok {
|
||||||
for _, stamp := range stamps {
|
for _, stamp := range stamps {
|
||||||
r.renderStamp(ctx, stamp, pageH)
|
r.renderStamp(ctx, stamp, pageH)
|
||||||
@@ -232,6 +236,21 @@ func (r *Renderer) RenderToMultiPagePDF(writer io.Writer) error {
|
|||||||
return p.Close()
|
return p.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renderAnnotations 渲染页面注释外观
|
||||||
|
// 入参: ctx 画布上下文, pageID 页面ID, pageH 页面高度
|
||||||
|
func (r *Renderer) renderAnnotations(ctx *canvas.Context, pageID string, pageH float64) {
|
||||||
|
for _, annot := range r.Reader.Annots[pageID] {
|
||||||
|
if strings.EqualFold(annot.Type, "Link") || len(annot.Appearance.Objects) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
box, _ := ParseBox(annot.Appearance.Boundary)
|
||||||
|
ctm := Matrix{a: 1, d: 1, e: box.X, f: box.Y}
|
||||||
|
for _, obj := range annot.Appearance.Objects {
|
||||||
|
r.renderObject(ctx, obj, pageH, nil, nil, 0, &ctm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// renderTemplate 渲染模板
|
// renderTemplate 渲染模板
|
||||||
// 入参: ctx 画布上下文, templateID 模板ID, pageH 页面高度
|
// 入参: ctx 画布上下文, templateID 模板ID, pageH 页面高度
|
||||||
func (r *Renderer) renderTemplate(ctx *canvas.Context, templateID string, pageH float64) {
|
func (r *Renderer) renderTemplate(ctx *canvas.Context, templateID string, pageH float64) {
|
||||||
@@ -295,6 +314,9 @@ func (r *Renderer) renderLayer(ctx *canvas.Context, layer Layer, pageH float64,
|
|||||||
// renderCompositeGraphicUnit 渲染复合图元
|
// renderCompositeGraphicUnit 渲染复合图元
|
||||||
// 入参: ctx 画布上下文, cgu 复合图元对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽, parentCTM 父级CTM
|
// 入参: ctx 画布上下文, cgu 复合图元对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽, parentCTM 父级CTM
|
||||||
func (r *Renderer) renderCompositeGraphicUnit(ctx *canvas.Context, cgu CompositeGraphicUnit, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix) {
|
func (r *Renderer) renderCompositeGraphicUnit(ctx *canvas.Context, cgu CompositeGraphicUnit, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix) {
|
||||||
|
if cgu.Visible != nil && !*cgu.Visible {
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.Push()
|
ctx.Push()
|
||||||
currentCTM := NewMatrix(cgu.CTM)
|
currentCTM := NewMatrix(cgu.CTM)
|
||||||
if parentCTM != nil {
|
if parentCTM != nil {
|
||||||
@@ -432,6 +454,9 @@ func (r *Renderer) initCommon() {
|
|||||||
// renderImage 渲染图片
|
// renderImage 渲染图片
|
||||||
// 入参: ctx 画布上下文, obj 图片对象, pageH 页面高度, parentCTM 父级CTM
|
// 入参: ctx 画布上下文, obj 图片对象, pageH 页面高度, parentCTM 父级CTM
|
||||||
func (r *Renderer) renderImage(ctx *canvas.Context, obj ImageObject, pageH float64, parentCTM *Matrix) {
|
func (r *Renderer) renderImage(ctx *canvas.Context, obj ImageObject, pageH float64, parentCTM *Matrix) {
|
||||||
|
if obj.Visible != nil && !*obj.Visible {
|
||||||
|
return
|
||||||
|
}
|
||||||
resPath, ok := r.Reader.ResMap[obj.ResourceID]
|
resPath, ok := r.Reader.ResMap[obj.ResourceID]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
@@ -470,6 +495,9 @@ func (r *Renderer) renderImage(ctx *canvas.Context, obj ImageObject, pageH float
|
|||||||
// renderPath 渲染路径
|
// renderPath 渲染路径
|
||||||
// 入参: ctx 画布上下文, obj 路径对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽, parentCTM 父级CTM
|
// 入参: ctx 画布上下文, obj 路径对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽, parentCTM 父级CTM
|
||||||
func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix) {
|
func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix) {
|
||||||
|
if obj.Visible != nil && !*obj.Visible {
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.Push()
|
ctx.Push()
|
||||||
bx, by := 0.0, 0.0
|
bx, by := 0.0, 0.0
|
||||||
if obj.Boundary != "" {
|
if obj.Boundary != "" {
|
||||||
@@ -499,12 +527,14 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
lineWidth = dp.LineWidth
|
lineWidth = dp.LineWidth
|
||||||
}
|
}
|
||||||
if dp.FillColor != nil {
|
if dp.FillColor != nil {
|
||||||
fillColor = parseFillColor(dp.FillColor)
|
fillColorNode := withFillAlpha(dp.FillColor, obj.Alpha)
|
||||||
fillPaint = parseFillPaint(dp.FillColor, bx, by, pageH, 0, 0)
|
fillColor = parseFillColor(fillColorNode)
|
||||||
|
fillPaint = parseFillPaint(fillColorNode, bx, by, pageH, 0, 0)
|
||||||
}
|
}
|
||||||
if dp.StrokeColor != nil {
|
if dp.StrokeColor != nil {
|
||||||
strokeColor = parseStrokeColor(dp.StrokeColor)
|
strokeColorNode := withStrokeAlpha(dp.StrokeColor, obj.Alpha)
|
||||||
strokePaint = parseStrokePaint(dp.StrokeColor, bx, by, pageH, 0, 0)
|
strokeColor = parseStrokeColor(strokeColorNode)
|
||||||
|
strokePaint = parseStrokePaint(strokeColorNode, bx, by, pageH, 0, 0)
|
||||||
}
|
}
|
||||||
if dp.Cap == "Round" {
|
if dp.Cap == "Round" {
|
||||||
lineCap = canvas.RoundCap
|
lineCap = canvas.RoundCap
|
||||||
@@ -526,12 +556,14 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
lineWidth = obj.LineWidth
|
lineWidth = obj.LineWidth
|
||||||
}
|
}
|
||||||
if obj.FillColor != nil {
|
if obj.FillColor != nil {
|
||||||
fillColor = parseFillColor(obj.FillColor)
|
fillColorNode := withFillAlpha(obj.FillColor, obj.Alpha)
|
||||||
fillPaint = parseFillPaint(obj.FillColor, bx, by, pageH, 0, 0)
|
fillColor = parseFillColor(fillColorNode)
|
||||||
|
fillPaint = parseFillPaint(fillColorNode, bx, by, pageH, 0, 0)
|
||||||
}
|
}
|
||||||
if obj.StrokeColor != nil {
|
if obj.StrokeColor != nil {
|
||||||
strokeColor = parseStrokeColor(obj.StrokeColor)
|
strokeColorNode := withStrokeAlpha(obj.StrokeColor, obj.Alpha)
|
||||||
strokePaint = parseStrokePaint(obj.StrokeColor, bx, by, pageH, 0, 0)
|
strokeColor = parseStrokeColor(strokeColorNode)
|
||||||
|
strokePaint = parseStrokePaint(strokeColorNode, bx, by, pageH, 0, 0)
|
||||||
}
|
}
|
||||||
if obj.Cap != "" {
|
if obj.Cap != "" {
|
||||||
if obj.Cap == "Round" {
|
if obj.Cap == "Round" {
|
||||||
@@ -624,6 +656,9 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
// renderText 渲染文本
|
// renderText 渲染文本
|
||||||
// 入参: ctx 画布上下文, obj 文本对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, parentCTM 父级CTM
|
// 入参: ctx 画布上下文, obj 文本对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, parentCTM 父级CTM
|
||||||
func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64, defaultFill, defaultStroke color.Color, parentCTM *Matrix) {
|
func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64, defaultFill, defaultStroke color.Color, parentCTM *Matrix) {
|
||||||
|
if obj.Visible != nil && !*obj.Visible {
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.Push()
|
ctx.Push()
|
||||||
bx, by := 0.0, 0.0
|
bx, by := 0.0, 0.0
|
||||||
if obj.Boundary != "" {
|
if obj.Boundary != "" {
|
||||||
@@ -662,14 +697,14 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
var fillPaint any = fillColor
|
var fillPaint any = fillColor
|
||||||
var fillColorNode *FillColor
|
var fillColorNode *FillColor
|
||||||
if dp != nil && dp.FillColor != nil {
|
if dp != nil && dp.FillColor != nil {
|
||||||
fillColor = parseFillColor(dp.FillColor)
|
fillColorNode = withFillAlpha(dp.FillColor, obj.Alpha)
|
||||||
fillColorNode = dp.FillColor
|
fillColor = parseFillColor(fillColorNode)
|
||||||
fillPaint = parseFillPaint(dp.FillColor, bx, by, pageH, 0, 0)
|
fillPaint = parseFillPaint(fillColorNode, bx, by, pageH, 0, 0)
|
||||||
}
|
}
|
||||||
if obj.FillColor != nil {
|
if obj.FillColor != nil {
|
||||||
fillColor = parseFillColor(obj.FillColor)
|
fillColorNode = withFillAlpha(obj.FillColor, obj.Alpha)
|
||||||
fillColorNode = obj.FillColor
|
fillColor = parseFillColor(fillColorNode)
|
||||||
fillPaint = parseFillPaint(obj.FillColor, bx, by, pageH, 0, 0)
|
fillPaint = parseFillPaint(fillColorNode, bx, by, pageH, 0, 0)
|
||||||
}
|
}
|
||||||
if fillPaint == nil {
|
if fillPaint == nil {
|
||||||
fillPaint = fillColor
|
fillPaint = fillColor
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ type CompositeGraphicUnit struct {
|
|||||||
CTM string `xml:"CTM,attr"`
|
CTM string `xml:"CTM,attr"`
|
||||||
DrawParam string `xml:"DrawParam,attr"`
|
DrawParam string `xml:"DrawParam,attr"`
|
||||||
Alpha *int `xml:"Alpha,attr"`
|
Alpha *int `xml:"Alpha,attr"`
|
||||||
|
Visible *bool `xml:"Visible,attr"`
|
||||||
Objects []GraphicObject `xml:"-"`
|
Objects []GraphicObject `xml:"-"`
|
||||||
TextObject []TextObject `xml:"TextObject"`
|
TextObject []TextObject `xml:"TextObject"`
|
||||||
PathObject []PathObject `xml:"PathObject"`
|
PathObject []PathObject `xml:"PathObject"`
|
||||||
|
|||||||
+65
-1
@@ -42,11 +42,72 @@ func parseColorWithAlpha(val string, alpha *int) color.Color {
|
|||||||
if alpha != nil {
|
if alpha != nil {
|
||||||
a = *alpha
|
a = *alpha
|
||||||
}
|
}
|
||||||
return color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: uint8(a)}
|
a = clampColor(a)
|
||||||
|
return color.RGBA{
|
||||||
|
R: uint8(clampColor(r) * a / 255),
|
||||||
|
G: uint8(clampColor(g) * a / 255),
|
||||||
|
B: uint8(clampColor(b) * a / 255),
|
||||||
|
A: uint8(a),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return color.Black
|
return color.Black
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clampColor 限制颜色分量范围
|
||||||
|
// 入参: v 颜色分量
|
||||||
|
// 返回: int 颜色分量
|
||||||
|
func clampColor(v int) int {
|
||||||
|
if v < 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if v > 255 {
|
||||||
|
return 255
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeAlpha 合并透明度
|
||||||
|
// 入参: colorAlpha 颜色透明度, objectAlpha 对象透明度
|
||||||
|
// 返回: *int 合并后的透明度
|
||||||
|
func mergeAlpha(colorAlpha, objectAlpha *int) *int {
|
||||||
|
if colorAlpha == nil && objectAlpha == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
alpha := 255
|
||||||
|
if colorAlpha != nil {
|
||||||
|
alpha = *colorAlpha
|
||||||
|
}
|
||||||
|
if objectAlpha != nil {
|
||||||
|
alpha = alpha * *objectAlpha / 255
|
||||||
|
}
|
||||||
|
alpha = clampColor(alpha)
|
||||||
|
return &alpha
|
||||||
|
}
|
||||||
|
|
||||||
|
// withFillAlpha 合并填充色透明度
|
||||||
|
// 入参: fillColor 填充颜色节点, alpha 对象透明度
|
||||||
|
// 返回: *FillColor 合并后的填充颜色节点
|
||||||
|
func withFillAlpha(fillColor *FillColor, alpha *int) *FillColor {
|
||||||
|
if fillColor == nil || alpha == nil {
|
||||||
|
return fillColor
|
||||||
|
}
|
||||||
|
merged := *fillColor
|
||||||
|
merged.Alpha = mergeAlpha(fillColor.Alpha, alpha)
|
||||||
|
return &merged
|
||||||
|
}
|
||||||
|
|
||||||
|
// withStrokeAlpha 合并勾边色透明度
|
||||||
|
// 入参: strokeColor 勾边颜色节点, alpha 对象透明度
|
||||||
|
// 返回: *StrokeColor 合并后的勾边颜色节点
|
||||||
|
func withStrokeAlpha(strokeColor *StrokeColor, alpha *int) *StrokeColor {
|
||||||
|
if strokeColor == nil || alpha == nil {
|
||||||
|
return strokeColor
|
||||||
|
}
|
||||||
|
merged := *strokeColor
|
||||||
|
merged.Alpha = mergeAlpha(strokeColor.Alpha, alpha)
|
||||||
|
return &merged
|
||||||
|
}
|
||||||
|
|
||||||
// parseFillColor 解析填充颜色
|
// parseFillColor 解析填充颜色
|
||||||
// 入参: fillColor 填充颜色节点
|
// 入参: fillColor 填充颜色节点
|
||||||
// 返回: color.Color 颜色对象
|
// 返回: color.Color 颜色对象
|
||||||
@@ -228,6 +289,9 @@ func parseRadialShdGradient(radialShd *RadialShd, alpha *int, x, y, pageH, origi
|
|||||||
// 入参: c 颜色对象
|
// 入参: c 颜色对象
|
||||||
// 返回: color.RGBA RGBA颜色
|
// 返回: color.RGBA RGBA颜色
|
||||||
func colorToRGBA(c color.Color) color.RGBA {
|
func colorToRGBA(c color.Color) color.RGBA {
|
||||||
|
if rgba, ok := c.(color.RGBA); ok {
|
||||||
|
return rgba
|
||||||
|
}
|
||||||
r, g, b, a := c.RGBA()
|
r, g, b, a := c.RGBA()
|
||||||
return color.RGBA{R: uint8(r >> 8), G: uint8(g >> 8), B: uint8(b >> 8), A: uint8(a >> 8)}
|
return color.RGBA{R: uint8(r >> 8), G: uint8(g >> 8), B: uint8(b >> 8), A: uint8(a >> 8)}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user