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 { XMat4 } from './XMat4.js'; 174514f5e3Sopenharmony_ciimport { XShader } from './XShader.js'; 184514f5e3Sopenharmony_ciimport { Scr } from '../XDefine.js'; 194514f5e3Sopenharmony_ciimport { XTexture } from './XTexture.js'; 204514f5e3Sopenharmony_ciimport { gl } from '../GLFrame.js'; 214514f5e3Sopenharmony_ciimport { fAngle, iDistance } from '../XTools.js'; 224514f5e3Sopenharmony_ci 234514f5e3Sopenharmony_ciexport class X2DFast { 244514f5e3Sopenharmony_ci static gi() { 254514f5e3Sopenharmony_ci if (X2DFast.px2f == null) X2DFast.px2f = new X2DFast(); 264514f5e3Sopenharmony_ci return X2DFast.px2f; 274514f5e3Sopenharmony_ci } 284514f5e3Sopenharmony_ci 294514f5e3Sopenharmony_ci constructor() { 304514f5e3Sopenharmony_ci this.localBuffer = gl.createBuffer(); 314514f5e3Sopenharmony_ci this.texSampleIdx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_ci this.vertexArray = new ArrayBuffer(1024 * 1024 * 4 * 2); 344514f5e3Sopenharmony_ci this.vertexFloat32 = new Float32Array(this.vertexArray); 354514f5e3Sopenharmony_ci this.vertexUint32 = new Uint32Array(this.vertexArray); 364514f5e3Sopenharmony_ci this.whiteImg = XTexture.gi().loadTextureFromImage('CUSTOM_TEXTURE_1'); 374514f5e3Sopenharmony_ci this.whiteCut = XTexture.gi().makeCut(this.whiteImg, 0, 0, 1, 1); 384514f5e3Sopenharmony_ci XShader.gi(); 394514f5e3Sopenharmony_ci 404514f5e3Sopenharmony_ci this.resetMat(); 414514f5e3Sopenharmony_ci } 424514f5e3Sopenharmony_ci resetMat() { 434514f5e3Sopenharmony_ci X2DFast.transform2D.unit(); 444514f5e3Sopenharmony_ci X2DFast.transform2D.orthoMat(0, 0, Scr.logicw, Scr.logich); 454514f5e3Sopenharmony_ci let tm = X2DFast.transform2D.mat; 464514f5e3Sopenharmony_ci this.t2dExt = [ 474514f5e3Sopenharmony_ci tm[0][0], 484514f5e3Sopenharmony_ci tm[1][0], 494514f5e3Sopenharmony_ci tm[2][0], 504514f5e3Sopenharmony_ci tm[3][0], 514514f5e3Sopenharmony_ci tm[0][1], 524514f5e3Sopenharmony_ci tm[1][1], 534514f5e3Sopenharmony_ci tm[2][1], 544514f5e3Sopenharmony_ci tm[3][1], 554514f5e3Sopenharmony_ci tm[0][2], 564514f5e3Sopenharmony_ci tm[1][2], 574514f5e3Sopenharmony_ci tm[2][2], 584514f5e3Sopenharmony_ci tm[3][2], 594514f5e3Sopenharmony_ci tm[0][3], 604514f5e3Sopenharmony_ci tm[1][3], 614514f5e3Sopenharmony_ci tm[2][3], 624514f5e3Sopenharmony_ci tm[3][3], 634514f5e3Sopenharmony_ci ]; 644514f5e3Sopenharmony_ci } 654514f5e3Sopenharmony_ci 664514f5e3Sopenharmony_ci swapMode2D() { 674514f5e3Sopenharmony_ci gl.disable(gl.DEPTH_TEST); 684514f5e3Sopenharmony_ci 694514f5e3Sopenharmony_ci gl.enable(gl.BLEND); 704514f5e3Sopenharmony_ci gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); // ONE_MINUS_SRC_ALPHA 714514f5e3Sopenharmony_ci // GL_FUNC_ADD、GL_FUNC_SUBTRACT、GL_FUNC_REVERSE_SUBTRACT、GL_MIN、GL_MAX和GL_LOGIC_OP 724514f5e3Sopenharmony_ci } 734514f5e3Sopenharmony_ci 744514f5e3Sopenharmony_ci DrawCircle(ox, oy, rw, rh, c = 0xffffffff, lw = 1) { 754514f5e3Sopenharmony_ci let lx = -1; 764514f5e3Sopenharmony_ci let ly = -1; 774514f5e3Sopenharmony_ci let i = 0; 784514f5e3Sopenharmony_ci let gap = (Math.PI * 2) / 32; 794514f5e3Sopenharmony_ci while (i < Math.PI * 2 + 0.00001) { 804514f5e3Sopenharmony_ci let dx = Math.cos(i) * rw + ox; 814514f5e3Sopenharmony_ci let dy = Math.sin(i) * rh + oy; 824514f5e3Sopenharmony_ci if (lx !== -1) { 834514f5e3Sopenharmony_ci this.drawLine(lx, ly, dx, dy, c, lw); 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci lx = dx; 864514f5e3Sopenharmony_ci ly = dy; 874514f5e3Sopenharmony_ci i += gap; 884514f5e3Sopenharmony_ci } 894514f5e3Sopenharmony_ci } 904514f5e3Sopenharmony_ci 914514f5e3Sopenharmony_ci fillRect(x, y, w, h, c = 0xffffffff) { 924514f5e3Sopenharmony_ci this.drawCut(this.whiteCut, x, y, w, h, 0, 0, 0, c); 934514f5e3Sopenharmony_ci } 944514f5e3Sopenharmony_ci 954514f5e3Sopenharmony_ci drawLine(x1, y1, x2, y2, c = 0xffffffff, linewidth = 1) { 964514f5e3Sopenharmony_ci x1 = parseInt(x1); 974514f5e3Sopenharmony_ci y1 = parseInt(y1); 984514f5e3Sopenharmony_ci x2 = parseInt(x2); 994514f5e3Sopenharmony_ci y2 = parseInt(y2); 1004514f5e3Sopenharmony_ci this.drawCut( 1014514f5e3Sopenharmony_ci this.whiteCut, 1024514f5e3Sopenharmony_ci x1, 1034514f5e3Sopenharmony_ci y1, 1044514f5e3Sopenharmony_ci iDistance(x1 - x2, y1 - y2), 1054514f5e3Sopenharmony_ci linewidth, 1064514f5e3Sopenharmony_ci fAngle(x2 - x1, y2 - y1), 1074514f5e3Sopenharmony_ci 0, 1084514f5e3Sopenharmony_ci 0, // +0.5 1094514f5e3Sopenharmony_ci c 1104514f5e3Sopenharmony_ci ); 1114514f5e3Sopenharmony_ci } 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_ci drawRect(x, y, w, h, c = 0xffffffff, lw = 1) { 1144514f5e3Sopenharmony_ci this.drawLine(x - lw / 2, y, x + w + lw / 2, y, c, lw); 1154514f5e3Sopenharmony_ci this.drawLine(x, y, x, y + h, c, lw); 1164514f5e3Sopenharmony_ci this.drawLine(x + w, y + h, x + w, y, c, lw); 1174514f5e3Sopenharmony_ci this.drawLine(x + w + lw / 2, y + h, x - lw / 2, y + h, c, lw); 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci 1204514f5e3Sopenharmony_ci static testTransform(x, y, sw, sh, ra, ox, oy, realw, realh) { 1214514f5e3Sopenharmony_ci X2DFast.tmpMat.unit(); 1224514f5e3Sopenharmony_ci if (ox === -1) ox = 0; 1234514f5e3Sopenharmony_ci if (ox === -2) ox = Math.floor(realw / 2); 1244514f5e3Sopenharmony_ci if (ox === -3) ox = realw; 1254514f5e3Sopenharmony_ci if (oy === -1) oy = 0; 1264514f5e3Sopenharmony_ci if (oy === -2) oy = Math.floor(realh / 2); 1274514f5e3Sopenharmony_ci if (oy === -3) oy = realh; 1284514f5e3Sopenharmony_ci if (ox !== 0 || oy !== 0) X2DFast.tmpMat.move(-ox, -oy, 0); 1294514f5e3Sopenharmony_ci if (sw !== 1 || sh !== 1) X2DFast.tmpMat.scale(sw, sh, 1); 1304514f5e3Sopenharmony_ci if (ra !== 0) X2DFast.tmpMat.rotate(0, 0, ra); 1314514f5e3Sopenharmony_ci if (x !== 0 || y !== 0) X2DFast.tmpMat.move(x, y, 0); 1324514f5e3Sopenharmony_ci } 1334514f5e3Sopenharmony_ci clearBuffer() { 1344514f5e3Sopenharmony_ci this.ridDict = {}; 1354514f5e3Sopenharmony_ci this.ridPoint = 0; 1364514f5e3Sopenharmony_ci this.drawCount = 0; 1374514f5e3Sopenharmony_ci } 1384514f5e3Sopenharmony_ci swapC(c) { 1394514f5e3Sopenharmony_ci let r; 1404514f5e3Sopenharmony_ci let g; 1414514f5e3Sopenharmony_ci let b; 1424514f5e3Sopenharmony_ci let a; 1434514f5e3Sopenharmony_ci if (isNaN(c)) { 1444514f5e3Sopenharmony_ci r = Math.floor(c[0] * 63 / 255); 1454514f5e3Sopenharmony_ci g = Math.floor(c[1] * 63 / 255); 1464514f5e3Sopenharmony_ci b = Math.floor(c[2] * 63 / 255); 1474514f5e3Sopenharmony_ci a = Math.floor(c[3] * 63 / 255); 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci else { 1504514f5e3Sopenharmony_ci if (c === -1) { 1514514f5e3Sopenharmony_ci c = 0xffffffff; 1524514f5e3Sopenharmony_ci } 1534514f5e3Sopenharmony_ci r = Math.floor((((c >> 16) & 0xff) * 63) / 255); 1544514f5e3Sopenharmony_ci g = Math.floor((((c >> 8) & 0xff) * 63) / 255); 1554514f5e3Sopenharmony_ci b = Math.floor(((c & 0xff) * 63) / 255); 1564514f5e3Sopenharmony_ci a = Math.floor((((c >> 24) & 0xff) * 63) / 255); 1574514f5e3Sopenharmony_ci } 1584514f5e3Sopenharmony_ci return ((a * 64 + r) * 64 + g) * 64 + b + 0.1; 1594514f5e3Sopenharmony_ci } 1604514f5e3Sopenharmony_ci drawCut_(pcut, m00, m01, m10, m11, m22, m30, m31, c = 0xffffffff) { 1614514f5e3Sopenharmony_ci c = this.swapC(c); 1624514f5e3Sopenharmony_ci this.vertexFloat32.set([0.0, 0.0, 0.0, pcut.u0, pcut.v0, m00, m01, m10, m11, m22, m30, m31, 1634514f5e3Sopenharmony_ci this.ridDict[pcut.rid], c, 1644514f5e3Sopenharmony_ci pcut.w, 0.0, 0.0, pcut.u1, pcut.v1, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 1654514f5e3Sopenharmony_ci pcut.w, pcut.h, 0.0, pcut.u2, pcut.v2, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 1664514f5e3Sopenharmony_ci 0.0, 0.0, 0.0, pcut.u0, pcut.v0, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 1674514f5e3Sopenharmony_ci pcut.w, pcut.h, 0.0, pcut.u2, pcut.v2, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 1684514f5e3Sopenharmony_ci 0.0, pcut.h, 0.0, pcut.u3, pcut.v3, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c,], 1694514f5e3Sopenharmony_ci this.drawCount * 14 * 6); 1704514f5e3Sopenharmony_ci this.drawCount += 1; 1714514f5e3Sopenharmony_ci } 1724514f5e3Sopenharmony_ci drawCutEx(cid, tmat, c = 0xffffffff) { 1734514f5e3Sopenharmony_ci let pcut = XTexture.pinstance_.allCuts[cid]; 1744514f5e3Sopenharmony_ci if (!(pcut.rid in this.ridDict)) { 1754514f5e3Sopenharmony_ci this.ridDict[pcut.rid] = this.ridPoint; 1764514f5e3Sopenharmony_ci this.ridPoint += 1; 1774514f5e3Sopenharmony_ci } 1784514f5e3Sopenharmony_ci tmat = tmat.mat; 1794514f5e3Sopenharmony_ci this.drawCut(pcut, tmat[0][0], tmat[0][1], tmat[1][0], tmat[1][1], tmat[2][2], tmat[3][0], tmat[3][1], c); 1804514f5e3Sopenharmony_ci } 1814514f5e3Sopenharmony_ci drawCut(cid, x = 0, y = 0, sw = 1, sh = 1, ra = 0, ox = 0, oy = 0, c = 0xffffffff) { 1824514f5e3Sopenharmony_ci let intX = parseInt(x); 1834514f5e3Sopenharmony_ci let intY = parseInt(y); 1844514f5e3Sopenharmony_ci let pcut = XTexture.gi().allCuts[cid]; 1854514f5e3Sopenharmony_ci if (pcut === null) return; 1864514f5e3Sopenharmony_ci if (!(pcut.rid in this.ridDict)) { 1874514f5e3Sopenharmony_ci if (this.ridPoint >= 16) { 1884514f5e3Sopenharmony_ci this.freshBuffer(); 1894514f5e3Sopenharmony_ci this.clearBuffer(); 1904514f5e3Sopenharmony_ci } 1914514f5e3Sopenharmony_ci this.ridDict[pcut.rid] = this.ridPoint; 1924514f5e3Sopenharmony_ci this.ridPoint += 1; 1934514f5e3Sopenharmony_ci } 1944514f5e3Sopenharmony_ci X2DFast.testTransform(intX, intY, sw, sh, ra, ox, oy, pcut.w, pcut.h); 1954514f5e3Sopenharmony_ci let tmat = X2DFast.tmpMat.mat; 1964514f5e3Sopenharmony_ci this.drawCut_(pcut, tmat[0][0], tmat[0][1], tmat[1][0], tmat[1][1], tmat[2][2], tmat[3][0], tmat[3][1], c); 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci drawText(s, size = 14, x = 0, y = 0, sw = 1, sh = 1, ra = 0, ox = 0, oy = 0, c = 0xffffffff) { 1994514f5e3Sopenharmony_ci if (s.length <= 0) return 0; 2004514f5e3Sopenharmony_ci let cid = XTexture.gi().getText(s, size); 2014514f5e3Sopenharmony_ci if (cid >= 0) this.drawCut(cid, x, y, sw, sh, ra, ox, oy, c); 2024514f5e3Sopenharmony_ci return XTexture.gi().allCuts[cid].w; 2034514f5e3Sopenharmony_ci } 2044514f5e3Sopenharmony_ci getTextWidth(s, size) { 2054514f5e3Sopenharmony_ci if (s.length <= 0) return 0; 2064514f5e3Sopenharmony_ci let cid = XTexture.gi().getText(s, size); 2074514f5e3Sopenharmony_ci return XTexture.gi().allCuts[cid].w; 2084514f5e3Sopenharmony_ci } 2094514f5e3Sopenharmony_ci freshBuffer() { 2104514f5e3Sopenharmony_ci XTexture.gi()._FreshText(); 2114514f5e3Sopenharmony_ci if (this.drawCount === 0) return; 2124514f5e3Sopenharmony_ci let ps = XShader.gi().use(XShader.ID_SHADER_FAST); 2134514f5e3Sopenharmony_ci for (let rid in this.ridDict) { 2144514f5e3Sopenharmony_ci gl.activeTexture(gl.TEXTURE0 + this.ridDict[rid]); 2154514f5e3Sopenharmony_ci gl.bindTexture(gl.TEXTURE_2D, XTexture.gi().ximages[rid].tex); 2164514f5e3Sopenharmony_ci 2174514f5e3Sopenharmony_ci gl.uniform1i(ps.tex[this.ridDict[rid]], this.ridDict[rid]); 2184514f5e3Sopenharmony_ci } 2194514f5e3Sopenharmony_ci 2204514f5e3Sopenharmony_ci gl.uniformMatrix4fv(ps.uMat, false, this.t2dExt); 2214514f5e3Sopenharmony_ci 2224514f5e3Sopenharmony_ci gl.bindBuffer(gl.ARRAY_BUFFER, this.localBuffer); 2234514f5e3Sopenharmony_ci gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW); 2244514f5e3Sopenharmony_ci gl.vertexAttribPointer(ps.position, 3, gl.FLOAT, false, 4 * 14, 0); 2254514f5e3Sopenharmony_ci gl.enableVertexAttribArray(ps.position); 2264514f5e3Sopenharmony_ci gl.vertexAttribPointer(ps.aTexCoord, 2, gl.FLOAT, false, 4 * 14, 4 * 3); 2274514f5e3Sopenharmony_ci gl.enableVertexAttribArray(ps.aTexCoord); 2284514f5e3Sopenharmony_ci gl.vertexAttribPointer(ps.ext1, 4, gl.FLOAT, false, 4 * 14, 4 * 5); 2294514f5e3Sopenharmony_ci gl.enableVertexAttribArray(ps.ext1); 2304514f5e3Sopenharmony_ci gl.vertexAttribPointer(ps.ext2, 4, gl.FLOAT, false, 4 * 14, 4 * 9); 2314514f5e3Sopenharmony_ci gl.enableVertexAttribArray(ps.ext2); 2324514f5e3Sopenharmony_ci gl.vertexAttribPointer(ps.inColor, 1, gl.FLOAT, false, 4 * 14, 4 * 13); 2334514f5e3Sopenharmony_ci gl.enableVertexAttribArray(ps.inColor); 2344514f5e3Sopenharmony_ci 2354514f5e3Sopenharmony_ci gl.drawArrays(gl.TRIANGLES, 0, 6 * this.drawCount); 2364514f5e3Sopenharmony_ci } 2374514f5e3Sopenharmony_ci} 2384514f5e3Sopenharmony_ciX2DFast.tmpMat = new XMat4(); 2394514f5e3Sopenharmony_ciX2DFast.transform2D = new XMat4(); 2404514f5e3Sopenharmony_ci 2414514f5e3Sopenharmony_ciX2DFast.px2f = null; 242