14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ciimport { gl } from '../GLFrame.js'; 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ciexport class XTexture { 194514f5e3Sopenharmony_ci static gi() { 204514f5e3Sopenharmony_ci if (XTexture.pinstance_ === null) XTexture.pinstance_ = new XTexture(); 214514f5e3Sopenharmony_ci return XTexture.pinstance_; 224514f5e3Sopenharmony_ci } 234514f5e3Sopenharmony_ci constructor() { 244514f5e3Sopenharmony_ci this.ximages = []; 254514f5e3Sopenharmony_ci this.allCuts = {}; 264514f5e3Sopenharmony_ci this.tmpCutid = 0; 274514f5e3Sopenharmony_ci this.aiCutid = 100; 284514f5e3Sopenharmony_ci 294514f5e3Sopenharmony_ci this.textImgs = {}; 304514f5e3Sopenharmony_ci this.textIdxs = {}; 314514f5e3Sopenharmony_ci 324514f5e3Sopenharmony_ci this.textTmpRid = this.loadTexture(1024, 256); 334514f5e3Sopenharmony_ci this.bfirst = true; 344514f5e3Sopenharmony_ci 354514f5e3Sopenharmony_ci this.textCvs = document.createElement('canvas'); 364514f5e3Sopenharmony_ci this.textCvs.width = 1024; 374514f5e3Sopenharmony_ci this.textCvs.height = 256; 384514f5e3Sopenharmony_ci this.textCtx = this.textCvs.getContext('2d', { willReadFrequently: true }); 394514f5e3Sopenharmony_ci this.textCtx.textBaseline = 'top'; 404514f5e3Sopenharmony_ci this.textCtx.textAlign = 'left'; 414514f5e3Sopenharmony_ci } 424514f5e3Sopenharmony_ci static initTextureStatus(tex) { 434514f5e3Sopenharmony_ci gl.activeTexture(gl.TEXTURE0); 444514f5e3Sopenharmony_ci gl.bindTexture(gl.TEXTURE_2D, tex); 454514f5e3Sopenharmony_ci gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); 464514f5e3Sopenharmony_ci gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 474514f5e3Sopenharmony_ci gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 484514f5e3Sopenharmony_ci gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 494514f5e3Sopenharmony_ci gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 504514f5e3Sopenharmony_ci } 514514f5e3Sopenharmony_ci loadTextureFromImage(path, keepdata = false) { 524514f5e3Sopenharmony_ci if (path === 'CUSTOM_TEXTURE_1') { 534514f5e3Sopenharmony_ci var rid = this.ximages.length; 544514f5e3Sopenharmony_ci 554514f5e3Sopenharmony_ci var texture = gl.createTexture(); 564514f5e3Sopenharmony_ci XTexture.initTextureStatus(texture); 574514f5e3Sopenharmony_ci 584514f5e3Sopenharmony_ci let tmp = new Uint8Array([255, 255, 255, 255]); 594514f5e3Sopenharmony_ci gl.texImage2D( 604514f5e3Sopenharmony_ci gl.TEXTURE_2D, 614514f5e3Sopenharmony_ci 0, 624514f5e3Sopenharmony_ci gl.RGBA, 634514f5e3Sopenharmony_ci 1, 644514f5e3Sopenharmony_ci 1, 654514f5e3Sopenharmony_ci 0, 664514f5e3Sopenharmony_ci gl.RGBA, 674514f5e3Sopenharmony_ci gl.UNSIGNED_BYTE, 684514f5e3Sopenharmony_ci tmp 694514f5e3Sopenharmony_ci ); 704514f5e3Sopenharmony_ci 714514f5e3Sopenharmony_ci this.ximages[rid] = { stat: 1, path: path, tex: texture, w: 1, h: 1 }; 724514f5e3Sopenharmony_ci return rid; 734514f5e3Sopenharmony_ci } else { 744514f5e3Sopenharmony_ci for (let i = 0; i < this.ximages.length; i++) { 754514f5e3Sopenharmony_ci if (this.ximages[i]['path'] === path) { 764514f5e3Sopenharmony_ci return i; 774514f5e3Sopenharmony_ci } 784514f5e3Sopenharmony_ci } 794514f5e3Sopenharmony_ci var rid = this.ximages.length; 804514f5e3Sopenharmony_ci this.ximages[rid] = { stat: 0, path: path, tex: null }; 814514f5e3Sopenharmony_ci var image = new Image(); 824514f5e3Sopenharmony_ci image.src = path; //"http://localhost:8910/"+ 834514f5e3Sopenharmony_ci image.onload = function () { 844514f5e3Sopenharmony_ci var texture = gl.createTexture(); 854514f5e3Sopenharmony_ci XTexture.initTextureStatus(texture); 864514f5e3Sopenharmony_ci 874514f5e3Sopenharmony_ci gl.texImage2D( 884514f5e3Sopenharmony_ci gl.TEXTURE_2D, 894514f5e3Sopenharmony_ci 0, 904514f5e3Sopenharmony_ci gl.RGBA, 914514f5e3Sopenharmony_ci gl.RGBA, 924514f5e3Sopenharmony_ci gl.UNSIGNED_BYTE, 934514f5e3Sopenharmony_ci image 944514f5e3Sopenharmony_ci ); 954514f5e3Sopenharmony_ci 964514f5e3Sopenharmony_ci XTexture.pinstance_.ximages[rid].tex = texture; 974514f5e3Sopenharmony_ci XTexture.pinstance_.ximages[rid].img = image; 984514f5e3Sopenharmony_ci XTexture.pinstance_.ximages[rid].stat = 1; 994514f5e3Sopenharmony_ci XTexture.pinstance_.ximages[rid].w = image.width; 1004514f5e3Sopenharmony_ci XTexture.pinstance_.ximages[rid].h = image.height; 1014514f5e3Sopenharmony_ci }; 1024514f5e3Sopenharmony_ci return rid; 1034514f5e3Sopenharmony_ci } 1044514f5e3Sopenharmony_ci } 1054514f5e3Sopenharmony_ci TmpCut(rid, x = 0, y = 0, w = -1, h = -1, ww = 1024, hh = 1024) { 1064514f5e3Sopenharmony_ci if (this.ximages[rid].stat !== 1) return -1; 1074514f5e3Sopenharmony_ci 1084514f5e3Sopenharmony_ci if (w === -1) w = ww; 1094514f5e3Sopenharmony_ci if (h === -1) h = hh; 1104514f5e3Sopenharmony_ci this.allCuts[this.tmpCutid] = { 1114514f5e3Sopenharmony_ci rid: rid, 1124514f5e3Sopenharmony_ci x: x, 1134514f5e3Sopenharmony_ci y: y, 1144514f5e3Sopenharmony_ci w: w, 1154514f5e3Sopenharmony_ci h: h, 1164514f5e3Sopenharmony_ci u0: x / ww, 1174514f5e3Sopenharmony_ci v0: y / hh, 1184514f5e3Sopenharmony_ci u1: (x + w) / ww, 1194514f5e3Sopenharmony_ci v1: y / hh, 1204514f5e3Sopenharmony_ci u2: (x + w) / ww, 1214514f5e3Sopenharmony_ci v2: (y + h) / hh, 1224514f5e3Sopenharmony_ci u3: x / ww, 1234514f5e3Sopenharmony_ci v3: (y + h) / hh, 1244514f5e3Sopenharmony_ci }; 1254514f5e3Sopenharmony_ci this.tmpCutid += 1; 1264514f5e3Sopenharmony_ci return this.tmpCutid - 1; 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci makeCut(rid, x = 0, y = 0, w = -1, h = -1, ww = -1, hh = -1) { 1294514f5e3Sopenharmony_ci if (ww === -1) ww = this.ximages[rid].w; 1304514f5e3Sopenharmony_ci if (hh === -1) hh = this.ximages[rid].h; 1314514f5e3Sopenharmony_ci if (w ===-1) w = ww; 1324514f5e3Sopenharmony_ci if (h === -1) h = hh; 1334514f5e3Sopenharmony_ci this.allCuts[this.aiCutid] = { 1344514f5e3Sopenharmony_ci rid: rid, 1354514f5e3Sopenharmony_ci x: x, 1364514f5e3Sopenharmony_ci y: y, 1374514f5e3Sopenharmony_ci w: w, 1384514f5e3Sopenharmony_ci h: h, 1394514f5e3Sopenharmony_ci u0: x / ww, 1404514f5e3Sopenharmony_ci v0: y / hh, 1414514f5e3Sopenharmony_ci u1: (x + w) / ww, 1424514f5e3Sopenharmony_ci v1: y / hh, 1434514f5e3Sopenharmony_ci u2: (x + w) / ww, 1444514f5e3Sopenharmony_ci v2: (y + h) / hh, 1454514f5e3Sopenharmony_ci u3: x / ww, 1464514f5e3Sopenharmony_ci v3: (y + h) / hh, 1474514f5e3Sopenharmony_ci }; 1484514f5e3Sopenharmony_ci this.aiCutid += 1; 1494514f5e3Sopenharmony_ci return this.aiCutid - 1; 1504514f5e3Sopenharmony_ci } 1514514f5e3Sopenharmony_ci timenow() { 1524514f5e3Sopenharmony_ci let myDate = new Date(); 1534514f5e3Sopenharmony_ci return myDate.getTime() / 1000; 1544514f5e3Sopenharmony_ci } 1554514f5e3Sopenharmony_ci 1564514f5e3Sopenharmony_ci PutTexture(tex, w, h) { 1574514f5e3Sopenharmony_ci var rid = this.ximages.length; 1584514f5e3Sopenharmony_ci this.ximages[rid] = { stat: 1, path: 'put' + rid, tex: tex, w: w, h: h }; 1594514f5e3Sopenharmony_ci return rid; 1604514f5e3Sopenharmony_ci } 1614514f5e3Sopenharmony_ci 1624514f5e3Sopenharmony_ci loadTexture(width, height) { 1634514f5e3Sopenharmony_ci var rid = this.ximages.length; 1644514f5e3Sopenharmony_ci 1654514f5e3Sopenharmony_ci var texture = gl.createTexture(); 1664514f5e3Sopenharmony_ci XTexture.initTextureStatus(texture); 1674514f5e3Sopenharmony_ci gl.texImage2D( 1684514f5e3Sopenharmony_ci gl.TEXTURE_2D, 1694514f5e3Sopenharmony_ci 0, 1704514f5e3Sopenharmony_ci gl.RGBA, 1714514f5e3Sopenharmony_ci width, 1724514f5e3Sopenharmony_ci height, 1734514f5e3Sopenharmony_ci 0, 1744514f5e3Sopenharmony_ci gl.RGBA, 1754514f5e3Sopenharmony_ci gl.UNSIGNED_BYTE, 1764514f5e3Sopenharmony_ci null 1774514f5e3Sopenharmony_ci ); 1784514f5e3Sopenharmony_ci 1794514f5e3Sopenharmony_ci this.ximages[rid] = { 1804514f5e3Sopenharmony_ci stat: 1, 1814514f5e3Sopenharmony_ci path: 'default' + rid, 1824514f5e3Sopenharmony_ci tex: texture, 1834514f5e3Sopenharmony_ci w: width, 1844514f5e3Sopenharmony_ci h: height, 1854514f5e3Sopenharmony_ci }; 1864514f5e3Sopenharmony_ci return rid; 1874514f5e3Sopenharmony_ci } 1884514f5e3Sopenharmony_ci initTextImageData(s, size) { 1894514f5e3Sopenharmony_ci this.textCtx.clearRect(0, 0, 1024, 256); 1904514f5e3Sopenharmony_ci this.textCtx.font = size + "px '宋体'"; 1914514f5e3Sopenharmony_ci this.textCtx.fillStyle = 'rgba(255,255,255,1)'; 1924514f5e3Sopenharmony_ci this.textCtx.fillText(s, 1, 1); 1934514f5e3Sopenharmony_ci let imgd = this.textCtx.getImageData(0, 0, 1024, 256).data; 1944514f5e3Sopenharmony_ci let w = 1024; 1954514f5e3Sopenharmony_ci let h = size + 5; 1964514f5e3Sopenharmony_ci let x = 256; 1974514f5e3Sopenharmony_ci while (x === 256) { 1984514f5e3Sopenharmony_ci h -= 1; 1994514f5e3Sopenharmony_ci for (x = 0; x < 128; x++) { 2004514f5e3Sopenharmony_ci let p = (h * 1024 + x) * 4; 2014514f5e3Sopenharmony_ci if (imgd[p] !== 0) break; 2024514f5e3Sopenharmony_ci } 2034514f5e3Sopenharmony_ci } 2044514f5e3Sopenharmony_ci let y = h; 2054514f5e3Sopenharmony_ci while (y === h) { 2064514f5e3Sopenharmony_ci w -= 1; 2074514f5e3Sopenharmony_ci for (y = 0; y < h; y++) { 2084514f5e3Sopenharmony_ci let p = (y * 1024 + w) * 4; 2094514f5e3Sopenharmony_ci if (imgd[p] !== 0) break; 2104514f5e3Sopenharmony_ci } 2114514f5e3Sopenharmony_ci } 2124514f5e3Sopenharmony_ci return this.textCtx.getImageData(0, 0, w + 1, h + 1); 2134514f5e3Sopenharmony_ci } 2144514f5e3Sopenharmony_ci getText(s, size) { 2154514f5e3Sopenharmony_ci let textIdx = s + size; 2164514f5e3Sopenharmony_ci 2174514f5e3Sopenharmony_ci if (textIdx in this.textIdxs) { 2184514f5e3Sopenharmony_ci this.textIdxs[textIdx].time = this.timenow(); 2194514f5e3Sopenharmony_ci return this.textIdxs[textIdx].cid; 2204514f5e3Sopenharmony_ci } 2214514f5e3Sopenharmony_ci let imgd = this.initTextImageData(s, size); 2224514f5e3Sopenharmony_ci let w = imgd.width; 2234514f5e3Sopenharmony_ci let h = imgd.height; 2244514f5e3Sopenharmony_ci let useHeight = Math.floor((h + 31) / 32); 2254514f5e3Sopenharmony_ci let mask = 0; 2264514f5e3Sopenharmony_ci for (let i = 0; i < useHeight; i++) mask |= 1 << i; 2274514f5e3Sopenharmony_ci let rid = -1; 2284514f5e3Sopenharmony_ci let off = -1; 2294514f5e3Sopenharmony_ci for (let k in this.textImgs) { 2304514f5e3Sopenharmony_ci for (let i = 0; i < 32 - useHeight + 1; i++) { 2314514f5e3Sopenharmony_ci if ((this.textImgs[k].mask & (mask << i)) === 0) { 2324514f5e3Sopenharmony_ci off = i; 2334514f5e3Sopenharmony_ci break; 2344514f5e3Sopenharmony_ci } 2354514f5e3Sopenharmony_ci } 2364514f5e3Sopenharmony_ci if (off !== -1) { 2374514f5e3Sopenharmony_ci rid = k; 2384514f5e3Sopenharmony_ci break; 2394514f5e3Sopenharmony_ci } 2404514f5e3Sopenharmony_ci } 2414514f5e3Sopenharmony_ci if (rid === -1) { 2424514f5e3Sopenharmony_ci rid = this.loadTexture(1024, 1024); 2434514f5e3Sopenharmony_ci this.textImgs[rid] = { mask: 0 }; 2444514f5e3Sopenharmony_ci off = 0; 2454514f5e3Sopenharmony_ci } 2464514f5e3Sopenharmony_ci let cid = this.makeCut(rid, 0, off * 32, w, h); 2474514f5e3Sopenharmony_ci this.textImgs[rid]['mask'] |= mask << off; 2484514f5e3Sopenharmony_ci this.textIdxs[textIdx] = { cid: cid, rid: rid, mask: mask << off, time: this.timenow(), }; 2494514f5e3Sopenharmony_ci gl.activeTexture(gl.TEXTURE0); 2504514f5e3Sopenharmony_ci gl.bindTexture(gl.TEXTURE_2D, this.ximages[rid].tex); 2514514f5e3Sopenharmony_ci gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); 2524514f5e3Sopenharmony_ci gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, off * 32, gl.RGBA, gl.UNSIGNED_BYTE, imgd); 2534514f5e3Sopenharmony_ci return cid; 2544514f5e3Sopenharmony_ci } 2554514f5e3Sopenharmony_ci _FreshText() { 2564514f5e3Sopenharmony_ci this.tmpCutid = 0; 2574514f5e3Sopenharmony_ci let nt = this.timenow(); 2584514f5e3Sopenharmony_ci let rm = []; 2594514f5e3Sopenharmony_ci for (let idx in this.textIdxs) { 2604514f5e3Sopenharmony_ci if (nt - this.textIdxs[idx].time > 3) { 2614514f5e3Sopenharmony_ci this.textImgs[this.textIdxs[idx].rid].mask &= ~this.textIdxs[idx].mask; 2624514f5e3Sopenharmony_ci delete this.allCuts[this.textIdxs[idx].cid]; 2634514f5e3Sopenharmony_ci rm.push(idx); 2644514f5e3Sopenharmony_ci } 2654514f5e3Sopenharmony_ci } 2664514f5e3Sopenharmony_ci for (let idx in rm) { 2674514f5e3Sopenharmony_ci delete this.textIdxs[rm[idx]]; 2684514f5e3Sopenharmony_ci } 2694514f5e3Sopenharmony_ci } 2704514f5e3Sopenharmony_ci static ExpandColor(c) { 2714514f5e3Sopenharmony_ci return [ 2724514f5e3Sopenharmony_ci ((c >> 16) & 0xff) / 255, 2734514f5e3Sopenharmony_ci ((c >> 8) & 0xff) / 255, 2744514f5e3Sopenharmony_ci (c & 0xff) / 255, 2754514f5e3Sopenharmony_ci ((c >> 24) & 0xff) / 255]; //r,g,b,a 2764514f5e3Sopenharmony_ci } 2774514f5e3Sopenharmony_ci} 2784514f5e3Sopenharmony_ciXTexture.pinstance_ = null; 279