diff --git a/backend/softwarebackend/fill.go b/backend/softwarebackend/fill.go index a9398d7..2800db7 100644 --- a/backend/softwarebackend/fill.go +++ b/backend/softwarebackend/fill.go @@ -58,6 +58,38 @@ func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) { col := rg.data.ColorAt(o) b.Image.SetRGBA(x, y, mix(col, b.Image.RGBAAt(x, y))) }) + } else if ip := style.ImagePattern; ip != nil { + ip := ip.(*ImagePattern) + img := ip.data.Image.(*Image) + mip := img.mips[0] // todo select the right mip size + w, h := img.Size() + fw, fh := float64(w), float64(h) + rx := ip.data.Repeat == backendbase.Repeat || ip.data.Repeat == backendbase.RepeatX + ry := ip.data.Repeat == backendbase.Repeat || ip.data.Repeat == backendbase.RepeatY + b.fillTriangles(pts, func(x, y int) { + pos := [2]float64{float64(x), float64(y)} + tfptx := pos[0]*ip.data.Transform[0] + pos[1]*ip.data.Transform[1] + ip.data.Transform[2] + tfpty := pos[0]*ip.data.Transform[3] + pos[1]*ip.data.Transform[4] + ip.data.Transform[5] + + if !rx && (tfptx < 0 || tfptx >= fw) { + return + } + if !ry && (tfpty < 0 || tfpty >= fh) { + return + } + + mx := int(math.Floor(tfptx)) % w + if mx < 0 { + mx += w + } + my := int(math.Floor(tfpty)) % h + if my < 0 { + my += h + } + + col := mip.At(mx, my) + b.Image.SetRGBA(x, y, mix(col, b.Image.RGBAAt(x, y))) + }) } else { b.fillTriangles(pts, func(x, y int) { b.Image.SetRGBA(x, y, mix(style.Color, b.Image.RGBAAt(x, y))) diff --git a/canvas_test.go b/canvas_test.go index 7714682..6725470 100644 --- a/canvas_test.go +++ b/canvas_test.go @@ -585,6 +585,20 @@ func TestImagePattern(t *testing.T) { }) } +func TestImagePattern2(t *testing.T) { + run(t, func(cv *canvas.Canvas) { + ptrn := cv.CreatePattern("testdata/cat.jpg", canvas.NoRepeat) + ptrn.SetTransform([6]float64{0, 0.1, 0.1, 0, 0, 0}) + + cv.Translate(50, 50) + cv.Scale(0.95, 1.05) + cv.Rotate(-math.Pi * 0.1) + + cv.SetFillStyle(ptrn) + cv.FillRect(-40, -40, 80, 80) + }) +} + func TestShadow(t *testing.T) { run(t, func(cv *canvas.Canvas) { cv.SetFillStyle("#800") diff --git a/testdata/ImagePattern2.png b/testdata/ImagePattern2.png new file mode 100755 index 0000000..3f766a1 Binary files /dev/null and b/testdata/ImagePattern2.png differ