mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-30 01:27:26 +08:00
This commit is contained in:
1 parent
537b5779e1
commit
bed08b2c4b
2 files changed
+75
-3
No files matched your search
+10
-3
@@ -223,6 +223,14 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
fillPaint, shadingClip, fillView := resolveShdPaint(ctx, style.fillPaint)
|
fillPaint, shadingClip, fillView := resolveShdPaint(ctx, style.fillPaint)
|
||||||
fillClip := intersectClipPath(clipPath, shadingClip)
|
fillClip := intersectClipPath(clipPath, shadingClip)
|
||||||
fp := p
|
fp := p
|
||||||
|
_, repeat := fillPaint.(*repeatAxialGradient)
|
||||||
|
if fillClip != nil || repeat {
|
||||||
|
paths := canvas.Paths(p.Copy().Split())
|
||||||
|
for _, path := range paths {
|
||||||
|
path.Close()
|
||||||
|
}
|
||||||
|
fp = paths.Merge()
|
||||||
|
}
|
||||||
fillRule := canvas.NonZero
|
fillRule := canvas.NonZero
|
||||||
if obj.Rule == "Even-Odd" {
|
if obj.Rule == "Even-Odd" {
|
||||||
fillRule = canvas.EvenOdd
|
fillRule = canvas.EvenOdd
|
||||||
@@ -231,8 +239,6 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fillClip != nil {
|
if fillClip != nil {
|
||||||
fp = fp.Copy()
|
|
||||||
fp.Close()
|
|
||||||
fp = applyClipPath(fp, fillClip)
|
fp = applyClipPath(fp, fillClip)
|
||||||
}
|
}
|
||||||
if style.fillPattern != nil {
|
if style.fillPattern != nil {
|
||||||
@@ -268,7 +274,8 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
ctx.SetDashes(0)
|
ctx.SetDashes(0)
|
||||||
}
|
}
|
||||||
strokeClip := intersectClipPath(clipPath, shadingClip)
|
strokeClip := intersectClipPath(clipPath, shadingClip)
|
||||||
if strokeClip != nil || strokeView != canvas.Identity || style.strokePattern != nil {
|
_, repeat := strokePaint.(*repeatAxialGradient)
|
||||||
|
if strokeClip != nil || strokeView != canvas.Identity || repeat || style.strokePattern != nil {
|
||||||
sp = sp.Copy()
|
sp = sp.Copy()
|
||||||
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)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package ofdgo
|
package ofdgo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@@ -29,6 +30,28 @@ type shdPaint struct {
|
|||||||
period float64
|
period float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// repeatAxialGradient 轴向重复渐变
|
||||||
|
type repeatAxialGradient struct {
|
||||||
|
*canvas.LinearGradient
|
||||||
|
period float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// At 获取重复区间内的渐变颜色
|
||||||
|
// 入参: x X坐标, y Y坐标
|
||||||
|
// 返回: color.RGBA 渐变颜色
|
||||||
|
func (g *repeatAxialGradient) At(x, y float64) color.RGBA {
|
||||||
|
d := g.End.Sub(g.Start)
|
||||||
|
t := (canvas.Point{X: x, Y: y}).Sub(g.Start).Dot(d) / d.Dot(d) / g.period
|
||||||
|
return g.Grad.At(t - math.Floor(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetColorSpace 转换重复渐变颜色空间
|
||||||
|
// 入参: space 颜色空间
|
||||||
|
// 返回: canvas.Gradient 渐变对象
|
||||||
|
func (g *repeatAxialGradient) SetColorSpace(space canvas.ColorSpace) canvas.Gradient {
|
||||||
|
return &repeatAxialGradient{LinearGradient: g.LinearGradient.SetColorSpace(space).(*canvas.LinearGradient), period: g.period}
|
||||||
|
}
|
||||||
|
|
||||||
// newShdPaint 创建渐变画刷
|
// newShdPaint 创建渐变画刷
|
||||||
// 入参: gradient 渐变对象, extend 延伸方向, mapType 绘制方式, mapUnit 渐变区间长度
|
// 入参: gradient 渐变对象, extend 延伸方向, mapType 绘制方式, mapUnit 渐变区间长度
|
||||||
// 返回: *shdPaint 渐变画刷
|
// 返回: *shdPaint 渐变画刷
|
||||||
@@ -66,6 +89,9 @@ func resolveShdPaint(ctx *canvas.Context, paint any) (any, *canvas.Path, canvas.
|
|||||||
if clip != nil && s.view != canvas.Identity {
|
if clip != nil && s.view != canvas.Identity {
|
||||||
clip = clip.Transform(s.view)
|
clip = clip.Transform(s.view)
|
||||||
}
|
}
|
||||||
|
if s.mapType == "Repeat" {
|
||||||
|
return &repeatAxialGradient{LinearGradient: g, period: s.period}, clip, s.view
|
||||||
|
}
|
||||||
if s.mapType != "Reflect" {
|
if s.mapType != "Reflect" {
|
||||||
return g, clip, s.view
|
return g, clip, s.view
|
||||||
}
|
}
|
||||||
@@ -135,6 +161,10 @@ func transformShdPaint(paint any, parentCTM *Matrix, bx, by, pageH float64, boun
|
|||||||
// 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) {
|
||||||
|
if gradient, ok := ctx.Style.Fill.Gradient.(*repeatAxialGradient); ok {
|
||||||
|
drawRepeatAxialPath(ctx, path, gradient, view)
|
||||||
|
return
|
||||||
|
}
|
||||||
if view == canvas.Identity {
|
if view == canvas.Identity {
|
||||||
ctx.DrawPath(0, 0, path)
|
ctx.DrawPath(0, 0, path)
|
||||||
return
|
return
|
||||||
@@ -144,6 +174,41 @@ func drawShdPath(ctx *canvas.Context, path *canvas.Path, view canvas.Matrix) {
|
|||||||
ctx.RenderPath(path.Copy().Transform(view.Inv()), ctx.Style, m)
|
ctx.RenderPath(path.Copy().Transform(view.Inv()), ctx.Style, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drawRepeatAxialPath 按周期裁剪并绘制轴向重复渐变
|
||||||
|
// 入参: ctx 画布上下文, path 填充路径, gradient 重复渐变, view 渐变变换
|
||||||
|
func drawRepeatAxialPath(ctx *canvas.Context, path *canvas.Path, gradient *repeatAxialGradient, view canvas.Matrix) {
|
||||||
|
p := path.Copy()
|
||||||
|
if ctx.FillRule == canvas.EvenOdd {
|
||||||
|
p = p.Settle(canvas.EvenOdd)
|
||||||
|
}
|
||||||
|
p = p.Transform(view.Inv())
|
||||||
|
d := gradient.End.Sub(gradient.Start).Mul(gradient.period)
|
||||||
|
axis := canvas.Matrix{{d.X, -d.Y, gradient.Start.X}, {d.Y, d.X, gradient.Start.Y}}
|
||||||
|
bounds := p.FastBounds().And(shdCanvasBounds(ctx).Transform(view.Inv()))
|
||||||
|
area := bounds.Transform(axis.Inv())
|
||||||
|
origin := ctx.CoordView().Dot(canvas.Point{})
|
||||||
|
m := ctx.CoordSystemView().Mul(ctx.View()).Translate(origin.X, origin.Y).Mul(view)
|
||||||
|
style := ctx.Style
|
||||||
|
style.FillRule = canvas.NonZero
|
||||||
|
stops := gradient.Grad
|
||||||
|
if stops[0].Offset > 0 {
|
||||||
|
stops = append(canvas.Grad{{Offset: 0, Color: stops[0].Color}}, stops...)
|
||||||
|
}
|
||||||
|
if last := stops[len(stops)-1]; last.Offset < 1 {
|
||||||
|
stops = append(append(canvas.Grad(nil), stops...), canvas.Stop{Offset: 1, Color: last.Color})
|
||||||
|
}
|
||||||
|
for i, end := math.Floor(area.X0), math.Ceil(area.X1); i < end; i++ {
|
||||||
|
clip := (canvas.Rect{X0: i, Y0: area.Y0, X1: i + 1, Y1: area.Y1}).ToPath().Transform(axis)
|
||||||
|
part := applyClipPath(p, clip)
|
||||||
|
if part.Empty() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
start := gradient.Start.Add(d.Mul(i))
|
||||||
|
style.Fill = canvas.Paint{Gradient: stops.ToLinear(start, start.Add(d))}
|
||||||
|
ctx.RenderPath(part, style, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// rangeLimits 限制渐变延伸区间
|
// rangeLimits 限制渐变延伸区间
|
||||||
// 入参: lo 区间起点, hi 区间终点
|
// 入参: lo 区间起点, hi 区间终点
|
||||||
// 返回: float64 起点, float64 终点
|
// 返回: float64 起点, float64 终点
|
||||||
|
|||||||
Reference in new issue
Block a user