clipping with the rect function now uses scissor test instead of stencil

This commit is contained in:
Thomas Friedel 2018-04-04 16:54:50 +02:00
parent d5a4c0b4bb
commit 8502818b6f
3 changed files with 60 additions and 2 deletions

View file

@ -38,6 +38,7 @@ type drawState struct {
lineDashPoint int lineDashPoint int
lineDashOffset float64 lineDashOffset float64
scissor scissor
clip []pathPoint clip []pathPoint
/* /*
The current transformation matrix. The current transformation matrix.
@ -57,6 +58,11 @@ type drawStyle struct {
image *Image image *Image
} }
type scissor struct {
on bool
tl, br vec
}
type lineJoin uint8 type lineJoin uint8
type lineEnd uint8 type lineEnd uint8
@ -261,6 +267,8 @@ func LoadGL(glimpl GL) (err error) {
gli.StencilOp(gl_KEEP, gl_KEEP, gl_KEEP) gli.StencilOp(gl_KEEP, gl_KEEP, gl_KEEP)
gli.StencilFunc(gl_EQUAL, 0, 0xFF) gli.StencilFunc(gl_EQUAL, 0, 0xFF)
gli.Enable(gl_SCISSOR_TEST)
return return
} }
@ -504,6 +512,7 @@ func (cv *Canvas) Restore() {
} }
cv.state = cv.stateStack[l-1] cv.state = cv.stateStack[l-1]
cv.stateStack = cv.stateStack[:l-1] cv.stateStack = cv.stateStack[:l-1]
cv.applyScissor()
} }
// Scale updates the current transformation with a scaling by the given values // Scale updates the current transformation with a scaling by the given values

View file

@ -826,6 +826,7 @@ type GL interface {
GetUniformLocation(program uint32, name *uint8) int32 GetUniformLocation(program uint32, name *uint8) int32
LinkProgram(program uint32) LinkProgram(program uint32)
ReadPixels(x int32, y int32, width int32, height int32, format uint32, xtype uint32, pixels unsafe.Pointer) ReadPixels(x int32, y int32, width int32, height int32, format uint32, xtype uint32, pixels unsafe.Pointer)
Scissor(x int32, y int32, width int32, height int32)
ShaderSource(shader uint32, count int32, xstring **uint8, length *int32) ShaderSource(shader uint32, count int32, xstring **uint8, length *int32)
StencilFunc(xfunc uint32, ref int32, mask uint32) StencilFunc(xfunc uint32, ref int32, mask uint32)
StencilMask(mask uint32) StencilMask(mask uint32)

View file

@ -17,6 +17,7 @@ type pathPointFlag uint8
const ( const (
pathMove pathPointFlag = 1 << iota pathMove pathPointFlag = 1 << iota
pathAttach pathAttach
pathIsRect
) )
func (cv *Canvas) BeginPath() { func (cv *Canvas) BeginPath() {
@ -497,10 +498,26 @@ func (cv *Canvas) Clip() {
return return
} }
cv.clip(cv.polyPath) path := cv.polyPath
for i := len(path) - 1; i >= 0; i-- {
if path[i].flags&pathMove != 0 {
path = path[i:]
break
}
}
cv.clip(path)
} }
func (cv *Canvas) clip(path []pathPoint) { func (cv *Canvas) clip(path []pathPoint) {
if len(path) < 3 {
return
}
if path[len(path)-1].flags&pathIsRect != 0 {
cv.scissor(path)
return
}
cv.activate() cv.activate()
var triBuf [1000]float32 var triBuf [1000]float32
@ -549,6 +566,35 @@ func (cv *Canvas) clip(path []pathPoint) {
copy(cv.state.clip, cv.polyPath) copy(cv.state.clip, cv.polyPath)
} }
func (cv *Canvas) scissor(path []pathPoint) {
tl, br := vec{math.MaxFloat64, math.MaxFloat64}, vec{}
for _, p := range path {
tl[0] = math.Min(p.tf[0], tl[0])
tl[1] = math.Min(p.tf[1], tl[1])
br[0] = math.Max(p.tf[0], br[0])
br[1] = math.Max(p.tf[1], br[1])
}
if cv.state.scissor.on {
tl[0] = math.Max(tl[0], cv.state.scissor.tl[0])
tl[1] = math.Max(tl[1], cv.state.scissor.tl[1])
br[0] = math.Min(br[0], cv.state.scissor.br[0])
br[1] = math.Min(br[1], cv.state.scissor.br[1])
}
cv.state.scissor = scissor{tl: tl, br: br, on: true}
cv.applyScissor()
}
func (cv *Canvas) applyScissor() {
s := &cv.state.scissor
if s.on {
gli.Scissor(int32(s.tl[0]+0.5), int32(cv.fh-s.br[1]+0.5), int32(s.br[0]-s.tl[0]+0.5), int32(s.br[1]-s.tl[1]+0.5))
} else {
gli.Scissor(0, 0, int32(cv.w), int32(cv.h))
}
}
// Rect creates a closed rectangle path for stroking or filling // Rect creates a closed rectangle path for stroking or filling
func (cv *Canvas) Rect(x, y, w, h float64) { func (cv *Canvas) Rect(x, y, w, h float64) {
cv.MoveTo(x, y) cv.MoveTo(x, y)
@ -556,6 +602,8 @@ func (cv *Canvas) Rect(x, y, w, h float64) {
cv.LineTo(x+w, y+h) cv.LineTo(x+w, y+h)
cv.LineTo(x, y+h) cv.LineTo(x, y+h)
cv.ClosePath() cv.ClosePath()
cv.linePath[len(cv.linePath)-1].flags |= pathIsRect
cv.polyPath[len(cv.polyPath)-1].flags |= pathIsRect
} }
// Rect creates a closed rectangle path for stroking or filling // Rect creates a closed rectangle path for stroking or filling