github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/tools/winresource/icon.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package main
     5  
     6  import (
     7  	"encoding/binary"
     8  	"io"
     9  	"os"
    10  
    11  	"github.com/akavel/rsrc/coff"
    12  	"github.com/akavel/rsrc/ico"
    13  )
    14  
    15  // *****************************************************************************
    16  /*
    17  Code from https://github.com/akavel/rsrc
    18  
    19  The MIT License (MIT)
    20  
    21  Copyright (c) 2013-2014 The rsrc Authors.
    22  
    23  Permission is hereby granted, free of charge, to any person obtaining a copy
    24  of this software and associated documentation files (the "Software"), to deal
    25  in the Software without restriction, including without limitation the rights
    26  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    27  copies of the Software, and to permit persons to whom the Software is
    28  furnished to do so, subject to the following conditions:
    29  
    30  The above copyright notice and this permission notice shall be included in
    31  all copies or substantial portions of the Software.
    32  
    33  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    34  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    35  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    36  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    37  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    38  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    39  THE SOFTWARE.
    40  */
    41  // *****************************************************************************
    42  
    43  const (
    44  	rtIcon      = coff.RT_ICON
    45  	rtGroupIcon = coff.RT_GROUP_ICON
    46  	_           = coff.RT_MANIFEST // rtManifest
    47  )
    48  
    49  // on storing icons, see: http://blogs.msdn.com/b/oldnewthing/archive/2012/07/20/10331787.aspx
    50  type gRPICONDIR struct {
    51  	ico.ICONDIR
    52  	Entries []gRPICONDIRENTRY
    53  }
    54  
    55  func (group gRPICONDIR) Size() int64 {
    56  	return int64(binary.Size(group.ICONDIR) + len(group.Entries)*binary.Size(group.Entries[0]))
    57  }
    58  
    59  type gRPICONDIRENTRY struct {
    60  	ico.IconDirEntryCommon
    61  	ID uint16
    62  }
    63  
    64  func addIcon(coff *coff.Coff, fname string, newID <-chan uint16) error {
    65  	f, err := os.Open(fname)
    66  	if err != nil {
    67  		return err
    68  	}
    69  	//defer f.Close() don't defer, files will be closed by OS when app closes
    70  
    71  	icons, err := ico.DecodeHeaders(f)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	if len(icons) > 0 {
    77  		// RT_ICONs
    78  		group := gRPICONDIR{ICONDIR: ico.ICONDIR{
    79  			Reserved: 0, // magic num.
    80  			Type:     1, // magic num.
    81  			Count:    uint16(len(icons)),
    82  		}}
    83  		for _, icon := range icons {
    84  			id := <-newID
    85  			r := io.NewSectionReader(f, int64(icon.ImageOffset), int64(icon.BytesInRes))
    86  			coff.AddResource(rtIcon, id, r)
    87  			group.Entries = append(group.Entries, gRPICONDIRENTRY{IconDirEntryCommon: icon.IconDirEntryCommon, ID: id})
    88  		}
    89  		id := <-newID
    90  		coff.AddResource(rtGroupIcon, id, group)
    91  	}
    92  
    93  	return nil
    94  }