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