github.com/utopiagio/gio@v0.0.8/widget/fit.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package widget 4 5 import ( 6 "image" 7 8 "github.com/utopiagio/gio/f32" 9 "github.com/utopiagio/gio/layout" 10 ) 11 12 // Fit scales a widget to fit and clip to the constraints. 13 type Fit uint8 14 15 const ( 16 // Unscaled does not alter the scale of a widget. 17 Unscaled Fit = iota 18 // Contain scales widget as large as possible without cropping 19 // and it preserves aspect-ratio. 20 Contain 21 // Cover scales the widget to cover the constraint area and 22 // preserves aspect-ratio. 23 Cover 24 // ScaleDown scales the widget smaller without cropping, 25 // when it exceeds the constraint area. 26 // It preserves aspect-ratio. 27 ScaleDown 28 // Fill stretches the widget to the constraints and does not 29 // preserve aspect-ratio. 30 Fill 31 ) 32 33 // scale computes the new dimensions and transformation required to fit dims to cs, given the position. 34 func (fit Fit) scale(cs layout.Constraints, pos layout.Direction, dims layout.Dimensions) (layout.Dimensions, f32.Affine2D) { 35 widgetSize := dims.Size 36 37 if fit == Unscaled || dims.Size.X == 0 || dims.Size.Y == 0 { 38 dims.Size = cs.Constrain(dims.Size) 39 40 offset := pos.Position(widgetSize, dims.Size) 41 dims.Baseline += offset.Y 42 return dims, f32.Affine2D{}.Offset(layout.FPt(offset)) 43 } 44 45 scale := f32.Point{ 46 X: float32(cs.Max.X) / float32(dims.Size.X), 47 Y: float32(cs.Max.Y) / float32(dims.Size.Y), 48 } 49 50 switch fit { 51 case Contain: 52 if scale.Y < scale.X { 53 scale.X = scale.Y 54 } else { 55 scale.Y = scale.X 56 } 57 case Cover: 58 if scale.Y > scale.X { 59 scale.X = scale.Y 60 } else { 61 scale.Y = scale.X 62 } 63 case ScaleDown: 64 if scale.Y < scale.X { 65 scale.X = scale.Y 66 } else { 67 scale.Y = scale.X 68 } 69 70 // The widget would need to be scaled up, no change needed. 71 if scale.X >= 1 { 72 dims.Size = cs.Constrain(dims.Size) 73 74 offset := pos.Position(widgetSize, dims.Size) 75 dims.Baseline += offset.Y 76 return dims, f32.Affine2D{}.Offset(layout.FPt(offset)) 77 } 78 case Fill: 79 } 80 81 var scaledSize image.Point 82 scaledSize.X = int(float32(widgetSize.X) * scale.X) 83 scaledSize.Y = int(float32(widgetSize.Y) * scale.Y) 84 dims.Size = cs.Constrain(scaledSize) 85 dims.Baseline = int(float32(dims.Baseline) * scale.Y) 86 87 offset := pos.Position(scaledSize, dims.Size) 88 trans := f32.Affine2D{}. 89 Scale(f32.Point{}, scale). 90 Offset(layout.FPt(offset)) 91 92 dims.Baseline += offset.Y 93 94 return dims, trans 95 }