1package main
2
3import (
4	"encoding/xml"
5	"flag"
6	"image"
7	"image/color"
8	"image/draw"
9	"image/png"
10	"io"
11	"io/ioutil"
12	"log"
13	"os"
14	"path/filepath"
15)
16
17var (
18	root = "../../../"
19)
20
21var (
22	flagRoot string
23)
24
25func init() {
26	flag.StringVar(&flagRoot, "root", "", "setup liteide root")
27}
28
29func main() {
30	flag.Parse()
31	if flagRoot != "" {
32		root = flagRoot
33	}
34	root, _ := filepath.Abs(root)
35	log.Println("process qrc files in liteide root", root)
36	var p Process
37	p.ProcessDir(filepath.Join(root, "src/liteapp"))
38	p.ProcessDir(filepath.Join(root, "src/plugins"))
39	p.Export(filepath.Join(root, "deploy/liteapp/qrc/default"), CopyFile)
40	p.Export(filepath.Join(root, "deploy/liteapp/qrc/gray"), MakeColorImage(GrayColor))
41}
42
43type Process struct {
44	rccs []RCC
45}
46
47func (p *Process) ProcessDir(dir string) {
48	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
49		if filepath.Ext(path) == ".qrc" {
50			p.ProcessQrc(path)
51		}
52		return nil
53	})
54}
55
56type QResource struct {
57	Prefix string   `xml:"prefix,attr"`
58	Files  []string `xml:"file"`
59}
60
61type RCC struct {
62	Dir      string
63	DirName  string
64	FileName string
65	XMLName  xml.Name  `xml:"RCC"`
66	Resource QResource `xml:"qresource"`
67}
68
69func (rcc *RCC) IsEmtpy() bool {
70	return len(rcc.Resource.Files) == 0
71}
72
73func (rcc *RCC) ImagesFiles() (images []string) {
74	for _, file := range rcc.Resource.Files {
75		if filepath.Ext(file) == ".png" {
76			image := filepath.Join(rcc.Dir, file)
77			_, err := os.Lstat(image)
78			if err != nil {
79				log.Println("warning, not find image", image)
80			}
81			images = append(images, image)
82		}
83	}
84	return
85}
86
87func (p *Process) ProcessQrc(path string) error {
88	data, err := ioutil.ReadFile(path)
89	if err != nil {
90		return err
91	}
92	var rcc RCC
93	err = xml.Unmarshal(data, &rcc)
94	if err != nil {
95		log.Println(err)
96		return err
97	}
98	rcc.Dir, rcc.FileName = filepath.Split(path)
99	_, rcc.DirName = filepath.Split(filepath.Clean(rcc.Dir))
100	p.rccs = append(p.rccs, rcc)
101	return nil
102}
103
104func (p *Process) Export(outdir string, copyFn CopyFunc) error {
105	log.Println("export", outdir)
106	for _, rcc := range p.rccs {
107		p.ExportQrc(outdir, rcc, copyFn)
108	}
109	return nil
110}
111
112func (p *Process) ExportQrc(outdir string, rcc RCC, copyFn CopyFunc) error {
113	images := rcc.ImagesFiles()
114	if len(images) == 0 {
115		//log.Println("skip empty rcc", rcc.FileName)
116		return nil
117	}
118	outpath := filepath.Join(outdir, rcc.DirName)
119	os.MkdirAll(outpath, 0777)
120	log.Println(rcc.DirName, "->", len(images))
121	for _, file := range images {
122		target := file[len(rcc.Dir):]
123		dest := filepath.Join(outpath, target)
124		d, _ := filepath.Split(dest)
125		os.MkdirAll(d, 0777)
126		err := copyFn(file, dest)
127		if err != nil {
128			log.Println(file, err)
129		}
130	}
131	return nil
132}
133
134type CopyFunc func(string, string) error
135type ColorFunc func(r, g, b uint8) (uint8, uint8, uint8)
136
137func GrayColor(r uint8, g uint8, b uint8) (uint8, uint8, uint8) {
138	Y, cb, cr := color.RGBToYCbCr(r, g, b)
139	cb = 128
140	cr = 128
141	return color.YCbCrToRGB(Y, cb, cr)
142}
143
144func MakeColorImage(colorFn ColorFunc) func(string, string) error {
145	return func(source string, dest string) error {
146		return CopyImage(source, dest, colorFn)
147	}
148}
149
150func CopyImage(source string, dest string, colorFn ColorFunc) error {
151	f, err := os.Open(source)
152	if err != nil {
153		return err
154	}
155	srcImage, err := png.Decode(f)
156	if err != nil {
157		return err
158	}
159	dstImage := image.NewRGBA(srcImage.Bounds())
160	draw.Draw(dstImage, dstImage.Bounds(), srcImage, srcImage.Bounds().Min, draw.Src)
161	//	dstImage.
162	b := dstImage.Bounds()
163	for y := b.Min.Y; y < b.Max.Y; y++ {
164		for x := b.Min.X; x < b.Max.X; x++ {
165			c := dstImage.RGBAAt(x, y)
166			r, g, b := colorFn(c.R, c.G, c.B)
167			dstImage.SetRGBA(x, y, color.RGBA{r, g, b, c.A})
168		}
169	}
170
171	w, err := os.Create(dest)
172	if err != nil {
173		return err
174	}
175	err = png.Encode(w, dstImage)
176	if err != nil {
177		return err
178	}
179	return nil
180}
181
182func CopyFile(source string, dest string) (err error) {
183	sourcefile, err := os.Open(source)
184	if err != nil {
185		return err
186	}
187	defer sourcefile.Close()
188	destfile, err := os.Create(dest)
189	if err != nil {
190		return err
191	}
192	defer destfile.Close()
193	_, err = io.Copy(destfile, sourcefile)
194	if err == nil {
195		sourceinfo, err := os.Stat(source)
196		if err != nil {
197			err = os.Chmod(dest, sourceinfo.Mode())
198		}
199	}
200	return
201}
202