slot.go (1978B)
1 package icns 2 3 import ( 4 "fmt" 5 "regexp" 6 "strconv" 7 ) 8 9 // Slot identifies an icon by the size it is drawn at and the display scale it 10 // is drawn for, the way an iconset names its files. Artwork for 16x16@2x and 11 // for 32x32 is 32 pixels either way, but the two fill different slots and 12 // need not be the same drawing. 13 type Slot struct { 14 // Points is the size the icon is drawn at. 15 Points uint 16 // Scale is the display scale, 1 for a plain display and 2 for retina. 17 Scale uint 18 } 19 20 // Pixels returns the dimensions artwork for this slot has. 21 func (s Slot) Pixels() uint { 22 return s.Points * s.Scale 23 } 24 25 // String renders the slot the way an iconset names it, such as "16x16@2x". 26 func (s Slot) String() string { 27 if s.Scale > 1 { 28 return fmt.Sprintf("%dx%d@%dx", s.Points, s.Points, s.Scale) 29 } 30 return fmt.Sprintf("%dx%d", s.Points, s.Points) 31 } 32 33 // Slots returns the slots an encoded icns holds, largest artwork first. 34 func Slots() []Slot { 35 var slots []Slot 36 for _, size := range sizes { 37 types, ok := getTypesFromSize(size) 38 if !ok { 39 continue 40 } 41 for _, t := range types { 42 slots = append(slots, t.slot) 43 } 44 } 45 return slots 46 } 47 48 // iconsetName matches the file names iconutil accepts in an iconset. 49 var iconsetName = regexp.MustCompile(`^icon_(\d+)x(\d+)(?:@(\d+)x)?\.png$`) 50 51 // ParseSlot reads an iconset file name, such as "icon_16x16@2x.png". The 52 // boolean reports whether the name is one. 53 func ParseSlot(name string) (Slot, bool) { 54 match := iconsetName.FindStringSubmatch(name) 55 if match == nil { 56 return Slot{}, false 57 } 58 width, err := strconv.ParseUint(match[1], 10, 32) 59 if err != nil { 60 return Slot{}, false 61 } 62 height, err := strconv.ParseUint(match[2], 10, 32) 63 if err != nil || width != height || width == 0 { 64 return Slot{}, false 65 } 66 scale := uint64(1) 67 if match[3] != "" { 68 if scale, err = strconv.ParseUint(match[3], 10, 32); err != nil || scale == 0 { 69 return Slot{}, false 70 } 71 } 72 return Slot{Points: uint(width), Scale: uint(scale)}, true 73 }