• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15
16import { gl } from "../GLFrame.js"
17
18export class XTexture {
19    static gi() {
20        if (XTexture.pinstance_ == null) XTexture.pinstance_ = new XTexture();
21        return XTexture.pinstance_;
22    }
23    constructor() {
24        this.ximages = [];
25        this.allCuts = {};
26        this.tmpCutid = 0;
27        this.aiCutid = 100;
28
29        this.textImgs = {};//rid,{mask}
30        this.textIdxs = {};//text,{}
31
32        this.textTmpRid = this.loadTexture(1024, 256)
33        this.bfirst = true;
34
35        this.textCvs = document.createElement('canvas');
36        this.textCvs.width = 1024;
37        this.textCvs.height = 256;
38        this.textCtx = this.textCvs.getContext("2d");
39        this.textCtx.textBaseline = 'top'
40        this.textCtx.textAlign = 'left'
41    }
42    static initTextureStatus(tex)
43    {
44            gl.activeTexture(gl.TEXTURE0);
45            gl.bindTexture(gl.TEXTURE_2D, tex);
46            gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
47            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
48            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
49            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
50            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
51    }
52    loadTextureFromImage(path, keepdata = false) {
53        if (path == "CUSTOM_TEXTURE_1") {
54            var rid = this.ximages.length;
55
56            var texture = gl.createTexture();
57            XTexture.initTextureStatus(texture);
58
59            let tmp=new Uint8Array([255,255,255,255])
60            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, tmp)
61
62            this.ximages[rid] = { "stat": 1, "path": path, "tex": texture ,"w":1,"h":1};
63            return rid
64        }
65        else {
66            for (let i = 0; i < this.ximages.length; i++) {
67                if (this.ximages[i]["path"] == path) {
68                    return i;
69                }
70            }
71            var rid = this.ximages.length;
72            this.ximages[rid] = { "stat": 0, "path": path, "tex": null };
73            var image = new Image();
74            image.src = path;//"http://localhost:8910/"+
75            image.onload = function () {
76                var texture = gl.createTexture();
77                XTexture.initTextureStatus(texture)
78
79                gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
80
81                XTexture.pinstance_.ximages[rid].tex = texture;
82                XTexture.pinstance_.ximages[rid].img = image;
83                XTexture.pinstance_.ximages[rid].stat = 1;
84                XTexture.pinstance_.ximages[rid].w = image.width;
85                XTexture.pinstance_.ximages[rid].h = image.height;
86            };
87            return rid;
88        }
89    }
90    TmpCut(rid, x = 0, y = 0, w = -1, h = -1, ww = 1024, hh = 1024) {
91        if (this.ximages[rid].stat != 1) return -1;
92
93        if (w == -1) w = ww;
94        if (h == -1) h = hh;
95        this.allCuts[this.tmpCutid] = {
96            "rid": rid,
97            "x": x, "y": y,
98            "w": w, "h": h,
99            "u0": x / ww, "v0": y / hh,
100            "u1": (x + w) / ww, "v1": y / hh,
101            "u2": (x + w) / ww, "v2": (y + h) / hh,
102            "u3": x / ww, "v3": (y + h) / hh
103        };
104        this.tmpCutid += 1;
105        return this.tmpCutid - 1;
106    }
107    makeCut(rid, x = 0, y = 0, w = -1, h = -1, ww = -1, hh = -1) {
108        if (this.ximages[rid].stat != 1) return -1;
109
110        if (ww == -1) ww = this.ximages[rid].w;
111        if (hh == -1) hh = this.ximages[rid].h;
112        if (w == -1) w = ww;
113        if (h == -1) h = hh;
114        this.allCuts[this.aiCutid] = {
115            "rid": rid,
116            "x": x, "y": y,
117            "w": w, "h": h,
118            "u0": x / ww, "v0": y / hh,
119            "u1": (x + w) / ww, "v1": y / hh,
120            "u2": (x + w) / ww, "v2": (y + h) / hh,
121            "u3": x / ww, "v3": (y + h) / hh
122        };
123        this.aiCutid += 1;
124        return this.aiCutid - 1;
125    }
126    timenow() {
127        let myDate = new Date();
128        return myDate.getTime() / 1000;
129    }
130
131    PutTexture(tex, w, h) {
132        var rid = this.ximages.length;
133        this.ximages[rid] = { "stat": 1, "path": "put" + rid, "tex": tex, "w": w, "h": h };
134        return rid;
135    }
136
137    loadTexture(width, height) {
138        var rid = this.ximages.length;
139
140        var texture = gl.createTexture();
141        XTexture.initTextureStatus(texture)
142        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)
143
144        this.ximages[rid] = { "stat": 1, "path": "default" + rid, "tex": texture, "w": width, "h": height };
145        return rid;
146    }
147    initTextImageData(s, size) {
148        this.textCtx.clearRect(0, 0, 1024, 256)
149        this.textCtx.font = size + "px 'Consolas'"
150        this.textCtx.fillStyle = "rgba(255,255,255,1)";
151        this.textCtx.fillText(s, 1, 1)
152        let imgd = this.textCtx.getImageData(0, 0, 1024, 256).data
153        let w = 1024;
154        let h = size+5;
155        let x = 256;
156        while (x == 256) {
157            h -= 1;
158            for (x = 0; x < 128; x++) {
159                let p = (h * 1024 + x) * 4;
160                if (imgd[p] != 0) break;
161            }
162        }
163        let y = h
164        while (y == h) {
165            w -= 1
166            for (y = 0; y < h; y++) {
167                let p = (y * 1024 + w) * 4;
168                if (imgd[p] != 0) break;
169            }
170        }
171        return this.textCtx.getImageData(0, 0, w + 1, h + 1)
172    }
173    getText(s, size) {
174        let textIdx = s + size
175
176        if (textIdx in this.textIdxs) {
177            this.textIdxs[textIdx].time = this.timenow()
178            return this.textIdxs[textIdx].cid
179        }
180        let imgd = this.initTextImageData(s, size)
181        let w = imgd.width
182        let h = imgd.height
183        let useHeight = Math.floor((h + 31) / 32)
184        let mask = 0
185        for (let i = 0; i < useHeight; i++)
186            mask |= (1 << i);
187        let rid = -1;
188        let off = -1;
189        for (let k in this.textImgs) {
190            for (let i = 0; i < 32 - useHeight + 1; i++) {
191                if ((this.textImgs[k].mask & (mask << i)) == 0) {
192                    off = i;
193                    break;
194                }
195            }
196            if (off != -1) {
197                rid = k;
198                break;
199            }
200        }
201        if (rid == -1) {
202            rid = this.loadTexture(1024, 1024)
203            this.textImgs[rid] = { "mask": 0 }
204            off = 0
205        }
206        let cid = this.makeCut(rid, 0, off * 32, w, h)
207        this.textImgs[rid]["mask"] |= mask << off
208        this.textIdxs[textIdx] = { "cid": cid, "rid": rid, "mask": mask << off, "time": this.timenow() }
209        gl.activeTexture(gl.TEXTURE0);
210        gl.bindTexture(gl.TEXTURE_2D, this.ximages[rid].tex);
211        gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
212        gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, off * 32, gl.RGBA, gl.UNSIGNED_BYTE, imgd);
213        return cid
214    }
215    _FreshText() {
216        this.tmpCutid = 0;
217        let nt=this.timenow()
218        let rm=[]
219        for(let idx in this.textIdxs)
220        {
221            if(nt-this.textIdxs[idx].time>10)
222            {
223                this.textImgs[this.textIdxs[idx].rid].mask&=(~this.textIdxs[idx].mask)
224                delete this.allCuts[this.textIdxs[idx].cid]
225                rm.push(idx)
226            }
227        }
228        for(let idx in rm)
229        {
230            delete this.textIdxs[rm[idx]]
231        }
232    }
233}
234XTexture.pinstance_ = null;