github.com/cybriq/giocore@v0.0.7-0.20210703034601-cfb9cb5f3900/op/clip/stroke.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package clip 4 5 import ( 6 "encoding/binary" 7 "math" 8 9 "github.com/cybriq/giocore/internal/opconst" 10 "github.com/cybriq/giocore/op" 11 ) 12 13 // Stroke represents a stroked path. 14 type Stroke struct { 15 Path PathSpec 16 Style StrokeStyle 17 18 // Dashes specify the dashes of the stroke. 19 // The empty value denotes no dashes. 20 Dashes DashSpec 21 } 22 23 // Op returns a clip operation representing the stroke. 24 func (s Stroke) Op() Op { 25 return Op{ 26 path: s.Path, 27 stroke: s.Style, 28 dashes: s.Dashes, 29 } 30 } 31 32 // StrokeStyle describes how a path should be stroked. 33 type StrokeStyle struct { 34 Width float32 // Width of the stroked path. 35 36 // Miter is the limit to apply to a miter joint. 37 // The zero Miter disables the miter joint; setting Miter to +∞ 38 // unconditionally enables the miter joint. 39 Miter float32 40 Cap StrokeCap // Cap describes the head or tail of a stroked path. 41 Join StrokeJoin // Join describes how stroked paths are collated. 42 } 43 44 // StrokeCap describes the head or tail of a stroked path. 45 type StrokeCap uint8 46 47 const ( 48 // RoundCap caps stroked paths with a round cap, joining the right-hand and 49 // left-hand sides of a stroked path with a half disc of diameter the 50 // stroked path's width. 51 RoundCap StrokeCap = iota 52 53 // FlatCap caps stroked paths with a flat cap, joining the right-hand 54 // and left-hand sides of a stroked path with a straight line. 55 FlatCap 56 57 // SquareCap caps stroked paths with a square cap, joining the right-hand 58 // and left-hand sides of a stroked path with a half square of length 59 // the stroked path's width. 60 SquareCap 61 ) 62 63 // StrokeJoin describes how stroked paths are collated. 64 type StrokeJoin uint8 65 66 const ( 67 // RoundJoin joins path segments with a round segment. 68 RoundJoin StrokeJoin = iota 69 70 // BevelJoin joins path segments with sharp bevels. 71 BevelJoin 72 ) 73 74 // Dash records dashes' lengths and phase for a stroked path. 75 type Dash struct { 76 ops *op.Ops 77 macro op.MacroOp 78 phase float32 79 size uint8 // size of the pattern 80 } 81 82 func (d *Dash) Begin(ops *op.Ops) { 83 d.ops = ops 84 d.macro = op.Record(ops) 85 // Write the TypeAux opcode 86 data := ops.Write(opconst.TypeAuxLen) 87 data[0] = byte(opconst.TypeAux) 88 } 89 90 func (d *Dash) Phase(v float32) { 91 d.phase = v 92 } 93 94 func (d *Dash) Dash(length float32) { 95 if d.size == math.MaxUint8 { 96 panic("clip: dash pattern too large") 97 } 98 data := d.ops.Write(4) 99 bo := binary.LittleEndian 100 bo.PutUint32(data[0:], math.Float32bits(length)) 101 d.size++ 102 } 103 104 func (d *Dash) End() DashSpec { 105 c := d.macro.Stop() 106 return DashSpec{ 107 spec: c, 108 phase: d.phase, 109 size: d.size, 110 } 111 } 112 113 // DashSpec describes a dashed pattern. 114 type DashSpec struct { 115 spec op.CallOp 116 phase float32 117 size uint8 // size of the pattern 118 }