• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022-2023 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 = {};
30    this.textIdxs = {};
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', { willReadFrequently: true });
39    this.textCtx.textBaseline = 'top';
40    this.textCtx.textAlign = 'left';
41  }
42  static initTextureStatus(tex) {
43    gl.activeTexture(gl.TEXTURE0);
44    gl.bindTexture(gl.TEXTURE_2D, tex);
45    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
46    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
47    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
48    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
49    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
50  }
51  loadTextureFromImage(path, keepdata = false) {
52    if (path === 'CUSTOM_TEXTURE_1') {
53      var rid = this.ximages.length;
54
55      var texture = gl.createTexture();
56      XTexture.initTextureStatus(texture);
57
58      let tmp = new Uint8Array([255, 255, 255, 255]);
59      gl.texImage2D(
60        gl.TEXTURE_2D,
61        0,
62        gl.RGBA,
63        1,
64        1,
65        0,
66        gl.RGBA,
67        gl.UNSIGNED_BYTE,
68        tmp
69      );
70
71      this.ximages[rid] = { stat: 1, path: path, tex: texture, w: 1, h: 1 };
72      return rid;
73    } else {
74      for (let i = 0; i < this.ximages.length; i++) {
75        if (this.ximages[i]['path'] === path) {
76          return i;
77        }
78      }
79      var rid = this.ximages.length;
80      this.ximages[rid] = { stat: 0, path: path, tex: null };
81      var image = new Image();
82      image.src = path; //"http://localhost:8910/"+
83      image.onload = function () {
84        var texture = gl.createTexture();
85        XTexture.initTextureStatus(texture);
86
87        gl.texImage2D(
88          gl.TEXTURE_2D,
89          0,
90          gl.RGBA,
91          gl.RGBA,
92          gl.UNSIGNED_BYTE,
93          image
94        );
95
96        XTexture.pinstance_.ximages[rid].tex = texture;
97        XTexture.pinstance_.ximages[rid].img = image;
98        XTexture.pinstance_.ximages[rid].stat = 1;
99        XTexture.pinstance_.ximages[rid].w = image.width;
100        XTexture.pinstance_.ximages[rid].h = image.height;
101      };
102      return rid;
103    }
104  }
105  TmpCut(rid, x = 0, y = 0, w = -1, h = -1, ww = 1024, hh = 1024) {
106    if (this.ximages[rid].stat !== 1) return -1;
107
108    if (w === -1) w = ww;
109    if (h === -1) h = hh;
110    this.allCuts[this.tmpCutid] = {
111      rid: rid,
112      x: x,
113      y: y,
114      w: w,
115      h: h,
116      u0: x / ww,
117      v0: y / hh,
118      u1: (x + w) / ww,
119      v1: y / hh,
120      u2: (x + w) / ww,
121      v2: (y + h) / hh,
122      u3: x / ww,
123      v3: (y + h) / hh,
124    };
125    this.tmpCutid += 1;
126    return this.tmpCutid - 1;
127  }
128  makeCut(rid, x = 0, y = 0, w = -1, h = -1, ww = -1, hh = -1) {
129    if (ww === -1) ww = this.ximages[rid].w;
130    if (hh === -1) hh = this.ximages[rid].h;
131    if (w === -1) w = ww;
132    if (h === -1) h = hh;
133    this.allCuts[this.aiCutid] = {
134      rid: rid,
135      x: x,
136      y: y,
137      w: w,
138      h: h,
139      u0: x / ww,
140      v0: y / hh,
141      u1: (x + w) / ww,
142      v1: y / hh,
143      u2: (x + w) / ww,
144      v2: (y + h) / hh,
145      u3: x / ww,
146      v3: (y + h) / hh,
147    };
148    this.aiCutid += 1;
149    return this.aiCutid - 1;
150  }
151  timenow() {
152    let myDate = new Date();
153    return myDate.getTime() / 1000;
154  }
155
156  PutTexture(tex, w, h) {
157    var rid = this.ximages.length;
158    this.ximages[rid] = { stat: 1, path: 'put' + rid, tex: tex, w: w, h: h };
159    return rid;
160  }
161
162  loadTexture(width, height) {
163    var rid = this.ximages.length;
164
165    var texture = gl.createTexture();
166    XTexture.initTextureStatus(texture);
167    gl.texImage2D(
168      gl.TEXTURE_2D,
169      0,
170      gl.RGBA,
171      width,
172      height,
173      0,
174      gl.RGBA,
175      gl.UNSIGNED_BYTE,
176      null
177    );
178
179    this.ximages[rid] = {
180      stat: 1,
181      path: 'default' + rid,
182      tex: texture,
183      w: width,
184      h: height,
185    };
186    return rid;
187  }
188  initTextImageData(s, size) {
189    this.textCtx.clearRect(0, 0, 1024, 256);
190    this.textCtx.font = size + "px '宋体'";
191    this.textCtx.fillStyle = 'rgba(255,255,255,1)';
192    this.textCtx.fillText(s, 1, 1);
193    let imgd = this.textCtx.getImageData(0, 0, 1024, 256).data;
194    let w = 1024;
195    let h = size + 5;
196    let x = 256;
197    while (x === 256) {
198      h -= 1;
199      for (x = 0; x < 128; x++) {
200        let p = (h * 1024 + x) * 4;
201        if (imgd[p] !== 0) break;
202      }
203    }
204    let y = h;
205    while (y === h) {
206      w -= 1;
207      for (y = 0; y < h; y++) {
208        let p = (y * 1024 + w) * 4;
209        if (imgd[p] !== 0) break;
210      }
211    }
212    return this.textCtx.getImageData(0, 0, w + 1, h + 1);
213  }
214  getText(s, size) {
215    let textIdx = s + size;
216
217    if (textIdx in this.textIdxs) {
218      this.textIdxs[textIdx].time = this.timenow();
219      return this.textIdxs[textIdx].cid;
220    }
221    let imgd = this.initTextImageData(s, size);
222    let w = imgd.width;
223    let h = imgd.height;
224    let useHeight = Math.floor((h + 31) / 32);
225    let mask = 0;
226    for (let i = 0; i < useHeight; i++) mask |= 1 << i;
227    let rid = -1;
228    let off = -1;
229    for (let k in this.textImgs) {
230      for (let i = 0; i < 32 - useHeight + 1; i++) {
231        if ((this.textImgs[k].mask & (mask << i)) === 0) {
232          off = i;
233          break;
234        }
235      }
236      if (off !== -1) {
237        rid = k;
238        break;
239      }
240    }
241    if (rid === -1) {
242      rid = this.loadTexture(1024, 1024);
243      this.textImgs[rid] = { mask: 0 };
244      off = 0;
245    }
246    let cid = this.makeCut(rid, 0, off * 32, w, h);
247    this.textImgs[rid]['mask'] |= mask << off;
248    this.textIdxs[textIdx] = { cid: cid, rid: rid, mask: mask << off, time: this.timenow(), };
249    gl.activeTexture(gl.TEXTURE0);
250    gl.bindTexture(gl.TEXTURE_2D, this.ximages[rid].tex);
251    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
252    gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, off * 32, gl.RGBA, gl.UNSIGNED_BYTE, imgd);
253    return cid;
254  }
255  _FreshText() {
256    this.tmpCutid = 0;
257    let nt = this.timenow();
258    let rm = [];
259    for (let idx in this.textIdxs) {
260      if (nt - this.textIdxs[idx].time > 3) {
261        this.textImgs[this.textIdxs[idx].rid].mask &= ~this.textIdxs[idx].mask;
262        delete this.allCuts[this.textIdxs[idx].cid];
263        rm.push(idx);
264      }
265    }
266    for (let idx in rm) {
267      delete this.textIdxs[rm[idx]];
268    }
269  }
270  static ExpandColor(c) {
271    return [
272      ((c >> 16) & 0xff) / 255,
273      ((c >> 8) & 0xff) / 255,
274      (c & 0xff) / 255,
275      ((c >> 24) & 0xff) / 255];//r,g,b,a
276  }
277}
278XTexture.pinstance_ = null;
279