• 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 { XMat4 } from './XMat4.js';
17import { XShader } from './XShader.js';
18import { Scr } from '../XDefine.js';
19import { XTexture } from './XTexture.js';
20import { gl } from '../GLFrame.js';
21import { fAngle, iDistance } from '../XTools.js';
22
23export class X2DFast {
24  static gi() {
25    if (X2DFast.px2f == null) X2DFast.px2f = new X2DFast();
26    return X2DFast.px2f;
27  }
28
29  constructor() {
30    this.localBuffer = gl.createBuffer();
31    this.texSampleIdx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
32
33    this.vertexArray = new ArrayBuffer(1024 * 1024 * 4 * 2);
34    this.vertexFloat32 = new Float32Array(this.vertexArray);
35    this.vertexUint32 = new Uint32Array(this.vertexArray);
36    this.whiteImg = XTexture.gi().loadTextureFromImage('CUSTOM_TEXTURE_1');
37    this.whiteCut = XTexture.gi().makeCut(this.whiteImg, 0, 0, 1, 1);
38    XShader.gi();
39
40    this.resetMat();
41  }
42  resetMat() {
43    X2DFast.transform2D.unit();
44    X2DFast.transform2D.orthoMat(0, 0, Scr.logicw, Scr.logich);
45    let tm = X2DFast.transform2D.mat;
46    this.t2dExt = [
47      tm[0][0],
48      tm[1][0],
49      tm[2][0],
50      tm[3][0],
51      tm[0][1],
52      tm[1][1],
53      tm[2][1],
54      tm[3][1],
55      tm[0][2],
56      tm[1][2],
57      tm[2][2],
58      tm[3][2],
59      tm[0][3],
60      tm[1][3],
61      tm[2][3],
62      tm[3][3],
63    ];
64  }
65
66  swapMode2D() {
67    gl.disable(gl.DEPTH_TEST);
68
69    gl.enable(gl.BLEND);
70    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); // ONE_MINUS_SRC_ALPHA
71    // GL_FUNC_ADD、GL_FUNC_SUBTRACT、GL_FUNC_REVERSE_SUBTRACT、GL_MIN、GL_MAX和GL_LOGIC_OP
72  }
73
74  DrawCircle(ox, oy, rw, rh, c = 0xffffffff, lw = 1) {
75    let lx = -1;
76    let ly = -1;
77    let i = 0;
78    let gap = (Math.PI * 2) / 32;
79    while (i < Math.PI * 2 + 0.00001) {
80      let dx = Math.cos(i) * rw + ox;
81      let dy = Math.sin(i) * rh + oy;
82      if (lx !== -1) {
83        this.drawLine(lx, ly, dx, dy, c, lw);
84      }
85      lx = dx;
86      ly = dy;
87      i += gap;
88    }
89  }
90
91  fillRect(x, y, w, h, c = 0xffffffff) {
92    this.drawCut(this.whiteCut, x, y, w, h, 0, 0, 0, c);
93  }
94
95  drawLine(x1, y1, x2, y2, c = 0xffffffff, linewidth = 1) {
96    x1 = parseInt(x1);
97    y1 = parseInt(y1);
98    x2 = parseInt(x2);
99    y2 = parseInt(y2);
100    this.drawCut(
101      this.whiteCut,
102      x1,
103      y1,
104      iDistance(x1 - x2, y1 - y2),
105      linewidth,
106      fAngle(x2 - x1, y2 - y1),
107      0,
108      0, // +0.5
109      c
110    );
111  }
112
113  drawRect(x, y, w, h, c = 0xffffffff, lw = 1) {
114    this.drawLine(x - lw / 2, y, x + w + lw / 2, y, c, lw);
115    this.drawLine(x, y, x, y + h, c, lw);
116    this.drawLine(x + w, y + h, x + w, y, c, lw);
117    this.drawLine(x + w + lw / 2, y + h, x - lw / 2, y + h, c, lw);
118  }
119
120  static testTransform(x, y, sw, sh, ra, ox, oy, realw, realh) {
121    X2DFast.tmpMat.unit();
122    if (ox === -1) {
123      ox = 0;
124    }
125    if (ox === -2) {
126      ox = Math.floor(realw / 2);
127    }
128    if (ox === -3) {
129      ox = realw;
130    }
131    if (oy === -1) {
132      oy = 0;
133    }
134    if (oy === -2) {
135      oy = Math.floor(realh / 2);
136    }
137    if (oy === -3) {
138      oy = realh;
139    }
140    if (ox !== 0 || oy !== 0) {
141      X2DFast.tmpMat.move(-ox, -oy, 0);
142    }
143    if (sw !== 1 || sh !== 1) {
144      X2DFast.tmpMat.scale(sw, sh, 1);
145    }
146    if (ra !== 0) {
147      X2DFast.tmpMat.rotate(0, 0, ra);
148    }
149    if (x !== 0 || y !== 0) {
150      X2DFast.tmpMat.move(x, y, 0);
151    }
152  }
153  clearBuffer() {
154    this.ridDict = {};
155    this.ridPoint = 0;
156    this.drawCount = 0;
157  }
158  swapC(c) {
159    let r;
160    let g;
161    let b;
162    let a;
163    if (isNaN(c)) {
164      r = Math.floor(c[0] * 63 / 255);
165      g = Math.floor(c[1] * 63 / 255);
166      b = Math.floor(c[2] * 63 / 255);
167      a = Math.floor(c[3] * 63 / 255);
168    }
169    else {
170      if (c === -1) {
171        c = 0xffffffff;
172      }
173      r = Math.floor((((c >> 16) & 0xff) * 63) / 255);
174      g = Math.floor((((c >> 8) & 0xff) * 63) / 255);
175      b = Math.floor(((c & 0xff) * 63) / 255);
176      a = Math.floor((((c >> 24) & 0xff) * 63) / 255);
177    }
178    return ((a * 64 + r) * 64 + g) * 64 + b + 0.1;
179  }
180  drawCut_(pcut, m00, m01, m10, m11, m22, m30, m31, c = 0xffffffff) {
181    c = this.swapC(c);
182    this.vertexFloat32.set([0.0, 0.0, 0.0, pcut.u0, pcut.v0, m00, m01, m10, m11, m22, m30, m31,
183      this.ridDict[pcut.rid], c,
184      pcut.w, 0.0, 0.0, pcut.u1, pcut.v1, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c,
185      pcut.w, pcut.h, 0.0, pcut.u2, pcut.v2, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c,
186      0.0, 0.0, 0.0, pcut.u0, pcut.v0, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c,
187      pcut.w, pcut.h, 0.0, pcut.u2, pcut.v2, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c,
188      0.0, pcut.h, 0.0, pcut.u3, pcut.v3, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c,],
189      this.drawCount * 14 * 6);
190    this.drawCount += 1;
191  }
192  drawCutEx(cid, tmat, c = 0xffffffff) {
193    let pcut = XTexture.pinstance_.allCuts[cid];
194    if (!(pcut.rid in this.ridDict)) {
195      this.ridDict[pcut.rid] = this.ridPoint;
196      this.ridPoint += 1;
197    }
198    tmat = tmat.mat;
199    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);
200  }
201  drawCut(cid, x = 0, y = 0, sw = 1, sh = 1, ra = 0, ox = 0, oy = 0, c = 0xffffffff) {
202    let intX = parseInt(x);
203    let intY = parseInt(y);
204    let pcut = XTexture.gi().allCuts[cid];
205    if (pcut === null) {
206      return;
207    }
208    if (!(pcut.rid in this.ridDict)) {
209      if (this.ridPoint >= 16) {
210        this.freshBuffer();
211        this.clearBuffer();
212      }
213      this.ridDict[pcut.rid] = this.ridPoint;
214      this.ridPoint += 1;
215    }
216    X2DFast.testTransform(intX, intY, sw, sh, ra, ox, oy, pcut.w, pcut.h);
217    let tmat = X2DFast.tmpMat.mat;
218    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);
219  }
220  drawText(s, size = 14, x = 0, y = 0, sw = 1, sh = 1, ra = 0, ox = 0, oy = 0, c = 0xffffffff) {
221    if (s.length <= 0) return 0;
222    let cid = XTexture.gi().getText(s, size);
223    if (cid >= 0) this.drawCut(cid, x, y, sw, sh, ra, ox, oy, c);
224    return XTexture.gi().allCuts[cid].w;
225  }
226  getTextWidth(s, size) {
227    if (s.length <= 0) return 0;
228    let cid = XTexture.gi().getText(s, size);
229    return XTexture.gi().allCuts[cid].w;
230  }
231  freshBuffer() {
232    XTexture.gi()._FreshText();
233    if (this.drawCount === 0) {
234      return;
235    }
236    let ps = XShader.gi().use(XShader.ID_SHADER_FAST);
237    for (let rid in this.ridDict) {
238      gl.activeTexture(gl.TEXTURE0 + this.ridDict[rid]);
239      gl.bindTexture(gl.TEXTURE_2D, XTexture.gi().ximages[rid].tex);
240
241      gl.uniform1i(ps.tex[this.ridDict[rid]], this.ridDict[rid]);
242    }
243
244    gl.uniformMatrix4fv(ps.uMat, false, this.t2dExt);
245
246    gl.bindBuffer(gl.ARRAY_BUFFER, this.localBuffer);
247    gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW);
248    gl.vertexAttribPointer(ps.position, 3, gl.FLOAT, false, 4 * 14, 0);
249    gl.enableVertexAttribArray(ps.position);
250    gl.vertexAttribPointer(ps.aTexCoord, 2, gl.FLOAT, false, 4 * 14, 4 * 3);
251    gl.enableVertexAttribArray(ps.aTexCoord);
252    gl.vertexAttribPointer(ps.ext1, 4, gl.FLOAT, false, 4 * 14, 4 * 5);
253    gl.enableVertexAttribArray(ps.ext1);
254    gl.vertexAttribPointer(ps.ext2, 4, gl.FLOAT, false, 4 * 14, 4 * 9);
255    gl.enableVertexAttribArray(ps.ext2);
256    gl.vertexAttribPointer(ps.inColor, 1, gl.FLOAT, false, 4 * 14, 4 * 13);
257    gl.enableVertexAttribArray(ps.inColor);
258
259    gl.drawArrays(gl.TRIANGLES, 0, 6 * this.drawCount);
260  }
261}
262X2DFast.tmpMat = new XMat4();
263X2DFast.transform2D = new XMat4();
264
265X2DFast.px2f = null;
266