gioui.org@v0.6.1-0.20240506124620-7a9ce51988ce/gpu/internal/rendertest/transform_test.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  package rendertest
     4  
     5  import (
     6  	"image"
     7  	"math"
     8  	"testing"
     9  
    10  	"golang.org/x/image/colornames"
    11  
    12  	"gioui.org/f32"
    13  	"gioui.org/op"
    14  	"gioui.org/op/clip"
    15  	"gioui.org/op/paint"
    16  )
    17  
    18  func TestPaintOffset(t *testing.T) {
    19  	run(t, func(o *op.Ops) {
    20  		defer op.Offset(image.Pt(10, 20)).Push(o).Pop()
    21  		paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
    22  	}, func(r result) {
    23  		r.expect(0, 0, transparent)
    24  		r.expect(59, 30, colornames.Red)
    25  		r.expect(60, 30, transparent)
    26  		r.expect(10, 70, transparent)
    27  	})
    28  }
    29  
    30  func TestPaintRotate(t *testing.T) {
    31  	run(t, func(o *op.Ops) {
    32  		a := f32.Affine2D{}.Rotate(f32.Pt(40, 40), -math.Pi/8)
    33  		defer op.Affine(a).Push(o).Pop()
    34  		paint.FillShape(o, red, clip.Rect(image.Rect(20, 20, 60, 60)).Op())
    35  	}, func(r result) {
    36  		r.expect(40, 40, colornames.Red)
    37  		r.expect(50, 19, colornames.Red)
    38  		r.expect(59, 19, transparent)
    39  		r.expect(21, 21, transparent)
    40  	})
    41  }
    42  
    43  func TestPaintShear(t *testing.T) {
    44  	run(t, func(o *op.Ops) {
    45  		a := f32.Affine2D{}.Shear(f32.Point{}, math.Pi/4, 0)
    46  		defer op.Affine(a).Push(o).Pop()
    47  		paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 40, 40)).Op())
    48  	}, func(r result) {
    49  		r.expect(10, 30, transparent)
    50  	})
    51  }
    52  
    53  func TestClipPaintOffset(t *testing.T) {
    54  	run(t, func(o *op.Ops) {
    55  		defer clip.RRect{Rect: image.Rect(10, 10, 30, 30)}.Push(o).Pop()
    56  		defer op.Offset(image.Pt(20, 20)).Push(o).Pop()
    57  		paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 100, 100)).Op())
    58  	}, func(r result) {
    59  		r.expect(0, 0, transparent)
    60  		r.expect(19, 19, transparent)
    61  		r.expect(20, 20, colornames.Red)
    62  		r.expect(30, 30, transparent)
    63  	})
    64  }
    65  
    66  func TestClipOffset(t *testing.T) {
    67  	run(t, func(o *op.Ops) {
    68  		defer op.Offset(image.Pt(20, 20)).Push(o).Pop()
    69  		defer clip.RRect{Rect: image.Rect(10, 10, 30, 30)}.Push(o).Pop()
    70  		paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 100, 100)).Op())
    71  	}, func(r result) {
    72  		r.expect(0, 0, transparent)
    73  		r.expect(29, 29, transparent)
    74  		r.expect(30, 30, colornames.Red)
    75  		r.expect(49, 49, colornames.Red)
    76  		r.expect(50, 50, transparent)
    77  	})
    78  }
    79  
    80  func TestClipScale(t *testing.T) {
    81  	run(t, func(o *op.Ops) {
    82  		a := f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(2, 2)).Offset(f32.Pt(10, 10))
    83  		defer op.Affine(a).Push(o).Pop()
    84  		defer clip.RRect{Rect: image.Rect(10, 10, 20, 20)}.Push(o).Pop()
    85  		paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 1000, 1000)).Op())
    86  	}, func(r result) {
    87  		r.expect(19+10, 19+10, transparent)
    88  		r.expect(20+10, 20+10, colornames.Red)
    89  		r.expect(39+10, 39+10, colornames.Red)
    90  		r.expect(40+10, 40+10, transparent)
    91  	})
    92  }
    93  
    94  func TestClipRotate(t *testing.T) {
    95  	run(t, func(o *op.Ops) {
    96  		defer op.Affine(f32.Affine2D{}.Rotate(f32.Pt(40, 40), -math.Pi/4)).Push(o).Pop()
    97  		defer clip.RRect{Rect: image.Rect(30, 30, 50, 50)}.Push(o).Pop()
    98  		paint.FillShape(o, red, clip.Rect(image.Rect(0, 40, 100, 100)).Op())
    99  	}, func(r result) {
   100  		r.expect(39, 39, transparent)
   101  		r.expect(41, 41, colornames.Red)
   102  		r.expect(50, 50, transparent)
   103  	})
   104  }
   105  
   106  func TestOffsetTexture(t *testing.T) {
   107  	run(t, func(o *op.Ops) {
   108  		defer op.Offset(image.Pt(15, 15)).Push(o).Pop()
   109  		squares.Add(o)
   110  		defer scale(50.0/512, 50.0/512).Push(o).Pop()
   111  		paint.PaintOp{}.Add(o)
   112  	}, func(r result) {
   113  		r.expect(14, 20, transparent)
   114  		r.expect(66, 20, transparent)
   115  		r.expect(16, 64, colornames.Green)
   116  		r.expect(64, 16, colornames.Green)
   117  	})
   118  }
   119  
   120  func TestOffsetScaleTexture(t *testing.T) {
   121  	run(t, func(o *op.Ops) {
   122  		defer op.Offset(image.Pt(15, 15)).Push(o).Pop()
   123  		squares.Add(o)
   124  		defer op.Affine(f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(2, 1))).Push(o).Pop()
   125  		defer scale(50.0/512, 50.0/512).Push(o).Pop()
   126  		paint.PaintOp{}.Add(o)
   127  	}, func(r result) {
   128  		r.expect(114, 64, colornames.Blue)
   129  		r.expect(116, 64, transparent)
   130  	})
   131  }
   132  
   133  func TestRotateTexture(t *testing.T) {
   134  	run(t, func(o *op.Ops) {
   135  		squares.Add(o)
   136  		a := f32.Affine2D{}.Offset(f32.Pt(30, 30)).Rotate(f32.Pt(40, 40), math.Pi/4)
   137  		defer op.Affine(a).Push(o).Pop()
   138  		defer scale(20.0/512, 20.0/512).Push(o).Pop()
   139  		paint.PaintOp{}.Add(o)
   140  	}, func(r result) {
   141  		r.expect(40, 40-12, colornames.Blue)
   142  		r.expect(40+12, 40, colornames.Green)
   143  	})
   144  }
   145  
   146  func TestRotateClipTexture(t *testing.T) {
   147  	run(t, func(o *op.Ops) {
   148  		squares.Add(o)
   149  		a := f32.Affine2D{}.Rotate(f32.Pt(40, 40), math.Pi/8)
   150  		defer op.Affine(a).Push(o).Pop()
   151  		defer clip.RRect{Rect: image.Rect(30, 30, 50, 50)}.Push(o).Pop()
   152  		defer op.Affine(f32.Affine2D{}.Offset(f32.Pt(10, 10))).Push(o).Pop()
   153  		defer scale(60.0/512, 60.0/512).Push(o).Pop()
   154  		paint.PaintOp{}.Add(o)
   155  	}, func(r result) {
   156  		r.expect(0, 0, transparent)
   157  		r.expect(37, 39, colornames.Green)
   158  		r.expect(36, 39, colornames.Green)
   159  		r.expect(35, 39, colornames.Green)
   160  		r.expect(34, 39, colornames.Green)
   161  		r.expect(33, 39, colornames.Green)
   162  	})
   163  }
   164  
   165  func TestComplicatedTransform(t *testing.T) {
   166  	run(t, func(o *op.Ops) {
   167  		squares.Add(o)
   168  
   169  		defer clip.RRect{Rect: image.Rect(0, 0, 100, 100), SE: 50, SW: 50, NW: 50, NE: 50}.Push(o).Pop()
   170  
   171  		a := f32.Affine2D{}.Shear(f32.Point{}, math.Pi/4, 0)
   172  		defer op.Affine(a).Push(o).Pop()
   173  		defer clip.RRect{Rect: image.Rect(0, 0, 50, 40)}.Push(o).Pop()
   174  
   175  		defer scale(50.0/512, 50.0/512).Push(o).Pop()
   176  		paint.PaintOp{}.Add(o)
   177  	}, func(r result) {
   178  		r.expect(20, 5, transparent)
   179  	})
   180  }
   181  
   182  func TestTransformOrder(t *testing.T) {
   183  	// check the ordering of operations bot in affine and in gpu stack.
   184  	run(t, func(o *op.Ops) {
   185  		a := f32.Affine2D{}.Offset(f32.Pt(64, 64))
   186  		defer op.Affine(a).Push(o).Pop()
   187  
   188  		b := f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(8, 8))
   189  		defer op.Affine(b).Push(o).Pop()
   190  
   191  		c := f32.Affine2D{}.Offset(f32.Pt(-10, -10)).Scale(f32.Point{}, f32.Pt(0.5, 0.5))
   192  		defer op.Affine(c).Push(o).Pop()
   193  		paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 20, 20)).Op())
   194  	}, func(r result) {
   195  		// centered and with radius 40
   196  		r.expect(64-41, 64, transparent)
   197  		r.expect(64-39, 64, colornames.Red)
   198  		r.expect(64+39, 64, colornames.Red)
   199  		r.expect(64+41, 64, transparent)
   200  	})
   201  }