mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 16:59:27 +08:00
1 parent
777d0c7c89
commit
e5e07f92cd
7 files changed
+166
-141
No files matched your search
@@ -82,6 +82,8 @@ type TextObject struct {
|
|||||||
Boundary string `xml:"Boundary,attr"`
|
Boundary string `xml:"Boundary,attr"`
|
||||||
DrawParam string `xml:"DrawParam,attr"`
|
DrawParam string `xml:"DrawParam,attr"`
|
||||||
LineWidth float64 `xml:"LineWidth,attr"`
|
LineWidth float64 `xml:"LineWidth,attr"`
|
||||||
|
Join string `xml:"Join,attr"`
|
||||||
|
MiterLimit float64 `xml:"MiterLimit,attr"`
|
||||||
Font string `xml:"Font,attr"`
|
Font string `xml:"Font,attr"`
|
||||||
Size float64 `xml:"Size,attr"`
|
Size float64 `xml:"Size,attr"`
|
||||||
Weight int `xml:"Weight,attr"`
|
Weight int `xml:"Weight,attr"`
|
||||||
|
|||||||
+8
-14
@@ -215,18 +215,18 @@ func (r *Renderer) parseStrokePaint(strokeColor *StrokeColor, x, y, pageH float6
|
|||||||
|
|
||||||
type patternPaint struct {
|
type patternPaint struct {
|
||||||
*Pattern
|
*Pattern
|
||||||
color color.Color
|
color FillColor
|
||||||
alpha *int
|
alpha *int
|
||||||
}
|
}
|
||||||
|
|
||||||
// parsePatternPaint 解析底纹画刷
|
// parsePatternPaint 解析底纹画刷
|
||||||
// 入参: pattern 底纹对象, value 颜色值, index 调色板索引, space 颜色空间标识, alpha 透明度
|
// 入参: fill 填充颜色节点
|
||||||
// 返回: *patternPaint 底纹画刷
|
// 返回: *patternPaint 底纹画刷
|
||||||
func (r *Renderer) parsePatternPaint(pattern *Pattern, value string, index *int, space string, alpha *int) *patternPaint {
|
func parsePatternPaint(fill *FillColor) *patternPaint {
|
||||||
if pattern == nil {
|
if fill.Pattern == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &patternPaint{Pattern: pattern, color: r.parseColorWithAlpha(value, index, space, nil), alpha: alpha}
|
return &patternPaint{Pattern: fill.Pattern, color: FillColor{Value: fill.Value, Index: fill.Index, ColorSpace: fill.ColorSpace}, alpha: fill.Alpha}
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseShdColor 解析渐变颜色
|
// parseShdColor 解析渐变颜色
|
||||||
@@ -299,21 +299,15 @@ func (r *Renderer) parseAxialShdGradient(axialShd *AxialShd, alpha *int, x, y, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
// axialShdClip 获取轴向渐变的延伸裁剪区域
|
// axialShdClip 获取轴向渐变的延伸裁剪区域
|
||||||
// 入参: ctx 画布上下文, gradient 轴向渐变, extend 延伸方向
|
// 入参: gradient 轴向渐变, extend 延伸方向, bounds 可见区域
|
||||||
// 返回: *canvas.Path 裁剪区域
|
// 返回: *canvas.Path 裁剪区域
|
||||||
func axialShdClip(ctx *canvas.Context, gradient *canvas.LinearGradient, extend int) *canvas.Path {
|
func axialShdClip(gradient *canvas.LinearGradient, extend int, bounds canvas.Rect) *canvas.Path {
|
||||||
if extend == 3 {
|
if extend == 3 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
d := gradient.End.Sub(gradient.Start)
|
d := gradient.End.Sub(gradient.Start)
|
||||||
axis := canvas.Matrix{{d.X, -d.Y, gradient.Start.X}, {d.Y, d.X, gradient.Start.Y}}
|
axis := canvas.Matrix{{d.X, -d.Y, gradient.Start.X}, {d.Y, d.X, gradient.Start.Y}}
|
||||||
origin := ctx.CoordView().Dot(canvas.Point{})
|
area := bounds.Transform(axis.Inv())
|
||||||
view := ctx.CoordSystemView().Mul(ctx.View()).Translate(origin.X, origin.Y).Mul(axis)
|
|
||||||
if view.Det() == 0 {
|
|
||||||
return &canvas.Path{}
|
|
||||||
}
|
|
||||||
width, height := ctx.Size()
|
|
||||||
area := (canvas.Rect{X1: width, Y1: height}).Transform(view.Inv())
|
|
||||||
if extend&1 == 0 {
|
if extend&1 == 0 {
|
||||||
area.X0 = math.Max(area.X0, 0)
|
area.X0 = math.Max(area.X0, 0)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -126,7 +126,7 @@ func (r *Renderer) renderPageToContext(ctx *canvas.Context, page *PageContent, d
|
|||||||
}
|
}
|
||||||
if page.Content.Layer != nil {
|
if page.Content.Layer != nil {
|
||||||
for _, layer := range page.Content.Layer {
|
for _, layer := range page.Content.Layer {
|
||||||
r.renderLayer(ctx, layer, pageH, nil, nil, 0, nil)
|
r.renderLayer(ctx, layer, pageH, nil, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(page.Template) > 0 && r.Reader.doc != nil {
|
if len(page.Template) > 0 && r.Reader.doc != nil {
|
||||||
|
|||||||
+68
-72
@@ -14,11 +14,7 @@
|
|||||||
|
|
||||||
package ofdgo
|
package ofdgo
|
||||||
|
|
||||||
import (
|
import "github.com/tdewolff/canvas"
|
||||||
"image/color"
|
|
||||||
|
|
||||||
"github.com/tdewolff/canvas"
|
|
||||||
)
|
|
||||||
|
|
||||||
// renderAnnotations 渲染页面注释外观
|
// renderAnnotations 渲染页面注释外观
|
||||||
// 入参: ctx 画布上下文, pageID 页面ID, pageH 页面高度
|
// 入参: ctx 画布上下文, pageID 页面ID, pageH 页面高度
|
||||||
@@ -30,7 +26,7 @@ func (r *Renderer) renderAnnotations(ctx *canvas.Context, pageID string, pageH f
|
|||||||
box, _ := ParseBox(annot.Appearance.Boundary)
|
box, _ := ParseBox(annot.Appearance.Boundary)
|
||||||
ctm := Matrix{a: 1, d: 1, e: box.X, f: box.Y}
|
ctm := Matrix{a: 1, d: 1, e: box.X, f: box.Y}
|
||||||
for _, obj := range annot.Appearance.Objects {
|
for _, obj := range annot.Appearance.Objects {
|
||||||
r.renderObject(ctx, obj, pageH, nil, nil, 0, &ctm, false, nil)
|
r.renderObject(ctx, obj, pageH, nil, &ctm, false, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,38 +55,38 @@ func (r *Renderer) renderTemplate(ctx *canvas.Context, templateID string, pageH
|
|||||||
}
|
}
|
||||||
if tplContent.Content.Layer != nil {
|
if tplContent.Content.Layer != nil {
|
||||||
for _, layer := range tplContent.Content.Layer {
|
for _, layer := range tplContent.Content.Layer {
|
||||||
r.renderLayer(ctx, layer, pageH, nil, nil, 0, nil)
|
r.renderLayer(ctx, layer, pageH, nil, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderLayer 渲染图层
|
// renderLayer 渲染图层
|
||||||
// 入参: ctx 画布上下文, layer 图层对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽, parentCTM 父级CTM
|
// 入参: ctx 画布上下文, layer 图层对象, pageH 页面高度, defaults 默认绘制参数, parentCTM 父级CTM
|
||||||
func (r *Renderer) renderLayer(ctx *canvas.Context, layer Layer, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix) {
|
func (r *Renderer) renderLayer(ctx *canvas.Context, layer Layer, pageH float64, defaults *DrawParam, parentCTM *Matrix) {
|
||||||
defaultFill, defaultStroke, defaultLW = r.drawParamDefaults(layer.DrawParam, defaultFill, defaultStroke, defaultLW)
|
defaults = r.drawParamDefaults(layer.DrawParam, defaults)
|
||||||
if len(layer.Objects) > 0 {
|
if len(layer.Objects) > 0 {
|
||||||
for _, obj := range layer.Objects {
|
for _, obj := range layer.Objects {
|
||||||
r.renderObject(ctx, obj, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, false, nil)
|
r.renderObject(ctx, obj, pageH, defaults, parentCTM, false, nil)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, textObj := range layer.TextObject {
|
for _, textObj := range layer.TextObject {
|
||||||
r.renderText(ctx, textObj, pageH, defaultFill, defaultStroke, parentCTM, false, nil)
|
r.renderText(ctx, textObj, pageH, defaults, parentCTM, false, nil)
|
||||||
}
|
}
|
||||||
for _, pathObj := range layer.PathObject {
|
for _, pathObj := range layer.PathObject {
|
||||||
r.renderPath(ctx, pathObj, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, false, nil)
|
r.renderPath(ctx, pathObj, pageH, defaults, parentCTM, false, nil)
|
||||||
}
|
}
|
||||||
for _, imgObj := range layer.ImageObject {
|
for _, imgObj := range layer.ImageObject {
|
||||||
r.renderImage(ctx, imgObj, pageH, parentCTM, false, nil)
|
r.renderImage(ctx, imgObj, pageH, parentCTM, false, nil)
|
||||||
}
|
}
|
||||||
for _, cgu := range layer.CompositeGraphicUnit {
|
for _, cgu := range layer.CompositeGraphicUnit {
|
||||||
r.renderCompositeGraphicUnit(ctx, cgu, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, false, nil)
|
r.renderCompositeGraphicUnit(ctx, cgu, pageH, defaults, parentCTM, false, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderCompositeGraphicUnit 渲染复合图元
|
// renderCompositeGraphicUnit 渲染复合图元
|
||||||
// 入参: ctx 画布上下文, cgu 复合图元对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽, parentCTM 父级CTM, boundaryInCTM 边界是否参与CTM变换, parentClip 父级裁剪路径
|
// 入参: ctx 画布上下文, cgu 复合图元对象, pageH 页面高度, defaults 默认绘制参数, parentCTM 父级CTM, boundaryInCTM 边界是否参与CTM变换, parentClip 父级裁剪路径
|
||||||
func (r *Renderer) renderCompositeGraphicUnit(ctx *canvas.Context, cgu CompositeGraphicUnit, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) {
|
func (r *Renderer) renderCompositeGraphicUnit(ctx *canvas.Context, cgu CompositeGraphicUnit, pageH float64, defaults *DrawParam, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) {
|
||||||
if cgu.Visible != nil && !*cgu.Visible {
|
if cgu.Visible != nil && !*cgu.Visible {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -109,18 +105,18 @@ func (r *Renderer) renderCompositeGraphicUnit(ctx *canvas.Context, cgu Composite
|
|||||||
clips, clipCTM = &clipCopy, boundaryCTM
|
clips, clipCTM = &clipCopy, boundaryCTM
|
||||||
}
|
}
|
||||||
clipPath := intersectClipPath(parentClip, r.buildClipPath(clips, pageH, 0, 0, clipCTM))
|
clipPath := intersectClipPath(parentClip, r.buildClipPath(clips, pageH, 0, 0, clipCTM))
|
||||||
|
defaults = r.drawParamDefaults(cgu.DrawParam, defaults)
|
||||||
if cgu.ResourceID != "" {
|
if cgu.ResourceID != "" {
|
||||||
if ref, ok := r.CompositeGraphicUnits[cgu.ResourceID]; ok {
|
if ref, ok := r.CompositeGraphicUnits[cgu.ResourceID]; ok {
|
||||||
refCopy := *ref
|
refCopy := *ref
|
||||||
refCopy.Alpha = mergeAlpha(refCopy.Alpha, cgu.Alpha)
|
refCopy.Alpha = mergeAlpha(refCopy.Alpha, cgu.Alpha)
|
||||||
r.renderCompositeGraphicUnit(ctx, refCopy, pageH, defaultFill, defaultStroke, defaultLW, ¤tCTM, true, clipPath)
|
r.renderCompositeGraphicUnit(ctx, refCopy, pageH, defaults, ¤tCTM, true, clipPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defaultFill, defaultStroke, defaultLW = r.drawParamDefaults(cgu.DrawParam, defaultFill, defaultStroke, defaultLW)
|
|
||||||
if len(cgu.Objects) > 0 {
|
if len(cgu.Objects) > 0 {
|
||||||
for _, obj := range cgu.Objects {
|
for _, obj := range cgu.Objects {
|
||||||
obj = mergeGraphicObjectAlpha(obj, cgu.Alpha)
|
obj = mergeGraphicObjectAlpha(obj, cgu.Alpha)
|
||||||
r.renderObject(ctx, obj, pageH, defaultFill, defaultStroke, defaultLW, ¤tCTM, boundaryInCTM, clipPath)
|
r.renderObject(ctx, obj, pageH, defaults, ¤tCTM, boundaryInCTM, clipPath)
|
||||||
}
|
}
|
||||||
ctx.Pop()
|
ctx.Pop()
|
||||||
return
|
return
|
||||||
@@ -131,31 +127,31 @@ func (r *Renderer) renderCompositeGraphicUnit(ctx *canvas.Context, cgu Composite
|
|||||||
}
|
}
|
||||||
for _, pathObj := range cgu.PathObject {
|
for _, pathObj := range cgu.PathObject {
|
||||||
pathObj.Alpha = mergeAlpha(pathObj.Alpha, cgu.Alpha)
|
pathObj.Alpha = mergeAlpha(pathObj.Alpha, cgu.Alpha)
|
||||||
r.renderPath(ctx, pathObj, pageH, defaultFill, defaultStroke, defaultLW, ¤tCTM, boundaryInCTM, clipPath)
|
r.renderPath(ctx, pathObj, pageH, defaults, ¤tCTM, boundaryInCTM, clipPath)
|
||||||
}
|
}
|
||||||
for _, textObj := range cgu.TextObject {
|
for _, textObj := range cgu.TextObject {
|
||||||
textObj.Alpha = mergeAlpha(textObj.Alpha, cgu.Alpha)
|
textObj.Alpha = mergeAlpha(textObj.Alpha, cgu.Alpha)
|
||||||
r.renderText(ctx, textObj, pageH, defaultFill, defaultStroke, ¤tCTM, boundaryInCTM, clipPath)
|
r.renderText(ctx, textObj, pageH, defaults, ¤tCTM, boundaryInCTM, clipPath)
|
||||||
}
|
}
|
||||||
for _, subCgu := range cgu.CompositeGraphicUnit {
|
for _, subCgu := range cgu.CompositeGraphicUnit {
|
||||||
subCgu.Alpha = mergeAlpha(subCgu.Alpha, cgu.Alpha)
|
subCgu.Alpha = mergeAlpha(subCgu.Alpha, cgu.Alpha)
|
||||||
r.renderCompositeGraphicUnit(ctx, subCgu, pageH, defaultFill, defaultStroke, defaultLW, ¤tCTM, boundaryInCTM, clipPath)
|
r.renderCompositeGraphicUnit(ctx, subCgu, pageH, defaults, ¤tCTM, boundaryInCTM, clipPath)
|
||||||
}
|
}
|
||||||
ctx.Pop()
|
ctx.Pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderObject 渲染图形对象
|
// renderObject 渲染图形对象
|
||||||
// 入参: ctx 画布上下文, obj 图形对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽, parentCTM 父级CTM, boundaryInCTM 边界是否参与CTM变换, parentClip 父级裁剪路径
|
// 入参: ctx 画布上下文, obj 图形对象, pageH 页面高度, defaults 默认绘制参数, parentCTM 父级CTM, boundaryInCTM 边界是否参与CTM变换, parentClip 父级裁剪路径
|
||||||
func (r *Renderer) renderObject(ctx *canvas.Context, obj GraphicObject, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) {
|
func (r *Renderer) renderObject(ctx *canvas.Context, obj GraphicObject, pageH float64, defaults *DrawParam, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) {
|
||||||
switch obj.Type {
|
switch obj.Type {
|
||||||
case "TextObject":
|
case "TextObject":
|
||||||
r.renderText(ctx, obj.TextObject, pageH, defaultFill, defaultStroke, parentCTM, boundaryInCTM, parentClip)
|
r.renderText(ctx, obj.TextObject, pageH, defaults, parentCTM, boundaryInCTM, parentClip)
|
||||||
case "PathObject":
|
case "PathObject":
|
||||||
r.renderPath(ctx, obj.PathObject, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, boundaryInCTM, parentClip)
|
r.renderPath(ctx, obj.PathObject, pageH, defaults, parentCTM, boundaryInCTM, parentClip)
|
||||||
case "ImageObject":
|
case "ImageObject":
|
||||||
r.renderImage(ctx, obj.ImageObject, pageH, parentCTM, boundaryInCTM, parentClip)
|
r.renderImage(ctx, obj.ImageObject, pageH, parentCTM, boundaryInCTM, parentClip)
|
||||||
case "CompositeGraphicUnit", "CompositeObject":
|
case "CompositeGraphicUnit", "CompositeObject":
|
||||||
r.renderCompositeGraphicUnit(ctx, obj.CompositeGraphicUnit, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, boundaryInCTM, parentClip)
|
r.renderCompositeGraphicUnit(ctx, obj.CompositeGraphicUnit, pageH, defaults, parentCTM, boundaryInCTM, parentClip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,26 +176,61 @@ func mergeGraphicObjectAlpha(obj GraphicObject, alpha *int) GraphicObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// drawParamDefaults 合并绘制参数默认样式
|
// drawParamDefaults 合并绘制参数默认样式
|
||||||
// 入参: id 绘制参数ID, defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽
|
// 入参: id 绘制参数ID, defaults 默认绘制参数
|
||||||
// 返回: color.Color 默认填充色, color.Color 默认描边色, float64 默认线宽
|
// 返回: *DrawParam 合并后的绘制参数
|
||||||
func (r *Renderer) drawParamDefaults(id string, defaultFill, defaultStroke color.Color, defaultLW float64) (color.Color, color.Color, float64) {
|
func (r *Renderer) drawParamDefaults(id string, defaults *DrawParam) *DrawParam {
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return defaultFill, defaultStroke, defaultLW
|
return defaults
|
||||||
}
|
}
|
||||||
dp := r.getDrawParam(id, nil)
|
dp := r.getDrawParam(id, nil)
|
||||||
if dp == nil {
|
if dp == nil {
|
||||||
return defaultFill, defaultStroke, defaultLW
|
return defaults
|
||||||
}
|
}
|
||||||
|
if defaults == nil {
|
||||||
|
return dp
|
||||||
|
}
|
||||||
|
return mergeDrawParam(*defaults, dp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeDrawParam 合并绘制参数属性
|
||||||
|
// 入参: base 基础绘制参数, dp 覆盖绘制参数
|
||||||
|
// 返回: *DrawParam 合并后的绘制参数
|
||||||
|
func mergeDrawParam(base DrawParam, dp *DrawParam) *DrawParam {
|
||||||
if dp.LineWidth > 0 {
|
if dp.LineWidth > 0 {
|
||||||
defaultLW = dp.LineWidth
|
base.LineWidth = dp.LineWidth
|
||||||
|
}
|
||||||
|
if dp.Join != "" {
|
||||||
|
base.Join = dp.Join
|
||||||
|
}
|
||||||
|
if dp.Cap != "" {
|
||||||
|
base.Cap = dp.Cap
|
||||||
|
}
|
||||||
|
if dp.DashPattern != "" {
|
||||||
|
base.DashPattern = dp.DashPattern
|
||||||
|
base.DashOffset = dp.DashOffset
|
||||||
|
}
|
||||||
|
if dp.MiterLimit > 0 {
|
||||||
|
base.MiterLimit = dp.MiterLimit
|
||||||
}
|
}
|
||||||
if dp.FillColor != nil {
|
if dp.FillColor != nil {
|
||||||
defaultFill = r.parseFillColor(dp.FillColor)
|
base.FillColor = dp.FillColor
|
||||||
}
|
}
|
||||||
if dp.StrokeColor != nil {
|
if dp.StrokeColor != nil {
|
||||||
defaultStroke = r.parseStrokeColor(dp.StrokeColor)
|
base.StrokeColor = dp.StrokeColor
|
||||||
}
|
}
|
||||||
return defaultFill, defaultStroke, defaultLW
|
if dp.Font != "" {
|
||||||
|
base.Font = dp.Font
|
||||||
|
}
|
||||||
|
if dp.Size > 0 {
|
||||||
|
base.Size = dp.Size
|
||||||
|
}
|
||||||
|
if dp.Weight > 0 {
|
||||||
|
base.Weight = dp.Weight
|
||||||
|
}
|
||||||
|
if dp.Italic {
|
||||||
|
base.Italic = dp.Italic
|
||||||
|
}
|
||||||
|
return &base
|
||||||
}
|
}
|
||||||
|
|
||||||
// getDrawParam 获取绘制参数逻辑
|
// getDrawParam 获取绘制参数逻辑
|
||||||
@@ -219,42 +250,7 @@ func (r *Renderer) getDrawParam(id string, visited map[string]bool) *DrawParam {
|
|||||||
if base == nil {
|
if base == nil {
|
||||||
return dp
|
return dp
|
||||||
}
|
}
|
||||||
merged := *base
|
return mergeDrawParam(*base, dp)
|
||||||
if dp.LineWidth > 0 {
|
|
||||||
merged.LineWidth = dp.LineWidth
|
|
||||||
}
|
|
||||||
if dp.Join != "" {
|
|
||||||
merged.Join = dp.Join
|
|
||||||
}
|
|
||||||
if dp.Cap != "" {
|
|
||||||
merged.Cap = dp.Cap
|
|
||||||
}
|
|
||||||
if dp.DashPattern != "" {
|
|
||||||
merged.DashPattern = dp.DashPattern
|
|
||||||
merged.DashOffset = dp.DashOffset
|
|
||||||
}
|
|
||||||
if dp.MiterLimit > 0 {
|
|
||||||
merged.MiterLimit = dp.MiterLimit
|
|
||||||
}
|
|
||||||
if dp.FillColor != nil {
|
|
||||||
merged.FillColor = dp.FillColor
|
|
||||||
}
|
|
||||||
if dp.StrokeColor != nil {
|
|
||||||
merged.StrokeColor = dp.StrokeColor
|
|
||||||
}
|
|
||||||
if dp.Font != "" {
|
|
||||||
merged.Font = dp.Font
|
|
||||||
}
|
|
||||||
if dp.Size > 0 {
|
|
||||||
merged.Size = dp.Size
|
|
||||||
}
|
|
||||||
if dp.Weight > 0 {
|
|
||||||
merged.Weight = dp.Weight
|
|
||||||
}
|
|
||||||
if dp.Italic {
|
|
||||||
merged.Italic = dp.Italic
|
|
||||||
}
|
|
||||||
return &merged
|
|
||||||
}
|
}
|
||||||
return dp
|
return dp
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-33
@@ -24,6 +24,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const defaultPathLineWidth = 0.353
|
const defaultPathLineWidth = 0.353
|
||||||
|
const defaultMiterLimit = 3.528
|
||||||
|
|
||||||
type pathStyle struct {
|
type pathStyle struct {
|
||||||
fillColor color.Color
|
fillColor color.Color
|
||||||
@@ -35,26 +36,24 @@ type pathStyle struct {
|
|||||||
lineWidth float64
|
lineWidth float64
|
||||||
lineCap canvas.Capper
|
lineCap canvas.Capper
|
||||||
lineJoin canvas.Joiner
|
lineJoin canvas.Joiner
|
||||||
|
miterLimit float64
|
||||||
dashOffset float64
|
dashOffset float64
|
||||||
dashPattern []float64
|
dashPattern []float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// newPathStyle 创建路径样式
|
// newPathStyle 创建路径样式
|
||||||
// 入参: defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽, alpha 对象透明度
|
// 入参: dp 默认绘制参数, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
||||||
// 返回: pathStyle 路径样式
|
// 返回: pathStyle 路径样式
|
||||||
func newPathStyle(defaultFill, defaultStroke color.Color, defaultLW float64, alpha *int) pathStyle {
|
func (r *Renderer) newPathStyle(dp *DrawParam, bx, by, pageH float64, alpha *int) pathStyle {
|
||||||
style := pathStyle{
|
style := pathStyle{
|
||||||
fillColor: colorWithAlpha(defaultFill, alpha),
|
lineWidth: defaultPathLineWidth,
|
||||||
strokeColor: colorWithAlpha(defaultStroke, alpha),
|
|
||||||
lineWidth: defaultLW,
|
|
||||||
lineCap: canvas.ButtCap,
|
lineCap: canvas.ButtCap,
|
||||||
lineJoin: canvas.MiterJoin,
|
lineJoin: canvas.MiterJoiner{GapJoiner: canvas.BevelJoin, Limit: defaultMiterLimit},
|
||||||
|
miterLimit: defaultMiterLimit,
|
||||||
}
|
}
|
||||||
if style.lineWidth == 0 {
|
if dp != nil {
|
||||||
style.lineWidth = defaultPathLineWidth
|
style.applyDrawParam(r, dp, bx, by, pageH, alpha)
|
||||||
}
|
}
|
||||||
style.fillPaint = style.fillColor
|
|
||||||
style.strokePaint = style.strokeColor
|
|
||||||
return style
|
return style
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +61,7 @@ func newPathStyle(defaultFill, defaultStroke color.Color, defaultLW float64, alp
|
|||||||
// 入参: r 渲染器, fill 填充颜色, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
// 入参: r 渲染器, fill 填充颜色, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
||||||
func (s *pathStyle) applyFillColor(r *Renderer, fill *FillColor, bx, by, pageH float64, alpha *int) {
|
func (s *pathStyle) applyFillColor(r *Renderer, fill *FillColor, bx, by, pageH float64, alpha *int) {
|
||||||
fillColorNode := withFillAlpha(fill, alpha)
|
fillColorNode := withFillAlpha(fill, alpha)
|
||||||
s.fillPattern = r.parsePatternPaint(fillColorNode.Pattern, fillColorNode.Value, fillColorNode.Index, fillColorNode.ColorSpace, fillColorNode.Alpha)
|
s.fillPattern = parsePatternPaint(fillColorNode)
|
||||||
s.fillColor = r.parseFillColor(fillColorNode)
|
s.fillColor = r.parseFillColor(fillColorNode)
|
||||||
s.fillPaint = r.parseFillPaint(fillColorNode, bx, by, pageH)
|
s.fillPaint = r.parseFillPaint(fillColorNode, bx, by, pageH)
|
||||||
}
|
}
|
||||||
@@ -71,7 +70,7 @@ func (s *pathStyle) applyFillColor(r *Renderer, fill *FillColor, bx, by, pageH f
|
|||||||
// 入参: r 渲染器, stroke 描边颜色, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
// 入参: r 渲染器, stroke 描边颜色, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
||||||
func (s *pathStyle) applyStrokeColor(r *Renderer, stroke *StrokeColor, bx, by, pageH float64, alpha *int) {
|
func (s *pathStyle) applyStrokeColor(r *Renderer, stroke *StrokeColor, bx, by, pageH float64, alpha *int) {
|
||||||
strokeColorNode := withStrokeAlpha(stroke, alpha)
|
strokeColorNode := withStrokeAlpha(stroke, alpha)
|
||||||
s.strokePattern = r.parsePatternPaint(strokeColorNode.Pattern, strokeColorNode.Value, strokeColorNode.Index, strokeColorNode.ColorSpace, strokeColorNode.Alpha)
|
s.strokePattern = parsePatternPaint((*FillColor)(strokeColorNode))
|
||||||
s.strokeColor = r.parseStrokeColor(strokeColorNode)
|
s.strokeColor = r.parseStrokeColor(strokeColorNode)
|
||||||
s.strokePaint = r.parseStrokePaint(strokeColorNode, bx, by, pageH)
|
s.strokePaint = r.parseStrokePaint(strokeColorNode, bx, by, pageH)
|
||||||
}
|
}
|
||||||
@@ -81,6 +80,8 @@ func (s *pathStyle) applyStrokeColor(r *Renderer, stroke *StrokeColor, bx, by, p
|
|||||||
// 返回: canvas.Capper 线帽样式
|
// 返回: canvas.Capper 线帽样式
|
||||||
func pathLineCap(cap string, fallback canvas.Capper) canvas.Capper {
|
func pathLineCap(cap string, fallback canvas.Capper) canvas.Capper {
|
||||||
switch cap {
|
switch cap {
|
||||||
|
case "Butt":
|
||||||
|
return canvas.ButtCap
|
||||||
case "Round":
|
case "Round":
|
||||||
return canvas.RoundCap
|
return canvas.RoundCap
|
||||||
case "Square":
|
case "Square":
|
||||||
@@ -89,17 +90,23 @@ func pathLineCap(cap string, fallback canvas.Capper) canvas.Capper {
|
|||||||
return fallback
|
return fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
// pathLineJoin 转换线连接样式
|
// applyLineJoin 应用线连接样式及尖角限制
|
||||||
// 入参: join 线连接名称, fallback 默认线连接
|
// 入参: join 线连接名称, limit 尖角限制
|
||||||
// 返回: canvas.Joiner 线连接样式
|
func (s *pathStyle) applyLineJoin(join string, limit float64) {
|
||||||
func pathLineJoin(join string, fallback canvas.Joiner) canvas.Joiner {
|
if limit > 0 {
|
||||||
|
s.miterLimit = limit
|
||||||
|
}
|
||||||
switch join {
|
switch join {
|
||||||
|
case "Miter":
|
||||||
|
s.lineJoin = canvas.MiterJoin
|
||||||
case "Round":
|
case "Round":
|
||||||
return canvas.RoundJoin
|
s.lineJoin = canvas.RoundJoin
|
||||||
case "Bevel":
|
case "Bevel":
|
||||||
return canvas.BevelJoin
|
s.lineJoin = canvas.BevelJoin
|
||||||
|
}
|
||||||
|
if _, ok := s.lineJoin.(canvas.MiterJoiner); ok {
|
||||||
|
s.lineJoin = canvas.MiterJoiner{GapJoiner: canvas.BevelJoin, Limit: s.miterLimit}
|
||||||
}
|
}
|
||||||
return fallback
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyDrawParam 应用绘制参数样式
|
// applyDrawParam 应用绘制参数样式
|
||||||
@@ -117,9 +124,7 @@ func (s *pathStyle) applyDrawParam(r *Renderer, dp *DrawParam, bx, by, pageH flo
|
|||||||
if dp.Cap != "" {
|
if dp.Cap != "" {
|
||||||
s.lineCap = pathLineCap(dp.Cap, s.lineCap)
|
s.lineCap = pathLineCap(dp.Cap, s.lineCap)
|
||||||
}
|
}
|
||||||
if dp.Join != "" {
|
s.applyLineJoin(dp.Join, dp.MiterLimit)
|
||||||
s.lineJoin = pathLineJoin(dp.Join, s.lineJoin)
|
|
||||||
}
|
|
||||||
if dp.DashPattern != "" {
|
if dp.DashPattern != "" {
|
||||||
s.dashPattern = parseFloats(dp.DashPattern)
|
s.dashPattern = parseFloats(dp.DashPattern)
|
||||||
s.dashOffset = dp.DashOffset
|
s.dashOffset = dp.DashOffset
|
||||||
@@ -141,9 +146,7 @@ func (s *pathStyle) applyPathObject(r *Renderer, obj PathObject, bx, by, pageH f
|
|||||||
if obj.Cap != "" {
|
if obj.Cap != "" {
|
||||||
s.lineCap = pathLineCap(obj.Cap, canvas.ButtCap)
|
s.lineCap = pathLineCap(obj.Cap, canvas.ButtCap)
|
||||||
}
|
}
|
||||||
if obj.Join != "" {
|
s.applyLineJoin(obj.Join, obj.MiterLimit)
|
||||||
s.lineJoin = pathLineJoin(obj.Join, canvas.MiterJoin)
|
|
||||||
}
|
|
||||||
if obj.DashPattern != "" {
|
if obj.DashPattern != "" {
|
||||||
s.dashPattern = parseFloats(obj.DashPattern)
|
s.dashPattern = parseFloats(obj.DashPattern)
|
||||||
s.dashOffset = obj.DashOffset
|
s.dashOffset = obj.DashOffset
|
||||||
@@ -163,8 +166,8 @@ func (s *pathStyle) scale(ctm Matrix) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// renderPath 渲染路径
|
// renderPath 渲染路径
|
||||||
// 入参: ctx 画布上下文, obj 路径对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, defaultLW 默认线宽, parentCTM 父级CTM, boundaryInCTM 边界是否参与CTM变换, parentClip 父级裁剪路径
|
// 入参: ctx 画布上下文, obj 路径对象, pageH 页面高度, defaults 默认绘制参数, parentCTM 父级CTM, boundaryInCTM 边界是否参与CTM变换, parentClip 父级裁剪路径
|
||||||
func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) {
|
func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64, defaults *DrawParam, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) {
|
||||||
if obj.Visible != nil && !*obj.Visible {
|
if obj.Visible != nil && !*obj.Visible {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -180,7 +183,7 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
if parentCTM != nil {
|
if parentCTM != nil {
|
||||||
ctm = parentCTM.Multiply(ctm)
|
ctm = parentCTM.Multiply(ctm)
|
||||||
}
|
}
|
||||||
style := newPathStyle(defaultFill, defaultStroke, defaultLW, obj.Alpha)
|
style := r.newPathStyle(defaults, bx, by, pageH, obj.Alpha)
|
||||||
if obj.DrawParam != "" {
|
if obj.DrawParam != "" {
|
||||||
if dp := r.getDrawParam(obj.DrawParam, nil); dp != nil {
|
if dp := r.getDrawParam(obj.DrawParam, nil); dp != nil {
|
||||||
style.applyDrawParam(r, dp, bx, by, pageH, obj.Alpha)
|
style.applyDrawParam(r, dp, bx, by, pageH, obj.Alpha)
|
||||||
@@ -188,10 +191,12 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
}
|
}
|
||||||
style.applyPathObject(r, obj, bx, by, pageH)
|
style.applyPathObject(r, obj, bx, by, pageH)
|
||||||
style.scale(ctm)
|
style.scale(ctm)
|
||||||
patternCTM := TranslationMatrix(bx, by).Multiply(ctm)
|
objectCTM := TranslationMatrix(bx, by).Multiply(ctm)
|
||||||
if boundaryInCTM && parentCTM != nil {
|
if boundaryInCTM && parentCTM != nil {
|
||||||
patternCTM = parentCTM.Multiply(TranslationMatrix(bx, by)).Multiply(localCTM)
|
objectCTM = parentCTM.Multiply(TranslationMatrix(bx, by)).Multiply(localCTM)
|
||||||
}
|
}
|
||||||
|
transformShdPaint(style.fillPaint, parentCTM, bx, by, pageH, boundaryInCTM)
|
||||||
|
transformShdPaint(style.strokePaint, parentCTM, bx, by, pageH, boundaryInCTM)
|
||||||
pathCTM := ctm
|
pathCTM := ctm
|
||||||
if boundaryInCTM {
|
if boundaryInCTM {
|
||||||
pathCTM = localCTM
|
pathCTM = localCTM
|
||||||
@@ -231,7 +236,7 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
fp = applyClipPath(fp, fillClip)
|
fp = applyClipPath(fp, fillClip)
|
||||||
}
|
}
|
||||||
if style.fillPattern != nil {
|
if style.fillPattern != nil {
|
||||||
r.renderPattern(ctx, style.fillPattern, pageH, fp, patternCTM)
|
r.renderPattern(ctx, style.fillPattern, pageH, fp, objectCTM)
|
||||||
} else if style.fillPaint != nil {
|
} else if style.fillPaint != nil {
|
||||||
ctx.SetFillRule(fillRule)
|
ctx.SetFillRule(fillRule)
|
||||||
ctx.SetFill(fillPaint)
|
ctx.SetFill(fillPaint)
|
||||||
@@ -268,7 +273,7 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
sp = sp.Stroke(style.lineWidth, style.lineCap, style.lineJoin, canvas.Tolerance)
|
sp = sp.Stroke(style.lineWidth, style.lineCap, style.lineJoin, canvas.Tolerance)
|
||||||
sp = applyClipPath(sp, strokeClip)
|
sp = applyClipPath(sp, strokeClip)
|
||||||
if style.strokePattern != nil {
|
if style.strokePattern != nil {
|
||||||
r.renderPattern(ctx, style.strokePattern, pageH, sp, patternCTM)
|
r.renderPattern(ctx, style.strokePattern, pageH, sp, objectCTM)
|
||||||
} else {
|
} else {
|
||||||
ctx.SetFill(strokePaint)
|
ctx.SetFill(strokePaint)
|
||||||
ctx.SetStrokeColor(canvas.Transparent)
|
ctx.SetStrokeColor(canvas.Transparent)
|
||||||
@@ -330,6 +335,7 @@ func (r *Renderer) renderPattern(ctx *canvas.Context, pattern *patternPaint, pag
|
|||||||
endX := int(math.Ceil(maxX/xStep)) + 1
|
endX := int(math.Ceil(maxX/xStep)) + 1
|
||||||
startY := int(math.Floor(minY/yStep)) - 1
|
startY := int(math.Floor(minY/yStep)) - 1
|
||||||
endY := int(math.Ceil(maxY/yStep)) + 1
|
endY := int(math.Ceil(maxY/yStep)) + 1
|
||||||
|
defaults := &DrawParam{FillColor: &pattern.color, StrokeColor: (*StrokeColor)(&pattern.color)}
|
||||||
for ix := startX; ix <= endX; ix++ {
|
for ix := startX; ix <= endX; ix++ {
|
||||||
for iy := startY; iy <= endY; iy++ {
|
for iy := startY; iy <= endY; iy++ {
|
||||||
tileCTM := patternCTM.Multiply(TranslationMatrix(float64(ix)*xStep, float64(iy)*yStep))
|
tileCTM := patternCTM.Multiply(TranslationMatrix(float64(ix)*xStep, float64(iy)*yStep))
|
||||||
@@ -341,7 +347,7 @@ func (r *Renderer) renderPattern(ctx *canvas.Context, pattern *patternPaint, pag
|
|||||||
}
|
}
|
||||||
for _, obj := range pattern.CellContent.Objects {
|
for _, obj := range pattern.CellContent.Objects {
|
||||||
obj = mergeGraphicObjectAlpha(obj, pattern.alpha)
|
obj = mergeGraphicObjectAlpha(obj, pattern.alpha)
|
||||||
r.renderObject(ctx, obj, pageH, pattern.color, pattern.color, 0, &tileCTM, true, clip)
|
r.renderObject(ctx, obj, pageH, defaults, &tileCTM, true, clip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-19
@@ -15,7 +15,6 @@
|
|||||||
package ofdgo
|
package ofdgo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image/color"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tdewolff/canvas"
|
"github.com/tdewolff/canvas"
|
||||||
@@ -24,8 +23,8 @@ import (
|
|||||||
const ptPerMM = 72.0 / 25.4
|
const ptPerMM = 72.0 / 25.4
|
||||||
|
|
||||||
// renderText 渲染文本
|
// renderText 渲染文本
|
||||||
// 入参: ctx 画布上下文, obj 文本对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, parentCTM 父级CTM, boundaryInCTM 边界是否参与父级CTM, parentClip 父级裁剪路径
|
// 入参: ctx 画布上下文, obj 文本对象, pageH 页面高度, defaults 默认绘制参数, parentCTM 父级CTM, boundaryInCTM 边界是否参与父级CTM, parentClip 父级裁剪路径
|
||||||
func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64, defaultFill, defaultStroke color.Color, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) {
|
func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64, defaults *DrawParam, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) {
|
||||||
if obj.Visible != nil && !*obj.Visible {
|
if obj.Visible != nil && !*obj.Visible {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -46,6 +45,10 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
if parentCTM != nil {
|
if parentCTM != nil {
|
||||||
ctm = parentCTM.Multiply(ctm)
|
ctm = parentCTM.Multiply(ctm)
|
||||||
}
|
}
|
||||||
|
objectCTM := TranslationMatrix(bx, by).Multiply(ctm)
|
||||||
|
if boundaryInCTM && parentCTM != nil {
|
||||||
|
objectCTM = parentCTM.Multiply(TranslationMatrix(bx, by)).Multiply(localCTM)
|
||||||
|
}
|
||||||
clipPath := intersectClipPath(parentClip, r.buildObjectClipPath(obj.Clips, pageH, bx, by, localCTM, parentCTM, boundaryInCTM))
|
clipPath := intersectClipPath(parentClip, r.buildObjectClipPath(obj.Clips, pageH, bx, by, localCTM, parentCTM, boundaryInCTM))
|
||||||
var dp *DrawParam
|
var dp *DrawParam
|
||||||
if obj.DrawParam != "" {
|
if obj.DrawParam != "" {
|
||||||
@@ -71,13 +74,13 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
sizeMM *= scale
|
sizeMM *= scale
|
||||||
}
|
}
|
||||||
sizePt := sizeMM * ptPerMM
|
sizePt := sizeMM * ptPerMM
|
||||||
fillColor := colorWithAlpha(defaultFill, obj.Alpha)
|
fillColor := colorWithAlpha(canvas.Black, obj.Alpha)
|
||||||
if fillColor == nil {
|
|
||||||
fillColor = colorWithAlpha(canvas.Black, obj.Alpha)
|
|
||||||
}
|
|
||||||
var fillPaint any = fillColor
|
var fillPaint any = fillColor
|
||||||
var fillPattern *patternPaint
|
var fillPattern *patternPaint
|
||||||
var fillColorNode *FillColor
|
var fillColorNode *FillColor
|
||||||
|
if defaults != nil {
|
||||||
|
fillColorNode = defaults.FillColor
|
||||||
|
}
|
||||||
if dp != nil && dp.FillColor != nil {
|
if dp != nil && dp.FillColor != nil {
|
||||||
fillColorNode = dp.FillColor
|
fillColorNode = dp.FillColor
|
||||||
}
|
}
|
||||||
@@ -88,17 +91,19 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
fillColorNode = withFillAlpha(fillColorNode, obj.Alpha)
|
fillColorNode = withFillAlpha(fillColorNode, obj.Alpha)
|
||||||
fillColor = r.parseFillColor(fillColorNode)
|
fillColor = r.parseFillColor(fillColorNode)
|
||||||
fillPaint = r.parseFillPaint(fillColorNode, bx, by, pageH)
|
fillPaint = r.parseFillPaint(fillColorNode, bx, by, pageH)
|
||||||
fillPattern = r.parsePatternPaint(fillColorNode.Pattern, fillColorNode.Value, fillColorNode.Index, fillColorNode.ColorSpace, fillColorNode.Alpha)
|
fillPattern = parsePatternPaint(fillColorNode)
|
||||||
}
|
}
|
||||||
if fillPaint == nil {
|
if fillPaint == nil {
|
||||||
fillPaint = fillColor
|
fillPaint = fillColor
|
||||||
}
|
}
|
||||||
|
transformShdPaint(fillPaint, parentCTM, bx, by, pageH, boundaryInCTM)
|
||||||
fillPaint, shadingClip, fillView := resolveShdPaint(ctx, fillPaint)
|
fillPaint, shadingClip, fillView := resolveShdPaint(ctx, fillPaint)
|
||||||
fillClip := intersectClipPath(clipPath, shadingClip)
|
fillClip := intersectClipPath(clipPath, shadingClip)
|
||||||
strokeStyle := newPathStyle(nil, defaultStroke, 0, obj.Alpha)
|
var strokeStyle pathStyle
|
||||||
strokeClip := clipPath
|
strokeClip := clipPath
|
||||||
strokeView := canvas.Identity
|
strokeView := canvas.Identity
|
||||||
if shouldStroke {
|
if shouldStroke {
|
||||||
|
strokeStyle = r.newPathStyle(defaults, bx, by, pageH, obj.Alpha)
|
||||||
if dp != nil {
|
if dp != nil {
|
||||||
strokeStyle.applyDrawParam(r, dp, bx, by, pageH, obj.Alpha)
|
strokeStyle.applyDrawParam(r, dp, bx, by, pageH, obj.Alpha)
|
||||||
}
|
}
|
||||||
@@ -108,17 +113,15 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
if obj.LineWidth > 0 {
|
if obj.LineWidth > 0 {
|
||||||
strokeStyle.lineWidth = obj.LineWidth
|
strokeStyle.lineWidth = obj.LineWidth
|
||||||
}
|
}
|
||||||
|
strokeStyle.applyLineJoin(obj.Join, obj.MiterLimit)
|
||||||
if strokeStyle.strokePaint == nil {
|
if strokeStyle.strokePaint == nil {
|
||||||
strokeStyle.strokePaint = colorWithAlpha(canvas.Black, obj.Alpha)
|
strokeStyle.strokePaint = colorWithAlpha(canvas.Black, obj.Alpha)
|
||||||
}
|
}
|
||||||
strokeStyle.scale(ctm)
|
strokeStyle.scale(ctm)
|
||||||
|
transformShdPaint(strokeStyle.strokePaint, parentCTM, bx, by, pageH, boundaryInCTM)
|
||||||
strokeStyle.strokePaint, shadingClip, strokeView = resolveShdPaint(ctx, strokeStyle.strokePaint)
|
strokeStyle.strokePaint, shadingClip, strokeView = resolveShdPaint(ctx, strokeStyle.strokePaint)
|
||||||
strokeClip = intersectClipPath(strokeClip, shadingClip)
|
strokeClip = intersectClipPath(strokeClip, shadingClip)
|
||||||
}
|
}
|
||||||
patternCTM := TranslationMatrix(bx, by).Multiply(ctm)
|
|
||||||
if boundaryInCTM && parentCTM != nil {
|
|
||||||
patternCTM = parentCTM.Multiply(TranslationMatrix(bx, by)).Multiply(localCTM)
|
|
||||||
}
|
|
||||||
fontStyle := canvas.FontRegular
|
fontStyle := canvas.FontRegular
|
||||||
weight := obj.Weight
|
weight := obj.Weight
|
||||||
if weight == 0 && dp != nil && dp.Weight > 0 {
|
if weight == 0 && dp != nil && dp.Weight > 0 {
|
||||||
@@ -247,7 +250,7 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
}
|
}
|
||||||
path := glyphPath.Copy().Transform(transform.Scale(scaleX, 1))
|
path := glyphPath.Copy().Transform(transform.Scale(scaleX, 1))
|
||||||
if shouldFill && fillPattern != nil {
|
if shouldFill && fillPattern != nil {
|
||||||
r.renderPattern(ctx, fillPattern, pageH, applyClipPath(path.Copy(), fillClip), patternCTM)
|
r.renderPattern(ctx, fillPattern, pageH, applyClipPath(path.Copy(), fillClip), objectCTM)
|
||||||
} else if shouldFill && fillPaint != nil {
|
} else if shouldFill && fillPaint != nil {
|
||||||
ctx.SetFill(fillPaint)
|
ctx.SetFill(fillPaint)
|
||||||
ctx.SetStrokeColor(canvas.Transparent)
|
ctx.SetStrokeColor(canvas.Transparent)
|
||||||
@@ -259,7 +262,7 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
path = path.Stroke(strokeStyle.lineWidth, strokeStyle.lineCap, strokeStyle.lineJoin, canvas.Tolerance)
|
path = path.Stroke(strokeStyle.lineWidth, strokeStyle.lineCap, strokeStyle.lineJoin, canvas.Tolerance)
|
||||||
path = applyClipPath(path, strokeClip)
|
path = applyClipPath(path, strokeClip)
|
||||||
if strokeStyle.strokePattern != nil {
|
if strokeStyle.strokePattern != nil {
|
||||||
r.renderPattern(ctx, strokeStyle.strokePattern, pageH, path, patternCTM)
|
r.renderPattern(ctx, strokeStyle.strokePattern, pageH, path, objectCTM)
|
||||||
} else {
|
} else {
|
||||||
ctx.SetFill(strokeStyle.strokePaint)
|
ctx.SetFill(strokeStyle.strokePaint)
|
||||||
ctx.SetStrokeColor(canvas.Transparent)
|
ctx.SetStrokeColor(canvas.Transparent)
|
||||||
@@ -271,12 +274,12 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
underline.LineTo(glyphWidth*scaleX, -sizeMM*0.1)
|
underline.LineTo(glyphWidth*scaleX, -sizeMM*0.1)
|
||||||
underline = underline.Stroke(sizeMM*0.05, canvas.ButtCap, canvas.MiterJoin, canvas.Tolerance)
|
underline = underline.Stroke(sizeMM*0.05, canvas.ButtCap, canvas.MiterJoin, canvas.Tolerance)
|
||||||
if shouldFill && fillPattern != nil {
|
if shouldFill && fillPattern != nil {
|
||||||
r.renderPattern(ctx, fillPattern, pageH, applyClipPath(underline.Transform(transform), clipPath), patternCTM)
|
r.renderPattern(ctx, fillPattern, pageH, applyClipPath(underline.Transform(transform), clipPath), objectCTM)
|
||||||
} else if shouldFill {
|
} else if shouldFill {
|
||||||
ctx.SetFillColor(fillColor)
|
ctx.SetFillColor(fillColor)
|
||||||
ctx.DrawPath(0, 0, applyClipPath(underline.Transform(transform), clipPath))
|
ctx.DrawPath(0, 0, applyClipPath(underline.Transform(transform), clipPath))
|
||||||
} else if strokeStyle.strokePattern != nil {
|
} else if strokeStyle.strokePattern != nil {
|
||||||
r.renderPattern(ctx, strokeStyle.strokePattern, pageH, applyClipPath(underline.Transform(transform), strokeClip), patternCTM)
|
r.renderPattern(ctx, strokeStyle.strokePattern, pageH, applyClipPath(underline.Transform(transform), strokeClip), objectCTM)
|
||||||
} else {
|
} else {
|
||||||
drawShdPath(ctx, applyClipPath(underline.Transform(transform), strokeClip), strokeView)
|
drawShdPath(ctx, applyClipPath(underline.Transform(transform), strokeClip), strokeView)
|
||||||
}
|
}
|
||||||
@@ -297,7 +300,7 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
}
|
}
|
||||||
glyphPath = applyClipPath(glyphPath.Copy().Transform(textTransform.Scale(scaleX, 1)), fillClip)
|
glyphPath = applyClipPath(glyphPath.Copy().Transform(textTransform.Scale(scaleX, 1)), fillClip)
|
||||||
if fillPattern != nil {
|
if fillPattern != nil {
|
||||||
r.renderPattern(ctx, fillPattern, pageH, glyphPath, patternCTM)
|
r.renderPattern(ctx, fillPattern, pageH, glyphPath, objectCTM)
|
||||||
} else {
|
} else {
|
||||||
drawShdPath(ctx, glyphPath, fillView)
|
drawShdPath(ctx, glyphPath, fillView)
|
||||||
}
|
}
|
||||||
@@ -310,7 +313,7 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
underline = underline.Stroke(uw, canvas.ButtCap, canvas.MiterJoin, canvas.Tolerance)
|
underline = underline.Stroke(uw, canvas.ButtCap, canvas.MiterJoin, canvas.Tolerance)
|
||||||
underline = applyClipPath(underline.Transform(textTransform), clipPath)
|
underline = applyClipPath(underline.Transform(textTransform), clipPath)
|
||||||
if fillPattern != nil {
|
if fillPattern != nil {
|
||||||
r.renderPattern(ctx, fillPattern, pageH, underline, patternCTM)
|
r.renderPattern(ctx, fillPattern, pageH, underline, objectCTM)
|
||||||
} else {
|
} else {
|
||||||
ctx.SetFillColor(fillColor)
|
ctx.SetFillColor(fillColor)
|
||||||
ctx.SetStrokeColor(canvas.Transparent)
|
ctx.SetStrokeColor(canvas.Transparent)
|
||||||
|
|||||||
+26
-2
@@ -56,15 +56,22 @@ func resolveShdPaint(ctx *canvas.Context, paint any) (any, *canvas.Path, canvas.
|
|||||||
if !ok {
|
if !ok {
|
||||||
return paint, nil, canvas.Identity
|
return paint, nil, canvas.Identity
|
||||||
}
|
}
|
||||||
|
if canvas.Equal(s.view.Det(), 0) {
|
||||||
|
return nil, &canvas.Path{}, canvas.Identity
|
||||||
|
}
|
||||||
switch g := s.gradient.(type) {
|
switch g := s.gradient.(type) {
|
||||||
case *canvas.LinearGradient:
|
case *canvas.LinearGradient:
|
||||||
clip := axialShdClip(ctx, g, s.extend)
|
bounds := shdCanvasBounds(ctx).Transform(s.view.Inv())
|
||||||
|
clip := axialShdClip(g, s.extend, bounds)
|
||||||
|
if clip != nil && s.view != canvas.Identity {
|
||||||
|
clip = clip.Transform(s.view)
|
||||||
|
}
|
||||||
if s.mapType != "Reflect" {
|
if s.mapType != "Reflect" {
|
||||||
return g, clip, s.view
|
return g, clip, s.view
|
||||||
}
|
}
|
||||||
d := g.End.Sub(g.Start)
|
d := g.End.Sub(g.Start)
|
||||||
axis := canvas.Matrix{{d.X, -d.Y, g.Start.X}, {d.Y, d.X, g.Start.Y}}
|
axis := canvas.Matrix{{d.X, -d.Y, g.Start.X}, {d.Y, d.X, g.Start.Y}}
|
||||||
area := shdCanvasBounds(ctx).Transform(axis.Inv())
|
area := bounds.Transform(axis.Inv())
|
||||||
lo, hi := s.rangeLimits(area.X0, area.X1)
|
lo, hi := s.rangeLimits(area.X0, area.X1)
|
||||||
if hi <= lo {
|
if hi <= lo {
|
||||||
return g, &canvas.Path{}, s.view
|
return g, &canvas.Path{}, s.view
|
||||||
@@ -108,6 +115,23 @@ func resolveShdPaint(ctx *canvas.Context, paint any) (any, *canvas.Path, canvas.
|
|||||||
return s.gradient, nil, s.view
|
return s.gradient, nil, s.view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// transformShdPaint 应用渐变的父级坐标变换
|
||||||
|
// 入参: paint 画刷, parentCTM 父级变换矩阵, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, boundaryInCTM 边界是否参与父级变换
|
||||||
|
func transformShdPaint(paint any, parentCTM *Matrix, bx, by, pageH float64, boundaryInCTM bool) {
|
||||||
|
s, ok := paint.(*shdPaint)
|
||||||
|
if !ok || parentCTM == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctm := *parentCTM
|
||||||
|
if !boundaryInCTM {
|
||||||
|
ctm = TranslationMatrix(bx, by).Multiply(ctm).Multiply(TranslationMatrix(-bx, -by))
|
||||||
|
}
|
||||||
|
s.view = canvas.Matrix{
|
||||||
|
{ctm.a, -ctm.c, ctm.c*pageH + ctm.e},
|
||||||
|
{-ctm.b, ctm.d, pageH*(1-ctm.d) - ctm.f},
|
||||||
|
}.Mul(s.view)
|
||||||
|
}
|
||||||
|
|
||||||
// drawShdPath 绘制渐变路径并保持图形轮廓不变
|
// drawShdPath 绘制渐变路径并保持图形轮廓不变
|
||||||
// 入参: ctx 画布上下文, path 填充路径, view 渐变变换
|
// 入参: ctx 画布上下文, path 填充路径, view 渐变变换
|
||||||
func drawShdPath(ctx *canvas.Context, path *canvas.Path, view canvas.Matrix) {
|
func drawShdPath(ctx *canvas.Context, path *canvas.Path, view canvas.Matrix) {
|
||||||
|
|||||||
Reference in new issue
Block a user