Skip to content

Commit

Permalink
HTMLCanvas: support linear and radial gradients, fixes #321
Browse files Browse the repository at this point in the history
  • Loading branch information
tdewolff committed Jan 20, 2025
1 parent d516b92 commit 3165c39
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 12 deletions.
4 changes: 2 additions & 2 deletions canvas.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ type Paint struct {
func (paint Paint) Equal(other Paint) bool {
if paint.IsColor() && other.IsColor() && paint.Color == other.Color {
return true
} else if paint.IsGradient() && other.IsGradient() && reflect.DeepEqual(paint, other) {
} else if paint.IsGradient() && other.IsGradient() && reflect.DeepEqual(paint.Gradient, other.Gradient) {
return true
} else if paint.IsPattern() && other.IsPattern() && reflect.DeepEqual(paint, other) {
} else if paint.IsPattern() && other.IsPattern() && reflect.DeepEqual(paint.Pattern, other.Pattern) {
return true
}
return false
Expand Down
Binary file modified examples/html-canvas/lib.wasm
Binary file not shown.
41 changes: 31 additions & 10 deletions renderers/htmlcanvas/htmlcanvas.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,27 @@ func (r *HTMLCanvas) writePath(path *canvas.Path) {
}
}

func (r *HTMLCanvas) toStyle(paint canvas.Paint) any {
if paint.IsPattern() {
// TODO
} else if paint.IsGradient() {
if g, ok := paint.Gradient.(*canvas.LinearGradient); ok {
grad := r.ctx.Call("createLinearGradient", g.Start.X*r.dpm, r.height-g.Start.Y*r.dpm, g.End.X*r.dpm, r.height-g.End.Y*r.dpm)
for _, stop := range g.Stops {
grad.Call("addColorStop", stop.Offset, canvas.CSSColor(stop.Color).String())
}
return grad
} else if g, ok := paint.Gradient.(*canvas.RadialGradient); ok {
grad := r.ctx.Call("createRadialGradient", g.C0.X*r.dpm, r.height-g.C0.Y*r.dpm, g.R0*r.dpm, g.C1.X*r.dpm, r.height-g.C1.Y*r.dpm, g.R1*r.dpm)
for _, stop := range g.Stops {
grad.Call("addColorStop", stop.Offset, canvas.CSSColor(stop.Color).String())
}
return grad
}
}
return canvas.CSSColor(paint.Color).String()
}

// RenderPath renders a path to the canvas using a style and a transformation matrix.
func (r *HTMLCanvas) RenderPath(path *canvas.Path, style canvas.Style, m canvas.Matrix) {
if path.Empty() {
Expand All @@ -86,9 +107,9 @@ func (r *HTMLCanvas) RenderPath(path *canvas.Path, style canvas.Style, m canvas.
}

if style.HasFill() {
if style.Fill.IsColor() && style.Fill.Color != r.style.Fill.Color {
r.ctx.Set("fillStyle", canvas.CSSColor(style.Fill.Color).String())
r.style.Fill.Color = style.Fill.Color
if !style.Fill.Equal(r.style.Fill) {
r.ctx.Set("fillStyle", r.toStyle(style.Fill))
r.style.Fill = style.Fill
}
r.ctx.Call("fill")
}
Expand Down Expand Up @@ -149,10 +170,10 @@ func (r *HTMLCanvas) RenderPath(path *canvas.Path, style canvas.Style, m canvas.
r.ctx.Set("lineWidth", style.StrokeWidth*r.dpm)
r.style.StrokeWidth = style.StrokeWidth
}
if style.Stroke.IsColor() && style.Stroke.Color != r.style.Stroke.Color {
r.ctx.Set("strokeStyle", canvas.CSSColor(style.Stroke.Color).String())
r.style.Stroke.Color = style.Stroke.Color
}
//if !style.Stroke.Equal(r.style.Stroke) {
r.ctx.Set("strokeStyle", r.toStyle(style.Stroke))
r.style.Stroke = style.Stroke
//}
r.ctx.Call("stroke")
} else if style.HasStroke() {
// stroke settings unsupported by HTML Canvas, draw stroke explicitly
Expand All @@ -161,9 +182,9 @@ func (r *HTMLCanvas) RenderPath(path *canvas.Path, style canvas.Style, m canvas.
}
path = path.Stroke(style.StrokeWidth, style.StrokeCapper, style.StrokeJoiner, canvas.Tolerance)
r.writePath(path.Transform(m).ReplaceArcs())
if style.Stroke.IsColor() && style.Stroke.Color != r.style.Fill.Color {
r.ctx.Set("fillStyle", canvas.CSSColor(style.Stroke.Color).String())
r.style.Fill.Color = style.Stroke.Color
if !style.Stroke.Equal(r.style.Fill) {
r.ctx.Set("fillStyle", r.toStyle(style.Stroke))
r.style.Fill = style.Stroke
}
r.ctx.Call("fill")
}
Expand Down

0 comments on commit 3165c39

Please sign in to comment.